From 795cee876e42a5604a30805962f04c8b3e7ca46d Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Thu, 4 Aug 2016 10:23:00 -0600 Subject: [PATCH] Add a method to scale geometries --- src/ol/geom/flat/transformflatgeom.js | 33 +++++++++++++++++++++++ src/ol/geom/geometry.js | 14 ++++++++++ src/ol/geom/geometrycollection.js | 13 +++++++++ src/ol/geom/simplegeometry.js | 24 +++++++++++++++++ test/spec/ol/geom/linestring.test.js | 25 +++++++++++++++++ test/spec/ol/geom/multilinestring.test.js | 25 +++++++++++++++++ test/spec/ol/geom/multipoint.test.js | 25 +++++++++++++++++ test/spec/ol/geom/point.test.js | 25 +++++++++++++++++ 8 files changed, 184 insertions(+) diff --git a/src/ol/geom/flat/transformflatgeom.js b/src/ol/geom/flat/transformflatgeom.js index ae097afe57..12b2b203e3 100644 --- a/src/ol/geom/flat/transformflatgeom.js +++ b/src/ol/geom/flat/transformflatgeom.js @@ -60,6 +60,39 @@ ol.geom.flat.transform.rotate = function(flatCoordinates, offset, end, stride, a }; +/** + * Scale the coordinates. + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} sx Scale factor in the x-direction. + * @param {number} sy Scale factor in the y-direction. + * @param {Array.} anchor Scale anchor point. + * @param {Array.=} opt_dest Destination. + * @return {Array.} Transformed coordinates. + */ +ol.geom.flat.transform.scale = function(flatCoordinates, offset, end, stride, sx, sy, anchor, opt_dest) { + var dest = opt_dest ? opt_dest : []; + var anchorX = anchor[0]; + var anchorY = anchor[1]; + var i = 0; + for (var j = offset; j < end; j += stride) { + var deltaX = flatCoordinates[j] - anchorX; + var deltaY = flatCoordinates[j + 1] - anchorY; + dest[i++] = anchorX + sx * deltaX; + dest[i++] = anchorY + sy * deltaY; + for (var k = j + 2; k < j + stride; ++k) { + dest[i++] = flatCoordinates[k]; + } + } + if (opt_dest && dest.length != i) { + dest.length = i; + } + return dest; +}; + + /** * @param {Array.} flatCoordinates Flat coordinates. * @param {number} offset Offset. diff --git a/src/ol/geom/geometry.js b/src/ol/geom/geometry.js index 69e9914477..344bb07036 100644 --- a/src/ol/geom/geometry.js +++ b/src/ol/geom/geometry.js @@ -180,6 +180,20 @@ ol.geom.Geometry.prototype.getExtent = function(opt_extent) { ol.geom.Geometry.prototype.rotate = function(angle, anchor) {}; +/** + * Scale the geometry (with an optional origin). This modifies the geometry + * coordinates in place. + * @abstract + * @param {number} sx The scaling factor in the x-direction. + * @param {number=} opt_sy The scaling factor in the y-direction (defaults to + * sx). + * @param {ol.Coordinate=} opt_anchor The scale origin (defaults to the center + * of the geometry extent). + * @api + */ +ol.geom.Geometry.prototype.scale = function(sx, opt_sy, opt_anchor) {}; + + /** * Create a simplified version of this geometry. For linestrings, this uses * the the {@link diff --git a/src/ol/geom/geometrycollection.js b/src/ol/geom/geometrycollection.js index 793141b373..0c6a6d52ce 100644 --- a/src/ol/geom/geometrycollection.js +++ b/src/ol/geom/geometrycollection.js @@ -244,6 +244,19 @@ ol.geom.GeometryCollection.prototype.rotate = function(angle, anchor) { }; +/** + * @inheritDoc + * @api + */ +ol.geom.GeometryCollection.prototype.scale = function(sx, opt_sy, opt_anchor) { + var geometries = this.geometries_; + for (var i = 0, ii = geometries.length; i < ii; ++i) { + geometries[i].scale(sx, opt_sy, opt_anchor); + } + this.changed(); +}; + + /** * Set the geometries that make up this geometry collection. * @param {Array.} geometries Geometries. diff --git a/src/ol/geom/simplegeometry.js b/src/ol/geom/simplegeometry.js index 7324386404..9089173d4d 100644 --- a/src/ol/geom/simplegeometry.js +++ b/src/ol/geom/simplegeometry.js @@ -278,6 +278,30 @@ ol.geom.SimpleGeometry.prototype.rotate = function(angle, anchor) { }; +/** + * @inheritDoc + * @api + */ +ol.geom.SimpleGeometry.prototype.scale = function(sx, opt_sy, opt_anchor) { + var sy = opt_sy; + if (sy === undefined) { + sy = sx; + } + var anchor = opt_anchor; + if (!anchor) { + anchor = ol.extent.getCenter(this.getExtent()); + } + var flatCoordinates = this.getFlatCoordinates(); + if (flatCoordinates) { + var stride = this.getStride(); + ol.geom.flat.transform.scale( + flatCoordinates, 0, flatCoordinates.length, + stride, sx, sy, anchor, flatCoordinates); + this.changed(); + } +}; + + /** * @inheritDoc * @api stable diff --git a/test/spec/ol/geom/linestring.test.js b/test/spec/ol/geom/linestring.test.js index 123b53010a..c3e133bfd4 100644 --- a/test/spec/ol/geom/linestring.test.js +++ b/test/spec/ol/geom/linestring.test.js @@ -242,6 +242,31 @@ describe('ol.geom.LineString', function() { }); + describe('#scale()', function() { + + it('scales a linestring', function() { + var geom = new ol.geom.LineString([[-10, -20], [10, 20]]); + geom.scale(10); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[-100, -200], [100, 200]]); + }); + + it('accepts sx and sy', function() { + var geom = new ol.geom.LineString([[-10, -20], [10, 20]]); + geom.scale(2, 3); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[-20, -60], [20, 60]]); + }); + + it('accepts an anchor', function() { + var geom = new ol.geom.LineString([[-10, -20], [10, 20]]); + geom.scale(3, 2, [10, 20]); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[-50, -60], [10, 20]]); + }); + + }); + describe('with a simple line string', function() { var lineString; diff --git a/test/spec/ol/geom/multilinestring.test.js b/test/spec/ol/geom/multilinestring.test.js index 555e14213e..a32dc7a96a 100644 --- a/test/spec/ol/geom/multilinestring.test.js +++ b/test/spec/ol/geom/multilinestring.test.js @@ -313,6 +313,31 @@ describe('ol.geom.MultiLineString', function() { }); + describe('#scale()', function() { + + it('scales a multi-linestring', function() { + var geom = new ol.geom.MultiLineString([[[-10, -20], [10, 20]], [[5, -10], [-5, 10]]]); + geom.scale(10); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[[-100, -200], [100, 200]], [[50, -100], [-50, 100]]]); + }); + + it('accepts sx and sy', function() { + var geom = new ol.geom.MultiLineString([[[-10, -20], [10, 20]], [[5, -10], [-5, 10]]]); + geom.scale(2, 3); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[[-20, -60], [20, 60]], [[10, -30], [-10, 30]]]); + }); + + it('accepts an anchor', function() { + var geom = new ol.geom.MultiLineString([[[-10, -20], [10, 20]], [[5, -10], [-5, 10]]]); + geom.scale(3, 2, [10, 20]); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[[-50, -60], [10, 20]], [[-5, -40], [-35, 0]]]); + }); + + }); + describe('#setLineStrings', function() { it('sets the line strings', function() { diff --git a/test/spec/ol/geom/multipoint.test.js b/test/spec/ol/geom/multipoint.test.js index 3b0fc57abf..44ae2e36bb 100644 --- a/test/spec/ol/geom/multipoint.test.js +++ b/test/spec/ol/geom/multipoint.test.js @@ -203,6 +203,31 @@ describe('ol.geom.MultiPoint', function() { }); + describe('#scale()', function() { + + it('scales a multi-point', function() { + var geom = new ol.geom.MultiPoint([[-10, -20], [10, 20]]); + geom.scale(10); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[-100, -200], [100, 200]]); + }); + + it('accepts sx and sy', function() { + var geom = new ol.geom.MultiPoint([[-10, -20], [10, 20]]); + geom.scale(2, 3); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[-20, -60], [20, 60]]); + }); + + it('accepts an anchor', function() { + var geom = new ol.geom.MultiPoint([[-10, -20], [10, 20]]); + geom.scale(3, 2, [-10, -20]); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([[-10, -20], [50, 60]]); + }); + + }); + describe('#applyTransform()', function() { var multi, transform; diff --git a/test/spec/ol/geom/point.test.js b/test/spec/ol/geom/point.test.js index 89f7b7f58e..18843125fe 100644 --- a/test/spec/ol/geom/point.test.js +++ b/test/spec/ol/geom/point.test.js @@ -129,6 +129,31 @@ describe('ol.geom.Point', function() { }); + describe('#scale()', function() { + + it('scales a point', function() { + var geom = new ol.geom.Point([1, 2]); + geom.scale(10e6); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([1, 2]); + }); + + it('accepts sx and sy', function() { + var geom = new ol.geom.Point([1, 2]); + geom.scale(1e6, -42); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([1, 2]); + }); + + it('accepts an anchor', function() { + var geom = new ol.geom.Point([1, 2]); + geom.scale(10, 15, [0, 0]); + var coordinates = geom.getCoordinates(); + expect(coordinates).to.eql([10, 30]); + }); + + }); + describe('#applyTransform()', function() { var point, transform;