Assuming I have the vertices of some polygon in a grid environment, how can I iterate through each cell it contains (including those on the edge)?
To clarify, I have the following vertices (counted as if the topleft is (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]
];
Which would define a polygon such as this:
Where each green dot is a point I would like to iterate, based on the vertices above. There is no pattern to the direction the vertices will walk along the edge of the polygon, it could go clockwise or counter-clockwise around the polygon. However, they will be in order; that is, if you put down your pen and move to each vertex in order, without lifting up, and it would draw the outline without crossing inside the polygon.
The use case being I have the imageData
from a PNG loaded via the canvas API. This PNG is split into "zones", and I need to iterate each pixel of the current "zone". Each "zone" is defined by a vertex array like above.
I tried something like the following, which will create a square to iterate through for each set of 4 vertices in the array.
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
}
}
}
Two big problems with that though:
- It can repeat points within the polygon, and
- It can grab points outside the polygon
I can solve the first issue by tracking which points I check, so I don't repeat a check. The second can only be solved by running a PointInPoly
check on each point, which would make this solution much heavier than I want it to be.
EDIT
Iterating each pixel in the entire image and applying a PointInPoly
check to each is also unacceptable; it would be even slower than the above algorithm.