Merge pull request #6078 from bjornharrtell/windingnumber
Use winding number algorithm for linearRingContainsXY
This commit is contained in:
@@ -36,22 +36,30 @@ ol.geom.flat.contains.linearRingContainsExtent = function(flatCoordinates, offse
|
|||||||
* @return {boolean} Contains (x, y).
|
* @return {boolean} Contains (x, y).
|
||||||
*/
|
*/
|
||||||
ol.geom.flat.contains.linearRingContainsXY = function(flatCoordinates, offset, end, stride, x, y) {
|
ol.geom.flat.contains.linearRingContainsXY = function(flatCoordinates, offset, end, stride, x, y) {
|
||||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
// http://geomalgorithms.com/a03-_inclusion.html
|
||||||
var contains = false;
|
// 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.
|
||||||
|
var wn = 0;
|
||||||
var x1 = flatCoordinates[end - stride];
|
var x1 = flatCoordinates[end - stride];
|
||||||
var y1 = flatCoordinates[end - stride + 1];
|
var y1 = flatCoordinates[end - stride + 1];
|
||||||
for (; offset < end; offset += stride) {
|
for (; offset < end; offset += stride) {
|
||||||
var x2 = flatCoordinates[offset];
|
var x2 = flatCoordinates[offset];
|
||||||
var y2 = flatCoordinates[offset + 1];
|
var y2 = flatCoordinates[offset + 1];
|
||||||
var intersect = ((y1 > y) != (y2 > y)) &&
|
if (y1 <= y) {
|
||||||
(x < (x2 - x1) * (y - y1) / (y2 - y1) + x1);
|
if (y2 > y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) > 0) {
|
||||||
if (intersect) {
|
wn++;
|
||||||
contains = !contains;
|
}
|
||||||
|
} else if (y2 <= y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) < 0) {
|
||||||
|
wn--;
|
||||||
}
|
}
|
||||||
x1 = x2;
|
x1 = x2;
|
||||||
y1 = y2;
|
y1 = y2;
|
||||||
}
|
}
|
||||||
return contains;
|
return wn !== 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
42
test/spec/ol/geom/flat/contains.test.js
Normal file
42
test/spec/ol/geom/flat/contains.test.js
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
goog.provide('ol.test.geom.flat.contains');
|
||||||
|
|
||||||
|
goog.require('ol.geom.flat.contains');
|
||||||
|
|
||||||
|
|
||||||
|
describe('ol.geom.flat.contains', function() {
|
||||||
|
|
||||||
|
describe('with simple data', function() {
|
||||||
|
|
||||||
|
var flatCoordinatesSimple = [0, 0, 1, 0, 1, 1, 0, 1];
|
||||||
|
var flatCoordinatesNonSimple = [0, 0, 4, 0, 4, 3, 1, 3, 1, 2, 3, 2, 3, 1, 2, 1, 2, 4, 0, 4];
|
||||||
|
|
||||||
|
describe('ol.geom.flat.contains.linearRingContainsXY', function() {
|
||||||
|
|
||||||
|
it('returns true for point inside a simple polygon', function() {
|
||||||
|
expect(ol.geom.flat.contains.linearRingContainsXY(
|
||||||
|
flatCoordinatesSimple, 0, flatCoordinatesSimple.length, 2, 0.5, 0.5)).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false for point outside a simple polygon', function() {
|
||||||
|
expect(ol.geom.flat.contains.linearRingContainsXY(
|
||||||
|
flatCoordinatesSimple, 0, flatCoordinatesSimple.length, 2, 1.5, 1.5)).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true for point inside a non-simple polygon', function() {
|
||||||
|
expect(ol.geom.flat.contains.linearRingContainsXY(
|
||||||
|
flatCoordinatesNonSimple, 0, flatCoordinatesNonSimple.length, 2, 1, 1)).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns true for point inside an overlap of a non-simple polygon', function() {
|
||||||
|
expect(ol.geom.flat.contains.linearRingContainsXY(
|
||||||
|
flatCoordinatesNonSimple, 0, flatCoordinatesNonSimple.length, 2, 1.5, 2.5)).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns false for a point inside a hole of a non-simple polygon', function() {
|
||||||
|
expect(ol.geom.flat.contains.linearRingContainsXY(
|
||||||
|
flatCoordinatesNonSimple, 0, flatCoordinatesNonSimple.length, 2, 2.5, 1.5)).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user