迭代多边形中的每个点

时间:2012-11-15 00:42:13

标签: javascript canvas polygon

假设我在网格环境中有一些多边形的顶点,我如何遍历它包含的每个单元格(包括边缘上的那些单元格)?

为了澄清,我有以下顶点(计算为topleft为(0, 0)):

//each point is [x, y]
var verts = [
    [1, 1],
    [3, 1],
    [3, 2],
    [4, 2],
    [4, 4],
    [0, 4],
    [0, 3],
    [1, 3]
];

这将定义一个多边形,例如:

grid

其中每个绿点是我想要迭代的点,基于上面的顶点。顶点沿多边形边缘移动的方向没有图案,它可以围绕多边形顺时针或逆时针移动。但是,它们将是有序的;也就是说,如果你按下笔并按顺序移动到每个顶点,而不抬起,它将绘制轮廓而不会在多边形内部交叉。

用例是我通过canvas API加载了PNG中的imageData。这个PNG被分成“区域”,我需要迭代当前“区域”的每个像素。每个“区域”由上面的顶点数组定义。

我尝试了类似下面的内容,它将创建一个正方形来迭代数组中每组4个顶点。

for(var v = 0, vl = verts.length - 4; v < vl; ++v) {
    //grabbing the minimum X, Y and maximum X, Y to define a square to iterate in
    var minX = Math.min(verts[v][0], verts[v + 1][0], verts[v + 2][0], verts[v + 3][0]),
        minY = Math.min(verts[v][1], verts[v + 1][1], verts[v + 2][1], verts[v + 3][1]),
        maxX = Math.max(verts[v][0], verts[v + 1][0], verts[v + 2][0], verts[v + 3][0]),
        maxY = Math.min(verts[v][1], verts[v + 1][1], verts[v + 2][1], verts[v + 3][1]);

    for(var x = minX; x < maxX; ++x) {
        for(var y = minY; y < maxY; ++y) {
            //do my checks on this pixel located at X, Y in the PNG
        }
    }
}

虽然有两大问题:

  1. 它可以在多边形内重复点,
  2. 它可以抓取多边形外的点
  3. 我可以通过跟踪我检查的点来解决第一个问题,所以我不重复检查。第二个只能通过对每个点进行PointInPoly检查来解决,这会使这个解决方案比我想要的要重得多。

    修改
    迭代整个图像中的每个像素并对每个像素应用PointInPoly检查也是不可接受的;它会比上面的算法慢。

1 个答案:

答案 0 :(得分:1)

如果您的多边形是凸的,则可以执行以下操作:

  • 为多边形的每个边创建一条线,表示一侧内侧和一侧外侧(这是基于法线,可以取决于卷绕方向)
  • 对于您已计算的边界框内的每个像素,请检查该像素是否位于该行的内侧。如果像素位于任何线的外侧,则它位于多边形外部。如果它在所有这些内部,那么它就在里面。

基本算法来自:https://github.com/thegrandpoobah/voronoi/blob/master/stippler/stippler.cpp#L187

如果您的多边形不是凸面,那么我要做的是实际在画布上以已知颜色绘制多边形,然后应用iterative flood fill algorithm。这要求您至少知道一个内部像素,但这不应该是一个昂贵的测试。但是如果您不能在屏幕外缓冲区(不熟悉canvas标记)中执行此操作,则可能不适用于JavaScript。