For a simple polygon with vertices in order:
with indices mod . The signed value is positive for counter-clockwise order.
long long area2(const vector<P>& p) { // TWICE the signed area
int n = p.size();
long long s = 0;
for (int i = 0; i < n; i++)
s += cross(p[i], p[(i + 1) % n]);
return s; // > 0 means CCW
}
double area(const vector<P>& p) { return fabs((double)area2(p)) / 2.0; }Keep twice the area
is always an integer for integer coordinates. Work with it throughout, halve only when printing, and you never touch floating point.
Why it works
Sum the signed areas of the triangles for any origin . Triangles outside the polygon are traversed in the opposite direction and cancel exactly. That is why the formula is origin-independent and works for non-convex polygons.
What the sign gives you
- → counter-clockwise; → clockwise; → degenerate.
- Normalise once at input:
if (area2(p) < 0) reverse(p.begin(), p.end());
Many algorithms (point-in-polygon, hull merging, Minkowski sums) silently assume CCW.
Requirements
The polygon must be simple — no self-intersections. For a self-intersecting polygon the formula returns a signed sum with regions counted by winding number, which is occasionally what you want but usually is not.
Related quantities
| Quantity | Formula |
|---|---|
| Perimeter | |
| Centroid | |
| Pick’s theorem | for a lattice polygon |
| Boundary lattice points | |
| Interior lattice points | |
| Is it convex? | all orientations agree |
| Bounding box | min/max of the coordinates |
The centroid formula is the area-weighted one (the centre of mass of the region), not the average of the vertices. The two differ for non-uniform vertex spacing, and problems usually mean the former.
Triangle area
Also useful: Heron’s formula with the semiperimeter — but it is numerically unstable for thin triangles. Prefer the cross product.
Area of a union of shapes
| Shapes | Method |
|---|---|
| Union of rectangles | sweep line + segment tree with counts, |
| Union of circles | angular sweep on each circle’s boundary, |
| Union of general polygons | polygon clipping (Weiler-Atherton, or a Boost/Clipper library) |
| Intersection of two convex polygons | by simultaneous traversal, or half-plane intersection |
| Intersection of a convex polygon and a half-plane | Sutherland-Hodgman clipping, |
| Circle-polygon intersection area | sum the signed areas of circle-triangle pieces per edge |
Sutherland-Hodgman clipping
vector<PD> clip(const vector<PD>& poly, P a, P b) { // keep the left side of line ab
vector<PD> res;
int n = poly.size();
for (int i = 0; i < n; i++) {
PD cur = poly[i], nxt = poly[(i + 1) % n];
bool in1 = orient(a, b, cur) >= 0, in2 = orient(a, b, nxt) >= 0;
if (in1) res.push_back(cur);
if (in1 != in2) res.push_back(lineInter(a, b, cur, nxt));
}
return res;
}Twenty lines, and clipping a convex polygon by each of another’s edges gives their intersection in — enough for most problems.
See also: Pick’s Theorem · Cross Product · Point in Polygon