假设我在网格环境中有一些多边形的顶点,我如何遍历它包含的每个单元格(包括边缘上的那些单元格)?
为了澄清,我有以下顶点(计算为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]
];
这将定义一个多边形,例如:
其中每个绿点是我想要迭代的点,基于上面的顶点。顶点沿多边形边缘移动的方向没有图案,它可以围绕多边形顺时针或逆时针移动。但是,它们将是有序的;也就是说,如果你按下笔并按顺序移动到每个顶点,而不抬起,它将绘制轮廓而不会在多边形内部交叉。
用例是我通过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
}
}
}
虽然有两大问题:
我可以通过跟踪我检查的点来解决第一个问题,所以我不重复检查。第二个只能通过对每个点进行PointInPoly
检查来解决,这会使这个解决方案比我想要的要重得多。
修改
迭代整个图像中的每个像素并对每个像素应用PointInPoly
检查也是不可接受的;它会比上面的算法慢。
答案 0 :(得分:1)
如果您的多边形是凸的,则可以执行以下操作:
基本算法来自:https://github.com/thegrandpoobah/voronoi/blob/master/stippler/stippler.cpp#L187
如果您的多边形不是凸面,那么我要做的是实际在画布上以已知颜色绘制多边形,然后应用iterative flood fill algorithm。这要求您至少知道一个内部像素,但这不应该是一个昂贵的测试。但是如果您不能在屏幕外缓冲区(不熟悉canvas标记)中执行此操作,则可能不适用于JavaScript。