From 405d5666e2c3848c4188a863e8a2e0be0a648eb1 Mon Sep 17 00:00:00 2001 From: Alvin Lindstam Date: Fri, 5 Jun 2015 09:57:36 +0200 Subject: [PATCH 1/3] Add tests for intersectsExtent/getExtent This commit adds tests for `intersectsExtent` of Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon and GeometryCollection. It also adds a basic test for `getExtent` of MultiPolygon --- test/spec/ol/geom/geometrycollection.test.js | 30 +++++++ test/spec/ol/geom/linestring.test.js | 64 +++++++++++++++ test/spec/ol/geom/multilinestring.test.js | 12 +++ test/spec/ol/geom/multipoint.test.js | 12 +++ test/spec/ol/geom/multipolygon.test.js | 24 ++++++ test/spec/ol/geom/point.test.js | 24 ++++++ test/spec/ol/geom/polygon.test.js | 83 ++++++++++++++++++++ 7 files changed, 249 insertions(+) diff --git a/test/spec/ol/geom/geometrycollection.test.js b/test/spec/ol/geom/geometrycollection.test.js index 9cefbf98ff..3c910ae43f 100644 --- a/test/spec/ol/geom/geometrycollection.test.js +++ b/test/spec/ol/geom/geometrycollection.test.js @@ -1,5 +1,6 @@ goog.provide('ol.test.geom.GeometryCollection'); +goog.require('ol.extent'); describe('ol.geom.GeometryCollection', function() { @@ -114,6 +115,35 @@ describe('ol.geom.GeometryCollection', function() { }); + describe('#intersectsExtent()', function() { + + beforeEach(function() { + point = new ol.geom.Point([5, 20]); + line = new ol.geom.LineString([[10, 20], [30, 40]]); + poly = new ol.geom.Polygon([outer, inner1, inner2]); + multi = new ol.geom.GeometryCollection([point, line, poly]); + }); + + it('returns true for intersecting point', function() { + expect(multi.intersectsExtent([5, 20, 5, 20])).to.be(true); + }); + + it('returns true for intersecting part of lineString', function() { + expect(multi.intersectsExtent([25, 35, 30, 40])).to.be(true); + }); + + it('returns true for intersecting part of polygon', function() { + expect(multi.intersectsExtent([0, 0, 5, 5])).to.be(true); + }); + + + it('returns false for non-matching extent within own extent', function() { + var extent = [0, 35, 5, 40]; + expect(poly.intersectsExtent(extent)).to.be(false); + }); + + }); + describe('#setGeometries', function() { var line, multi, point, poly; diff --git a/test/spec/ol/geom/linestring.test.js b/test/spec/ol/geom/linestring.test.js index 9b8808a0eb..f4dd6cbd11 100644 --- a/test/spec/ol/geom/linestring.test.js +++ b/test/spec/ol/geom/linestring.test.js @@ -73,6 +73,22 @@ describe('ol.geom.LineString', function() { expect(lineString.getStride()).to.be(2); }); + describe('#intersectsExtent', function() { + + it('return false for non matching extent', function() { + expect(lineString.intersectsExtent([1, 3, 1.9, 4])).to.be(false); + }); + + it('return true for extent on midpoint', function() { + expect(lineString.intersectsExtent([2, 3, 4, 3])).to.be(true); + }); + + it('returns true for the geom\'s own extent', function() { + expect(lineString.intersectsExtent(lineString.getExtent())).to.be(true); + }); + + }); + }); describe('construct with 3D coordinates', function() { @@ -102,6 +118,22 @@ describe('ol.geom.LineString', function() { expect(lineString.getStride()).to.be(3); }); + describe('#intersectsExtent', function() { + + it('return false for non matching extent', function() { + expect(lineString.intersectsExtent([1, 3, 1.9, 4])).to.be(false); + }); + + it('return true for extent on midpoint', function() { + expect(lineString.intersectsExtent([2, 3, 4, 3])).to.be(true); + }); + + it('returns true for the geom\'s own extent', function() { + expect(lineString.intersectsExtent(lineString.getExtent())).to.be(true); + }); + + }); + }); describe('construct with 3D coordinates and layout XYM', function() { @@ -132,6 +164,22 @@ describe('ol.geom.LineString', function() { expect(lineString.getStride()).to.be(3); }); + describe('#intersectsExtent', function() { + + it('return false for non matching extent', function() { + expect(lineString.intersectsExtent([1, 3, 1.9, 4])).to.be(false); + }); + + it('return true for extent on midpoint', function() { + expect(lineString.intersectsExtent([2, 3, 4, 3])).to.be(true); + }); + + it('returns true for the geom\'s own extent', function() { + expect(lineString.intersectsExtent(lineString.getExtent())).to.be(true); + }); + + }); + }); describe('construct with 4D coordinates', function() { @@ -161,6 +209,22 @@ describe('ol.geom.LineString', function() { expect(lineString.getStride()).to.be(4); }); + describe('#intersectsExtent', function() { + + it('return false for non matching extent', function() { + expect(lineString.intersectsExtent([1, 3, 1.9, 4])).to.be(false); + }); + + it('return true for extent on midpoint', function() { + expect(lineString.intersectsExtent([2, 3, 4, 3])).to.be(true); + }); + + it('returns true for the geom\'s own extent', function() { + expect(lineString.intersectsExtent(lineString.getExtent())).to.be(true); + }); + + }); + }); describe('with a simple line string', function() { diff --git a/test/spec/ol/geom/multilinestring.test.js b/test/spec/ol/geom/multilinestring.test.js index 92470424db..ba989e30f7 100644 --- a/test/spec/ol/geom/multilinestring.test.js +++ b/test/spec/ol/geom/multilinestring.test.js @@ -88,6 +88,18 @@ describe('ol.geom.MultiLineString', function() { }); + describe('#intersectsExtent()', function() { + + it('returns true for intersecting part of lineString', function() { + expect(multiLineString.intersectsExtent([1, 2, 2, 3])).to.be(true); + }); + + it('returns false for non-matching extent within own extent', function() { + expect(multiLineString.intersectsExtent([1, 7, 2, 8])).to.be(false); + }); + + }); + }); describe('construct with 3D coordinates', function() { diff --git a/test/spec/ol/geom/multipoint.test.js b/test/spec/ol/geom/multipoint.test.js index e7f090dc72..b4f866e47a 100644 --- a/test/spec/ol/geom/multipoint.test.js +++ b/test/spec/ol/geom/multipoint.test.js @@ -73,6 +73,18 @@ describe('ol.geom.MultiPoint', function() { expect(multiPoint.getStride()).to.be(2); }); + describe('#intersectsExtent()', function() { + + it('returns true for extent covering a point', function() { + expect(multiPoint.intersectsExtent([1, 2, 2, 2])).to.be(true); + }); + + it('returns false for non-matching extent within own extent', function() { + expect(multiPoint.intersectsExtent([2, 3, 2, 4])).to.be(false); + }); + + }); + }); describe('construct with 3D coordinates', function() { diff --git a/test/spec/ol/geom/multipolygon.test.js b/test/spec/ol/geom/multipolygon.test.js index 64ca5e494b..6143d0dc43 100644 --- a/test/spec/ol/geom/multipolygon.test.js +++ b/test/spec/ol/geom/multipolygon.test.js @@ -115,6 +115,14 @@ describe('ol.geom.MultiPolygon', function() { }); + describe('#getExtent()', function() { + + it('returns expected result', function() { + expect(multiPolygon.getExtent()).to.eql([0, 0, 5, 2]); + }); + + }); + describe('#getSimplifiedGeometry', function() { it('returns the expected result', function() { @@ -127,6 +135,22 @@ describe('ol.geom.MultiPolygon', function() { }); }); + describe('#intersectsExtent()', function() { + + it('returns true for extent of of each polygon', function() { + var polygons = multiPolygon.getPolygons(); + for (var i = 0; i < polygons.length; i++) { + expect(multiPolygon.intersectsExtent( + polygons[i].getExtent())).to.be(true); + } + }); + + it('returns false for non-matching extent within own extent', function() { + expect(multiPolygon.intersectsExtent([2.1, 0, 2.9, 2])).to.be(false); + }); + + }); + }); }); diff --git a/test/spec/ol/geom/point.test.js b/test/spec/ol/geom/point.test.js index 66ef298b33..78fe361c4a 100644 --- a/test/spec/ol/geom/point.test.js +++ b/test/spec/ol/geom/point.test.js @@ -37,6 +37,14 @@ describe('ol.geom.Point', function() { expect(point.getStride()).to.be(2); }); + it('does not intersect non matching extent', function() { + expect(point.intersectsExtent([0, 0, 10, 0.5])).to.be(false); + }); + + it('does intersect it\'s extent', function() { + expect(point.intersectsExtent(point.getExtent())).to.be(true); + }); + }); describe('construct with 3D coordinates and layout XYM', function() { @@ -66,6 +74,14 @@ describe('ol.geom.Point', function() { expect(point.getStride()).to.be(3); }); + it('does not intersect non matching extent', function() { + expect(point.intersectsExtent([0, 0, 10, 0.5])).to.be(false); + }); + + it('does intersect it\'s extent', function() { + expect(point.intersectsExtent(point.getExtent())).to.be(true); + }); + }); describe('construct with 4D coordinates', function() { @@ -95,6 +111,14 @@ describe('ol.geom.Point', function() { expect(point.getStride()).to.be(4); }); + it('does not intersect non matching extent', function() { + expect(point.intersectsExtent([0, 0, 10, 0.5])).to.be(false); + }); + + it('does intersect it\'s extent', function() { + expect(point.intersectsExtent(point.getExtent())).to.be(true); + }); + describe('#getClosestPoint', function() { it('preseves extra dimensions', function() { diff --git a/test/spec/ol/geom/polygon.test.js b/test/spec/ol/geom/polygon.test.js index 2b42111f91..7eeb87635e 100644 --- a/test/spec/ol/geom/polygon.test.js +++ b/test/spec/ol/geom/polygon.test.js @@ -215,6 +215,33 @@ describe('ol.geom.Polygon', function() { expect(polygon.containsCoordinate(insideInner)).to.be(false); }); + describe('#intersectsExtent', function() { + + it('does not intersect outside extent', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([outsideOuter]))).to.be(false); + }); + + it('does intersect inside extent', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([inside]))).to.be(true); + }); + + it('does intersect boundary extent', function() { + var firstMidX = (outerRing[0][0] + outerRing[1][0]) / 2; + var firstMidY = (outerRing[0][1] + outerRing[1][1]) / 2; + + expect(polygon.intersectsExtent(ol.extent.boundingExtent([[firstMidX, + firstMidY]]))).to.be(true); + }); + + it('does not intersect extent fully contained by inner ring', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([insideInner]))).to.be(false); + }); + + }); + describe('#getOrientedFlatCoordinates', function() { it('reverses the outer ring if necessary', function() { @@ -287,6 +314,33 @@ describe('ol.geom.Polygon', function() { expect(polygon.containsCoordinate(insideInner)).to.be(false); }); + describe('#intersectsExtent', function() { + + it('does not intersect outside extent', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([outsideOuter]))).to.be(false); + }); + + it('does intersect inside extent', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([inside]))).to.be(true); + }); + + it('does intersect boundary extent', function() { + var firstMidX = (outerRing[0][0] + outerRing[1][0]) / 2; + var firstMidY = (outerRing[0][1] + outerRing[1][1]) / 2; + + expect(polygon.intersectsExtent(ol.extent.boundingExtent([[firstMidX, + firstMidY]]))).to.be(true); + }); + + it('does not intersect extent fully contained by inner ring', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([insideInner]))).to.be(false); + }); + + }); + describe('#getOrientedFlatCoordinates', function() { it('reverses the outer ring if necessary', function() { @@ -367,6 +421,35 @@ describe('ol.geom.Polygon', function() { expect(polygon.containsCoordinate(insideInner2)).to.be(false); }); + describe('#intersectsExtent', function() { + + it('does not intersect outside extent', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([outsideOuter]))).to.be(false); + }); + + it('does intersect inside extent', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([inside]))).to.be(true); + }); + + it('does intersect boundary extent', function() { + var firstMidX = (outerRing[0][0] + outerRing[1][0]) / 2; + var firstMidY = (outerRing[0][1] + outerRing[1][1]) / 2; + + expect(polygon.intersectsExtent(ol.extent.boundingExtent([[firstMidX, + firstMidY]]))).to.be(true); + }); + + it('does not intersect extent fully contained by inner ring', function() { + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([insideInner1]))).to.be(false); + expect(polygon.intersectsExtent( + ol.extent.boundingExtent([insideInner2]))).to.be(false); + }); + + }); + describe('#getOrientedFlatCoordinates', function() { it('reverses the outer ring if necessary', function() { From 1dc6c9932820ccecbbfcfb6b4479a9ef7819c2fb Mon Sep 17 00:00:00 2001 From: Alvin Lindstam Date: Fri, 5 Jun 2015 10:47:54 +0200 Subject: [PATCH 2/3] Make ol.geom.Circle support #intersectsExtent, with tests --- src/ol/geom/circle.js | 23 +++++++++++++++++++++++ test/spec/ol/geom/circle.test.js | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/ol/geom/circle.js b/src/ol/geom/circle.js index 8d04d541c1..ac24f592c5 100644 --- a/src/ol/geom/circle.js +++ b/src/ol/geom/circle.js @@ -137,6 +137,29 @@ ol.geom.Circle.prototype.getType = function() { }; +/** + * @inheritDoc + * @api stable + */ +ol.geom.Circle.prototype.intersectsExtent = function(extent) { + var circleExtent = this.getExtent(); + if (ol.extent.intersects(extent, circleExtent)) { + var center = this.getCenter(); + + if (extent[0] <= center[0] && extent[2] >= center[0]) { + return true; + } + if (extent[1] <= center[1] && extent[3] >= center[1]) { + return true; + } + + return ol.extent.forEachCorner(extent, this.containsCoordinate, this); + } + return false; + +}; + + /** * Set the center of the circle as {@link ol.Coordinate coordinate}. * @param {ol.Coordinate} center Center. diff --git a/test/spec/ol/geom/circle.test.js b/test/spec/ol/geom/circle.test.js index 463d8c257b..bb5fc9a8b9 100644 --- a/test/spec/ol/geom/circle.test.js +++ b/test/spec/ol/geom/circle.test.js @@ -203,6 +203,30 @@ describe('ol.geom.Circle', function() { }); + describe('#intersectsExtent', function() { + + it('return false for non matching extent', function() { + expect(circle.intersectsExtent([0.9, 0.9, 10, 10])).to.be(false); + }); + + it('return true for extent within circle', function() { + expect(circle.intersectsExtent([0.5, 0.5, 0.5, 0.5])).to.be(true); + }); + + it('return true for extent overlapping circle', function() { + expect(circle.intersectsExtent([0.5, 0.5, 10, 10])).to.be(true); + }); + + it('return true for non-overlapping but intersecting extent', function() { + expect(circle.intersectsExtent([0, 1, 1, 2])).to.be(true); + }); + + it('returns true for the geom\'s own extent', function() { + expect(circle.intersectsExtent(circle.getExtent())).to.be(true); + }); + + }); + }); }); From 488a55c83ce829c809fff78c994aba821400283e Mon Sep 17 00:00:00 2001 From: Marc Jansen Date: Fri, 5 Jun 2015 13:09:56 +0200 Subject: [PATCH 3/3] Add more tests for intersectsExtent --- test/spec/ol/geom/circle.test.js | 61 +++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/test/spec/ol/geom/circle.test.js b/test/spec/ol/geom/circle.test.js index bb5fc9a8b9..c844108640 100644 --- a/test/spec/ol/geom/circle.test.js +++ b/test/spec/ol/geom/circle.test.js @@ -205,24 +205,67 @@ describe('ol.geom.Circle', function() { describe('#intersectsExtent', function() { - it('return false for non matching extent', function() { - expect(circle.intersectsExtent([0.9, 0.9, 10, 10])).to.be(false); + it('returns false for non-intersecting extents (wide outside own bbox)', + function() { + var wideOutsideLeftTop = [-3, 2, -2, 3]; + var wideOutsideRightTop = [2, 2, 3, 3]; + var wideOutsideRightBottom = [2, -3, 3, -2]; + var wideOutsideLeftBottom = [-3, -3, -2, -2]; + expect(circle.intersectsExtent(wideOutsideLeftTop)).to.be(false); + expect(circle.intersectsExtent(wideOutsideRightTop)).to.be(false); + expect(circle.intersectsExtent(wideOutsideRightBottom)).to.be(false); + expect(circle.intersectsExtent(wideOutsideLeftBottom)).to.be(false); + } + ); + + it('returns false for non-intersecting extents (inside own bbox)', + function() { + var nearOutsideLeftTop = [-1, 0.9, -0.9, 1]; + var nearOutsideRightTop = [0.9, 0.9, 1, 1]; + var nearOutsideRightBottom = [0.9, -1, 1, -0.9]; + var nearOutsideLeftBottom = [-1, -1, -0.9, -0.9]; + expect(circle.intersectsExtent(nearOutsideLeftTop)).to.be(false); + expect(circle.intersectsExtent(nearOutsideRightTop)).to.be(false); + expect(circle.intersectsExtent(nearOutsideRightBottom)).to.be(false); + expect(circle.intersectsExtent(nearOutsideLeftBottom)).to.be(false); + } + ); + + it('returns true for extents that intersect clearly', function() { + var intersectingLeftTop = [-1.5, 0.5, -0.5, 1.5]; + var intersectingRightTop = [0.5, 0.5, 1.5, 1.5]; + var intersectingRightBottom = [0.5, -1.5, 1.5, -0.5]; + var intersectingLeftBottom = [-1.5, -1.5, -0.5, -0.5]; + expect(circle.intersectsExtent(intersectingLeftTop)).to.be(true); + expect(circle.intersectsExtent(intersectingRightTop)).to.be(true); + expect(circle.intersectsExtent(intersectingRightBottom)).to.be(true); + expect(circle.intersectsExtent(intersectingLeftBottom)).to.be(true); }); - it('return true for extent within circle', function() { - expect(circle.intersectsExtent([0.5, 0.5, 0.5, 0.5])).to.be(true); + it('returns true for extents that touch the circumference', function() { + var touchCircumferenceLeft = [-2, 0, -1, 1]; + var touchCircumferenceTop = [0, 1, 1, 2]; + var touchCircumferenceRight = [1, -1, 2, 0]; + var touchCircumferenceBottom = [-1, -2, 0, -1]; + expect(circle.intersectsExtent(touchCircumferenceLeft)).to.be(true); + expect(circle.intersectsExtent(touchCircumferenceTop)).to.be(true); + expect(circle.intersectsExtent(touchCircumferenceRight)).to.be(true); + expect(circle.intersectsExtent(touchCircumferenceBottom)).to.be(true); }); - it('return true for extent overlapping circle', function() { - expect(circle.intersectsExtent([0.5, 0.5, 10, 10])).to.be(true); + it('returns true for a contained extent', function() { + var containedExtent = [-0.5, -0.5, 0.5, 0.5]; + expect(circle.intersectsExtent(containedExtent)).to.be(true); }); - it('return true for non-overlapping but intersecting extent', function() { - expect(circle.intersectsExtent([0, 1, 1, 2])).to.be(true); + it('returns true for a covering extent', function() { + var bigCoveringExtent = [-5, -5, 5, 5]; + expect(circle.intersectsExtent(bigCoveringExtent)).to.be(true); }); it('returns true for the geom\'s own extent', function() { - expect(circle.intersectsExtent(circle.getExtent())).to.be(true); + var circleExtent = circle.getExtent(); + expect(circle.intersectsExtent(circleExtent)).to.be(true); }); });