Geometric Primitives
Points, Lines, Segments, and Polygons
Point: . Represented as a pair of coordinates (integer or floating-point).
Line: defined by equation , or parametrically as for direction and . Two points determine a unique line.
Line segment: the portion of a line between two endpoints : .
Ray: .
Polygon: ordered sequence of vertices defining a closed region via edges .
- Simple polygon: edges intersect only at shared vertices (Jordan curve theorem applies: divides plane into interior and exterior)
- Convex polygon: all interior angles ; equivalently, any line segment between two interior points lies entirely inside
- Monotone polygon: any vertical line intersects the boundary at most twice
Orientation Test (Cross Product)
The cross product of vectors and :
This equals the signed area of the parallelogram spanned by and .
Orientation of three points : compute the cross product :
- : counterclockwise (left turn)
- : collinear
- : clockwise (right turn)
This is the fundamental predicate of computational geometry. Nearly every algorithm reduces to orientation tests. Equivalent to computing the sign of a determinant:
Segment Intersection
Two segments and intersect iff:
- General position: and have different signs, AND and have different signs
- Collinear case: if any orientation is zero, check if the point lies on the segment (bounding box test)
For the intersection point (if it exists), solve the parametric system:
This yields parameters via Cramer's rule in time.
Proper intersection: segments cross transversally (not at endpoints). Improper: endpoint touches the other segment or segments overlap.
Area Computation (Shoelace Formula)
For a simple polygon with vertices in order:
where indices are taken modulo . The signed version (without absolute value) is positive for counterclockwise vertex ordering.
Derivation: sum of signed areas of triangles formed with the origin. Each edge contributes a trapezoid. The formula is exact for integer/rational coordinates.
Centroid of a simple polygon:
and analogously for .
Point-in-Polygon
Ray Casting
Cast a horizontal ray from the query point to . Count the number of edge crossings:
- Odd crossings: inside
- Even crossings: outside
Edge cases: ray passes through a vertex or is collinear with an edge. Handle by treating the ray as passing slightly above: count an edge crossing only if one endpoint is strictly above and the other is at or below the ray's -coordinate.
Complexity: per query for an -vertex polygon. Can be preprocessed for queries via trapezoidal decomposition.
Winding Number
The winding number counts how many times the polygon boundary winds around the query point:
- : outside
- : inside (for simple polygons, )
Efficient computation: avoid trigonometry by tracking sign changes in the -coordinate relative to the query point and using orientation tests. Same complexity as ray casting.
Advantage over ray casting: correctly handles self-intersecting polygons (where "inside" is ambiguous for ray casting but well-defined by winding number convention).
Convexity Testing
A polygon is convex iff all cross products of consecutive edge vectors have the same sign:
time.
Point-in-convex-polygon: by binary search on the angle from a fixed interior point (e.g., the first vertex), then a single orientation test.
Distance Computations
Point to line (line through ):
Point to segment : project onto the line; if the projection parameter is in , use the point-to-line distance. Otherwise, use the distance to the nearer endpoint.
Segment to segment: check if projections overlap; otherwise, minimum of four point-to-segment distances. Important for collision detection.
Polygon Triangulation
Every simple polygon can be triangulated into triangles (for vertices).
Ear-clipping: an "ear" is a triangle formed by three consecutive vertices whose diagonal lies inside the polygon. Every simple polygon with vertices has at least two ears (two-ears theorem). Repeatedly clip ears: naive ; optimized via careful bookkeeping (though the algorithm by Chazelle is complex).
Monotone polygon triangulation: after monotone decomposition (sweep-line). This is the standard practical approach.
Fan triangulation for convex polygons: , all triangles share a common vertex.
Convex Polygon Operations
Intersection of two convex polygons: via rotating calipers or simultaneous traversal (O'Rourke's algorithm).
Minkowski sum of two convex polygons: by merging sorted edge vectors.
Tangent lines, supporting lines: via binary search on the polygon.
Exact Arithmetic and Robustness
The Robustness Problem
Floating-point orientation tests can give incorrect signs due to rounding, leading to:
- Topological inconsistencies (a point reported inside and outside)
- Infinite loops in sweep-line algorithms
- Invalid geometric constructions (self-intersecting "convex" hulls)
A classic failure: three nearly collinear points with coordinates like where is below machine precision.
Shewchuk's Exact Predicates
Jonathan Shewchuk's adaptive precision arithmetic (1997) provides exact geometric predicates using only floating-point hardware:
Key idea: represent intermediate results as non-overlapping expansions (sums of floating-point numbers with decreasing magnitude). The orientation predicate becomes:
- Compute with standard double precision (fast filter)
- If the result is clearly positive/negative, return immediately
- If near zero, progressively refine using error-free transformations (Dekker/Knuth two-product, two-sum)
- Final exact result uses machine words for 2D orientation
Performance: the fast filter succeeds for >99% of non-degenerate cases, costing only ~2x standard floating-point. Exact path is 10-50x slower but rarely needed.
Predicates provided: orient2d, orient3d, incircle, insphere. These suffice for Delaunay triangulation, convex hull, and most fundamental algorithms.
Alternative Approaches
- Exact integer arithmetic: use integer coordinates and multiprecision integers for determinants. GMP library. Exact but slow
- Interval arithmetic: compute with intervals; if the interval contains zero, refine. CGAL uses this approach
- Simulation of simplicity (SoS): symbolic perturbation to eliminate degeneracies. Edelsbrunner and Mucke (1990). Perturb input by infinitesimal amounts and evaluate the sign using lexicographic rules
- Controlled perturbation: actually perturb coordinates by small random amounts, then verify geometric consistency
CGAL's Exact Computation Paradigm
The Exact Geometric Computation (EGC) paradigm: all geometric decisions (predicates) are computed exactly; only numerical constructions (coordinates of intersection points) may be approximate. Since algorithms branch only on predicates, EGC guarantees topological correctness.
CGAL implements this via:
- Lazy exact arithmetic: compute with doubles, fall back to exact (MPFR/GMP) only when needed
- Algebraic number types for constructions involving square roots (circular arcs)
- Separation bounds to determine when floating-point precision suffices
Degeneracies
Common degeneracies: three collinear points, four cocircular points, coincident points, vertical segments in sweep-line algorithms.
Handling strategies:
- General position assumption: state and prove algorithms assuming non-degeneracy, then handle special cases
- Symbolic perturbation (SoS): automatically resolves all degeneracies consistently
- Explicit case analysis: handle each degenerate case in the code (error-prone but sometimes necessary)
Correct handling of degeneracies is often where the majority of implementation complexity lies. It is the primary reason computational geometry libraries (CGAL, S2 Geometry) are strongly preferred over hand-rolled implementations for production use.