diff --git a/examples/vector-layer.html b/examples/vector-layer.html index c34ff9cde5..6cea238384 100644 --- a/examples/vector-layer.html +++ b/examples/vector-layer.html @@ -37,7 +37,7 @@

Vector layer example

-

Example of a vector layer.

+

Example of a countries vector layer with country information on hover.

See the vector-layer.js source to see how this is done.

diff --git a/src/ol/geom/base.js b/src/ol/geom/base.js index 1b8d3e4a04..24c2ee75fe 100644 --- a/src/ol/geom/base.js +++ b/src/ol/geom/base.js @@ -42,31 +42,3 @@ ol.geom.squaredDistanceToSegment = function(coordinate, segment) { return ol.coordinate.squaredDistance(coordinate, [v[0] + t * (w[0] - v[0]), v[1] + t * (w[1] - v[1])]); }; - - -/** - * Calculate whether a point falls inside a polygon. - * - * @param {ol.Coordinate} coordinate Coordinate of the point. - * @param {Array.} vertices Vertices of the polygon. - * @return {boolean} Whether the point falls inside the polygon. - */ -ol.geom.pointInPolygon = function(coordinate, vertices) { - // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html - var x = coordinate[0], y = coordinate[1]; - var inside = false; - var xi, yi, xj, yj, intersect; - var numVertices = vertices.length; - for (var i = 0, j = numVertices - 1; i < numVertices; j = i++) { - xi = vertices[i][0]; - yi = vertices[i][1]; - xj = vertices[j][0]; - yj = vertices[j][1]; - intersect = ((yi > y) != (yj > y)) && - (x < (xj - xi) * (y - yi) / (yj - yi) + xi); - if (intersect) { - inside = !inside; - } - } - return inside; -}; diff --git a/src/ol/geom/linearring.js b/src/ol/geom/linearring.js index 0d2180be87..8437fd8543 100644 --- a/src/ol/geom/linearring.js +++ b/src/ol/geom/linearring.js @@ -33,3 +33,33 @@ goog.inherits(ol.geom.LinearRing, ol.geom.LineString); ol.geom.LinearRing.prototype.getType = function() { return ol.geom.GeometryType.LINEARRING; }; + + +/** + * Check whether a given coordinate is inside this ring. Note that this is a + * fast and simple check - points on an edge or vertex of the ring are either + * classified inside or outside. + * + * @param {ol.Coordinate} coordinate Coordinate. + * @return {boolean} Whether the coordinate is inside the ring. + */ +ol.geom.LinearRing.prototype.containsCoordinate = function(coordinate) { + // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html + var x = coordinate[0], y = coordinate[1]; + var vertices = this.getCoordinates(); + var inside = false; + var xi, yi, xj, yj, intersect; + var numVertices = vertices.length; + for (var i = 0, j = numVertices - 1; i < numVertices; j = i++) { + xi = vertices[i][0]; + yi = vertices[i][1]; + xj = vertices[j][0]; + yj = vertices[j][1]; + intersect = ((yi > y) != (yj > y)) && + (x < (xj - xi) * (y - yi) / (yj - yi) + xi); + if (intersect) { + inside = !inside; + } + } + return inside; +}; diff --git a/src/ol/geom/polygon.js b/src/ol/geom/polygon.js index 383cdebd98..57fd12ffd8 100644 --- a/src/ol/geom/polygon.js +++ b/src/ol/geom/polygon.js @@ -91,22 +91,24 @@ ol.geom.Polygon.prototype.getType = function() { /** - * Check whether a given coordinate is inside this polygon. + * Check whether a given coordinate is inside this polygon. Note that this is a + * fast and simple check - points on an edge or vertex of the polygon or one of + * its inner rings are either classified inside or outside. * * @param {ol.Coordinate} coordinate Coordinate. * @return {boolean} Whether the coordinate is inside the polygon. */ ol.geom.Polygon.prototype.containsCoordinate = function(coordinate) { var rings = this.rings; - var containsCoordinate = ol.geom.pointInPolygon(coordinate, - rings[0].getCoordinates()); - if (containsCoordinate) { - // if inner ring contains point, polygon does not contain it - for (var i = 1, ii = rings.length; i < ii; ++i) { - if (ol.geom.pointInPolygon(coordinate, rings[i].getCoordinates())) { - containsCoordinate = false; - break; - } + var containsCoordinate; + for (var i = 0, ii = rings.length; i < ii; ++i) { + containsCoordinate = rings[i].containsCoordinate(coordinate); + // if inner ring (i > 0) contains coordinate, polygon does not contain it + if (i > 0) { + containsCoordinate = !containsCoordinate; + } + if (!containsCoordinate) { + break; } } return containsCoordinate; diff --git a/test/spec/ol/geom/linearring.test.js b/test/spec/ol/geom/linearring.test.js index 402dfbf874..1c3380deff 100644 --- a/test/spec/ol/geom/linearring.test.js +++ b/test/spec/ol/geom/linearring.test.js @@ -40,6 +40,72 @@ describe('ol.geom.LinearRing', function() { }); + describe('#containsCoordinate()', function() { + + it('knows when a point coordinate is inside a ring', function() { + /** + * The ring: + * edge 3 + * (5, 10) __________ (15, 10) + * / / + * edge 4 / / edge 2 + * / / + * (0, 0) /_________/ (10, 0) + * edge 1 + */ + var ring = new ol.geom.LinearRing( + [[0, 0], [10, 0], [15, 10], [5, 10]]); + + // contains: 1 (touches - not implemented), true (within), false (outside) + var cases = [{ + point: [5, 5], contains: true + }, { + point: [20, 20], contains: false + }, { + point: [15, 15], contains: false + }/*, { + point: [0, 0], contains: 1 // lower left corner + }, { + point: [10, 0], contains: 1 // lower right corner + }, { + point: [15, 10], contains: 1 // upper right corner + }, { + point: [5, 10], contains: 1 // upper left corner + }, { + point: [5, 0], contains: 1 // on edge 1 + }*/, { + point: [5, -0.1], contains: false // below edge 1 + }, { + point: [5, 0.1], contains: true // above edge 1 + }/*, { + point: [12.5, 5], contains: 1 // on edge 2 + }*/, { + point: [12.4, 5], contains: true // left of edge 2 + }, { + point: [12.6, 5], contains: false // right of edge 2 + }/*, { + point: [10, 10], contains: 1 // on edge 3 + }*/, { + point: [10, 9.9], contains: true // below edge 3 + }, { + point: [10, 10.1], contains: false // above edge 3 + }/*, { + point: [2.5, 5], contains: 1 // on edge 4 + }*/, { + point: [2.4, 5], contains: false // left of edge 4 + }, { + point: [2.6, 5], contains: true // right of edge 4 + }]; + + var len = cases.length; + var c; + for (var i=0; i