17.16 Integer Geometry
Many computational geometry problems use coordinates that are naturally integers: ```text grid maps pixels
17.16 Integer Geometry
Problem
Many computational geometry problems use coordinates that are naturally integers:
grid maps
pixels
game worlds
GIS tiles
CAD layouts
competitive programming datasets
In these settings, floating-point arithmetic often introduces unnecessary complexity.
A segment intersection test that should be exact may fail because of rounding. A convex hull algorithm may classify collinear points incorrectly. A polygon area computation may lose precision even though every input coordinate is an integer.
Integer geometry avoids many of these issues by performing calculations exactly.
Solution
Whenever the problem permits, perform geometric predicates using integer arithmetic.
The most important geometric operations:
orientation
area
distance comparison
segment intersection
point-on-segment tests
can all be implemented without floating-point arithmetic.
The central idea is simple:
compare values directly
avoid division
avoid square roots
avoid trigonometric functions
As long as intermediate calculations do not overflow, the results are exact.
Exact Orientation
The orientation predicate is naturally integer-valued.
Given:
A = (x1, y1)
B = (x2, y2)
C = (x3, y3)
compute:
def orientation(a, b, c):
return (
(b.x - a.x) * (c.y - a.y)
-
(b.y - a.y) * (c.x - a.x)
)
The result is:
positive -> left turn
negative -> right turn
zero -> collinear
No epsilon is needed.
No rounding occurs.
This exactness is one reason many geometry libraries prefer integer coordinates when possible.
Exact Polygon Area
Recall the shoelace formula:
def area2(points):
result = 0
n = len(points)
for i in range(n):
j = (i + 1) % n
result += (
points[i].x * points[j].y
-
points[j].x * points[i].y
)
return result
The returned value equals:
2 × signed area
If all coordinates are integers:
area2
is also an integer.
The actual area may be:
integer
or:
integer + 1/2
For example:
triangle:
(0,0)
(3,0)
(0,1)
Produces:
area2 = 3
Actual area:
3/2
Many algorithms never need to divide by two.
Keeping the doubled area preserves exact arithmetic.
Comparing Distances
Suppose two distances must be compared.
Avoid:
sqrt(dx * dx + dy * dy)
Instead compare:
dx * dx + dy * dy
directly.
Implementation:
def distance_squared(a, b):
dx = a.x - b.x
dy = a.y - b.y
return dx * dx + dy * dy
Then:
if distance_squared(a, b) < distance_squared(c, d):
...
This is exact for integer coordinates.
No square roots are required.
Segment Intersection
Integer geometry works particularly well for segment intersection.
The algorithm from Section 17.3 uses:
orientation
bounding-box checks
both of which can be computed exactly.
def segments_intersect(a, b, c, d):
...
No floating-point arithmetic is necessary.
As a result:
touching endpoints
collinear overlaps
shared vertices
can be handled reliably.
Rational Coordinates
Some constructions produce non-integer coordinates.
Example:
line intersections
polygon clipping
Voronoi vertices
Instead of immediately converting to floating point, store coordinates as rational numbers.
Python example:
from fractions import Fraction
x = Fraction(1, 3)
y = Fraction(7, 5)
Arithmetic remains exact:
Fraction(1, 3) + Fraction(1, 6)
produces:
1/2
exactly.
This approach is slower than integer arithmetic but avoids rounding errors.
Pick's Theorem
Integer geometry provides remarkable results that do not exist in general floating-point geometry.
One example is Pick's Theorem.
For a simple polygon whose vertices lie on integer lattice points:
Area
=
I + B/2 - 1
where:
I = interior lattice points
B = boundary lattice points
Example:
rectangle:
(0,0)
(4,0)
(4,3)
(0,3)
Interior lattice points:
6
Boundary lattice points:
14
Therefore:
6 + 14/2 - 1
=
12
which matches:
4 × 3
=
12
Pick's Theorem appears in combinatorial geometry and programming contests.
Counting Boundary Lattice Points
For an edge:
(x1, y1)
(x2, y2)
the number of lattice points on the edge is:
gcd(
|x2 - x1|,
|y2 - y1|
)
Implementation:
from math import gcd
def boundary_points(a, b):
return gcd(
abs(a.x - b.x),
abs(a.y - b.y)
)
Summing over all polygon edges yields the boundary count needed by Pick's Theorem.
Coordinate Compression
Integer geometry often appears with large coordinates.
Example:
1,000,000,000
5,000,000,000
9,000,000,000
Only the ordering matters.
Coordinate compression replaces them with:
0
1
2
while preserving relative order.
def compress(values):
values = sorted(set(values))
return {
value: index
for index, value in enumerate(values)
}
Compressed coordinates are widely used in:
segment trees
Fenwick trees
sweep-line algorithms
rectangle union
range queries
Overflow Concerns
Integer arithmetic is exact only if values fit the numeric type.
Suppose:
coordinates ≈ 10^9
Then:
x × y ≈ 10^18
A 32-bit integer cannot store this value.
A signed 64-bit integer can:
2^63 - 1
≈ 9.22 × 10^18
But even 64-bit integers can overflow for larger coordinates.
Language behavior differs:
| Language | Integer Behavior |
|---|---|
| Python | Arbitrary precision |
| Java | Fixed-width |
| Go | Fixed-width |
| C++ | Fixed-width |
| Rust | Fixed-width |
Always estimate the largest possible intermediate value.
Exact Convex Hulls
Convex hull algorithms become particularly clean with integer coordinates.
The monotonic chain algorithm uses:
orientation
sorting
only.
Both operations are exact.
while orientation(
hull[-2],
hull[-1],
point
) <= 0:
hull.pop()
No epsilon tuning is required.
This makes integer convex hull implementations extremely reliable.
Integer Line Representation
A line:
Ax + By + C = 0
can be represented exactly using integer coefficients.
Given points:
(x1,y1)
(x2,y2)
construct:
A = y2 - y1
B = x1 - x2
C = -(Ax1 + By1)
Normalize:
divide by gcd(A,B,C)
This representation is useful for:
line comparison
parallelism
incidence tests
without floating-point arithmetic.
Common Pitfalls
Assuming Integer Means Safe
Overflow can still occur.
Converting to Float Too Early
Keep values exact as long as possible.
Using Square Roots for Comparisons
Squared distances are sufficient.
Ignoring Rational Results
Line intersections often produce fractions even when inputs are integers.
Mixing Coordinate Systems
Compressed coordinates should not be used directly for geometric measurements.
They preserve order, not distance.
Complexity Analysis
Integer arithmetic usually has the same asymptotic complexity as floating-point arithmetic:
orientation O(1)
area O(n)
convex hull O(n log n)
segment test O(1)
The primary difference is reliability, not asymptotic performance.
Arbitrary-precision arithmetic may increase constant factors, but the algorithmic structure remains unchanged.
Discussion
Integer geometry occupies an important niche in computational geometry because it provides exact predicates with relatively little effort. Many classical geometric algorithms become simpler when coordinates are integral. Orientation tests become exact. Polygon areas become exact up to a factor of two. Distance comparisons avoid square roots. Segment intersections avoid epsilon thresholds.
For grid-based and discrete geometric problems, integer arithmetic should usually be the default choice. Floating-point arithmetic is most valuable when the problem itself contains inherently non-integral quantities. Even then, preserving exact predicates whenever possible often leads to more robust and maintainable geometric software.