@diagrammo/dgmo 0.21.0 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -6
- package/dist/advanced.cjs +2521 -623
- package/dist/advanced.d.cts +917 -534
- package/dist/advanced.d.ts +917 -534
- package/dist/advanced.js +2516 -623
- package/dist/auto.cjs +2333 -608
- package/dist/auto.js +119 -119
- package/dist/auto.mjs +2335 -609
- package/dist/cli.cjs +168 -168
- package/dist/editor.cjs +13 -15
- package/dist/editor.js +13 -15
- package/dist/highlight.cjs +15 -12
- package/dist/highlight.js +15 -12
- package/dist/index.cjs +2317 -595
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +2319 -596
- package/dist/internal.cjs +2521 -623
- package/dist/internal.d.cts +917 -534
- package/dist/internal.d.ts +917 -534
- package/dist/internal.js +2516 -623
- package/dist/map-data/PROVENANCE.json +1 -1
- package/dist/map-data/mountain-ranges.json +1 -0
- package/dist/map-data/water-bodies.json +1 -0
- package/docs/language-reference.md +44 -31
- package/gallery/fixtures/map-categorical-world.dgmo +16 -0
- package/gallery/fixtures/map-categorical.dgmo +0 -1
- package/gallery/fixtures/map-choropleth.dgmo +0 -1
- package/gallery/fixtures/map-coastline.dgmo +7 -0
- package/gallery/fixtures/map-colorize.dgmo +11 -0
- package/gallery/fixtures/map-direct-color.dgmo +9 -0
- package/gallery/fixtures/map-reference-world.dgmo +11 -0
- package/gallery/fixtures/map-region-scope.dgmo +0 -3
- package/gallery/fixtures/map-route.dgmo +0 -1
- package/package.json +1 -1
- package/src/advanced.ts +26 -1
- package/src/boxes-and-lines/renderer.ts +39 -12
- package/src/cli.ts +1 -1
- package/src/completion.ts +32 -24
- package/src/cycle/renderer.ts +14 -1
- package/src/d3.ts +23 -11
- package/src/editor/highlight-api.ts +4 -0
- package/src/editor/keywords.ts +13 -15
- package/src/infra/renderer.ts +35 -7
- package/src/map/colorize.ts +54 -0
- package/src/map/context-labels.ts +429 -0
- package/src/map/data/PROVENANCE.json +1 -1
- package/src/map/data/mountain-ranges.json +1 -0
- package/src/map/data/types.ts +34 -0
- package/src/map/data/water-bodies.json +1 -0
- package/src/map/dimensions.ts +117 -0
- package/src/map/geo-query.ts +295 -0
- package/src/map/geo.ts +305 -2
- package/src/map/invert.ts +111 -0
- package/src/map/layout.ts +1504 -335
- package/src/map/load-data.ts +16 -2
- package/src/map/parser.ts +57 -111
- package/src/map/renderer.ts +556 -13
- package/src/map/resolved-types.ts +24 -2
- package/src/map/resolver.ts +237 -67
- package/src/map/types.ts +39 -23
- package/src/mindmap/renderer.ts +10 -1
- package/src/palettes/atlas.ts +77 -0
- package/src/palettes/blueprint.ts +73 -0
- package/src/palettes/color-utils.ts +58 -1
- package/src/palettes/index.ts +12 -3
- package/src/palettes/slate.ts +73 -0
- package/src/palettes/tidewater.ts +73 -0
- package/src/render.ts +8 -1
- package/src/tech-radar/renderer.ts +3 -0
- package/src/tech-radar/types.ts +3 -0
- package/src/utils/d3-types.ts +5 -0
- package/src/utils/legend-layout.ts +21 -4
- package/src/utils/legend-types.ts +7 -0
- package/src/utils/reserved-key-registry.ts +3 -0
- package/src/palettes/bold.ts +0 -67
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
// Context-label placement (step 4, part of layout). Produces a sparse,
|
|
2
|
+
// density-thinned ORIENTATION layer — water-body names + unreferenced notable
|
|
3
|
+
// country names — distinct from `region-labels`. PURE + SYNC + DETERMINISTIC.
|
|
4
|
+
//
|
|
5
|
+
// Design (tech-spec §map-context-labels): a deliberately LOW per-view label
|
|
6
|
+
// BUDGET is the primary noise lever; a span-derived TIER BAND orders candidates
|
|
7
|
+
// into it; each candidate is committed only if it survives COLLISION against
|
|
8
|
+
// every already-placed data/region/POI/route label (the `collides` closure) AND
|
|
9
|
+
// the other context labels. Context labels place DEAD LAST and never displace
|
|
10
|
+
// data — they only fill leftover space, degrading gracefully to zero. See
|
|
11
|
+
// Decisions 6 (budget), 7 (dead-last), 8 (viewport/projection guards).
|
|
12
|
+
import { mix } from '../palettes/color-utils';
|
|
13
|
+
import type { PaletteColors } from '../palettes/types';
|
|
14
|
+
import type { LabelRect } from '../label-layout';
|
|
15
|
+
import { measureLegendText } from '../utils/legend-constants';
|
|
16
|
+
import type { ProjectionFamily } from './resolved-types';
|
|
17
|
+
import type { WaterBodies, WaterKind } from './data/types';
|
|
18
|
+
import type { PlacedLabel } from './layout';
|
|
19
|
+
|
|
20
|
+
/** A view span band → priority ordering (NOT a hard zoom cutoff, Decision 6). */
|
|
21
|
+
export type TierBand = 'world' | 'continental' | 'regional' | 'local';
|
|
22
|
+
|
|
23
|
+
/** An unreferenced country, pre-projected by layout (geo work stays in layout;
|
|
24
|
+
* area-rank + name-fit + collision live here so the module is unit-testable). */
|
|
25
|
+
export interface CountryCandidate {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
/** Projected screen bbox `[x0, y0, x1, y1]` (from `path.bounds`). */
|
|
28
|
+
readonly bbox: readonly [number, number, number, number];
|
|
29
|
+
/** Projected screen anchor `[x, y]` (mainland anchor or `path.centroid`), or
|
|
30
|
+
* null when the feature doesn't project to a finite point. */
|
|
31
|
+
readonly anchor: readonly [number, number] | null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface ContextLabelArgs {
|
|
35
|
+
readonly projection: ProjectionFamily;
|
|
36
|
+
readonly dLonSpan: number;
|
|
37
|
+
readonly dLatSpan: number;
|
|
38
|
+
readonly width: number;
|
|
39
|
+
readonly height: number;
|
|
40
|
+
readonly waterBodies?: WaterBodies | undefined;
|
|
41
|
+
readonly countries: readonly CountryCandidate[];
|
|
42
|
+
readonly palette: PaletteColors;
|
|
43
|
+
readonly project: (lon: number, lat: number) => [number, number] | null;
|
|
44
|
+
/** Collision test against every committed data/region/POI/route obstacle. */
|
|
45
|
+
readonly collides: (rect: LabelRect) => boolean;
|
|
46
|
+
/** True when the screen point sits over LAND (a country/state fill) rather than
|
|
47
|
+
* open water. WATER labels are rejected when their footprint touches land — an
|
|
48
|
+
* ocean name belongs over the ocean (they're optional orientation aids, so drop
|
|
49
|
+
* rather than misplace). Country labels are exempt (they label land). Optional
|
|
50
|
+
* for unit tests; absent ⇒ no land rejection. */
|
|
51
|
+
readonly overLand?: (x: number, y: number) => boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const FONT = 11; // matches layout's on-map label font
|
|
55
|
+
const LINE_HEIGHT = FONT + 2; // px per wrapped line — MUST match the renderer's
|
|
56
|
+
const PADX = 4; // half-padding around a context label rect
|
|
57
|
+
const PADY = 3;
|
|
58
|
+
const WATER_LETTER_SPACING = 1.5; // px — cartographic spread for water names
|
|
59
|
+
const CONTEXT_PAD = 4; // extra gap enforced between two context labels
|
|
60
|
+
const EDGE_CLAMP_MARGIN = 8; // px inset for edge-clamped ocean labels
|
|
61
|
+
const EDGE_CLAMP_OVERSHOOT = 0.35; // max off-frame overshoot (× dim) to still clamp
|
|
62
|
+
|
|
63
|
+
// Water-kind priority within a tier (oceans first, then seas, then the rest) so
|
|
64
|
+
// a thin budget always spends on the highest-orientation-value names.
|
|
65
|
+
const KIND_ORDER: Record<WaterKind, number> = {
|
|
66
|
+
ocean: 0,
|
|
67
|
+
sea: 1,
|
|
68
|
+
gulf: 2,
|
|
69
|
+
bay: 3,
|
|
70
|
+
strait: 4,
|
|
71
|
+
channel: 5,
|
|
72
|
+
sound: 6,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/** Span band from the larger of the two view spans (Decision 6 — priority, not
|
|
76
|
+
* a hard gate). */
|
|
77
|
+
export function tierBand(maxSpanDeg: number): TierBand {
|
|
78
|
+
if (maxSpanDeg >= 90) return 'world';
|
|
79
|
+
if (maxSpanDeg >= 20) return 'continental';
|
|
80
|
+
if (maxSpanDeg >= 5) return 'regional';
|
|
81
|
+
return 'local';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Deliberately-LOW combined label budget = f(canvas area, band). Floors to ~1
|
|
85
|
+
* on a thumbnail and 0 on a tiny canvas (Decision 6, ADR-3; AC9). Caps the
|
|
86
|
+
* TOTAL context labels (water + country), so `relief`/data don't get extra
|
|
87
|
+
* headroom (Decision 13). */
|
|
88
|
+
export function labelBudget(
|
|
89
|
+
width: number,
|
|
90
|
+
height: number,
|
|
91
|
+
band: TierBand
|
|
92
|
+
): number {
|
|
93
|
+
const bandCap: Record<TierBand, number> = {
|
|
94
|
+
world: 6,
|
|
95
|
+
continental: 5,
|
|
96
|
+
regional: 4,
|
|
97
|
+
local: 3,
|
|
98
|
+
};
|
|
99
|
+
const area = Math.floor(Math.sqrt(Math.max(0, width * height)) / 150);
|
|
100
|
+
return Math.max(0, Math.min(area, bandCap[band]));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Which water tiers/kinds are eligible at a band. World view is oceans + major
|
|
104
|
+
* seas ONLY (never bays/sounds/minor gulfs, AC3); broader views progressively
|
|
105
|
+
* admit smaller features by `scalerank` (AC4). */
|
|
106
|
+
function waterEligible(tier: number, kind: WaterKind, band: TierBand): boolean {
|
|
107
|
+
switch (band) {
|
|
108
|
+
case 'world':
|
|
109
|
+
return tier <= 1 && (kind === 'ocean' || kind === 'sea');
|
|
110
|
+
case 'continental':
|
|
111
|
+
return tier <= 2;
|
|
112
|
+
case 'regional':
|
|
113
|
+
return tier <= 3;
|
|
114
|
+
case 'local':
|
|
115
|
+
return tier <= 4;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function insideViewport(
|
|
120
|
+
p: readonly [number, number] | null,
|
|
121
|
+
width: number,
|
|
122
|
+
height: number
|
|
123
|
+
): p is [number, number] {
|
|
124
|
+
return (
|
|
125
|
+
!!p &&
|
|
126
|
+
Number.isFinite(p[0]) &&
|
|
127
|
+
Number.isFinite(p[1]) &&
|
|
128
|
+
p[0] >= 0 &&
|
|
129
|
+
p[0] <= width &&
|
|
130
|
+
p[1] >= 0 &&
|
|
131
|
+
p[1] <= height
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Rendered label width INCLUDING letter-spacing — `measureLegendText` ignores
|
|
136
|
+
* the per-gap `letter-spacing` the renderer applies to water names, so without
|
|
137
|
+
* this the fit/clamp math under-measures by ~`(len-1)*spacing` and the label
|
|
138
|
+
* clips at the canvas edge. */
|
|
139
|
+
export function labelWidth(text: string, letterSpacing: number): number {
|
|
140
|
+
const spacing =
|
|
141
|
+
letterSpacing > 0 ? Math.max(0, text.length - 1) * letterSpacing : 0;
|
|
142
|
+
return measureLegendText(text, FONT) + spacing + 2 * PADX;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Wrap a multi-word name into balanced lines, biased to wrap READILY — water
|
|
146
|
+
* names ("North Pacific Ocean") read better stacked, and a narrower footprint
|
|
147
|
+
* is far likelier to clear surrounding land (the hard rule below). Of every
|
|
148
|
+
* contiguous split into ≤`maxLines`, picks the one minimising the widest line
|
|
149
|
+
* (so it shrinks horizontally whenever a break helps); ties break to fewer
|
|
150
|
+
* lines, then top-heavy ("North Pacific" / "Ocean", not "North" / "Pacific
|
|
151
|
+
* Ocean"). Single-word names pass through unwrapped. */
|
|
152
|
+
export function wrapLabel(text: string, letterSpacing: number): string[] {
|
|
153
|
+
const words = text.split(/\s+/).filter(Boolean);
|
|
154
|
+
if (words.length <= 1) return [text];
|
|
155
|
+
const maxLines = words.length >= 4 ? 3 : 2;
|
|
156
|
+
const n = words.length;
|
|
157
|
+
type Split = { lines: string[]; cost: number; head: number };
|
|
158
|
+
let best: Split | null = null;
|
|
159
|
+
for (let mask = 0; mask < 1 << (n - 1); mask++) {
|
|
160
|
+
const lines: string[] = [];
|
|
161
|
+
let cur = [words[0]!];
|
|
162
|
+
for (let i = 1; i < n; i++) {
|
|
163
|
+
if (mask & (1 << (i - 1))) {
|
|
164
|
+
lines.push(cur.join(' '));
|
|
165
|
+
cur = [words[i]!];
|
|
166
|
+
} else cur.push(words[i]!);
|
|
167
|
+
}
|
|
168
|
+
lines.push(cur.join(' '));
|
|
169
|
+
if (lines.length > maxLines) continue;
|
|
170
|
+
const cost = Math.round(
|
|
171
|
+
Math.max(...lines.map((l) => labelWidth(l, letterSpacing)))
|
|
172
|
+
);
|
|
173
|
+
const head = labelWidth(lines[0]!, letterSpacing);
|
|
174
|
+
if (
|
|
175
|
+
!best ||
|
|
176
|
+
cost < best.cost ||
|
|
177
|
+
(cost === best.cost && lines.length < best.lines.length) ||
|
|
178
|
+
(cost === best.cost &&
|
|
179
|
+
lines.length === best.lines.length &&
|
|
180
|
+
head > best.head)
|
|
181
|
+
)
|
|
182
|
+
best = { lines, cost, head };
|
|
183
|
+
}
|
|
184
|
+
return best?.lines ?? [text];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function rectAround(
|
|
188
|
+
cx: number,
|
|
189
|
+
cy: number,
|
|
190
|
+
lines: readonly string[],
|
|
191
|
+
letterSpacing: number
|
|
192
|
+
): LabelRect {
|
|
193
|
+
const w = Math.max(...lines.map((l) => labelWidth(l, letterSpacing)));
|
|
194
|
+
const h = (lines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY;
|
|
195
|
+
return { x: cx - w / 2, y: cy - h / 2, w, h };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function rectFits(r: LabelRect, width: number, height: number): boolean {
|
|
199
|
+
return r.x >= 0 && r.y >= 0 && r.x + r.w <= width && r.y + r.h <= height;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function overlapsPadded(a: LabelRect, b: LabelRect, pad: number): boolean {
|
|
203
|
+
return (
|
|
204
|
+
a.x - pad < b.x + b.w &&
|
|
205
|
+
a.x + a.w + pad > b.x &&
|
|
206
|
+
a.y - pad < b.y + b.h &&
|
|
207
|
+
a.y + a.h + pad > b.y
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** Place the orientation backdrop. Returns committed labels in priority order;
|
|
212
|
+
* caller pushes them onto `labels` LAST so they never displace data. */
|
|
213
|
+
export function placeContextLabels(args: ContextLabelArgs): PlacedLabel[] {
|
|
214
|
+
const {
|
|
215
|
+
projection,
|
|
216
|
+
dLonSpan,
|
|
217
|
+
dLatSpan,
|
|
218
|
+
width,
|
|
219
|
+
height,
|
|
220
|
+
waterBodies,
|
|
221
|
+
countries,
|
|
222
|
+
palette,
|
|
223
|
+
project,
|
|
224
|
+
collides,
|
|
225
|
+
overLand,
|
|
226
|
+
} = args;
|
|
227
|
+
|
|
228
|
+
// albers-usa is supported: the CONUS conic projects CONUS-area water (Gulf of
|
|
229
|
+
// America, the Pacific/Atlantic margins) correctly, and the viewport-visibility
|
|
230
|
+
// check below drops the off-frame anchors (Gulf of Alaska, mid-Pacific) that the
|
|
231
|
+
// AK/HI inset relocation would otherwise mislabel. The caller additionally feeds
|
|
232
|
+
// the AK/HI inset frames into `collides` so a label never lands on an inset box.
|
|
233
|
+
// (Supersedes the original blanket albers-usa disable — the US map is the
|
|
234
|
+
// flagship orientation case.)
|
|
235
|
+
void projection;
|
|
236
|
+
|
|
237
|
+
const band = tierBand(Math.max(dLonSpan, dLatSpan));
|
|
238
|
+
const budget = labelBudget(width, height, band);
|
|
239
|
+
if (budget <= 0) return [];
|
|
240
|
+
|
|
241
|
+
// Subordinate cartographic colours (palette-derived, no hex; resvg-safe via
|
|
242
|
+
// pre-computed mix()). Water = muted blue-gray italic; country = muted gray.
|
|
243
|
+
const waterColor = mix(palette.colors.blue, palette.textMuted, 50);
|
|
244
|
+
const countryColor = palette.textMuted;
|
|
245
|
+
const haloColor = palette.bg;
|
|
246
|
+
|
|
247
|
+
type Candidate = {
|
|
248
|
+
text: string;
|
|
249
|
+
lines: string[];
|
|
250
|
+
cx: number;
|
|
251
|
+
cy: number;
|
|
252
|
+
italic: boolean;
|
|
253
|
+
letterSpacing: number;
|
|
254
|
+
color: string;
|
|
255
|
+
sort: number; // priority key (lower first)
|
|
256
|
+
};
|
|
257
|
+
const candidates: Candidate[] = [];
|
|
258
|
+
|
|
259
|
+
// -- Water candidates (priority core: oceans → seas → minor water) --
|
|
260
|
+
const center: [number, number] = [width / 2, height / 2];
|
|
261
|
+
for (const e of waterBodies?.entries ?? []) {
|
|
262
|
+
const [lat, lon, name, tier, kind, alt] = e;
|
|
263
|
+
if (!waterEligible(tier, kind, band)) continue;
|
|
264
|
+
// Wrap eagerly (Decision: water names stack readily) so the clamp/fit math
|
|
265
|
+
// below sees the real, narrower wrapped footprint, not the one-line width.
|
|
266
|
+
const wlines = wrapLabel(name, WATER_LETTER_SPACING);
|
|
267
|
+
// Multi-anchor (Decision 5 / ADR-4): of the anchors that project inside the
|
|
268
|
+
// viewport, pick the one nearest the viewport centre.
|
|
269
|
+
const anchorsLngLat: Array<[number, number]> = [[lon, lat]];
|
|
270
|
+
for (const a of alt ?? []) anchorsLngLat.push([a[1], a[0]]);
|
|
271
|
+
let best: [number, number] | null = null;
|
|
272
|
+
let bestD = Infinity;
|
|
273
|
+
let nearestProj: [number, number] | null = null; // best finite proj (any side)
|
|
274
|
+
let nearestProjD = Infinity;
|
|
275
|
+
for (const [aLon, aLat] of anchorsLngLat) {
|
|
276
|
+
const p = project(aLon, aLat);
|
|
277
|
+
if (!p || !Number.isFinite(p[0]) || !Number.isFinite(p[1])) continue;
|
|
278
|
+
const d = (p[0] - center[0]) ** 2 + (p[1] - center[1]) ** 2;
|
|
279
|
+
if (d < nearestProjD) {
|
|
280
|
+
nearestProjD = d;
|
|
281
|
+
nearestProj = p;
|
|
282
|
+
}
|
|
283
|
+
if (!insideViewport(p, width, height)) continue;
|
|
284
|
+
if (d < bestD) {
|
|
285
|
+
bestD = d;
|
|
286
|
+
best = p;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Oceans (tier 0) are large enough that a frame-edge label still reads
|
|
290
|
+
// correctly, so when their anchor falls off-screen on a zoomed-in view
|
|
291
|
+
// (e.g. the mid-Atlantic/Pacific centroid on a US map) we CLAMP it to the
|
|
292
|
+
// viewport margin rather than drop it — the standard cartographic "ocean
|
|
293
|
+
// name hugs the edge" behaviour. Smaller basins keep the strict drop-if-
|
|
294
|
+
// off-screen rule (AC10) to avoid mislabelling an adjacent basin.
|
|
295
|
+
if (!best && tier === 0 && nearestProj) {
|
|
296
|
+
// Only clamp an ocean ADJACENT to the frame: if its centroid overshoots
|
|
297
|
+
// the viewport by more than ~half a dimension it's a distant ocean (e.g.
|
|
298
|
+
// the South Atlantic / Arctic relative to a US view) and edge-clamping it
|
|
299
|
+
// would mislabel that margin — drop instead. The surviving oceans are the
|
|
300
|
+
// ones the frame actually borders (Pacific to the west, Atlantic east).
|
|
301
|
+
const overX = Math.max(0, -nearestProj[0], nearestProj[0] - width);
|
|
302
|
+
const overY = Math.max(0, -nearestProj[1], nearestProj[1] - height);
|
|
303
|
+
if (
|
|
304
|
+
overX <= width * EDGE_CLAMP_OVERSHOOT &&
|
|
305
|
+
overY <= height * EDGE_CLAMP_OVERSHOOT
|
|
306
|
+
) {
|
|
307
|
+
// Clamp the CENTRE inward by half the label so the whole (centre-
|
|
308
|
+
// anchored) rect stays on-canvas — clamping to the bare margin would
|
|
309
|
+
// overflow a wide name like "North Atlantic Ocean" off the edge.
|
|
310
|
+
// letter-spacing IS counted (labelWidth) so the clamp matches render.
|
|
311
|
+
const halfW =
|
|
312
|
+
Math.max(...wlines.map((l) => labelWidth(l, WATER_LETTER_SPACING))) /
|
|
313
|
+
2;
|
|
314
|
+
const halfH = ((wlines.length - 1) * LINE_HEIGHT + FONT + 2 * PADY) / 2;
|
|
315
|
+
const m = EDGE_CLAMP_MARGIN;
|
|
316
|
+
best = [
|
|
317
|
+
Math.min(Math.max(nearestProj[0], halfW + m), width - halfW - m),
|
|
318
|
+
Math.min(Math.max(nearestProj[1], halfH + m), height - halfH - m),
|
|
319
|
+
];
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (!best) continue;
|
|
323
|
+
candidates.push({
|
|
324
|
+
text: name,
|
|
325
|
+
lines: wlines,
|
|
326
|
+
cx: best[0],
|
|
327
|
+
cy: best[1],
|
|
328
|
+
italic: true,
|
|
329
|
+
letterSpacing: WATER_LETTER_SPACING,
|
|
330
|
+
color: waterColor,
|
|
331
|
+
// Water before any country (×1000), then by tier, then kind, then name.
|
|
332
|
+
sort: tier * 10 + KIND_ORDER[kind],
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// -- Country candidates (unreferenced; biggest projected area first) --
|
|
337
|
+
// Rank by screen bbox area; keep only those whose name fits the footprint
|
|
338
|
+
// (width-fit, like region-labels) and whose anchor projects inside the view.
|
|
339
|
+
const ranked = countries
|
|
340
|
+
.map((c) => {
|
|
341
|
+
const [x0, y0, x1, y1] = c.bbox;
|
|
342
|
+
const w = x1 - x0;
|
|
343
|
+
const h = y1 - y0;
|
|
344
|
+
return { c, w, h, area: w * h };
|
|
345
|
+
})
|
|
346
|
+
.filter((r) => Number.isFinite(r.area) && r.area > 0)
|
|
347
|
+
.sort((a, b) => b.area - a.area);
|
|
348
|
+
let ci = 0;
|
|
349
|
+
for (const r of ranked) {
|
|
350
|
+
const { c, w, h } = r;
|
|
351
|
+
// F2: an antimeridian-crossing / global-smear country yields a near-full-
|
|
352
|
+
// canvas bbox while its real landmass is split — the `path.centroid` anchor
|
|
353
|
+
// is then unreliable (mid-map, wrong basin). Drop such over-wide candidates
|
|
354
|
+
// rather than spend a top-priority slot on a mispositioned name.
|
|
355
|
+
if (w > width * 0.66 || h > height * 0.66) continue;
|
|
356
|
+
if (!insideViewport(c.anchor, width, height)) continue;
|
|
357
|
+
// Always the full country name — never an ISO abbreviation. If the name
|
|
358
|
+
// doesn't fit the footprint, drop the label rather than abbreviate.
|
|
359
|
+
const text = c.name;
|
|
360
|
+
const tw = labelWidth(text, 0);
|
|
361
|
+
// Approximate fit (Decision 4): name fits inside the footprint bbox. NOT
|
|
362
|
+
// true point-in-polygon — cartographic labels routinely overrun coastlines.
|
|
363
|
+
if (tw > w || FONT + 2 * PADY > h) continue;
|
|
364
|
+
candidates.push({
|
|
365
|
+
text,
|
|
366
|
+
lines: [text],
|
|
367
|
+
cx: c.anchor[0],
|
|
368
|
+
cy: c.anchor[1],
|
|
369
|
+
italic: false,
|
|
370
|
+
letterSpacing: 0,
|
|
371
|
+
color: countryColor,
|
|
372
|
+
// Always after every water body (+1e6); larger area = earlier.
|
|
373
|
+
sort: 1_000_000 + ci++,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// -- Commit dead-last, highest-priority-first, into leftover space only --
|
|
378
|
+
candidates.sort((a, b) => a.sort - b.sort);
|
|
379
|
+
const placed: PlacedLabel[] = [];
|
|
380
|
+
const placedRects: LabelRect[] = [];
|
|
381
|
+
for (const cand of candidates) {
|
|
382
|
+
if (placed.length >= budget) break;
|
|
383
|
+
const rect = rectAround(cand.cx, cand.cy, cand.lines, cand.letterSpacing);
|
|
384
|
+
if (!rectFits(rect, width, height)) continue;
|
|
385
|
+
// Water labels must sit over OPEN WATER and NEVER touch land — sample a grid
|
|
386
|
+
// over every wrapped line (each line's own horizontal extent at five points);
|
|
387
|
+
// drop the whole label if ANY sample hits land (Decision: optional orientation
|
|
388
|
+
// aids, so exclude rather than misplace over a coastline). Country labels are
|
|
389
|
+
// exempt — they belong on their country.
|
|
390
|
+
if (cand.italic && overLand) {
|
|
391
|
+
const inset = 2;
|
|
392
|
+
const top = cand.cy - ((cand.lines.length - 1) / 2) * LINE_HEIGHT;
|
|
393
|
+
const touchesLand = cand.lines.some((line, li) => {
|
|
394
|
+
const lw = labelWidth(line, cand.letterSpacing);
|
|
395
|
+
const x0 = cand.cx - lw / 2 + inset;
|
|
396
|
+
const x1 = cand.cx + lw / 2 - inset;
|
|
397
|
+
const xs = [x0, (x0 + cand.cx) / 2, cand.cx, (cand.cx + x1) / 2, x1];
|
|
398
|
+
const base = top + li * LINE_HEIGHT;
|
|
399
|
+
// Sample the glyph body top→baseline (text rises above the baseline) so a
|
|
400
|
+
// label whose ascenders clip a coastline is rejected, not just one whose
|
|
401
|
+
// baseline sits on land.
|
|
402
|
+
return [base, base - FONT * 0.4, base - FONT * 0.8].some((y) =>
|
|
403
|
+
xs.some((x) => overLand(x, y))
|
|
404
|
+
);
|
|
405
|
+
});
|
|
406
|
+
if (touchesLand) continue;
|
|
407
|
+
}
|
|
408
|
+
if (collides(rect)) continue;
|
|
409
|
+
if (placedRects.some((r) => overlapsPadded(rect, r, CONTEXT_PAD))) continue;
|
|
410
|
+
placedRects.push(rect);
|
|
411
|
+
placed.push({
|
|
412
|
+
x: cand.cx,
|
|
413
|
+
y: cand.cy,
|
|
414
|
+
text: cand.text,
|
|
415
|
+
anchor: 'middle',
|
|
416
|
+
color: cand.color,
|
|
417
|
+
// No halo: the bg-coloured outline reads as a ghost box behind the text
|
|
418
|
+
// over the tinted water/land. Context labels are muted enough to sit
|
|
419
|
+
// cleanly on the basemap without one.
|
|
420
|
+
halo: false,
|
|
421
|
+
haloColor,
|
|
422
|
+
italic: cand.italic,
|
|
423
|
+
letterSpacing: cand.letterSpacing,
|
|
424
|
+
...(cand.lines.length > 1 ? { lines: cand.lines } : {}),
|
|
425
|
+
lineNumber: 0,
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
return placed;
|
|
429
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"assets":{"gazetteer.json":{"bytes":130706,"gzBytes":56251,"sha256":"8cefc36db73c9337429e66c94339a385656de3ec22a67487b0a146aa37dd632a"},"lakes.json":{"bytes":6315,"gzBytes":1487,"sha256":"5840ffd49b8dbf30183a9534a72adf80b6e77ceec224665393fa94e956220323"},"region-names.json":{"bytes":11667,"gzBytes":2235,"sha256":"059662d30b6ee8572c5943096905e05218e5f337e6973a9d43d6b41b7313a9ac"},"rivers.json":{"bytes":6707,"gzBytes":2158,"sha256":"3912508469099b1c37360c5505ea033c4ffa30ce95f7428e668e9d824cb81407"},"us-states.json":{"bytes":23313,"gzBytes":7413,"sha256":"0fe3a8937bc7566192662439f29a7866e8823d687290bcb003433ad5edd86567"},"world-coarse.json":{"bytes":55426,"gzBytes":18390,"sha256":"9ed5a15d775c0a303003dcf096a209dd433383ea52e18014885d482c38bc01a4"},"world-detail.json":{"bytes":163555,"gzBytes":46762,"sha256":"e99dddc3fccd96465ad4e5cd7bcca839095672e9c595d78276d510c44db84fd7"}},"counts":{"countries":175,"gazetteerAliases":8,"gazetteerCities":2118,"usStates":56},"generatedBy":"scripts/build-map-data.mjs","sourceHashes":{"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_lakes.json":{"bytes":27711,"sha256":"6f315b60488e0cf5da9c360e3ce593babf64c2f44cc21e2820c536f7a2aff606"},"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_rivers_lake_centerlines.json":{"bytes":54146,"sha256":"959e13128e4eb5a6ee530b8270c5017bcee9149ce48a97f6fe7fee1fce600b5d"},"https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/states-10m.json":{"bytes":114554,"sha256":"d76b391ccfa8bff601d51e3e3da5d43a89fa46cd5caca72ce731b383be5596d0"},"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json":{"bytes":107761,"sha256":"2516c915867c7baf18ddec727aec46c315541a07cfb3d79a6559b05d5e94eee8"},"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json":{"bytes":756420,"sha256":"04342cdc1e3016bcd7db1630de95684d67b79fe3c8c460321e87aef469502394"},"https://download.geonames.org/export/dump/cities5000.zip":{"bytes":5546862,"sha256":"e898c1399b05bd521540c5fa56ac3db44b4b2029d432b5f40a1e45f66d5a0929"}},"sources":{"geonames":{"citiesUrl":"https://download.geonames.org/export/dump/cities5000.zip","license":"CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/","modificationDateRange":"2006-01-17..2026-05-25 (filtered subset)"},"lakes":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_lakes.json","version":"natural-earth 110m (martynafford snapshot)"},"rivers":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_rivers_lake_centerlines.json","version":"natural-earth 110m (martynafford snapshot)"},"usAtlas":{"url":"https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/states-10m.json","version":"3.0.1"},"worldCoarse":{"url":"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json","version":"2.0.2"},"worldDetail":{"url":"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json","version":"2.0.2"}},"tooling":{"mapshaper":"0.7.22"}}
|
|
1
|
+
{"assets":{"gazetteer.json":{"bytes":130706,"gzBytes":56251,"sha256":"8cefc36db73c9337429e66c94339a385656de3ec22a67487b0a146aa37dd632a"},"lakes.json":{"bytes":6315,"gzBytes":1487,"sha256":"5840ffd49b8dbf30183a9534a72adf80b6e77ceec224665393fa94e956220323"},"mountain-ranges.json":{"bytes":30081,"gzBytes":8971,"sha256":"b0eb87e6b3c514b882245299fbe698b3caaa3f40494e3d220f973caf6a12a16c"},"region-names.json":{"bytes":11667,"gzBytes":2235,"sha256":"059662d30b6ee8572c5943096905e05218e5f337e6973a9d43d6b41b7313a9ac"},"rivers.json":{"bytes":6707,"gzBytes":2158,"sha256":"3912508469099b1c37360c5505ea033c4ffa30ce95f7428e668e9d824cb81407"},"us-states.json":{"bytes":23313,"gzBytes":7413,"sha256":"0fe3a8937bc7566192662439f29a7866e8823d687290bcb003433ad5edd86567"},"world-coarse.json":{"bytes":55426,"gzBytes":18390,"sha256":"9ed5a15d775c0a303003dcf096a209dd433383ea52e18014885d482c38bc01a4"},"world-detail.json":{"bytes":163555,"gzBytes":46762,"sha256":"e99dddc3fccd96465ad4e5cd7bcca839095672e9c595d78276d510c44db84fd7"}},"counts":{"countries":175,"gazetteerAliases":8,"gazetteerCities":2118,"mountainRanges":114,"usStates":56},"generatedBy":"scripts/build-map-data.mjs","sourceHashes":{"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_lakes.json":{"bytes":27711,"sha256":"6f315b60488e0cf5da9c360e3ce593babf64c2f44cc21e2820c536f7a2aff606"},"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_rivers_lake_centerlines.json":{"bytes":54146,"sha256":"959e13128e4eb5a6ee530b8270c5017bcee9149ce48a97f6fe7fee1fce600b5d"},"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_50m_geography_regions_polys.geojson":{"bytes":4305815,"sha256":"33396643d8f0eed408e80bf5ca43dcdb7993f790fdc4eadae311660f8b91fe76"},"https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/states-10m.json":{"bytes":114554,"sha256":"d76b391ccfa8bff601d51e3e3da5d43a89fa46cd5caca72ce731b383be5596d0"},"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json":{"bytes":107761,"sha256":"2516c915867c7baf18ddec727aec46c315541a07cfb3d79a6559b05d5e94eee8"},"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json":{"bytes":756420,"sha256":"04342cdc1e3016bcd7db1630de95684d67b79fe3c8c460321e87aef469502394"},"https://download.geonames.org/export/dump/cities5000.zip":{"bytes":5546862,"sha256":"e898c1399b05bd521540c5fa56ac3db44b4b2029d432b5f40a1e45f66d5a0929"}},"sources":{"geonames":{"citiesUrl":"https://download.geonames.org/export/dump/cities5000.zip","license":"CC BY 4.0 — https://creativecommons.org/licenses/by/4.0/","modificationDateRange":"2006-01-17..2026-05-25 (filtered subset)"},"lakes":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_lakes.json","version":"natural-earth 110m (martynafford snapshot)"},"mountainRanges":{"license":"public domain (Natural Earth)","url":"https://cdn.jsdelivr.net/gh/nvkelso/natural-earth-vector@master/geojson/ne_50m_geography_regions_polys.geojson","version":"natural-earth 50m (nvkelso vector snapshot)"},"rivers":{"url":"https://cdn.jsdelivr.net/gh/martynafford/natural-earth-geojson@master/110m/physical/ne_110m_rivers_lake_centerlines.json","version":"natural-earth 110m (martynafford snapshot)"},"usAtlas":{"url":"https://cdn.jsdelivr.net/npm/us-atlas@3.0.1/states-10m.json","version":"3.0.1"},"worldCoarse":{"url":"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json","version":"2.0.2"},"worldDetail":{"url":"https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-50m.json","version":"2.0.2"}},"tooling":{"mapshaper":"0.7.22"}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"arcs":[[[9125,1356],[-84,39],[66,69],[57,117],[30,184],[-6,121],[67,162],[10,156],[-22,75],[-77,32],[-62,132],[-60,290],[-23,404],[47,8],[24,-123],[10,-137],[87,-200],[16,-104],[86,-264],[21,-272],[-34,-242],[-32,-97],[-57,-301],[-64,-49]],[[5293,8032],[-56,-7],[-67,-62],[-81,19],[-55,-169],[-36,51],[6,80],[76,154],[91,55],[116,10],[6,-131]],[[7024,7736],[-4,0]],[[7020,7736],[-6,1]],[[7014,7737],[10,-1]],[[7014,7737],[6,-1]],[[7020,7736],[4,0]],[[7024,7736],[47,41],[211,31]],[[7282,7808],[61,36]],[[7343,7844],[135,-14],[52,23],[83,-22],[-29,-106],[-36,47],[-112,-15],[-46,-87],[-82,11],[-67,-26],[-146,-141],[-120,-10],[14,238],[25,-5]],[[6530,8448],[-45,111],[26,169],[16,326],[26,229],[2,146],[52,35],[-26,-374],[26,-289],[-49,-171],[-28,-182]],[[5954,7918],[69,3],[144,-139],[54,-13],[42,-205],[-61,83],[-139,72],[-55,81],[-54,118]],[[7382,6498],[-132,78],[-93,154]],[[7157,6730],[-104,194],[19,109],[48,-22]],[[7120,7011],[6,-10]],[[7126,7001],[183,-322],[103,0],[197,-31],[15,-62],[-43,-80],[-63,-21],[-81,23],[-55,-10]],[[2856,5203],[3,-9]],[[2859,5194],[11,-5]],[[2870,5189],[10,4]],[[2880,5193],[42,-3]],[[2922,5190],[-79,-56]],[[2843,5134],[-58,-119]],[[2785,5015],[-18,-43]],[[2767,4972],[-10,-113]],[[2757,4859],[-51,-167]],[[2706,4692],[-7,-116]],[[2699,4576],[-5,-37]],[[2694,4539],[-81,-127],[-23,-155],[5,-255],[52,-138],[6,-217]],[[2653,3647],[38,-110]],[[2691,3537],[50,-106]],[[2741,3431],[20,-32]],[[2761,3399],[83,-110]],[[2844,3289],[61,-146]],[[2905,3143],[57,-142]],[[2962,3001],[35,-43]],[[2997,2958],[3,-22]],[[3000,2936],[8,-152]],[[3008,2784],[-42,-476],[-29,-104],[14,-84],[-45,-84],[-28,-184],[-29,-63],[-23,-234],[20,-46],[-62,-443],[3,-226],[-48,-402],[11,-192],[34,-58],[-40,-66],[-42,63],[-20,169],[-2,212],[50,440],[0,135],[22,218],[14,255],[-7,350],[35,346],[-2,129],[13,224],[-6,241],[-38,94],[-69,96],[-58,116],[-31,190],[-62,326],[-25,172],[-6,100],[14,160],[-24,13],[10,166],[55,134],[24,140]],[[2589,4611],[9,56]],[[2598,4667],[15,135]],[[2613,4802],[-3,236],[13,12]],[[2623,5050],[12,-46]],[[2635,5004],[12,-35]],[[2647,4969],[8,6]],[[2655,4975],[47,119],[-9,79]],[[2693,5173],[-4,78]],[[2689,5251],[6,1]],[[2695,5252],[35,2]],[[2730,5254],[13,-10]],[[2743,5244],[5,-7]],[[2748,5237],[62,22]],[[2810,5259],[29,2]],[[2839,5261],[17,-58]],[[1218,9081],[36,-49],[46,-96],[6,-99],[189,-417],[82,-303],[63,-30],[14,-80],[53,-27],[78,-243],[19,-167],[10,-328],[-30,-79],[-42,-11],[-29,242],[-40,71],[-39,-19],[-44,-102],[5,222],[-26,111],[-109,148],[-1,147],[-18,168]],[[1441,8140],[12,38]],[[1453,8178],[0,2]],[[1453,8180],[-66,278],[-60,87],[-52,169]],[[1275,8714],[-16,33]],[[1259,8747],[-15,22]],[[1244,8769],[-64,147],[-20,155]],[[1160,9071],[35,-18]],[[1195,9053],[18,16]],[[1213,9069],[5,12]],[[6011,5282],[6,-200],[35,-29],[-12,-233],[-71,-82],[-37,8],[-28,98],[-29,-14],[-12,179],[-27,123],[18,106],[30,22],[19,152],[42,77],[8,131],[-15,91],[33,29],[11,-108],[35,-121],[-6,-229]],[[6447,6479],[-62,54],[-38,97],[-71,265],[-63,103],[-22,159],[24,40],[121,-311],[70,-208],[78,-74],[0,-75],[-37,-50]],[[7426,8356],[1,-23]],[[7427,8333],[5,-7]],[[7432,8326],[97,-162],[83,-94],[119,-98],[42,-65],[-3,-64],[-67,4],[-34,-65],[-58,87],[-110,24],[-30,59],[-49,169],[-118,59],[-34,135],[-36,61],[41,120],[98,-22],[53,-118]],[[8477,8408],[-5,-26]],[[8472,8382],[-26,-80],[10,-83],[-30,-81],[9,-114],[-36,-111],[-75,-129],[-57,1],[16,235],[50,258],[26,262],[75,52],[47,-29],[-4,-155]],[[8522,8890],[66,-43],[96,27],[83,-19],[83,24],[18,-59],[-112,-150],[-85,-15],[-27,35],[-162,10],[-49,144],[89,46]],[[7929,5816],[81,-237],[22,-177],[-11,-134],[-31,-55],[-26,45],[-14,218],[-21,73],[-12,143],[-42,132],[-28,-11],[-13,92],[13,94],[36,79],[56,-93],[-22,-95],[12,-74]],[[7382,6498],[10,-52],[-153,118],[-83,121],[1,45]],[[7157,6730],[33,-37],[192,-195]],[[7074,7357],[-13,-8]],[[7061,7349],[-48,-22]],[[7013,7327],[-36,-7]],[[6977,7320],[-9,-5]],[[6968,7315],[-9,-9]],[[6959,7306],[-11,-11]],[[6948,7295],[-13,5]],[[6935,7300],[-13,150],[30,34],[100,-24],[22,-103]],[[7037,7286],[9,-29]],[[7046,7257],[5,-107],[-36,-93]],[[7015,7057],[-13,4]],[[7002,7061],[-2,0]],[[7000,7061],[-3,0]],[[6997,7061],[-2,0]],[[6995,7061],[-5,-2]],[[6990,7059],[-52,36],[-61,-21],[-77,26],[-10,98],[20,56],[107,65],[18,-19]],[[6935,7300],[13,-5]],[[6948,7295],[11,11]],[[6959,7306],[9,9]],[[6968,7315],[9,5]],[[6977,7320],[36,7]],[[7013,7327],[24,-41]],[[7126,7001],[-6,10]],[[7120,7011],[-48,94],[-26,152]],[[7046,7257],[-9,29]],[[7037,7286],[24,63]],[[7061,7349],[13,8]],[[7074,7357],[53,-135]],[[7127,7222],[21,-21]],[[7148,7201],[25,-138],[-47,-62]],[[7399,7326],[47,2]],[[7446,7328],[9,0]],[[7455,7328],[49,2],[53,-74],[80,-14],[53,-85],[-299,26],[-17,-16],[-180,-21],[-46,55]],[[7148,7201],[-21,21]],[[7127,7222],[43,63],[47,-45],[62,33],[75,70],[45,-17]],[[4955,7070],[-28,-32]],[[4927,7038],[-60,-68]],[[4867,6970],[-34,-47]],[[4833,6923],[-52,-76],[-51,-24],[-40,-79],[-65,-80],[-71,-62],[-24,38],[37,135],[20,143],[48,60],[14,74],[72,89],[67,-6],[96,113],[148,42],[46,-15],[51,36],[9,-249],[-39,-2],[-62,62],[-82,-52]],[[2949,8161],[-48,-135],[-54,-32],[-73,-219],[-13,-77],[-167,-236],[-87,-256],[-104,-166],[-87,-97],[-30,-2],[-18,106],[16,184],[-15,82],[31,48],[97,66],[55,-15],[78,174],[-19,124],[44,101],[55,0],[90,-67],[11,181],[157,287],[75,43],[6,-94]],[[574,9673],[-252,-33],[-245,33],[-77,97],[131,151],[149,78],[141,-69],[254,-26],[174,-91],[-37,-53],[-238,-87]],[[1305,8333],[-44,-88]],[[1261,8245],[-57,102],[-67,51],[-34,164],[-41,55],[-35,171],[-65,105],[-101,243],[48,36],[55,-140],[77,-124],[42,-136],[41,-31],[19,-142],[67,-147],[95,-119]],[[1369,8341],[-9,-48]],[[1360,8293],[0,-8]],[[1360,8285],[-1,-103]],[[1359,8182],[-1,-20]],[[1358,8162],[-24,-82],[-34,-349],[24,-161]],[[1324,7570],[-4,-15]],[[1320,7555],[-14,-10]],[[1306,7545],[-6,-13]],[[1300,7532],[-16,90],[-8,159],[-13,73],[11,122]],[[1274,7976],[-3,74]],[[1271,8050],[21,95],[-31,100]],[[1305,8333],[67,58]],[[1372,8391],[-3,-50]],[[556,9438],[65,-12],[41,-107],[-50,-35],[-123,47],[-49,-144],[-96,13],[4,95],[154,153],[54,-10]],[[4927,7038],[-60,-68]],[[4867,6970],[-34,-47]],[[4833,6923],[-43,9],[138,181],[27,-43]],[[4955,7070],[-28,-32]],[[4754,6948],[-75,-100],[2,102],[73,-2]],[[5724,1936],[-87,-206],[-58,7],[-47,90],[45,85],[63,19],[-6,64],[30,116],[32,17],[36,158],[-22,172],[58,-91],[0,-132],[21,-63],[-65,-236]],[[5234,4146],[0,-137],[17,-174],[33,-81],[-19,-79],[-27,122],[-10,133],[-79,228],[-8,98],[13,119],[51,-44],[29,-185]],[[5418,6143],[-8,-211],[-27,-30],[-59,53],[-12,82],[69,121],[8,85],[37,2],[-8,-102]],[[4987,6493],[12,-112],[55,-80],[48,-15],[-5,-129],[-30,-3],[-28,-80],[-59,78],[-9,125],[-50,-3],[38,206],[28,13]],[[5107,5734],[-47,176],[25,57],[49,-139],[-27,-94]],[[5693,3969],[-30,96],[35,36],[-5,-132]],[[8472,8382],[5,26]],[[8477,8408],[50,33],[47,-154],[63,-44],[25,-149],[-69,-55],[-48,184],[-56,39],[-17,120]],[[8726,7747],[-16,63],[67,181],[74,227],[64,207],[27,-6],[-11,-181],[-106,-321],[-52,-121],[-47,-49]],[[8903,9320],[-305,114],[-69,149],[24,304],[87,7],[-5,-211],[48,-164],[208,-103],[12,-96]],[[8009,5289],[-33,21],[-18,297],[35,-19],[23,-212],[-7,-87]],[[7846,7322],[-14,-80],[-49,-19],[-79,65],[-102,114],[-3,96],[34,37],[117,-56],[96,-157]],[[7642,8501],[-57,60]],[[7585,8561],[-63,117],[25,101],[68,-55],[50,23],[195,-247],[-7,-47],[-140,-3],[-71,51]],[[8276,8452],[-75,-85],[-45,-103],[-68,45],[19,116],[46,118],[41,155],[55,275],[61,36],[65,-79],[-1,-168],[-33,-130],[-65,-180]],[[8261,6828],[-34,-89],[-32,72],[-49,20],[-12,83],[82,-16],[45,-70]],[[8142,6231],[-36,-31],[-54,47],[-16,85],[25,75],[93,-38],[18,-39],[-30,-99]],[[7083,5196],[-11,5]],[[7072,5201],[-16,37],[-64,391],[-22,287],[30,84],[5,-174],[52,-422],[45,-111],[-19,-97]],[[7140,5257],[-30,38],[29,185],[5,148],[69,203],[4,54],[52,104],[60,-31],[-60,-196],[-51,-29],[-48,-127],[3,-189],[-33,-160]],[[7087,6157],[-87,-69],[-2,69],[65,38],[68,102],[23,-97],[-67,-43]],[[8253,6367],[-33,74],[18,120],[56,21],[-13,-179],[-28,-36]],[[7345,8093],[-6,-47],[-153,50],[-23,126],[67,-22],[60,-77],[55,-30]],[[7455,7328],[-9,0]],[[7446,7328],[-47,-2]],[[7399,7326],[-21,62],[76,71],[127,26],[-64,-144],[-62,-13]],[[6010,6161],[-17,4],[-97,335],[-15,135],[38,-17],[45,-154],[36,-168],[10,-135]],[[6125,5668],[-12,4],[-55,221],[-25,134],[29,19],[50,-205],[13,-173]],[[6362,7252],[80,30],[4,-50],[-67,-74],[-122,138],[10,57],[95,-101]],[[5059,8987],[-40,46],[4,220],[103,122],[78,147],[80,181],[168,175],[11,-82],[-87,-113],[-154,-342],[-119,-222],[-44,-132]],[[5451,8309],[42,0],[113,-142],[25,-82],[-6,-149],[-105,-45],[-44,34],[16,168],[-10,113],[-50,-53],[-76,91],[24,64],[71,1]],[[5314,7516],[-91,153],[27,42],[68,-147],[-4,-48]],[[4790,7759],[-9,23]],[[4781,7782],[20,15],[129,-53],[1,-66],[-118,53],[-23,28]],[[1789,6016],[9,-1]],[[1798,6015],[47,-56],[76,-22],[50,-75],[41,26],[46,-140],[16,-109],[-31,-37],[-42,23],[-168,189],[-37,69],[-7,133]],[[1271,8050],[3,-74]],[[1274,7976],[-16,-105],[-1,-123],[25,-103],[-11,-79],[22,-191],[-28,-4],[-40,174],[-4,195],[17,310],[33,0]],[[1299,7366],[64,-209],[-31,-18],[-53,188],[20,39]],[[1988,5958],[-39,37],[-18,204],[-17,91],[-46,62],[-33,120],[6,181],[54,59],[5,-142],[55,-253],[33,-359]],[[1306,7545],[14,10]],[[1324,7570],[60,-203],[1,-152],[-59,159],[-26,158]],[[1798,6015],[-9,1]],[[1789,6016],[-17,143],[-117,357],[-33,176],[4,131],[52,-4],[29,-169],[53,-180],[48,-217],[50,-86],[9,-76],[-22,-65],[-47,-11]],[[638,9235],[101,-57],[-13,-73],[-75,2],[-83,77],[70,51]],[[1251,9187],[-3,-23]],[[1248,9164],[0,-19]],[[1248,9145],[-5,-27]],[[1243,9118],[-8,-26]],[[1235,9092],[-17,-11]],[[1218,9081],[-5,-12]],[[1213,9069],[-18,-16]],[[1195,9053],[-35,18]],[[1160,9071],[-73,50],[-12,67],[-103,87],[-17,85]],[[955,9360],[-16,27]],[[939,9387],[-93,11],[34,155],[79,21],[160,-28],[85,-69],[53,-136],[-6,-154]],[[2574,3667],[15,-70]],[[2589,3597],[5,-30],[49,-192],[31,-81],[122,-225],[39,-102],[-45,-26],[-27,80],[-79,108],[-64,220],[-41,192],[-5,126]],[[2891,3047],[34,-104]],[[2925,2943],[1,-4]],[[2926,2939],[15,-103]],[[2941,2836],[-2,-196],[-30,81],[-18,326]],[[2653,3647],[19,8],[19,-118]],[[2691,3537],[16,-79],[34,-27]],[[2741,3431],[20,-32]],[[2761,3399],[83,-110]],[[2844,3289],[23,-23],[38,-123]],[[2905,3143],[36,-126],[21,-16]],[[2962,3001],[35,-43]],[[2997,2958],[3,-22]],[[3000,2936],[8,-152]],[[3008,2784],[-25,-225],[-35,80],[-7,197]],[[2941,2836],[-15,103]],[[2926,2939],[-1,4]],[[2925,2943],[-34,104]],[[2891,3047],[-55,146],[-96,87]],[[2740,3280],[-22,22]],[[2718,3302],[-9,18]],[[2709,3320],[-49,195]],[[2660,3515],[-11,35]],[[2649,3550],[-38,191]],[[2611,3741],[-11,127],[-31,70]],[[2569,3938],[-1,5]],[[2568,3943],[-10,58]],[[2558,4001],[1,78]],[[2559,4079],[7,59]],[[2566,4138],[4,76]],[[2570,4214],[29,-263],[41,-100],[13,-204]],[[2611,3741],[38,-191]],[[2649,3550],[11,-35]],[[2660,3515],[49,-195]],[[2709,3320],[9,-18]],[[2718,3302],[22,-22]],[[2740,3280],[24,-22],[-2,-118],[-86,153],[-39,107],[-48,197]],[[2589,3597],[-15,70]],[[2574,3667],[-16,11],[-34,171],[-9,155],[22,57]],[[2537,4061],[17,32]],[[2554,4093],[5,-14]],[[2559,4079],[-1,-78]],[[2558,4001],[10,-58]],[[2568,3943],[1,-5]],[[2569,3938],[42,-197]],[[2598,4667],[15,135]],[[2613,4802],[0,235],[10,13]],[[2623,5050],[12,-46]],[[2635,5004],[12,-35]],[[2647,4969],[-7,-52]],[[2640,4917],[-2,-80]],[[2638,4837],[2,-10]],[[2640,4827],[4,-18]],[[2644,4809],[0,-6]],[[2644,4803],[-2,-27]],[[2642,4776],[-3,-18]],[[2639,4758],[-19,-128]],[[2620,4630],[-8,-41]],[[2612,4589],[-11,-66]],[[2601,4523],[-18,-103]],[[2583,4420],[-21,-76]],[[2562,4344],[-3,-34]],[[2559,4310],[-10,-101]],[[2549,4209],[-8,121],[30,160],[18,121]],[[2554,4093],[-17,-32]],[[2537,4061],[12,148]],[[2549,4209],[10,101]],[[2559,4310],[3,34]],[[2562,4344],[21,76]],[[2583,4420],[18,103]],[[2612,4589],[8,41]],[[2620,4630],[19,128]],[[2639,4758],[3,18]],[[2642,4776],[2,27]],[[2644,4803],[0,6]],[[2644,4809],[-4,18]],[[2640,4827],[-2,10]],[[2638,4837],[2,80]],[[2640,4917],[15,58]],[[2655,4975],[35,2],[-25,-245],[-44,-216]],[[2621,4516],[-18,-77]],[[2603,4439],[-33,-225]],[[2570,4214],[-4,-76]],[[2566,4138],[-12,-45]],[[2870,5189],[10,4]],[[2880,5193],[42,-3]],[[2922,5190],[-50,-73],[-29,17]],[[2843,5134],[-58,-119]],[[2785,5015],[-18,-43]],[[2767,4972],[-10,-113]],[[2757,4859],[-51,-167]],[[2706,4692],[-7,-116]],[[2699,4576],[-5,-37]],[[2694,4539],[-91,-100]],[[2603,4439],[18,77]],[[2621,4516],[30,51],[33,274],[33,120],[-16,116],[14,84],[-22,12]],[[2693,5173],[-4,78]],[[2689,5251],[6,1]],[[2695,5252],[35,2]],[[2730,5254],[13,-10]],[[2743,5244],[5,-7]],[[2748,5237],[-22,-112],[9,-125],[51,109],[-11,71],[35,79]],[[2810,5259],[29,2]],[[2839,5261],[17,-58]],[[2856,5203],[3,-9]],[[2859,5194],[11,-5]],[[9713,724],[0,71],[41,85],[67,85],[53,36],[-114,-190],[-47,-87]],[[4568,6620],[11,125],[57,74],[77,48],[-24,-121],[-78,-52],[-43,-74]],[[5647,3002],[43,219],[39,-58],[-68,-108],[-14,-53]],[[3383,2072],[2,23]],[[3385,2095],[6,29]],[[3391,2124],[5,22]],[[3396,2146],[5,27]],[[3401,2173],[-16,39]],[[3385,2212],[8,52]],[[3393,2264],[10,13]],[[3403,2277],[-6,99]],[[3397,2376],[0,1]],[[3397,2377],[29,37]],[[3426,2414],[25,0]],[[3451,2414],[-18,-93],[-8,-209],[-42,-40]],[[3397,2377],[0,-1]],[[3397,2376],[6,-99]],[[3403,2277],[-10,-13]],[[3393,2264],[-8,-52]],[[3385,2212],[16,-39]],[[3401,2173],[-5,-27]],[[3396,2146],[-5,-22]],[[3391,2124],[-6,-29]],[[3385,2095],[-2,-23]],[[3383,2072],[-95,-67],[15,221],[-27,187],[30,117],[47,-34],[32,34],[24,-92],[-12,-61]],[[3451,2414],[-25,0]],[[3426,2414],[68,162],[92,121],[52,-67],[-187,-216]],[[3014,4913],[84,11],[35,-70],[13,-117],[-37,-75],[-23,13],[-46,-58],[-43,22],[-32,-61],[-51,37],[-37,80],[-5,76],[22,153],[38,58],[82,-69]],[[2160,5765],[38,-73],[-10,-122],[-20,-26],[-81,145],[24,70],[49,6]],[[1251,9187],[-3,-23]],[[1248,9164],[0,-19]],[[1248,9145],[-5,-27]],[[1243,9118],[-8,-26]],[[1235,9092],[-16,5],[-25,-36],[-110,77],[0,79],[-28,61],[-66,1],[-35,81]],[[955,9360],[-16,27]],[[939,9387],[87,80],[49,-130],[176,-150]],[[1453,8180],[0,-2]],[[1453,8178],[-12,-38]],[[1441,8140],[-83,22]],[[1358,8162],[1,20]],[[1359,8182],[1,103]],[[1360,8285],[0,8]],[[1360,8293],[9,48]],[[1369,8341],[3,50]],[[1372,8391],[-69,154],[-60,167],[1,57]],[[1244,8769],[15,-22]],[[1259,8747],[16,-33]],[[1275,8714],[119,-224],[62,-104],[36,-130],[-39,-76]],[[2989,9065],[20,-76],[-27,-1],[-21,75],[28,2]],[[9003,4010],[48,-31],[62,-132],[37,-148],[-113,134],[-97,136],[-55,37],[-88,27],[20,85],[80,-14],[106,-94]],[[7861,7990],[-80,-13],[-118,89],[-24,94],[37,55],[51,-3],[109,-95],[25,-127]],[[8625,7649],[-2,-61],[-74,-92],[-9,134],[42,81],[43,-62]],[[9428,8579],[11,190],[121,321],[62,39],[-112,-310],[-82,-240]],[[9687,9153],[-24,68],[152,132],[136,39],[48,-46],[-312,-193]],[[9368,9164],[-18,41],[119,168],[139,129],[13,-78],[-207,-190],[-46,-70]],[[9122,9427],[-208,156],[85,22],[102,-63],[21,-115]],[[7573,6060],[-34,71],[8,113],[32,-103],[-6,-81]],[[8097,7656],[-22,-67],[-149,56],[58,68],[113,-57]],[[7494,8436],[2,25]],[[7496,8461],[1,45]],[[7497,8506],[3,27]],[[7500,8533],[85,28]],[[7585,8561],[57,-60]],[[7642,8501],[-5,-58],[-143,-7]],[[7432,8326],[-5,7]],[[7427,8333],[-1,23]],[[7426,8356],[1,201],[64,84],[9,-108]],[[7500,8533],[-3,-27]],[[7497,8506],[-1,-45]],[[7496,8461],[-2,-25]],[[7494,8436],[-9,-57]],[[7485,8379],[13,-74]],[[7498,8305],[-66,21]],[[7498,8305],[-13,74]],[[7485,8379],[52,54],[56,7],[65,-69],[-116,-3],[-44,-63]],[[8164,7166],[-20,47],[-9,169],[14,72],[1,183],[44,-36],[-14,-170],[0,-205],[-16,-60]],[[8125,7111],[-36,48],[-3,262],[34,159],[18,-267],[-4,-197]],[[8134,7116],[-9,-5]],[[8125,7111],[9,5]],[[8134,7116],[15,-78],[-52,-95],[-76,3],[-39,46],[-50,-6],[-4,114],[101,-23],[96,34]],[[7989,6673],[7,-113],[-45,-43],[-21,-69],[-31,30],[-15,145],[105,50]],[[7809,5555],[93,-14],[-16,-52],[-54,-30],[-23,96]],[[7588,6207],[-23,81],[16,128],[58,36],[-51,-245]],[[7612,5723],[-48,302],[21,22],[29,-141],[-2,-183]],[[7072,5201],[11,-5]],[[7083,5196],[50,14],[-1,-64],[-55,-24],[-5,79]],[[7158,6075],[-49,-36],[-68,-12],[-2,74],[103,72],[16,-98]],[[6990,7059],[5,2]],[[6995,7061],[2,0]],[[6997,7061],[3,0]],[[7000,7061],[2,0]],[[7002,7061],[13,-4]],[[7015,7057],[-25,2]],[[7343,7844],[-61,-36]],[[7282,7808],[-68,40],[11,68],[118,-72]],[[7237,7972],[-33,-98],[-92,-39],[13,121],[81,63],[31,-47]],[[7584,6455],[-28,-110],[-68,16],[-5,53],[101,41]],[[6071,7633],[-4,28]],[[6067,7661],[76,13],[79,-156],[-25,-69],[-73,161],[-53,23]],[[6067,7661],[4,-28]],[[6071,7633],[-55,-93],[-82,11],[-89,63],[16,61],[104,-78],[82,19],[20,45]],[[6476,6647],[-42,42],[-1,94],[49,-86],[-6,-50]],[[5534,7801],[93,-1],[-18,-77],[-68,8],[-7,70]],[[5330,7932],[123,-62],[24,-113],[-57,-70],[-106,115],[-63,157],[79,-27]],[[4781,7782],[9,-23]],[[4790,7759],[-129,-24],[-16,54],[136,-7]],[[4761,7274],[-41,7],[1,50],[61,17],[-21,-74]],[[4762,7423],[-116,-108],[-2,43],[61,63],[57,2]],[[6264,5472],[-46,-32],[-12,97],[24,69],[54,64],[69,20],[2,-108],[-72,-61],[-19,-49]]],"objects":{"ranges":{"geometries":[{"arcs":[[0]],"id":"mtn-0","properties":{"cla":"Range/mtn","name":"GREAT DIVIDING RANGE"},"type":"Polygon"},{"arcs":[[1]],"id":"mtn-1","properties":{"cla":"Range/mtn","name":"ALPS"},"type":"Polygon"},{"arcs":[[[2,3,4]],[[5,6,7,8,9]]],"id":"mtn-2","properties":{"cla":"Range/mtn","name":"TIAN SHAN"},"type":"MultiPolygon"},{"arcs":[[10]],"id":"mtn-3","properties":{"cla":"Range/mtn","name":"URAL MOUNTAINS"},"type":"Polygon"},{"arcs":[[11]],"id":"mtn-4","properties":{"cla":"Range/mtn","name":"CAUCASUS MTS."},"type":"Polygon"},{"arcs":[[12,13,14,15]],"id":"mtn-5","properties":{"cla":"Range/mtn","name":"HIMALAYAS"},"type":"Polygon"},{"arcs":[[16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52]],"id":"mtn-6","properties":{"cla":"Range/mtn","name":"ANDES"},"type":"Polygon"},{"arcs":[[53,54,55,56,57,58,59,60,61,62]],"id":"mtn-7","properties":{"cla":"Range/mtn","name":"ROCKY MOUNTAINS"},"type":"Polygon"},{"arcs":[[63]],"id":"mtn-8","properties":{"cla":"Range/mtn","name":"ETHIOPIAN HIGHLANDS"},"type":"Polygon"},{"arcs":[[64]],"id":"mtn-9","properties":{"cla":"Range/mtn","name":"ZAGROS MOUNTAINS"},"type":"Polygon"},{"arcs":[[65,66,67]],"id":"mtn-10","properties":{"cla":"Range/mtn","name":"ALTAY MOUNTAINS"},"type":"Polygon"},{"arcs":[[68,69]],"id":"mtn-11","properties":{"cla":"Range/mtn","name":"GREATER KHINGAN RANGE"},"type":"Polygon"},{"arcs":[[70]],"id":"mtn-12","properties":{"cla":"Range/mtn","name":"STANOVOY RANGE"},"type":"Polygon"},{"arcs":[[71]],"id":"mtn-13","properties":{"cla":"Range/mtn","name":"CHAÎNE ANNAMITIQUE"},"type":"Polygon"},{"arcs":[[72,73]],"id":"mtn-14","properties":{"cla":"Range/mtn","name":"Siwalik Hills"},"type":"Polygon"},{"arcs":[[74,75,76,77,78,79,80,81]],"id":"mtn-15","properties":{"cla":"Range/mtn","name":"PAMIRS"},"type":"Polygon"},{"arcs":[[82,83,84,85,86,87,88,89,90,91,92,93,94,95]],"id":"mtn-16","properties":{"cla":"Range/mtn","name":"HINDU KUSH"},"type":"Polygon"},{"arcs":[[96,97,98,99,100,101,102,103]],"id":"mtn-17","properties":{"cla":"Range/mtn","name":"KARAKORAM RA."},"type":"Polygon"},{"arcs":[[104,105,106,107,108]],"id":"mtn-18","properties":{"cla":"Range/mtn","name":"KUNLUN MOUNTAINS"},"type":"Polygon"},{"arcs":[[109,110,111,112]],"id":"mtn-19","properties":{"cla":"Range/mtn","name":"ATLAS MOUNTAINS"},"type":"Polygon"},{"arcs":[[113]],"id":"mtn-20","properties":{"cla":"Range/mtn","name":"APPALACHIAN MTS."},"type":"Polygon"},{"arcs":[[114]],"id":"mtn-21","properties":{"cla":"Range/mtn","name":"BROOKS RANGE"},"type":"Polygon"},{"arcs":[[115,116]],"id":"mtn-22","properties":{"cla":"Range/mtn","name":"COAST MOUNTAINS"},"type":"Polygon"},{"arcs":[[117,118,119,120,121,122,123,124,125,126,127,-116,128,129]],"id":"mtn-23","properties":{"cla":"Range/mtn","name":"CASCADE RANGE"},"type":"Polygon"},{"arcs":[[130]],"id":"mtn-24","properties":{"cla":"Range/mtn","name":"ALASKA RANGE"},"type":"Polygon"},{"arcs":[[131,132,133,134]],"id":"mtn-25","properties":{"cla":"Range/mtn","name":"ATLAS SAHARIEN"},"type":"Polygon"},{"arcs":[[135]],"id":"mtn-26","properties":{"cla":"Range/mtn","name":"HAUT ATLAS"},"type":"Polygon"},{"arcs":[[136]],"id":"mtn-27","properties":{"cla":"Range/mtn","name":"DRAKENSBERG"},"type":"Polygon"},{"arcs":[[137]],"id":"mtn-28","properties":{"cla":"Range/mtn","name":"CRYSTAL MOUNTAINS"},"type":"Polygon"},{"arcs":[[138]],"id":"mtn-29","properties":{"cla":"Range/mtn","name":"TIBESTI MTS."},"type":"Polygon"},{"arcs":[[139]],"id":"mtn-30","properties":{"cla":"Range/mtn","name":"AHAGGAR MTS."},"type":"Polygon"},{"arcs":[[140]],"id":"mtn-31","properties":{"cla":"Range/mtn","name":"AÏR MTS."},"type":"Polygon"},{"arcs":[[141]],"id":"mtn-32","properties":{"cla":"Range/mtn","name":"MITUMBA MTS."},"type":"Polygon"},{"arcs":[[142,143]],"id":"mtn-33","properties":{"cla":"Range/mtn","name":"Lesser Khingan Range"},"type":"Polygon"},{"arcs":[[144]],"id":"mtn-34","properties":{"cla":"Range/mtn","name":"SIKHOTE-ALIN’ RANGE"},"type":"Polygon"},{"arcs":[[145]],"id":"mtn-35","properties":{"cla":"Range/mtn","name":"VERKHOYANSK RANGE"},"type":"Polygon"},{"arcs":[[146]],"id":"mtn-36","properties":{"cla":"Range/mtn","name":"Central Highlands"},"type":"Polygon"},{"arcs":[[147]],"id":"mtn-37","properties":{"cla":"Range/mtn","name":"QUILIAN MOUNTAINS"},"type":"Polygon"},{"arcs":[[148,149]],"id":"mtn-38","properties":{"cla":"Range/mtn","name":"EASTERN SAYAN MTS."},"type":"Polygon"},{"arcs":[[150]],"id":"mtn-39","properties":{"cla":"Range/mtn","name":"YABLONOVYY RANGE"},"type":"Polygon"},{"arcs":[[151]],"id":"mtn-40","properties":{"cla":"Range/mtn","name":"Dabie Mts."},"type":"Polygon"},{"arcs":[[152]],"id":"mtn-41","properties":{"cla":"Range/mtn","name":"Nan Ling Mts."},"type":"Polygon"},{"arcs":[[153,154]],"id":"mtn-42","properties":{"cla":"Range/mtn","name":"WESTERN GHATS"},"type":"Polygon"},{"arcs":[[155]],"id":"mtn-43","properties":{"cla":"Range/mtn","name":"EASTERN GHATS"},"type":"Polygon"},{"arcs":[[156]],"id":"mtn-44","properties":{"cla":"Range/mtn","name":"Vindhya Range"},"type":"Polygon"},{"arcs":[[157]],"id":"mtn-45","properties":{"cla":"Range/mtn","name":"Wuyi Mts."},"type":"Polygon"},{"arcs":[[158]],"id":"mtn-46","properties":{"cla":"Range/mtn","name":"Tarbagatay Ra."},"type":"Polygon"},{"arcs":[[159,160,161]],"id":"mtn-47","properties":{"cla":"Range/mtn","name":"ALTUN MTS."},"type":"Polygon"},{"arcs":[[162]],"id":"mtn-48","properties":{"cla":"Range/mtn","name":"HEJAZ MTS."},"type":"Polygon"},{"arcs":[[163]],"id":"mtn-49","properties":{"cla":"Range/mtn","name":"ASIR MTS."},"type":"Polygon"},{"arcs":[[164]],"id":"mtn-50","properties":{"cla":"Range/mtn","name":"ELBURZ MTS."},"type":"Polygon"},{"arcs":[[165]],"id":"mtn-51","properties":{"cla":"Range/mtn","name":"KJØLEN MOUNTAINS"},"type":"Polygon"},{"arcs":[[166]],"id":"mtn-52","properties":{"cla":"Range/mtn","name":"CARPATHIAN MOUNTAINS"},"type":"Polygon"},{"arcs":[[167]],"id":"mtn-53","properties":{"cla":"Range/mtn","name":"APPENNINI"},"type":"Polygon"},{"arcs":[[168,169]],"id":"mtn-54","properties":{"cla":"Range/mtn","name":"PYRENEES"},"type":"Polygon"},{"arcs":[[170,171]],"id":"mtn-55","properties":{"cla":"Range/mtn","name":"Sierra Madre del Sur"},"type":"Polygon"},{"arcs":[[[172,173]],[[174]]],"id":"mtn-56","properties":{"cla":"Range/mtn","name":"COAST RANGES"},"type":"MultiPolygon"},{"arcs":[[175]],"id":"mtn-57","properties":{"cla":"Range/mtn","name":"SIERRA MADRE ORIENTAL"},"type":"Polygon"},{"arcs":[[-125,176,-123,177]],"id":"mtn-58","properties":{"cla":"Range/mtn","name":"SIERRA NEVADA"},"type":"Polygon"},{"arcs":[[178,179]],"id":"mtn-59","properties":{"cla":"Range/mtn","name":"SIERRA MADRE OCCIDENTAL"},"type":"Polygon"},{"arcs":[[180]],"id":"mtn-60","properties":{"cla":"Range/mtn","name":"CHUGACH MTS."},"type":"Polygon"},{"arcs":[[181,182,183,184,185,186,187,188,189,190,191]],"id":"mtn-61","properties":{"cla":"Range/mtn","name":"MACKENZIE MTS."},"type":"Polygon"},{"arcs":[[192,193]],"id":"mtn-62","properties":{"cla":"Range/mtn","name":"CORDILLERA OCCIDENTAL"},"type":"Polygon"},{"arcs":[[194,195,196,197]],"id":"mtn-63","properties":{"cla":"Range/mtn","name":"CORDILLERA REAL"},"type":"Polygon"},{"arcs":[[198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223]],"id":"mtn-64","properties":{"cla":"Range/mtn","name":"CORDILLERA ORIENTAL"},"type":"Polygon"},{"arcs":[[224,225,226,227,228,229,230,231,232,233,234,235,236,237]],"id":"mtn-65","properties":{"cla":"Range/mtn","name":"CORD. CENTRAL"},"type":"Polygon"},{"arcs":[[38,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256]],"id":"mtn-66","properties":{"cla":"Range/mtn","name":"CORD. OCCIDENTAL"},"type":"Polygon"},{"arcs":[[257,258,259,260,261,262,-252,263,264,265,266,267,268,269,270,271,272,273,274,275,276]],"id":"mtn-67","properties":{"cla":"Range/mtn","name":"CORD. CENTRAL"},"type":"Polygon"},{"arcs":[[277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298]],"id":"mtn-68","properties":{"cla":"Range/mtn","name":"CORDILLERA ORIENTAL"},"type":"Polygon"},{"arcs":[[299]],"id":"mtn-69","properties":{"cla":"Range/mtn","name":"SOUTHERN ALPS"},"type":"Polygon"},{"arcs":[[300]],"id":"mtn-70","properties":{"cla":"Range/mtn","name":"Anti Atlas"},"type":"Polygon"},{"arcs":[[301]],"id":"mtn-71","properties":{"cla":"Range/mtn","name":"Muchinga Mts."},"type":"Polygon"},{"arcs":[[302,303,304,305,306,307,308,309,310,311,312,313]],"id":"mtn-72","properties":{"cla":"Range/mtn","name":"Serra do Mar"},"type":"Polygon"},{"arcs":[[314,315,316,317,318,319,320,321,322,323]],"id":"mtn-73","properties":{"cla":"Range/mtn","name":"Serra Geral"},"type":"Polygon"},{"arcs":[[324,325]],"id":"mtn-74","properties":{"cla":"Range/mtn","name":"Serra da Mantiqueira"},"type":"Polygon"},{"arcs":[[326]],"id":"mtn-75","properties":{"cla":"Range/mtn","name":"GUIANA HIGHLANDS"},"type":"Polygon"},{"arcs":[[327]],"id":"mtn-76","properties":{"cla":"Range/mtn","name":"Sierra Chiapas"},"type":"Polygon"},{"arcs":[[328,329,330,331,332,333,334]],"id":"mtn-77","properties":{"cla":"Range/mtn","name":"SELWYN MTS."},"type":"Polygon"},{"arcs":[[335,336,337,338,339,340,341,342,343,344,345,346]],"id":"mtn-78","properties":{"cla":"Range/mtn","name":"COLUMBIA MTS."},"type":"Polygon"},{"arcs":[[347]],"id":"mtn-79","properties":{"cla":"Range/mtn","name":"TORNGAT MTS."},"type":"Polygon"},{"arcs":[[348]],"id":"mtn-80","properties":{"cla":"Range/mtn","name":"NEW GUINEA HIGHLANDS"},"type":"Polygon"},{"arcs":[[349]],"id":"mtn-81","properties":{"cla":"Range/mtn","name":"Hangayn Mts."},"type":"Polygon"},{"arcs":[[350]],"id":"mtn-82","properties":{"cla":"Range/mtn","name":"Hamgyong Mts."},"type":"Polygon"},{"arcs":[[351]],"id":"mtn-83","properties":{"cla":"Range/mtn","name":"SREDINNYY RANGE"},"type":"Polygon"},{"arcs":[[352]],"id":"mtn-84","properties":{"cla":"Range/mtn","name":"Koryak Range"},"type":"Polygon"},{"arcs":[[353]],"id":"mtn-85","properties":{"cla":"Range/mtn","name":"KOLYMA RANGE"},"type":"Polygon"},{"arcs":[[354]],"id":"mtn-86","properties":{"cla":"Range/mtn","name":"CHERSKIY RANGE"},"type":"Polygon"},{"arcs":[[355]],"id":"mtn-87","properties":{"cla":"Range/mtn","name":"Chin Hills"},"type":"Polygon"},{"arcs":[[356]],"id":"mtn-88","properties":{"cla":"Range/mtn","name":"Yin Mts."},"type":"Polygon"},{"arcs":[[357,358,359,360,361,362]],"id":"mtn-89","properties":{"cla":"Range/mtn","name":"Western Sayan Mts."},"type":"Polygon"},{"arcs":[[363,364,365,366,367,368,369,370,371]],"id":"mtn-90","properties":{"cla":"Range/mtn","name":"Abakanskiy Ra."},"type":"Polygon"},{"arcs":[[372,373]],"id":"mtn-91","properties":{"cla":"Range/mtn","name":"Tannu-Ola Ra."},"type":"Polygon"},{"arcs":[[374]],"id":"mtn-92","properties":{"cla":"Range/mtn","name":"Taihang Mts."},"type":"Polygon"},{"arcs":[[375,376]],"id":"mtn-93","properties":{"cla":"Range/mtn","name":"Lüliang Mts."},"type":"Polygon"},{"arcs":[[377,378]],"id":"mtn-94","properties":{"cla":"Range/mtn","name":"Qinling Mountains"},"type":"Polygon"},{"arcs":[[379]],"id":"mtn-95","properties":{"cla":"Range/mtn","name":"Dalou Mts."},"type":"Polygon"},{"arcs":[[380]],"id":"mtn-96","properties":{"cla":"Range/mtn","name":"Dângrêk Ra."},"type":"Polygon"},{"arcs":[[381]],"id":"mtn-97","properties":{"cla":"Range/mtn","name":"Naga Hills"},"type":"Polygon"},{"arcs":[[382]],"id":"mtn-98","properties":{"cla":"Range/mtn","name":"Arakan Yoma"},"type":"Polygon"},{"arcs":[[383,384]],"id":"mtn-99","properties":{"cla":"Range/mtn","name":"Southern Ghats"},"type":"Polygon"},{"arcs":[[385]],"id":"mtn-100","properties":{"cla":"Range/mtn","name":"Satpura Range"},"type":"Polygon"},{"arcs":[[386,387,388,389,390,391]],"id":"mtn-101","properties":{"cla":"Range/mtn","name":"Salt Ra."},"type":"Polygon"},{"arcs":[[392,393]],"id":"mtn-102","properties":{"cla":"Range/mtn","name":"Borohoro Mts."},"type":"Polygon"},{"arcs":[[394]],"id":"mtn-103","properties":{"cla":"Range/mtn","name":"Alataw Mts."},"type":"Polygon"},{"arcs":[[395]],"id":"mtn-104","properties":{"cla":"Range/mtn","name":"Khasi Hills"},"type":"Polygon"},{"arcs":[[396,397]],"id":"mtn-105","properties":{"cla":"Range/mtn","name":"Lesser Caucasus"},"type":"Polygon"},{"arcs":[[398,399]],"id":"mtn-106","properties":{"cla":"Range/mtn","name":"PONTIC MOUNTAINS"},"type":"Polygon"},{"arcs":[[400]],"id":"mtn-107","properties":{"cla":"Range/mtn","name":"KUH RUD MOUNTAINS"},"type":"Polygon"},{"arcs":[[401]],"id":"mtn-108","properties":{"cla":"Range/mtn","name":"Balkan Mts."},"type":"Polygon"},{"arcs":[[402]],"id":"mtn-109","properties":{"cla":"Range/mtn","name":"Dinaric Alps"},"type":"Polygon"},{"arcs":[[403,404]],"id":"mtn-110","properties":{"cla":"Range/mtn","name":"Cord. Cantábrica"},"type":"Polygon"},{"arcs":[[405]],"id":"mtn-111","properties":{"cla":"Range/mtn","name":"S. Nevada"},"type":"Polygon"},{"arcs":[[406]],"id":"mtn-112","properties":{"cla":"Range/mtn","name":"Sierra Morena"},"type":"Polygon"},{"arcs":[[407]],"id":"mtn-113","properties":{"cla":"Range/mtn","name":"Hadhramaut"},"type":"Polygon"}],"type":"GeometryCollection"}},"transform":{"scale":[0.03432598249824983,0.012651238423842383],"translate":[-166.380518,-55.18078800000001]},"type":"Topology"}
|
package/src/map/data/types.ts
CHANGED
|
@@ -50,6 +50,40 @@ export interface Gazetteer {
|
|
|
50
50
|
alt: Record<string, number>;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
/** Water-feature class (Natural Earth `featurecla`, rivers/reefs excluded). */
|
|
54
|
+
export type WaterKind =
|
|
55
|
+
| 'ocean'
|
|
56
|
+
| 'sea'
|
|
57
|
+
| 'gulf'
|
|
58
|
+
| 'bay'
|
|
59
|
+
| 'strait'
|
|
60
|
+
| 'channel'
|
|
61
|
+
| 'sound';
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A water-body label entry: `[lat, lon, name, tier, kind, alt?]`.
|
|
65
|
+
* - `lat`/`lon` — label anchor (Natural Earth inner point), rounded to 3 decimals.
|
|
66
|
+
* - `name` — full display name (no abbreviation exists for water bodies).
|
|
67
|
+
* - `tier` — Natural Earth `scalerank` (0 = most prominent → orientation priority).
|
|
68
|
+
* - `kind` — feature class (drives styling/priority bucketing).
|
|
69
|
+
* - `alt` — optional extra anchor points `[lat, lon][]`; the layout picks the
|
|
70
|
+
* one nearest the viewport center (Decision 5 multi-anchor seam). Absent today.
|
|
71
|
+
*/
|
|
72
|
+
export type WaterBodyEntry = [
|
|
73
|
+
lat: number,
|
|
74
|
+
lon: number,
|
|
75
|
+
name: string,
|
|
76
|
+
tier: number,
|
|
77
|
+
kind: WaterKind,
|
|
78
|
+
alt?: ReadonlyArray<readonly [number, number]>,
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
export interface WaterBodies {
|
|
82
|
+
/** Deterministically ordered (tier, then name). Generated from Natural Earth
|
|
83
|
+
* marine polys by scripts/build-map-data.mjs into `water-bodies.json`. */
|
|
84
|
+
readonly entries: readonly WaterBodyEntry[];
|
|
85
|
+
}
|
|
86
|
+
|
|
53
87
|
/** A fill-able region (country or US state) — the display name + its ISO id +
|
|
54
88
|
* layer. Powers region-name autocomplete (completion-only; the renderer derives
|
|
55
89
|
* names from the topology directly). Extracted from the topologies by
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"entries":[[85.078,21.558,"Arctic Ocean",0,"ocean"],[-26.746,83.424,"Indian Ocean",0,"ocean"],[39.898,-30.68,"North Atlantic Ocean",0,"ocean",[[40,-55],[30,-45],[50,-25],[15,-45]]],[24.49,-136.445,"North Pacific Ocean",0,"ocean",[[36,-126],[47,-131],[55,-143],[35,160],[15,165]]],[-34.311,-18.311,"South Atlantic Ocean",0,"ocean",[[-25,-35],[-40,-15],[-10,-20]]],[-30.137,-126.822,"South Pacific Ocean",0,"ocean",[[-20,-110],[-40,-95],[-15,170],[-35,170]]],[-65.892,-18.447,"Southern Ocean",0,"ocean"],[13.692,63.675,"Arabian Sea",1,"sea"],[72.951,-66.643,"Baffin Bay",1,"bay"],[13.118,86.757,"Bay of Bengal",1,"bay"],[71.997,-136.388,"Beaufort Sea",1,"sea"],[43.547,31.292,"Black Sea",1,"sea"],[13.754,-78.235,"Caribbean Sea",1,"sea"],[41.954,50.61,"Caspian Sea",1,"sea"],[-18.886,157.126,"Coral Sea",1,"sea"],[58.108,-149.198,"Gulf of Alaska",1,"gulf"],[25.319,-90.053,"Gulf of America",1,"gulf"],[59.246,-85.292,"Hudson Bay",1,"bay"],[55.979,-52.602,"Labrador Sea",1,"sea"],[34.341,17.988,"Mediterranean Sea",1,"sea"],[25.683,52.866,"Persian Gulf",1,"gulf"],[17.263,133.481,"Philippine Sea",1,"sea"],[19.579,38.751,"Red Sea",1,"sea"],[-77.493,-169.96,"Ross Sea",1,"sea"],[40.613,136.423,"Sea of Japan",1,"sea"],[52.851,149.205,"Sea of Okhotsk",1,"sea"],[13.781,114.703,"South China Sea",1,"sea"],[-40.358,160.682,"Tasman Sea",1,"sea"],[-75.66,-53.473,"Weddell Sea",1,"sea"],[-73.979,-106.379,"Amundsen Sea",2,"sea"],[10.878,95.492,"Andaman Sea",2,"sea"],[-9.347,135.278,"Arafura Sea",2,"sea"],[19.67,-93.559,"Bahía de Campeche",2,"bay"],[56.024,19.234,"Baltic Sea",2,"sea"],[-5.658,126.23,"Banda Sea",2,"sea"],[74.604,43.063,"Barents Sea",2,"sea"],[45.627,-4.33,"Bay of Biscay",2,"bay"],[-72.084,-82.745,"Bellingshausen Sea",2,"sea"],[56.349,-171.512,"Bering Sea",2,"sea"],[3.571,122.574,"Celebes Sea",2,"sea"],[68.633,-169.418,"Chukchi Sea",2,"sea"],[64.549,-57.848,"Davis Strait",2,"strait"],[-66.686,-68.017,"Drake Passage",2,"channel"],[28.854,125.37,"East China Sea",2,"sea"],[76.558,-8.516,"Greenland Sea",2,"sea"],[3.294,2.903,"Gulf of Guinea",2,"gulf"],[9.545,101.832,"Gulf of Thailand",2,"gulf"],[53.543,-5.35,"Irish Sea",2,"sea"],[-5.2,112.569,"Java Sea",2,"sea"],[76.92,73.103,"Kara Sea",2,"sea"],[5.871,75.234,"Laccadive Sea",2,"sea"],[75.961,120.379,"Laptev Sea",2,"sea"],[22.073,120.87,"Luzon Strait",2,"strait"],[-20.03,40.414,"Mozambique Channel",2,"channel"],[56.502,2.655,"North Sea",2,"sea"],[66.883,1.329,"Norwegian Sea",2,"sea"],[27.646,-59.716,"Sargasso Sea",2,"sea"],[-61.149,-54.893,"Scotia Sea",2,"sea"],[8.392,120.208,"Sulu Sea",2,"sea"],[-10.978,127.712,"Timor Sea",2,"sea"],[35.164,123.956,"Yellow Sea",2,"sea"],[42.81,15.327,"Adriatic Sea",3,"sea"],[49.707,-2.894,"English Channel",3,"channel"],[26.35,-110.53,"Golfo de California",3,"gulf"],[-35.41,131.682,"Great Australian Bight",3,"gulf"],[12.621,48.305,"Gulf of Aden",3,"gulf"],[61.904,19.763,"Gulf of Bothnia",3,"gulf"],[-14.387,139.215,"Gulf of Carpentaria",3,"gulf"],[16.3,-88.001,"Gulf of Honduras",3,"gulf"],[24.54,58.766,"Gulf of Oman",3,"gulf"],[63.3,-73.224,"Hudson Strait",3,"strait"],[53.746,-80.255,"James Bay",3,"bay"],[39.863,12.144,"Tyrrhenian Sea",3,"sea"],[65.418,38.854,"White Sea",3,"sea"],[38.899,24.994,"Aegean Sea",4,"sea"],[70.531,-120.687,"Amundsen Gulf",4,"gulf"],[40.132,1.619,"Balearic Sea",4,"sea"],[44.909,-66.051,"Bay of Fundy",4,"bay"],[-37.489,176.808,"Bay of Plenty",4,"bay"],[-3.776,147.903,"Bismarck Sea",4,"sea"],[38.756,120.053,"Bo Hai",4,"sea"],[57.651,-160.179,"Bristol Bay",4,"bay"],[51.086,-5.339,"Bristol Channel",4,"channel"],[-2.412,131.169,"Ceram Sea",4,"sea"],[37.829,-76.031,"Chesapeake Bay",4,"bay"],[59.657,-152.312,"Cook Inlet",4,"bay"],[42.981,3.976,"Golfe du Lion",4,"gulf"],[-46.117,-66.587,"Golfo San Jorge",4,"gulf"],[8.18,-79.211,"Golfo de Panamá",4,"gulf"],[59.969,26.987,"Gulf of Finland",4,"gulf"],[22.57,69.333,"Gulf of Kutch",4,"gulf"],[43.368,-68.504,"Gulf of Maine",4,"gulf"],[8.43,78.962,"Gulf of Mannar",4,"gulf"],[48.615,-60.525,"Gulf of Saint Lawrence",4,"gulf"],[19.791,107.611,"Gulf of Tonkin",4,"gulf"],[33.956,132.471,"Inner Sea",4,"sea"],[56.267,-7.03,"Inner Seas",4,"sea"],[38.178,18.626,"Ionian Sea",4,"sea"],[33.799,128.392,"Korea Strait",4,"strait"],[-1.86,118.021,"Makassar Strait",4,"strait"],[75.523,-61.147,"Melville Bay",4,"bay"],[0.591,126.128,"Molucca Sea",4,"sea"],[-35.469,-56.554,"Río de la Plata",4,"gulf"],[59.897,157.821,"Shelikhova Gulf",4,"gulf"],[-9.247,155.069,"Solomon Sea",4,"sea"],[35.783,-5.919,"Strait of Gibraltar",4,"strait"],[5.586,99.038,"Strait of Malacca",4,"strait"],[1.193,103.68,"Strait of Singapore",4,"strait"],[25.571,-79.276,"Straits of Florida",4,"strait"],[24.166,119.387,"Taiwan Strait",4,"strait"],[70.288,-99.272,"The North Western Passages",4,"channel"],[59.341,-67.41,"Ungava Bay",4,"bay"],[73.851,-109.102,"Viscount Melville Sound",4,"sound"]]}
|