MapMath

CHAPTER 16

The antimeridian — the bug that breaks every map

Why lines and polygons that cross the ±180° longitude line break naive code, the splitting algorithm that fixes it, and GeoJSON specifics.

3 min read

The antimeridian is the line at 180° / −180° longitude — the opposite side of the globe from the prime meridian. It runs through the Pacific Ocean and is where the International Date Line roughly follows.

Every developer who draws routes, polygons, or heatmaps eventually ships a bug where a line from Japan to Alaska shoots across the entire world map instead of crossing the Pacific. This chapter explains why and how to fix it.

The naive bug

Consider two points:

  • Tokyo: (35.68, 139.69)
  • Anchorage: (61.22, -149.90)

A naive renderer connects them with a straight line in longitude space: from 139.69° E to -149.90° W — a difference of 289.59° going westward across Eurasia. The correct path crosses the antimeridian going eastward: a difference of only 70.41° across the Pacific.

Δλwrong=149.90139.69=289.59°\Delta\lambda_\text{wrong} = -149.90 - 139.69 = -289.59° Δλcorrect=360289.59=70.41°\Delta\lambda_\text{correct} = 360 - 289.59 = 70.41°

The root cause: longitude wraps around at ±180°, but a simple subtraction doesn't know that. The number line treats -149.90 as "less than" 139.69 and draws the line in the wrong direction. The correct interpretation is that 210.10° E and -149.90° W are the same meridian.

Tokyo → Anchorage

±180°TokyoAnchorage

❌ Naive: draws a straight line across the whole map (289° the wrong way)

Detecting an antimeridian crossing

optional — skip if familiarrefresher

The antimeridian is at longitude 180° / −180°. These are the same meridian — the number line wraps. The International Date Line roughly follows it but deviates for political reasons. For pure geographic math, treat 180° = −180°.

A segment crosses the antimeridian when the absolute difference in longitude is greater than 180°:

function crossesAntimeridian(lon1, lon2) {
  return Math.abs(lon1 - lon2) > 180;
}

The fix: split the segment

When a crossing is detected, split the segment into two parts at ±180°:

function splitAtAntimeridian(lat1, lon1, lat2, lon2) {
  if (!crossesAntimeridian(lon1, lon2)) {
    return [[lat1, lon1, lat2, lon2]]; // no split needed
  }

  // Fraction along the segment where it crosses the antimeridian
  const adjust = lon1 > 0 ? 360 : -360;
  const lon2a  = lon2 + adjust;
  const t      = (180 - lon1) / (lon2a - lon1);   // t ∈ (0,1)
  const latX   = lat1 + t * (lat2 - lat1);          // interpolated lat at crossing

  return [
    [lat1, lon1,  latX,  lon1 > 0 ?  180 : -180],
    [latX, lon2 > 0 ? -180 : 180, lat2, lon2],
  ];
}

The adjust step "unwraps" the second longitude by adding or subtracting 360°, placing both longitudes on the same continuous number line so the interpolation t is valid.

Chapter 16 · Paid content

Continue reading "The antimeridian — the bug that breaks every map"

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.