FA-69881 / Map projection transforms / Open access
Spherical web mercator inverse projection: longitude unit conversion · case 01
Longitudes are returned in radians.
ROOT CAUSE
The easting divided by the radius is returned without converting radians to degrees.
VERIFIED REPAIR
At the longitude unit conversion step restore `lon = math.degrees(px / R)`, leaving the rest of the model unchanged.
Unsuccessful approach: The diameter is used as the divisor, so longitudes are half of the correct value.
Case contract
Input [x, y] metres (sphere radius 6378137). Eastings outside the world extent E = 20037508.342789244 are wrapped into [-E, E) first. Return [lon, lat] in degrees rounded to 7 decimals.
Why this case matters
Converting clicked map positions or tile corners back to geographic coordinates uses this inverse; faults misplace every reverse-geocoded point.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
px, py = x
R = 6378137.0
E = 20037508.342789244
px = ((px + E) % (2 * E)) - E
lon = px / R
lat = math.degrees(2 * math.atan(math.exp(py / R)) - math.pi / 2)
return [round(lon, 7), round(lat, 7)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression #0', [25000000.0, 1000000.0], [-135.421179, 8.9465739]), ('regression #1', [-30000000.0, -2000000.0], [90.5054148, -17.6789142]), ('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288])], [('regression #1', [-30000000.0, -2000000.0], [90.5054148, -17.6789142]), ('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('control #6', [15000000.0, -6000000.0], [134.7472926, -47.3537047]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #9', [500000.0, -500000.0], [4.4915764, -4.486983])], [('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #9', [500000.0, -500000.0], [4.4915764, -4.486983]), ('control #10', [-19000000.0, 12000000.0], [-170.679904, 72.6726763]), ('control #11', [3000000.0, 9000000.0], [26.9494585, 62.5882773])], [('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #11', [3000000.0, 9000000.0], [26.9494585, 62.5882773]), ('regression #12', [45000000.0, 3000000.0], [44.2418779, 26.0074202]), ('control #13', [-1234567.0, 7654321.0], [-11.0903041, 56.4787668])], [('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('control #6', [15000000.0, -6000000.0], [134.7472926, -47.3537047]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('regression #14', [-21000000.0, 500000.0], [171.3537903, 4.486983]), ('regression #15', [-25000000.0, -4000000.0], [135.421179, -33.7852301]), ('regression #16', [-40075016.0, 0.0], [6.2e-06, 0.0])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression #0 | [-2.3635454, 8.9465739] | [-135.421179, 8.9465739] | Failed |
| regression #1 | [1.5796175, -17.6789142] | [90.5054148, -17.6789142] | Failed |
| boundary #2 | [-3.1415927, 0.0] | [-180.0, 0.0] | Failed |
| control #3 | [0.0, 0.0] | [0.0, 0.0] | Passed |
| control #4 | [0.1745329, 10.0] | [9.9999999, 10.0] | Failed |
| control #5 | [-1.2915436, 40.7139556] | [-73.9999998, 40.7139556] | Failed |
| boundary #7 | [0.0, 85.0511288] | [0.0, 85.0511288] | Passed |
| boundary #8 | [0.0, -85.0511288] | [0.0, -85.0511288] | Passed |
SHA-256 / d1f85b30f65355ebcbff11bf52f9b611c962f3ecce7d8878f8e2e5f09e0c3955
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
px, py = x
R = 6378137.0
E = 20037508.342789244
px = ((px + E) % (2 * E)) - E
lon = math.degrees(px / (2 * R))
lat = math.degrees(2 * math.atan(math.exp(py / R)) - math.pi / 2)
return [round(lon, 7), round(lat, 7)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression #0', [25000000.0, 1000000.0], [-135.421179, 8.9465739]), ('regression #1', [-30000000.0, -2000000.0], [90.5054148, -17.6789142]), ('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288])], [('regression #1', [-30000000.0, -2000000.0], [90.5054148, -17.6789142]), ('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('control #6', [15000000.0, -6000000.0], [134.7472926, -47.3537047]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #9', [500000.0, -500000.0], [4.4915764, -4.486983])], [('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #9', [500000.0, -500000.0], [4.4915764, -4.486983]), ('control #10', [-19000000.0, 12000000.0], [-170.679904, 72.6726763]), ('control #11', [3000000.0, 9000000.0], [26.9494585, 62.5882773])], [('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #11', [3000000.0, 9000000.0], [26.9494585, 62.5882773]), ('regression #12', [45000000.0, 3000000.0], [44.2418779, 26.0074202]), ('control #13', [-1234567.0, 7654321.0], [-11.0903041, 56.4787668])], [('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('control #6', [15000000.0, -6000000.0], [134.7472926, -47.3537047]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('regression #14', [-21000000.0, 500000.0], [171.3537903, 4.486983]), ('regression #15', [-25000000.0, -4000000.0], [135.421179, -33.7852301]), ('regression #16', [-40075016.0, 0.0], [6.2e-06, 0.0])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression #0 | [-67.7105895, 8.9465739] | [-135.421179, 8.9465739] | Failed |
| regression #1 | [45.2527074, -17.6789142] | [90.5054148, -17.6789142] | Failed |
| boundary #2 | [-90.0, 0.0] | [-180.0, 0.0] | Failed |
| control #3 | [0.0, 0.0] | [0.0, 0.0] | Passed |
| control #4 | [5.0, 10.0] | [9.9999999, 10.0] | Failed |
| control #5 | [-36.9999999, 40.7139556] | [-73.9999998, 40.7139556] | Failed |
| boundary #7 | [0.0, 85.0511288] | [0.0, 85.0511288] | Passed |
| boundary #8 | [0.0, -85.0511288] | [0.0, -85.0511288] | Passed |
SHA-256 / c949b4e6880e2fcb822fb5632e64b2563d2788e94334e01c2bc8655009650146
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
px, py = x
R = 6378137.0
E = 20037508.342789244
px = ((px + E) % (2 * E)) - E
lon = math.degrees(px / R)
lat = math.degrees(2 * math.atan(math.exp(py / R)) - math.pi / 2)
return [round(lon, 7), round(lat, 7)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression #0', [25000000.0, 1000000.0], [-135.421179, 8.9465739]), ('regression #1', [-30000000.0, -2000000.0], [90.5054148, -17.6789142]), ('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288])], [('regression #1', [-30000000.0, -2000000.0], [90.5054148, -17.6789142]), ('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('control #6', [15000000.0, -6000000.0], [134.7472926, -47.3537047]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #9', [500000.0, -500000.0], [4.4915764, -4.486983])], [('boundary #2', [20037508.342789244, 0.0], [-180.0, 0.0]), ('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #9', [500000.0, -500000.0], [4.4915764, -4.486983]), ('control #10', [-19000000.0, 12000000.0], [-170.679904, 72.6726763]), ('control #11', [3000000.0, 9000000.0], [26.9494585, 62.5882773])], [('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #4', [1113194.9, 1118889.97], [9.9999999, 10.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('control #11', [3000000.0, 9000000.0], [26.9494585, 62.5882773]), ('regression #12', [45000000.0, 3000000.0], [44.2418779, 26.0074202]), ('control #13', [-1234567.0, 7654321.0], [-11.0903041, 56.4787668])], [('control #3', [0.0, 0.0], [0.0, 0.0]), ('control #5', [-8237642.3, 4970241.3], [-73.9999998, 40.7139556]), ('control #6', [15000000.0, -6000000.0], [134.7472926, -47.3537047]), ('boundary #7', [0.0, 20037508.342789244], [0.0, 85.0511288]), ('boundary #8', [0.0, -20037508.342789244], [0.0, -85.0511288]), ('regression #14', [-21000000.0, 500000.0], [171.3537903, 4.486983]), ('regression #15', [-25000000.0, -4000000.0], [135.421179, -33.7852301]), ('regression #16', [-40075016.0, 0.0], [6.2e-06, 0.0])]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression #0 | [-135.421179, 8.9465739] | [-135.421179, 8.9465739] | Passed |
| regression #1 | [90.5054148, -17.6789142] | [90.5054148, -17.6789142] | Passed |
| boundary #2 | [-180.0, 0.0] | [-180.0, 0.0] | Passed |
| control #3 | [0.0, 0.0] | [0.0, 0.0] | Passed |
| control #4 | [9.9999999, 10.0] | [9.9999999, 10.0] | Passed |
| control #5 | [-73.9999998, 40.7139556] | [-73.9999998, 40.7139556] | Passed |
| boundary #7 | [0.0, 85.0511288] | [0.0, 85.0511288] | Passed |
| boundary #8 | [0.0, -85.0511288] | [0.0, -85.0511288] | Passed |
SHA-256 / 4ea4047e7893ad6eb5c470237b0dd29d64e2dcc1590e7e5756de12765a0b9bcf
Verification & scope
Stipulated deterministic toy contract on a bounded input domain; results are rounded as stated and no conformance with any published standard or library is claimed. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:15.444542+00:00.
Case digest / 84b18617793b12b4fa161496b6203c364bf7b68ffd4eb2b119eac18c4ee08985