Repository navigation
Fix precision loss in cellAreaRads2 for cells crossing the antimeridian - #1274
thevar1able wants to merge 2 commits into
Conversation
|
Caution Review failedAn error occurred during the review process. Please try again later. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe area calculation now adjusts longitude differences for edges that cross the antimeridian. New tests compare loop and cell areas across the antimeridian and after rotating cell boundaries. ChangesArea calculation precision
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~12 minutes Change: Bug fix · Severity of issue fixed: Medium Merge Risk: ⚪ Minimal · up to
|
2194649 to
94b48e8
Compare
cagnoli subtracted the raw longitudes of an edge's endpoints. For an edge crossing +-180 degrees the difference is close to +-360 and the true, tiny longitude step is lost to the rounding of a value that large, so cells straddling the antimeridian came out too small: 1e-8 relative at res 7, 0.1% at res 13 and 9% at res 15. Shifting both longitudes to the same side of the antimeridian before subtracting keeps the subtraction between two nearby values; sin and cos are 2pi-periodic, so nothing else changes. This is upstream uber/h3#1274, which the pinned release does not yet contain. The conformance suite could not see the defect: its seeded sample has straddling cells only at resolutions 0 and 1, where the loss is far below tolerance. The generator now carries the upstream change as a second patch and writes floats/curated.jsonl, the upstream test pairs at res 13 to 15 plus the cell containing (lat, 180) at every resolution for three latitudes, which the floats/cells checks run. The fifteen straddling res 0 and 1 cells already in floats/cells.jsonl move by at most 4e-14 relative; every other file, the digests included, is byte for byte unchanged. Three tests port the upstream ones: straddling cells agree with their non-straddling neighbours, a cell on the antimeridian keeps its area when rotated onto the prime meridian, and a small triangle across +-180 has the area of the same triangle across 0. All three fail without the shift. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
cagnoli subtracted the raw longitudes of an edge's endpoints. For an edge crossing +-180 degrees the difference is close to +-360 and the true, tiny longitude step is lost to the rounding of a value that large, so cells straddling the antimeridian came out too small: 1e-8 relative at res 7, 0.1% at res 13 and 9% at res 15. Shifting both longitudes to the same side of the antimeridian before subtracting keeps the subtraction between two nearby values; sin and cos are 2pi-periodic, so nothing else changes. This is upstream uber/h3#1274, which the pinned release does not yet contain. The conformance suite could not see the defect: its seeded sample has straddling cells only at resolutions 0 and 1, where the loss is far below tolerance. The generator now carries the upstream change as a second patch and writes floats/curated.jsonl, the upstream test pairs at res 13 to 15 plus the cell containing (lat, 180) at every resolution for three latitudes, which the floats/cells checks run. The fifteen straddling res 0 and 1 cells already in floats/cells.jsonl move by at most 4e-14 relative; every other file, the digests included, is byte for byte unchanged. Three tests port the upstream ones: straddling cells agree with their non-straddling neighbours, a cell on the antimeridian keeps its area when rotated onto the prime meridian, and a small triangle across +-180 has the area of the same triangle across 0. All three fail without the shift. Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Since #1101,
cellAreaRads2adds up a term per cell edge (cagnoliinarea.c). For an edge that crosses ±180°, the raw longitude difference is close to ±2π. The real gap between the two vertices is tiny, and at that magnitude it gets lost to floating-point rounding beforesinandcosare applied. Nothing cancels the error, so cells that straddle the antimeridian come out too small. Compared with a neighbouring cell, a straddling cell is about 0.07% too small at res 13, 0.4% at res 14 and 2.5% at res 15. This also affectscellAreaKm2andcellAreaM2, andgeoLoopAreaRads2and the other polygon area helpers. Releases before #1101 used a different formula and don't have this problem.The fix shifts both longitudes to the same side of the antimeridian before subtracting, so the subtraction is between two nearby values.
sinandcosrepeat every 2π, so the result is mathematically the same. Edges that don't cross the antimeridian take the old path unchanged.Tests:
cell_area_antimeridian: three pairs of cells at res 13–15, each a straddling cell next to one that doesn't straddle. Their areas must agree to within 1e-5.cell_area_antimeridian_rotation: at every resolution, cells along ±180° must keep their area when their boundary is shifted 180° in longitude, to within 1e-6. Shifting around the polar axis can't change an area, so this needs no reference values. The worst result on fixed code is 3e-8 at res 15; unfixed code is off by up to 7.6e-2.antimeridianTriangle: a small triangle across ±180° must have the same area as the same triangle across 0°. This uses a triangle and not a rectangle on purpose: a rectangle's two crossing edges have identical longitude differences, so their rounding errors cancel and the test passes even without the fix.Each new test fails without the fix. The existing exhaustive area tests still pass. They only go up to res 4, where the error is too small for them to see, which is why nothing caught this.
This was found and fixed in ClickHouse's fork (ClickHouse#13, reported in ClickHouse/ClickHouse#124447). This PR ports that fix and adds the rotation and triangle tests.
Related: #1101, #1108