feat: split RU-ARK into mainland + New Earth + Severnaya Zemlya — idempotent stage, manifests 1,798 (v0.25.0, #31)
This commit is contained in:
+54
-12
@@ -530,16 +530,20 @@ describe('regions.geo.json', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('is at the v0.17 fixed point: 1,796 regions, 11,794 parts, 11,795 rings, 164,801 vertices, 1 hole (KZ-KZY)', () => {
|
||||
it('is at the v0.25 fixed point: 1,798 regions, 11,794 parts, 11,795 rings, 164,801 vertices, 1 hole (KZ-KZY)', () => {
|
||||
// v0.17 (scripts/fill-gaps.mjs) APPENDED cleaned gap pieces to the v0.16
|
||||
// fixed point: it never moves an existing border, merges a part, or
|
||||
// removes a ring — it only adds new parts (+6,768: 5,026 → 11,794) and
|
||||
// keeps the single KZ-KZY hole. The region count (1,796), the
|
||||
// per-feature ids/names/parents and their order are unchanged; only the
|
||||
// part/ring/vertex totals and the hole's part structure moved. Pinning
|
||||
// the signature guards against a non-idempotent or destructive re-run.
|
||||
// The fill is byte-deterministic per input and idempotent (a second run
|
||||
// on the filled file changes nothing).
|
||||
// keeps the single KZ-KZY hole. The v0.25 Arkhangel'sk split (#31,
|
||||
// scripts/split-arkhangel.mjs) then repartitioned the 78 RU-ARK parts
|
||||
// across three features (RU-ARK + RU-ARK-NE + RU-ARK-SZ) — a pure
|
||||
// re-grouping: no part/ring/vertex moves, so only the region count
|
||||
// changed (1,796 → 1,798); the part/ring/vertex totals, the per-feature
|
||||
// ids/names/parents, and the feature order (the two new features sit
|
||||
// immediately after RU-ARK) are as pinned below. Pinning the signature
|
||||
// guards against a non-idempotent or destructive re-run; both stages are
|
||||
// byte-deterministic per input and idempotent (a second run changes
|
||||
// nothing).
|
||||
const polysOf = (g: Geometry) => (g.type === 'Polygon' ? [g.coordinates] : g.coordinates);
|
||||
let verts = 0,
|
||||
rings = 0,
|
||||
@@ -556,15 +560,53 @@ describe('regions.geo.json', () => {
|
||||
for (const ring of poly) verts += ring.length;
|
||||
}
|
||||
}
|
||||
expect(regions.features.length, 'region count').toBe(1796); // unchanged by the fill
|
||||
expect(parts, 'parts').toBe(11_794); // v0.16: 5,026 → +6,768 appended gap pieces
|
||||
expect(regions.features.length, 'region count').toBe(1798); // v0.17: 1,796 → +2 by the #31 split
|
||||
expect(parts, 'parts').toBe(11_794); // v0.16: 5,026 → +6,768 appended gap pieces; unchanged by the split
|
||||
expect(rings, 'rings').toBe(11_795); // every appended part is a single-ring polygon (+1 hole = KZ-KZY, pre-existing)
|
||||
expect(holes, 'holes').toBe(1); // the single KZ-KZY hole, unchanged
|
||||
expect(holeIds, 'the one remaining hole is KZ-KZY').toEqual(['KZ-KZY']);
|
||||
expect(verts, 'total vertices (incl. ring closure)').toBe(164_801); // v0.16: 111,175
|
||||
expect(verts, 'total vertices (incl. ring closure)').toBe(164_801); // v0.16: 111,175; unchanged by the split
|
||||
console.log(
|
||||
`\n v0.17 gap fill: ${regions.features.length} regions, ${parts} parts, ${rings} rings, ` +
|
||||
`${holes} hole (KZ-KZY), ${verts} vertices — v0.16 topology preserved, 6,768 gap pieces appended`,
|
||||
`\n v0.25 fixed point: ${regions.features.length} regions (1,796 + the #31 split's two islands), ` +
|
||||
`${parts} parts, ${rings} rings, ${holes} hole (KZ-KZY), ${verts} vertices — v0.17 topology preserved`,
|
||||
);
|
||||
});
|
||||
|
||||
it('has the three Arkhangel\'sk features split per #31 (RU-ARK main + New Earth + Severnaya Zemlya)', () => {
|
||||
// v0.25 (#31): the ~411,500 km² RU-ARK mega-region (a 78-part MultiPolygon
|
||||
// mixing mainland and far-north islands) was repartitioned by part
|
||||
// centroid into the mainland (RU-ARK, keeps its id/name/key), the Franz
|
||||
// Josef Land islets (RU-ARK-NE "New Earth", centroid lat ≥ 79.5) and the
|
||||
// Severnaya Zemlya islets (RU-ARK-SZ, centroid 76–79.5° N, lon ≥ 55°E).
|
||||
// Pure re-grouping: all three keep parent RUS and all 78 original parts.
|
||||
const byId = new Map(regions.features.map((f) => [f.id, f]));
|
||||
const ark = byId.get('RU-ARK');
|
||||
const ne = byId.get('RU-ARK-NE');
|
||||
const sz = byId.get('RU-ARK-SZ');
|
||||
expect(ark, 'RU-ARK (the main feature) exists').toBeDefined();
|
||||
expect(ne, 'RU-ARK-NE (New Earth) exists').toBeDefined();
|
||||
expect(sz, 'RU-ARK-SZ (Severnaya Zemlya) exists').toBeDefined();
|
||||
for (const f of [ark!, ne!, sz!]) {
|
||||
expect(f.properties.parent, `${f.id} parent`).toBe('RUS');
|
||||
expect(f.geometry.type, `${f.id} geometry`).toBe('MultiPolygon');
|
||||
}
|
||||
expect(ark!.properties.name, 'RU-ARK keeps its name').toBe("Arkhangel'sk");
|
||||
expect(ne!.properties.name, 'RU-ARK-NE name').toBe('New Earth');
|
||||
expect(sz!.properties.name, 'RU-ARK-SZ name').toBe('Severnaya Zemlya');
|
||||
// the 78 parts of the pre-split feature are all accounted for, verbatim
|
||||
const countParts = (f: (typeof regions.features)[number]) =>
|
||||
f.geometry.type === 'MultiPolygon' ? f.geometry.coordinates.length : 1;
|
||||
expect(
|
||||
countParts(ark!) + countParts(ne!) + countParts(sz!),
|
||||
'total parts across the three features',
|
||||
).toBe(78);
|
||||
// stable file order: the two new features sit immediately after RU-ARK
|
||||
const idx = regions.features.findIndex((f) => f.id === 'RU-ARK');
|
||||
expect(regions.features[idx + 1]?.id).toBe('RU-ARK-NE');
|
||||
expect(regions.features[idx + 2]?.id).toBe('RU-ARK-SZ');
|
||||
console.log(
|
||||
`\n #31 split: RU-ARK ${countParts(ark!)} parts (mainland), RU-ARK-NE ${countParts(ne!)} parts (New Earth), ` +
|
||||
`RU-ARK-SZ ${countParts(sz!)} parts (Severnaya Zemlya)`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user