Get hit candidates from RTree, then refine result
Now we get exact hits also for lines and polygons.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
goog.provide('ol.geom.Vertex');
|
||||
goog.provide('ol.geom.VertexArray');
|
||||
|
||||
goog.require('ol.coordinate');
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {Array.<number>}
|
||||
@@ -12,3 +14,59 @@ ol.geom.Vertex;
|
||||
* @typedef {Array.<ol.geom.Vertex>}
|
||||
*/
|
||||
ol.geom.VertexArray;
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the squared distance from a point to a line segment.
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate of the point.
|
||||
* @param {Array.<ol.Coordinate>} segment Line segment (2 coordinates).
|
||||
* @return {number} Squared distance from the point to the line segment.
|
||||
*/
|
||||
ol.geom.squaredDistanceToSegment = function(coordinate, segment) {
|
||||
// http://de.softuses.com/103478, Kommentar #1
|
||||
var v = segment[0];
|
||||
var w = segment[1];
|
||||
var l2 = ol.coordinate.squaredDistance(v, w);
|
||||
if (l2 == 0) {
|
||||
return ol.coordinate.squaredDistance(coordinate, v);
|
||||
}
|
||||
var t = ((coordinate[0] - v[0]) * (w[0] - v[0]) +
|
||||
(coordinate[1] - v[1]) * (w[1] - v[1])) / l2;
|
||||
if (t < 0) {
|
||||
return ol.coordinate.squaredDistance(coordinate, v);
|
||||
}
|
||||
if (t > 1) {
|
||||
return ol.coordinate.squaredDistance(coordinate, w);
|
||||
}
|
||||
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.<ol.Coordinate>} 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;
|
||||
};
|
||||
|
||||
@@ -146,3 +146,20 @@ ol.geom.LineString.prototype.getType = function() {
|
||||
ol.geom.LineString.prototype.getSharedId = function() {
|
||||
return this.sharedId_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the distance from a coordinate to this linestring.
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {number} Distance from the coordinate to this linestring.
|
||||
*/
|
||||
ol.geom.LineString.prototype.distanceFromCoordinate = function(coordinate) {
|
||||
var coordinates = this.getCoordinates();
|
||||
var dist2 = Infinity;
|
||||
for (var i = 0, j = 1, len = coordinates.length; j < len; i = j++) {
|
||||
dist2 = Math.min(dist2, ol.geom.squaredDistanceToSegment(coordinate,
|
||||
[coordinates[i], coordinates[j]]));
|
||||
}
|
||||
return Math.sqrt(dist2);
|
||||
};
|
||||
|
||||
@@ -55,6 +55,25 @@ ol.geom.MultiLineString.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the distance from a coordinate to this multilinestring. This is
|
||||
* the closest distance of the coordinate to one of this multilinestring's
|
||||
* components.<
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {number} Distance from the coordinate to this multilinestring.
|
||||
*/
|
||||
ol.geom.MultiLineString.prototype.distanceFromCoordinate =
|
||||
function(coordinate) {
|
||||
var distance = Infinity;
|
||||
for (var i = 0, ii = this.components.length; i < ii; ++i) {
|
||||
distance = Math.min(distance,
|
||||
this.components[i].distanceFromCoordinate(coordinate));
|
||||
}
|
||||
return distance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a multi-linestring geometry from an array of linestring geometries.
|
||||
*
|
||||
|
||||
@@ -56,6 +56,24 @@ ol.geom.MultiPolygon.prototype.getType = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check whether a given coordinate is inside this multipolygon.
|
||||
*
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @return {boolean} Whether the coordinate is inside the multipolygon.
|
||||
*/
|
||||
ol.geom.MultiPolygon.prototype.containsCoordinate = function(coordinate) {
|
||||
var containsCoordinate = false;
|
||||
for (var i = 0, ii = this.components.length; i < ii; ++i) {
|
||||
if (this.components[i].containsCoordinate(coordinate)) {
|
||||
containsCoordinate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return containsCoordinate;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a multi-polygon geometry from an array of polygon geometries.
|
||||
*
|
||||
|
||||
@@ -88,3 +88,26 @@ ol.geom.Polygon.prototype.getCoordinates = function() {
|
||||
ol.geom.Polygon.prototype.getType = function() {
|
||||
return ol.geom.GeometryType.POLYGON;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check whether a given coordinate is inside this polygon.
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
}
|
||||
return containsCoordinate;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user