From b374d5c5b8da12c345645d2abbd0405ff61ad266 Mon Sep 17 00:00:00 2001 From: Tom Payne Date: Fri, 6 Dec 2013 19:35:10 +0100 Subject: [PATCH] Avoid simplifying geometries when it will have no effect --- src/ol/geom/geometry.js | 29 +++++++++++++++++++++++++--- test/spec/ol/geom/linestring.test.js | 13 ++++++++++++- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/ol/geom/geometry.js b/src/ol/geom/geometry.js index 80a9b3cb88..7f85cdafcb 100644 --- a/src/ol/geom/geometry.js +++ b/src/ol/geom/geometry.js @@ -87,6 +87,12 @@ ol.geom.Geometry = function() { */ this.simplifiedGeometryCache_ = {}; + /** + * @private + * @type {number} + */ + this.simplifiedGeometryMaxMinSquaredTolerance_ = 0; + /** * @private * @type {number} @@ -207,9 +213,14 @@ ol.geom.Geometry.prototype.getRevision = function() { ol.geom.Geometry.prototype.getSimplifiedGeometry = function(squaredTolerance) { if (this.simplifiedGeometryRevision_ != this.revision) { goog.object.clear(this.simplifiedGeometryCache_); + this.simplifiedGeometryMaxMinSquaredTolerance_ = 0; this.simplifiedGeometryRevision_ = this.revision; } - if (squaredTolerance < 0) { + // If squaredTolerance is negative or if we know that simplification will not + // have any effect then just return this. + if (squaredTolerance < 0 || + (this.simplifiedGeometryMaxMinSquaredTolerance_ !== 0 && + squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance_)) { return this; } var key = squaredTolerance.toString(); @@ -218,8 +229,20 @@ ol.geom.Geometry.prototype.getSimplifiedGeometry = function(squaredTolerance) { } else { var simplifiedGeometry = this.getSimplifiedGeometryInternal(squaredTolerance); - this.simplifiedGeometryCache_[key] = simplifiedGeometry; - return simplifiedGeometry; + var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates(); + if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) { + this.simplifiedGeometryCache_[key] = simplifiedGeometry; + return simplifiedGeometry; + } else { + // Simplification did not actually remove any coordinates. We now know + // that any calls to getSimplifiedGeometry with a squaredTolerance less + // than or equal to the current squaredTolerance will also not have any + // effect. This allows us to short circuit simplification (saving CPU + // cycles) and prevents the cache of simplified geometries from filling + // up with useless identical copies of this geometry (saving memory). + this.simplifiedGeometryMaxMinSquaredTolerance_ = squaredTolerance; + return this; + } } }; diff --git a/test/spec/ol/geom/linestring.test.js b/test/spec/ol/geom/linestring.test.js index 1a45d345b8..9060945a35 100644 --- a/test/spec/ol/geom/linestring.test.js +++ b/test/spec/ol/geom/linestring.test.js @@ -161,7 +161,7 @@ describe('ol.geom.LineString', function() { var lineString; beforeEach(function() { lineString = new ol.geom.LineString( - [[0, 0], [1, 1], [3, 3], [5, 1], [6, 3], [7, 5]]); + [[0, 0], [1.5, 1], [3, 3], [5, 1], [6, 3.5], [7, 5]]); }); describe('#getSimplifiedGeometry', function() { @@ -186,7 +186,18 @@ describe('ol.geom.LineString', function() { expect(simplifiedGeometry1).not.to.be(simplifiedGeometry2); }); + it('remembers the minimum squared tolerance', function() { + sinon.spy(lineString, 'getSimplifiedGeometryInternal'); + var simplifiedGeometry1 = lineString.getSimplifiedGeometry(0.05); + expect(lineString.getSimplifiedGeometryInternal.callCount).to.be(1); + expect(simplifiedGeometry1).to.be(lineString); + var simplifiedGeometry2 = lineString.getSimplifiedGeometry(0.01); + expect(lineString.getSimplifiedGeometryInternal.callCount).to.be(1); + expect(simplifiedGeometry2).to.be(lineString); + }); + }); + }); });