{"abstract":"Northings are wildly exaggerated even at mid latitudes.","category":"Map projection transforms","checks":8,"contract":"Input [lon, lat] in degrees. Longitude is first wrapped into the half-open range [-180, 180); latitude is clamped to +/-85.05112878. Return [x, y] metres on a sphere of radius 6378137 with y growing northward, each rounded to 3 decimals.","evaluation_group":"w2-map-projection-transforms-web-mercator-forward","failed_approach":"The halving was restored but the latitude is no longer converted to radians.","family":"w2-map-projection-transforms-web-mercator-forward-half-angle-term","id":"FA-69851","implementations":{"attempt":{"sha256":"90ae36c9e8750157877c1800e55c184da1e6502030491842bae08c56e3d3770a","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    lon, lat = x\n    lon = ((lon + 180.0) % 360.0) - 180.0\n    lat = max(-85.05112878, min(85.05112878, lat))\n    R = 6378137.0\n    px = R * math.radians(lon)\n    py = R * math.log(math.tan(math.pi / 4 + lat / 2))\n    return [round(px, 3), round(py, 3)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452])], [('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452]), ('control #16', [151.867, -5.771], [16905757.108, -643513.79])], [('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('control #16', [151.867, -5.771], [16905757.108, -643513.79]), ('control #24', [55.104, 19.415], [6134149.221, 2203856.898]), ('control #27', [-110.905, -43.354], [-12345888.126, -5366010.423]), ('control #28', [-168.23, -6.059], [-18727277.936, -675745.443])], [('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('control #28', [-168.23, -6.059], [-18727277.936, -675745.443]), ('control #30', [6.846, 23.569], [762093.234, 2700976.142]), ('control #32', [-15.276, -37.269], [-1700516.541, -4476668.54])], [('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"9090b65603d15fe5738e2db2bbb641bcea13b7295ec43314d281c8ce27ce4d8d","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    lon, lat = x\n    lon = ((lon + 180.0) % 360.0) - 180.0\n    lat = max(-85.05112878, min(85.05112878, lat))\n    R = 6378137.0\n    px = R * math.radians(lon)\n    py = R * math.log(math.tan(math.pi / 4 + math.radians(lat)))\n    return [round(px, 3), round(py, 3)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452])], [('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452]), ('control #16', [151.867, -5.771], [16905757.108, -643513.79])], [('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('control #16', [151.867, -5.771], [16905757.108, -643513.79]), ('control #24', [55.104, 19.415], [6134149.221, 2203856.898]), ('control #27', [-110.905, -43.354], [-12345888.126, -5366010.423]), ('control #28', [-168.23, -6.059], [-18727277.936, -675745.443])], [('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('control #28', [-168.23, -6.059], [-18727277.936, -675745.443]), ('control #30', [6.846, 23.569], [762093.234, 2700976.142]), ('control #32', [-15.276, -37.269], [-1700516.541, -4476668.54])], [('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"fee2a80c1f4f472122733f166bc8ec407a712ddd295d470621e84bd94faa020c","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(x):\n    lon, lat = x\n    lon = ((lon + 180.0) % 360.0) - 180.0\n    lat = max(-85.05112878, min(85.05112878, lat))\n    R = 6378137.0\n    px = R * math.radians(lon)\n    py = R * math.log(math.tan(math.pi / 4 + math.radians(lat) / 2))\n    return [round(px, 3), round(py, 3)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452])], [('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452]), ('control #16', [151.867, -5.771], [16905757.108, -643513.79])], [('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('control #16', [151.867, -5.771], [16905757.108, -643513.79]), ('control #24', [55.104, 19.415], [6134149.221, 2203856.898]), ('control #27', [-110.905, -43.354], [-12345888.126, -5366010.423]), ('control #28', [-168.23, -6.059], [-18727277.936, -675745.443])], [('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('control #28', [-168.23, -6.059], [-18727277.936, -675745.443]), ('control #30', [6.846, 23.569], [762093.234, 2700976.142]), ('control #32', [-15.276, -37.269], [-1700516.541, -4476668.54])], [('regression #1', [-200.0, -20.0], [17811118.527, -2273030.927]), ('boundary #2', [180.0, 0.0], [-20037508.343, -0.0]), ('boundary #3', [-180.0, 45.0], [-20037508.343, 5621521.486]), ('regression #4', [545.0, 5.0], [-19480910.889, 557305.257]), ('control #8', [0.0, 0.0], [0.0, -0.0]), ('regression #9', [-540.0, 30.0], [-20037508.343, 3503549.844]), ('regression #10', [-250.0, 12.5], [12245143.987, 1402665.19]), ('regression #14', [-181.0, 0.5], [19926188.852, 55660.452])]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-map-projection-transforms-web-mercator-forward-half-angle-term","generated_at":"2026-09-29T14:48:15.187829+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Web map tiles, vector tile encoders and map viewers all start from this forward transform; small mistakes shift features by kilometres or mirror them across the equator.","repair":"At the half-angle term step restore `math.pi / 4 + math.radians(lat) / 2`, leaving the rest of the model unchanged.","root_cause":"The isometric latitude uses tan(pi/4 + phi) instead of tan(pi/4 + phi/2), doubling the latitude inside the tangent.","sha256":"826f17626088ea6a8223dd2181bca6fa11e536d6fd7fc7e0839ea2862cfe5477","title":"Spherical web mercator forward projection: half-angle term · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":77.352,"exit_code":1,"observations":[{"actual":[17811118.527,-9853781.978],"check":"regression #1","expected":[17811118.527,-2273030.927],"passed":false},{"actual":[-20037508.343,-0.0],"check":"boundary #2","expected":[-20037508.343,-0.0],"passed":true},{"actual":[-20037508.343,8032739.293],"check":"boundary #3","expected":[-20037508.343,5621521.486],"passed":false},{"actual":[-19480910.889,-12324899.673],"check":"regression #4","expected":[-19480910.889,557305.257],"passed":false},{"actual":[0.0,-0.0],"check":"control #8","expected":[0.0,-0.0],"passed":true},{"actual":[-20037508.343,-16304535.145],"check":"regression #9","expected":[-20037508.343,3503549.844],"passed":false},{"actual":[12245143.987,-423632.006],"check":"regression #10","expected":[12245143.987,1402665.19],"passed":false},{"actual":[19926188.852,3330906.169],"check":"regression #14","expected":[19926188.852,55660.452],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression #1\", \"actual\": [17811118.527, -9853781.978], \"expected\": [17811118.527, -2273030.927], \"passed\": false}, {\"check\": \"boundary #2\", \"actual\": [-20037508.343, -0.0], \"expected\": [-20037508.343, -0.0], \"passed\": true}, {\"check\": \"boundary #3\", \"actual\": [-20037508.343, 8032739.293], \"expected\": [-20037508.343, 5621521.486], \"passed\": false}, {\"check\": \"regression #4\", \"actual\": [-19480910.889, -12324899.673], \"expected\": [-19480910.889, 557305.257], \"passed\": false}, {\"check\": \"control #8\", \"actual\": [0.0, -0.0], \"expected\": [0.0, -0.0], \"passed\": true}, {\"check\": \"regression #9\", \"actual\": [-20037508.343, -16304535.145], \"expected\": [-20037508.343, 3503549.844], \"passed\": false}, {\"check\": \"regression #10\", \"actual\": [12245143.987, -423632.006], \"expected\": [12245143.987, 1402665.19], \"passed\": false}, {\"check\": \"regression #14\", \"actual\": [19926188.852, 3330906.169], \"expected\": [19926188.852, 55660.452], \"passed\": false}], \"passed\": false}\n"},"broken":{"elapsed_ms":56.5,"exit_code":1,"observations":[{"actual":[17811118.527,-4865942.28],"check":"regression #1","expected":[17811118.527,-2273030.927],"passed":false},{"actual":[-20037508.343,-0.0],"check":"boundary #2","expected":[-20037508.343,-0.0],"passed":true},{"actual":[-20037508.343,238107693.265],"check":"boundary #3","expected":[-20037508.343,5621521.486],"passed":false},{"actual":[-19480910.889,1118889.975],"check":"regression #4","expected":[-19480910.889,557305.257],"passed":false},{"actual":[0.0,-0.0],"check":"control #8","expected":[0.0,-0.0],"passed":true},{"actual":[-20037508.343,8399737.89],"check":"regression #9","expected":[-20037508.343,3503549.844],"passed":false},{"actual":[12245143.987,2875744.624],"check":"regression #10","expected":[12245143.987,1402665.19],"passed":false},{"actual":[19926188.852,111325.143],"check":"regression #14","expected":[19926188.852,55660.452],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression #1\", \"actual\": [17811118.527, -4865942.28], \"expected\": [17811118.527, -2273030.927], \"passed\": false}, {\"check\": \"boundary #2\", \"actual\": [-20037508.343, -0.0], \"expected\": [-20037508.343, -0.0], \"passed\": true}, {\"check\": \"boundary #3\", \"actual\": [-20037508.343, 238107693.265], \"expected\": [-20037508.343, 5621521.486], \"passed\": false}, {\"check\": \"regression #4\", \"actual\": [-19480910.889, 1118889.975], \"expected\": [-19480910.889, 557305.257], \"passed\": false}, {\"check\": \"control #8\", \"actual\": [0.0, -0.0], \"expected\": [0.0, -0.0], \"passed\": true}, {\"check\": \"regression #9\", \"actual\": [-20037508.343, 8399737.89], \"expected\": [-20037508.343, 3503549.844], \"passed\": false}, {\"check\": \"regression #10\", \"actual\": [12245143.987, 2875744.624], \"expected\": [12245143.987, 1402665.19], \"passed\": false}, {\"check\": \"regression #14\", \"actual\": [19926188.852, 111325.143], \"expected\": [19926188.852, 55660.452], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.167,"exit_code":0,"observations":[{"actual":[17811118.527,-2273030.927],"check":"regression #1","expected":[17811118.527,-2273030.927],"passed":true},{"actual":[-20037508.343,-0.0],"check":"boundary #2","expected":[-20037508.343,-0.0],"passed":true},{"actual":[-20037508.343,5621521.486],"check":"boundary #3","expected":[-20037508.343,5621521.486],"passed":true},{"actual":[-19480910.889,557305.257],"check":"regression #4","expected":[-19480910.889,557305.257],"passed":true},{"actual":[0.0,-0.0],"check":"control #8","expected":[0.0,-0.0],"passed":true},{"actual":[-20037508.343,3503549.844],"check":"regression #9","expected":[-20037508.343,3503549.844],"passed":true},{"actual":[12245143.987,1402665.19],"check":"regression #10","expected":[12245143.987,1402665.19],"passed":true},{"actual":[19926188.852,55660.452],"check":"regression #14","expected":[19926188.852,55660.452],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression #1\", \"actual\": [17811118.527, -2273030.927], \"expected\": [17811118.527, -2273030.927], \"passed\": true}, {\"check\": \"boundary #2\", \"actual\": [-20037508.343, -0.0], \"expected\": [-20037508.343, -0.0], \"passed\": true}, {\"check\": \"boundary #3\", \"actual\": [-20037508.343, 5621521.486], \"expected\": [-20037508.343, 5621521.486], \"passed\": true}, {\"check\": \"regression #4\", \"actual\": [-19480910.889, 557305.257], \"expected\": [-19480910.889, 557305.257], \"passed\": true}, {\"check\": \"control #8\", \"actual\": [0.0, -0.0], \"expected\": [0.0, -0.0], \"passed\": true}, {\"check\": \"regression #9\", \"actual\": [-20037508.343, 3503549.844], \"expected\": [-20037508.343, 3503549.844], \"passed\": true}, {\"check\": \"regression #10\", \"actual\": [12245143.987, 1402665.19], \"expected\": [12245143.987, 1402665.19], \"passed\": true}, {\"check\": \"regression #14\", \"actual\": [19926188.852, 55660.452], \"expected\": [19926188.852, 55660.452], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}