简体   繁体   English

画布中的多边形边缘处理和检测

[英]polygon edge handling and detection in canvas

I'm trying to detect polygons on a canvas. 我正在尝试检测画布上的多边形。 I'm using code from this stack overflow question https://stackoverflow.com/a/15308571/3885989 我正在使用来自此堆栈溢出问题的代码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
}

It's working OK, but with more complex shapes, it doesn't work that well... Here's a link to the isolated code with an example of one shape that works and one that doesn't: http://jsfiddle.net/snqF7/ 它可以正常工作,但形状更复杂,效果不佳。这是到隔离代码的链接,其中包含一个有效的形状和一个无效的形状的示例: http : //jsfiddle.net/ snqF7 /

The algorithm you are using require the polygon to be convex. 您使用的算法要求多边形是凸的。
Convex mean, in a nutshell, that you can draw a line in between any two points in the polygon, all the line will be inside the polygon. 简而言之,凸意味着您可以在多边形的任意两个点之间绘制一条线,所有线都将在多边形内部。
- More or less a potato or a square :) -. -或多或少是马铃薯或正方形:)-。

Solution is either to split your polygons in convex parts or to go for a more complex algorithm that handles non-convex polygons. 解决方案是将多边形分成凸形部分,或者采用更复杂的算法来处理非凸多边形。

To handle non convex polygons, idea is to take a reference point you know is (or isn't) in the polygon, then draw a line between your tested point and this reference point, then count how many times and in which direction it intersect with the polygon segments. 要处理非凸多边形,想法是获取一个已知(或不在多边形中)的参考点,然后在测试点和该参考点之间画一条线,然后计算它相交的次数和方向与多边形线段。 Count +1 or -1 on each cross, and the point is inside if final sum is null. 在每个十字架上计数+1或-1,如果最终总和为空,则该点在内部。

ah! 啊! like GameAlchemist said, the issue is that this algorithm is meant for convex polygons, here's a new && improved algorithm which works with non-convex ( or complex ) polygons ( not perfect ) which I translated from these C code examples ( http://alienryderflex.com/polygon/ ) 就像GameAlchemist所说的那样,问题在于该算法适用于凸多边形,这是一种新的&&改进算法,适用于非凸(或复杂)多边形(不完美),我从这些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;

}

and here's a working fiddle: http://jsfiddle.net/snqF7/3/ 这是一个有效的小提琴: http : //jsfiddle.net/snqF7/3/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM