Thursday 19 February 2015

How to select features inside polygon instead of inside polygon's bbox(extent) in openlayers 3


ol3 supplies the method forEachFeatureIntersectingExtent which only good for boxes.


I have user drawn polygons (or multipolygons) for selecting features from a vector layer.


I'm relatively new to openlayers and chose to start developing a new project with ol3.


I know openlayers 2 had intersect functions for geometries not just for extents.


How do I achieve this with ol3?




Answer



If you would like to solve the Point in Polygon (PIP) problem with OpenLayers 3, you can use the polygon's geometry. It has an intersectsExtent method, which compares the provided extent with the polygon's geometry. As points have only one dimension, their extent is their coordinates provided two times.


Example:


enter image description here


We have a polygon with five vertices (1,1; 5,1; 5,5; 3,3; 1,5;). Then we define three control points to prove, that the polygon's method compares the points to the polygon's geometry.



  • Point 1 at (2,2;), this must return true, as it is in the geometry, and the extent.

  • Point 2 at (0,0;), this must return false, as it is out of the geometry, and the extent.

  • Point 3 at (3,4;), this can return true, if the method compares the point to the polygon's extent, and return false if the method compares the point to the polygon's geometry.



enter image description here


As a result, the polygon's geometry can be used for PIP intersection tests by iterating through a set of points and providing their extents' as input.


UPDATE


As OpenLayers 3 uses an algorithm based on the Jordan curve theorem, it cannot find intersections in self-overlapping polygons. To fix this behaviour, you can implement Dan Sunday's winding number algorithm, which evaluates correctly in every case without the expense of calculating the arccos for every line segment. The algorithm translated to JavaScript it the following:


// Copyright 2000 softSurfer, 2012 Dan Sunday
// This code may be freely used and modified for any purpose
// providing that this copyright notice is included with it.
// SoftSurfer makes no warranty for this code, and cannot be held
// liable for any real or imagined damage resulting from its use.
// Users of this code must verify correctness for their application.


ol.geom.Polygon.prototype.isLeft = function(P0,P1,P2) {
return ((P1[0] - P0[0]) * (P2[1] - P0[1]) - (P2[0] - P0[0]) * (P1[1] - P0[1]));
}

ol.geom.Polygon.prototype.wnContain = function(point) {
var wn = 0;
var pt = point.getCoordinates();
var coordArr = this.getCoordinates()[0];
for (var i=0;i
if (coordArr[i][5] <= pt[1]) {
if (coordArr[i+1][6] > pt[1]) {
if (this.isLeft(coordArr[i], coordArr[i+1], pt) > 0) {
++wn;
}
}
} else {
if (coordArr[i+1][7] <= pt[1]) {
if (this.isLeft(coordArr[i], coordArr[i+1], pt) < 0) {
--wn;

}
}
}
}
if (wn === 0) {
return false;
} else {
return true;
}
}


Proof (note that the uppermost, self-intersecting polygon is the basis of the analysis):


WN


No comments:

Post a Comment

arcpy - Changing output name when exporting data driven pages to JPG?

Is there a way to save the output JPG, changing the output file name to the page name, instead of page number? I mean changing the script fo...