Is there an algorithm to separate polygons that share an edge? - algorithm

I have a list of vertices that define a polygon, a list of perimeter edges that connect those vertices and define the outline of the polygon, and a list of inner edges connecting vertices, effectively splitting the polygon. None of the edges intersect each other (they only meet at the start and end points).
I want to partition the bigger polygon into its smaller components by splitting it at the inner edges. Basically I need to know which sets of vertices are part of a polygon that has no intersecting edges.
Basically, this is the information I have:
The vertices [0, 1, 3, 5, 7, 9, 11, 13, 15] define the outside perimeter of my polygon and the blue edge (5, 13) is an inner edge splitting that perimeter into two polygons. (Disregard the horizontal purple lines, they are the result of the trapezoidalization of the polygon to find the edge (5, 13). They have no further meaning)
This is what I want to get to:
One polygon is defined by the vertices [0, 1, 3, 5, 13, 15] and the other is defined by [5, 7, 9, 11, 13].
I need a solution that works for any number of splitting inner edges.
In the end, I would like to be able to partition a polygon like the following:
The sub-polygons are not necessarily convex. That might be of importance for any algorithm depending on it. The red sub-polygon has a concave vertex (13) for example.
My idea initially was to traverse the inside of each sub-polygon in a clockwise or counter-clockwise direction, keeping track of the vertices I encounter and their order. However I am having trouble finding a starting edge/vertex and guaranteeing that the next cw or ccw point is in fact on the inside of that sub-polygon I want to extract.
I tried to google for solutions but this is a field of mathematics I am too unfamiliar with to know what to search for. An idea/algorithm of how to tackle this problem would be much appreciated!
(I don't need any actual code, just an explanation of how to do this or pseudocode would totally suffice)
Now, unfortunately I don't have some code to show as I need a concept to try out first. I don't know how to tackle this problem and thus can't code anything that could accomplish what I need it to do.
EDIT:
This is just one step in what I am trying to do ultimately, which is polygon triangulation. I have read numerous solutions to that problem and wanted to implement it via trapezoidalization to get monotone polygons and ultimately triangulate those. This is basically the last step of (or I guess the next step after) the trapezoidalization, which is never explained in any resources on the topic that i could find.
The end result of the trapezoidalization are the inner edges which define the split into (in my case vertically monotone) polygons. I just need to split the polygons along those edges "datastructurally" so I can work on the subpolygons individually. I hope that helps to clarify things.

The key of the algorithm that you need, is to know how edges can be ordered:
Finding out which is the next edge in (counter)clockwise order
You can calculate the absolute angle, of an edge from node i to node j, with the following formula:
atan2(jy-iy, jx-ix)
See atan2
The relative angle between an edge (i, j) and (j, k) is then given by:
atan2(ky-jy, kx-jx) - atan2(jy-iy, jx-ix)
This expression may yield angles outside of the [-𝜋, 𝜋] range, so you should map the result back into that range by adding or subtracting 2𝜋.
So when you have traversed an edge (i, j) and need to choose the next edge (j, k), you can then pick the edge that has the smallest relative angle.
The Algorithm
The partitioning algorithm does not really need to know upfront which edges are internal edges, so I'll assume you just have an edge list. The algorithm could look like this:
Create an adjacency list, so you have a list of neighboring vertices for every vertex.
Add every edge to this adjacency list in both directions, so actually adding two directed edges for each original edge
Pick a directed edge (i, j) from the adjacency list, and remove it from there.
Define a new polygon and add vertex i as its first vertex.
Repeat until you get back to the first vertex in the polygon that's being constructed:
add vertex j to the polygon
find vertex k among the neighbors of vertex j that is not vertex i, and which minimizes the relative angle with the above given formula.
add this angle to a sum
Delete this directed edge from the neighbors of vertex j, so it will never be visited again
let i = j, j = k
If the sum of angles is positive (it will be 2𝜋) then add the polygon to the list of "positive" polygons, otherwise (it will be -2𝜋) add it to an alternative list.
Keep repeating from step 2 until there are no more directed edges in the adjacency list.
Finally you'll have two lists of polygons. One list will only have one polygon. This will be the original, outer polygon, and can be ignored. The other list will have the partitioning.
As a demo, here is some code in a runnable JavaScript snippet. It uses one of the examples you pictured in your question (but will consecutive vertex numbering), finds the partitioning according to this algorithm, and shows the result by coloring the polygons that were identified:
function partition(nodes, edges) {
// Create an adjacency list
let adj = [];
for (let i = 0; i < nodes.length; i++) {
adj[i] = []; // initialise the list for each node as an empty one
}
for (let i = 0; i < edges.length; i++) {
let a = edges[i][0]; // Get the two nodes (a, b) that this edge connects
let b = edges[i][1];
adj[a].push(b); // Add as directed edge in both directions
adj[b].push(a);
}
// Traverse the graph to identify polygons, until none are to be found
let polygons = [[], []]; // two lists of polygons, one per "winding" (clockwise or ccw)
let more = true;
while (more) {
more = false;
for (let i = 0; i < nodes.length; i++) {
if (adj[i].length) { // we have unvisited directed edge(s) here
let start = i;
let polygon = [i]; // collect the vertices on a new polygon
let sumAngle = 0;
// Take one neighbor out of this node's neighbor list and follow a path
for (let j = adj[i].pop(), next; j !== start; i = j, j = next) {
polygon.push(j);
// Get coordinates of the current edge's end-points
let ix = nodes[i][0];
let iy = nodes[i][1];
let jx = nodes[j][0];
let jy = nodes[j][1];
let startAngle = Math.atan2(jy-iy, jx-ix);
// In the adjacency list of node j, find the next neighboring vertex in counterclockwise order
// relative to node i where we came from.
let minAngle = 10; // Larger than any normalised angle
for (let neighborIndex = 0; neighborIndex < adj[j].length; neighborIndex++) {
let k = adj[j][neighborIndex];
if (k === i) continue; // ignore the reverse of the edge we came from
let kx = nodes[k][0];
let ky = nodes[k][1];
let relAngle = Math.atan2(ky-jy, kx-jx) - startAngle; // The "magic"
// Normalise the relative angle to the range [-PI, +PI)
if (relAngle < -Math.PI) relAngle += 2*Math.PI;
if (relAngle >= Math.PI) relAngle -= 2*Math.PI;
if (relAngle < minAngle) { // this one comes earlier in counterclockwise order
minAngle = relAngle;
nextNeighborIndex = neighborIndex;
}
}
sumAngle += minAngle; // track the sum of all the angles in the polygon
next = adj[j][nextNeighborIndex];
// delete the chosen directed edge (so it cannot be visited again)
adj[j].splice(nextNeighborIndex, 1);
}
let winding = sumAngle > 0 ? 1 : 0; // sumAngle will be 2*PI or -2*PI. Clockwise or ccw.
polygons[winding].push(polygon);
more = true;
}
}
}
// return the largest list of polygons, so to exclude the whole polygon,
// which will be the only one with a winding that's different from all the others.
return polygons[0].length > polygons[1].length ? polygons[0] : polygons[1];
}
// Sample input:
let nodes = [[59,25],[26,27],[9,59],[3,99],[30,114],[77,116],[89,102],[102,136],[105,154],[146,157],[181,151],[201,125],[194,83],[155,72],[174,47],[182,24],[153,6],[117,2],[89,9],[97,45]];
let internalEdges = [[6, 13], [13, 19], [19, 6]];
// Join outer edges with inner edges to an overall list of edges:
let edges = nodes.map((a, i) => [i, (i+1)%nodes.length]).concat(internalEdges);
// Apply algorithm
let polygons = partition(nodes, edges);
// Report on results
document.querySelector("div").innerHTML =
"input polygon has these points, numbered 0..n<br>" +
JSON.stringify(nodes) + "<br>" +
"resulting polygons, by vertex numbers<br>" +
JSON.stringify(polygons)
// Graphics handling
let io = {
ctx: document.querySelector("canvas").getContext("2d"),
drawEdges(edges) {
for (let [a, b] of edges) {
this.ctx.moveTo(...a);
this.ctx.lineTo(...b);
this.ctx.stroke();
}
},
colorPolygon(polygon, color) {
this.ctx.beginPath();
this.ctx.moveTo(...polygon[0]);
for (let p of polygon.slice(1)) {
this.ctx.lineTo(...p);
}
this.ctx.closePath();
this.ctx.fillStyle = color;
this.ctx.fill();
}
};
// Display original graph
io.drawEdges(edges.map(([a,b]) => [nodes[a], nodes[b]]));
// Color the polygons that the algorithm identified
let colors = ["red", "blue", "silver", "purple", "green", "brown", "orange", "cyan"];
for (let polygon of polygons) {
io.colorPolygon(polygon.map(i => nodes[i]), colors.pop());
}
<canvas width="400" height="180"></canvas>
<div></div>

Related

Porting d3-voronoi to d3-delunay

What I want to do is replicate a data-structure produced by processing the output from d3-voronoi, but by using d3-delaunay instead.
The data-structure in question is the one produced by this makeMesh function:
function makeMesh(pts, extent) {
extent = extent || defaultExtent;
var vor = voronoi(pts, extent);
var vxs = [];
var vxids = {};
var adj = [];
var edges = [];
var tris = [];
for (var i = 0; i < vor.edges.length; i++) {
var e = vor.edges[i];
if (e == undefined) continue;
var e0 = vxids[e[0]];
var e1 = vxids[e[1]];
if (e0 == undefined) {
e0 = vxs.length;
vxids[e[0]] = e0;
vxs.push(e[0]);
}
if (e1 == undefined) {
e1 = vxs.length;
vxids[e[1]] = e1;
vxs.push(e[1]);
}
adj[e0] = adj[e0] || [];
adj[e0].push(e1);
adj[e1] = adj[e1] || [];
adj[e1].push(e0);
edges.push([e0, e1, e.left, e.right]);
tris[e0] = tris[e0] || [];
if (!tris[e0].includes(e.left)) tris[e0].push(e.left);
if (e.right && !tris[e0].includes(e.right)) tris[e0].push(e.right);
tris[e1] = tris[e1] || [];
if (!tris[e1].includes(e.left)) tris[e1].push(e.left);
if (e.right && !tris[e1].includes(e.right)) tris[e1].push(e.right);
}
var mesh = {
pts: pts,
vxs: vxs,
adj: adj,
tris: tris,
edges: edges,
extent: extent
}
mesh.map = function (f) {
var mapped = vxs.map(f);
mapped.mesh = mesh;
return mapped;
}
return mesh;
}
I've been trying to solve this for a while now and have finally made some progress here on observablehq:
https://observablehq.com/#folcon/original-code-by-martin-oleary-mewo2
I'm assessing how well it works by comparing the rendered images:
I want to produce these smooth colour transitions, which requires a correct mapping between vertices, heightmap and triangles.
Attempt 1:
Well I got something rendered, if my approach below doesn't work, it might be instructive to come back to this.
Attempt 2:
This one I feel is a lot better, I don't appear to be getting extra triangles (no black ones visible), but the issue appears to be I'm rendering in the wrong order. I was attempting to go from the leftmost point and then walk around the cell edges, this seems like the right idea, but the ordering is wrong...
I've dug into the delunator's guide to datastructures and at this point I feel like I'm pretty close, but missing something obvious.
Useful Notes / Assumptions:
The mesh uses the edges of the cells, not the triangles for "edges", if you look at the adj (adjacencies) it's never higher than 3, which is in keeping with using the cells as each vertex of the cell has no more than 3 neighbours.
Given that an edge is an edge of a cell, the left and the right of the edge should therefore be the two cells that edge sits on.
Hopefully that's clear.
To answer #thclark:
The Output Data Structure:
{
pts: pts,
vxs: vxs,
adj: adj,
tris: tris,
edges: edges,
extent: extent
}
pts is the original points array, which is a list of pairs of [x, y] coordinates.
vxs is the vertices of the cell as pairs of [x, y] coordinates. The points here are unique, and their index in the array is the authoritative id for that vertex.
I will use one of redblobgame's images to clarify:
The red dots in this image are the original points, the blue one's are the vertices of the cell.
edges is are comprised of 4 values, the first two are the indexes of the vertices that make up the edges of a cell, which in the image above are in white. The second two are the circumcenter's corresponding left and right cells which I've illustrated in an image above, but hopefully this will be clearer:
adj is a mapping from a vertex index to the other vertex index's which are connected to it, because we're using the cells, no entry in adj should have more than 3 indexes. As you can see in the image below, each vertex (red), can only have 3 neighbours (green).
tris is an array of triangles, the original data-structure does not always have complete triangles, but they indexed by the vertex index, to the circumcenter's corresponding left and right cells.
You can see in the above image, that by combining the left and right circumcenter's of three edges, it describes a triangle.
The Input Data Structure:
Delaunator's data-structures guide has a lot more detail, but a quick overview is this:
Delaunator takes an array of [x, y] coordinates of length N and makes a points array of length 2N where each coordinate in the original [x, y] array now sits at it's original index * 2 if it was the x coord, and * 2 + 1 if it was the y.
For example, the coords [[1, 2], [3, 4], [5, 6]] would become: [1, 2, 3, 4, 5, 6].
It then builds a delaunay triangulation, where each triangle edge is comprised of two halfedge's.
A halfedge takes a bi-directional edge and splits it into two directional edges.
So a triangle made up of 3 edges, now has 6 halfedges like so:
It also constructs two arrays:
delaunay.triangles which takes a halfedge index and returns the point id (an index into the points array described previously) where the halfedge begins.
delaunay.halfedges which takes a halfedge index and returns the opposite halfedge in the adjacent triangle:
Hopefully that's sufficient detail?
I've tried to make the setup runnable, so if someone wants to poke around with it to test out a quick hypothesis, they can do so easily, just edit the notebook or fork it.
I've also added at the bottom a more complete example that's purely focused on the "physical" things the map derives from the mesh+heightmap, which is basically the coastline and rivers.

Merging two overlapping rectangles into the resulting polygon

I am looking for an algorithm that, given two rectangles that overlap partially or totally, finds the ordered list of vertexes that defines the polygon representing the sum of the two rectangles.
To be more specific:
I have as input two ordered list of points, representing the two rectangles
I know how to find the vertexes of the resulting polygon, which is formed by the vertexes of each rectangle which are outside the other rectangle, plus the intersection points between each edge of one rectangle with each edge of the other
I don't currently know how to order into an array the points, obtained as explained above, so that the element j and j+1 of the array represents the two vertexes of the same edge (this is what I mean by ordered list of vertexes).
Thanks in advance for any help
UPDATE :
I found a way to sort vertexes to obtain a polygon, as follows:
compute the vertexes centroid ( coords average )
sort the vertexes by the angle formed between the segment from the centroid and the vertex and any reference line passing by the centroid (e.g. the X axis ).
However, although I consistently obtain a polygon enclosing the two rectangles, without holes or intersecting edges, it is not always the polygon I want ( sometimes it includes extra area not belonging to one of the input rectangles ).
So I'm going back to the solution pointed in one of the comments, which is also described here:
polygon union without holes
Once you have the 4 vertices, you merely find the farther point using the distance formula (since it seems we can't make the assumption of a collinear or unrotated beginning rects)
So if you have points a = (xA, yA), b, c, d and you know these 4 points make a rectangle
float dist(Point a, Point b){
float dx = a.x - b.x;
float dy = a.y - b.y;
return Math.sqrt(dx * dx + dy * dy);
}
//somewhere else, where u need it
//put point A into index 0
Point curFarthest = b;
float distance = dist(a, b);
if (dist(a, c) > distance){
curFarther = c;
distance = dist(a, c);
} else if (dist(a, d) > distance){
curFarther = d;
curFarthest = dist(a, d);
}
//store curFarthest into index 2
// store the rest (exculding points a and curFarthest)
// into index 1 and 3 in no particular order
I am working on the same problem but I use a different approach(work still in progress).
Find the intersection points.
Distance of each point(vertices) with its neighboring connected points.
Using Dinics Algorithm find the Maxmimum flow.
Note: there will be a few special cases. But then again my problems revolves around polygons having 1 common point(vertice).

How to correct winding of triangles to counter-clockwise direction of a 3D Mesh model?

First of all let me clear .. I am not asking about 2D mesh, to determine the winding order of 2D mesh its very easy with normal-z direction.
Second is, I am not asking any optimized algorithm, I do not worry about the time or speed, I just want to do it with my mesh.
When I triangulate a 3D object using Greedy Projection Triangulation algorithm, This problem happens.
check the attached images.
If I apply 2D approaches to this model using "Calculate Signed Area" or "Cross production of AB and BC vectors of a triangle", it only solves the 2D mesh but how about a 3D mesh?
First we need to check that which triangles are in wrong winding direction in 3D mesh, then we only consider those triangles, so the issue is, how can we check that which triangles are in wrong winding direction in 3D? We can not just do with 2D approach I have tested it and but no success.
For example in case of a sphere, we can not apply 2D approach to sphere.
So is there any way to solve this issue ?
Thanks.
Update # 1:
Below is the algorithm to check which edge has the same winding. It doesn't work well, I don't know why. Theoretically it should correct all the triangles but it is not correcting. For example in case of a sphere check in the attached figure. Something is wrong with it.
void GLReversedEdge(int i, int j, GLFace *temp)
{
//i'th triangle
int V1 = temp[i].v1;
int V2 = temp[i].v2;
int V3 = temp[i].v3;
//i'th triangle edges
int E1[] ={V1, V2};
int E2[] ={V2, V3};
int E3[] ={V3, V1};
//adjacent triangle
int jV1 = temp[j].v1;
int jV2 = temp[j].v2;
int jV3 = temp[j].v3;
//adjacent edges
int jE1[] ={jV1, jV2};
int jE2[] ={jV2, jV3};
int jE3[] ={jV3, jV1};
// 1st edge of adjacent triangle is checking with all edges of ith triangle
if((jE1[0] == E1[0] && jE1[1] == E1[1]) ||
(jE1[0] == E2[0] && jE1[1] == E2[1]) ||
(jE1[0] == E3[0] && jE1[1] == E3[1]))
{
temp[j].set(jV2, jV1, jV3); // 1st edges orientation is same, so reverse/swap it
}
// 2nd edge of adjacent triangle is checking with all edges of ith triangle
else if((jE2[0] == E1[0] && jE2[1] == E1[1]) ||
(jE2[0] == E2[0] && jE2[1] == E2[1]) ||
(jE2[0] == E3[0] && jE2[1] == E3[1]))
{
temp[j].set(jV1, jV3, jV2); // 2nd edges orientation is same, so reverse/swap it
}
// 3rd edge of adjacent triangle is checking with all edges of ith triangle
else if((jE3[0] == E1[0] && jE3[1] == E1[1]) ||
(jE3[0] == E2[0] && jE3[1] == E2[1]) ||
(jE3[0] == E3[0] && jE3[1] == E3[1]))
{
temp[j].set(jV3, jV2, jV1); // 3rd edges orientation is same, so reverse/swap it
}
}
void GetCorrectWindingOfMesh()
{
for(int i=0; i<nbF; i++)
{
int j1 = AdjacentTriangleToEdgeV1V2;
if(j1 >= 0) GLReversedEdge(i, j1, temp);
int j2 = AdjacentTriangleToEdgeV2V3;
if(j2 >= 0) GLReversedEdge(i, j2, temp);
int j3 = AdjacentTriangleToEdgeV3V1;
if(j3 >= 0) GLReversedEdge(i, j3, temp);
}
}
To retrieve neighboring information lets assume we have method that returns neighbor of triangle on given edge neighbor_on_egde( next_tria, edge ).
That method can be implemented with information for each vertex in which triangles it is used. That is dictionary structure that maps vertex index to list of triangle indices. It is easily created by passing through list of triangles and setting for each triangle vertex index of triangle in right dictionary element.
Traversal is done by storing which triangles to check for orientation and which triangles are already checked. While there are triangles to check, make check on it and add it's neighbors to be checked if they weren't checked. Pseudo code looks like:
to_process = set of pairs triangle and orientation edge
initial state is one good oriented triangle with any edge on it
processed = set of processed triangles; initial empty
while to_process is not empty:
next_tria, orientation_edge = to_process.pop()
add next_tria in processed
if next_tria is not opposite oriented than orientation_edge:
change next_tria (ABC) orientation (B<->C)
for each edge (AB) in next_tria:
neighbor_tria = neighbor_on_egde( next_tria, edge )
if neighbor_tria exists and neighbor_tria not in processed:
to_process add (neighbor_tria, edge opposite oriented (BA))
Does your mesh include edge adjacency information? i.e. each triangle T contains three vertices A,B,C and three edges AB, BC and CA, where AB is a link to the triangle T1 which shares common vertices A,B and includes a new vertex D. Something like
struct Vertex
{
double x,y,z;
};
struct Triangle
{
int vertices[3],edges[3];
};
struct TriangleMesh
{
Vertex Vertices[];
Triangle Triangles[];
};
If this is the case, for any triangle T = {{VA,VB,VC},{TAB,TBC,TCA}} with neighbour TE = &TAB at edge AB, A and B must appear in the reverse order for T and TE to have the same winding. e.g. TAB = {{VB,VA,VD},{TBA,TAD,TDA}} where TBA = &T. This can be used to give all the triangles the same winding.

Detect Polygons from Randomly Listed Edges

I have a vector drawing containing the edges of lots of polygons. Each edge is represented by a start point and end point. Connections between edges are not explicitly indicated. I need to extract the polygons from this data. The obvious way to do this is to take one vertex of each edge, search all other edges for a matching vertex and repeat this with the next vertex of the edge so located till I have a closed loop. But this is very inefficient.
What are some good algorithms out there to extract polygons given only start and end points of edges in no particular order?
Try something like this (python-pseudocode):
vertices = {} #map (x, y) coords to a list of all edges containing that vertex
for edge in edges:
#add start & end vertices
if edge.start not in vertices:
vertices[edge.start] = []
if edge.end not in vertices:
vertices[edge.end] = []
vertices[edge.start].append(edge)
vertices[edge.end].append(edge)
Now you have all the vertices and all the edges coming out of each vertex. You can now do the initial idea for your algorithm, but instead of having to search through all the edges for a matching vertex, that lookup is instant.
One easy way to do it would be:
Sort the list of edges by end point. Call that array edges
Create a new array, polygon, size is num_edges
edgeIndex = 0
copy edge from edges[0] to polygon[0]
count = 1
while (count < number_of_edges)
{
starting_point = edges[edgeIndex].endpoint
// do a binary search to find the segment that starts
// at this edge's end point
newIndex = binary_search(edges, starting_point)
copy edge[newIndex] to polygon[count]
++count
edgeIndex = newIndex
}
When you're done with this, the polygon array should contain the edges, in order.
The above assumes that the edge points are output rationally. That is, given a triangle with vertices '[(0, 0), (10, 10), (10, 0)]', the edges are given as:
{(0, 0), (10, 10)}
{(10, 10), (10, 0)}
{(10, 0), (0, 0)}
Although not necessarily in that order. If the second edge is given as {(10, 0), (10, 10)} (i.e. start and end are reversed), then the problem is somewhat more difficult.
You can do the same thing with a hash map and direct lookups, which will be faster than binary search.
Note also that this assumes you won't have more than two edges connected to any single point.

find all inner grid points of a polygon made up from neighbouring grid points

I have list of Points (int x, int y).
together they form areas, I check if this area is closed and then I need to get inner area formed by all positions that are inside this area.
example area:
Only idea I had is to convert this area to vector and check every point if it is inside polygon or not, counting intersections of polygon a axis's of point.
But I don't think it would be the most efficient way to do it.
other idea was to first get all points that are outside, I start from corners (if corner is not part of list of points, then is 100% empty), add all neighbor points that are empty and repeat.
then all points that aren't outside and aren't in highlighted list are inside.
but again, it feels somehow cumbersome...
To find all inner grid points of grid polygon, one can exploit these observations:
for each inner grid point (x,y) also (x,y+0.5) and (x,y-0.5) are inner points.
the lines defined by y=n+0.5 have simple intersections with the grid polygon
This leads to the following algorithm:
As a prerequisite one needs all non-horizontal (i.e. vertical and diagonal) polygon edges, actually only the x-coords of the centers in ascending order for each (second) mid-row.
The grid is scanned at each second horizontal "mid-line", i.e. y=2n+0.5, where n is from a sufficient range of integers s.t. the polygon is "covered", see the blue lines in the scetch.
Starting from the left all intersections with the polygon (i.e. the non-horizontal edges) and all inner points of the form (m,2n+0.5) are to be detected, see the red and green circles (this is done by iterating over the x-coors of the edges' centers)
Now the vertical grid neighbours (m,2n) and (m,2n+1) of inner points (m,2n+0.5) are inner points, if they are not on the boundary, see the green points in the scetch.
Here is some pseudo code (C++/python inspired :-) ):
list<Point> polygon; // given polygon as list of neighbouring grid points
// get centers of non-horizontal edges organized by line
map<int, set<float> > edgeCentersX; // for each scan line the x-coords of edges in ascending order
p_i = polygon[0]
yMin, yMax = 999999, -999999
for (i=1; i<polygon.size(); ++i)
p_i1 = polygon[i] // next point after p_i
if (p_i.x == p_i1.x)
continue // horizontal edges can be ignored
yMin_i = min(p_i.y, p_i1.y)
if (yMin_i % 2 == 1)
continue // we only need to look at each second mid-row
if (yMin_i < yMin)
yMin = yMin_i
if (yMin_i > yMax)
yMax = yMin_i
cx = 0.5*(p_i.x+p_i1.x)
edgeCentersX[yMin_i].insert(cx) // store edge center (yMin_i+0.5, cx)
p_i = p_i1
list<Point> innerPoints
for (y=yMin; y<= yMax; y+=2)
inside = false
cx_i = edgeCentersX[y][0]
for (i=1; i<edgeCentersX[y].size(); ++i)
cx_i1 = edgeCentersX[y][i]
inside = !inside
if (!inside)
continue
for (x=floor(cx_i)+1; x<cx_i1; ++x)
pLower = Point(y,x)
if (!polygon.contains(pLower))
innerPoints.append(pLower)
pUpper = Point(y+1,x)
if (!polygon.contains(pUpper))
innerPoints.append(pUpper)
Pick's theorem might be the formula you are looking for. It allows rather simple computation of the area for a polygon whose corners are grid points (i.e. have integer coordinates).

Resources