d3 / d3-polygon

Geometric operations for two-dimensional polygons.
https://d3js.org/d3-polygon
ISC License
97 stars 25 forks source link

polygonContains should be uniform when testing the verteces of the polygon #30

Closed Kcnarf closed 4 years ago

Kcnarf commented 4 years ago
var d3Polygon = require("d3-polygon")
var unitSquare = [[0,0], [0,1], [1,1], [1,0]];
var polygonContains = d3Polygon.polygonContains;
unitSquare.forEach( p => console.log(`[${p}] in unitSquare : ${polygonContains(unitSquare, p)}`));

>"[0,0] in unitSquare : true"
>"[0,1] in unitSquare : false"
>"[1,1] in unitSquare : false"
>"[1,0] in unitSquare : false"

In Runkit => https://runkit.com/embed/tht1jbzi6iqq

Imho, all the verteces of the polygon should be either inside or outside.

mbostock commented 4 years ago

polygonContains is not robust, so it’s not guaranteed to return the correct result in edge cases like this. We could tweak the algorithm to make it perform better in special cases, but only at the expense of complexity and speed. I don’t think we want to go all the way to making it robust.

See https://observablehq.com/@tmcw/understanding-point-in-polygon for an explanation of the algorithm.

Kcnarf commented 4 years ago

Thanks for the response and the provided links.

I discovered the use case while debugging some tests I did for d3-weighted-voronoi plugin, which sometimes were failing. I was positioning a site at the [1,1] vertex, considered outside of the unit square, and hence re-position the site in a random fashion (hence the rare failure).

Closing the issue as the non-robustness seems assumed.

PS: perhaps a hint in the documentation may help.