From 6b018bbaf93b4adba51a0ed8f73d1cd2f452499f Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sat, 22 Feb 2014 18:39:04 -0700 Subject: [PATCH] Testing segment intersection with extent If needed, this function can be modified to take two additional coorinates that will be set to the intersection points. --- src/ol/extent.js | 53 +++++++++++++++ test/spec/ol/extent.test.js | 125 ++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) diff --git a/src/ol/extent.js b/src/ol/extent.js index 989b889212..766beeaa62 100644 --- a/src/ol/extent.js +++ b/src/ol/extent.js @@ -643,6 +643,59 @@ ol.extent.scaleFromCenter = function(extent, value) { }; +/** + * Determine if the segment between two coordinates intersects (crosses, + * touches, or is contained by) the provided extent. + * @param {ol.Extent} extent The extent. + * @param {ol.Coordinate} start Segment start coordinate. + * @param {ol.Coordinate} end Segment end coordinate. + * @return {boolean} The segment intersects the extent. + */ +ol.extent.segmentIntersects = function(extent, start, end) { + var intersects = false; + var startRel = ol.extent.coordinateRelationship(extent, start); + var endRel = ol.extent.coordinateRelationship(extent, end); + if (startRel === ol.extent.Relationship.INTERSECTING || + endRel === ol.extent.Relationship.INTERSECTING) { + intersects = true; + } else { + var minX = extent[0]; + var minY = extent[1]; + var maxX = extent[2]; + var maxY = extent[3]; + var startX = start[0]; + var startY = start[1]; + var endX = end[0]; + var endY = end[1]; + var slope = (endY - startY) / (endX - startX); + var x, y; + if (!!(endRel & ol.extent.Relationship.ABOVE) && + !(startRel & ol.extent.Relationship.ABOVE)) { + // potentially intersects top + x = endX - ((endY - maxY) / slope); + intersects = x >= minX && x <= maxX; + } else if (!!(endRel & ol.extent.Relationship.RIGHT) && + !(startRel & ol.extent.Relationship.RIGHT)) { + // potentially intersects right + y = endY - ((endX - maxX) * slope); + intersects = y >= minY && y <= maxY; + } else if (!!(endRel & ol.extent.Relationship.BELOW) && + !(startRel & ol.extent.Relationship.BELOW)) { + // potentially intersects bottom + x = endX - ((endY - minY) / slope); + intersects = x >= minX && x <= maxX; + } else if (!!(endRel & ol.extent.Relationship.LEFT) && + !(startRel & ol.extent.Relationship.LEFT)) { + // potentially intersects left + y = endY - ((endX - minX) * slope); + intersects = y >= minY && y <= maxY; + } + + } + return intersects; +}; + + /** * @param {ol.Extent} extent1 Extent 1. * @param {ol.Extent} extent2 Extent 2. diff --git a/test/spec/ol/extent.test.js b/test/spec/ol/extent.test.js index f6fee8f1f6..52901cff5f 100644 --- a/test/spec/ol/extent.test.js +++ b/test/spec/ol/extent.test.js @@ -300,6 +300,131 @@ describe('ol.extent', function() { }); }); + describe('segmentIntersects()', function() { + + var extent = [-180, -90, 180, 90]; + var north = [0, 100]; + var northeast = [190, 100]; + var east = [190, 0]; + var southeast = [190, -100]; + var south = [0, -100]; + var southwest = [-190, -100]; + var west = [-190, 0]; + var northwest = [-190, 100]; + var center = [0, 0]; + var top = [0, 90]; + var right = [180, 0]; + var bottom = [-90, 0]; + var left = [-180, 0]; + var inside = [10, 10]; + + it('returns true if contained', function() { + var intersects = ol.extent.segmentIntersects(extent, center, inside); + expect(intersects).to.be(true); + }); + + it('returns true if crosses top', function() { + var intersects = ol.extent.segmentIntersects(extent, center, north); + expect(intersects).to.be(true); + }); + + it('returns true if crosses right', function() { + var intersects = ol.extent.segmentIntersects(extent, center, east); + expect(intersects).to.be(true); + }); + + it('returns true if crosses bottom', function() { + var intersects = ol.extent.segmentIntersects(extent, center, south); + expect(intersects).to.be(true); + }); + + it('returns true if crosses left', function() { + var intersects = ol.extent.segmentIntersects(extent, center, west); + expect(intersects).to.be(true); + }); + + it('returns false if above', function() { + var intersects = ol.extent.segmentIntersects(extent, northwest, north); + expect(intersects).to.be(false); + }); + + it('returns false if right', function() { + var intersects = ol.extent.segmentIntersects(extent, northeast, east); + expect(intersects).to.be(false); + }); + + it('returns false if below', function() { + var intersects = ol.extent.segmentIntersects(extent, south, southwest); + expect(intersects).to.be(false); + }); + + it('returns false if left', function() { + var intersects = ol.extent.segmentIntersects(extent, west, southwest); + expect(intersects).to.be(false); + }); + + it('returns true if crosses top to bottom', function() { + var intersects = ol.extent.segmentIntersects(extent, north, south); + expect(intersects).to.be(true); + }); + + it('returns true if crosses bottom to top', function() { + var intersects = ol.extent.segmentIntersects(extent, south, north); + expect(intersects).to.be(true); + }); + + it('returns true if crosses left to right', function() { + var intersects = ol.extent.segmentIntersects(extent, west, east); + expect(intersects).to.be(true); + }); + + it('returns true if crosses right to left', function() { + var intersects = ol.extent.segmentIntersects(extent, east, west); + expect(intersects).to.be(true); + }); + + it('returns true if crosses northwest to east', function() { + var intersects = ol.extent.segmentIntersects(extent, northwest, east); + expect(intersects).to.be(true); + }); + + it('returns true if crosses south to west', function() { + var intersects = ol.extent.segmentIntersects(extent, south, west); + expect(intersects).to.be(true); + }); + + it('returns true if touches top', function() { + var intersects = ol.extent.segmentIntersects(extent, northwest, top); + expect(intersects).to.be(true); + }); + + it('returns true if touches right', function() { + var intersects = ol.extent.segmentIntersects(extent, southeast, right); + expect(intersects).to.be(true); + }); + + it('returns true if touches bottom', function() { + var intersects = ol.extent.segmentIntersects(extent, bottom, south); + expect(intersects).to.be(true); + }); + + it('returns true if touches left', function() { + var intersects = ol.extent.segmentIntersects(extent, left, west); + expect(intersects).to.be(true); + }); + + it('works for zero length inside', function() { + var intersects = ol.extent.segmentIntersects(extent, center, center); + expect(intersects).to.be(true); + }); + + it('works for zero length outside', function() { + var intersects = ol.extent.segmentIntersects(extent, north, north); + expect(intersects).to.be(false); + }); + + }); + describe('transform', function() { it('does transform', function() {