SwadhyAI Notes

All DSA notes

DSA Geometry

Computational Geometry

The drone must decide if obstacle C is left or right of segment AB before the next control tick. Floating atan2 is slow and brittle. Use an test from a .

Geometry algorithms are predicates plus careful . Hulls, intersections, and collision tests all bottom out here.

Algorithm journey

1

Orientation predicate

Sign of 2D cross product.

2

Handle collinear cases

On-segment tests, ties.

3

Compose algorithms

Hull, intersect, SAT, …

4

Choose robustness policy

Epsilon vs exact predicates.

What actually happens

Naive idea: compare angles or use floats with a universal 1e-9 epsilon. Breaks near the origin vs far away, and on nearly collinear points.

Better idea: decide turns with integer-friendly cross products when coordinates allow, and treat collinearity as a first-class case.

The improved design still fails without a robustness policy: topology bugs appear as missing edges, infinite loops in hulls, or false collision clears.

Invariant

Geometric algorithms must keep predicate outcomes consistent with the chosen arithmetic model. Mixing exact topology decisions with ad hoc float epsilons is how “impossible” diagrams appear.

How to choose geometry tools

1. Turn / side tests? Orientation via cross product.

2. Convex collision? Separating axis theorem.

3. Exact topology? Exact/adaptive predicates; do not hope.

Quantitative check

Graham scan / monotone chain hull is O(n log n) from sorting. Each orientation is O(1) arithmetic; the hidden cost is predicate failure rate under float noise, not the big-O line.

The foundation: orientation and cross products

In geometry, we don't use atan2 or angles (they are too slow and prone to precision errors). Instead, we use Orientation Tests based on Cross Products.

CP > 0Counter-Clockwise
CP < 0Clockwise
CP = 0Collinear

Interactive orientation predicate

Robust-predicate lab

Orientation decides the turn

ABC

cross(B−A, C−A)

26500

Sign: counter-clockwise.

For integer coordinates, compute products in a wide type. With floating inputs, epsilon is scale-dependent; robust predicates may need adaptive exact arithmetic.

Orientation and closed-segment intersection

General intersections require opposite-orientation tests; collinear cases additionally require inclusive bounding-box checks. These examples use exact integer arithmetic.

Python

python
from dataclasses import dataclass

@dataclass(frozen=True, order=True)
class Point:
    x: int
    y: int

def cross(a, b, c):
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)

def on_segment(a, b, p):
    return (cross(a, b, p) == 0 and
            min(a.x, b.x) <= p.x <= max(a.x, b.x) and
            min(a.y, b.y) <= p.y <= max(a.y, b.y))

def intersects(a, b, c, d):
    o1, o2 = cross(a, b, c), cross(a, b, d)
    o3, o4 = cross(c, d, a), cross(c, d, b)
    if ((o1 > 0 > o2 or o2 > 0 > o1) and
            (o3 > 0 > o4 or o4 > 0 > o3)):
        return True
    return ((o1 == 0 and on_segment(a, b, c)) or
            (o2 == 0 and on_segment(a, b, d)) or
            (o3 == 0 and on_segment(c, d, a)) or
            (o4 == 0 and on_segment(c, d, b)))

assert intersects(Point(0, 0), Point(4, 4), Point(0, 4), Point(4, 0))

Java

java
import java.math.BigInteger;

public final class SegmentIntersection {
    record Point(int x, int y) {}

    static BigInteger cross(Point a, Point b, Point c) {
        long abx = (long) b.x() - a.x(), aby = (long) b.y() - a.y();
        long acx = (long) c.x() - a.x(), acy = (long) c.y() - a.y();
        return BigInteger.valueOf(abx).multiply(BigInteger.valueOf(acy))
                .subtract(BigInteger.valueOf(aby).multiply(BigInteger.valueOf(acx)));
    }

    static boolean onSegment(Point a, Point b, Point p) {
        return cross(a, b, p).signum() == 0
                && Math.min(a.x(), b.x()) <= p.x() && p.x() <= Math.max(a.x(), b.x())
                && Math.min(a.y(), b.y()) <= p.y() && p.y() <= Math.max(a.y(), b.y());
    }

    static boolean intersects(Point a, Point b, Point c, Point d) {
        int o1 = cross(a, b, c).signum(), o2 = cross(a, b, d).signum();
        int o3 = cross(c, d, a).signum(), o4 = cross(c, d, b).signum();
        if (((o1 > 0 && o2 < 0) || (o1 < 0 && o2 > 0))
                && ((o3 > 0 && o4 < 0) || (o3 < 0 && o4 > 0))) return true;
        return (o1 == 0 && onSegment(a, b, c)) || (o2 == 0 && onSegment(a, b, d))
                || (o3 == 0 && onSegment(c, d, a)) || (o4 == 0 && onSegment(c, d, b));
    }

    public static void main(String[] args) {
        Point a = new Point(0, 0), b = new Point(4, 4);
        Point c = new Point(0, 4), d = new Point(4, 0);
        if (!intersects(a, b, c, d)) throw new AssertionError();
        if (cross(a, b, new Point(2, 2)).signum() != 0) throw new AssertionError();
        Point min = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE);
        Point max = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
        if (cross(min, max, new Point(Integer.MIN_VALUE, Integer.MAX_VALUE)).signum() <= 0) {
            throw new AssertionError("full-range coordinates must not overflow");
        }
    }
}

🛡️ Convex Hull: The Minimal Perimeter

Graham Scan (O(N log N))

The industry standard. It sorts points by angle and uses a stack to build the hull. It efficiently "pops" points that create a concave turn.

Analogy: Stretching a rubber band over a set of nails.

Monotone-chain hull invariant

Sort + deduplicate

Lexicographic (x,y) order gives deterministic endpoints; duplicates must not create zero edges.

Build lower/upper

While the last two hull points plus candidate make a forbidden turn, pop the middle point.

Collinear policy

Use ≤ 0 to discard boundary-interior collinear points, or < 0 to retain them; state the contract.

Sorting costs O(n log n); each point is pushed/popped at most once per chain, so the scan is O(n). Decide whether the result repeats the first point and what happens for 0, 1, 2, or all-collinear unique points.

Robustness is part of correctness

Integer coordinates

Differences and products can overflow before assignment. Cast operands before subtraction/multiplication; 32-bit coordinates may still exceed signed 64-bit cross products at full range, requiring bounded contracts or big integers.

Floating coordinates

A universal 1e-9 epsilon is not robust across scales. Use scale-aware tolerances for approximate product semantics, or adaptive/exact predicates when topology must be correct.

  • • Test shared endpoints, touching, overlapping collinear segments, vertical/horizontal segments, zero-length segments, duplicates, and huge coordinates.
  • • Separate broad-phase spatial indexing from exact narrow-phase predicates.
  • • Avoid angle sorting with atan2 when orientation/quadrant comparators can remain exact.
  • • Property-test orientation antisymmetry and hull containment against a trusted library/oracle.

📦 Spatial Partitioning: Managing Scale

How do you find which of 1-million players is "closest" to an explosion without checking every player? (The Last-Mile problem in Game Engines).

K-D Trees

Higher Dimensional Search

Recursively splits space into half-spaces using axis-aligned hyperplanes. Excellent for Nearest Neighbor Search in ML and Robotics.

  • Used in LiDAR processing.
  • Efficient for range queries.

Quadtrees / Octrees

Recursive Grids

Splits a 2D space into 4 quadrants (8 for Octrees in 3D). If a quadrant has too many objects, it splits again.

  • Used in Collision Detection (Unity/Unreal).
  • Optimal for sparse distributions.

🎮 Application: Collision Detection

The Separating Axis Theorem (SAT)

A fundamental tool for detecting if two convex polygons are overlapping.Theorem: Two convex objects do NOT overlap if there exists an axis on which their projections do not overlap.

GPU AcceleratedVector Math

💡 Architectural Insight

In computational geometry, numerical robustness is part of the specification. For approximate measurements, choose an absolute/relative tolerance derived from coordinate scale and error budget, not a universal epsilon. When orientation or topology must be exact, use bounded integer arithmetic, wider/big integers, or adaptive exact predicates and handle degeneracies explicitly.

Short takeaway

Computational geometry starts from orientation predicates (2D cross products) and a robustness policy. Build hulls, intersections, and collision tests on consistent predicates.

Exercises

  1. Points A=(0,0), B=(10,0), C=(5,1e-12). What goes wrong with a fixed epsilon orientation test at different scales?
  2. Why prefer cross-product orientation over comparing atan2 angles for turn tests?
  3. State the Separating Axis Theorem in one sentence for convex polygons.

Primary sources

  • de Berg et al., Computational Geometry: Algorithms and Applications.
  • Preparata & Shamos: Computational Geometry.
  • Shewchuk: Adaptive Precision Floating-Point Arithmetic and Fast Robust Geometric Predicates.