From cdbc1a07be2a63ac8bac31be9985d6140132e0f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89ric=20Lemoine?= Date: Tue, 8 Jul 2014 16:19:13 +0200 Subject: [PATCH] Add ol.geom.flat.intersectsextent Includes functions for testing if an extent and a geometry intersect. --- src/ol/geom/flat/intersectsextent.js | 154 ++++++++++++++++++ .../flat/intersectsextentflatgeom.test.js | 92 +++++++++++ 2 files changed, 246 insertions(+) create mode 100644 src/ol/geom/flat/intersectsextent.js create mode 100644 test/spec/ol/geom/flat/intersectsextentflatgeom.test.js diff --git a/src/ol/geom/flat/intersectsextent.js b/src/ol/geom/flat/intersectsextent.js new file mode 100644 index 0000000000..6f880c7baa --- /dev/null +++ b/src/ol/geom/flat/intersectsextent.js @@ -0,0 +1,154 @@ +goog.provide('ol.geom.flat.intersectsextent'); + +goog.require('goog.asserts'); +goog.require('ol.extent'); +goog.require('ol.geom.flat.contains'); +goog.require('ol.geom.flat.segments'); + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {ol.Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +ol.geom.flat.intersectsextent.lineString = + function(flatCoordinates, offset, end, stride, extent) { + var coordinatesExtent = ol.extent.extendFlatCoordinates( + ol.extent.createEmpty(), flatCoordinates, offset, end, stride); + if (!ol.extent.intersects(extent, coordinatesExtent)) { + return false; + } + if (ol.extent.containsExtent(extent, coordinatesExtent)) { + return true; + } + if (coordinatesExtent[0] >= extent[0] && + coordinatesExtent[2] <= extent[2]) { + return true; + } + if (coordinatesExtent[1] >= extent[1] && + coordinatesExtent[3] <= extent[3]) { + return true; + } + return ol.geom.flat.segments.forEach(flatCoordinates, offset, end, stride, + /** + * @param {ol.Coordinate} point1 Start point. + * @param {ol.Coordinate} point2 End point. + * @return {boolean} `true` if the segment and the extent intersect, + * `false` otherwise. + */ + function(point1, point2) { + return ol.extent.segmentIntersects(extent, point1, point2); + }); +}; + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array.} ends Ends. + * @param {number} stride Stride. + * @param {ol.Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +ol.geom.flat.intersectsextent.lineStrings = + function(flatCoordinates, offset, ends, stride, extent) { + var i, ii; + for (i = 0, ii = ends.length; i < ii; ++i) { + if (ol.geom.flat.intersectsextent.lineString( + flatCoordinates, offset, ends[i], stride, extent)) { + return true; + } + offset = ends[i]; + } + return false; +}; + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {ol.Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +ol.geom.flat.intersectsextent.linearRing = + function(flatCoordinates, offset, end, stride, extent) { + if (ol.geom.flat.intersectsextent.lineString( + flatCoordinates, offset, end, stride, extent)) { + return true; + } + if (ol.geom.flat.contains.linearRingContainsXY( + flatCoordinates, offset, end, stride, extent[0], extent[1])) { + return true; + } + if (ol.geom.flat.contains.linearRingContainsXY( + flatCoordinates, offset, end, stride, extent[0], extent[3])) { + return true; + } + if (ol.geom.flat.contains.linearRingContainsXY( + flatCoordinates, offset, end, stride, extent[2], extent[1])) { + return true; + } + if (ol.geom.flat.contains.linearRingContainsXY( + flatCoordinates, offset, end, stride, extent[2], extent[3])) { + return true; + } + return false; +}; + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array.} ends Ends. + * @param {number} stride Stride. + * @param {ol.Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +ol.geom.flat.intersectsextent.linearRings = + function(flatCoordinates, offset, ends, stride, extent) { + goog.asserts.assert(ends.length > 0); + if (!ol.geom.flat.intersectsextent.linearRing( + flatCoordinates, offset, ends[0], stride, extent)) { + return false; + } + if (ends.length === 1) { + return true; + } + var i, ii; + for (i = 1, ii = ends.length; i < ii; ++i) { + if (ol.geom.flat.contains.linearRingContainsExtent( + flatCoordinates, ends[i - 1], ends[i], stride, extent)) { + return false; + } + } + return true; +}; + + +/** + * @param {Array.} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array.>} endss Endss. + * @param {number} stride Stride. + * @param {ol.Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +ol.geom.flat.intersectsextent.linearRingss = + function(flatCoordinates, offset, endss, stride, extent) { + goog.asserts.assert(endss.length > 0); + var i, ii; + for (i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + if (ol.geom.flat.intersectsextent.linearRings( + flatCoordinates, offset, ends, stride, extent)) { + return true; + } + offset = ends[ends.length - 1]; + } + return false; +}; diff --git a/test/spec/ol/geom/flat/intersectsextentflatgeom.test.js b/test/spec/ol/geom/flat/intersectsextentflatgeom.test.js new file mode 100644 index 0000000000..e929efc08e --- /dev/null +++ b/test/spec/ol/geom/flat/intersectsextentflatgeom.test.js @@ -0,0 +1,92 @@ +goog.provide('ol.test.geom.flat.intersectsextent'); + +describe('ol.geom.flat.intersectsextent', function() { + + describe('ol.geom.flat.intersectsextent.lineString', function() { + var flatCoordinates; + beforeEach(function() { + flatCoordinates = [0, 0, 1, 1, 2, 2]; + }); + describe('linestring envelope does not intersect the extent', function() { + it('returns false', function() { + var extent = [3, 3, 4, 4]; + var r = ol.geom.flat.intersectsextent.lineString( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(false); + }); + }); + describe('linestring envelope within the extent', function() { + it('returns true', function() { + var extent = [-1, -1, 3, 3]; + var r = ol.geom.flat.intersectsextent.lineString( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(true); + }); + }); + describe('linestring envelope bisected by an edge of the extent', + function() { + it('returns true', function() { + var extent = [-0.1, 0.1, 2.1, 0.1]; + var r = ol.geom.flat.intersectsextent.lineString( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(true); + }); + }); + describe('a segment intersects the extent', function() { + it('returns true', function() { + var extent = [-0.5, -0.5, 0.5, 0.5]; + var r = ol.geom.flat.intersectsextent.lineString( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(true); + }); + }); + describe('no segments intersect the extent', function() { + it('returns false', function() { + var extent = [0.5, 1.5, 1, 1.75]; + var r = ol.geom.flat.intersectsextent.lineString( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(false); + }); + it('returns false', function() { + var extent = [1, 0.25, 1.5, 0.5]; + var r = ol.geom.flat.intersectsextent.lineString( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(false); + }); + }); + }); + + describe('ol.geom.flat.intersectsextent.linearRing', function() { + var flatCoordinates; + beforeEach(function() { + flatCoordinates = [0, 0, 1, 1, 2, 0, 1, -1, 0, 0]; + }); + describe('boundary intersects the extent', function() { + it('returns true', function() { + var extent = [1.5, 0.0, 2.5, 1.0]; + var r = ol.geom.flat.intersectsextent.linearRing( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(true); + }); + }); + describe('boundary does not intersect the extent and ring does not ' + + 'contain a corner of the extent', function() { + it('returns false', function() { + var extent = [2.0, 0.5, 3, 1.5]; + var r = ol.geom.flat.intersectsextent.linearRing( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(false); + }); + }); + describe('ring contains the extent', function() { + it('returns true', function() { + var extent = [0.75, -0.25, 1.25, 0.25]; + var r = ol.geom.flat.intersectsextent.linearRing( + flatCoordinates, 0, flatCoordinates.length, 2, extent); + expect(r).to.be(true); + }); + }); + }); +}); + +goog.require('ol.geom.flat.intersectsextent');