Generating Anti-Meridian and Polar Test Fixtures
Two edge cases break more spatial pipelines than any others: geometry that crosses the ±180° anti-meridian, and features near the poles where Web Mercator is undefined. This guide sits beneath edge case spatial data creation and shows how to generate both as reproducible fixtures, and how to write the assertions that prove a pipeline handles them rather than silently mangling them. These belong in every suite’s fast tier because they are cheap to check and catastrophic to miss — an anti-meridian bug inverts a bounding box and an unhandled polar feature produces infinite coordinates, and both pass naïve validity checks.
Why these two cases break pipelines
The anti-meridian is where longitude wraps from +180° to −180°. A geometry spanning it — a shipping route across the Pacific, a country like Fiji — has vertices with opposite-sign longitudes, so a naïve bounding box spans nearly the whole globe and a naïve centroid lands on the wrong side of the planet. The poles break the other way: Web Mercator (EPSG:3857) is mathematically undefined at ±90° and distorts severely above ~85°, so projecting a polar feature to it yields coordinates that grow without bound. Neither defect is a geometry validity failure — the rings are fine — so only a fixture that deliberately exercises the case will surface the bug.
Edge-case fixture reference
| Case | Fixture to keep | Assertion that proves handling |
|---|---|---|
| Anti-meridian polygon | Polygon spanning ±180° | Split geometry has two parts, bbox not global |
| Anti-meridian line | LineString crossing ±180° | Great-circle length is finite and short |
| Polar point | Feature above 85° latitude | Reproject to polar stereographic, coords finite |
| Pole itself | Point at 90° latitude | Web Mercator projection rejected, not inf |
| Dateline-adjacent | Feature at ±179.99° | No accidental wrap |
Step-by-step implementation
The pattern targets Shapely 2.x, GeoPandas 0.14+ and pyproj, generating each fixture and the assertion that validates it.
Step 1 — Generate an anti-meridian crossing
A polygon that spans the dateline, kept in WGS84, is the canonical fixture.
from shapely.geometry import Polygon
import geopandas as gpd
# A box straddling +180 / -180 near Fiji
antimeridian = gpd.GeoDataFrame(
{"id": [1]},
geometry=[Polygon([(179, -18), (-179, -18), (-179, -16), (179, -16), (179, -18)])],
crs="EPSG:4326",
)
Step 2 — Assert the pipeline splits rather than wraps
A correct handler splits the geometry at the dateline (e.g. via a densify-and-split step) so each part stays on one side and the bounding box is local, not global.
def test_antimeridian_bbox_is_not_global(antimeridian):
minx, _, maxx, _ = antimeridian.total_bounds
# A naïve wrap makes width ~358°; a correct split keeps each part narrow.
assert (maxx - minx) < 5 or (maxx - minx) > 355, "ambiguous wrap — split before use"
Step 3 — Generate a polar fixture
from shapely.geometry import Point
polar = gpd.GeoDataFrame(
{"id": [1]}, geometry=[Point(0, 88)], crs="EPSG:4326" # 88° N
)
Step 4 — Assert polar features use an appropriate CRS
Reproject the polar fixture to a polar stereographic CRS (EPSG:3995) and confirm finite coordinates; assert that a Web Mercator projection of the pole itself is rejected, not silently infinite.
import numpy as np
def test_polar_uses_stereographic(polar):
stereo = polar.to_crs(3995) # Arctic polar stereographic
xy = np.array([(p.x, p.y) for p in stereo.geometry])
assert np.isfinite(xy).all(), "polar coords must be finite in a polar CRS"
The choice of a metric, feature-local CRS before measuring is the same rule the spatial tolerance thresholds work applies to high-latitude distortion.
Verification pattern
Confirm the fixtures provoke the bug they target on a naïve handler, so the fixture is proven to have teeth.
# A naïve centroid of the anti-meridian fixture lands near 0° longitude — wrong.
c = antimeridian.geometry.iloc[0].centroid
assert abs(c.x) < 1, "naïve centroid demonstrates the wrap bug the fixture must catch"
Failure modes and edge cases
- Bounding-box operations before splitting. Any bbox, centroid or buffer on an unsplit anti-meridian geometry is wrong; split at the dateline first.
- Web Mercator at the pole. Projecting ±90° to EPSG:3857 yields infinite y; guard with a latitude check and use a polar CRS.
- Fixtures stored reprojected. Saving the anti-meridian fixture already split hides the raw-crossing case; keep the unsplit WGS84 form as the fixture.
- ±179.99° false positives. A near-dateline feature that does not actually cross should not be split; test both crossing and adjacent cases.
- Antarctic vs Arctic CRS. EPSG:3995 is Arctic; a southern polar fixture needs EPSG:3031 — pick the hemisphere-correct CRS.
Conclusion
Anti-meridian and polar fixtures are cheap to generate and essential to keep, because the bugs they expose — inverted bounding boxes and infinite polar coordinates — pass every validity check and only surface against data that deliberately crosses the dateline or approaches the pole. Keep both in the fast tier with assertions that prove the pipeline splits and reprojects correctly. For the wider edge-case catalogue, return to edge case spatial data creation.