@diagrammo/dgmo 0.20.3 → 0.21.1
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/dist/advanced.cjs +867 -286
- package/dist/advanced.js +866 -286
- package/dist/auto.cjs +635 -284
- package/dist/auto.js +113 -113
- package/dist/auto.mjs +635 -284
- package/dist/cli.cjs +156 -156
- package/dist/editor.cjs +6 -2
- package/dist/editor.js +6 -2
- package/dist/highlight.cjs +6 -2
- package/dist/highlight.js +6 -2
- package/dist/index.cjs +628 -281
- package/dist/index.js +628 -281
- package/dist/internal.cjs +867 -286
- package/dist/internal.js +866 -286
- package/dist/map-data/PROVENANCE.json +1 -1
- package/dist/map-data/mountain-ranges.json +1 -0
- package/docs/language-reference.md +27 -25
- package/gallery/fixtures/map-choropleth.dgmo +7 -7
- package/gallery/fixtures/map-direct-color.dgmo +10 -0
- package/gallery/fixtures/map-pois.dgmo +4 -4
- package/gallery/fixtures/map-region-scope.dgmo +8 -8
- package/gallery/fixtures/map-route.dgmo +5 -6
- package/package.json +1 -1
- package/src/advanced.ts +14 -0
- package/src/completion.ts +10 -4
- package/src/d3.ts +15 -9
- package/src/editor/keywords.ts +6 -2
- package/src/map/data/PROVENANCE.json +1 -1
- package/src/map/data/mountain-ranges.json +1 -0
- package/src/map/geo-query.ts +277 -0
- package/src/map/geo.ts +258 -1
- package/src/map/invert.ts +111 -0
- package/src/map/layout.ts +333 -139
- package/src/map/load-data.ts +7 -1
- package/src/map/parser.ts +142 -33
- package/src/map/renderer.ts +57 -6
- package/src/map/resolved-types.ts +21 -2
- package/src/map/resolver.ts +219 -53
- package/src/map/types.ts +57 -14
- package/src/utils/reserved-key-registry.ts +7 -7
- package/dist/advanced.d.cts +0 -5290
- package/dist/advanced.d.ts +0 -5290
- package/dist/auto.d.cts +0 -39
- package/dist/auto.d.ts +0 -39
- package/dist/index.d.cts +0 -336
- package/dist/index.d.ts +0 -336
- package/dist/internal.d.cts +0 -5290
- package/dist/internal.d.ts +0 -5290
package/dist/internal.cjs
CHANGED
|
@@ -857,13 +857,9 @@ var init_reserved_key_registry = __esm({
|
|
|
857
857
|
"icon"
|
|
858
858
|
]);
|
|
859
859
|
MAP_REGISTRY = staticRegistry([
|
|
860
|
-
"
|
|
860
|
+
"value",
|
|
861
861
|
"label",
|
|
862
|
-
"
|
|
863
|
-
"description",
|
|
864
|
-
"weight",
|
|
865
|
-
"style",
|
|
866
|
-
"date"
|
|
862
|
+
"style"
|
|
867
863
|
]);
|
|
868
864
|
ORG_REGISTRY = staticRegistry([
|
|
869
865
|
"color",
|
|
@@ -15828,7 +15824,8 @@ function parseMap(content) {
|
|
|
15828
15824
|
continue;
|
|
15829
15825
|
}
|
|
15830
15826
|
if (open.route && indent > open.route.indent) {
|
|
15831
|
-
open.route.route.
|
|
15827
|
+
const leg = parseLeg(trimmed, lineNumber, open.route.route.style);
|
|
15828
|
+
open.route.route.legs.push(leg);
|
|
15832
15829
|
continue;
|
|
15833
15830
|
}
|
|
15834
15831
|
if (open.poi && indent > open.poi.indent) {
|
|
@@ -15859,6 +15856,10 @@ function parseMap(content) {
|
|
|
15859
15856
|
handleTag(trimmed, lineNumber);
|
|
15860
15857
|
continue;
|
|
15861
15858
|
}
|
|
15859
|
+
if ((firstWord === "muted" || firstWord === "natural") && trimmed === firstWord) {
|
|
15860
|
+
handleDirective(firstWord, "", lineNumber);
|
|
15861
|
+
continue;
|
|
15862
|
+
}
|
|
15862
15863
|
if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
|
|
15863
15864
|
handleDirective(
|
|
15864
15865
|
firstWord,
|
|
@@ -15923,13 +15924,20 @@ function parseMap(content) {
|
|
|
15923
15924
|
);
|
|
15924
15925
|
d.projection = value;
|
|
15925
15926
|
break;
|
|
15926
|
-
case "metric":
|
|
15927
|
-
dup(d.
|
|
15928
|
-
|
|
15927
|
+
case "region-metric": {
|
|
15928
|
+
dup(d.regionMetric);
|
|
15929
|
+
const { label: rmLabel, colorName: rmColor } = peelTrailingColorName(value);
|
|
15930
|
+
d.regionMetric = rmLabel;
|
|
15931
|
+
if (rmColor) d.regionMetricColor = rmColor;
|
|
15932
|
+
break;
|
|
15933
|
+
}
|
|
15934
|
+
case "poi-metric":
|
|
15935
|
+
dup(d.poiMetric);
|
|
15936
|
+
d.poiMetric = value;
|
|
15929
15937
|
break;
|
|
15930
|
-
case "
|
|
15931
|
-
dup(d.
|
|
15932
|
-
d.
|
|
15938
|
+
case "flow-metric":
|
|
15939
|
+
dup(d.flowMetric);
|
|
15940
|
+
d.flowMetric = value;
|
|
15933
15941
|
break;
|
|
15934
15942
|
case "scale":
|
|
15935
15943
|
dup(d.scale);
|
|
@@ -15971,6 +15979,21 @@ function parseMap(content) {
|
|
|
15971
15979
|
case "no-legend":
|
|
15972
15980
|
d.noLegend = true;
|
|
15973
15981
|
break;
|
|
15982
|
+
case "no-insets":
|
|
15983
|
+
d.noInsets = true;
|
|
15984
|
+
break;
|
|
15985
|
+
case "relief":
|
|
15986
|
+
d.relief = true;
|
|
15987
|
+
break;
|
|
15988
|
+
case "muted":
|
|
15989
|
+
case "natural":
|
|
15990
|
+
if (d.basemapStyle !== void 0 && d.basemapStyle !== key)
|
|
15991
|
+
pushWarning(
|
|
15992
|
+
line12,
|
|
15993
|
+
`Conflicting basemap dress \u2014 "${d.basemapStyle}" then "${key}"; last wins.`
|
|
15994
|
+
);
|
|
15995
|
+
d.basemapStyle = key;
|
|
15996
|
+
break;
|
|
15974
15997
|
case "subtitle":
|
|
15975
15998
|
dup(d.subtitle);
|
|
15976
15999
|
d.subtitle = value;
|
|
@@ -16048,14 +16071,14 @@ function parseMap(content) {
|
|
|
16048
16071
|
line12
|
|
16049
16072
|
);
|
|
16050
16073
|
const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
|
|
16051
|
-
let
|
|
16052
|
-
const
|
|
16053
|
-
if (
|
|
16054
|
-
delete meta["
|
|
16055
|
-
|
|
16056
|
-
if (!Number.isFinite(
|
|
16057
|
-
pushError(line12, `
|
|
16058
|
-
|
|
16074
|
+
let valueNum;
|
|
16075
|
+
const value = meta["value"];
|
|
16076
|
+
if (value !== void 0) {
|
|
16077
|
+
delete meta["value"];
|
|
16078
|
+
valueNum = Number(value);
|
|
16079
|
+
if (!Number.isFinite(valueNum)) {
|
|
16080
|
+
pushError(line12, `value must be a number (got "${value}").`);
|
|
16081
|
+
valueNum = void 0;
|
|
16059
16082
|
}
|
|
16060
16083
|
}
|
|
16061
16084
|
let regionName = split.name;
|
|
@@ -16073,7 +16096,8 @@ function parseMap(content) {
|
|
|
16073
16096
|
lineNumber: line12
|
|
16074
16097
|
};
|
|
16075
16098
|
if (regionScope !== void 0) region.scope = regionScope;
|
|
16076
|
-
if (
|
|
16099
|
+
if (valueNum !== void 0) region.value = valueNum;
|
|
16100
|
+
if (split.color) region.color = split.color;
|
|
16077
16101
|
regions.push(region);
|
|
16078
16102
|
}
|
|
16079
16103
|
function handlePoi(rest, line12, indent) {
|
|
@@ -16098,28 +16122,81 @@ function parseMap(content) {
|
|
|
16098
16122
|
const poi = { pos, tags, meta, lineNumber: line12 };
|
|
16099
16123
|
if (split.alias) poi.alias = split.alias;
|
|
16100
16124
|
if (label !== void 0) poi.label = label;
|
|
16125
|
+
if (split.color) poi.color = split.color;
|
|
16101
16126
|
pois.push(poi);
|
|
16102
16127
|
open.poi = { poi, indent };
|
|
16103
16128
|
}
|
|
16104
16129
|
function handleRoute(rest, line12, indent) {
|
|
16105
|
-
const
|
|
16106
|
-
|
|
16130
|
+
const split = rest ? splitNameAndMeta(
|
|
16131
|
+
rest,
|
|
16132
|
+
registry(),
|
|
16133
|
+
aliasMap,
|
|
16134
|
+
void 0,
|
|
16135
|
+
diagnostics,
|
|
16136
|
+
line12
|
|
16137
|
+
) : { name: "", meta: {}, alias: void 0 };
|
|
16138
|
+
const pos = parsePos(split.name, line12);
|
|
16139
|
+
if (!pos || pos.kind === "name" && !pos.name) {
|
|
16140
|
+
pushError(
|
|
16141
|
+
line12,
|
|
16142
|
+
"route requires an origin: `route <origin> [style: arc]`."
|
|
16143
|
+
);
|
|
16144
|
+
return;
|
|
16145
|
+
}
|
|
16146
|
+
const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
|
|
16147
|
+
const originLabel = meta["label"];
|
|
16148
|
+
const originValue = meta["value"];
|
|
16149
|
+
const style = meta["style"] === "arc" ? "arc" : "straight";
|
|
16150
|
+
const route = {
|
|
16151
|
+
origin: pos,
|
|
16152
|
+
...split.alias !== void 0 && { originAlias: split.alias },
|
|
16153
|
+
...originLabel !== void 0 && { originLabel },
|
|
16154
|
+
...originValue !== void 0 && { originValue },
|
|
16155
|
+
originTags: tags,
|
|
16156
|
+
style,
|
|
16157
|
+
legs: [],
|
|
16158
|
+
lineNumber: line12
|
|
16159
|
+
};
|
|
16107
16160
|
routes.push(route);
|
|
16108
16161
|
open.route = { route, indent };
|
|
16109
16162
|
}
|
|
16110
|
-
function
|
|
16111
|
-
|
|
16112
|
-
|
|
16163
|
+
function parseLeg(trimmed, line12, headerStyle) {
|
|
16164
|
+
let arrowStyle = "straight";
|
|
16165
|
+
let label;
|
|
16166
|
+
let rest = trimmed;
|
|
16167
|
+
const m = trimmed.match(LEG_ARROW_RE);
|
|
16168
|
+
if (m) {
|
|
16169
|
+
const arr = classifyArrow(m[1], line12);
|
|
16170
|
+
arrowStyle = arr.style;
|
|
16171
|
+
label = arr.label;
|
|
16172
|
+
rest = m[2];
|
|
16173
|
+
}
|
|
16174
|
+
const split = splitNameAndMeta(
|
|
16175
|
+
rest,
|
|
16176
|
+
registry(),
|
|
16177
|
+
aliasMap,
|
|
16178
|
+
void 0,
|
|
16179
|
+
diagnostics,
|
|
16180
|
+
line12
|
|
16181
|
+
);
|
|
16182
|
+
const pos = parsePos(split.name, line12) ?? {
|
|
16113
16183
|
kind: "name",
|
|
16114
16184
|
name: split.name
|
|
16115
16185
|
};
|
|
16116
|
-
const
|
|
16117
|
-
|
|
16118
|
-
|
|
16186
|
+
const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
|
|
16187
|
+
const value = meta["value"];
|
|
16188
|
+
const destLabel = meta["label"];
|
|
16189
|
+
const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
|
|
16190
|
+
return {
|
|
16191
|
+
...label !== void 0 && { label },
|
|
16192
|
+
style,
|
|
16193
|
+
...value !== void 0 && { value },
|
|
16194
|
+
dest: pos,
|
|
16195
|
+
...split.alias !== void 0 && { destAlias: split.alias },
|
|
16196
|
+
...destLabel !== void 0 && { destLabel },
|
|
16197
|
+
destTags: tags,
|
|
16119
16198
|
lineNumber: line12
|
|
16120
16199
|
};
|
|
16121
|
-
if (split.alias) stop.alias = split.alias;
|
|
16122
|
-
return stop;
|
|
16123
16200
|
}
|
|
16124
16201
|
function handleEdges(trimmed, line12) {
|
|
16125
16202
|
const parts = trimmed.split(ARROW_SPLIT);
|
|
@@ -16221,7 +16298,7 @@ function partitionMeta(meta, tagGroupNames) {
|
|
|
16221
16298
|
function poiName(pos) {
|
|
16222
16299
|
return pos.kind === "name" ? pos.name : void 0;
|
|
16223
16300
|
}
|
|
16224
|
-
var COORD_RE, NUMERIC_LEAD_RE, SCOPE_RE, ARROW_SPLIT, HUB_RE, AT_RE, DIRECTIVE_SET;
|
|
16301
|
+
var COORD_RE, NUMERIC_LEAD_RE, SCOPE_RE, ARROW_SPLIT, HUB_RE, LEG_ARROW_RE, AT_RE, DIRECTIVE_SET;
|
|
16225
16302
|
var init_parser12 = __esm({
|
|
16226
16303
|
"src/map/parser.ts"() {
|
|
16227
16304
|
"use strict";
|
|
@@ -16235,12 +16312,14 @@ var init_parser12 = __esm({
|
|
|
16235
16312
|
SCOPE_RE = /^[A-Z]{2}(?:-[A-Z0-9]{1,3})?$/;
|
|
16236
16313
|
ARROW_SPLIT = /\s+(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+/;
|
|
16237
16314
|
HUB_RE = /^(->|~>)\s+(.+)$/;
|
|
16315
|
+
LEG_ARROW_RE = /^(-[^>]*?->|->|~[^>]*?~>|~>|--)\s+(.+)$/;
|
|
16238
16316
|
AT_RE = /(^|[\s,])at\s*:/i;
|
|
16239
16317
|
DIRECTIVE_SET = /* @__PURE__ */ new Set([
|
|
16240
16318
|
"region",
|
|
16241
16319
|
"projection",
|
|
16242
|
-
"metric",
|
|
16243
|
-
"
|
|
16320
|
+
"region-metric",
|
|
16321
|
+
"poi-metric",
|
|
16322
|
+
"flow-metric",
|
|
16244
16323
|
"scale",
|
|
16245
16324
|
"region-labels",
|
|
16246
16325
|
"poi-labels",
|
|
@@ -16248,6 +16327,8 @@ var init_parser12 = __esm({
|
|
|
16248
16327
|
"default-state",
|
|
16249
16328
|
"active-tag",
|
|
16250
16329
|
"no-legend",
|
|
16330
|
+
"no-insets",
|
|
16331
|
+
"relief",
|
|
16251
16332
|
"subtitle",
|
|
16252
16333
|
"caption"
|
|
16253
16334
|
]);
|
|
@@ -45774,6 +45855,84 @@ function featureIndex(topo) {
|
|
|
45774
45855
|
}
|
|
45775
45856
|
return idx;
|
|
45776
45857
|
}
|
|
45858
|
+
function decodeFeatures(topo) {
|
|
45859
|
+
return geomObject(topo).geometries.map((g) => {
|
|
45860
|
+
const f = (0, import_topojson_client.feature)(topo, g);
|
|
45861
|
+
return {
|
|
45862
|
+
type: "Feature",
|
|
45863
|
+
id: g.id,
|
|
45864
|
+
properties: g.properties,
|
|
45865
|
+
geometry: f.geometry
|
|
45866
|
+
};
|
|
45867
|
+
});
|
|
45868
|
+
}
|
|
45869
|
+
function pointInRing(lon, lat, ring) {
|
|
45870
|
+
let inside = false;
|
|
45871
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
45872
|
+
const xi = ring[i][0];
|
|
45873
|
+
const yi = ring[i][1];
|
|
45874
|
+
const xj = ring[j][0];
|
|
45875
|
+
const yj = ring[j][1];
|
|
45876
|
+
const intersect = yi > lat !== yj > lat && lon < (xj - xi) * (lat - yi) / (yj - yi) + xi;
|
|
45877
|
+
if (intersect) inside = !inside;
|
|
45878
|
+
}
|
|
45879
|
+
return inside;
|
|
45880
|
+
}
|
|
45881
|
+
function pointOnRingEdge(lon, lat, ring) {
|
|
45882
|
+
for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
45883
|
+
const xi = ring[i][0];
|
|
45884
|
+
const yi = ring[i][1];
|
|
45885
|
+
const xj = ring[j][0];
|
|
45886
|
+
const yj = ring[j][1];
|
|
45887
|
+
if (lon < Math.min(xi, xj) - EDGE_EPS || lon > Math.max(xi, xj) + EDGE_EPS)
|
|
45888
|
+
continue;
|
|
45889
|
+
if (lat < Math.min(yi, yj) - EDGE_EPS || lat > Math.max(yi, yj) + EDGE_EPS)
|
|
45890
|
+
continue;
|
|
45891
|
+
const cross = (xj - xi) * (lat - yi) - (yj - yi) * (lon - xi);
|
|
45892
|
+
if (Math.abs(cross) <= EDGE_EPS) return true;
|
|
45893
|
+
}
|
|
45894
|
+
return false;
|
|
45895
|
+
}
|
|
45896
|
+
function pointInGeometry(geometry, lon, lat) {
|
|
45897
|
+
const g = geometry;
|
|
45898
|
+
if (!g) return false;
|
|
45899
|
+
const polys = g.type === "Polygon" ? [g.coordinates] : g.type === "MultiPolygon" ? g.coordinates : [];
|
|
45900
|
+
for (const rings of polys) {
|
|
45901
|
+
if (!rings.length) continue;
|
|
45902
|
+
if (pointOnRingEdge(lon, lat, rings[0])) return true;
|
|
45903
|
+
if (!pointInRing(lon, lat, rings[0])) continue;
|
|
45904
|
+
let inHole = false;
|
|
45905
|
+
for (let h = 1; h < rings.length; h++) {
|
|
45906
|
+
if (pointInRing(lon, lat, rings[h]) && !pointOnRingEdge(lon, lat, rings[h])) {
|
|
45907
|
+
inHole = true;
|
|
45908
|
+
break;
|
|
45909
|
+
}
|
|
45910
|
+
}
|
|
45911
|
+
if (!inHole) return true;
|
|
45912
|
+
}
|
|
45913
|
+
return false;
|
|
45914
|
+
}
|
|
45915
|
+
function regionAt(lonLat, countries, states) {
|
|
45916
|
+
const lon = lonLat[0];
|
|
45917
|
+
const lat = lonLat[1];
|
|
45918
|
+
let country = null;
|
|
45919
|
+
for (const f of countries) {
|
|
45920
|
+
if (pointInGeometry(f.geometry, lon, lat)) {
|
|
45921
|
+
country = { iso: f.id, name: f.properties.name };
|
|
45922
|
+
break;
|
|
45923
|
+
}
|
|
45924
|
+
}
|
|
45925
|
+
let state = null;
|
|
45926
|
+
if (country?.iso === "US" && states) {
|
|
45927
|
+
for (const f of states) {
|
|
45928
|
+
if (pointInGeometry(f.geometry, lon, lat)) {
|
|
45929
|
+
state = { iso: f.id, name: f.properties.name };
|
|
45930
|
+
break;
|
|
45931
|
+
}
|
|
45932
|
+
}
|
|
45933
|
+
}
|
|
45934
|
+
return { country, state };
|
|
45935
|
+
}
|
|
45777
45936
|
function featureBbox(topo, geomId) {
|
|
45778
45937
|
const geom = geomObject(topo).geometries.find((g) => g.id === geomId);
|
|
45779
45938
|
if (!geom) return null;
|
|
@@ -45785,6 +45944,74 @@ function featureBbox(topo, geomId) {
|
|
|
45785
45944
|
[b[1][0], b[1][1]]
|
|
45786
45945
|
];
|
|
45787
45946
|
}
|
|
45947
|
+
function explodePolygons(gj) {
|
|
45948
|
+
const g = gj.geometry ?? gj;
|
|
45949
|
+
const t = g.type;
|
|
45950
|
+
const coords = g.coordinates;
|
|
45951
|
+
if (t === "Polygon") {
|
|
45952
|
+
return [
|
|
45953
|
+
{ type: "Feature", geometry: { type: "Polygon", coordinates: coords } }
|
|
45954
|
+
];
|
|
45955
|
+
}
|
|
45956
|
+
if (t === "MultiPolygon") {
|
|
45957
|
+
return coords.map((rings) => ({
|
|
45958
|
+
type: "Feature",
|
|
45959
|
+
geometry: { type: "Polygon", coordinates: rings }
|
|
45960
|
+
}));
|
|
45961
|
+
}
|
|
45962
|
+
return [];
|
|
45963
|
+
}
|
|
45964
|
+
function bboxGap(a, b) {
|
|
45965
|
+
const lonGap = Math.max(0, a[0][0] - b[1][0], b[0][0] - a[1][0]);
|
|
45966
|
+
const latGap = Math.max(0, a[0][1] - b[1][1], b[0][1] - a[1][1]);
|
|
45967
|
+
return Math.max(lonGap, latGap);
|
|
45968
|
+
}
|
|
45969
|
+
function featureBboxPrimary(topo, geomId) {
|
|
45970
|
+
const geom = geomObject(topo).geometries.find((g) => g.id === geomId);
|
|
45971
|
+
if (!geom) return null;
|
|
45972
|
+
const gj = (0, import_topojson_client.feature)(topo, geom);
|
|
45973
|
+
const parts = explodePolygons(gj);
|
|
45974
|
+
if (parts.length <= 1) return featureBbox(topo, geomId);
|
|
45975
|
+
const polys = parts.map((p) => {
|
|
45976
|
+
const b = (0, import_d3_geo.geoBounds)(p);
|
|
45977
|
+
if (!b || !Number.isFinite(b[0][0])) return null;
|
|
45978
|
+
const wraps = b[1][0] < b[0][0];
|
|
45979
|
+
const bbox = [
|
|
45980
|
+
[b[0][0], b[0][1]],
|
|
45981
|
+
[b[1][0], b[1][1]]
|
|
45982
|
+
];
|
|
45983
|
+
return { bbox, area: (0, import_d3_geo.geoArea)(p), wraps };
|
|
45984
|
+
}).filter(
|
|
45985
|
+
(p) => p !== null
|
|
45986
|
+
);
|
|
45987
|
+
if (polys.length <= 1 || polys.some((p) => p.wraps))
|
|
45988
|
+
return featureBbox(topo, geomId);
|
|
45989
|
+
const maxArea = Math.max(...polys.map((p) => p.area));
|
|
45990
|
+
const anchor = polys.find((p) => p.area === maxArea);
|
|
45991
|
+
const cluster = [
|
|
45992
|
+
[anchor.bbox[0][0], anchor.bbox[0][1]],
|
|
45993
|
+
[anchor.bbox[1][0], anchor.bbox[1][1]]
|
|
45994
|
+
];
|
|
45995
|
+
const remaining = polys.filter((p) => p !== anchor);
|
|
45996
|
+
let added = true;
|
|
45997
|
+
while (added) {
|
|
45998
|
+
added = false;
|
|
45999
|
+
for (let i = remaining.length - 1; i >= 0; i--) {
|
|
46000
|
+
const p = remaining[i];
|
|
46001
|
+
const near = bboxGap(p.bbox, cluster) <= DETACH_GAP_DEG;
|
|
46002
|
+
const large = p.area >= DETACH_AREA_FRAC * maxArea;
|
|
46003
|
+
if (near || large) {
|
|
46004
|
+
cluster[0][0] = Math.min(cluster[0][0], p.bbox[0][0]);
|
|
46005
|
+
cluster[0][1] = Math.min(cluster[0][1], p.bbox[0][1]);
|
|
46006
|
+
cluster[1][0] = Math.max(cluster[1][0], p.bbox[1][0]);
|
|
46007
|
+
cluster[1][1] = Math.max(cluster[1][1], p.bbox[1][1]);
|
|
46008
|
+
remaining.splice(i, 1);
|
|
46009
|
+
added = true;
|
|
46010
|
+
}
|
|
46011
|
+
}
|
|
46012
|
+
}
|
|
46013
|
+
return cluster;
|
|
46014
|
+
}
|
|
45788
46015
|
function unionExtent(boxes, points) {
|
|
45789
46016
|
const lats = [];
|
|
45790
46017
|
const lons = [];
|
|
@@ -45823,13 +46050,16 @@ function unionLongitudes(lons) {
|
|
|
45823
46050
|
}
|
|
45824
46051
|
return { west: pts[gapIdx], east: pts[gapIdx - 1] + 360 };
|
|
45825
46052
|
}
|
|
45826
|
-
var import_topojson_client, import_d3_geo, fold;
|
|
46053
|
+
var import_topojson_client, import_d3_geo, fold, EDGE_EPS, DETACH_GAP_DEG, DETACH_AREA_FRAC;
|
|
45827
46054
|
var init_geo = __esm({
|
|
45828
46055
|
"src/map/geo.ts"() {
|
|
45829
46056
|
"use strict";
|
|
45830
46057
|
import_topojson_client = require("topojson-client");
|
|
45831
46058
|
import_d3_geo = require("d3-geo");
|
|
45832
46059
|
fold = (s) => s.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();
|
|
46060
|
+
EDGE_EPS = 1e-9;
|
|
46061
|
+
DETACH_GAP_DEG = 10;
|
|
46062
|
+
DETACH_AREA_FRAC = 0.25;
|
|
45833
46063
|
}
|
|
45834
46064
|
});
|
|
45835
46065
|
|
|
@@ -45838,6 +46068,11 @@ var resolver_exports = {};
|
|
|
45838
46068
|
__export(resolver_exports, {
|
|
45839
46069
|
resolveMap: () => resolveMap
|
|
45840
46070
|
});
|
|
46071
|
+
function usStateFromBareScope(scope) {
|
|
46072
|
+
if (!scope) return null;
|
|
46073
|
+
const up = scope.toUpperCase();
|
|
46074
|
+
return US_STATE_POSTAL.has(up) ? `US-${up}` : null;
|
|
46075
|
+
}
|
|
45841
46076
|
function looksUS(lat, lon) {
|
|
45842
46077
|
if (lat < 15 || lat > 72) return false;
|
|
45843
46078
|
return lon >= -180 && lon <= -64 || lon >= 172;
|
|
@@ -45887,9 +46122,9 @@ function resolveMap(parsed, data) {
|
|
|
45887
46122
|
const f = fold(r.name);
|
|
45888
46123
|
return usStateIndex.has(f) && !countryIndex.has(f);
|
|
45889
46124
|
}) || parsed.regions.some(
|
|
45890
|
-
(r) => r.scope === "US" || r.scope?.startsWith("US-")
|
|
46125
|
+
(r) => r.scope === "US" || r.scope?.startsWith("US-") || usStateFromBareScope(r.scope) !== null
|
|
45891
46126
|
) || parsed.pois.some(
|
|
45892
|
-
(p) => p.pos.kind === "name" && p.pos.scope?.startsWith("US-")
|
|
46127
|
+
(p) => p.pos.kind === "name" && (p.pos.scope?.startsWith("US-") || usStateFromBareScope(p.pos.scope) !== null)
|
|
45893
46128
|
);
|
|
45894
46129
|
const regions = [];
|
|
45895
46130
|
const seenRegion = /* @__PURE__ */ new Map();
|
|
@@ -45928,12 +46163,12 @@ function resolveMap(parsed, data) {
|
|
|
45928
46163
|
chosen = { ...inState, layer: "us-state" };
|
|
45929
46164
|
} else {
|
|
45930
46165
|
chosen = { ...inCountry, layer: "country" };
|
|
46166
|
+
warn(
|
|
46167
|
+
r.lineNumber,
|
|
46168
|
+
`"${r.name}" is both a country and a US state \u2014 resolved as ${chosen.layer} (${chosen.id}). Pin it with an ISO code (${inState.id} / ${inCountry.id}) or name + scope ("${r.name} US" / "${r.name} ${inCountry.id}").`,
|
|
46169
|
+
"W_MAP_REGION_AMBIGUOUS"
|
|
46170
|
+
);
|
|
45931
46171
|
}
|
|
45932
|
-
warn(
|
|
45933
|
-
r.lineNumber,
|
|
45934
|
-
`"${r.name}" is both a country and a US state \u2014 resolved as ${chosen.layer} (${chosen.id}). Pin it with an ISO code (${inState.id} / ${inCountry.id}) or name + scope ("${r.name} US" / "${r.name} ${inCountry.id}").`,
|
|
45935
|
-
"W_MAP_REGION_AMBIGUOUS"
|
|
45936
|
-
);
|
|
45937
46172
|
} else if (inState) {
|
|
45938
46173
|
chosen = { ...inState, layer: "us-state" };
|
|
45939
46174
|
} else if (inCountry) {
|
|
@@ -45956,7 +46191,8 @@ function resolveMap(parsed, data) {
|
|
|
45956
46191
|
iso: chosen.id,
|
|
45957
46192
|
name: chosen.name,
|
|
45958
46193
|
layer: chosen.layer,
|
|
45959
|
-
...r.
|
|
46194
|
+
...r.value !== void 0 && { value: r.value },
|
|
46195
|
+
...r.color !== void 0 && { color: r.color },
|
|
45960
46196
|
tags: r.tags,
|
|
45961
46197
|
meta: r.meta,
|
|
45962
46198
|
lineNumber: r.lineNumber
|
|
@@ -46014,9 +46250,10 @@ function resolveMap(parsed, data) {
|
|
|
46014
46250
|
let cands = idxs.map((i) => data.gazetteer.cities[i]);
|
|
46015
46251
|
const scopeUse = scope ?? scopeHint;
|
|
46016
46252
|
if (scopeUse) {
|
|
46017
|
-
const
|
|
46253
|
+
const bareState = usStateFromBareScope(scopeUse);
|
|
46254
|
+
const subScope = /^[A-Za-z]{2}-/.test(scopeUse) ? scopeUse : bareState;
|
|
46018
46255
|
const filtered = cands.filter(
|
|
46019
|
-
(c2) =>
|
|
46256
|
+
(c2) => subScope ? c2[5] === subScope : c2[2] === scopeUse
|
|
46020
46257
|
);
|
|
46021
46258
|
if (filtered.length) cands = filtered;
|
|
46022
46259
|
else if (scope) {
|
|
@@ -46097,6 +46334,7 @@ function resolveMap(parsed, data) {
|
|
|
46097
46334
|
lat,
|
|
46098
46335
|
lon,
|
|
46099
46336
|
...p.label !== void 0 && { label: p.label },
|
|
46337
|
+
...p.color !== void 0 && { color: p.color },
|
|
46100
46338
|
tags: p.tags,
|
|
46101
46339
|
meta: p.meta,
|
|
46102
46340
|
lineNumber: p.lineNumber
|
|
@@ -46145,33 +46383,89 @@ function resolveMap(parsed, data) {
|
|
|
46145
46383
|
lineNumber: e.lineNumber
|
|
46146
46384
|
});
|
|
46147
46385
|
}
|
|
46148
|
-
const
|
|
46149
|
-
|
|
46150
|
-
|
|
46151
|
-
|
|
46152
|
-
|
|
46153
|
-
if (
|
|
46154
|
-
|
|
46155
|
-
|
|
46156
|
-
|
|
46157
|
-
const poi = {
|
|
46386
|
+
const resolveStop = (pos, alias, label, tags, sizeValue, line12) => {
|
|
46387
|
+
const meta = sizeValue !== void 0 ? { value: sizeValue } : {};
|
|
46388
|
+
if (pos.kind === "coords") {
|
|
46389
|
+
const id = alias ? fold(alias) : `@${pos.lat},${pos.lon}`;
|
|
46390
|
+
if (!looksUS(pos.lat, pos.lon)) anyNonUsPoi = true;
|
|
46391
|
+
if (!registry.has(id)) {
|
|
46392
|
+
registerPoi(
|
|
46393
|
+
id,
|
|
46394
|
+
{
|
|
46158
46395
|
id,
|
|
46159
|
-
...
|
|
46160
|
-
lat:
|
|
46161
|
-
lon:
|
|
46162
|
-
|
|
46163
|
-
|
|
46164
|
-
|
|
46165
|
-
|
|
46166
|
-
}
|
|
46167
|
-
|
|
46168
|
-
|
|
46169
|
-
} else {
|
|
46170
|
-
id = stop.alias && registry.has(fold(stop.alias)) ? fold(stop.alias) : resolveEndpoint2(stop.ref.name, stop.lineNumber);
|
|
46396
|
+
...alias !== void 0 && { name: alias },
|
|
46397
|
+
lat: pos.lat,
|
|
46398
|
+
lon: pos.lon,
|
|
46399
|
+
...label !== void 0 && { label },
|
|
46400
|
+
tags,
|
|
46401
|
+
meta,
|
|
46402
|
+
lineNumber: line12
|
|
46403
|
+
},
|
|
46404
|
+
line12
|
|
46405
|
+
);
|
|
46171
46406
|
}
|
|
46172
|
-
|
|
46407
|
+
return id;
|
|
46173
46408
|
}
|
|
46174
|
-
|
|
46409
|
+
const f = fold(pos.name);
|
|
46410
|
+
if (registry.has(f)) return f;
|
|
46411
|
+
const aliased = declaredByName.get(f);
|
|
46412
|
+
if (aliased) return aliased;
|
|
46413
|
+
const got = lookupName(pos.name, pos.scope, line12, inferredCountry, true);
|
|
46414
|
+
if (got.kind !== "ok") return null;
|
|
46415
|
+
noteCountry(got.iso);
|
|
46416
|
+
registerPoi(
|
|
46417
|
+
f,
|
|
46418
|
+
{
|
|
46419
|
+
id: f,
|
|
46420
|
+
name: pos.name,
|
|
46421
|
+
lat: got.lat,
|
|
46422
|
+
lon: got.lon,
|
|
46423
|
+
...label !== void 0 && { label },
|
|
46424
|
+
tags,
|
|
46425
|
+
meta,
|
|
46426
|
+
lineNumber: line12
|
|
46427
|
+
},
|
|
46428
|
+
line12
|
|
46429
|
+
);
|
|
46430
|
+
return f;
|
|
46431
|
+
};
|
|
46432
|
+
const routes = [];
|
|
46433
|
+
for (const rt of parsed.routes) {
|
|
46434
|
+
const originId = resolveStop(
|
|
46435
|
+
rt.origin,
|
|
46436
|
+
rt.originAlias,
|
|
46437
|
+
rt.originLabel,
|
|
46438
|
+
rt.originTags,
|
|
46439
|
+
rt.originValue,
|
|
46440
|
+
rt.lineNumber
|
|
46441
|
+
);
|
|
46442
|
+
if (!originId) continue;
|
|
46443
|
+
const stopIds = [originId];
|
|
46444
|
+
const legs = [];
|
|
46445
|
+
let prevId = originId;
|
|
46446
|
+
for (const leg of rt.legs) {
|
|
46447
|
+
const destId = resolveStop(
|
|
46448
|
+
leg.dest,
|
|
46449
|
+
leg.destAlias,
|
|
46450
|
+
leg.destLabel,
|
|
46451
|
+
leg.destTags,
|
|
46452
|
+
void 0,
|
|
46453
|
+
// a leg's `value:` is leg thickness, not the dest's size
|
|
46454
|
+
leg.lineNumber
|
|
46455
|
+
);
|
|
46456
|
+
if (!destId) continue;
|
|
46457
|
+
legs.push({
|
|
46458
|
+
fromId: prevId,
|
|
46459
|
+
toId: destId,
|
|
46460
|
+
...leg.label !== void 0 && { label: leg.label },
|
|
46461
|
+
style: leg.style,
|
|
46462
|
+
...leg.value !== void 0 && { value: leg.value },
|
|
46463
|
+
lineNumber: leg.lineNumber
|
|
46464
|
+
});
|
|
46465
|
+
if (!stopIds.includes(destId)) stopIds.push(destId);
|
|
46466
|
+
prevId = destId;
|
|
46467
|
+
}
|
|
46468
|
+
routes.push({ stopIds, legs, lineNumber: rt.lineNumber });
|
|
46175
46469
|
}
|
|
46176
46470
|
const subdivisions = [];
|
|
46177
46471
|
if (usSubdivisionReferenced || parsed.directives.region === "us-states")
|
|
@@ -46183,7 +46477,7 @@ function resolveMap(parsed, data) {
|
|
|
46183
46477
|
}
|
|
46184
46478
|
for (const r of regions) {
|
|
46185
46479
|
if (r.layer === "country") {
|
|
46186
|
-
const bb =
|
|
46480
|
+
const bb = featureBboxPrimary(data.worldCoarse, r.iso);
|
|
46187
46481
|
if (bb) regionBoxes.push(bb);
|
|
46188
46482
|
}
|
|
46189
46483
|
}
|
|
@@ -46197,6 +46491,7 @@ function resolveMap(parsed, data) {
|
|
|
46197
46491
|
const lonSpan = extent2[1][0] - extent2[0][0];
|
|
46198
46492
|
const latSpan = extent2[1][1] - extent2[0][1];
|
|
46199
46493
|
const span = Math.max(lonSpan, latSpan);
|
|
46494
|
+
const maxAbsLat = Math.max(Math.abs(extent2[0][1]), Math.abs(extent2[1][1]));
|
|
46200
46495
|
const usDominant = (subdivisions.includes("us-states") || regions.some((r) => r.layer === "us-state")) && !regions.some((r) => r.layer === "country" && r.iso !== "US") && !anyNonUsPoi;
|
|
46201
46496
|
let projection;
|
|
46202
46497
|
const override = parsed.directives.projection;
|
|
@@ -46204,12 +46499,10 @@ function resolveMap(parsed, data) {
|
|
|
46204
46499
|
projection = override;
|
|
46205
46500
|
} else if (usDominant) {
|
|
46206
46501
|
projection = "albers-usa";
|
|
46207
|
-
} else if (span > WORLD_SPAN) {
|
|
46502
|
+
} else if (span > WORLD_SPAN || maxAbsLat > MERCATOR_MAX_LAT) {
|
|
46208
46503
|
projection = "equirectangular";
|
|
46209
|
-
} else if (span < MERCATOR_MAX_SPAN) {
|
|
46210
|
-
projection = "mercator";
|
|
46211
46504
|
} else {
|
|
46212
|
-
projection = "
|
|
46505
|
+
projection = "mercator";
|
|
46213
46506
|
}
|
|
46214
46507
|
if (lonSpan >= 180) {
|
|
46215
46508
|
extent2 = [
|
|
@@ -46263,14 +46556,14 @@ function firstError(diags) {
|
|
|
46263
46556
|
const e = diags.find((d) => d.severity === "error");
|
|
46264
46557
|
return e ? formatDgmoError(e) : null;
|
|
46265
46558
|
}
|
|
46266
|
-
var WORLD_SPAN,
|
|
46559
|
+
var WORLD_SPAN, MERCATOR_MAX_LAT, PAD_FRACTION, WORLD_LAT_SOUTH, WORLD_LAT_NORTH, REGION_ALIASES, US_STATE_POSTAL;
|
|
46267
46560
|
var init_resolver2 = __esm({
|
|
46268
46561
|
"src/map/resolver.ts"() {
|
|
46269
46562
|
"use strict";
|
|
46270
46563
|
init_diagnostics();
|
|
46271
46564
|
init_geo();
|
|
46272
46565
|
WORLD_SPAN = 90;
|
|
46273
|
-
|
|
46566
|
+
MERCATOR_MAX_LAT = 80;
|
|
46274
46567
|
PAD_FRACTION = 0.05;
|
|
46275
46568
|
WORLD_LAT_SOUTH = -58;
|
|
46276
46569
|
WORLD_LAT_NORTH = 78;
|
|
@@ -46295,115 +46588,59 @@ var init_resolver2 = __esm({
|
|
|
46295
46588
|
"north macedonia": "macedonia",
|
|
46296
46589
|
"czech republic": "czechia"
|
|
46297
46590
|
};
|
|
46298
|
-
|
|
46299
|
-
|
|
46300
|
-
|
|
46301
|
-
|
|
46302
|
-
|
|
46303
|
-
|
|
46304
|
-
|
|
46305
|
-
|
|
46306
|
-
|
|
46307
|
-
|
|
46308
|
-
|
|
46309
|
-
|
|
46310
|
-
|
|
46311
|
-
|
|
46312
|
-
|
|
46313
|
-
|
|
46314
|
-
|
|
46315
|
-
|
|
46316
|
-
|
|
46317
|
-
|
|
46318
|
-
|
|
46319
|
-
|
|
46320
|
-
|
|
46321
|
-
|
|
46322
|
-
|
|
46323
|
-
|
|
46324
|
-
|
|
46325
|
-
|
|
46326
|
-
|
|
46327
|
-
|
|
46328
|
-
|
|
46329
|
-
|
|
46330
|
-
|
|
46331
|
-
|
|
46332
|
-
|
|
46333
|
-
|
|
46334
|
-
|
|
46335
|
-
|
|
46336
|
-
|
|
46337
|
-
|
|
46338
|
-
|
|
46339
|
-
|
|
46340
|
-
|
|
46341
|
-
|
|
46342
|
-
|
|
46343
|
-
|
|
46344
|
-
|
|
46345
|
-
|
|
46346
|
-
|
|
46347
|
-
|
|
46348
|
-
|
|
46349
|
-
|
|
46350
|
-
const [
|
|
46351
|
-
worldCoarse,
|
|
46352
|
-
worldDetail,
|
|
46353
|
-
usStates,
|
|
46354
|
-
lakes,
|
|
46355
|
-
rivers,
|
|
46356
|
-
naLand,
|
|
46357
|
-
naLakes,
|
|
46358
|
-
gazetteer
|
|
46359
|
-
] = await Promise.all([
|
|
46360
|
-
readJson(nb, dir, FILES.worldCoarse),
|
|
46361
|
-
readJson(nb, dir, FILES.worldDetail),
|
|
46362
|
-
readJson(nb, dir, FILES.usStates),
|
|
46363
|
-
// Lakes/rivers/NA assets are optional — older bundles may predate them.
|
|
46364
|
-
readJson(nb, dir, FILES.lakes).catch(() => void 0),
|
|
46365
|
-
readJson(nb, dir, FILES.rivers).catch(() => void 0),
|
|
46366
|
-
readJson(nb, dir, FILES.naLand).catch(() => void 0),
|
|
46367
|
-
readJson(nb, dir, FILES.naLakes).catch(() => void 0),
|
|
46368
|
-
readJson(nb, dir, FILES.gazetteer)
|
|
46591
|
+
US_STATE_POSTAL = /* @__PURE__ */ new Set([
|
|
46592
|
+
"AL",
|
|
46593
|
+
"AK",
|
|
46594
|
+
"AZ",
|
|
46595
|
+
"AR",
|
|
46596
|
+
"CA",
|
|
46597
|
+
"CO",
|
|
46598
|
+
"CT",
|
|
46599
|
+
"DE",
|
|
46600
|
+
"FL",
|
|
46601
|
+
"GA",
|
|
46602
|
+
"HI",
|
|
46603
|
+
"ID",
|
|
46604
|
+
"IL",
|
|
46605
|
+
"IN",
|
|
46606
|
+
"IA",
|
|
46607
|
+
"KS",
|
|
46608
|
+
"KY",
|
|
46609
|
+
"LA",
|
|
46610
|
+
"ME",
|
|
46611
|
+
"MD",
|
|
46612
|
+
"MA",
|
|
46613
|
+
"MI",
|
|
46614
|
+
"MN",
|
|
46615
|
+
"MS",
|
|
46616
|
+
"MO",
|
|
46617
|
+
"MT",
|
|
46618
|
+
"NE",
|
|
46619
|
+
"NV",
|
|
46620
|
+
"NH",
|
|
46621
|
+
"NJ",
|
|
46622
|
+
"NM",
|
|
46623
|
+
"NY",
|
|
46624
|
+
"NC",
|
|
46625
|
+
"ND",
|
|
46626
|
+
"OH",
|
|
46627
|
+
"OK",
|
|
46628
|
+
"OR",
|
|
46629
|
+
"PA",
|
|
46630
|
+
"RI",
|
|
46631
|
+
"SC",
|
|
46632
|
+
"SD",
|
|
46633
|
+
"TN",
|
|
46634
|
+
"TX",
|
|
46635
|
+
"UT",
|
|
46636
|
+
"VT",
|
|
46637
|
+
"VA",
|
|
46638
|
+
"WA",
|
|
46639
|
+
"WV",
|
|
46640
|
+
"WI",
|
|
46641
|
+
"WY",
|
|
46642
|
+
"DC"
|
|
46369
46643
|
]);
|
|
46370
|
-
return validate({
|
|
46371
|
-
worldCoarse,
|
|
46372
|
-
worldDetail,
|
|
46373
|
-
usStates,
|
|
46374
|
-
gazetteer,
|
|
46375
|
-
...lakes && { lakes },
|
|
46376
|
-
...rivers && { rivers },
|
|
46377
|
-
...naLand && { naLand },
|
|
46378
|
-
...naLakes && { naLakes }
|
|
46379
|
-
});
|
|
46380
|
-
})().catch((e) => {
|
|
46381
|
-
cache = void 0;
|
|
46382
|
-
throw e;
|
|
46383
|
-
});
|
|
46384
|
-
return cache;
|
|
46385
|
-
}
|
|
46386
|
-
var import_meta, FILES, CANDIDATE_DIRS, cache;
|
|
46387
|
-
var init_load_data = __esm({
|
|
46388
|
-
"src/map/load-data.ts"() {
|
|
46389
|
-
"use strict";
|
|
46390
|
-
import_meta = {};
|
|
46391
|
-
FILES = {
|
|
46392
|
-
worldCoarse: "world-coarse.json",
|
|
46393
|
-
worldDetail: "world-detail.json",
|
|
46394
|
-
usStates: "us-states.json",
|
|
46395
|
-
lakes: "lakes.json",
|
|
46396
|
-
rivers: "rivers.json",
|
|
46397
|
-
naLand: "na-land.json",
|
|
46398
|
-
naLakes: "na-lakes.json",
|
|
46399
|
-
gazetteer: "gazetteer.json"
|
|
46400
|
-
};
|
|
46401
|
-
CANDIDATE_DIRS = [
|
|
46402
|
-
"./data",
|
|
46403
|
-
"./map-data",
|
|
46404
|
-
"../map-data",
|
|
46405
|
-
"../src/map/data"
|
|
46406
|
-
];
|
|
46407
46644
|
}
|
|
46408
46645
|
});
|
|
46409
46646
|
|
|
@@ -46433,10 +46670,14 @@ function projectionFor(family) {
|
|
|
46433
46670
|
return (0, import_d3_geo2.geoEquirectangular)();
|
|
46434
46671
|
}
|
|
46435
46672
|
}
|
|
46436
|
-
function mapBackgroundColor(palette) {
|
|
46437
|
-
return mix(
|
|
46673
|
+
function mapBackgroundColor(palette, isDark = false, _dataActive = false) {
|
|
46674
|
+
return mix(
|
|
46675
|
+
palette.colors.blue,
|
|
46676
|
+
palette.bg,
|
|
46677
|
+
isDark ? WATER_TINT_DARK : WATER_TINT_LIGHT
|
|
46678
|
+
);
|
|
46438
46679
|
}
|
|
46439
|
-
function mapNeutralLandColor(palette, isDark) {
|
|
46680
|
+
function mapNeutralLandColor(palette, isDark, _dataActive = false) {
|
|
46440
46681
|
return mix(
|
|
46441
46682
|
palette.colors.green,
|
|
46442
46683
|
palette.bg,
|
|
@@ -46462,28 +46703,19 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46462
46703
|
}
|
|
46463
46704
|
}
|
|
46464
46705
|
const usLayer = wantsUsStates ? decodeLayer(data.usStates) : null;
|
|
46465
|
-
const landTint = isDark ? LAND_TINT_DARK : LAND_TINT_LIGHT;
|
|
46466
|
-
const neutralFill = mix(palette.colors.green, palette.bg, landTint);
|
|
46467
|
-
const water = mapBackgroundColor(palette);
|
|
46468
46706
|
const usContext = usLayer !== null;
|
|
46469
|
-
const foreignFill = mix(
|
|
46470
|
-
palette.colors.gray,
|
|
46471
|
-
palette.bg,
|
|
46472
|
-
isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
46473
|
-
);
|
|
46474
46707
|
const regionStroke = isDark ? mix(palette.bg, palette.text, 78) : mix(palette.text, palette.bg, 78);
|
|
46475
|
-
const
|
|
46708
|
+
const values = resolved.regions.filter((r) => r.value !== void 0).map((r) => r.value);
|
|
46476
46709
|
const scaleOverride = resolved.directives.scale;
|
|
46477
|
-
const rampMin = scaleOverride ? scaleOverride.min : Math.min(...
|
|
46478
|
-
const rampMax = scaleOverride ? scaleOverride.max : Math.max(...
|
|
46479
|
-
const rampHue = palette.colors.red;
|
|
46480
|
-
const hasRamp =
|
|
46481
|
-
const
|
|
46710
|
+
const rampMin = scaleOverride ? scaleOverride.min : Math.min(...values);
|
|
46711
|
+
const rampMax = scaleOverride ? scaleOverride.max : Math.max(...values);
|
|
46712
|
+
const rampHue = resolveColor(resolved.directives.regionMetricColor ?? "", palette) ?? palette.colors.red;
|
|
46713
|
+
const hasRamp = values.length > 0;
|
|
46714
|
+
const VALUE_NAME = hasRamp ? resolved.directives.regionMetric?.trim() || "Value" : null;
|
|
46482
46715
|
const matchColorGroup = (v) => {
|
|
46483
46716
|
const lv = v.trim().toLowerCase();
|
|
46484
46717
|
if (lv === "none") return null;
|
|
46485
|
-
if (
|
|
46486
|
-
return SCORE_NAME;
|
|
46718
|
+
if (lv === VALUE_NAME?.toLowerCase()) return VALUE_NAME;
|
|
46487
46719
|
const tg = resolved.tagGroups.find((g) => g.name.toLowerCase() === lv);
|
|
46488
46720
|
return tg ? tg.name : v;
|
|
46489
46721
|
};
|
|
@@ -46494,11 +46726,20 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46494
46726
|
} else if (resolved.directives.activeTag !== void 0) {
|
|
46495
46727
|
activeGroup = matchColorGroup(resolved.directives.activeTag);
|
|
46496
46728
|
} else {
|
|
46497
|
-
activeGroup =
|
|
46729
|
+
activeGroup = VALUE_NAME ?? (resolved.tagGroups.length > 0 ? resolved.tagGroups[0].name : null);
|
|
46498
46730
|
}
|
|
46499
|
-
const activeIsScore =
|
|
46731
|
+
const activeIsScore = VALUE_NAME !== null && activeGroup === VALUE_NAME;
|
|
46732
|
+
const mutedBasemap = resolved.directives.basemapStyle === "muted" ? true : resolved.directives.basemapStyle === "natural" ? false : activeGroup !== null;
|
|
46733
|
+
const neutralFill = mapNeutralLandColor(palette, isDark, mutedBasemap);
|
|
46734
|
+
const water = mapBackgroundColor(palette, isDark, mutedBasemap);
|
|
46735
|
+
const lakeStroke = mix(regionStroke, water, 45);
|
|
46736
|
+
const foreignFill = mix(
|
|
46737
|
+
palette.colors.gray,
|
|
46738
|
+
palette.bg,
|
|
46739
|
+
mutedBasemap ? isDark ? MUTED_FOREIGN_DARK : MUTED_FOREIGN_LIGHT : isDark ? FOREIGN_TINT_DARK : FOREIGN_TINT_LIGHT
|
|
46740
|
+
);
|
|
46500
46741
|
const rampBase = isDark ? mix(palette.surface, palette.text, 28) : palette.bg;
|
|
46501
|
-
const
|
|
46742
|
+
const fillForValue = (s) => {
|
|
46502
46743
|
const t = rampMax > rampMin ? (s - rampMin) / (rampMax - rampMin) : 1;
|
|
46503
46744
|
const pct = RAMP_FLOOR + Math.max(0, Math.min(1, t)) * (100 - RAMP_FLOOR);
|
|
46504
46745
|
return mix(rampHue, rampBase, pct);
|
|
@@ -46521,9 +46762,16 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46521
46762
|
isDark ? TAG_TINT_DARK : TAG_TINT_LIGHT
|
|
46522
46763
|
);
|
|
46523
46764
|
};
|
|
46765
|
+
const directFill = (name) => {
|
|
46766
|
+
const hex = name ? resolveColor(name, palette) : null;
|
|
46767
|
+
if (!hex) return null;
|
|
46768
|
+
return mix(hex, palette.bg, isDark ? TAG_TINT_DARK : TAG_TINT_LIGHT);
|
|
46769
|
+
};
|
|
46524
46770
|
const regionFill = (r) => {
|
|
46771
|
+
const direct = directFill(r.color);
|
|
46772
|
+
if (direct) return direct;
|
|
46525
46773
|
if (activeIsScore) {
|
|
46526
|
-
return r.
|
|
46774
|
+
return r.value !== void 0 ? fillForValue(r.value) : neutralFill;
|
|
46527
46775
|
}
|
|
46528
46776
|
return tagFill(r.tags, activeGroup) ?? neutralFill;
|
|
46529
46777
|
};
|
|
@@ -46575,6 +46823,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46575
46823
|
const fitIsGlobal = fitGB[1][0] - fitGB[0][0] >= 270 || fitGB[1][1] - fitGB[0][1] >= 130;
|
|
46576
46824
|
let path;
|
|
46577
46825
|
let project;
|
|
46826
|
+
let stretchParams = null;
|
|
46578
46827
|
if (fitIsGlobal) {
|
|
46579
46828
|
const cb = (0, import_d3_geo2.geoPath)(projection).bounds(fitTarget);
|
|
46580
46829
|
const bx0 = cb[0][0];
|
|
@@ -46585,6 +46834,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46585
46834
|
const oy = fitBox[0][1];
|
|
46586
46835
|
const sx = cw > 0 ? (fitBox[1][0] - ox) / cw : 1;
|
|
46587
46836
|
const sy = ch > 0 ? (fitBox[1][1] - oy) / ch : 1;
|
|
46837
|
+
stretchParams = { sx, sy, ox, oy, bx0, by0 };
|
|
46588
46838
|
const stretch = (x, y) => [
|
|
46589
46839
|
ox + (x - bx0) * sx,
|
|
46590
46840
|
oy + (y - by0) * sy
|
|
@@ -46616,7 +46866,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46616
46866
|
const insets = [];
|
|
46617
46867
|
const insetRegions = [];
|
|
46618
46868
|
const insetLabelSeeds = [];
|
|
46619
|
-
if (resolved.projection === "albers-usa" && usLayer) {
|
|
46869
|
+
if (resolved.projection === "albers-usa" && usLayer && !resolved.directives.noInsets) {
|
|
46620
46870
|
const PAD = 8;
|
|
46621
46871
|
const GAP = 12;
|
|
46622
46872
|
const yB = height - FIT_PAD;
|
|
@@ -46647,38 +46897,14 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46647
46897
|
}
|
|
46648
46898
|
return y;
|
|
46649
46899
|
};
|
|
46650
|
-
const
|
|
46900
|
+
const coastFloor = (x0, xr) => {
|
|
46651
46901
|
const n = 24;
|
|
46652
|
-
const pts = [];
|
|
46653
46902
|
let maxY = -Infinity;
|
|
46654
46903
|
for (let i = 0; i <= n; i++) {
|
|
46655
|
-
const
|
|
46656
|
-
|
|
46657
|
-
|
|
46658
|
-
|
|
46659
|
-
if (y > maxY) maxY = y;
|
|
46660
|
-
}
|
|
46661
|
-
}
|
|
46662
|
-
if (pts.length === 0) return () => yB - height * 0.42;
|
|
46663
|
-
let m = 0;
|
|
46664
|
-
if (pts.length >= 2) {
|
|
46665
|
-
let sx = 0, sy = 0, sxx = 0, sxy = 0;
|
|
46666
|
-
for (const [x, y] of pts) {
|
|
46667
|
-
sx += x;
|
|
46668
|
-
sy += y;
|
|
46669
|
-
sxx += x * x;
|
|
46670
|
-
sxy += x * y;
|
|
46671
|
-
}
|
|
46672
|
-
const den = pts.length * sxx - sx * sx;
|
|
46673
|
-
if (den !== 0) m = (pts.length * sxy - sx * sy) / den;
|
|
46674
|
-
}
|
|
46675
|
-
m = Math.max(-0.35, Math.min(0.35, m));
|
|
46676
|
-
let c = -Infinity;
|
|
46677
|
-
for (const [x, y] of pts) {
|
|
46678
|
-
const need = y - m * x + GAP;
|
|
46679
|
-
if (need > c) c = need;
|
|
46680
|
-
}
|
|
46681
|
-
return (x) => m * x + c;
|
|
46904
|
+
const y = at(x0 + (xr - x0) * i / n);
|
|
46905
|
+
if (y > maxY) maxY = y;
|
|
46906
|
+
}
|
|
46907
|
+
return maxY;
|
|
46682
46908
|
};
|
|
46683
46909
|
const placeInset = (iso, proj, boxX, iwReq) => {
|
|
46684
46910
|
const f = usLayer.get(iso);
|
|
@@ -46687,19 +46913,15 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46687
46913
|
const iw = Math.min(iwReq, width - FIT_PAD - x0 - 2 * PAD);
|
|
46688
46914
|
if (iw < 24) return boxX;
|
|
46689
46915
|
const xr = x0 + iw + 2 * PAD;
|
|
46690
|
-
const
|
|
46691
|
-
const
|
|
46692
|
-
const yR = top(xr);
|
|
46916
|
+
const floor = coastFloor(x0, xr);
|
|
46917
|
+
const topGuess = floor > -Infinity ? floor + GAP : yB - height * 0.42;
|
|
46693
46918
|
proj.fitWidth(iw, f);
|
|
46694
46919
|
const bb = (0, import_d3_geo2.geoPath)(proj).bounds(f);
|
|
46695
46920
|
const sh = Number.isFinite(bb[0][0]) ? bb[1][1] - bb[0][1] : iw;
|
|
46696
46921
|
const needH = sh + 2 * PAD;
|
|
46697
|
-
let topFit =
|
|
46922
|
+
let topFit = topGuess;
|
|
46698
46923
|
const bottom = Math.min(topFit + needH, yB);
|
|
46699
46924
|
if (bottom - topFit < needH) topFit = bottom - needH;
|
|
46700
|
-
const lift = topFit - Math.max(yL, yR);
|
|
46701
|
-
const topL = yL + lift;
|
|
46702
|
-
const topR = yR + lift;
|
|
46703
46925
|
proj.fitExtent(
|
|
46704
46926
|
[
|
|
46705
46927
|
[x0 + PAD, topFit + PAD],
|
|
@@ -46718,15 +46940,18 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46718
46940
|
}
|
|
46719
46941
|
insets.push({
|
|
46720
46942
|
x: x0,
|
|
46721
|
-
y:
|
|
46943
|
+
y: topFit,
|
|
46722
46944
|
w: xr - x0,
|
|
46723
|
-
h: bottom -
|
|
46945
|
+
h: bottom - topFit,
|
|
46724
46946
|
points: [
|
|
46725
|
-
[x0,
|
|
46726
|
-
[xr,
|
|
46947
|
+
[x0, topFit],
|
|
46948
|
+
[xr, topFit],
|
|
46727
46949
|
[xr, bottom],
|
|
46728
46950
|
[x0, bottom]
|
|
46729
|
-
]
|
|
46951
|
+
],
|
|
46952
|
+
// The FITTED inset projection (just fit to this box) — captured so the
|
|
46953
|
+
// geo-query can invert pixels inside the frame back to AK/HI coords.
|
|
46954
|
+
projection: proj
|
|
46730
46955
|
});
|
|
46731
46956
|
insetRegions.push({
|
|
46732
46957
|
id: iso,
|
|
@@ -46735,7 +46960,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46735
46960
|
stroke: regionStroke,
|
|
46736
46961
|
lineNumber,
|
|
46737
46962
|
layer: "us-state",
|
|
46738
|
-
...r?.
|
|
46963
|
+
...r?.value !== void 0 && { value: r.value },
|
|
46739
46964
|
...r && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
46740
46965
|
});
|
|
46741
46966
|
const ctr = (0, import_d3_geo2.geoPath)(proj).centroid(f);
|
|
@@ -46878,7 +47103,7 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46878
47103
|
lineNumber,
|
|
46879
47104
|
layer,
|
|
46880
47105
|
...label !== void 0 && { label },
|
|
46881
|
-
...isThisLayer && r.
|
|
47106
|
+
...isThisLayer && r.value !== void 0 && { value: r.value },
|
|
46882
47107
|
...isThisLayer && Object.keys(r.tags).length > 0 && { tags: r.tags }
|
|
46883
47108
|
});
|
|
46884
47109
|
}
|
|
@@ -46896,13 +47121,40 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46896
47121
|
id: "lake",
|
|
46897
47122
|
d,
|
|
46898
47123
|
fill: water,
|
|
46899
|
-
stroke:
|
|
47124
|
+
stroke: lakeStroke,
|
|
46900
47125
|
lineNumber: -1,
|
|
46901
47126
|
layer: "base"
|
|
46902
47127
|
});
|
|
46903
47128
|
}
|
|
46904
47129
|
}
|
|
46905
|
-
const
|
|
47130
|
+
const relief = [];
|
|
47131
|
+
let reliefHatch = null;
|
|
47132
|
+
if (resolved.directives.relief === true && data.mountainRanges) {
|
|
47133
|
+
for (const [, f] of decodeLayer(data.mountainRanges)) {
|
|
47134
|
+
const viewF = isGlobalView ? dropFrameFillers(f) : cullFeatureToView(f);
|
|
47135
|
+
if (!viewF) continue;
|
|
47136
|
+
const area2 = path.area(viewF);
|
|
47137
|
+
if (!Number.isFinite(area2) || area2 < RELIEF_MIN_AREA) continue;
|
|
47138
|
+
const box = path.bounds(viewF);
|
|
47139
|
+
if (box[1][0] - box[0][0] < RELIEF_MIN_DIM || box[1][1] - box[0][1] < RELIEF_MIN_DIM)
|
|
47140
|
+
continue;
|
|
47141
|
+
const d = path(viewF) ?? "";
|
|
47142
|
+
if (!d) continue;
|
|
47143
|
+
relief.push({ d });
|
|
47144
|
+
}
|
|
47145
|
+
if (relief.length) {
|
|
47146
|
+
const darkTone = isDark ? palette.bg : palette.text;
|
|
47147
|
+
const lightTone = isDark ? palette.text : palette.bg;
|
|
47148
|
+
const landLum = relativeLuminance(neutralFill);
|
|
47149
|
+
const tone = Math.abs(landLum - relativeLuminance(darkTone)) > 0.04 ? darkTone : lightTone;
|
|
47150
|
+
reliefHatch = {
|
|
47151
|
+
color: mix(tone, neutralFill, RELIEF_HATCH_STRENGTH),
|
|
47152
|
+
spacing: RELIEF_HATCH_SPACING,
|
|
47153
|
+
width: RELIEF_HATCH_WIDTH
|
|
47154
|
+
};
|
|
47155
|
+
}
|
|
47156
|
+
}
|
|
47157
|
+
const riverColor = mix(water, regionStroke, 16);
|
|
46906
47158
|
const rivers = [];
|
|
46907
47159
|
if (data.rivers) {
|
|
46908
47160
|
for (const [, f] of decodeLayer(data.rivers)) {
|
|
@@ -46913,16 +47165,19 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46913
47165
|
rivers.push({ d, color: riverColor, width: RIVER_WIDTH });
|
|
46914
47166
|
}
|
|
46915
47167
|
}
|
|
46916
|
-
const sizeVals = resolved.pois.map((p) => Number(p.meta["
|
|
47168
|
+
const sizeVals = resolved.pois.map((p) => Number(p.meta["value"])).filter((n) => Number.isFinite(n) && n > 0);
|
|
46917
47169
|
const sizeMin = sizeVals.length ? Math.min(...sizeVals) : 0;
|
|
46918
47170
|
const sizeMax = sizeVals.length ? Math.max(...sizeVals) : 0;
|
|
46919
47171
|
const radiusFor = (p) => {
|
|
46920
|
-
const v = Number(p.meta["
|
|
47172
|
+
const v = Number(p.meta["value"]);
|
|
46921
47173
|
if (!Number.isFinite(v) || v <= 0 || sizeMax <= 0) return R_DEFAULT;
|
|
46922
47174
|
const t = sizeMax > sizeMin ? (Math.sqrt(v) - Math.sqrt(sizeMin)) / (Math.sqrt(sizeMax) - Math.sqrt(sizeMin)) : 1;
|
|
46923
47175
|
return R_MIN + Math.max(0, Math.min(1, t)) * (R_MAX - R_MIN);
|
|
46924
47176
|
};
|
|
46925
47177
|
const poiFill = (p) => {
|
|
47178
|
+
const directHex = p.color ? resolveColor(p.color, palette) : null;
|
|
47179
|
+
if (directHex)
|
|
47180
|
+
return { fill: directHex, stroke: mix(directHex, palette.text, 18) };
|
|
46926
47181
|
for (const group of resolved.tagGroups) {
|
|
46927
47182
|
const val = p.tags[group.name.toLowerCase()];
|
|
46928
47183
|
if (!val) continue;
|
|
@@ -46984,7 +47239,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
46984
47239
|
lineNumber: e.p.lineNumber,
|
|
46985
47240
|
implicit: !!e.p.implicit,
|
|
46986
47241
|
isOrigin: originIds.has(e.p.id),
|
|
46987
|
-
...num !== void 0 && { routeNumber: num }
|
|
47242
|
+
...num !== void 0 && { routeNumber: num },
|
|
47243
|
+
...Object.keys(e.p.tags).length > 0 && { tags: e.p.tags }
|
|
46988
47244
|
});
|
|
46989
47245
|
});
|
|
46990
47246
|
}
|
|
@@ -47020,26 +47276,40 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47020
47276
|
const by = b.cy - (b.cy - py) / tb * trimB;
|
|
47021
47277
|
return `M${ax},${ay}Q${px},${py} ${bx},${by}`;
|
|
47022
47278
|
};
|
|
47279
|
+
const routeLegVals = resolved.routes.flatMap((rt) => rt.legs).map((l) => Number(l.value)).filter((n) => Number.isFinite(n) && n > 0);
|
|
47280
|
+
const rlMin = routeLegVals.length ? Math.min(...routeLegVals) : 0;
|
|
47281
|
+
const rlMax = routeLegVals.length ? Math.max(...routeLegVals) : 0;
|
|
47282
|
+
const routeWidthFor = (v) => {
|
|
47283
|
+
if (!Number.isFinite(v) || v <= 0 || rlMax <= 0) return W_MIN;
|
|
47284
|
+
const t = rlMax > rlMin ? (v - rlMin) / (rlMax - rlMin) : 1;
|
|
47285
|
+
return W_MIN + t * (W_MAX - W_MIN);
|
|
47286
|
+
};
|
|
47023
47287
|
for (const rt of resolved.routes) {
|
|
47024
|
-
const
|
|
47025
|
-
|
|
47026
|
-
const
|
|
47027
|
-
const b = poiScreen.get(rt.stopIds[i]);
|
|
47288
|
+
for (const leg of rt.legs) {
|
|
47289
|
+
const a = poiScreen.get(leg.fromId);
|
|
47290
|
+
const b = poiScreen.get(leg.toId);
|
|
47028
47291
|
if (!a || !b) continue;
|
|
47292
|
+
const mx = (a.cx + b.cx) / 2;
|
|
47293
|
+
const my = (a.cy + b.cy) / 2;
|
|
47029
47294
|
legs.push({
|
|
47030
|
-
d: legPath(a, b,
|
|
47031
|
-
width:
|
|
47295
|
+
d: legPath(a, b, leg.style === "arc", 0),
|
|
47296
|
+
width: routeWidthFor(Number(leg.value)),
|
|
47032
47297
|
color: mix(palette.text, palette.bg, 72),
|
|
47033
47298
|
arrow: true,
|
|
47034
|
-
lineNumber:
|
|
47299
|
+
lineNumber: leg.lineNumber,
|
|
47300
|
+
...leg.label !== void 0 && {
|
|
47301
|
+
label: leg.label,
|
|
47302
|
+
labelX: mx,
|
|
47303
|
+
labelY: my - 4
|
|
47304
|
+
}
|
|
47035
47305
|
});
|
|
47036
47306
|
}
|
|
47037
47307
|
}
|
|
47038
|
-
const weightVals = resolved.edges.map((e) => Number(e.meta["
|
|
47308
|
+
const weightVals = resolved.edges.map((e) => Number(e.meta["value"])).filter((n) => Number.isFinite(n) && n > 0);
|
|
47039
47309
|
const wMin = weightVals.length ? Math.min(...weightVals) : 0;
|
|
47040
47310
|
const wMax = weightVals.length ? Math.max(...weightVals) : 0;
|
|
47041
47311
|
const widthFor = (e) => {
|
|
47042
|
-
const v = Number(e.meta["
|
|
47312
|
+
const v = Number(e.meta["value"]);
|
|
47043
47313
|
if (!Number.isFinite(v) || v <= 0 || wMax <= 0) return W_MIN;
|
|
47044
47314
|
const t = wMax > wMin ? (v - wMin) / (wMax - wMin) : 1;
|
|
47045
47315
|
return W_MIN + t * (W_MAX - W_MIN);
|
|
@@ -47302,8 +47572,8 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47302
47572
|
activeGroup,
|
|
47303
47573
|
...hasRamp && {
|
|
47304
47574
|
ramp: {
|
|
47305
|
-
...resolved.directives.
|
|
47306
|
-
metric: resolved.directives.
|
|
47575
|
+
...resolved.directives.regionMetric !== void 0 && {
|
|
47576
|
+
metric: resolved.directives.regionMetric
|
|
47307
47577
|
},
|
|
47308
47578
|
min: rampMin,
|
|
47309
47579
|
max: rampMax,
|
|
@@ -47323,21 +47593,26 @@ function layoutMap(resolved, data, size, opts) {
|
|
|
47323
47593
|
...resolved.caption !== void 0 && { caption: resolved.caption },
|
|
47324
47594
|
regions,
|
|
47325
47595
|
rivers,
|
|
47596
|
+
relief,
|
|
47597
|
+
reliefHatch,
|
|
47326
47598
|
legs,
|
|
47327
47599
|
pois,
|
|
47328
47600
|
labels,
|
|
47329
47601
|
legend,
|
|
47330
47602
|
insets,
|
|
47331
|
-
insetRegions
|
|
47603
|
+
insetRegions,
|
|
47604
|
+
projection,
|
|
47605
|
+
stretch: stretchParams
|
|
47332
47606
|
};
|
|
47333
47607
|
}
|
|
47334
|
-
var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT, COLO_EPS, LAND_TINT_LIGHT, LAND_TINT_DARK, TAG_TINT_LIGHT, TAG_TINT_DARK,
|
|
47608
|
+
var import_d3_geo2, import_topojson_client2, FIT_PAD, RAMP_FLOOR, R_DEFAULT, R_MIN, R_MAX, W_MIN, W_MAX, FONT, COLO_EPS, LAND_TINT_LIGHT, LAND_TINT_DARK, TAG_TINT_LIGHT, TAG_TINT_DARK, WATER_TINT_LIGHT, WATER_TINT_DARK, RIVER_WIDTH, RELIEF_MIN_AREA, RELIEF_MIN_DIM, RELIEF_HATCH_SPACING, RELIEF_HATCH_WIDTH, RELIEF_HATCH_STRENGTH, FOREIGN_TINT_LIGHT, FOREIGN_TINT_DARK, MUTED_FOREIGN_LIGHT, MUTED_FOREIGN_DARK, COLO_R, GOLDEN_ANGLE, FAN_STEP, ARC_CURVE_FRAC, usConusProjection, alaskaProjection, hawaiiProjection, INSET_STATES, US_NON_CONUS;
|
|
47335
47609
|
var init_layout15 = __esm({
|
|
47336
47610
|
"src/map/layout.ts"() {
|
|
47337
47611
|
"use strict";
|
|
47338
47612
|
import_d3_geo2 = require("d3-geo");
|
|
47339
47613
|
import_topojson_client2 = require("topojson-client");
|
|
47340
47614
|
init_color_utils();
|
|
47615
|
+
init_colors();
|
|
47341
47616
|
init_label_layout();
|
|
47342
47617
|
init_legend_constants();
|
|
47343
47618
|
init_title_constants();
|
|
@@ -47350,14 +47625,22 @@ var init_layout15 = __esm({
|
|
|
47350
47625
|
W_MAX = 8;
|
|
47351
47626
|
FONT = 11;
|
|
47352
47627
|
COLO_EPS = 1.5;
|
|
47353
|
-
LAND_TINT_LIGHT =
|
|
47354
|
-
LAND_TINT_DARK =
|
|
47628
|
+
LAND_TINT_LIGHT = 12;
|
|
47629
|
+
LAND_TINT_DARK = 24;
|
|
47355
47630
|
TAG_TINT_LIGHT = 60;
|
|
47356
47631
|
TAG_TINT_DARK = 68;
|
|
47357
|
-
|
|
47632
|
+
WATER_TINT_LIGHT = 13;
|
|
47633
|
+
WATER_TINT_DARK = 14;
|
|
47358
47634
|
RIVER_WIDTH = 1.3;
|
|
47635
|
+
RELIEF_MIN_AREA = 12;
|
|
47636
|
+
RELIEF_MIN_DIM = 2;
|
|
47637
|
+
RELIEF_HATCH_SPACING = 3;
|
|
47638
|
+
RELIEF_HATCH_WIDTH = 0.25;
|
|
47639
|
+
RELIEF_HATCH_STRENGTH = 32;
|
|
47359
47640
|
FOREIGN_TINT_LIGHT = 30;
|
|
47360
47641
|
FOREIGN_TINT_DARK = 62;
|
|
47642
|
+
MUTED_FOREIGN_LIGHT = 28;
|
|
47643
|
+
MUTED_FOREIGN_DARK = 16;
|
|
47361
47644
|
COLO_R = 9;
|
|
47362
47645
|
GOLDEN_ANGLE = 2.399963229728653;
|
|
47363
47646
|
FAN_STEP = 16;
|
|
@@ -47411,7 +47694,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47411
47694
|
const p = g.append("path").attr("d", r.d).attr("fill", r.fill).attr("stroke", r.stroke).attr("stroke-width", strokeWidth);
|
|
47412
47695
|
if (r.layer !== "base") {
|
|
47413
47696
|
p.classed("dgmo-map-region", true).attr("data-region", r.id);
|
|
47414
|
-
if (r.
|
|
47697
|
+
if (r.value !== void 0) p.attr("data-value", r.value);
|
|
47415
47698
|
if (r.tags) {
|
|
47416
47699
|
for (const [group, value] of Object.entries(r.tags)) {
|
|
47417
47700
|
p.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
@@ -47429,6 +47712,20 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47429
47712
|
}
|
|
47430
47713
|
};
|
|
47431
47714
|
for (const r of layout.regions) drawRegion(gRegions, r, 0.5);
|
|
47715
|
+
if (layout.relief.length && layout.reliefHatch) {
|
|
47716
|
+
const h = layout.reliefHatch;
|
|
47717
|
+
const rangeClipId = "dgmo-relief-clip";
|
|
47718
|
+
const landClipId = "dgmo-relief-land";
|
|
47719
|
+
const rangeClip = defs.append("clipPath").attr("id", rangeClipId);
|
|
47720
|
+
for (const s of layout.relief) rangeClip.append("path").attr("d", s.d);
|
|
47721
|
+
const landClip = defs.append("clipPath").attr("id", landClipId);
|
|
47722
|
+
for (const r of layout.regions)
|
|
47723
|
+
if (r.id !== "lake") landClip.append("path").attr("d", r.d);
|
|
47724
|
+
const gRelief = svg.append("g").attr("clip-path", `url(#${landClipId})`).append("g").attr("class", "dgmo-map-relief").attr("clip-path", `url(#${rangeClipId})`).attr("stroke", h.color).attr("stroke-width", h.width).attr("vector-effect", "non-scaling-stroke");
|
|
47725
|
+
for (let y = h.spacing; y < height; y += h.spacing) {
|
|
47726
|
+
gRelief.append("line").attr("x1", 0).attr("y1", y).attr("x2", width).attr("y2", y);
|
|
47727
|
+
}
|
|
47728
|
+
}
|
|
47432
47729
|
if (layout.rivers.length) {
|
|
47433
47730
|
const gRivers = svg.append("g").attr("class", "dgmo-map-rivers").attr("fill", "none");
|
|
47434
47731
|
for (const r of layout.rivers) {
|
|
@@ -47472,6 +47769,11 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47472
47769
|
gPois.append("circle").attr("cx", poi.cx).attr("cy", poi.cy).attr("r", poi.r + 3).attr("fill", "none").attr("stroke", poi.stroke).attr("stroke-width", 1.5);
|
|
47473
47770
|
}
|
|
47474
47771
|
const c = gPois.append("circle").attr("cx", poi.cx).attr("cy", poi.cy).attr("r", poi.r).attr("fill", poi.fill).attr("stroke", poi.stroke).attr("stroke-width", 1).attr("data-line-number", poi.lineNumber).attr("data-poi", poi.id);
|
|
47772
|
+
if (poi.tags) {
|
|
47773
|
+
for (const [group, value] of Object.entries(poi.tags)) {
|
|
47774
|
+
c.attr(`data-tag-${group.toLowerCase()}`, value.toLowerCase());
|
|
47775
|
+
}
|
|
47776
|
+
}
|
|
47475
47777
|
if (onClickItem) {
|
|
47476
47778
|
c.style("cursor", "pointer").on(
|
|
47477
47779
|
"click",
|
|
@@ -47521,7 +47823,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47521
47823
|
const legendG = svg.append("g").attr("class", "dgmo-map-legend").attr("transform", `translate(0, ${legendY})`);
|
|
47522
47824
|
const ramp = layout.legend.ramp;
|
|
47523
47825
|
const scoreGroup = ramp ? {
|
|
47524
|
-
name: ramp.metric?.trim() || "
|
|
47826
|
+
name: ramp.metric?.trim() || "Value",
|
|
47525
47827
|
entries: [],
|
|
47526
47828
|
gradient: {
|
|
47527
47829
|
min: ramp.min,
|
|
@@ -47548,7 +47850,7 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
|
|
|
47548
47850
|
}
|
|
47549
47851
|
}
|
|
47550
47852
|
if (layout.title) {
|
|
47551
|
-
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 4).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.title);
|
|
47853
|
+
svg.append("text").attr("class", "dgmo-map-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).attr("fill", palette.text).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 4).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.title);
|
|
47552
47854
|
}
|
|
47553
47855
|
if (layout.subtitle) {
|
|
47554
47856
|
svg.append("text").attr("x", width / 2).attr("y", TITLE_Y + TITLE_FONT_SIZE).attr("text-anchor", "middle").attr("font-size", LABEL_FONT + 1).attr("fill", palette.textMuted).attr("paint-order", "stroke fill").attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("stroke-opacity", 0.7).text(layout.subtitle);
|
|
@@ -47581,6 +47883,121 @@ var init_renderer16 = __esm({
|
|
|
47581
47883
|
}
|
|
47582
47884
|
});
|
|
47583
47885
|
|
|
47886
|
+
// src/map/load-data.ts
|
|
47887
|
+
var load_data_exports = {};
|
|
47888
|
+
__export(load_data_exports, {
|
|
47889
|
+
loadMapData: () => loadMapData
|
|
47890
|
+
});
|
|
47891
|
+
async function loadNodeBuiltins() {
|
|
47892
|
+
const [{ readFile }, { fileURLToPath }, { dirname: dirname2, resolve }] = await Promise.all([
|
|
47893
|
+
import("fs/promises"),
|
|
47894
|
+
import("url"),
|
|
47895
|
+
import("path")
|
|
47896
|
+
]);
|
|
47897
|
+
return { readFile, fileURLToPath, dirname: dirname2, resolve };
|
|
47898
|
+
}
|
|
47899
|
+
async function readJson(nb, dir, name) {
|
|
47900
|
+
return JSON.parse(await nb.readFile(nb.resolve(dir, name), "utf8"));
|
|
47901
|
+
}
|
|
47902
|
+
async function firstExistingDir(nb, baseDir) {
|
|
47903
|
+
for (const rel of CANDIDATE_DIRS) {
|
|
47904
|
+
const dir = nb.resolve(baseDir, rel);
|
|
47905
|
+
try {
|
|
47906
|
+
await nb.readFile(nb.resolve(dir, FILES.gazetteer), "utf8");
|
|
47907
|
+
return dir;
|
|
47908
|
+
} catch {
|
|
47909
|
+
}
|
|
47910
|
+
}
|
|
47911
|
+
throw new Error(
|
|
47912
|
+
`map data assets not found near ${baseDir} (looked in ${CANDIDATE_DIRS.join(", ")}). Run \`pnpm build:map-data\` and \`pnpm build\`.`
|
|
47913
|
+
);
|
|
47914
|
+
}
|
|
47915
|
+
function validate(data) {
|
|
47916
|
+
const topoOk = (t) => !!t && t.type === "Topology" && !!t.objects;
|
|
47917
|
+
if (!topoOk(data.worldCoarse) || !topoOk(data.worldDetail) || !topoOk(data.usStates) || !data.gazetteer || !Array.isArray(data.gazetteer.cities) || !data.gazetteer.byName) {
|
|
47918
|
+
throw new Error("map data assets are malformed (failed shape validation)");
|
|
47919
|
+
}
|
|
47920
|
+
return data;
|
|
47921
|
+
}
|
|
47922
|
+
function moduleBaseDir(nb) {
|
|
47923
|
+
try {
|
|
47924
|
+
const url = import_meta.url;
|
|
47925
|
+
if (url) return nb.dirname(nb.fileURLToPath(url));
|
|
47926
|
+
} catch {
|
|
47927
|
+
}
|
|
47928
|
+
if (typeof __dirname !== "undefined") return __dirname;
|
|
47929
|
+
return process.cwd();
|
|
47930
|
+
}
|
|
47931
|
+
function loadMapData() {
|
|
47932
|
+
cache ??= (async () => {
|
|
47933
|
+
const nb = await loadNodeBuiltins();
|
|
47934
|
+
const dir = await firstExistingDir(nb, moduleBaseDir(nb));
|
|
47935
|
+
const [
|
|
47936
|
+
worldCoarse,
|
|
47937
|
+
worldDetail,
|
|
47938
|
+
usStates,
|
|
47939
|
+
lakes,
|
|
47940
|
+
rivers,
|
|
47941
|
+
mountainRanges,
|
|
47942
|
+
naLand,
|
|
47943
|
+
naLakes,
|
|
47944
|
+
gazetteer
|
|
47945
|
+
] = await Promise.all([
|
|
47946
|
+
readJson(nb, dir, FILES.worldCoarse),
|
|
47947
|
+
readJson(nb, dir, FILES.worldDetail),
|
|
47948
|
+
readJson(nb, dir, FILES.usStates),
|
|
47949
|
+
// Lakes/rivers/mountain/NA assets are optional — older bundles may predate them.
|
|
47950
|
+
readJson(nb, dir, FILES.lakes).catch(() => void 0),
|
|
47951
|
+
readJson(nb, dir, FILES.rivers).catch(() => void 0),
|
|
47952
|
+
readJson(nb, dir, FILES.mountainRanges).catch(
|
|
47953
|
+
() => void 0
|
|
47954
|
+
),
|
|
47955
|
+
readJson(nb, dir, FILES.naLand).catch(() => void 0),
|
|
47956
|
+
readJson(nb, dir, FILES.naLakes).catch(() => void 0),
|
|
47957
|
+
readJson(nb, dir, FILES.gazetteer)
|
|
47958
|
+
]);
|
|
47959
|
+
return validate({
|
|
47960
|
+
worldCoarse,
|
|
47961
|
+
worldDetail,
|
|
47962
|
+
usStates,
|
|
47963
|
+
gazetteer,
|
|
47964
|
+
...lakes && { lakes },
|
|
47965
|
+
...rivers && { rivers },
|
|
47966
|
+
...mountainRanges && { mountainRanges },
|
|
47967
|
+
...naLand && { naLand },
|
|
47968
|
+
...naLakes && { naLakes }
|
|
47969
|
+
});
|
|
47970
|
+
})().catch((e) => {
|
|
47971
|
+
cache = void 0;
|
|
47972
|
+
throw e;
|
|
47973
|
+
});
|
|
47974
|
+
return cache;
|
|
47975
|
+
}
|
|
47976
|
+
var import_meta, FILES, CANDIDATE_DIRS, cache;
|
|
47977
|
+
var init_load_data = __esm({
|
|
47978
|
+
"src/map/load-data.ts"() {
|
|
47979
|
+
"use strict";
|
|
47980
|
+
import_meta = {};
|
|
47981
|
+
FILES = {
|
|
47982
|
+
worldCoarse: "world-coarse.json",
|
|
47983
|
+
worldDetail: "world-detail.json",
|
|
47984
|
+
usStates: "us-states.json",
|
|
47985
|
+
lakes: "lakes.json",
|
|
47986
|
+
rivers: "rivers.json",
|
|
47987
|
+
mountainRanges: "mountain-ranges.json",
|
|
47988
|
+
naLand: "na-land.json",
|
|
47989
|
+
naLakes: "na-lakes.json",
|
|
47990
|
+
gazetteer: "gazetteer.json"
|
|
47991
|
+
};
|
|
47992
|
+
CANDIDATE_DIRS = [
|
|
47993
|
+
"./data",
|
|
47994
|
+
"./map-data",
|
|
47995
|
+
"../map-data",
|
|
47996
|
+
"../src/map/data"
|
|
47997
|
+
];
|
|
47998
|
+
}
|
|
47999
|
+
});
|
|
48000
|
+
|
|
47584
48001
|
// src/pyramid/renderer.ts
|
|
47585
48002
|
var renderer_exports17 = {};
|
|
47586
48003
|
__export(renderer_exports17, {
|
|
@@ -55760,15 +56177,17 @@ async function renderForExport(content, theme, palette, viewState, options) {
|
|
|
55760
56177
|
if (detectedType === "map") {
|
|
55761
56178
|
const { parseMap: parseMap2 } = await Promise.resolve().then(() => (init_parser12(), parser_exports11));
|
|
55762
56179
|
const { resolveMap: resolveMap2 } = await Promise.resolve().then(() => (init_resolver2(), resolver_exports));
|
|
55763
|
-
const { loadMapData: loadMapData2 } = await Promise.resolve().then(() => (init_load_data(), load_data_exports));
|
|
55764
56180
|
const { renderMapForExport: renderMapForExport2 } = await Promise.resolve().then(() => (init_renderer16(), renderer_exports16));
|
|
55765
56181
|
const effectivePalette2 = await resolveExportPalette(theme, palette);
|
|
55766
56182
|
const mapParsed = parseMap2(content);
|
|
55767
|
-
let mapData;
|
|
55768
|
-
|
|
55769
|
-
|
|
55770
|
-
|
|
55771
|
-
|
|
56183
|
+
let mapData = options?.mapData;
|
|
56184
|
+
if (!mapData) {
|
|
56185
|
+
const { loadMapData: loadMapData2 } = await Promise.resolve().then(() => (init_load_data(), load_data_exports));
|
|
56186
|
+
try {
|
|
56187
|
+
mapData = await loadMapData2();
|
|
56188
|
+
} catch {
|
|
56189
|
+
return "";
|
|
56190
|
+
}
|
|
55772
56191
|
}
|
|
55773
56192
|
const mapResolved = resolveMap2(mapParsed, mapData);
|
|
55774
56193
|
const container2 = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
|
|
@@ -56619,6 +57038,7 @@ __export(internal_exports, {
|
|
|
56619
57038
|
computeTimeTicks: () => computeTimeTicks,
|
|
56620
57039
|
contrastText: () => contrastText,
|
|
56621
57040
|
controlsGroupCapsuleWidth: () => controlsGroupCapsuleWidth,
|
|
57041
|
+
createMapGeoQuery: () => createMapGeoQuery,
|
|
56622
57042
|
decodeDiagramUrl: () => decodeDiagramUrl,
|
|
56623
57043
|
decodeViewState: () => decodeViewState,
|
|
56624
57044
|
displayName: () => displayName,
|
|
@@ -57347,6 +57767,160 @@ init_load_data();
|
|
|
57347
57767
|
init_layout15();
|
|
57348
57768
|
init_renderer16();
|
|
57349
57769
|
|
|
57770
|
+
// src/map/geo-query.ts
|
|
57771
|
+
init_parser12();
|
|
57772
|
+
init_resolver2();
|
|
57773
|
+
init_layout15();
|
|
57774
|
+
init_geo();
|
|
57775
|
+
|
|
57776
|
+
// src/map/invert.ts
|
|
57777
|
+
function inInsetFrame(inset, px, py) {
|
|
57778
|
+
return px >= inset.x && px <= inset.x + inset.w && py >= inset.y && py <= inset.y + inset.h;
|
|
57779
|
+
}
|
|
57780
|
+
function unstretch(layout, px, py) {
|
|
57781
|
+
const s = layout.stretch;
|
|
57782
|
+
return [
|
|
57783
|
+
s.bx0 + (s.sx !== 0 ? (px - s.ox) / s.sx : 0),
|
|
57784
|
+
s.by0 + (s.sy !== 0 ? (py - s.oy) / s.sy : 0)
|
|
57785
|
+
];
|
|
57786
|
+
}
|
|
57787
|
+
function applyStretch(layout, x, y) {
|
|
57788
|
+
const s = layout.stretch;
|
|
57789
|
+
return [s.ox + (x - s.bx0) * s.sx, s.oy + (y - s.by0) * s.sy];
|
|
57790
|
+
}
|
|
57791
|
+
function pixelToLonLat(layout, px, py) {
|
|
57792
|
+
for (const inset of layout.insets) {
|
|
57793
|
+
if (inInsetFrame(inset, px, py)) {
|
|
57794
|
+
const ll2 = inset.projection.invert?.([px, py]);
|
|
57795
|
+
return ll2 && Number.isFinite(ll2[0]) && Number.isFinite(ll2[1]) ? [ll2[0], ll2[1]] : null;
|
|
57796
|
+
}
|
|
57797
|
+
}
|
|
57798
|
+
const [x, y] = layout.stretch ? unstretch(layout, px, py) : [px, py];
|
|
57799
|
+
const ll = layout.projection.invert?.([x, y]);
|
|
57800
|
+
return ll && Number.isFinite(ll[0]) && Number.isFinite(ll[1]) ? [ll[0], ll[1]] : null;
|
|
57801
|
+
}
|
|
57802
|
+
function lonLatToPixel(layout, lonLat) {
|
|
57803
|
+
const pt = [lonLat[0], lonLat[1]];
|
|
57804
|
+
const main = layout.projection(pt);
|
|
57805
|
+
const mainPx = main && Number.isFinite(main[0]) && Number.isFinite(main[1]) ? layout.stretch ? applyStretch(layout, main[0], main[1]) : [main[0], main[1]] : null;
|
|
57806
|
+
const onCanvas = !!mainPx && mainPx[0] >= 0 && mainPx[0] <= layout.width && mainPx[1] >= 0 && mainPx[1] <= layout.height;
|
|
57807
|
+
if (onCanvas) return mainPx;
|
|
57808
|
+
for (const inset of layout.insets) {
|
|
57809
|
+
const p = inset.projection(pt);
|
|
57810
|
+
if (p && Number.isFinite(p[0]) && Number.isFinite(p[1]) && inInsetFrame(inset, p[0], p[1]))
|
|
57811
|
+
return [p[0], p[1]];
|
|
57812
|
+
}
|
|
57813
|
+
return mainPx;
|
|
57814
|
+
}
|
|
57815
|
+
|
|
57816
|
+
// src/map/geo-query.ts
|
|
57817
|
+
var EARTH_R_KM = 6371;
|
|
57818
|
+
var DEG = Math.PI / 180;
|
|
57819
|
+
function haversineKm(lat1, lon1, lat2, lon2) {
|
|
57820
|
+
const dLat = (lat2 - lat1) * DEG;
|
|
57821
|
+
const dLon = (lon2 - lon1) * DEG;
|
|
57822
|
+
const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * DEG) * Math.cos(lat2 * DEG) * Math.sin(dLon / 2) ** 2;
|
|
57823
|
+
return 2 * EARTH_R_KM * Math.asin(Math.min(1, Math.sqrt(a)));
|
|
57824
|
+
}
|
|
57825
|
+
var POP_PULL_KM = 12;
|
|
57826
|
+
function nearestCity(lonLat, gazetteer) {
|
|
57827
|
+
const [lon, lat] = lonLat;
|
|
57828
|
+
let best = null;
|
|
57829
|
+
const cities = gazetteer.cities;
|
|
57830
|
+
for (let i = 0; i < cities.length; i++) {
|
|
57831
|
+
const c2 = cities[i];
|
|
57832
|
+
const dist = haversineKm(lat, lon, c2[0], c2[1]);
|
|
57833
|
+
const score = dist - POP_PULL_KM * Math.log10((c2[3] || 0) + 1);
|
|
57834
|
+
if (!best || score < best.score) best = { score, idx: i, dist };
|
|
57835
|
+
}
|
|
57836
|
+
if (!best) return null;
|
|
57837
|
+
const c = cities[best.idx];
|
|
57838
|
+
return {
|
|
57839
|
+
name: c[4],
|
|
57840
|
+
iso: c[2],
|
|
57841
|
+
...c[5] !== void 0 && { sub: c[5] },
|
|
57842
|
+
distanceKm: best.dist
|
|
57843
|
+
};
|
|
57844
|
+
}
|
|
57845
|
+
function roundCoord(n) {
|
|
57846
|
+
return Number(n.toFixed(2));
|
|
57847
|
+
}
|
|
57848
|
+
function buildTokens(lonLat, region, city) {
|
|
57849
|
+
const coordPoiLine = `poi ${roundCoord(lonLat[1])} ${roundCoord(lonLat[0])}`;
|
|
57850
|
+
let stateTok = null;
|
|
57851
|
+
if (region.state) {
|
|
57852
|
+
const { iso, name } = region.state;
|
|
57853
|
+
stateTok = { primary: `${name} ${iso}`, alternates: [iso, name] };
|
|
57854
|
+
}
|
|
57855
|
+
let countryTok = null;
|
|
57856
|
+
if (region.country) {
|
|
57857
|
+
const { iso, name } = region.country;
|
|
57858
|
+
countryTok = { primary: name, alternates: [iso] };
|
|
57859
|
+
}
|
|
57860
|
+
let cityTok = null;
|
|
57861
|
+
if (city) {
|
|
57862
|
+
const scope = city.sub ?? (city.iso || "");
|
|
57863
|
+
cityTok = scope ? { token: `poi ${city.name} ${scope}`, ambiguous: false } : { token: `poi ${city.name}`, ambiguous: true };
|
|
57864
|
+
}
|
|
57865
|
+
return { coordPoiLine, state: stateTok, country: countryTok, city: cityTok };
|
|
57866
|
+
}
|
|
57867
|
+
var MAX_CITY_DOTS = 250;
|
|
57868
|
+
function createMapGeoQuery(opts) {
|
|
57869
|
+
const { content, width, height, data, palette, isDark } = opts;
|
|
57870
|
+
const resolved = resolveMap(parseMap(content), data);
|
|
57871
|
+
const layout = layoutMap(
|
|
57872
|
+
resolved,
|
|
57873
|
+
data,
|
|
57874
|
+
{ width, height },
|
|
57875
|
+
{ palette, isDark }
|
|
57876
|
+
);
|
|
57877
|
+
const countries = decodeFeatures(data.worldDetail);
|
|
57878
|
+
const states = decodeFeatures(data.usStates);
|
|
57879
|
+
const gazetteer = data.gazetteer;
|
|
57880
|
+
const invert = (px, py) => pixelToLonLat(layout, px, py);
|
|
57881
|
+
const project = (lonLat) => lonLatToPixel(layout, lonLat);
|
|
57882
|
+
const locate = (px, py) => {
|
|
57883
|
+
const lonLat = invert(px, py);
|
|
57884
|
+
if (!lonLat) return null;
|
|
57885
|
+
const region = regionAt(lonLat, countries, states);
|
|
57886
|
+
const city = nearestCity(lonLat, gazetteer);
|
|
57887
|
+
return {
|
|
57888
|
+
lonLat,
|
|
57889
|
+
country: region.country,
|
|
57890
|
+
state: region.state,
|
|
57891
|
+
nearestCity: city,
|
|
57892
|
+
tokens: buildTokens(lonLat, region, city)
|
|
57893
|
+
};
|
|
57894
|
+
};
|
|
57895
|
+
const cities = (extent2) => {
|
|
57896
|
+
const sorted = [...gazetteer.cities].sort((a, b) => b[3] - a[3]);
|
|
57897
|
+
const out = [];
|
|
57898
|
+
for (const c of sorted) {
|
|
57899
|
+
const [lat, lon, iso, pop, name, sub] = c;
|
|
57900
|
+
if (extent2) {
|
|
57901
|
+
const [[w, s], [e, n]] = extent2;
|
|
57902
|
+
if (lon < w || lon > e || lat < s || lat > n) continue;
|
|
57903
|
+
}
|
|
57904
|
+
const p = project([lon, lat]);
|
|
57905
|
+
if (!p) continue;
|
|
57906
|
+
if (p[0] < 0 || p[0] > width || p[1] < 0 || p[1] > height) continue;
|
|
57907
|
+
out.push({
|
|
57908
|
+
name,
|
|
57909
|
+
iso,
|
|
57910
|
+
...sub !== void 0 && { sub },
|
|
57911
|
+
lon,
|
|
57912
|
+
lat,
|
|
57913
|
+
px: p[0],
|
|
57914
|
+
py: p[1],
|
|
57915
|
+
pop
|
|
57916
|
+
});
|
|
57917
|
+
if (out.length >= MAX_CITY_DOTS) break;
|
|
57918
|
+
}
|
|
57919
|
+
return out;
|
|
57920
|
+
};
|
|
57921
|
+
return { invert, project, locate, cities };
|
|
57922
|
+
}
|
|
57923
|
+
|
|
57350
57924
|
// src/map/completion.ts
|
|
57351
57925
|
var fold2 = (s) => s.normalize("NFD").replace(/\p{Diacritic}/gu, "").toLowerCase().trim();
|
|
57352
57926
|
var groupThousands = (n) => String(n).replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
|
@@ -58469,7 +59043,7 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
58469
59043
|
[
|
|
58470
59044
|
"map",
|
|
58471
59045
|
// Geographic map directives (§24B.2/.7). `poi`/`route` are content
|
|
58472
|
-
// keywords, not directives; metadata keys (
|
|
59046
|
+
// keywords, not directives; metadata keys (value/label/style) live in the
|
|
58473
59047
|
// reserved-key registry.
|
|
58474
59048
|
withGlobals({
|
|
58475
59049
|
region: {
|
|
@@ -58480,9 +59054,14 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
58480
59054
|
description: "Override the auto projection",
|
|
58481
59055
|
values: ["equirectangular", "natural-earth", "albers-usa", "mercator"]
|
|
58482
59056
|
},
|
|
58483
|
-
metric: { description: "Label for the region
|
|
58484
|
-
"
|
|
58485
|
-
|
|
59057
|
+
"region-metric": { description: "Label for the region value ramp" },
|
|
59058
|
+
"poi-metric": {
|
|
59059
|
+
description: "Label for the POI value (marker size) channel"
|
|
59060
|
+
},
|
|
59061
|
+
"flow-metric": {
|
|
59062
|
+
description: "Label for the edge/leg value (thickness) channel"
|
|
59063
|
+
},
|
|
59064
|
+
scale: { description: "Override value ramp anchors: scale <min> <max>" },
|
|
58486
59065
|
"region-labels": {
|
|
58487
59066
|
description: "Subdivision name labels",
|
|
58488
59067
|
values: ["full", "abbrev", "off"]
|
|
@@ -58494,6 +59073,7 @@ var COMPLETION_REGISTRY = /* @__PURE__ */ new Map([
|
|
|
58494
59073
|
"default-country": { description: "ISO scope for bare city resolution" },
|
|
58495
59074
|
"default-state": { description: "ISO subdivision scope" },
|
|
58496
59075
|
"no-legend": { description: "Suppress the legend" },
|
|
59076
|
+
relief: { description: "Subtle mountain-range relief shading" },
|
|
58497
59077
|
subtitle: { description: "Subtitle line" },
|
|
58498
59078
|
caption: { description: "Caption line" }
|
|
58499
59079
|
})
|
|
@@ -59999,6 +60579,7 @@ function formatLineDiff(path, original, migrated) {
|
|
|
59999
60579
|
computeTimeTicks,
|
|
60000
60580
|
contrastText,
|
|
60001
60581
|
controlsGroupCapsuleWidth,
|
|
60582
|
+
createMapGeoQuery,
|
|
60002
60583
|
decodeDiagramUrl,
|
|
60003
60584
|
decodeViewState,
|
|
60004
60585
|
displayName,
|