Your browser does not support the HTML5 canvas tag.

Drag either polygon to reposition it and watch the tracked closest features (orange / pink) update.

Controls

0.00 px 0.00 px - - 0 0 0 / 0 0.00 ms

Lin-Canny: closest features via Voronoi regions

Given two convex polygons, many algorithms (continuous collision detection, distance-based contact handling, path planning) need the pair of points on their boundaries that are closest to each other, together with the separation distance. Testing every vertex/edge of polygon A against every vertex/edge of polygon B directly is only $O(n_A \cdot n_B)$, cheap once, but far too much when this query has to run every single time step for every pair of nearby objects in a simulation. The Lin-Canny algorithm [LC91] instead maintains a single candidate pair of features (a vertex or an edge on each polygon) and updates it incrementally, needing only a handful of tests per step once it has locked on.

Voronoi regions of a convex polygon

Every point in the plane has a uniquely closest feature on a convex polygon's boundary (a vertex or an edge), and the set of points that are closest to a particular feature is called that feature's Voronoi region:

These regions partition the whole plane (outside the polygon) without gaps or overlaps. Consequently, a candidate feature $f$ is the closest feature to a point $p$ if and only if $p$ lies in $f$'s Voronoi region — a test that only needs the two edges neighboring $f$, not the whole polygon.

The algorithm

Starting from a candidate pair of features $(f_A, f_B)$ (one on each polygon), each iteration performs a simple local check:

  1. Compute the closest points $p_A \in f_A$ and $p_B \in f_B$ between the current pair of features (point–point, point–segment or segment–segment, depending on whether $f_A, f_B$ are vertices or edges).
  2. Test whether $p_B$ lies in the Voronoi region of $f_A$. If not, $f_A$ cannot be part of the closest pair yet — replace it with the neighboring feature on the side of the violated boundary and repeat from step 1.
  3. Otherwise, test whether $p_A$ lies in the Voronoi region of $f_B$. If not, replace $f_B$ with its corresponding neighbor and repeat from step 1.
  4. If both regions already contain the other feature's point, the pair $(f_A, f_B)$ is the closest pair of features, and $\|p_A - p_B\|$ is the separation distance.

Because the polygons are convex, this purely local, greedy walk is guaranteed to reach the globally closest pair — it can never get stuck in a wrong local candidate, which is precisely the property the original 1991 paper proves. Compare the "Distance (Lin-Canny)" and "Distance (brute force)" statistics: apart from rare, momentarily unconverged states in step-by-step mode, they always agree, confirming this on every frame.

Why this is fast: temporal coherence

Object shapes and positions rarely change much from one simulation step to the next. If the walk is restarted from the pair found in the previous step ("warm start"), it typically only needs zero to a few iterations to re-converge, since the true closest pair has usually not moved far either. Restarting from an arbitrary fixed feature every time ("cold start") needs far more iterations in general, up to $O(n_A + n_B)$ in the worst case. The "Iterations (warm start)" and "Iterations (cold restart)" statistics make this difference directly measurable: watch how much smaller the warm count stays as the polygons drift and rotate, compared to the cold count computed from scratch for reference on every frame.

Use "Reset walk (cold start)" to throw away the current tracked pair and see how many steps are actually spent recovering it, or switch to step-by-step mode to single-step through the walk and watch each Voronoi-region test and feature update individually.

Properties and limitations

References