MapMath

CHAPTER 20

Geometry simplification

Douglas-Peucker and Visvalingam-Whyatt — how to strip vertices from polygons and lines without losing their shape.

3 min read

A 100,000-vertex coastline rendered at zoom 3 looks identical to a 200-vertex approximation — but takes 500× more memory and GPU time. Simplification is the art of removing redundant points while preserving visible shape. It's a prerequisite for building map pipelines that stay fast at all zoom levels.

Ramer-Douglas-Peucker simplification

32 pts29 pts

Ramer-Douglas-Peucker (RDP)

The most widely used algorithm. Pick the farthest point from the segment connecting the first and last point. If it's within epsilon, discard all intermediate points. Otherwise, recurse on both sides.

The key parameter is epsilon: the maximum perpendicular distance a discarded point can be from the simplified line. Points closer than epsilon to the simplified segment are invisible at the target resolution, so removing them has no visual effect.

function rdp(points, epsilon) {
  if (points.length <= 2) return points;

  // Find the point farthest from the line connecting endpoints
  const [start, end] = [points[0], points.at(-1)];
  let maxDist = 0, maxIdx = 0;

  for (let i = 1; i < points.length - 1; i++) {
    const d = perpendicularDistance(points[i], start, end);
    if (d > maxDist) { maxDist = d; maxIdx = i; }
  }

  if (maxDist <= epsilon) return [start, end]; // discard all middle points

  // Recurse on both halves
  return [
    ...rdp(points.slice(0, maxIdx + 1), epsilon).slice(0, -1),
    ...rdp(points.slice(maxIdx), epsilon),
  ];
}

function perpendicularDistance([px, py], [x1, y1], [x2, y2]) {
  const dx = x2 - x1, dy = y2 - y1;
  const len = Math.sqrt(dx * dx + dy * dy);
  if (len === 0) return Math.hypot(px - x1, py - y1);
  return Math.abs(dy * px - dx * py + x2 * y1 - y2 * x1) / len;
}

Choosing epsilon

The right epsilon depends on your target zoom level. A common heuristic: set epsilon to ~1 pixel in world coordinates at the zoom level you're simplifying for. At zoom 10, 1 pixel ≈ 152 metres; at zoom 14, ≈ 9.5 metres. Simplifying for lower zooms allows more aggressive removal.

Visvalingam-Whyatt

optional — skip if familiarrefresher

Both RDP and Visvalingam are greedy algorithms — they make locally optimal decisions without reconsidering earlier choices. Neither guarantees a globally optimal simplification, but both are fast and produce good results in practice.

Instead of perpendicular distance, removes the point that produces the smallest triangle area with its two neighbours. This better preserves the visual importance of points in complex shapes.

function visvalingam(points, targetCount) {
  // Build a min-heap of triangle areas
  // Remove the min-area point, update neighbours, repeat
  // Until targetCount points remain
}

Visvalingam preserves prominent features (peaks, sharp corners) longer than RDP — it's the algorithm Mapbox uses internally.

Chapter 20 · Paid content

Continue reading "Geometry simplification"

You've reached the end of the free preview. Unlock all 22 paid chapters, including distance math, bearings, polygons, spatial indexing, and 3D map rendering — plus a downloadable PDF and the companion code repo.

  • All 22 paid chapters with worked examples
  • Downloadable PDF for offline reading
  • Companion GitHub repo (JavaScript + Python)
  • Free updates for life

Multiple payment options including Wise, PayPal, and bank transfer.