@math.gl/geospatial 5.0.0-beta.1 → 5.0.0-beta.2
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/crs/crs-identifier.d.ts +23 -0
- package/dist/crs/crs-identifier.d.ts.map +1 -0
- package/dist/crs/crs-identifier.js +74 -0
- package/dist/crs/crs-identifier.js.map +1 -0
- package/dist/crs/index.cjs +48 -0
- package/dist/crs/index.cjs.map +2 -2
- package/dist/crs/index.d.ts +1 -0
- package/dist/crs/index.d.ts.map +1 -1
- package/dist/crs/index.js +1 -0
- package/dist/crs/index.js.map +1 -1
- package/dist/discontinuous/cap-map.d.ts.map +1 -1
- package/dist/discontinuous/cap-map.js +197 -13
- package/dist/discontinuous/cap-map.js.map +1 -1
- package/dist/discontinuous/elastic/geometry.d.ts +1 -1
- package/dist/discontinuous/elastic/geometry.d.ts.map +1 -1
- package/dist/discontinuous/elastic/geometry.js +7 -7
- package/dist/discontinuous/elastic/geometry.js.map +1 -1
- package/dist/discontinuous/elastic/map.d.ts.map +1 -1
- package/dist/discontinuous/elastic/map.js +263 -23
- package/dist/discontinuous/elastic/map.js.map +1 -1
- package/dist/discontinuous/elastic/source-arc.d.ts +10 -0
- package/dist/discontinuous/elastic/source-arc.d.ts.map +1 -0
- package/dist/discontinuous/elastic/source-arc.js +111 -0
- package/dist/discontinuous/elastic/source-arc.js.map +1 -0
- package/dist/discontinuous/global-polygons.d.ts +1 -1
- package/dist/discontinuous/global-polygons.d.ts.map +1 -1
- package/dist/discontinuous/global-polygons.js +49 -1
- package/dist/discontinuous/global-polygons.js.map +1 -1
- package/dist/discontinuous/map-engine.d.ts +9 -0
- package/dist/discontinuous/map-engine.d.ts.map +1 -1
- package/dist/discontinuous/map-layout.d.ts +21 -0
- package/dist/discontinuous/map-layout.d.ts.map +1 -1
- package/dist/discontinuous/map-layout.js +116 -1
- package/dist/discontinuous/map-layout.js.map +1 -1
- package/dist/discontinuous/map-transition.d.ts.map +1 -1
- package/dist/discontinuous/map-transition.js +66 -3
- package/dist/discontinuous/map-transition.js.map +1 -1
- package/dist/discontinuous/mercator-map.d.ts +2 -2
- package/dist/discontinuous/mercator-map.d.ts.map +1 -1
- package/dist/discontinuous/mercator-map.js +123 -11
- package/dist/discontinuous/mercator-map.js.map +1 -1
- package/dist/discontinuous/polygon-constraints.d.ts +16 -0
- package/dist/discontinuous/polygon-constraints.d.ts.map +1 -0
- package/dist/discontinuous/polygon-constraints.js +157 -0
- package/dist/discontinuous/polygon-constraints.js.map +1 -0
- package/dist/discontinuous/prepare-features.d.ts +27 -0
- package/dist/discontinuous/prepare-features.d.ts.map +1 -1
- package/dist/discontinuous/prepare-features.js +106 -5
- package/dist/discontinuous/prepare-features.js.map +1 -1
- package/dist/discontinuous/rotated-map.d.ts +9 -0
- package/dist/discontinuous/rotated-map.d.ts.map +1 -1
- package/dist/discontinuous/source-arc.d.ts +4 -0
- package/dist/discontinuous/source-arc.d.ts.map +1 -0
- package/dist/discontinuous/source-arc.js +23 -0
- package/dist/discontinuous/source-arc.js.map +1 -0
- package/dist/discontinuous/world-kernels.d.ts +1 -1
- package/dist/discontinuous.cjs +1047 -75
- package/dist/discontinuous.cjs.map +3 -3
- package/dist/index.cjs +48 -0
- package/dist/index.cjs.map +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/turf.cjs +69 -5
- package/dist/turf.cjs.map +2 -2
- package/dist/turf.d.ts +9 -0
- package/dist/turf.d.ts.map +1 -1
- package/dist/turf.js +67 -0
- package/dist/turf.js.map +1 -1
- package/dist/workers/index.cjs +1075 -79
- package/dist/workers/index.cjs.map +3 -3
- package/dist/workers/operations.cjs +1049 -77
- package/dist/workers/operations.cjs.map +3 -3
- package/package.json +5 -5
- package/src/crs/crs-identifier.ts +86 -0
- package/src/crs/index.ts +1 -0
- package/src/discontinuous/cap-map.ts +248 -19
- package/src/discontinuous/elastic/geometry.ts +18 -7
- package/src/discontinuous/elastic/map.ts +334 -30
- package/src/discontinuous/elastic/source-arc.ts +129 -0
- package/src/discontinuous/global-polygons.ts +56 -2
- package/src/discontinuous/map-layout.ts +165 -2
- package/src/discontinuous/map-transition.ts +67 -3
- package/src/discontinuous/mercator-map.ts +151 -12
- package/src/discontinuous/polygon-constraints.ts +184 -0
- package/src/discontinuous/prepare-features.ts +154 -6
- package/src/discontinuous/source-arc.ts +31 -0
- package/src/index.ts +1 -0
- package/src/turf.ts +86 -0
package/dist/workers/index.cjs
CHANGED
|
@@ -809,8 +809,49 @@ function cutSphericalPolygon(rings, options) {
|
|
|
809
809
|
}
|
|
810
810
|
function projectSphericalPolygon(map, rings, options) {
|
|
811
811
|
const result = [];
|
|
812
|
+
if (options.polygonEdgeProvenance && (!map.regions || !map.seams))
|
|
813
|
+
throw new Error("Atlas provenance requires map region and seam metadata");
|
|
812
814
|
for (const part of cutSphericalPolygon(rings, options))
|
|
813
|
-
|
|
815
|
+
for (const polygon of map.projectPolygon(part.rings, options)) {
|
|
816
|
+
if (options.polygonEdgeProvenance) {
|
|
817
|
+
if (!polygon.edgeProvenance)
|
|
818
|
+
throw new Error("Map backend does not support polygon edge provenance");
|
|
819
|
+
const region = map.regions.find((r) => r.id === polygon.regionId);
|
|
820
|
+
polygon.edgeProvenance = polygon.edgeProvenance.map((edges, ring) => edges.map((edge2, i) => {
|
|
821
|
+
if (edge2.kind !== "source-boundary")
|
|
822
|
+
return edge2;
|
|
823
|
+
const parent = part.edges[edge2.ring][edge2.segment];
|
|
824
|
+
if (parent.kind === "source")
|
|
825
|
+
return {
|
|
826
|
+
...edge2,
|
|
827
|
+
ring: parent.ringIndex,
|
|
828
|
+
segment: parent.edgeIndex,
|
|
829
|
+
t0: parent.startFraction + edge2.t0 * (parent.endFraction - parent.startFraction),
|
|
830
|
+
t1: parent.startFraction + edge2.t1 * (parent.endFraction - parent.startFraction)
|
|
831
|
+
};
|
|
832
|
+
const a = geographic(polygon.sourceCoordinates[ring][i]), b = geographic(polygon.sourceCoordinates[ring][i + 1]), kinds = [];
|
|
833
|
+
region.boundary.forEach((p, j) => {
|
|
834
|
+
const normal = cross(geographic(p), geographic(region.boundary[(j + 1) % region.boundary.length]));
|
|
835
|
+
const length = Math.hypot(...normal);
|
|
836
|
+
if (length < 1e-12)
|
|
837
|
+
return;
|
|
838
|
+
if ([a, b].every((v) => Math.abs(dot(normal, v)) / length < 1e-10)) {
|
|
839
|
+
const seam = map.seams.find((s) => s.regions.some((id, k2) => id === region.id && s.edges[k2] === j));
|
|
840
|
+
if (seam)
|
|
841
|
+
kinds.push(seam.kind);
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
return {
|
|
845
|
+
kind: kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join",
|
|
846
|
+
ring: 4294967295,
|
|
847
|
+
segment: 4294967295,
|
|
848
|
+
t0: 0,
|
|
849
|
+
t1: 0
|
|
850
|
+
};
|
|
851
|
+
}));
|
|
852
|
+
}
|
|
853
|
+
result.push(polygon);
|
|
854
|
+
}
|
|
814
855
|
return result;
|
|
815
856
|
}
|
|
816
857
|
var import_polygon_clipping, TOL, arcCross, angle2;
|
|
@@ -841,33 +882,13 @@ function inRing(p, ring, includeBoundary = true) {
|
|
|
841
882
|
}
|
|
842
883
|
return inside;
|
|
843
884
|
}
|
|
844
|
-
function clipSegment(a, b, polygons) {
|
|
845
|
-
const ts = [0, 1], dx = b[0] - a[0], dy = b[1] - a[1];
|
|
846
|
-
for (const rings of polygons)
|
|
847
|
-
for (const ring of rings)
|
|
848
|
-
for (let i = 1; i < ring.length; i++) {
|
|
849
|
-
const c = ring[i - 1], d = ring[i], ex = d[0] - c[0], ey = d[1] - c[1], det = dx * ey - dy * ex;
|
|
850
|
-
if (Math.abs(det) < 1e-14)
|
|
851
|
-
continue;
|
|
852
|
-
const t = ((c[0] - a[0]) * ey - (c[1] - a[1]) * ex) / det;
|
|
853
|
-
const u = ((c[0] - a[0]) * dy - (c[1] - a[1]) * dx) / det;
|
|
854
|
-
if (t > 0 && t < 1 && u >= -1e-10 && u <= 1 + 1e-10)
|
|
855
|
-
ts.push(t);
|
|
856
|
-
}
|
|
857
|
-
ts.sort((a2, b2) => a2 - b2);
|
|
858
|
-
const result = [];
|
|
859
|
-
for (let i = 1; i < ts.length; i++)
|
|
860
|
-
if (ts[i] - ts[i - 1] > 1e-12 && contains(polygons, lerp(a, b, (ts[i] + ts[i - 1]) / 2)))
|
|
861
|
-
result.push([lerp(a, b, ts[i - 1]), lerp(a, b, ts[i])]);
|
|
862
|
-
return result;
|
|
863
|
-
}
|
|
864
885
|
function sampling(options) {
|
|
865
886
|
const step = options.maxAngularStep ?? 2, tolerance = options.tolerance ?? 1e-4;
|
|
866
887
|
if (!Number.isFinite(step) || step <= 0 || step > 90 || !Number.isFinite(tolerance) || tolerance <= 0)
|
|
867
888
|
throw new Error("Invalid map sampling options");
|
|
868
889
|
return { step, tolerance };
|
|
869
890
|
}
|
|
870
|
-
function sample(line, project, options, cellStep) {
|
|
891
|
+
function sample(line, project, options, cellStep, interpolate) {
|
|
871
892
|
const { step, tolerance } = sampling(options), source = [], xy = [];
|
|
872
893
|
const emit = (p, q) => {
|
|
873
894
|
if (source.length >= 1e5)
|
|
@@ -878,23 +899,23 @@ function sample(line, project, options, cellStep) {
|
|
|
878
899
|
const at = (p) => {
|
|
879
900
|
const q = project(p);
|
|
880
901
|
if (!q)
|
|
881
|
-
throw new Error(
|
|
902
|
+
throw new Error(`Elastic grid is undefined inside its coverage at ${p}`);
|
|
882
903
|
return q;
|
|
883
904
|
};
|
|
884
|
-
const visit = (a, b, qa, qb, depth) => {
|
|
885
|
-
const mid = lerp(a, b, 0.5), qm = at(mid), chord2 = lerp(qa, qb, 0.5);
|
|
905
|
+
const visit = (a, b, qa, qb, depth, segment, t0, t1) => {
|
|
906
|
+
const tm = (t0 + t1) / 2, mid = interpolate ? interpolate(segment, tm) : lerp(a, b, 0.5), qm = at(mid), chord2 = lerp(qa, qb, 0.5);
|
|
886
907
|
if (Math.hypot(b[0] - a[0], b[1] - a[1]) > Math.min(step, cellStep / 2) || Math.hypot(qm[0] - chord2[0], qm[1] - chord2[1]) > tolerance) {
|
|
887
908
|
if (depth >= 24)
|
|
888
909
|
throw new Error("Elastic sampling limit exceeded");
|
|
889
|
-
visit(a, mid, qa, qm, depth + 1);
|
|
890
|
-
visit(mid, b, qm, qb, depth + 1);
|
|
910
|
+
visit(a, mid, qa, qm, depth + 1, segment, t0, tm);
|
|
911
|
+
visit(mid, b, qm, qb, depth + 1, segment, tm, t1);
|
|
891
912
|
} else
|
|
892
913
|
emit(b, qb);
|
|
893
914
|
};
|
|
894
915
|
if (line.length) {
|
|
895
916
|
emit(line[0], at(line[0]));
|
|
896
917
|
for (let i = 1; i < line.length; i++)
|
|
897
|
-
visit(line[i - 1], line[i], at(line[i - 1]), at(line[i]), 0);
|
|
918
|
+
visit(line[i - 1], line[i], at(line[i - 1]), at(line[i]), 0, i - 1, 0, 1);
|
|
898
919
|
}
|
|
899
920
|
return { source, xy };
|
|
900
921
|
}
|
|
@@ -1001,7 +1022,7 @@ function fullCoverage(map) {
|
|
|
1001
1022
|
const overlaps = domains.some((domain, i) => domains.slice(i + 1).some((other) => import_polygon_clipping2.default.intersection(domain, other).length > 0));
|
|
1002
1023
|
covered = completeSections && !overlaps && import_polygon_clipping2.default.difference(world, ...domains).length === 0;
|
|
1003
1024
|
} else if (d.type === "world") {
|
|
1004
|
-
covered =
|
|
1025
|
+
covered = directWorldProjections.has(d.projection) && Object.keys(d.parameters ?? {}).length === 0;
|
|
1005
1026
|
}
|
|
1006
1027
|
coverageCache.set(map, covered);
|
|
1007
1028
|
return covered;
|
|
@@ -1016,12 +1037,71 @@ function geographicRings(rings, center3) {
|
|
|
1016
1037
|
});
|
|
1017
1038
|
});
|
|
1018
1039
|
}
|
|
1019
|
-
var import_polygon_clipping2, MapTransitionGeometry, MapTransition, coverageCache;
|
|
1040
|
+
var import_polygon_clipping2, directWorldProjections, MapTransitionGeometry, MapTransition, coverageCache;
|
|
1020
1041
|
var init_map_transition = __esm({
|
|
1021
1042
|
"dist/discontinuous/map-transition.js"() {
|
|
1022
1043
|
import_polygon_clipping2 = __toESM(require("polygon-clipping"), 1);
|
|
1023
1044
|
init_math2();
|
|
1024
1045
|
init_geometry();
|
|
1046
|
+
directWorldProjections = /* @__PURE__ */ new Set([
|
|
1047
|
+
"gilbert",
|
|
1048
|
+
"aitoff",
|
|
1049
|
+
"august",
|
|
1050
|
+
"baker",
|
|
1051
|
+
"boggs",
|
|
1052
|
+
"bromley",
|
|
1053
|
+
"collignon",
|
|
1054
|
+
"craster",
|
|
1055
|
+
"eckert1",
|
|
1056
|
+
"eckert2",
|
|
1057
|
+
"eckert3",
|
|
1058
|
+
"eckert4",
|
|
1059
|
+
"eckert5",
|
|
1060
|
+
"eckert6",
|
|
1061
|
+
"fahey",
|
|
1062
|
+
"foucaut",
|
|
1063
|
+
"ginzburg4",
|
|
1064
|
+
"ginzburg5",
|
|
1065
|
+
"ginzburg6",
|
|
1066
|
+
"ginzburg8",
|
|
1067
|
+
"ginzburg9",
|
|
1068
|
+
"homolosine",
|
|
1069
|
+
"kavrayskiy7",
|
|
1070
|
+
"larrivee",
|
|
1071
|
+
"laskowski",
|
|
1072
|
+
"miller",
|
|
1073
|
+
"mollweide",
|
|
1074
|
+
"mt-flat-polar-parabolic",
|
|
1075
|
+
"mt-flat-polar-quartic",
|
|
1076
|
+
"mt-flat-polar-sinusoidal",
|
|
1077
|
+
"natural-earth2",
|
|
1078
|
+
"nell-hammer",
|
|
1079
|
+
"patterson",
|
|
1080
|
+
"robinson",
|
|
1081
|
+
"sinusoidal",
|
|
1082
|
+
"times",
|
|
1083
|
+
"van-der-grinten",
|
|
1084
|
+
"van-der-grinten2",
|
|
1085
|
+
"van-der-grinten3",
|
|
1086
|
+
"van-der-grinten4",
|
|
1087
|
+
"wagner4",
|
|
1088
|
+
"wagner6",
|
|
1089
|
+
"winkel3",
|
|
1090
|
+
"bonne",
|
|
1091
|
+
"bottomley",
|
|
1092
|
+
"cylindrical-equal-area",
|
|
1093
|
+
"cylindrical-stereographic",
|
|
1094
|
+
"foucaut-sinusoidal",
|
|
1095
|
+
"hammer",
|
|
1096
|
+
"hill",
|
|
1097
|
+
"hufnagel",
|
|
1098
|
+
"hyperelliptical",
|
|
1099
|
+
"lagrange",
|
|
1100
|
+
"loximuthal",
|
|
1101
|
+
"wagner7",
|
|
1102
|
+
"quartic-authalic",
|
|
1103
|
+
"wagner"
|
|
1104
|
+
]);
|
|
1025
1105
|
MapTransitionGeometry = class {
|
|
1026
1106
|
constructor(parts, strategy, radius2) {
|
|
1027
1107
|
this.strategy = strategy;
|
|
@@ -1234,6 +1314,16 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
1234
1314
|
throw new Error("Expected a feature array");
|
|
1235
1315
|
if (options.polygonOutlines !== void 0 && typeof options.polygonOutlines !== "boolean")
|
|
1236
1316
|
throw new Error("polygonOutlines must be boolean");
|
|
1317
|
+
const provenance = options.provenance;
|
|
1318
|
+
if (provenance !== void 0 && (!provenance || typeof provenance !== "object" || Array.isArray(provenance)))
|
|
1319
|
+
throw new Error("Unsupported provenance policy");
|
|
1320
|
+
if ((provenance == null ? void 0 : provenance.distances) !== void 0 && (!provenance.distances || typeof provenance.distances !== "object"))
|
|
1321
|
+
throw new Error("Unsupported provenance distance policy");
|
|
1322
|
+
if (provenance && (typeof provenance !== "object" || Object.keys(provenance).some((k2) => !["sourceSegments", "boundaries", "distances", "polygonEdges"].includes(k2)) || [provenance.sourceSegments, provenance.boundaries, provenance.polygonEdges].some((v) => v !== void 0 && typeof v !== "boolean") || provenance.distances && (provenance.distances.metric !== "spherical" || !Number.isFinite(provenance.distances.radius) || provenance.distances.radius <= 0)))
|
|
1323
|
+
throw new Error("Unsupported provenance policy");
|
|
1324
|
+
const edgeKinds = [], edgeRings = [], edgeSegments = [], edgeParameters = [];
|
|
1325
|
+
const lineage = Boolean((provenance == null ? void 0 : provenance.sourceSegments) || (provenance == null ? void 0 : provenance.boundaries) || (provenance == null ? void 0 : provenance.distances));
|
|
1326
|
+
const segments = [], parameters = [], originalVertices = [], distances = [], startReasons = [], endReasons = [];
|
|
1237
1327
|
const regionIds = map.regions.map((r) => r.id), regionIndices = new Map(regionIds.map((id, i) => [id, i]));
|
|
1238
1328
|
const points = vertices(), paths = vertices(), polygons = vertices();
|
|
1239
1329
|
const pointParts = [], pathParts = [], polygonParts = [];
|
|
@@ -1254,7 +1344,27 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
1254
1344
|
const isRing = ringIndex !== void 0;
|
|
1255
1345
|
if (isRing && !closed(line))
|
|
1256
1346
|
line.push([...line[0]]);
|
|
1257
|
-
for (const p of map.projectLine(line,
|
|
1347
|
+
for (const p of map.projectLine(line, {
|
|
1348
|
+
...options.sampling,
|
|
1349
|
+
pathProvenance: lineage,
|
|
1350
|
+
pathDistances: Boolean(provenance == null ? void 0 : provenance.distances),
|
|
1351
|
+
pathBoundaries: Boolean(provenance == null ? void 0 : provenance.boundaries)
|
|
1352
|
+
})) {
|
|
1353
|
+
if (lineage) {
|
|
1354
|
+
if (!p.provenance)
|
|
1355
|
+
throw new Error("Map backend does not support path provenance");
|
|
1356
|
+
if (provenance == null ? void 0 : provenance.sourceSegments) {
|
|
1357
|
+
segments.push(...p.provenance.segments);
|
|
1358
|
+
parameters.push(...p.provenance.parameters);
|
|
1359
|
+
originalVertices.push(...p.provenance.vertices);
|
|
1360
|
+
}
|
|
1361
|
+
if (provenance == null ? void 0 : provenance.distances)
|
|
1362
|
+
distances.push(...p.provenance.angularDistances.map((d) => d * provenance.distances.radius));
|
|
1363
|
+
if (provenance == null ? void 0 : provenance.boundaries) {
|
|
1364
|
+
startReasons.push(p.provenance.startReason);
|
|
1365
|
+
endReasons.push(p.provenance.endReason);
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1258
1368
|
append(paths, p.coordinates, p.sourceCoordinates);
|
|
1259
1369
|
pathParts.push({
|
|
1260
1370
|
...part(featureIndex, geometryPath, p.regionId),
|
|
@@ -1266,12 +1376,41 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
1266
1376
|
}
|
|
1267
1377
|
};
|
|
1268
1378
|
const addPolygon = (input, featureIndex, geometryPath) => {
|
|
1379
|
+
var _a2;
|
|
1269
1380
|
if (!input.length)
|
|
1270
1381
|
return;
|
|
1271
1382
|
const rings = input.map((r) => r.map(position));
|
|
1272
|
-
const parts = options.sphericalCuts ? map.projectGlobalPolygon(rings, {
|
|
1383
|
+
const parts = options.sphericalCuts ? map.projectGlobalPolygon(rings, {
|
|
1384
|
+
...options.sampling,
|
|
1385
|
+
...options.sphericalCuts,
|
|
1386
|
+
polygonEdgeProvenance: provenance == null ? void 0 : provenance.polygonEdges
|
|
1387
|
+
}) : map.projectPolygon(rings, {
|
|
1388
|
+
...options.sampling,
|
|
1389
|
+
polygonEdgeProvenance: provenance == null ? void 0 : provenance.polygonEdges
|
|
1390
|
+
});
|
|
1273
1391
|
for (const p of parts) {
|
|
1274
1392
|
for (let i = 0; i < p.coordinates.length; i++) {
|
|
1393
|
+
if (provenance == null ? void 0 : provenance.polygonEdges) {
|
|
1394
|
+
const edges = (_a2 = p.edgeProvenance) == null ? void 0 : _a2[i];
|
|
1395
|
+
if (!edges)
|
|
1396
|
+
throw new Error("Map backend does not support polygon edge provenance");
|
|
1397
|
+
const kinds = [
|
|
1398
|
+
"source-boundary",
|
|
1399
|
+
"coverage-boundary",
|
|
1400
|
+
"chart-cut",
|
|
1401
|
+
"continuous-chart-join"
|
|
1402
|
+
];
|
|
1403
|
+
for (const edge2 of edges) {
|
|
1404
|
+
edgeKinds.push(kinds.indexOf(edge2.kind) + 1);
|
|
1405
|
+
edgeRings.push(edge2.ring);
|
|
1406
|
+
edgeSegments.push(edge2.segment);
|
|
1407
|
+
edgeParameters.push(edge2.t0, edge2.t1);
|
|
1408
|
+
}
|
|
1409
|
+
edgeKinds.push(0);
|
|
1410
|
+
edgeRings.push(4294967295);
|
|
1411
|
+
edgeSegments.push(4294967295);
|
|
1412
|
+
edgeParameters.push(0, 0);
|
|
1413
|
+
}
|
|
1275
1414
|
append(polygons, p.coordinates[i], p.sourceCoordinates[i]);
|
|
1276
1415
|
ringStarts.push(polygons.positions.length / 2);
|
|
1277
1416
|
}
|
|
@@ -1335,12 +1474,38 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
1335
1474
|
featureIds,
|
|
1336
1475
|
regionIds,
|
|
1337
1476
|
points: { ...pack(points), parts: pointParts },
|
|
1338
|
-
paths: {
|
|
1477
|
+
paths: {
|
|
1478
|
+
...pack(paths),
|
|
1479
|
+
parts: pathParts,
|
|
1480
|
+
pathStarts: new Uint32Array(pathStarts),
|
|
1481
|
+
...lineage ? {
|
|
1482
|
+
provenance: {
|
|
1483
|
+
...(provenance == null ? void 0 : provenance.sourceSegments) ? {
|
|
1484
|
+
sourceSegmentIndices: new Uint32Array(segments),
|
|
1485
|
+
sourceSegmentParameters: new Float64Array(parameters),
|
|
1486
|
+
sourceVertexIndices: new Uint32Array(originalVertices)
|
|
1487
|
+
} : {},
|
|
1488
|
+
...(provenance == null ? void 0 : provenance.distances) ? {
|
|
1489
|
+
sourceDistances: new Float64Array(distances),
|
|
1490
|
+
distanceRadius: provenance.distances.radius
|
|
1491
|
+
} : {},
|
|
1492
|
+
...(provenance == null ? void 0 : provenance.boundaries) ? { startReasons, endReasons } : {}
|
|
1493
|
+
}
|
|
1494
|
+
} : {}
|
|
1495
|
+
},
|
|
1339
1496
|
polygons: {
|
|
1340
1497
|
...pack(polygons),
|
|
1341
1498
|
parts: polygonParts,
|
|
1342
1499
|
ringStarts: new Uint32Array(ringStarts),
|
|
1343
|
-
polygonStarts: new Uint32Array(polygonStarts)
|
|
1500
|
+
polygonStarts: new Uint32Array(polygonStarts),
|
|
1501
|
+
...(provenance == null ? void 0 : provenance.polygonEdges) ? {
|
|
1502
|
+
edgeProvenance: {
|
|
1503
|
+
kinds: new Uint8Array(edgeKinds),
|
|
1504
|
+
sourceRingIndices: new Uint32Array(edgeRings),
|
|
1505
|
+
sourceSegmentIndices: new Uint32Array(edgeSegments),
|
|
1506
|
+
sourceParameterRanges: new Float64Array(edgeParameters)
|
|
1507
|
+
}
|
|
1508
|
+
} : {}
|
|
1344
1509
|
}
|
|
1345
1510
|
};
|
|
1346
1511
|
}
|
|
@@ -1355,6 +1520,181 @@ var init_prepare_features = __esm({
|
|
|
1355
1520
|
}
|
|
1356
1521
|
});
|
|
1357
1522
|
|
|
1523
|
+
// dist/discontinuous/polygon-constraints.js
|
|
1524
|
+
function tracePolygonConstraints(input, output, tolerance = 1e-10, priorities, accept, degenerate) {
|
|
1525
|
+
const constraints = input.flatMap((ring, r) => ring.slice(0, -1).map((a, i) => ({ a, b: ring[i + 1], r, i })));
|
|
1526
|
+
let work = 0;
|
|
1527
|
+
const tick = () => {
|
|
1528
|
+
if (++work > 2e7)
|
|
1529
|
+
throw new Error("Polygon constraint work limit exceeded");
|
|
1530
|
+
};
|
|
1531
|
+
const fraction = (p, a, b) => {
|
|
1532
|
+
const dx = b[0] - a[0], dy = b[1] - a[1], l = dx * dx + dy * dy;
|
|
1533
|
+
return l ? ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / l : NaN;
|
|
1534
|
+
};
|
|
1535
|
+
const on = (p, a, b) => {
|
|
1536
|
+
tick();
|
|
1537
|
+
const t = fraction(p, a, b), length = Math.hypot(b[0] - a[0], b[1] - a[1]);
|
|
1538
|
+
return length > 0 && t >= -tolerance && t <= 1 + tolerance && Math.hypot(p[0] - a[0] - t * (b[0] - a[0]), p[1] - a[1] - t * (b[1] - a[1])) <= tolerance * Math.max(1, length);
|
|
1539
|
+
};
|
|
1540
|
+
const boxes = constraints.map((c) => [
|
|
1541
|
+
Math.min(c.a[0], c.b[0]),
|
|
1542
|
+
Math.min(c.a[1], c.b[1]),
|
|
1543
|
+
Math.max(c.a[0], c.b[0]),
|
|
1544
|
+
Math.max(c.a[1], c.b[1])
|
|
1545
|
+
]);
|
|
1546
|
+
const build = (ids) => {
|
|
1547
|
+
const box = [Infinity, Infinity, -Infinity, -Infinity];
|
|
1548
|
+
for (const id of ids) {
|
|
1549
|
+
tick();
|
|
1550
|
+
const b = boxes[id];
|
|
1551
|
+
box[0] = Math.min(box[0], b[0]);
|
|
1552
|
+
box[1] = Math.min(box[1], b[1]);
|
|
1553
|
+
box[2] = Math.max(box[2], b[2]);
|
|
1554
|
+
box[3] = Math.max(box[3], b[3]);
|
|
1555
|
+
}
|
|
1556
|
+
if (ids.length <= 16)
|
|
1557
|
+
return { box, ids };
|
|
1558
|
+
const axis = box[2] - box[0] >= box[3] - box[1] ? 0 : 1;
|
|
1559
|
+
ids.sort((a, b) => {
|
|
1560
|
+
tick();
|
|
1561
|
+
return boxes[a][axis] + boxes[a][axis + 2] - boxes[b][axis] - boxes[b][axis + 2];
|
|
1562
|
+
});
|
|
1563
|
+
const middle = Math.floor(ids.length / 2);
|
|
1564
|
+
return { box, left: build(ids.slice(0, middle)), right: build(ids.slice(middle)) };
|
|
1565
|
+
};
|
|
1566
|
+
const root = build(constraints.map((_, i) => i));
|
|
1567
|
+
const padding = tolerance * Math.max(1, root.box[2] - root.box[0], root.box[3] - root.box[1]);
|
|
1568
|
+
const query = (a, b) => {
|
|
1569
|
+
const box = [
|
|
1570
|
+
Math.min(a[0], b[0]) - padding,
|
|
1571
|
+
Math.min(a[1], b[1]) - padding,
|
|
1572
|
+
Math.max(a[0], b[0]) + padding,
|
|
1573
|
+
Math.max(a[1], b[1]) + padding
|
|
1574
|
+
], ids = [];
|
|
1575
|
+
const overlaps = (b2) => b2[0] <= box[2] && b2[2] >= box[0] && b2[1] <= box[3] && b2[3] >= box[1];
|
|
1576
|
+
const visit = (node) => {
|
|
1577
|
+
tick();
|
|
1578
|
+
if (!overlaps(node.box))
|
|
1579
|
+
return;
|
|
1580
|
+
if (node.ids) {
|
|
1581
|
+
for (const id of node.ids) {
|
|
1582
|
+
tick();
|
|
1583
|
+
if (overlaps(boxes[id]))
|
|
1584
|
+
ids.push(id);
|
|
1585
|
+
}
|
|
1586
|
+
} else {
|
|
1587
|
+
visit(node.left);
|
|
1588
|
+
visit(node.right);
|
|
1589
|
+
}
|
|
1590
|
+
};
|
|
1591
|
+
visit(root);
|
|
1592
|
+
return ids.map((id) => constraints[id]);
|
|
1593
|
+
};
|
|
1594
|
+
const rings = [], owners = [];
|
|
1595
|
+
for (const ring of output) {
|
|
1596
|
+
const points = [];
|
|
1597
|
+
for (let i = 1; i < ring.length; i++) {
|
|
1598
|
+
const a = ring[i - 1], b = ring[i];
|
|
1599
|
+
if (a.every((v, k2) => v === b[k2]))
|
|
1600
|
+
continue;
|
|
1601
|
+
const breaks = [{ t: 0, p: a }];
|
|
1602
|
+
for (const c of query(a, b))
|
|
1603
|
+
if (on(c.a, a, b) && (!accept || accept(c.a))) {
|
|
1604
|
+
const t = fraction(c.a, a, b);
|
|
1605
|
+
if (t > 1e-12 && t < 1 - 1e-12)
|
|
1606
|
+
breaks.push({ t, p: c.a });
|
|
1607
|
+
}
|
|
1608
|
+
breaks.sort((a2, b2) => a2.t - b2.t);
|
|
1609
|
+
for (const item of breaks)
|
|
1610
|
+
if (!points.length || Math.hypot(...points[points.length - 1].map((v, k2) => v - item.p[k2])) > 1e-14)
|
|
1611
|
+
points.push([...item.p]);
|
|
1612
|
+
}
|
|
1613
|
+
if (points.length < 3)
|
|
1614
|
+
continue;
|
|
1615
|
+
points.push([...points[0]]);
|
|
1616
|
+
const tags = [];
|
|
1617
|
+
for (let i = 1; i < points.length; i++) {
|
|
1618
|
+
const a = points[i - 1], b = points[i];
|
|
1619
|
+
if (degenerate == null ? void 0 : degenerate(a, b)) {
|
|
1620
|
+
tags.push(null);
|
|
1621
|
+
continue;
|
|
1622
|
+
}
|
|
1623
|
+
let candidates = query(a, b).filter((c) => on(a, c.a, c.b) && on(b, c.a, c.b));
|
|
1624
|
+
const same = (p, q) => Math.hypot(...p.map((v, k2) => v - q[k2])) <= 64 * Number.EPSILON * Math.max(1, ...p.map(Math.abs), ...q.map(Math.abs));
|
|
1625
|
+
const exact = candidates.filter((c) => same(a, c.a) && same(b, c.b) || same(a, c.b) && same(b, c.a));
|
|
1626
|
+
if (exact.length)
|
|
1627
|
+
candidates = exact;
|
|
1628
|
+
if (candidates.some((c) => {
|
|
1629
|
+
var _a2, _b;
|
|
1630
|
+
return ((_b = (_a2 = priorities == null ? void 0 : priorities[c.r]) == null ? void 0 : _a2[c.i]) == null ? void 0 : _b.kind) === "source-boundary";
|
|
1631
|
+
}))
|
|
1632
|
+
candidates = candidates.filter((c) => {
|
|
1633
|
+
var _a2, _b;
|
|
1634
|
+
return ((_b = (_a2 = priorities == null ? void 0 : priorities[c.r]) == null ? void 0 : _a2[c.i]) == null ? void 0 : _b.kind) === "source-boundary";
|
|
1635
|
+
});
|
|
1636
|
+
if (candidates.length > 1) {
|
|
1637
|
+
const score = (c) => Math.max(...[a, b].map((p) => {
|
|
1638
|
+
const t = Math.min(1, Math.max(0, fraction(p, c.a, c.b)));
|
|
1639
|
+
return Math.hypot(p[0] - c.a[0] - t * (c.b[0] - c.a[0]), p[1] - c.a[1] - t * (c.b[1] - c.a[1]));
|
|
1640
|
+
}));
|
|
1641
|
+
candidates.sort((a2, b2) => score(a2) - score(b2));
|
|
1642
|
+
const epsilon7 = 64 * Number.EPSILON * Math.max(1, ...a.map(Math.abs), ...b.map(Math.abs));
|
|
1643
|
+
if (score(candidates[1]) - score(candidates[0]) > epsilon7)
|
|
1644
|
+
candidates = [candidates[0]];
|
|
1645
|
+
else if (Math.hypot(a[0] - b[0], a[1] - b[1]) <= 2 * epsilon7)
|
|
1646
|
+
candidates = [];
|
|
1647
|
+
else
|
|
1648
|
+
throw new Error("Ambiguous polygon clipping constraint ancestry");
|
|
1649
|
+
}
|
|
1650
|
+
tags.push(candidates.length ? [candidates[0].r, candidates[0].i] : null);
|
|
1651
|
+
}
|
|
1652
|
+
rings.push(points);
|
|
1653
|
+
owners.push(tags);
|
|
1654
|
+
}
|
|
1655
|
+
return { rings, owners };
|
|
1656
|
+
}
|
|
1657
|
+
function composePolygonEdge(parent, a, b, start, end) {
|
|
1658
|
+
if (parent.kind !== "source-boundary")
|
|
1659
|
+
return { ...parent };
|
|
1660
|
+
const v = geographic(a), length = angle(v, geographic(b));
|
|
1661
|
+
const parameter = (p) => length ? Math.min(1, angle(v, geographic(p)) / length) : 0;
|
|
1662
|
+
return {
|
|
1663
|
+
...parent,
|
|
1664
|
+
t0: parent.t0 + parameter(start) * (parent.t1 - parent.t0),
|
|
1665
|
+
t1: parent.t0 + parameter(end) * (parent.t1 - parent.t0)
|
|
1666
|
+
};
|
|
1667
|
+
}
|
|
1668
|
+
var init_polygon_constraints = __esm({
|
|
1669
|
+
"dist/discontinuous/polygon-constraints.js"() {
|
|
1670
|
+
init_math2();
|
|
1671
|
+
}
|
|
1672
|
+
});
|
|
1673
|
+
|
|
1674
|
+
// dist/discontinuous/source-arc.js
|
|
1675
|
+
function sourceArc(a, b) {
|
|
1676
|
+
const va = geographic(a), vb = geographic(b), length = angle(va, vb);
|
|
1677
|
+
const poleA = Math.abs(a[1]) === 90, poleB = Math.abs(b[1]) === 90;
|
|
1678
|
+
const start = poleA && !poleB ? [b[0], a[1]] : [...a], end = poleB && !poleA ? [a[0], b[1]] : [...b];
|
|
1679
|
+
return (t) => {
|
|
1680
|
+
if (t === 0)
|
|
1681
|
+
return [...start];
|
|
1682
|
+
if (t === 1)
|
|
1683
|
+
return [...end];
|
|
1684
|
+
if (length < 1e-14)
|
|
1685
|
+
return [a[0] + t * (b[0] - a[0]), a[1] + t * (b[1] - a[1])];
|
|
1686
|
+
const p = coordinates(unit(va.map((v, k2) => (Math.sin((1 - t) * length) * v + Math.sin(t * length) * vb[k2]) / Math.sin(length))));
|
|
1687
|
+
const reference = start[0] + t * (end[0] - start[0]);
|
|
1688
|
+
p[0] += 360 * Math.round((reference - p[0]) / 360);
|
|
1689
|
+
return p;
|
|
1690
|
+
};
|
|
1691
|
+
}
|
|
1692
|
+
var init_source_arc = __esm({
|
|
1693
|
+
"dist/discontinuous/source-arc.js"() {
|
|
1694
|
+
init_math2();
|
|
1695
|
+
}
|
|
1696
|
+
});
|
|
1697
|
+
|
|
1358
1698
|
// dist/discontinuous/map-layout.js
|
|
1359
1699
|
function sampling2(options) {
|
|
1360
1700
|
const step = options.maxAngularStep ?? 2, tolerance = options.tolerance ?? 1e-4;
|
|
@@ -1546,6 +1886,10 @@ var init_map_layout = __esm({
|
|
|
1546
1886
|
for (let i = 1; i < points.length; i++)
|
|
1547
1887
|
validateArc(points[i - 1], points[i]);
|
|
1548
1888
|
const results = [];
|
|
1889
|
+
const cumulative = options.pathDistances ? [0] : void 0;
|
|
1890
|
+
if (cumulative)
|
|
1891
|
+
for (let i = 1; i < points.length; i++)
|
|
1892
|
+
cumulative.push(cumulative[i - 1] + angle(points[i - 1], points[i]));
|
|
1549
1893
|
for (const r of this.compiled) {
|
|
1550
1894
|
let current = null;
|
|
1551
1895
|
for (let i = 1; i < points.length; i++) {
|
|
@@ -1554,18 +1898,42 @@ var init_map_layout = __esm({
|
|
|
1554
1898
|
current = null;
|
|
1555
1899
|
continue;
|
|
1556
1900
|
}
|
|
1901
|
+
const reason = (p, endpoint, isEndpoint) => {
|
|
1902
|
+
if (isEndpoint && angle(p, endpoint) < 1e-12)
|
|
1903
|
+
return "source-endpoint";
|
|
1904
|
+
const kinds = r.normals.map((normal, edge2) => {
|
|
1905
|
+
var _a2;
|
|
1906
|
+
return Math.abs(dot(normal, p)) < 1e-9 ? (_a2 = this.seams.find((s) => s.regions.some((id, i2) => id === r.definition.id && s.edges[i2] === edge2))) == null ? void 0 : _a2.kind : void 0;
|
|
1907
|
+
}).filter(Boolean);
|
|
1908
|
+
return kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : kinds.includes("join") ? "continuous-chart-join" : "coverage-boundary";
|
|
1909
|
+
};
|
|
1557
1910
|
const sampled = this.sample(r, clipped[0], clipped[1], settings);
|
|
1558
1911
|
if (sampled.length < 2)
|
|
1559
1912
|
continue;
|
|
1560
1913
|
if (!current || angle(geographic(current.sourceCoordinates[current.sourceCoordinates.length - 1]), clipped[0]) > EPS || !this.sameProjectedPoint(current.coordinates[current.coordinates.length - 1], this.project(r, sampled[0]))) {
|
|
1561
1914
|
current = { regionId: r.definition.id, coordinates: [], sourceCoordinates: [] };
|
|
1915
|
+
if (options.pathProvenance)
|
|
1916
|
+
current.provenance = { segments: [], parameters: [], vertices: [], angularDistances: [] };
|
|
1917
|
+
if (current.provenance && options.pathBoundaries)
|
|
1918
|
+
current.provenance.startReason = reason(clipped[0], points[0], i === 1);
|
|
1562
1919
|
results.push(current);
|
|
1563
1920
|
} else
|
|
1564
1921
|
sampled.shift();
|
|
1565
1922
|
for (const p of sampled) {
|
|
1566
1923
|
current.coordinates.push(this.project(r, p));
|
|
1567
1924
|
current.sourceCoordinates.push(coordinates(p));
|
|
1925
|
+
if (current.provenance) {
|
|
1926
|
+
const length = angle(points[i - 1], points[i]);
|
|
1927
|
+
const t = length ? Math.min(1, Math.max(0, angle(points[i - 1], p) / length)) : 0;
|
|
1928
|
+
current.provenance.segments.push(i - 1);
|
|
1929
|
+
current.provenance.parameters.push(t);
|
|
1930
|
+
current.provenance.vertices.push(angle(points[i - 1], p) < 1e-12 ? i - 1 : angle(points[i], p) < 1e-12 ? i : 4294967295);
|
|
1931
|
+
if (cumulative)
|
|
1932
|
+
current.provenance.angularDistances.push(cumulative[i - 1] + t * length);
|
|
1933
|
+
}
|
|
1568
1934
|
}
|
|
1935
|
+
if (current.provenance && options.pathBoundaries)
|
|
1936
|
+
current.provenance.endReason = reason(clipped[1], points[points.length - 1], i === points.length - 1);
|
|
1569
1937
|
if (!this.contains(r, points[i]))
|
|
1570
1938
|
current = null;
|
|
1571
1939
|
}
|
|
@@ -1662,26 +2030,91 @@ var init_map_layout = __esm({
|
|
|
1662
2030
|
coordinates: [],
|
|
1663
2031
|
sourceCoordinates: []
|
|
1664
2032
|
};
|
|
2033
|
+
if (options.polygonEdgeProvenance)
|
|
2034
|
+
output.edgeProvenance = [];
|
|
1665
2035
|
polygon.forEach((ring, index) => {
|
|
1666
2036
|
const sphere = ring.map((p) => unit(add(center3, add(scale(x, p[0]), scale(y, p[1])))));
|
|
1667
2037
|
const points = [];
|
|
2038
|
+
const edges = [];
|
|
2039
|
+
const classify = (a, b) => {
|
|
2040
|
+
if (angle(a, b) < 64 * Number.EPSILON)
|
|
2041
|
+
return {
|
|
2042
|
+
kind: "continuous-chart-join",
|
|
2043
|
+
ring: 4294967295,
|
|
2044
|
+
segment: 4294967295,
|
|
2045
|
+
t0: 0,
|
|
2046
|
+
t1: 0
|
|
2047
|
+
};
|
|
2048
|
+
const candidates = [];
|
|
2049
|
+
vectors.forEach((source, ring2) => source.forEach((u, segment) => {
|
|
2050
|
+
const v = source[(segment + 1) % source.length], length = angle(u, v);
|
|
2051
|
+
if (length > 1e-12 && [a, b].every((p) => Math.abs(dot(unit(cross(u, v)), p)) < 1e-12 && Math.abs(angle(u, p) + angle(p, v) - length) < 1e-10))
|
|
2052
|
+
candidates.push({ ring: ring2, segment });
|
|
2053
|
+
}));
|
|
2054
|
+
if (candidates.length > 1)
|
|
2055
|
+
throw new Error("Ambiguous polygon boundary provenance");
|
|
2056
|
+
if (candidates.length) {
|
|
2057
|
+
const { ring: ring2, segment } = candidates[0], source = vectors[ring2], u = source[segment], length = angle(u, source[(segment + 1) % source.length]);
|
|
2058
|
+
return {
|
|
2059
|
+
kind: "source-boundary",
|
|
2060
|
+
ring: ring2,
|
|
2061
|
+
segment,
|
|
2062
|
+
t0: Math.min(1, angle(u, a) / length),
|
|
2063
|
+
t1: Math.min(1, angle(u, b) / length)
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
const kinds = r.normals.map((n, edge2) => {
|
|
2067
|
+
var _a2;
|
|
2068
|
+
return [a, b].every((p) => Math.abs(dot(n, p)) < 1e-9) ? (_a2 = this.seams.find((s) => s.regions.some((id, i) => id === r.definition.id && s.edges[i] === edge2))) == null ? void 0 : _a2.kind : void 0;
|
|
2069
|
+
}).filter(Boolean);
|
|
2070
|
+
if (!kinds.length)
|
|
2071
|
+
throw new Error("Unknown polygon clipping constraint");
|
|
2072
|
+
return {
|
|
2073
|
+
kind: kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join",
|
|
2074
|
+
ring: 4294967295,
|
|
2075
|
+
segment: 4294967295,
|
|
2076
|
+
t0: 0,
|
|
2077
|
+
t1: 0
|
|
2078
|
+
};
|
|
2079
|
+
};
|
|
1668
2080
|
for (let i = 1; i < sphere.length; i++) {
|
|
2081
|
+
const origin2 = options.polygonEdgeProvenance && !sphere[i - 1].every((value2, k2) => value2 === sphere[i][k2]) ? classify(sphere[i - 1], sphere[i]) : void 0;
|
|
1669
2082
|
const sampled = this.sample(r, sphere[i - 1], sphere[i], settings);
|
|
1670
2083
|
for (const point of sampled) {
|
|
1671
2084
|
const previous = points[points.length - 1];
|
|
1672
|
-
if (!previous || !point.every((value2, k2) => value2 === previous[k2]))
|
|
2085
|
+
if (!previous || !point.every((value2, k2) => value2 === previous[k2])) {
|
|
2086
|
+
if (previous && origin2) {
|
|
2087
|
+
const edge2 = { ...origin2 };
|
|
2088
|
+
if (edge2.kind === "source-boundary") {
|
|
2089
|
+
const source = vectors[edge2.ring], u = source[edge2.segment], length = angle(u, source[(edge2.segment + 1) % source.length]);
|
|
2090
|
+
edge2.t0 = Math.min(1, angle(u, previous) / length);
|
|
2091
|
+
edge2.t1 = Math.min(1, angle(u, point) / length);
|
|
2092
|
+
}
|
|
2093
|
+
edges.push(edge2);
|
|
2094
|
+
}
|
|
1673
2095
|
points.push(point);
|
|
2096
|
+
}
|
|
1674
2097
|
}
|
|
1675
2098
|
}
|
|
1676
2099
|
if (points.length < 3)
|
|
1677
2100
|
return;
|
|
1678
2101
|
if (points[points.length - 1].every((value2, k2) => value2 === points[0][k2]))
|
|
1679
2102
|
points.pop();
|
|
2103
|
+
if (options.polygonEdgeProvenance && edges.length < points.length)
|
|
2104
|
+
edges.push(classify(points[points.length - 1], points[0]));
|
|
1680
2105
|
points.push(points[0]);
|
|
1681
2106
|
const xy = points.map((p) => this.project(r, p));
|
|
1682
2107
|
if (ringOrientation(xy) > 0 !== (index === 0)) {
|
|
1683
2108
|
xy.reverse();
|
|
1684
2109
|
points.reverse();
|
|
2110
|
+
edges.reverse();
|
|
2111
|
+
for (const e of edges)
|
|
2112
|
+
[e.t0, e.t1] = [e.t1, e.t0];
|
|
2113
|
+
}
|
|
2114
|
+
if (output.edgeProvenance) {
|
|
2115
|
+
if (edges.length !== points.length - 1)
|
|
2116
|
+
throw new Error("Mismatched polygon edge provenance");
|
|
2117
|
+
output.edgeProvenance.push(edges);
|
|
1685
2118
|
}
|
|
1686
2119
|
output.coordinates.push(xy);
|
|
1687
2120
|
output.sourceCoordinates.push(points.map(coordinates));
|
|
@@ -1794,6 +2227,8 @@ var CapMap;
|
|
|
1794
2227
|
var init_cap_map = __esm({
|
|
1795
2228
|
"dist/discontinuous/cap-map.js"() {
|
|
1796
2229
|
init_clip_circle();
|
|
2230
|
+
init_polygon_constraints();
|
|
2231
|
+
init_source_arc();
|
|
1797
2232
|
init_circle();
|
|
1798
2233
|
init_map_layout();
|
|
1799
2234
|
init_math2();
|
|
@@ -1850,10 +2285,11 @@ var init_cap_map = __esm({
|
|
|
1850
2285
|
unprojectPoint(p, id) {
|
|
1851
2286
|
return super.unprojectPoint(p, id).filter((q) => this.visible(q.position));
|
|
1852
2287
|
}
|
|
1853
|
-
clip(rings, polygon, options, regionId) {
|
|
2288
|
+
clip(rings, polygon, options, regionId, segmentIndices) {
|
|
1854
2289
|
const output = [];
|
|
1855
2290
|
const originals = /* @__PURE__ */ new Map();
|
|
1856
|
-
let ring = [];
|
|
2291
|
+
let ring = [], indices = [], activeSegment = 0;
|
|
2292
|
+
let previousInput, currentInput;
|
|
1857
2293
|
const precision = Math.min((options == null ? void 0 : options.maxAngularStep) ?? 2, Math.sqrt(((options == null ? void 0 : options.tolerance) ?? 1e-4) / this.radius) / RAD / 4) * RAD;
|
|
1858
2294
|
if (!Number.isFinite(precision) || 2 * Math.PI / precision > 1e6)
|
|
1859
2295
|
throw new Error("Projection sampling limit exceeded; relax tolerance");
|
|
@@ -1908,14 +2344,49 @@ var init_cap_map = __esm({
|
|
|
1908
2344
|
point: (x, y) => {
|
|
1909
2345
|
if (++emitted > 1e6)
|
|
1910
2346
|
throw new Error("Projection sampling limit exceeded; relax tolerance");
|
|
1911
|
-
|
|
2347
|
+
let source = originals.get(`${x},${y}`);
|
|
2348
|
+
if (!source && !polygon && this.nonlinear && previousInput && currentInput) {
|
|
2349
|
+
const a = geographic(previousInput), b = geographic(currentInput), length = angle(a, b);
|
|
2350
|
+
const at = (t) => length < 1e-14 ? [...currentInput] : coordinates(unit(a.map((v, k2) => (Math.sin((1 - t) * length) * v + Math.sin(t * length) * b[k2]) / Math.sin(length))));
|
|
2351
|
+
const value2 = (t) => geographic(local(at(t)))[0] - Math.cos(this.cap);
|
|
2352
|
+
const approximate = this.source([x / RAD, y / RAD]);
|
|
2353
|
+
const reference = length ? Math.min(1, angle(a, geographic(approximate)) / length) : 0;
|
|
2354
|
+
const roots = [];
|
|
2355
|
+
for (let j = 0; j < 32; j++) {
|
|
2356
|
+
let lo = j / 32, hi = (j + 1) / 32, f = value2(lo), g = value2(hi);
|
|
2357
|
+
if (Math.abs(f) < 1e-14)
|
|
2358
|
+
roots.push(lo);
|
|
2359
|
+
if (f * g >= 0)
|
|
2360
|
+
continue;
|
|
2361
|
+
for (let k2 = 0; k2 < 52; k2++) {
|
|
2362
|
+
const mid = (lo + hi) / 2;
|
|
2363
|
+
if (value2(mid) >= 0 === f >= 0)
|
|
2364
|
+
lo = mid;
|
|
2365
|
+
else
|
|
2366
|
+
hi = mid;
|
|
2367
|
+
}
|
|
2368
|
+
roots.push((lo + hi) / 2);
|
|
2369
|
+
}
|
|
2370
|
+
if (Math.abs(value2(1)) < 1e-14)
|
|
2371
|
+
roots.push(1);
|
|
2372
|
+
if (!roots.length)
|
|
2373
|
+
throw new Error("Unresolved nonlinear cap source intersection");
|
|
2374
|
+
roots.sort((a2, b2) => Math.abs(a2 - reference) - Math.abs(b2 - reference));
|
|
2375
|
+
source = at(roots[0]);
|
|
2376
|
+
}
|
|
2377
|
+
ring.push(source ?? this.source([x / RAD, y / RAD]));
|
|
2378
|
+
if (segmentIndices)
|
|
2379
|
+
indices.push(activeSegment);
|
|
1912
2380
|
},
|
|
1913
2381
|
lineStart: () => {
|
|
1914
2382
|
ring = [];
|
|
2383
|
+
indices = [];
|
|
1915
2384
|
},
|
|
1916
2385
|
lineEnd: () => {
|
|
1917
|
-
if (ring.length > 1)
|
|
2386
|
+
if (ring.length > 1) {
|
|
1918
2387
|
output.push(ring);
|
|
2388
|
+
segmentIndices == null ? void 0 : segmentIndices.push(indices);
|
|
2389
|
+
}
|
|
1919
2390
|
},
|
|
1920
2391
|
polygonStart: () => {
|
|
1921
2392
|
},
|
|
@@ -1932,7 +2403,9 @@ var init_cap_map = __esm({
|
|
|
1932
2403
|
}
|
|
1933
2404
|
const x = q[0] * RAD, y = q[1] * RAD;
|
|
1934
2405
|
originals.set(`${x},${y}`, [...p]);
|
|
2406
|
+
currentInput = p;
|
|
1935
2407
|
stream.point(x, y);
|
|
2408
|
+
previousInput = p;
|
|
1936
2409
|
};
|
|
1937
2410
|
const subdivide = (a, b, depth = 0) => {
|
|
1938
2411
|
if (this.nonlinear && depth < 20) {
|
|
@@ -1949,11 +2422,14 @@ var init_cap_map = __esm({
|
|
|
1949
2422
|
emit(b);
|
|
1950
2423
|
};
|
|
1951
2424
|
for (const points of rings) {
|
|
2425
|
+
previousInput = void 0;
|
|
1952
2426
|
stream.lineStart();
|
|
1953
2427
|
if (points.length)
|
|
1954
2428
|
emit(points[0]);
|
|
1955
|
-
for (let i = 1; i < points.length; i++)
|
|
2429
|
+
for (let i = 1; i < points.length; i++) {
|
|
2430
|
+
activeSegment = i - 1;
|
|
1956
2431
|
subdivide(points[i - 1], points[i]);
|
|
2432
|
+
}
|
|
1957
2433
|
if (polygon && points.length)
|
|
1958
2434
|
subdivide(points[points.length - 1], points[0]);
|
|
1959
2435
|
stream.lineEnd();
|
|
@@ -1965,7 +2441,41 @@ var init_cap_map = __esm({
|
|
|
1965
2441
|
projectLine(line, options) {
|
|
1966
2442
|
if (this.cap === Math.PI / 2 && !this.nonlinear)
|
|
1967
2443
|
return super.projectLine(line, options);
|
|
1968
|
-
return super.projectLine(line, options).flatMap((part) =>
|
|
2444
|
+
return super.projectLine(line, options).flatMap((part) => {
|
|
2445
|
+
const indices = part.provenance ? [] : void 0;
|
|
2446
|
+
const clipped = this.clip([part.sourceCoordinates], false, options, part.regionId, indices);
|
|
2447
|
+
return clipped.flatMap((points, piece) => super.projectLine(points, options).filter((q) => q.regionId === part.regionId).map((q) => {
|
|
2448
|
+
const parent = part.provenance, child2 = q.provenance;
|
|
2449
|
+
if (!parent || !child2)
|
|
2450
|
+
return q;
|
|
2451
|
+
const provenance = {
|
|
2452
|
+
segments: [],
|
|
2453
|
+
parameters: [],
|
|
2454
|
+
vertices: [],
|
|
2455
|
+
angularDistances: []
|
|
2456
|
+
};
|
|
2457
|
+
for (let j = 0; j < q.sourceCoordinates.length; j++) {
|
|
2458
|
+
const k2 = child2.segments[j];
|
|
2459
|
+
const edge2 = indices[piece][k2 + 1];
|
|
2460
|
+
const a = geographic(part.sourceCoordinates[edge2]), b = geographic(part.sourceCoordinates[edge2 + 1]), p = geographic(q.sourceCoordinates[j]);
|
|
2461
|
+
const length = angle(a, b), t = length ? Math.min(1, angle(a, p) / length) : 0;
|
|
2462
|
+
const endpoint = t < 1e-12 ? edge2 : t > 1 - 1e-12 ? edge2 + 1 : -1;
|
|
2463
|
+
const segment = parent.segments[edge2 + 1];
|
|
2464
|
+
const from = parent.segments[edge2] === segment ? parent.parameters[edge2] : 0;
|
|
2465
|
+
provenance.segments.push(endpoint >= 0 ? parent.segments[endpoint] : segment);
|
|
2466
|
+
provenance.parameters.push(endpoint >= 0 ? parent.parameters[endpoint] : from + t * (parent.parameters[edge2 + 1] - from));
|
|
2467
|
+
provenance.vertices.push(endpoint >= 0 ? parent.vertices[endpoint] : 4294967295);
|
|
2468
|
+
if (options == null ? void 0 : options.pathDistances)
|
|
2469
|
+
provenance.angularDistances.push(parent.angularDistances[edge2] + t * (parent.angularDistances[edge2 + 1] - parent.angularDistances[edge2]));
|
|
2470
|
+
}
|
|
2471
|
+
if (options == null ? void 0 : options.pathBoundaries) {
|
|
2472
|
+
const same = (a, b) => angle(geographic(a), geographic(b)) < 1e-12;
|
|
2473
|
+
provenance.startReason = same(q.sourceCoordinates[0], part.sourceCoordinates[0]) ? parent.startReason : "coverage-boundary";
|
|
2474
|
+
provenance.endReason = same(q.sourceCoordinates[q.sourceCoordinates.length - 1], part.sourceCoordinates[part.sourceCoordinates.length - 1]) ? parent.endReason : "coverage-boundary";
|
|
2475
|
+
}
|
|
2476
|
+
return { ...q, provenance };
|
|
2477
|
+
}));
|
|
2478
|
+
});
|
|
1969
2479
|
}
|
|
1970
2480
|
projectPolygon(rings, options) {
|
|
1971
2481
|
if (this.cap === Math.PI / 2 && !this.nonlinear)
|
|
@@ -2038,15 +2548,95 @@ var init_cap_map = __esm({
|
|
|
2038
2548
|
};
|
|
2039
2549
|
for (const ring of outer) {
|
|
2040
2550
|
const plane = ring.map(planar), sources = [ring, ...holes.filter((h2) => contains2(plane, planar(h2[0])))];
|
|
2551
|
+
const parentPlane = part.sourceCoordinates.map((r) => r.map(planar));
|
|
2552
|
+
const fromPlane = (p) => coordinates(unit(center3.map((v, k2) => v + x[k2] * p[0] + y[k2] * p[1])));
|
|
2553
|
+
const traced = tracePolygonConstraints(parentPlane, sources.map((r) => r.map(planar)), this.nonlinear ? 2e-6 : 1e-10, part.edgeProvenance, (p) => this.visible(fromPlane(p)));
|
|
2554
|
+
const resolved2 = traced.rings.map((r) => r.map(fromPlane));
|
|
2555
|
+
traced.owners.forEach((owners, r) => owners.forEach((owner, i) => {
|
|
2556
|
+
if (!owner)
|
|
2557
|
+
return;
|
|
2558
|
+
const [pr, pe] = owner, a = part.sourceCoordinates[pr][pe], b = part.sourceCoordinates[pr][pe + 1], at = sourceArc(a, b);
|
|
2559
|
+
for (const j of [i, i + 1]) {
|
|
2560
|
+
const point = resolved2[r][j], distance3 = angle(geographic(a), geographic(b)), fraction = distance3 ? angle(geographic(a), geographic(point)) / distance3 : 0;
|
|
2561
|
+
if (fraction < 1e-10)
|
|
2562
|
+
resolved2[r][j] = [...a];
|
|
2563
|
+
else if (fraction > 1 - 1e-10)
|
|
2564
|
+
resolved2[r][j] = [...b];
|
|
2565
|
+
else if (Math.hypot(...cross(geographic(a), geographic(b))) > 1e-14 && Math.abs(dot(unit(cross(geographic(a), geographic(b))), geographic(point))) < 1e-12) {
|
|
2566
|
+
resolved2[r][j] = at(Math.min(1, Math.max(0, fraction)));
|
|
2567
|
+
} else {
|
|
2568
|
+
const value2 = (t) => geographic(this.local(at(t)))[0] - Math.cos(this.cap), roots = [];
|
|
2569
|
+
for (let k2 = 0; k2 < 32; k2++) {
|
|
2570
|
+
let lo = k2 / 32, hi = (k2 + 1) / 32, f = value2(lo), g = value2(hi);
|
|
2571
|
+
if (Math.abs(f) < 1e-13)
|
|
2572
|
+
roots.push(lo);
|
|
2573
|
+
if (f * g >= 0)
|
|
2574
|
+
continue;
|
|
2575
|
+
for (let n = 0; n < 52; n++) {
|
|
2576
|
+
const mid = (lo + hi) / 2;
|
|
2577
|
+
if (value2(mid) >= 0 === f >= 0)
|
|
2578
|
+
lo = mid;
|
|
2579
|
+
else
|
|
2580
|
+
hi = mid;
|
|
2581
|
+
}
|
|
2582
|
+
roots.push((lo + hi) / 2);
|
|
2583
|
+
}
|
|
2584
|
+
if (Math.abs(value2(1)) < 1e-13)
|
|
2585
|
+
roots.push(1);
|
|
2586
|
+
if (!roots.length)
|
|
2587
|
+
throw new Error("Unresolved cap polygon source intersection");
|
|
2588
|
+
roots.sort((a2, b2) => Math.abs(a2 - fraction) - Math.abs(b2 - fraction));
|
|
2589
|
+
resolved2[r][j] = at(roots[0]);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
}));
|
|
2593
|
+
for (const ring2 of resolved2)
|
|
2594
|
+
ring2[ring2.length - 1] = [...ring2[0]];
|
|
2041
2595
|
result.push({
|
|
2042
2596
|
regionId: part.regionId,
|
|
2043
|
-
sourceCoordinates:
|
|
2044
|
-
coordinates:
|
|
2597
|
+
sourceCoordinates: resolved2,
|
|
2598
|
+
coordinates: resolved2.map((r) => r.map((p) => {
|
|
2045
2599
|
const q = super.projectPoint(p, part.regionId);
|
|
2046
2600
|
if (!q)
|
|
2047
|
-
throw new Error(
|
|
2601
|
+
throw new Error("Cap polygon source constraint left its owning chart");
|
|
2048
2602
|
return q.position;
|
|
2049
|
-
}))
|
|
2603
|
+
})),
|
|
2604
|
+
...(options == null ? void 0 : options.polygonEdgeProvenance) ? {
|
|
2605
|
+
edgeProvenance: traced.owners.map((owners, r) => owners.map((owner, i) => {
|
|
2606
|
+
const a = resolved2[r][i], b = resolved2[r][i + 1];
|
|
2607
|
+
if (owner) {
|
|
2608
|
+
const [pr, pe] = owner;
|
|
2609
|
+
return composePolygonEdge(part.edgeProvenance[pr][pe], part.sourceCoordinates[pr][pe], part.sourceCoordinates[pr][pe + 1], a, b);
|
|
2610
|
+
}
|
|
2611
|
+
if (angle(geographic(a), geographic(b)) < 64 * Number.EPSILON)
|
|
2612
|
+
return {
|
|
2613
|
+
kind: "continuous-chart-join",
|
|
2614
|
+
ring: 4294967295,
|
|
2615
|
+
segment: 4294967295,
|
|
2616
|
+
t0: 0,
|
|
2617
|
+
t1: 0
|
|
2618
|
+
};
|
|
2619
|
+
const kinds = [];
|
|
2620
|
+
region.boundary.forEach((p, j) => {
|
|
2621
|
+
const n = cross(geographic(p), geographic(region.boundary[(j + 1) % region.boundary.length])), length = Math.hypot(...n);
|
|
2622
|
+
if (length && [a, b].every((p2) => Math.abs(dot(n, geographic(p2))) / length < 1e-9)) {
|
|
2623
|
+
const seam = this.seams.find((s) => s.regions.some((id, k2) => id === region.id && s.edges[k2] === j));
|
|
2624
|
+
if (seam)
|
|
2625
|
+
kinds.push(seam.kind);
|
|
2626
|
+
}
|
|
2627
|
+
});
|
|
2628
|
+
const horizon = [a, b].every((p) => Math.abs(geographic(this.local(p))[0] - Math.cos(this.cap)) < 1e-7);
|
|
2629
|
+
if (!horizon && !kinds.length)
|
|
2630
|
+
throw new Error("Unknown cap polygon clipping constraint");
|
|
2631
|
+
return {
|
|
2632
|
+
kind: horizon ? "coverage-boundary" : kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join",
|
|
2633
|
+
ring: 4294967295,
|
|
2634
|
+
segment: 4294967295,
|
|
2635
|
+
t0: 0,
|
|
2636
|
+
t1: 0
|
|
2637
|
+
};
|
|
2638
|
+
}))
|
|
2639
|
+
} : {}
|
|
2050
2640
|
});
|
|
2051
2641
|
}
|
|
2052
2642
|
}
|
|
@@ -4322,6 +4912,101 @@ var init_grid = __esm({
|
|
|
4322
4912
|
}
|
|
4323
4913
|
});
|
|
4324
4914
|
|
|
4915
|
+
// dist/discontinuous/elastic/source-arc.js
|
|
4916
|
+
function clipSourceArc(a, b, polygons) {
|
|
4917
|
+
const at = sourceArc(a, b), va = geographic(a), vb = geographic(b), omega = angle(va, vb), ts = [0, 1];
|
|
4918
|
+
let work = 0;
|
|
4919
|
+
const tick = () => {
|
|
4920
|
+
if (++work > 1e6)
|
|
4921
|
+
throw new Error("Elastic source clipping limit exceeded");
|
|
4922
|
+
};
|
|
4923
|
+
const linear = omega < 1e-14 || Math.abs(a[1]) < 1e-12 && Math.abs(b[1]) < 1e-12 || Math.abs(at(0)[0] - at(1)[0]) < 1e-12;
|
|
4924
|
+
const tangent = omega > 1e-14 ? va.map((v, k2) => (vb[k2] - v * Math.cos(omega)) / Math.sin(omega)) : [0, 0, 0];
|
|
4925
|
+
const momentum = Math.abs(omega * (va[0] * tangent[1] - va[1] * tangent[0])) + 64 * Number.EPSILON * omega;
|
|
4926
|
+
const vector = (t) => va.map((v, k2) => v * Math.cos(omega * t) + tangent[k2] * Math.sin(omega * t));
|
|
4927
|
+
const derivative = (t) => va.map((v, k2) => omega * (-v * Math.sin(omega * t) + tangent[k2] * Math.cos(omega * t)));
|
|
4928
|
+
for (const rings of polygons)
|
|
4929
|
+
for (const ring of rings)
|
|
4930
|
+
for (let edge2 = 1; edge2 < ring.length; edge2++) {
|
|
4931
|
+
const c = ring[edge2 - 1], d = ring[edge2], dx = d[0] - c[0], dy = d[1] - c[1], length = Math.hypot(dx, dy);
|
|
4932
|
+
if (!length)
|
|
4933
|
+
continue;
|
|
4934
|
+
const angular = omega / RAD, latitude = Math.min(90, Math.max(Math.abs(a[1]), Math.abs(b[1])) + angular), cosine2 = Math.cos(latitude * RAD), longitude3 = cosine2 > 1e-10 ? angular / cosine2 : 360;
|
|
4935
|
+
if (Math.max(c[1], d[1]) < Math.min(a[1], b[1]) - angular - 1e-10 || Math.min(c[1], d[1]) > Math.max(a[1], b[1]) + angular + 1e-10 || Math.max(c[0], d[0]) < Math.min(a[0], b[0]) - longitude3 - 1e-10 || Math.min(c[0], d[0]) > Math.max(a[0], b[0]) + longitude3 + 1e-10)
|
|
4936
|
+
continue;
|
|
4937
|
+
const value2 = (t) => {
|
|
4938
|
+
tick();
|
|
4939
|
+
const p = at(t);
|
|
4940
|
+
return ((p[0] - c[0]) * dy - (p[1] - c[1]) * dx) / length;
|
|
4941
|
+
};
|
|
4942
|
+
const put = (t) => {
|
|
4943
|
+
const p = at(t), u = ((p[0] - c[0]) * dx + (p[1] - c[1]) * dy) / (length * length);
|
|
4944
|
+
if (u >= -1e-10 && u <= 1 + 1e-10)
|
|
4945
|
+
ts.push(t);
|
|
4946
|
+
};
|
|
4947
|
+
const bisect = (lo, hi, f) => {
|
|
4948
|
+
for (let k2 = 0; k2 < 52; k2++) {
|
|
4949
|
+
const mid = (lo + hi) / 2;
|
|
4950
|
+
if (value2(mid) >= 0 === f >= 0)
|
|
4951
|
+
lo = mid;
|
|
4952
|
+
else
|
|
4953
|
+
hi = mid;
|
|
4954
|
+
}
|
|
4955
|
+
put((lo + hi) / 2);
|
|
4956
|
+
};
|
|
4957
|
+
const visit = (lo, hi, depth) => {
|
|
4958
|
+
tick();
|
|
4959
|
+
const f = value2(lo), g = value2(hi), mid = (lo + hi) / 2, h2 = (hi - lo) / 2;
|
|
4960
|
+
if (Math.abs(f) < 1e-12)
|
|
4961
|
+
put(lo);
|
|
4962
|
+
if (Math.abs(g) < 1e-12)
|
|
4963
|
+
put(hi);
|
|
4964
|
+
if (linear) {
|
|
4965
|
+
if (f * g < 0)
|
|
4966
|
+
bisect(lo, hi, f);
|
|
4967
|
+
return;
|
|
4968
|
+
}
|
|
4969
|
+
const v = vector(mid), dv = derivative(mid), r2 = v[0] * v[0] + v[1] * v[1];
|
|
4970
|
+
const df = ((v[0] * dv[1] - v[1] * dv[0]) / r2 * dy - dv[2] / Math.sqrt(r2) * dx) / (RAD * length);
|
|
4971
|
+
let z = Math.max(Math.abs(vector(lo)[2]), Math.abs(vector(hi)[2]));
|
|
4972
|
+
const phase = Math.atan2(tangent[2], va[2]);
|
|
4973
|
+
for (let k2 = -2; k2 <= 2; k2++) {
|
|
4974
|
+
const theta = phase + k2 * Math.PI;
|
|
4975
|
+
if (theta >= omega * lo && theta <= omega * hi)
|
|
4976
|
+
z = Math.max(z, Math.hypot(va[2], tangent[2]));
|
|
4977
|
+
}
|
|
4978
|
+
const r = Math.sqrt(Math.max(0, 1 - Math.min(1, z) ** 2));
|
|
4979
|
+
const second = r ? (2 * momentum * omega * Math.abs(dy) / r ** 4 + omega ** 2 * Math.abs(dx) * (1 / r + 1 / r ** 3)) / (RAD * length) : Infinity;
|
|
4980
|
+
if (Number.isFinite(df) && Math.abs(df) > second * h2 + 1e-12) {
|
|
4981
|
+
if (f * g < 0)
|
|
4982
|
+
bisect(lo, hi, f);
|
|
4983
|
+
return;
|
|
4984
|
+
}
|
|
4985
|
+
const speed = r ? (momentum * Math.abs(dy) / r ** 2 + omega * Math.abs(dx)) / (RAD * length) : Infinity;
|
|
4986
|
+
if (Math.abs(value2(mid)) > speed * h2 + 1e-12)
|
|
4987
|
+
return;
|
|
4988
|
+
if (depth >= 24)
|
|
4989
|
+
throw new Error("Unresolved Elastic source clipping tangent or pole");
|
|
4990
|
+
visit(lo, mid, depth + 1);
|
|
4991
|
+
visit(mid, hi, depth + 1);
|
|
4992
|
+
};
|
|
4993
|
+
visit(0, 1, 0);
|
|
4994
|
+
}
|
|
4995
|
+
ts.sort((a2, b2) => a2 - b2);
|
|
4996
|
+
const result = [];
|
|
4997
|
+
for (let i = 1; i < ts.length; i++)
|
|
4998
|
+
if (ts[i] - ts[i - 1] > 1e-12 && contains(polygons, at((ts[i] + ts[i - 1]) / 2)))
|
|
4999
|
+
result.push({ a: at(ts[i - 1]), b: at(ts[i]) });
|
|
5000
|
+
return result;
|
|
5001
|
+
}
|
|
5002
|
+
var init_source_arc2 = __esm({
|
|
5003
|
+
"dist/discontinuous/elastic/source-arc.js"() {
|
|
5004
|
+
init_math2();
|
|
5005
|
+
init_geometry();
|
|
5006
|
+
init_source_arc();
|
|
5007
|
+
}
|
|
5008
|
+
});
|
|
5009
|
+
|
|
4325
5010
|
// dist/discontinuous/elastic/map.js
|
|
4326
5011
|
function createElasticMap(data, options = {}) {
|
|
4327
5012
|
return new ElasticMap(data, options.radius ?? 1);
|
|
@@ -4331,7 +5016,7 @@ function wrap2(lon) {
|
|
|
4331
5016
|
return x > 180 ? x - 360 : x < -180 ? x + 360 : x;
|
|
4332
5017
|
}
|
|
4333
5018
|
function snapPolygon(rings) {
|
|
4334
|
-
return rings.map((
|
|
5019
|
+
return rings.map((r) => r.map((p) => p.map((v) => Math.round(v * 1e10) / 1e10)));
|
|
4335
5020
|
}
|
|
4336
5021
|
var import_polygon_clipping4, kernel, splitter, ElasticMap;
|
|
4337
5022
|
var init_map = __esm({
|
|
@@ -4341,6 +5026,9 @@ var init_map = __esm({
|
|
|
4341
5026
|
init_math2();
|
|
4342
5027
|
init_grid();
|
|
4343
5028
|
init_geometry();
|
|
5029
|
+
init_source_arc2();
|
|
5030
|
+
init_source_arc();
|
|
5031
|
+
init_polygon_constraints();
|
|
4344
5032
|
kernel = Object.assign((x, y) => [x, y], {
|
|
4345
5033
|
invert: (x, y) => [x, y]
|
|
4346
5034
|
});
|
|
@@ -4468,7 +5156,7 @@ var init_map = __esm({
|
|
|
4468
5156
|
}
|
|
4469
5157
|
sourceOptions(options) {
|
|
4470
5158
|
const { step } = sampling(options);
|
|
4471
|
-
return { maxAngularStep: Math.min(step, 1), tolerance: 1e-5 };
|
|
5159
|
+
return { ...options, maxAngularStep: Math.min(step, 1), tolerance: 1e-5 };
|
|
4472
5160
|
}
|
|
4473
5161
|
sampled(c, line, options) {
|
|
4474
5162
|
return sample(line, (p) => c.grid.project(p), options, Math.min(180 / (c.grid.section.rows - 1), 360 / (c.grid.section.columns - 1)));
|
|
@@ -4477,23 +5165,70 @@ var init_map = __esm({
|
|
|
4477
5165
|
const out = [];
|
|
4478
5166
|
for (const part of splitter.projectLine(line, this.sourceOptions(options)))
|
|
4479
5167
|
for (const c of this.charts.filter((c2) => c2.baseId === part.regionId)) {
|
|
4480
|
-
let current
|
|
4481
|
-
const
|
|
4482
|
-
if (
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
5168
|
+
let current;
|
|
5169
|
+
const boundary = (point, vertex) => {
|
|
5170
|
+
if (vertex === 0 || vertex === line.length - 1)
|
|
5171
|
+
return "source-endpoint";
|
|
5172
|
+
let edge2 = 0;
|
|
5173
|
+
const kinds = [];
|
|
5174
|
+
for (const polygon of c.domain)
|
|
5175
|
+
for (const ring of polygon)
|
|
5176
|
+
for (let i = 1; i < ring.length; i++, edge2++)
|
|
5177
|
+
if (onSegment(point, ring[i - 1], ring[i])) {
|
|
5178
|
+
const seam = this.seams.find((s) => s.regions.some((id, j) => id === c.region.id && s.edges[j] === edge2));
|
|
5179
|
+
kinds.push((seam == null ? void 0 : seam.kind) ?? "boundary");
|
|
5180
|
+
}
|
|
5181
|
+
return kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : kinds.includes("join") ? "continuous-chart-join" : "coverage-boundary";
|
|
4487
5182
|
};
|
|
4488
|
-
for (let i = 1; i < part.
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
current.push(b);
|
|
5183
|
+
for (let i = 1; i < part.sourceCoordinates.length; i++) {
|
|
5184
|
+
const a = part.coordinates[i - 1], b = part.coordinates[i];
|
|
5185
|
+
const intervals = clipSourceArc(a, b, c.domain);
|
|
5186
|
+
if (!intervals.length) {
|
|
5187
|
+
current = void 0;
|
|
5188
|
+
continue;
|
|
4495
5189
|
}
|
|
4496
|
-
|
|
5190
|
+
if (Math.hypot(intervals[0].a[0] - a[0], intervals[0].a[1] - a[1]) > 1e-8)
|
|
5191
|
+
current = void 0;
|
|
5192
|
+
for (const clipped of intervals) {
|
|
5193
|
+
const arc = sourceArc(clipped.a, clipped.b);
|
|
5194
|
+
const samples = sample([clipped.a, clipped.b], (p) => c.grid.project(p), options, Math.min(180 / (c.grid.section.rows - 1), 360 / (c.grid.section.columns - 1)), (_, t) => arc(t));
|
|
5195
|
+
const first = samples.source[0], last = samples.source[samples.source.length - 1];
|
|
5196
|
+
const joined = current && Math.hypot(...current.sourceCoordinates[current.sourceCoordinates.length - 1].map((v, k2) => v - first[k2])) < 1e-8;
|
|
5197
|
+
if (!joined) {
|
|
5198
|
+
current = { regionId: c.region.id, coordinates: [], sourceCoordinates: [] };
|
|
5199
|
+
if (part.provenance)
|
|
5200
|
+
current.provenance = {
|
|
5201
|
+
segments: [],
|
|
5202
|
+
parameters: [],
|
|
5203
|
+
vertices: [],
|
|
5204
|
+
angularDistances: []
|
|
5205
|
+
};
|
|
5206
|
+
out.push(current);
|
|
5207
|
+
}
|
|
5208
|
+
for (let j = joined ? 1 : 0; j < samples.source.length; j++) {
|
|
5209
|
+
const p = samples.source[j];
|
|
5210
|
+
current.sourceCoordinates.push(p);
|
|
5211
|
+
current.coordinates.push(samples.xy[j]);
|
|
5212
|
+
const parent = part.provenance, target = current.provenance;
|
|
5213
|
+
if (parent && target) {
|
|
5214
|
+
const length = angle(geographic(a), geographic(b)), t = length ? Math.min(1, angle(geographic(a), geographic(p)) / length) : 0;
|
|
5215
|
+
const endpoint = t < 1e-12 ? i - 1 : t > 1 - 1e-12 ? i : -1, segment = parent.segments[i], from = parent.segments[i - 1] === segment ? parent.parameters[i - 1] : 0;
|
|
5216
|
+
target.segments.push(endpoint >= 0 ? parent.segments[endpoint] : segment);
|
|
5217
|
+
target.parameters.push(endpoint >= 0 ? parent.parameters[endpoint] : from + t * (parent.parameters[i] - from));
|
|
5218
|
+
target.vertices.push(endpoint >= 0 ? parent.vertices[endpoint] : 4294967295);
|
|
5219
|
+
if (options.pathDistances)
|
|
5220
|
+
target.angularDistances.push(parent.angularDistances[i - 1] + t * (parent.angularDistances[i] - parent.angularDistances[i - 1]));
|
|
5221
|
+
if (options.pathBoundaries) {
|
|
5222
|
+
if (target.vertices.length === 1)
|
|
5223
|
+
target.startReason = boundary(p, target.vertices[0]);
|
|
5224
|
+
target.endReason = boundary(p, target.vertices[target.vertices.length - 1]);
|
|
5225
|
+
}
|
|
5226
|
+
}
|
|
5227
|
+
}
|
|
5228
|
+
if (Math.hypot(last[0] - b[0], last[1] - b[1]) > 1e-8)
|
|
5229
|
+
current = void 0;
|
|
5230
|
+
}
|
|
5231
|
+
}
|
|
4497
5232
|
}
|
|
4498
5233
|
return out;
|
|
4499
5234
|
}
|
|
@@ -4501,13 +5236,175 @@ var init_map = __esm({
|
|
|
4501
5236
|
const out = [];
|
|
4502
5237
|
for (const part of splitter.projectPolygon(rings, this.sourceOptions(options)))
|
|
4503
5238
|
for (const c of this.charts.filter((c2) => c2.baseId === part.regionId)) {
|
|
4504
|
-
const
|
|
5239
|
+
const prepared = [], preparedEdges = [];
|
|
5240
|
+
part.coordinates.forEach((ring, r) => {
|
|
5241
|
+
const points = [], edges = [];
|
|
5242
|
+
for (let i = 1; i < ring.length; i++) {
|
|
5243
|
+
const a = ring[i - 1], b = ring[i], arc = sourceArc(a, b), length = angle(geographic(a), geographic(b)), fractions = [0, 1];
|
|
5244
|
+
for (const interval of clipSourceArc(a, b, c.domain))
|
|
5245
|
+
for (const p of [interval.a, interval.b]) {
|
|
5246
|
+
const t = length > 1e-14 ? angle(geographic(a), geographic(p)) / length : Math.abs(b[0] - a[0]) > 1e-14 ? (p[0] - a[0]) / (b[0] - a[0]) : 0;
|
|
5247
|
+
if (t > 1e-12 && t < 1 - 1e-12)
|
|
5248
|
+
fractions.push(t);
|
|
5249
|
+
}
|
|
5250
|
+
fractions.sort((a2, b2) => a2 - b2);
|
|
5251
|
+
const split = fractions.filter((t, i2) => !i2 || t - fractions[i2 - 1] > 1e-12);
|
|
5252
|
+
const append2 = (point) => {
|
|
5253
|
+
if (points.length >= 1e5)
|
|
5254
|
+
throw new Error("Elastic polygon constraint vertex limit exceeded");
|
|
5255
|
+
if (points.length) {
|
|
5256
|
+
const previous = points[points.length - 1];
|
|
5257
|
+
if (options.polygonEdgeProvenance)
|
|
5258
|
+
edges.push(composePolygonEdge(part.edgeProvenance[r][i - 1], a, b, previous, point));
|
|
5259
|
+
}
|
|
5260
|
+
points.push(point);
|
|
5261
|
+
};
|
|
5262
|
+
const first = arc(0);
|
|
5263
|
+
if (!points.length)
|
|
5264
|
+
points.push(first);
|
|
5265
|
+
else if (points[points.length - 1].some((v, k2) => v !== first[k2])) {
|
|
5266
|
+
if (angle(geographic(points[points.length - 1]), geographic(first)) > 1e-10)
|
|
5267
|
+
throw new Error("Discontinuous Elastic input source constraint");
|
|
5268
|
+
if (options.polygonEdgeProvenance)
|
|
5269
|
+
edges.push({
|
|
5270
|
+
kind: "continuous-chart-join",
|
|
5271
|
+
ring: 4294967295,
|
|
5272
|
+
segment: 4294967295,
|
|
5273
|
+
t0: 0,
|
|
5274
|
+
t1: 0
|
|
5275
|
+
});
|
|
5276
|
+
points.push(first);
|
|
5277
|
+
}
|
|
5278
|
+
for (let j = 1; j < split.length; j++) {
|
|
5279
|
+
append2(arc((split[j - 1] + split[j]) / 2));
|
|
5280
|
+
append2(arc(split[j]));
|
|
5281
|
+
}
|
|
5282
|
+
}
|
|
5283
|
+
if (points[points.length - 1].some((v, k2) => v !== points[0][k2])) {
|
|
5284
|
+
if (angle(geographic(points[points.length - 1]), geographic(points[0])) > 1e-10)
|
|
5285
|
+
throw new Error("Unclosed Elastic input source constraint");
|
|
5286
|
+
if (options.polygonEdgeProvenance)
|
|
5287
|
+
edges.push({
|
|
5288
|
+
kind: "continuous-chart-join",
|
|
5289
|
+
ring: 4294967295,
|
|
5290
|
+
segment: 4294967295,
|
|
5291
|
+
t0: 0,
|
|
5292
|
+
t1: 0
|
|
5293
|
+
});
|
|
5294
|
+
points.push([...points[0]]);
|
|
5295
|
+
}
|
|
5296
|
+
prepared.push(points);
|
|
5297
|
+
preparedEdges.push(edges);
|
|
5298
|
+
});
|
|
5299
|
+
const clipped = import_polygon_clipping4.default.intersection(snapPolygon(prepared), c.domain.map(snapPolygon));
|
|
4505
5300
|
for (const polygon of clipped) {
|
|
4506
|
-
const
|
|
5301
|
+
const input = snapPolygon(prepared), traced = tracePolygonConstraints(input, polygon, 1e-9, options.polygonEdgeProvenance ? preparedEdges : void 0, void 0, (a, b) => angle(geographic(a), geographic(b)) < 64 * Number.EPSILON), resolved2 = traced.rings.map((r) => r.map((p) => [...p]));
|
|
5302
|
+
traced.owners.forEach((owners, r) => owners.forEach((owner, i) => {
|
|
5303
|
+
if (!owner)
|
|
5304
|
+
return;
|
|
5305
|
+
const [pr, pe] = owner, a = prepared[pr][pe], b = prepared[pr][pe + 1], length = angle(geographic(a), geographic(b)), arc = sourceArc(a, b);
|
|
5306
|
+
for (const j of [i, i + 1]) {
|
|
5307
|
+
const q = traced.rings[r][j], start = input[pr][pe], end = input[pr][pe + 1];
|
|
5308
|
+
if (Math.hypot(q[0] - start[0], q[1] - start[1]) < 1e-8)
|
|
5309
|
+
resolved2[r][j] = [...a];
|
|
5310
|
+
else if (Math.hypot(q[0] - end[0], q[1] - end[1]) < 1e-8)
|
|
5311
|
+
resolved2[r][j] = [...b];
|
|
5312
|
+
else {
|
|
5313
|
+
const candidates = clipSourceArc(a, b, c.domain).flatMap((interval) => [
|
|
5314
|
+
interval.a,
|
|
5315
|
+
interval.b
|
|
5316
|
+
]);
|
|
5317
|
+
if (!candidates.length)
|
|
5318
|
+
throw new Error("Unresolved Elastic polygon source intersection");
|
|
5319
|
+
const reference = length ? angle(geographic(a), geographic(q)) / length : 0;
|
|
5320
|
+
candidates.sort((x, y) => Math.abs((length ? angle(geographic(a), geographic(x)) / length : 0) - reference) - Math.abs((length ? angle(geographic(a), geographic(y)) / length : 0) - reference));
|
|
5321
|
+
const fraction = length ? angle(geographic(a), geographic(candidates[0])) / length : 0;
|
|
5322
|
+
resolved2[r][j] = arc(Math.min(1, Math.max(0, fraction)));
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
}));
|
|
5326
|
+
for (const ring of resolved2)
|
|
5327
|
+
ring[ring.length - 1] = [...ring[0]];
|
|
5328
|
+
const generated = (a, b) => {
|
|
5329
|
+
if (angle(geographic(a), geographic(b)) < 64 * Number.EPSILON)
|
|
5330
|
+
return "continuous-chart-join";
|
|
5331
|
+
let edge2 = 0;
|
|
5332
|
+
const kinds = [];
|
|
5333
|
+
for (const polygon2 of c.domain)
|
|
5334
|
+
for (const ring of polygon2)
|
|
5335
|
+
for (let j = 1; j < ring.length; j++, edge2++)
|
|
5336
|
+
if (onSegment(a, ring[j - 1], ring[j]) && onSegment(b, ring[j - 1], ring[j])) {
|
|
5337
|
+
const seam = this.seams.find((s) => s.regions.some((id, k2) => id === c.region.id && s.edges[k2] === edge2));
|
|
5338
|
+
kinds.push((seam == null ? void 0 : seam.kind) ?? "boundary");
|
|
5339
|
+
}
|
|
5340
|
+
if (!kinds.length)
|
|
5341
|
+
throw new Error("Unknown Elastic polygon clipping constraint");
|
|
5342
|
+
return kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join";
|
|
5343
|
+
};
|
|
5344
|
+
const coordinates2 = [], sourceCoordinates = [], edgeProvenance = [];
|
|
5345
|
+
resolved2.forEach((ring, r) => {
|
|
5346
|
+
const source = [], xy = [], edges = [];
|
|
5347
|
+
for (let i = 1; i < ring.length; i++) {
|
|
5348
|
+
const owner = traced.owners[r][i - 1], arc = owner ? sourceArc(ring[i - 1], ring[i]) : void 0;
|
|
5349
|
+
const samples = sample(arc ? [arc(0), arc(1)] : [ring[i - 1], ring[i]], (p) => c.grid.project(p), options, Math.min(180 / (c.grid.section.rows - 1), 360 / (c.grid.section.columns - 1)), arc ? (_, t) => arc(t) : void 0);
|
|
5350
|
+
if (!source.length) {
|
|
5351
|
+
source.push(samples.source[0]);
|
|
5352
|
+
xy.push(samples.xy[0]);
|
|
5353
|
+
} else if (source[source.length - 1].some((v, k2) => Math.abs(v - samples.source[0][k2]) > 1e-10)) {
|
|
5354
|
+
if (angle(geographic(source[source.length - 1]), geographic(samples.source[0])) > 1e-10)
|
|
5355
|
+
throw new Error("Discontinuous Elastic polygon source constraint");
|
|
5356
|
+
if (options.polygonEdgeProvenance)
|
|
5357
|
+
edges.push({
|
|
5358
|
+
kind: "continuous-chart-join",
|
|
5359
|
+
ring: 4294967295,
|
|
5360
|
+
segment: 4294967295,
|
|
5361
|
+
t0: 0,
|
|
5362
|
+
t1: 0
|
|
5363
|
+
});
|
|
5364
|
+
source.push(samples.source[0]);
|
|
5365
|
+
xy.push(samples.xy[0]);
|
|
5366
|
+
}
|
|
5367
|
+
for (let j = 1; j < samples.source.length; j++) {
|
|
5368
|
+
if (options.polygonEdgeProvenance) {
|
|
5369
|
+
if (owner) {
|
|
5370
|
+
const [pr, pe] = owner;
|
|
5371
|
+
edges.push(composePolygonEdge(preparedEdges[pr][pe], prepared[pr][pe], prepared[pr][pe + 1], source[source.length - 1], samples.source[j]));
|
|
5372
|
+
} else
|
|
5373
|
+
edges.push({
|
|
5374
|
+
kind: generated(ring[i - 1], ring[i]),
|
|
5375
|
+
ring: 4294967295,
|
|
5376
|
+
segment: 4294967295,
|
|
5377
|
+
t0: 0,
|
|
5378
|
+
t1: 0
|
|
5379
|
+
});
|
|
5380
|
+
}
|
|
5381
|
+
source.push(samples.source[j]);
|
|
5382
|
+
xy.push(samples.xy[j]);
|
|
5383
|
+
}
|
|
5384
|
+
}
|
|
5385
|
+
if (source.length && source[source.length - 1].some((v, k2) => v !== source[0][k2])) {
|
|
5386
|
+
if (angle(geographic(source[source.length - 1]), geographic(source[0])) > 1e-10)
|
|
5387
|
+
throw new Error("Unclosed Elastic polygon source constraint");
|
|
5388
|
+
if (options.polygonEdgeProvenance)
|
|
5389
|
+
edges.push({
|
|
5390
|
+
kind: "continuous-chart-join",
|
|
5391
|
+
ring: 4294967295,
|
|
5392
|
+
segment: 4294967295,
|
|
5393
|
+
t0: 0,
|
|
5394
|
+
t1: 0
|
|
5395
|
+
});
|
|
5396
|
+
source.push([...source[0]]);
|
|
5397
|
+
xy.push([...xy[0]]);
|
|
5398
|
+
}
|
|
5399
|
+
coordinates2.push(xy);
|
|
5400
|
+
sourceCoordinates.push(source);
|
|
5401
|
+
edgeProvenance.push(edges);
|
|
5402
|
+
});
|
|
4507
5403
|
out.push({
|
|
4508
5404
|
regionId: c.region.id,
|
|
4509
|
-
coordinates:
|
|
4510
|
-
sourceCoordinates
|
|
5405
|
+
coordinates: coordinates2,
|
|
5406
|
+
sourceCoordinates,
|
|
5407
|
+
...options.polygonEdgeProvenance ? { edgeProvenance } : {}
|
|
4511
5408
|
});
|
|
4512
5409
|
}
|
|
4513
5410
|
}
|
|
@@ -7242,7 +8139,7 @@ function restoreLayout(data) {
|
|
|
7242
8139
|
const { mesh, panels, targetAngles } = data;
|
|
7243
8140
|
if (panels.length !== mesh.faces.length || targetAngles.length !== panels.length || !targetAngles.every(Number.isFinite) || data.rootTransform.length !== 16 || !data.rootTransform.every(Number.isFinite))
|
|
7244
8141
|
throw new Error("Invalid prepared hinge layout");
|
|
7245
|
-
const tree = new
|
|
8142
|
+
const tree = new import_geometry4.HingeTree(panels);
|
|
7246
8143
|
const rootTransform = new import_core2.Matrix4(data.rootTransform);
|
|
7247
8144
|
const poses = new Float64Array(panels.length * 16), angles = new Float64Array(panels.length);
|
|
7248
8145
|
const evaluate2 = (amount) => {
|
|
@@ -7285,11 +8182,11 @@ function countOverlaps(faces) {
|
|
|
7285
8182
|
}
|
|
7286
8183
|
return count;
|
|
7287
8184
|
}
|
|
7288
|
-
var import_core2,
|
|
8185
|
+
var import_core2, import_geometry4;
|
|
7289
8186
|
var init_unfold = __esm({
|
|
7290
8187
|
"dist/discontinuous/myriahedral/unfold.js"() {
|
|
7291
8188
|
import_core2 = require("@math.gl/core");
|
|
7292
|
-
|
|
8189
|
+
import_geometry4 = require("@math.gl/geometry");
|
|
7293
8190
|
init_mesh();
|
|
7294
8191
|
}
|
|
7295
8192
|
});
|
|
@@ -7488,6 +8385,8 @@ var import_polygon_clipping5, MercatorMap;
|
|
|
7488
8385
|
var init_mercator_map = __esm({
|
|
7489
8386
|
"dist/discontinuous/mercator-map.js"() {
|
|
7490
8387
|
import_polygon_clipping5 = __toESM(require("polygon-clipping"), 1);
|
|
8388
|
+
init_polygon_constraints();
|
|
8389
|
+
init_source_arc();
|
|
7491
8390
|
init_map_layout();
|
|
7492
8391
|
init_math2();
|
|
7493
8392
|
MercatorMap = class extends DiscontinuousMap {
|
|
@@ -7567,17 +8466,65 @@ var init_mercator_map = __esm({
|
|
|
7567
8466
|
continue;
|
|
7568
8467
|
}
|
|
7569
8468
|
const at = (t) => [a[0] + (b[0] - a[0]) * t, a[1] + dy * t];
|
|
7570
|
-
const
|
|
8469
|
+
const endpoint = (t) => {
|
|
8470
|
+
if (t === 0 || t === 1)
|
|
8471
|
+
return { xy: at(t), source: part.sourceCoordinates[i - 1 + t], t };
|
|
8472
|
+
const va = geographic(part.sourceCoordinates[i - 1]), vb = geographic(part.sourceCoordinates[i]), arc = angle(va, vb);
|
|
8473
|
+
const sourceAt = (t2) => {
|
|
8474
|
+
if (!arc)
|
|
8475
|
+
return part.sourceCoordinates[i - 1];
|
|
8476
|
+
const a2 = Math.sin((1 - t2) * arc) / Math.sin(arc), b2 = Math.sin(t2 * arc) / Math.sin(arc);
|
|
8477
|
+
return coordinates(unit(va.map((v, k2) => a2 * v + b2 * vb[k2])));
|
|
8478
|
+
};
|
|
8479
|
+
const latitude = Math.sign(at(t)[1]) * this.limit;
|
|
8480
|
+
let lo = 0, hi = 1;
|
|
8481
|
+
for (let j = 0; j < 52; j++) {
|
|
8482
|
+
const mid = (lo + hi) / 2;
|
|
8483
|
+
if (sourceAt(mid)[1] < latitude === part.sourceCoordinates[i - 1][1] < latitude)
|
|
8484
|
+
lo = mid;
|
|
8485
|
+
else
|
|
8486
|
+
hi = mid;
|
|
8487
|
+
}
|
|
8488
|
+
const f = (lo + hi) / 2, source = sourceAt(f);
|
|
8489
|
+
const xy = super.projectPoint(source, part.regionId).position;
|
|
8490
|
+
return { xy, source, t: f };
|
|
8491
|
+
};
|
|
8492
|
+
const start = endpoint(t0), end = endpoint(t1);
|
|
8493
|
+
const append2 = (point, index) => {
|
|
8494
|
+
current.coordinates.push(point.xy);
|
|
8495
|
+
current.sourceCoordinates.push(point.source);
|
|
8496
|
+
const source = part.provenance, target = current.provenance;
|
|
8497
|
+
if (!source || !target)
|
|
8498
|
+
return;
|
|
8499
|
+
const segment = source.segments[i];
|
|
8500
|
+
const from = source.segments[i - 1] === segment ? source.parameters[i - 1] : 0;
|
|
8501
|
+
target.segments.push(point.t === 0 || point.t === 1 ? source.segments[index] : segment);
|
|
8502
|
+
target.parameters.push(point.t === 0 || point.t === 1 ? source.parameters[index] : from + point.t * (source.parameters[i] - from));
|
|
8503
|
+
target.vertices.push(point.t === 0 || point.t === 1 ? source.vertices[index] : 4294967295);
|
|
8504
|
+
if (options == null ? void 0 : options.pathDistances)
|
|
8505
|
+
target.angularDistances.push(source.angularDistances[i - 1] + point.t * (source.angularDistances[i] - source.angularDistances[i - 1]));
|
|
8506
|
+
};
|
|
7571
8507
|
if (!current || t0 > 0) {
|
|
7572
8508
|
current = {
|
|
7573
8509
|
regionId: part.regionId,
|
|
7574
|
-
coordinates: [
|
|
7575
|
-
sourceCoordinates: [
|
|
8510
|
+
coordinates: [],
|
|
8511
|
+
sourceCoordinates: [],
|
|
8512
|
+
...part.provenance ? {
|
|
8513
|
+
provenance: {
|
|
8514
|
+
segments: [],
|
|
8515
|
+
parameters: [],
|
|
8516
|
+
vertices: [],
|
|
8517
|
+
angularDistances: [],
|
|
8518
|
+
...(options == null ? void 0 : options.pathBoundaries) ? { startReason: t0 > 0 ? "coverage-boundary" : part.provenance.startReason } : {}
|
|
8519
|
+
}
|
|
8520
|
+
} : {}
|
|
7576
8521
|
};
|
|
7577
8522
|
result.push(current);
|
|
8523
|
+
append2(start, i - 1);
|
|
7578
8524
|
}
|
|
7579
|
-
|
|
7580
|
-
current.
|
|
8525
|
+
append2(end, i);
|
|
8526
|
+
if (current.provenance && (options == null ? void 0 : options.pathBoundaries))
|
|
8527
|
+
current.provenance.endReason = t1 < 1 ? "coverage-boundary" : part.provenance.endReason;
|
|
7581
8528
|
if (t1 < 1)
|
|
7582
8529
|
current = void 0;
|
|
7583
8530
|
}
|
|
@@ -7595,11 +8542,60 @@ var init_mercator_map = __esm({
|
|
|
7595
8542
|
[-x, -y]
|
|
7596
8543
|
]
|
|
7597
8544
|
];
|
|
7598
|
-
return super.projectPolygon(rings, options).flatMap((part) => import_polygon_clipping5.default.intersection(part.coordinates, box).map((
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
7602
|
-
|
|
8545
|
+
return super.projectPolygon(rings, options).flatMap((part) => import_polygon_clipping5.default.intersection(part.coordinates, box).map((polygon) => {
|
|
8546
|
+
const traced = tracePolygonConstraints(part.coordinates, polygon, 1e-10, part.edgeProvenance);
|
|
8547
|
+
const sources = traced.rings.map((r) => r.map((p) => this.source(p)));
|
|
8548
|
+
traced.owners.forEach((owners, r) => owners.forEach((owner, i) => {
|
|
8549
|
+
if (!owner)
|
|
8550
|
+
return;
|
|
8551
|
+
const [parentRing, parentEdge] = owner, a = part.sourceCoordinates[parentRing][parentEdge], b = part.sourceCoordinates[parentRing][parentEdge + 1], at = sourceArc(a, b);
|
|
8552
|
+
for (const j of [i, i + 1]) {
|
|
8553
|
+
const q = traced.rings[r][j], first = part.coordinates[parentRing][parentEdge], last = part.coordinates[parentRing][parentEdge + 1];
|
|
8554
|
+
if (Math.hypot(q[0] - first[0], q[1] - first[1]) < 1e-10 * this.radius)
|
|
8555
|
+
sources[r][j] = [...a];
|
|
8556
|
+
else if (Math.hypot(q[0] - last[0], q[1] - last[1]) < 1e-10 * this.radius)
|
|
8557
|
+
sources[r][j] = [...b];
|
|
8558
|
+
else {
|
|
8559
|
+
const latitude = Math.sign(q[1]) * this.limit;
|
|
8560
|
+
let lo = 0, hi = 1;
|
|
8561
|
+
if (a[1] < latitude === b[1] < latitude)
|
|
8562
|
+
throw new Error("Unresolved Mercator source constraint intersection");
|
|
8563
|
+
for (let k2 = 0; k2 < 52; k2++) {
|
|
8564
|
+
const mid = (lo + hi) / 2;
|
|
8565
|
+
if (at(mid)[1] < latitude === a[1] < latitude)
|
|
8566
|
+
lo = mid;
|
|
8567
|
+
else
|
|
8568
|
+
hi = mid;
|
|
8569
|
+
}
|
|
8570
|
+
sources[r][j] = at((lo + hi) / 2);
|
|
8571
|
+
}
|
|
8572
|
+
}
|
|
8573
|
+
}));
|
|
8574
|
+
for (const r of sources)
|
|
8575
|
+
r[r.length - 1] = [...r[0]];
|
|
8576
|
+
return {
|
|
8577
|
+
regionId: part.regionId,
|
|
8578
|
+
sourceCoordinates: sources,
|
|
8579
|
+
coordinates: sources.map((r) => r.map((p) => super.projectPoint(p, part.regionId).position)),
|
|
8580
|
+
...(options == null ? void 0 : options.polygonEdgeProvenance) ? {
|
|
8581
|
+
edgeProvenance: traced.owners.map((owners, r) => owners.map((owner, i) => {
|
|
8582
|
+
if (owner) {
|
|
8583
|
+
const [pr, pe] = owner;
|
|
8584
|
+
return composePolygonEdge(part.edgeProvenance[pr][pe], part.sourceCoordinates[pr][pe], part.sourceCoordinates[pr][pe + 1], sources[r][i], sources[r][i + 1]);
|
|
8585
|
+
}
|
|
8586
|
+
if (!sources[r].slice(i, i + 2).every((p) => Math.abs(Math.abs(p[1]) - this.limit) < 1e-7))
|
|
8587
|
+
throw new Error("Unknown Mercator clipping constraint");
|
|
8588
|
+
return {
|
|
8589
|
+
kind: "coverage-boundary",
|
|
8590
|
+
ring: 4294967295,
|
|
8591
|
+
segment: 4294967295,
|
|
8592
|
+
t0: 0,
|
|
8593
|
+
t1: 0
|
|
8594
|
+
};
|
|
8595
|
+
}))
|
|
8596
|
+
} : {}
|
|
8597
|
+
};
|
|
8598
|
+
}));
|
|
7603
8599
|
}
|
|
7604
8600
|
};
|
|
7605
8601
|
}
|