1// Where S2 stops being useful, pinned so nobody rediscovers it as a bug.2//3// `appliesTo` asks two questions — is this a sphere, and is there an invertible4// flattening — and a Web-Mercator city window answers yes to both. It is still5// not a ground the grid should be offered on, and the reason is arithmetic6// rather than taste. This file records the limit instead of quietly changing7// `appliesTo`: the vectors gate has no mercator ground and would not have8// caught the change, and a silent narrowing of a system's applicability is9// exactly the kind of divergence the clean-room rule exists to prevent.10//11// The fix, when someone wants it, is a curation decision in the app (offer S212// only on whole-world lenses) or a `Ground` that says what fraction of a world13// its surface pictures. Both are M6+ conversations; neither is this lane's to14// make unilaterally. See docs/analysis.md, "the whole-world assumption".1516import assert from "node:assert/strict";17import test from "node:test";1819import { s2System } from "../cellsystems/s2.ts";20import { surfaceWidth } from "../cellsystems/ground.ts";21import { mercatorCity } from "./grounds.ts";2223test("S2 accepts a city window, because the ground answers both its questions", () => {24 assert.equal(s2System.appliesTo(mercatorCity), true);25});2627test("but the seam unwrap treats the surface as one whole world", () => {28 // The unwrap corrects any step longer than half the surface, on the theory29 // that a half-world jump in x is the antimeridian. On a lens picturing a30 // fifth of a degree, a planetary cell's edge is many surfaces wide and the31 // correction has nothing to do with the seam.32 const on = s2System.on(mercatorCity);33 const ring = on.ring("5");34 const half = surfaceWidth(mercatorCity) / 2;35 const jumps = ring.filter((point, at) => {36 const previous = ring[at - 1];37 return at > 0 && previous !== undefined && Math.abs(point[0] - previous[0]) > half;38 });39 assert.ok(jumps.length > 0,40 "a face-sized cell on a city window does not stay continuous, and cannot");41});4243test("the cells that matter on such a ground are far below the seam problem", () => {44 // The limit is about coarse cells. A cell at the telescope's floor is a few45 // kilometres across, comfortably inside a city window, and behaves.46 const on = s2System.on(mercatorCity);47 const probe = [2048, -2048] as const;48 let id = "";49 for (let hop = 0; hop < 11; hop++) id = on.descendTarget(id, probe);50 assert.equal(on.level(id), 11);51 assert.equal(on.contains(id, probe), true);52 const ring = on.ring(id);53 const half = surfaceWidth(mercatorCity) / 2;54 for (let at = 1; at < ring.length; at++) {55 const current = ring[at];56 const previous = ring[at - 1];57 assert.ok(current && previous);58 assert.ok(Math.abs(current[0] - previous[0]) <= half, "a leaf cell is continuous");59 }60});