我正在尝试在画布上检测多边形。我正在使用此堆栈溢出问题https://stackoverflow.com/a/15308571/3885989
中的代码function Vec2(x, y) {
return [x, y]
}
Vec2.nsub = function (v1, v2) {
return Vec2(v1[0] - v2[0], v1[1] - v2[1])
}
// aka the "scalar cross product"
Vec2.perpdot = function (v1, v2) {
return v1[0] * v2[1] - v1[1] * v2[0]
}
// Determine if a point is inside a polygon.
//
// point - A Vec2 (2-element Array).
// polyVerts - Array of Vec2's (2-element Arrays). The vertices that make
// up the polygon, in clockwise order around the polygon.
//
function coordsAreInside(point, polyVerts) {
var i, len, v1, v2, edge, x
// First translate the polygon so that `point` is the origin. Then, for each
// edge, get the angle between two vectors: 1) the edge vector and 2) the
// vector of the first vertex of the edge. If all of the angles are the same
// sign (which is negative since they will be counter-clockwise) then the
// point is inside the polygon; otherwise, the point is outside.
for (i = 0, len = polyVerts.length; i < len; i++) {
v1 = Vec2.nsub(polyVerts[i], point)
v2 = Vec2.nsub(polyVerts[i + 1 > len - 1 ? 0 : i + 1], point)
edge = Vec2.nsub(v1, v2)
// Note that we could also do this by using the normal + dot product
x = Vec2.perpdot(edge, v1)
// If the point lies directly on an edge then count it as in the polygon
if (x < 0) {
return false
}
}
return true
}
它工作正常,但是使用更复杂的形状,它不能很好地工作......这是一个孤立代码的链接,其中包含一个有效的形状和一个不可用的形状的示例: http://jsfiddle.net/snqF7/
答案 0 :(得分:2)
您使用的算法要求多边形为凸面
简而言之,凸起意味着您可以在多边形中的任意两点之间绘制直线,所有直线都在多边形内。
- 或多或少马铃薯或方形:) - 。
解决方案是将多边形分割为凸面部分,或者采用更复杂的算法来处理非凸多边形。
要处理非凸多边形,想法是在多边形中取一个你知道(或不是)的参考点,然后在测试点和这个参考点之间画一条线,然后计算多少次和它与多边形段相交的方向。在每个十字架上计数+1或-1,如果最终总和为空,则该点在内部。
答案 1 :(得分:2)
啊!就像GameAlchemist所说,问题是这个算法适用于凸多边形, 这是一个新的&amp;&amp;我使用这些C代码示例(http://alienryderflex.com/polygon/)翻译的非凸(或复杂)多边形(非完美)的改进算法
function pointInPolygon(point, polyVerts) {
var j = polyVerts.length - 1,
oddNodes = false,
polyY = [], polyX = [],
x = point[0],
y = point[1];
for (var s = 0; s < polyVerts.length; s++) {
polyX.push(polyVerts[s][0]);
polyY.push(polyVerts[s][1]);
};
for (var i = 0; i < polyVerts.length; i++) {
if ((polyY[i]< y && polyY[j]>=y
|| polyY[j]< y && polyY[i]>=y)
&& (polyX[i]<=x || polyX[j]<=x)) {
oddNodes^=(polyX[i]+(y-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i])<x);
}
j=i;
}
return oddNodes;
}
这是一个工作小提琴:http://jsfiddle.net/snqF7/3/