@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/discontinuous.cjs
CHANGED
|
@@ -286,6 +286,10 @@ var DiscontinuousMap = class {
|
|
|
286
286
|
for (let i = 1; i < points.length; i++)
|
|
287
287
|
validateArc(points[i - 1], points[i]);
|
|
288
288
|
const results = [];
|
|
289
|
+
const cumulative = options.pathDistances ? [0] : void 0;
|
|
290
|
+
if (cumulative)
|
|
291
|
+
for (let i = 1; i < points.length; i++)
|
|
292
|
+
cumulative.push(cumulative[i - 1] + angle(points[i - 1], points[i]));
|
|
289
293
|
for (const r of this.compiled) {
|
|
290
294
|
let current = null;
|
|
291
295
|
for (let i = 1; i < points.length; i++) {
|
|
@@ -294,18 +298,42 @@ var DiscontinuousMap = class {
|
|
|
294
298
|
current = null;
|
|
295
299
|
continue;
|
|
296
300
|
}
|
|
301
|
+
const reason = (p, endpoint, isEndpoint) => {
|
|
302
|
+
if (isEndpoint && angle(p, endpoint) < 1e-12)
|
|
303
|
+
return "source-endpoint";
|
|
304
|
+
const kinds = r.normals.map((normal, edge2) => {
|
|
305
|
+
var _a;
|
|
306
|
+
return Math.abs(dot(normal, p)) < 1e-9 ? (_a = this.seams.find((s) => s.regions.some((id, i2) => id === r.definition.id && s.edges[i2] === edge2))) == null ? void 0 : _a.kind : void 0;
|
|
307
|
+
}).filter(Boolean);
|
|
308
|
+
return kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : kinds.includes("join") ? "continuous-chart-join" : "coverage-boundary";
|
|
309
|
+
};
|
|
297
310
|
const sampled = this.sample(r, clipped[0], clipped[1], settings);
|
|
298
311
|
if (sampled.length < 2)
|
|
299
312
|
continue;
|
|
300
313
|
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]))) {
|
|
301
314
|
current = { regionId: r.definition.id, coordinates: [], sourceCoordinates: [] };
|
|
315
|
+
if (options.pathProvenance)
|
|
316
|
+
current.provenance = { segments: [], parameters: [], vertices: [], angularDistances: [] };
|
|
317
|
+
if (current.provenance && options.pathBoundaries)
|
|
318
|
+
current.provenance.startReason = reason(clipped[0], points[0], i === 1);
|
|
302
319
|
results.push(current);
|
|
303
320
|
} else
|
|
304
321
|
sampled.shift();
|
|
305
322
|
for (const p of sampled) {
|
|
306
323
|
current.coordinates.push(this.project(r, p));
|
|
307
324
|
current.sourceCoordinates.push(coordinates(p));
|
|
325
|
+
if (current.provenance) {
|
|
326
|
+
const length = angle(points[i - 1], points[i]);
|
|
327
|
+
const t = length ? Math.min(1, Math.max(0, angle(points[i - 1], p) / length)) : 0;
|
|
328
|
+
current.provenance.segments.push(i - 1);
|
|
329
|
+
current.provenance.parameters.push(t);
|
|
330
|
+
current.provenance.vertices.push(angle(points[i - 1], p) < 1e-12 ? i - 1 : angle(points[i], p) < 1e-12 ? i : 4294967295);
|
|
331
|
+
if (cumulative)
|
|
332
|
+
current.provenance.angularDistances.push(cumulative[i - 1] + t * length);
|
|
333
|
+
}
|
|
308
334
|
}
|
|
335
|
+
if (current.provenance && options.pathBoundaries)
|
|
336
|
+
current.provenance.endReason = reason(clipped[1], points[points.length - 1], i === points.length - 1);
|
|
309
337
|
if (!this.contains(r, points[i]))
|
|
310
338
|
current = null;
|
|
311
339
|
}
|
|
@@ -402,26 +430,91 @@ var DiscontinuousMap = class {
|
|
|
402
430
|
coordinates: [],
|
|
403
431
|
sourceCoordinates: []
|
|
404
432
|
};
|
|
433
|
+
if (options.polygonEdgeProvenance)
|
|
434
|
+
output.edgeProvenance = [];
|
|
405
435
|
polygon.forEach((ring, index) => {
|
|
406
436
|
const sphere = ring.map((p) => unit(add(center3, add(scale(x, p[0]), scale(y, p[1])))));
|
|
407
437
|
const points = [];
|
|
438
|
+
const edges = [];
|
|
439
|
+
const classify = (a, b) => {
|
|
440
|
+
if (angle(a, b) < 64 * Number.EPSILON)
|
|
441
|
+
return {
|
|
442
|
+
kind: "continuous-chart-join",
|
|
443
|
+
ring: 4294967295,
|
|
444
|
+
segment: 4294967295,
|
|
445
|
+
t0: 0,
|
|
446
|
+
t1: 0
|
|
447
|
+
};
|
|
448
|
+
const candidates = [];
|
|
449
|
+
vectors.forEach((source, ring2) => source.forEach((u, segment) => {
|
|
450
|
+
const v = source[(segment + 1) % source.length], length = angle(u, v);
|
|
451
|
+
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))
|
|
452
|
+
candidates.push({ ring: ring2, segment });
|
|
453
|
+
}));
|
|
454
|
+
if (candidates.length > 1)
|
|
455
|
+
throw new Error("Ambiguous polygon boundary provenance");
|
|
456
|
+
if (candidates.length) {
|
|
457
|
+
const { ring: ring2, segment } = candidates[0], source = vectors[ring2], u = source[segment], length = angle(u, source[(segment + 1) % source.length]);
|
|
458
|
+
return {
|
|
459
|
+
kind: "source-boundary",
|
|
460
|
+
ring: ring2,
|
|
461
|
+
segment,
|
|
462
|
+
t0: Math.min(1, angle(u, a) / length),
|
|
463
|
+
t1: Math.min(1, angle(u, b) / length)
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
const kinds = r.normals.map((n, edge2) => {
|
|
467
|
+
var _a;
|
|
468
|
+
return [a, b].every((p) => Math.abs(dot(n, p)) < 1e-9) ? (_a = this.seams.find((s) => s.regions.some((id, i) => id === r.definition.id && s.edges[i] === edge2))) == null ? void 0 : _a.kind : void 0;
|
|
469
|
+
}).filter(Boolean);
|
|
470
|
+
if (!kinds.length)
|
|
471
|
+
throw new Error("Unknown polygon clipping constraint");
|
|
472
|
+
return {
|
|
473
|
+
kind: kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join",
|
|
474
|
+
ring: 4294967295,
|
|
475
|
+
segment: 4294967295,
|
|
476
|
+
t0: 0,
|
|
477
|
+
t1: 0
|
|
478
|
+
};
|
|
479
|
+
};
|
|
408
480
|
for (let i = 1; i < sphere.length; i++) {
|
|
481
|
+
const origin2 = options.polygonEdgeProvenance && !sphere[i - 1].every((value, k2) => value === sphere[i][k2]) ? classify(sphere[i - 1], sphere[i]) : void 0;
|
|
409
482
|
const sampled = this.sample(r, sphere[i - 1], sphere[i], settings);
|
|
410
483
|
for (const point of sampled) {
|
|
411
484
|
const previous = points[points.length - 1];
|
|
412
|
-
if (!previous || !point.every((value, k2) => value === previous[k2]))
|
|
485
|
+
if (!previous || !point.every((value, k2) => value === previous[k2])) {
|
|
486
|
+
if (previous && origin2) {
|
|
487
|
+
const edge2 = { ...origin2 };
|
|
488
|
+
if (edge2.kind === "source-boundary") {
|
|
489
|
+
const source = vectors[edge2.ring], u = source[edge2.segment], length = angle(u, source[(edge2.segment + 1) % source.length]);
|
|
490
|
+
edge2.t0 = Math.min(1, angle(u, previous) / length);
|
|
491
|
+
edge2.t1 = Math.min(1, angle(u, point) / length);
|
|
492
|
+
}
|
|
493
|
+
edges.push(edge2);
|
|
494
|
+
}
|
|
413
495
|
points.push(point);
|
|
496
|
+
}
|
|
414
497
|
}
|
|
415
498
|
}
|
|
416
499
|
if (points.length < 3)
|
|
417
500
|
return;
|
|
418
501
|
if (points[points.length - 1].every((value, k2) => value === points[0][k2]))
|
|
419
502
|
points.pop();
|
|
503
|
+
if (options.polygonEdgeProvenance && edges.length < points.length)
|
|
504
|
+
edges.push(classify(points[points.length - 1], points[0]));
|
|
420
505
|
points.push(points[0]);
|
|
421
506
|
const xy = points.map((p) => this.project(r, p));
|
|
422
507
|
if (ringOrientation(xy) > 0 !== (index === 0)) {
|
|
423
508
|
xy.reverse();
|
|
424
509
|
points.reverse();
|
|
510
|
+
edges.reverse();
|
|
511
|
+
for (const e of edges)
|
|
512
|
+
[e.t0, e.t1] = [e.t1, e.t0];
|
|
513
|
+
}
|
|
514
|
+
if (output.edgeProvenance) {
|
|
515
|
+
if (edges.length !== points.length - 1)
|
|
516
|
+
throw new Error("Mismatched polygon edge provenance");
|
|
517
|
+
output.edgeProvenance.push(edges);
|
|
425
518
|
}
|
|
426
519
|
output.coordinates.push(xy);
|
|
427
520
|
output.sourceCoordinates.push(points.map(coordinates));
|
|
@@ -2873,8 +2966,49 @@ function cutSphericalPolygon(rings, options) {
|
|
|
2873
2966
|
}
|
|
2874
2967
|
function projectSphericalPolygon(map, rings, options) {
|
|
2875
2968
|
const result = [];
|
|
2969
|
+
if (options.polygonEdgeProvenance && (!map.regions || !map.seams))
|
|
2970
|
+
throw new Error("Atlas provenance requires map region and seam metadata");
|
|
2876
2971
|
for (const part of cutSphericalPolygon(rings, options))
|
|
2877
|
-
|
|
2972
|
+
for (const polygon of map.projectPolygon(part.rings, options)) {
|
|
2973
|
+
if (options.polygonEdgeProvenance) {
|
|
2974
|
+
if (!polygon.edgeProvenance)
|
|
2975
|
+
throw new Error("Map backend does not support polygon edge provenance");
|
|
2976
|
+
const region = map.regions.find((r) => r.id === polygon.regionId);
|
|
2977
|
+
polygon.edgeProvenance = polygon.edgeProvenance.map((edges, ring) => edges.map((edge2, i) => {
|
|
2978
|
+
if (edge2.kind !== "source-boundary")
|
|
2979
|
+
return edge2;
|
|
2980
|
+
const parent = part.edges[edge2.ring][edge2.segment];
|
|
2981
|
+
if (parent.kind === "source")
|
|
2982
|
+
return {
|
|
2983
|
+
...edge2,
|
|
2984
|
+
ring: parent.ringIndex,
|
|
2985
|
+
segment: parent.edgeIndex,
|
|
2986
|
+
t0: parent.startFraction + edge2.t0 * (parent.endFraction - parent.startFraction),
|
|
2987
|
+
t1: parent.startFraction + edge2.t1 * (parent.endFraction - parent.startFraction)
|
|
2988
|
+
};
|
|
2989
|
+
const a = geographic(polygon.sourceCoordinates[ring][i]), b = geographic(polygon.sourceCoordinates[ring][i + 1]), kinds = [];
|
|
2990
|
+
region.boundary.forEach((p, j) => {
|
|
2991
|
+
const normal = cross(geographic(p), geographic(region.boundary[(j + 1) % region.boundary.length]));
|
|
2992
|
+
const length = Math.hypot(...normal);
|
|
2993
|
+
if (length < 1e-12)
|
|
2994
|
+
return;
|
|
2995
|
+
if ([a, b].every((v) => Math.abs(dot(normal, v)) / length < 1e-10)) {
|
|
2996
|
+
const seam = map.seams.find((s) => s.regions.some((id, k2) => id === region.id && s.edges[k2] === j));
|
|
2997
|
+
if (seam)
|
|
2998
|
+
kinds.push(seam.kind);
|
|
2999
|
+
}
|
|
3000
|
+
});
|
|
3001
|
+
return {
|
|
3002
|
+
kind: kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join",
|
|
3003
|
+
ring: 4294967295,
|
|
3004
|
+
segment: 4294967295,
|
|
3005
|
+
t0: 0,
|
|
3006
|
+
t1: 0
|
|
3007
|
+
};
|
|
3008
|
+
}));
|
|
3009
|
+
}
|
|
3010
|
+
result.push(polygon);
|
|
3011
|
+
}
|
|
2878
3012
|
return result;
|
|
2879
3013
|
}
|
|
2880
3014
|
|
|
@@ -2911,33 +3045,13 @@ var lerp = (a, b, t) => [
|
|
|
2911
3045
|
a[0] + (b[0] - a[0]) * t,
|
|
2912
3046
|
a[1] + (b[1] - a[1]) * t
|
|
2913
3047
|
];
|
|
2914
|
-
function clipSegment(a, b, polygons) {
|
|
2915
|
-
const ts = [0, 1], dx = b[0] - a[0], dy = b[1] - a[1];
|
|
2916
|
-
for (const rings of polygons)
|
|
2917
|
-
for (const ring of rings)
|
|
2918
|
-
for (let i = 1; i < ring.length; i++) {
|
|
2919
|
-
const c = ring[i - 1], d = ring[i], ex = d[0] - c[0], ey = d[1] - c[1], det = dx * ey - dy * ex;
|
|
2920
|
-
if (Math.abs(det) < 1e-14)
|
|
2921
|
-
continue;
|
|
2922
|
-
const t = ((c[0] - a[0]) * ey - (c[1] - a[1]) * ex) / det;
|
|
2923
|
-
const u = ((c[0] - a[0]) * dy - (c[1] - a[1]) * dx) / det;
|
|
2924
|
-
if (t > 0 && t < 1 && u >= -1e-10 && u <= 1 + 1e-10)
|
|
2925
|
-
ts.push(t);
|
|
2926
|
-
}
|
|
2927
|
-
ts.sort((a2, b2) => a2 - b2);
|
|
2928
|
-
const result = [];
|
|
2929
|
-
for (let i = 1; i < ts.length; i++)
|
|
2930
|
-
if (ts[i] - ts[i - 1] > 1e-12 && contains(polygons, lerp(a, b, (ts[i] + ts[i - 1]) / 2)))
|
|
2931
|
-
result.push([lerp(a, b, ts[i - 1]), lerp(a, b, ts[i])]);
|
|
2932
|
-
return result;
|
|
2933
|
-
}
|
|
2934
3048
|
function sampling2(options) {
|
|
2935
3049
|
const step = options.maxAngularStep ?? 2, tolerance = options.tolerance ?? 1e-4;
|
|
2936
3050
|
if (!Number.isFinite(step) || step <= 0 || step > 90 || !Number.isFinite(tolerance) || tolerance <= 0)
|
|
2937
3051
|
throw new Error("Invalid map sampling options");
|
|
2938
3052
|
return { step, tolerance };
|
|
2939
3053
|
}
|
|
2940
|
-
function sample(line, project, options, cellStep) {
|
|
3054
|
+
function sample(line, project, options, cellStep, interpolate) {
|
|
2941
3055
|
const { step, tolerance } = sampling2(options), source = [], xy = [];
|
|
2942
3056
|
const emit = (p, q) => {
|
|
2943
3057
|
if (source.length >= 1e5)
|
|
@@ -2948,23 +3062,23 @@ function sample(line, project, options, cellStep) {
|
|
|
2948
3062
|
const at = (p) => {
|
|
2949
3063
|
const q = project(p);
|
|
2950
3064
|
if (!q)
|
|
2951
|
-
throw new Error(
|
|
3065
|
+
throw new Error(`Elastic grid is undefined inside its coverage at ${p}`);
|
|
2952
3066
|
return q;
|
|
2953
3067
|
};
|
|
2954
|
-
const visit = (a, b, qa, qb, depth) => {
|
|
2955
|
-
const mid = lerp(a, b, 0.5), qm = at(mid), chord2 = lerp(qa, qb, 0.5);
|
|
3068
|
+
const visit = (a, b, qa, qb, depth, segment, t0, t1) => {
|
|
3069
|
+
const tm = (t0 + t1) / 2, mid = interpolate ? interpolate(segment, tm) : lerp(a, b, 0.5), qm = at(mid), chord2 = lerp(qa, qb, 0.5);
|
|
2956
3070
|
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) {
|
|
2957
3071
|
if (depth >= 24)
|
|
2958
3072
|
throw new Error("Elastic sampling limit exceeded");
|
|
2959
|
-
visit(a, mid, qa, qm, depth + 1);
|
|
2960
|
-
visit(mid, b, qm, qb, depth + 1);
|
|
3073
|
+
visit(a, mid, qa, qm, depth + 1, segment, t0, tm);
|
|
3074
|
+
visit(mid, b, qm, qb, depth + 1, segment, tm, t1);
|
|
2961
3075
|
} else
|
|
2962
3076
|
emit(b, qb);
|
|
2963
3077
|
};
|
|
2964
3078
|
if (line.length) {
|
|
2965
3079
|
emit(line[0], at(line[0]));
|
|
2966
3080
|
for (let i = 1; i < line.length; i++)
|
|
2967
|
-
visit(line[i - 1], line[i], at(line[i - 1]), at(line[i]), 0);
|
|
3081
|
+
visit(line[i - 1], line[i], at(line[i - 1]), at(line[i]), 0, i - 1, 0, 1);
|
|
2968
3082
|
}
|
|
2969
3083
|
return { source, xy };
|
|
2970
3084
|
}
|
|
@@ -3001,6 +3115,65 @@ function indexDomain(polygons) {
|
|
|
3001
3115
|
}
|
|
3002
3116
|
|
|
3003
3117
|
// dist/discontinuous/map-transition.js
|
|
3118
|
+
var directWorldProjections = /* @__PURE__ */ new Set([
|
|
3119
|
+
"gilbert",
|
|
3120
|
+
"aitoff",
|
|
3121
|
+
"august",
|
|
3122
|
+
"baker",
|
|
3123
|
+
"boggs",
|
|
3124
|
+
"bromley",
|
|
3125
|
+
"collignon",
|
|
3126
|
+
"craster",
|
|
3127
|
+
"eckert1",
|
|
3128
|
+
"eckert2",
|
|
3129
|
+
"eckert3",
|
|
3130
|
+
"eckert4",
|
|
3131
|
+
"eckert5",
|
|
3132
|
+
"eckert6",
|
|
3133
|
+
"fahey",
|
|
3134
|
+
"foucaut",
|
|
3135
|
+
"ginzburg4",
|
|
3136
|
+
"ginzburg5",
|
|
3137
|
+
"ginzburg6",
|
|
3138
|
+
"ginzburg8",
|
|
3139
|
+
"ginzburg9",
|
|
3140
|
+
"homolosine",
|
|
3141
|
+
"kavrayskiy7",
|
|
3142
|
+
"larrivee",
|
|
3143
|
+
"laskowski",
|
|
3144
|
+
"miller",
|
|
3145
|
+
"mollweide",
|
|
3146
|
+
"mt-flat-polar-parabolic",
|
|
3147
|
+
"mt-flat-polar-quartic",
|
|
3148
|
+
"mt-flat-polar-sinusoidal",
|
|
3149
|
+
"natural-earth2",
|
|
3150
|
+
"nell-hammer",
|
|
3151
|
+
"patterson",
|
|
3152
|
+
"robinson",
|
|
3153
|
+
"sinusoidal",
|
|
3154
|
+
"times",
|
|
3155
|
+
"van-der-grinten",
|
|
3156
|
+
"van-der-grinten2",
|
|
3157
|
+
"van-der-grinten3",
|
|
3158
|
+
"van-der-grinten4",
|
|
3159
|
+
"wagner4",
|
|
3160
|
+
"wagner6",
|
|
3161
|
+
"winkel3",
|
|
3162
|
+
"bonne",
|
|
3163
|
+
"bottomley",
|
|
3164
|
+
"cylindrical-equal-area",
|
|
3165
|
+
"cylindrical-stereographic",
|
|
3166
|
+
"foucaut-sinusoidal",
|
|
3167
|
+
"hammer",
|
|
3168
|
+
"hill",
|
|
3169
|
+
"hufnagel",
|
|
3170
|
+
"hyperelliptical",
|
|
3171
|
+
"lagrange",
|
|
3172
|
+
"loximuthal",
|
|
3173
|
+
"wagner7",
|
|
3174
|
+
"quartic-authalic",
|
|
3175
|
+
"wagner"
|
|
3176
|
+
]);
|
|
3004
3177
|
var MapTransitionGeometry = class {
|
|
3005
3178
|
constructor(parts, strategy, radius) {
|
|
3006
3179
|
this.strategy = strategy;
|
|
@@ -3232,7 +3405,7 @@ function fullCoverage(map) {
|
|
|
3232
3405
|
const overlaps = domains.some((domain, i) => domains.slice(i + 1).some((other) => import_polygon_clipping3.default.intersection(domain, other).length > 0));
|
|
3233
3406
|
covered = completeSections && !overlaps && import_polygon_clipping3.default.difference(world, ...domains).length === 0;
|
|
3234
3407
|
} else if (d.type === "world") {
|
|
3235
|
-
covered =
|
|
3408
|
+
covered = directWorldProjections.has(d.projection) && Object.keys(d.parameters ?? {}).length === 0;
|
|
3236
3409
|
}
|
|
3237
3410
|
coverageCache.set(map, covered);
|
|
3238
3411
|
return covered;
|
|
@@ -3282,6 +3455,16 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
3282
3455
|
throw new Error("Expected a feature array");
|
|
3283
3456
|
if (options.polygonOutlines !== void 0 && typeof options.polygonOutlines !== "boolean")
|
|
3284
3457
|
throw new Error("polygonOutlines must be boolean");
|
|
3458
|
+
const provenance = options.provenance;
|
|
3459
|
+
if (provenance !== void 0 && (!provenance || typeof provenance !== "object" || Array.isArray(provenance)))
|
|
3460
|
+
throw new Error("Unsupported provenance policy");
|
|
3461
|
+
if ((provenance == null ? void 0 : provenance.distances) !== void 0 && (!provenance.distances || typeof provenance.distances !== "object"))
|
|
3462
|
+
throw new Error("Unsupported provenance distance policy");
|
|
3463
|
+
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)))
|
|
3464
|
+
throw new Error("Unsupported provenance policy");
|
|
3465
|
+
const edgeKinds = [], edgeRings = [], edgeSegments = [], edgeParameters = [];
|
|
3466
|
+
const lineage = Boolean((provenance == null ? void 0 : provenance.sourceSegments) || (provenance == null ? void 0 : provenance.boundaries) || (provenance == null ? void 0 : provenance.distances));
|
|
3467
|
+
const segments = [], parameters = [], originalVertices = [], distances = [], startReasons = [], endReasons = [];
|
|
3285
3468
|
const regionIds = map.regions.map((r) => r.id), regionIndices = new Map(regionIds.map((id, i) => [id, i]));
|
|
3286
3469
|
const points = vertices(), paths = vertices(), polygons = vertices();
|
|
3287
3470
|
const pointParts = [], pathParts = [], polygonParts = [];
|
|
@@ -3302,7 +3485,27 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
3302
3485
|
const isRing = ringIndex !== void 0;
|
|
3303
3486
|
if (isRing && !closed(line))
|
|
3304
3487
|
line.push([...line[0]]);
|
|
3305
|
-
for (const p of map.projectLine(line,
|
|
3488
|
+
for (const p of map.projectLine(line, {
|
|
3489
|
+
...options.sampling,
|
|
3490
|
+
pathProvenance: lineage,
|
|
3491
|
+
pathDistances: Boolean(provenance == null ? void 0 : provenance.distances),
|
|
3492
|
+
pathBoundaries: Boolean(provenance == null ? void 0 : provenance.boundaries)
|
|
3493
|
+
})) {
|
|
3494
|
+
if (lineage) {
|
|
3495
|
+
if (!p.provenance)
|
|
3496
|
+
throw new Error("Map backend does not support path provenance");
|
|
3497
|
+
if (provenance == null ? void 0 : provenance.sourceSegments) {
|
|
3498
|
+
segments.push(...p.provenance.segments);
|
|
3499
|
+
parameters.push(...p.provenance.parameters);
|
|
3500
|
+
originalVertices.push(...p.provenance.vertices);
|
|
3501
|
+
}
|
|
3502
|
+
if (provenance == null ? void 0 : provenance.distances)
|
|
3503
|
+
distances.push(...p.provenance.angularDistances.map((d) => d * provenance.distances.radius));
|
|
3504
|
+
if (provenance == null ? void 0 : provenance.boundaries) {
|
|
3505
|
+
startReasons.push(p.provenance.startReason);
|
|
3506
|
+
endReasons.push(p.provenance.endReason);
|
|
3507
|
+
}
|
|
3508
|
+
}
|
|
3306
3509
|
append(paths, p.coordinates, p.sourceCoordinates);
|
|
3307
3510
|
pathParts.push({
|
|
3308
3511
|
...part(featureIndex, geometryPath, p.regionId),
|
|
@@ -3314,12 +3517,41 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
3314
3517
|
}
|
|
3315
3518
|
};
|
|
3316
3519
|
const addPolygon = (input, featureIndex, geometryPath) => {
|
|
3520
|
+
var _a;
|
|
3317
3521
|
if (!input.length)
|
|
3318
3522
|
return;
|
|
3319
3523
|
const rings = input.map((r) => r.map(position));
|
|
3320
|
-
const parts = options.sphericalCuts ? map.projectGlobalPolygon(rings, {
|
|
3524
|
+
const parts = options.sphericalCuts ? map.projectGlobalPolygon(rings, {
|
|
3525
|
+
...options.sampling,
|
|
3526
|
+
...options.sphericalCuts,
|
|
3527
|
+
polygonEdgeProvenance: provenance == null ? void 0 : provenance.polygonEdges
|
|
3528
|
+
}) : map.projectPolygon(rings, {
|
|
3529
|
+
...options.sampling,
|
|
3530
|
+
polygonEdgeProvenance: provenance == null ? void 0 : provenance.polygonEdges
|
|
3531
|
+
});
|
|
3321
3532
|
for (const p of parts) {
|
|
3322
3533
|
for (let i = 0; i < p.coordinates.length; i++) {
|
|
3534
|
+
if (provenance == null ? void 0 : provenance.polygonEdges) {
|
|
3535
|
+
const edges = (_a = p.edgeProvenance) == null ? void 0 : _a[i];
|
|
3536
|
+
if (!edges)
|
|
3537
|
+
throw new Error("Map backend does not support polygon edge provenance");
|
|
3538
|
+
const kinds = [
|
|
3539
|
+
"source-boundary",
|
|
3540
|
+
"coverage-boundary",
|
|
3541
|
+
"chart-cut",
|
|
3542
|
+
"continuous-chart-join"
|
|
3543
|
+
];
|
|
3544
|
+
for (const edge2 of edges) {
|
|
3545
|
+
edgeKinds.push(kinds.indexOf(edge2.kind) + 1);
|
|
3546
|
+
edgeRings.push(edge2.ring);
|
|
3547
|
+
edgeSegments.push(edge2.segment);
|
|
3548
|
+
edgeParameters.push(edge2.t0, edge2.t1);
|
|
3549
|
+
}
|
|
3550
|
+
edgeKinds.push(0);
|
|
3551
|
+
edgeRings.push(4294967295);
|
|
3552
|
+
edgeSegments.push(4294967295);
|
|
3553
|
+
edgeParameters.push(0, 0);
|
|
3554
|
+
}
|
|
3323
3555
|
append(polygons, p.coordinates[i], p.sourceCoordinates[i]);
|
|
3324
3556
|
ringStarts.push(polygons.positions.length / 2);
|
|
3325
3557
|
}
|
|
@@ -3383,12 +3615,38 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
3383
3615
|
featureIds,
|
|
3384
3616
|
regionIds,
|
|
3385
3617
|
points: { ...pack(points), parts: pointParts },
|
|
3386
|
-
paths: {
|
|
3618
|
+
paths: {
|
|
3619
|
+
...pack(paths),
|
|
3620
|
+
parts: pathParts,
|
|
3621
|
+
pathStarts: new Uint32Array(pathStarts),
|
|
3622
|
+
...lineage ? {
|
|
3623
|
+
provenance: {
|
|
3624
|
+
...(provenance == null ? void 0 : provenance.sourceSegments) ? {
|
|
3625
|
+
sourceSegmentIndices: new Uint32Array(segments),
|
|
3626
|
+
sourceSegmentParameters: new Float64Array(parameters),
|
|
3627
|
+
sourceVertexIndices: new Uint32Array(originalVertices)
|
|
3628
|
+
} : {},
|
|
3629
|
+
...(provenance == null ? void 0 : provenance.distances) ? {
|
|
3630
|
+
sourceDistances: new Float64Array(distances),
|
|
3631
|
+
distanceRadius: provenance.distances.radius
|
|
3632
|
+
} : {},
|
|
3633
|
+
...(provenance == null ? void 0 : provenance.boundaries) ? { startReasons, endReasons } : {}
|
|
3634
|
+
}
|
|
3635
|
+
} : {}
|
|
3636
|
+
},
|
|
3387
3637
|
polygons: {
|
|
3388
3638
|
...pack(polygons),
|
|
3389
3639
|
parts: polygonParts,
|
|
3390
3640
|
ringStarts: new Uint32Array(ringStarts),
|
|
3391
|
-
polygonStarts: new Uint32Array(polygonStarts)
|
|
3641
|
+
polygonStarts: new Uint32Array(polygonStarts),
|
|
3642
|
+
...(provenance == null ? void 0 : provenance.polygonEdges) ? {
|
|
3643
|
+
edgeProvenance: {
|
|
3644
|
+
kinds: new Uint8Array(edgeKinds),
|
|
3645
|
+
sourceRingIndices: new Uint32Array(edgeRings),
|
|
3646
|
+
sourceSegmentIndices: new Uint32Array(edgeSegments),
|
|
3647
|
+
sourceParameterRanges: new Float64Array(edgeParameters)
|
|
3648
|
+
}
|
|
3649
|
+
} : {}
|
|
3392
3650
|
}
|
|
3393
3651
|
};
|
|
3394
3652
|
}
|
|
@@ -3396,6 +3654,171 @@ function prepareMapFeatures(map, features, options = {}) {
|
|
|
3396
3654
|
// dist/discontinuous/elastic/map.js
|
|
3397
3655
|
var import_polygon_clipping4 = __toESM(require("polygon-clipping"), 1);
|
|
3398
3656
|
|
|
3657
|
+
// dist/discontinuous/polygon-constraints.js
|
|
3658
|
+
function tracePolygonConstraints(input, output, tolerance = 1e-10, priorities, accept, degenerate) {
|
|
3659
|
+
const constraints = input.flatMap((ring, r) => ring.slice(0, -1).map((a, i) => ({ a, b: ring[i + 1], r, i })));
|
|
3660
|
+
let work = 0;
|
|
3661
|
+
const tick = () => {
|
|
3662
|
+
if (++work > 2e7)
|
|
3663
|
+
throw new Error("Polygon constraint work limit exceeded");
|
|
3664
|
+
};
|
|
3665
|
+
const fraction = (p, a, b) => {
|
|
3666
|
+
const dx = b[0] - a[0], dy = b[1] - a[1], l = dx * dx + dy * dy;
|
|
3667
|
+
return l ? ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / l : NaN;
|
|
3668
|
+
};
|
|
3669
|
+
const on = (p, a, b) => {
|
|
3670
|
+
tick();
|
|
3671
|
+
const t = fraction(p, a, b), length = Math.hypot(b[0] - a[0], b[1] - a[1]);
|
|
3672
|
+
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);
|
|
3673
|
+
};
|
|
3674
|
+
const boxes = constraints.map((c) => [
|
|
3675
|
+
Math.min(c.a[0], c.b[0]),
|
|
3676
|
+
Math.min(c.a[1], c.b[1]),
|
|
3677
|
+
Math.max(c.a[0], c.b[0]),
|
|
3678
|
+
Math.max(c.a[1], c.b[1])
|
|
3679
|
+
]);
|
|
3680
|
+
const build = (ids) => {
|
|
3681
|
+
const box = [Infinity, Infinity, -Infinity, -Infinity];
|
|
3682
|
+
for (const id of ids) {
|
|
3683
|
+
tick();
|
|
3684
|
+
const b = boxes[id];
|
|
3685
|
+
box[0] = Math.min(box[0], b[0]);
|
|
3686
|
+
box[1] = Math.min(box[1], b[1]);
|
|
3687
|
+
box[2] = Math.max(box[2], b[2]);
|
|
3688
|
+
box[3] = Math.max(box[3], b[3]);
|
|
3689
|
+
}
|
|
3690
|
+
if (ids.length <= 16)
|
|
3691
|
+
return { box, ids };
|
|
3692
|
+
const axis = box[2] - box[0] >= box[3] - box[1] ? 0 : 1;
|
|
3693
|
+
ids.sort((a, b) => {
|
|
3694
|
+
tick();
|
|
3695
|
+
return boxes[a][axis] + boxes[a][axis + 2] - boxes[b][axis] - boxes[b][axis + 2];
|
|
3696
|
+
});
|
|
3697
|
+
const middle = Math.floor(ids.length / 2);
|
|
3698
|
+
return { box, left: build(ids.slice(0, middle)), right: build(ids.slice(middle)) };
|
|
3699
|
+
};
|
|
3700
|
+
const root = build(constraints.map((_, i) => i));
|
|
3701
|
+
const padding = tolerance * Math.max(1, root.box[2] - root.box[0], root.box[3] - root.box[1]);
|
|
3702
|
+
const query = (a, b) => {
|
|
3703
|
+
const box = [
|
|
3704
|
+
Math.min(a[0], b[0]) - padding,
|
|
3705
|
+
Math.min(a[1], b[1]) - padding,
|
|
3706
|
+
Math.max(a[0], b[0]) + padding,
|
|
3707
|
+
Math.max(a[1], b[1]) + padding
|
|
3708
|
+
], ids = [];
|
|
3709
|
+
const overlaps = (b2) => b2[0] <= box[2] && b2[2] >= box[0] && b2[1] <= box[3] && b2[3] >= box[1];
|
|
3710
|
+
const visit = (node) => {
|
|
3711
|
+
tick();
|
|
3712
|
+
if (!overlaps(node.box))
|
|
3713
|
+
return;
|
|
3714
|
+
if (node.ids) {
|
|
3715
|
+
for (const id of node.ids) {
|
|
3716
|
+
tick();
|
|
3717
|
+
if (overlaps(boxes[id]))
|
|
3718
|
+
ids.push(id);
|
|
3719
|
+
}
|
|
3720
|
+
} else {
|
|
3721
|
+
visit(node.left);
|
|
3722
|
+
visit(node.right);
|
|
3723
|
+
}
|
|
3724
|
+
};
|
|
3725
|
+
visit(root);
|
|
3726
|
+
return ids.map((id) => constraints[id]);
|
|
3727
|
+
};
|
|
3728
|
+
const rings = [], owners = [];
|
|
3729
|
+
for (const ring of output) {
|
|
3730
|
+
const points = [];
|
|
3731
|
+
for (let i = 1; i < ring.length; i++) {
|
|
3732
|
+
const a = ring[i - 1], b = ring[i];
|
|
3733
|
+
if (a.every((v, k2) => v === b[k2]))
|
|
3734
|
+
continue;
|
|
3735
|
+
const breaks = [{ t: 0, p: a }];
|
|
3736
|
+
for (const c of query(a, b))
|
|
3737
|
+
if (on(c.a, a, b) && (!accept || accept(c.a))) {
|
|
3738
|
+
const t = fraction(c.a, a, b);
|
|
3739
|
+
if (t > 1e-12 && t < 1 - 1e-12)
|
|
3740
|
+
breaks.push({ t, p: c.a });
|
|
3741
|
+
}
|
|
3742
|
+
breaks.sort((a2, b2) => a2.t - b2.t);
|
|
3743
|
+
for (const item of breaks)
|
|
3744
|
+
if (!points.length || Math.hypot(...points[points.length - 1].map((v, k2) => v - item.p[k2])) > 1e-14)
|
|
3745
|
+
points.push([...item.p]);
|
|
3746
|
+
}
|
|
3747
|
+
if (points.length < 3)
|
|
3748
|
+
continue;
|
|
3749
|
+
points.push([...points[0]]);
|
|
3750
|
+
const tags = [];
|
|
3751
|
+
for (let i = 1; i < points.length; i++) {
|
|
3752
|
+
const a = points[i - 1], b = points[i];
|
|
3753
|
+
if (degenerate == null ? void 0 : degenerate(a, b)) {
|
|
3754
|
+
tags.push(null);
|
|
3755
|
+
continue;
|
|
3756
|
+
}
|
|
3757
|
+
let candidates = query(a, b).filter((c) => on(a, c.a, c.b) && on(b, c.a, c.b));
|
|
3758
|
+
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));
|
|
3759
|
+
const exact = candidates.filter((c) => same(a, c.a) && same(b, c.b) || same(a, c.b) && same(b, c.a));
|
|
3760
|
+
if (exact.length)
|
|
3761
|
+
candidates = exact;
|
|
3762
|
+
if (candidates.some((c) => {
|
|
3763
|
+
var _a, _b;
|
|
3764
|
+
return ((_b = (_a = priorities == null ? void 0 : priorities[c.r]) == null ? void 0 : _a[c.i]) == null ? void 0 : _b.kind) === "source-boundary";
|
|
3765
|
+
}))
|
|
3766
|
+
candidates = candidates.filter((c) => {
|
|
3767
|
+
var _a, _b;
|
|
3768
|
+
return ((_b = (_a = priorities == null ? void 0 : priorities[c.r]) == null ? void 0 : _a[c.i]) == null ? void 0 : _b.kind) === "source-boundary";
|
|
3769
|
+
});
|
|
3770
|
+
if (candidates.length > 1) {
|
|
3771
|
+
const score = (c) => Math.max(...[a, b].map((p) => {
|
|
3772
|
+
const t = Math.min(1, Math.max(0, fraction(p, c.a, c.b)));
|
|
3773
|
+
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]));
|
|
3774
|
+
}));
|
|
3775
|
+
candidates.sort((a2, b2) => score(a2) - score(b2));
|
|
3776
|
+
const epsilon6 = 64 * Number.EPSILON * Math.max(1, ...a.map(Math.abs), ...b.map(Math.abs));
|
|
3777
|
+
if (score(candidates[1]) - score(candidates[0]) > epsilon6)
|
|
3778
|
+
candidates = [candidates[0]];
|
|
3779
|
+
else if (Math.hypot(a[0] - b[0], a[1] - b[1]) <= 2 * epsilon6)
|
|
3780
|
+
candidates = [];
|
|
3781
|
+
else
|
|
3782
|
+
throw new Error("Ambiguous polygon clipping constraint ancestry");
|
|
3783
|
+
}
|
|
3784
|
+
tags.push(candidates.length ? [candidates[0].r, candidates[0].i] : null);
|
|
3785
|
+
}
|
|
3786
|
+
rings.push(points);
|
|
3787
|
+
owners.push(tags);
|
|
3788
|
+
}
|
|
3789
|
+
return { rings, owners };
|
|
3790
|
+
}
|
|
3791
|
+
function composePolygonEdge(parent, a, b, start, end) {
|
|
3792
|
+
if (parent.kind !== "source-boundary")
|
|
3793
|
+
return { ...parent };
|
|
3794
|
+
const v = geographic(a), length = angle(v, geographic(b));
|
|
3795
|
+
const parameter = (p) => length ? Math.min(1, angle(v, geographic(p)) / length) : 0;
|
|
3796
|
+
return {
|
|
3797
|
+
...parent,
|
|
3798
|
+
t0: parent.t0 + parameter(start) * (parent.t1 - parent.t0),
|
|
3799
|
+
t1: parent.t0 + parameter(end) * (parent.t1 - parent.t0)
|
|
3800
|
+
};
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3803
|
+
// dist/discontinuous/source-arc.js
|
|
3804
|
+
function sourceArc(a, b) {
|
|
3805
|
+
const va = geographic(a), vb = geographic(b), length = angle(va, vb);
|
|
3806
|
+
const poleA = Math.abs(a[1]) === 90, poleB = Math.abs(b[1]) === 90;
|
|
3807
|
+
const start = poleA && !poleB ? [b[0], a[1]] : [...a], end = poleB && !poleA ? [a[0], b[1]] : [...b];
|
|
3808
|
+
return (t) => {
|
|
3809
|
+
if (t === 0)
|
|
3810
|
+
return [...start];
|
|
3811
|
+
if (t === 1)
|
|
3812
|
+
return [...end];
|
|
3813
|
+
if (length < 1e-14)
|
|
3814
|
+
return [a[0] + t * (b[0] - a[0]), a[1] + t * (b[1] - a[1])];
|
|
3815
|
+
const p = coordinates(unit(va.map((v, k2) => (Math.sin((1 - t) * length) * v + Math.sin(t * length) * vb[k2]) / Math.sin(length))));
|
|
3816
|
+
const reference = start[0] + t * (end[0] - start[0]);
|
|
3817
|
+
p[0] += 360 * Math.round((reference - p[0]) / 360);
|
|
3818
|
+
return p;
|
|
3819
|
+
};
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3399
3822
|
// dist/discontinuous/cap-map.js
|
|
3400
3823
|
var CapMap = class extends DiscontinuousMap {
|
|
3401
3824
|
constructor(regions2, local, source, cap2, radius, polarLimits = false, nonlinear = false) {
|
|
@@ -3450,10 +3873,11 @@ var CapMap = class extends DiscontinuousMap {
|
|
|
3450
3873
|
unprojectPoint(p, id) {
|
|
3451
3874
|
return super.unprojectPoint(p, id).filter((q) => this.visible(q.position));
|
|
3452
3875
|
}
|
|
3453
|
-
clip(rings, polygon, options, regionId) {
|
|
3876
|
+
clip(rings, polygon, options, regionId, segmentIndices) {
|
|
3454
3877
|
const output = [];
|
|
3455
3878
|
const originals = /* @__PURE__ */ new Map();
|
|
3456
|
-
let ring = [];
|
|
3879
|
+
let ring = [], indices = [], activeSegment = 0;
|
|
3880
|
+
let previousInput, currentInput;
|
|
3457
3881
|
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;
|
|
3458
3882
|
if (!Number.isFinite(precision) || 2 * Math.PI / precision > 1e6)
|
|
3459
3883
|
throw new Error("Projection sampling limit exceeded; relax tolerance");
|
|
@@ -3508,14 +3932,49 @@ var CapMap = class extends DiscontinuousMap {
|
|
|
3508
3932
|
point: (x, y) => {
|
|
3509
3933
|
if (++emitted > 1e6)
|
|
3510
3934
|
throw new Error("Projection sampling limit exceeded; relax tolerance");
|
|
3511
|
-
|
|
3935
|
+
let source = originals.get(`${x},${y}`);
|
|
3936
|
+
if (!source && !polygon && this.nonlinear && previousInput && currentInput) {
|
|
3937
|
+
const a = geographic(previousInput), b = geographic(currentInput), length = angle(a, b);
|
|
3938
|
+
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))));
|
|
3939
|
+
const value = (t) => geographic(local(at(t)))[0] - Math.cos(this.cap);
|
|
3940
|
+
const approximate = this.source([x / RAD, y / RAD]);
|
|
3941
|
+
const reference = length ? Math.min(1, angle(a, geographic(approximate)) / length) : 0;
|
|
3942
|
+
const roots = [];
|
|
3943
|
+
for (let j = 0; j < 32; j++) {
|
|
3944
|
+
let lo = j / 32, hi = (j + 1) / 32, f = value(lo), g = value(hi);
|
|
3945
|
+
if (Math.abs(f) < 1e-14)
|
|
3946
|
+
roots.push(lo);
|
|
3947
|
+
if (f * g >= 0)
|
|
3948
|
+
continue;
|
|
3949
|
+
for (let k2 = 0; k2 < 52; k2++) {
|
|
3950
|
+
const mid = (lo + hi) / 2;
|
|
3951
|
+
if (value(mid) >= 0 === f >= 0)
|
|
3952
|
+
lo = mid;
|
|
3953
|
+
else
|
|
3954
|
+
hi = mid;
|
|
3955
|
+
}
|
|
3956
|
+
roots.push((lo + hi) / 2);
|
|
3957
|
+
}
|
|
3958
|
+
if (Math.abs(value(1)) < 1e-14)
|
|
3959
|
+
roots.push(1);
|
|
3960
|
+
if (!roots.length)
|
|
3961
|
+
throw new Error("Unresolved nonlinear cap source intersection");
|
|
3962
|
+
roots.sort((a2, b2) => Math.abs(a2 - reference) - Math.abs(b2 - reference));
|
|
3963
|
+
source = at(roots[0]);
|
|
3964
|
+
}
|
|
3965
|
+
ring.push(source ?? this.source([x / RAD, y / RAD]));
|
|
3966
|
+
if (segmentIndices)
|
|
3967
|
+
indices.push(activeSegment);
|
|
3512
3968
|
},
|
|
3513
3969
|
lineStart: () => {
|
|
3514
3970
|
ring = [];
|
|
3971
|
+
indices = [];
|
|
3515
3972
|
},
|
|
3516
3973
|
lineEnd: () => {
|
|
3517
|
-
if (ring.length > 1)
|
|
3974
|
+
if (ring.length > 1) {
|
|
3518
3975
|
output.push(ring);
|
|
3976
|
+
segmentIndices == null ? void 0 : segmentIndices.push(indices);
|
|
3977
|
+
}
|
|
3519
3978
|
},
|
|
3520
3979
|
polygonStart: () => {
|
|
3521
3980
|
},
|
|
@@ -3532,7 +3991,9 @@ var CapMap = class extends DiscontinuousMap {
|
|
|
3532
3991
|
}
|
|
3533
3992
|
const x = q[0] * RAD, y = q[1] * RAD;
|
|
3534
3993
|
originals.set(`${x},${y}`, [...p]);
|
|
3994
|
+
currentInput = p;
|
|
3535
3995
|
stream.point(x, y);
|
|
3996
|
+
previousInput = p;
|
|
3536
3997
|
};
|
|
3537
3998
|
const subdivide = (a, b, depth = 0) => {
|
|
3538
3999
|
if (this.nonlinear && depth < 20) {
|
|
@@ -3549,11 +4010,14 @@ var CapMap = class extends DiscontinuousMap {
|
|
|
3549
4010
|
emit(b);
|
|
3550
4011
|
};
|
|
3551
4012
|
for (const points of rings) {
|
|
4013
|
+
previousInput = void 0;
|
|
3552
4014
|
stream.lineStart();
|
|
3553
4015
|
if (points.length)
|
|
3554
4016
|
emit(points[0]);
|
|
3555
|
-
for (let i = 1; i < points.length; i++)
|
|
4017
|
+
for (let i = 1; i < points.length; i++) {
|
|
4018
|
+
activeSegment = i - 1;
|
|
3556
4019
|
subdivide(points[i - 1], points[i]);
|
|
4020
|
+
}
|
|
3557
4021
|
if (polygon && points.length)
|
|
3558
4022
|
subdivide(points[points.length - 1], points[0]);
|
|
3559
4023
|
stream.lineEnd();
|
|
@@ -3565,7 +4029,41 @@ var CapMap = class extends DiscontinuousMap {
|
|
|
3565
4029
|
projectLine(line, options) {
|
|
3566
4030
|
if (this.cap === Math.PI / 2 && !this.nonlinear)
|
|
3567
4031
|
return super.projectLine(line, options);
|
|
3568
|
-
return super.projectLine(line, options).flatMap((part) =>
|
|
4032
|
+
return super.projectLine(line, options).flatMap((part) => {
|
|
4033
|
+
const indices = part.provenance ? [] : void 0;
|
|
4034
|
+
const clipped = this.clip([part.sourceCoordinates], false, options, part.regionId, indices);
|
|
4035
|
+
return clipped.flatMap((points, piece) => super.projectLine(points, options).filter((q) => q.regionId === part.regionId).map((q) => {
|
|
4036
|
+
const parent = part.provenance, child = q.provenance;
|
|
4037
|
+
if (!parent || !child)
|
|
4038
|
+
return q;
|
|
4039
|
+
const provenance = {
|
|
4040
|
+
segments: [],
|
|
4041
|
+
parameters: [],
|
|
4042
|
+
vertices: [],
|
|
4043
|
+
angularDistances: []
|
|
4044
|
+
};
|
|
4045
|
+
for (let j = 0; j < q.sourceCoordinates.length; j++) {
|
|
4046
|
+
const k2 = child.segments[j];
|
|
4047
|
+
const edge2 = indices[piece][k2 + 1];
|
|
4048
|
+
const a = geographic(part.sourceCoordinates[edge2]), b = geographic(part.sourceCoordinates[edge2 + 1]), p = geographic(q.sourceCoordinates[j]);
|
|
4049
|
+
const length = angle(a, b), t = length ? Math.min(1, angle(a, p) / length) : 0;
|
|
4050
|
+
const endpoint = t < 1e-12 ? edge2 : t > 1 - 1e-12 ? edge2 + 1 : -1;
|
|
4051
|
+
const segment = parent.segments[edge2 + 1];
|
|
4052
|
+
const from = parent.segments[edge2] === segment ? parent.parameters[edge2] : 0;
|
|
4053
|
+
provenance.segments.push(endpoint >= 0 ? parent.segments[endpoint] : segment);
|
|
4054
|
+
provenance.parameters.push(endpoint >= 0 ? parent.parameters[endpoint] : from + t * (parent.parameters[edge2 + 1] - from));
|
|
4055
|
+
provenance.vertices.push(endpoint >= 0 ? parent.vertices[endpoint] : 4294967295);
|
|
4056
|
+
if (options == null ? void 0 : options.pathDistances)
|
|
4057
|
+
provenance.angularDistances.push(parent.angularDistances[edge2] + t * (parent.angularDistances[edge2 + 1] - parent.angularDistances[edge2]));
|
|
4058
|
+
}
|
|
4059
|
+
if (options == null ? void 0 : options.pathBoundaries) {
|
|
4060
|
+
const same = (a, b) => angle(geographic(a), geographic(b)) < 1e-12;
|
|
4061
|
+
provenance.startReason = same(q.sourceCoordinates[0], part.sourceCoordinates[0]) ? parent.startReason : "coverage-boundary";
|
|
4062
|
+
provenance.endReason = same(q.sourceCoordinates[q.sourceCoordinates.length - 1], part.sourceCoordinates[part.sourceCoordinates.length - 1]) ? parent.endReason : "coverage-boundary";
|
|
4063
|
+
}
|
|
4064
|
+
return { ...q, provenance };
|
|
4065
|
+
}));
|
|
4066
|
+
});
|
|
3569
4067
|
}
|
|
3570
4068
|
projectPolygon(rings, options) {
|
|
3571
4069
|
if (this.cap === Math.PI / 2 && !this.nonlinear)
|
|
@@ -3638,15 +4136,95 @@ var CapMap = class extends DiscontinuousMap {
|
|
|
3638
4136
|
};
|
|
3639
4137
|
for (const ring of outer) {
|
|
3640
4138
|
const plane = ring.map(planar), sources = [ring, ...holes.filter((h2) => contains2(plane, planar(h2[0])))];
|
|
4139
|
+
const parentPlane = part.sourceCoordinates.map((r) => r.map(planar));
|
|
4140
|
+
const fromPlane = (p) => coordinates(unit(center3.map((v, k2) => v + x[k2] * p[0] + y[k2] * p[1])));
|
|
4141
|
+
const traced = tracePolygonConstraints(parentPlane, sources.map((r) => r.map(planar)), this.nonlinear ? 2e-6 : 1e-10, part.edgeProvenance, (p) => this.visible(fromPlane(p)));
|
|
4142
|
+
const resolved = traced.rings.map((r) => r.map(fromPlane));
|
|
4143
|
+
traced.owners.forEach((owners, r) => owners.forEach((owner, i) => {
|
|
4144
|
+
if (!owner)
|
|
4145
|
+
return;
|
|
4146
|
+
const [pr, pe] = owner, a = part.sourceCoordinates[pr][pe], b = part.sourceCoordinates[pr][pe + 1], at = sourceArc(a, b);
|
|
4147
|
+
for (const j of [i, i + 1]) {
|
|
4148
|
+
const point = resolved[r][j], distance3 = angle(geographic(a), geographic(b)), fraction = distance3 ? angle(geographic(a), geographic(point)) / distance3 : 0;
|
|
4149
|
+
if (fraction < 1e-10)
|
|
4150
|
+
resolved[r][j] = [...a];
|
|
4151
|
+
else if (fraction > 1 - 1e-10)
|
|
4152
|
+
resolved[r][j] = [...b];
|
|
4153
|
+
else if (Math.hypot(...cross(geographic(a), geographic(b))) > 1e-14 && Math.abs(dot(unit(cross(geographic(a), geographic(b))), geographic(point))) < 1e-12) {
|
|
4154
|
+
resolved[r][j] = at(Math.min(1, Math.max(0, fraction)));
|
|
4155
|
+
} else {
|
|
4156
|
+
const value = (t) => geographic(this.local(at(t)))[0] - Math.cos(this.cap), roots = [];
|
|
4157
|
+
for (let k2 = 0; k2 < 32; k2++) {
|
|
4158
|
+
let lo = k2 / 32, hi = (k2 + 1) / 32, f = value(lo), g = value(hi);
|
|
4159
|
+
if (Math.abs(f) < 1e-13)
|
|
4160
|
+
roots.push(lo);
|
|
4161
|
+
if (f * g >= 0)
|
|
4162
|
+
continue;
|
|
4163
|
+
for (let n = 0; n < 52; n++) {
|
|
4164
|
+
const mid = (lo + hi) / 2;
|
|
4165
|
+
if (value(mid) >= 0 === f >= 0)
|
|
4166
|
+
lo = mid;
|
|
4167
|
+
else
|
|
4168
|
+
hi = mid;
|
|
4169
|
+
}
|
|
4170
|
+
roots.push((lo + hi) / 2);
|
|
4171
|
+
}
|
|
4172
|
+
if (Math.abs(value(1)) < 1e-13)
|
|
4173
|
+
roots.push(1);
|
|
4174
|
+
if (!roots.length)
|
|
4175
|
+
throw new Error("Unresolved cap polygon source intersection");
|
|
4176
|
+
roots.sort((a2, b2) => Math.abs(a2 - fraction) - Math.abs(b2 - fraction));
|
|
4177
|
+
resolved[r][j] = at(roots[0]);
|
|
4178
|
+
}
|
|
4179
|
+
}
|
|
4180
|
+
}));
|
|
4181
|
+
for (const ring2 of resolved)
|
|
4182
|
+
ring2[ring2.length - 1] = [...ring2[0]];
|
|
3641
4183
|
result.push({
|
|
3642
4184
|
regionId: part.regionId,
|
|
3643
|
-
sourceCoordinates:
|
|
3644
|
-
coordinates:
|
|
4185
|
+
sourceCoordinates: resolved,
|
|
4186
|
+
coordinates: resolved.map((r) => r.map((p) => {
|
|
3645
4187
|
const q = super.projectPoint(p, part.regionId);
|
|
3646
4188
|
if (!q)
|
|
3647
|
-
throw new Error(
|
|
4189
|
+
throw new Error("Cap polygon source constraint left its owning chart");
|
|
3648
4190
|
return q.position;
|
|
3649
|
-
}))
|
|
4191
|
+
})),
|
|
4192
|
+
...(options == null ? void 0 : options.polygonEdgeProvenance) ? {
|
|
4193
|
+
edgeProvenance: traced.owners.map((owners, r) => owners.map((owner, i) => {
|
|
4194
|
+
const a = resolved[r][i], b = resolved[r][i + 1];
|
|
4195
|
+
if (owner) {
|
|
4196
|
+
const [pr, pe] = owner;
|
|
4197
|
+
return composePolygonEdge(part.edgeProvenance[pr][pe], part.sourceCoordinates[pr][pe], part.sourceCoordinates[pr][pe + 1], a, b);
|
|
4198
|
+
}
|
|
4199
|
+
if (angle(geographic(a), geographic(b)) < 64 * Number.EPSILON)
|
|
4200
|
+
return {
|
|
4201
|
+
kind: "continuous-chart-join",
|
|
4202
|
+
ring: 4294967295,
|
|
4203
|
+
segment: 4294967295,
|
|
4204
|
+
t0: 0,
|
|
4205
|
+
t1: 0
|
|
4206
|
+
};
|
|
4207
|
+
const kinds = [];
|
|
4208
|
+
region.boundary.forEach((p, j) => {
|
|
4209
|
+
const n = cross(geographic(p), geographic(region.boundary[(j + 1) % region.boundary.length])), length = Math.hypot(...n);
|
|
4210
|
+
if (length && [a, b].every((p2) => Math.abs(dot(n, geographic(p2))) / length < 1e-9)) {
|
|
4211
|
+
const seam = this.seams.find((s) => s.regions.some((id, k2) => id === region.id && s.edges[k2] === j));
|
|
4212
|
+
if (seam)
|
|
4213
|
+
kinds.push(seam.kind);
|
|
4214
|
+
}
|
|
4215
|
+
});
|
|
4216
|
+
const horizon = [a, b].every((p) => Math.abs(geographic(this.local(p))[0] - Math.cos(this.cap)) < 1e-7);
|
|
4217
|
+
if (!horizon && !kinds.length)
|
|
4218
|
+
throw new Error("Unknown cap polygon clipping constraint");
|
|
4219
|
+
return {
|
|
4220
|
+
kind: horizon ? "coverage-boundary" : kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join",
|
|
4221
|
+
ring: 4294967295,
|
|
4222
|
+
segment: 4294967295,
|
|
4223
|
+
t0: 0,
|
|
4224
|
+
t1: 0
|
|
4225
|
+
};
|
|
4226
|
+
}))
|
|
4227
|
+
} : {}
|
|
3650
4228
|
});
|
|
3651
4229
|
}
|
|
3652
4230
|
}
|
|
@@ -5384,6 +5962,94 @@ function invertCell(p, target) {
|
|
|
5384
5962
|
return output;
|
|
5385
5963
|
}
|
|
5386
5964
|
|
|
5965
|
+
// dist/discontinuous/elastic/source-arc.js
|
|
5966
|
+
function clipSourceArc(a, b, polygons) {
|
|
5967
|
+
const at = sourceArc(a, b), va = geographic(a), vb = geographic(b), omega = angle(va, vb), ts = [0, 1];
|
|
5968
|
+
let work = 0;
|
|
5969
|
+
const tick = () => {
|
|
5970
|
+
if (++work > 1e6)
|
|
5971
|
+
throw new Error("Elastic source clipping limit exceeded");
|
|
5972
|
+
};
|
|
5973
|
+
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;
|
|
5974
|
+
const tangent = omega > 1e-14 ? va.map((v, k2) => (vb[k2] - v * Math.cos(omega)) / Math.sin(omega)) : [0, 0, 0];
|
|
5975
|
+
const momentum = Math.abs(omega * (va[0] * tangent[1] - va[1] * tangent[0])) + 64 * Number.EPSILON * omega;
|
|
5976
|
+
const vector = (t) => va.map((v, k2) => v * Math.cos(omega * t) + tangent[k2] * Math.sin(omega * t));
|
|
5977
|
+
const derivative = (t) => va.map((v, k2) => omega * (-v * Math.sin(omega * t) + tangent[k2] * Math.cos(omega * t)));
|
|
5978
|
+
for (const rings of polygons)
|
|
5979
|
+
for (const ring of rings)
|
|
5980
|
+
for (let edge2 = 1; edge2 < ring.length; edge2++) {
|
|
5981
|
+
const c = ring[edge2 - 1], d = ring[edge2], dx = d[0] - c[0], dy = d[1] - c[1], length = Math.hypot(dx, dy);
|
|
5982
|
+
if (!length)
|
|
5983
|
+
continue;
|
|
5984
|
+
const angular = omega / RAD, latitude = Math.min(90, Math.max(Math.abs(a[1]), Math.abs(b[1])) + angular), cosine = Math.cos(latitude * RAD), longitude3 = cosine > 1e-10 ? angular / cosine : 360;
|
|
5985
|
+
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)
|
|
5986
|
+
continue;
|
|
5987
|
+
const value = (t) => {
|
|
5988
|
+
tick();
|
|
5989
|
+
const p = at(t);
|
|
5990
|
+
return ((p[0] - c[0]) * dy - (p[1] - c[1]) * dx) / length;
|
|
5991
|
+
};
|
|
5992
|
+
const put = (t) => {
|
|
5993
|
+
const p = at(t), u = ((p[0] - c[0]) * dx + (p[1] - c[1]) * dy) / (length * length);
|
|
5994
|
+
if (u >= -1e-10 && u <= 1 + 1e-10)
|
|
5995
|
+
ts.push(t);
|
|
5996
|
+
};
|
|
5997
|
+
const bisect = (lo, hi, f) => {
|
|
5998
|
+
for (let k2 = 0; k2 < 52; k2++) {
|
|
5999
|
+
const mid = (lo + hi) / 2;
|
|
6000
|
+
if (value(mid) >= 0 === f >= 0)
|
|
6001
|
+
lo = mid;
|
|
6002
|
+
else
|
|
6003
|
+
hi = mid;
|
|
6004
|
+
}
|
|
6005
|
+
put((lo + hi) / 2);
|
|
6006
|
+
};
|
|
6007
|
+
const visit = (lo, hi, depth) => {
|
|
6008
|
+
tick();
|
|
6009
|
+
const f = value(lo), g = value(hi), mid = (lo + hi) / 2, h2 = (hi - lo) / 2;
|
|
6010
|
+
if (Math.abs(f) < 1e-12)
|
|
6011
|
+
put(lo);
|
|
6012
|
+
if (Math.abs(g) < 1e-12)
|
|
6013
|
+
put(hi);
|
|
6014
|
+
if (linear) {
|
|
6015
|
+
if (f * g < 0)
|
|
6016
|
+
bisect(lo, hi, f);
|
|
6017
|
+
return;
|
|
6018
|
+
}
|
|
6019
|
+
const v = vector(mid), dv = derivative(mid), r2 = v[0] * v[0] + v[1] * v[1];
|
|
6020
|
+
const df = ((v[0] * dv[1] - v[1] * dv[0]) / r2 * dy - dv[2] / Math.sqrt(r2) * dx) / (RAD * length);
|
|
6021
|
+
let z = Math.max(Math.abs(vector(lo)[2]), Math.abs(vector(hi)[2]));
|
|
6022
|
+
const phase = Math.atan2(tangent[2], va[2]);
|
|
6023
|
+
for (let k2 = -2; k2 <= 2; k2++) {
|
|
6024
|
+
const theta = phase + k2 * Math.PI;
|
|
6025
|
+
if (theta >= omega * lo && theta <= omega * hi)
|
|
6026
|
+
z = Math.max(z, Math.hypot(va[2], tangent[2]));
|
|
6027
|
+
}
|
|
6028
|
+
const r = Math.sqrt(Math.max(0, 1 - Math.min(1, z) ** 2));
|
|
6029
|
+
const second = r ? (2 * momentum * omega * Math.abs(dy) / r ** 4 + omega ** 2 * Math.abs(dx) * (1 / r + 1 / r ** 3)) / (RAD * length) : Infinity;
|
|
6030
|
+
if (Number.isFinite(df) && Math.abs(df) > second * h2 + 1e-12) {
|
|
6031
|
+
if (f * g < 0)
|
|
6032
|
+
bisect(lo, hi, f);
|
|
6033
|
+
return;
|
|
6034
|
+
}
|
|
6035
|
+
const speed = r ? (momentum * Math.abs(dy) / r ** 2 + omega * Math.abs(dx)) / (RAD * length) : Infinity;
|
|
6036
|
+
if (Math.abs(value(mid)) > speed * h2 + 1e-12)
|
|
6037
|
+
return;
|
|
6038
|
+
if (depth >= 24)
|
|
6039
|
+
throw new Error("Unresolved Elastic source clipping tangent or pole");
|
|
6040
|
+
visit(lo, mid, depth + 1);
|
|
6041
|
+
visit(mid, hi, depth + 1);
|
|
6042
|
+
};
|
|
6043
|
+
visit(0, 1, 0);
|
|
6044
|
+
}
|
|
6045
|
+
ts.sort((a2, b2) => a2 - b2);
|
|
6046
|
+
const result = [];
|
|
6047
|
+
for (let i = 1; i < ts.length; i++)
|
|
6048
|
+
if (ts[i] - ts[i - 1] > 1e-12 && contains(polygons, at((ts[i] + ts[i - 1]) / 2)))
|
|
6049
|
+
result.push({ a: at(ts[i - 1]), b: at(ts[i]) });
|
|
6050
|
+
return result;
|
|
6051
|
+
}
|
|
6052
|
+
|
|
5387
6053
|
// dist/discontinuous/elastic/map.js
|
|
5388
6054
|
var kernel = Object.assign((x, y) => [x, y], {
|
|
5389
6055
|
invert: (x, y) => [x, y]
|
|
@@ -5515,7 +6181,7 @@ var ElasticMap = class {
|
|
|
5515
6181
|
}
|
|
5516
6182
|
sourceOptions(options) {
|
|
5517
6183
|
const { step } = sampling2(options);
|
|
5518
|
-
return { maxAngularStep: Math.min(step, 1), tolerance: 1e-5 };
|
|
6184
|
+
return { ...options, maxAngularStep: Math.min(step, 1), tolerance: 1e-5 };
|
|
5519
6185
|
}
|
|
5520
6186
|
sampled(c, line, options) {
|
|
5521
6187
|
return sample(line, (p) => c.grid.project(p), options, Math.min(180 / (c.grid.section.rows - 1), 360 / (c.grid.section.columns - 1)));
|
|
@@ -5524,23 +6190,70 @@ var ElasticMap = class {
|
|
|
5524
6190
|
const out = [];
|
|
5525
6191
|
for (const part of splitter.projectLine(line, this.sourceOptions(options)))
|
|
5526
6192
|
for (const c of this.charts.filter((c2) => c2.baseId === part.regionId)) {
|
|
5527
|
-
let current
|
|
5528
|
-
const
|
|
5529
|
-
if (
|
|
5530
|
-
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
6193
|
+
let current;
|
|
6194
|
+
const boundary = (point, vertex) => {
|
|
6195
|
+
if (vertex === 0 || vertex === line.length - 1)
|
|
6196
|
+
return "source-endpoint";
|
|
6197
|
+
let edge2 = 0;
|
|
6198
|
+
const kinds = [];
|
|
6199
|
+
for (const polygon of c.domain)
|
|
6200
|
+
for (const ring of polygon)
|
|
6201
|
+
for (let i = 1; i < ring.length; i++, edge2++)
|
|
6202
|
+
if (onSegment(point, ring[i - 1], ring[i])) {
|
|
6203
|
+
const seam = this.seams.find((s) => s.regions.some((id, j) => id === c.region.id && s.edges[j] === edge2));
|
|
6204
|
+
kinds.push((seam == null ? void 0 : seam.kind) ?? "boundary");
|
|
6205
|
+
}
|
|
6206
|
+
return kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : kinds.includes("join") ? "continuous-chart-join" : "coverage-boundary";
|
|
5534
6207
|
};
|
|
5535
|
-
for (let i = 1; i < part.
|
|
5536
|
-
|
|
5537
|
-
|
|
5538
|
-
|
|
5539
|
-
|
|
5540
|
-
|
|
5541
|
-
current.push(b);
|
|
6208
|
+
for (let i = 1; i < part.sourceCoordinates.length; i++) {
|
|
6209
|
+
const a = part.coordinates[i - 1], b = part.coordinates[i];
|
|
6210
|
+
const intervals = clipSourceArc(a, b, c.domain);
|
|
6211
|
+
if (!intervals.length) {
|
|
6212
|
+
current = void 0;
|
|
6213
|
+
continue;
|
|
5542
6214
|
}
|
|
5543
|
-
|
|
6215
|
+
if (Math.hypot(intervals[0].a[0] - a[0], intervals[0].a[1] - a[1]) > 1e-8)
|
|
6216
|
+
current = void 0;
|
|
6217
|
+
for (const clipped of intervals) {
|
|
6218
|
+
const arc = sourceArc(clipped.a, clipped.b);
|
|
6219
|
+
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));
|
|
6220
|
+
const first = samples.source[0], last = samples.source[samples.source.length - 1];
|
|
6221
|
+
const joined = current && Math.hypot(...current.sourceCoordinates[current.sourceCoordinates.length - 1].map((v, k2) => v - first[k2])) < 1e-8;
|
|
6222
|
+
if (!joined) {
|
|
6223
|
+
current = { regionId: c.region.id, coordinates: [], sourceCoordinates: [] };
|
|
6224
|
+
if (part.provenance)
|
|
6225
|
+
current.provenance = {
|
|
6226
|
+
segments: [],
|
|
6227
|
+
parameters: [],
|
|
6228
|
+
vertices: [],
|
|
6229
|
+
angularDistances: []
|
|
6230
|
+
};
|
|
6231
|
+
out.push(current);
|
|
6232
|
+
}
|
|
6233
|
+
for (let j = joined ? 1 : 0; j < samples.source.length; j++) {
|
|
6234
|
+
const p = samples.source[j];
|
|
6235
|
+
current.sourceCoordinates.push(p);
|
|
6236
|
+
current.coordinates.push(samples.xy[j]);
|
|
6237
|
+
const parent = part.provenance, target = current.provenance;
|
|
6238
|
+
if (parent && target) {
|
|
6239
|
+
const length = angle(geographic(a), geographic(b)), t = length ? Math.min(1, angle(geographic(a), geographic(p)) / length) : 0;
|
|
6240
|
+
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;
|
|
6241
|
+
target.segments.push(endpoint >= 0 ? parent.segments[endpoint] : segment);
|
|
6242
|
+
target.parameters.push(endpoint >= 0 ? parent.parameters[endpoint] : from + t * (parent.parameters[i] - from));
|
|
6243
|
+
target.vertices.push(endpoint >= 0 ? parent.vertices[endpoint] : 4294967295);
|
|
6244
|
+
if (options.pathDistances)
|
|
6245
|
+
target.angularDistances.push(parent.angularDistances[i - 1] + t * (parent.angularDistances[i] - parent.angularDistances[i - 1]));
|
|
6246
|
+
if (options.pathBoundaries) {
|
|
6247
|
+
if (target.vertices.length === 1)
|
|
6248
|
+
target.startReason = boundary(p, target.vertices[0]);
|
|
6249
|
+
target.endReason = boundary(p, target.vertices[target.vertices.length - 1]);
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6253
|
+
if (Math.hypot(last[0] - b[0], last[1] - b[1]) > 1e-8)
|
|
6254
|
+
current = void 0;
|
|
6255
|
+
}
|
|
6256
|
+
}
|
|
5544
6257
|
}
|
|
5545
6258
|
return out;
|
|
5546
6259
|
}
|
|
@@ -5548,13 +6261,175 @@ var ElasticMap = class {
|
|
|
5548
6261
|
const out = [];
|
|
5549
6262
|
for (const part of splitter.projectPolygon(rings, this.sourceOptions(options)))
|
|
5550
6263
|
for (const c of this.charts.filter((c2) => c2.baseId === part.regionId)) {
|
|
5551
|
-
const
|
|
6264
|
+
const prepared = [], preparedEdges = [];
|
|
6265
|
+
part.coordinates.forEach((ring, r) => {
|
|
6266
|
+
const points = [], edges = [];
|
|
6267
|
+
for (let i = 1; i < ring.length; i++) {
|
|
6268
|
+
const a = ring[i - 1], b = ring[i], arc = sourceArc(a, b), length = angle(geographic(a), geographic(b)), fractions = [0, 1];
|
|
6269
|
+
for (const interval of clipSourceArc(a, b, c.domain))
|
|
6270
|
+
for (const p of [interval.a, interval.b]) {
|
|
6271
|
+
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;
|
|
6272
|
+
if (t > 1e-12 && t < 1 - 1e-12)
|
|
6273
|
+
fractions.push(t);
|
|
6274
|
+
}
|
|
6275
|
+
fractions.sort((a2, b2) => a2 - b2);
|
|
6276
|
+
const split = fractions.filter((t, i2) => !i2 || t - fractions[i2 - 1] > 1e-12);
|
|
6277
|
+
const append2 = (point) => {
|
|
6278
|
+
if (points.length >= 1e5)
|
|
6279
|
+
throw new Error("Elastic polygon constraint vertex limit exceeded");
|
|
6280
|
+
if (points.length) {
|
|
6281
|
+
const previous = points[points.length - 1];
|
|
6282
|
+
if (options.polygonEdgeProvenance)
|
|
6283
|
+
edges.push(composePolygonEdge(part.edgeProvenance[r][i - 1], a, b, previous, point));
|
|
6284
|
+
}
|
|
6285
|
+
points.push(point);
|
|
6286
|
+
};
|
|
6287
|
+
const first = arc(0);
|
|
6288
|
+
if (!points.length)
|
|
6289
|
+
points.push(first);
|
|
6290
|
+
else if (points[points.length - 1].some((v, k2) => v !== first[k2])) {
|
|
6291
|
+
if (angle(geographic(points[points.length - 1]), geographic(first)) > 1e-10)
|
|
6292
|
+
throw new Error("Discontinuous Elastic input source constraint");
|
|
6293
|
+
if (options.polygonEdgeProvenance)
|
|
6294
|
+
edges.push({
|
|
6295
|
+
kind: "continuous-chart-join",
|
|
6296
|
+
ring: 4294967295,
|
|
6297
|
+
segment: 4294967295,
|
|
6298
|
+
t0: 0,
|
|
6299
|
+
t1: 0
|
|
6300
|
+
});
|
|
6301
|
+
points.push(first);
|
|
6302
|
+
}
|
|
6303
|
+
for (let j = 1; j < split.length; j++) {
|
|
6304
|
+
append2(arc((split[j - 1] + split[j]) / 2));
|
|
6305
|
+
append2(arc(split[j]));
|
|
6306
|
+
}
|
|
6307
|
+
}
|
|
6308
|
+
if (points[points.length - 1].some((v, k2) => v !== points[0][k2])) {
|
|
6309
|
+
if (angle(geographic(points[points.length - 1]), geographic(points[0])) > 1e-10)
|
|
6310
|
+
throw new Error("Unclosed Elastic input source constraint");
|
|
6311
|
+
if (options.polygonEdgeProvenance)
|
|
6312
|
+
edges.push({
|
|
6313
|
+
kind: "continuous-chart-join",
|
|
6314
|
+
ring: 4294967295,
|
|
6315
|
+
segment: 4294967295,
|
|
6316
|
+
t0: 0,
|
|
6317
|
+
t1: 0
|
|
6318
|
+
});
|
|
6319
|
+
points.push([...points[0]]);
|
|
6320
|
+
}
|
|
6321
|
+
prepared.push(points);
|
|
6322
|
+
preparedEdges.push(edges);
|
|
6323
|
+
});
|
|
6324
|
+
const clipped = import_polygon_clipping4.default.intersection(snapPolygon(prepared), c.domain.map(snapPolygon));
|
|
5552
6325
|
for (const polygon of clipped) {
|
|
5553
|
-
const
|
|
6326
|
+
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), resolved = traced.rings.map((r) => r.map((p) => [...p]));
|
|
6327
|
+
traced.owners.forEach((owners, r) => owners.forEach((owner, i) => {
|
|
6328
|
+
if (!owner)
|
|
6329
|
+
return;
|
|
6330
|
+
const [pr, pe] = owner, a = prepared[pr][pe], b = prepared[pr][pe + 1], length = angle(geographic(a), geographic(b)), arc = sourceArc(a, b);
|
|
6331
|
+
for (const j of [i, i + 1]) {
|
|
6332
|
+
const q = traced.rings[r][j], start = input[pr][pe], end = input[pr][pe + 1];
|
|
6333
|
+
if (Math.hypot(q[0] - start[0], q[1] - start[1]) < 1e-8)
|
|
6334
|
+
resolved[r][j] = [...a];
|
|
6335
|
+
else if (Math.hypot(q[0] - end[0], q[1] - end[1]) < 1e-8)
|
|
6336
|
+
resolved[r][j] = [...b];
|
|
6337
|
+
else {
|
|
6338
|
+
const candidates = clipSourceArc(a, b, c.domain).flatMap((interval) => [
|
|
6339
|
+
interval.a,
|
|
6340
|
+
interval.b
|
|
6341
|
+
]);
|
|
6342
|
+
if (!candidates.length)
|
|
6343
|
+
throw new Error("Unresolved Elastic polygon source intersection");
|
|
6344
|
+
const reference = length ? angle(geographic(a), geographic(q)) / length : 0;
|
|
6345
|
+
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));
|
|
6346
|
+
const fraction = length ? angle(geographic(a), geographic(candidates[0])) / length : 0;
|
|
6347
|
+
resolved[r][j] = arc(Math.min(1, Math.max(0, fraction)));
|
|
6348
|
+
}
|
|
6349
|
+
}
|
|
6350
|
+
}));
|
|
6351
|
+
for (const ring of resolved)
|
|
6352
|
+
ring[ring.length - 1] = [...ring[0]];
|
|
6353
|
+
const generated = (a, b) => {
|
|
6354
|
+
if (angle(geographic(a), geographic(b)) < 64 * Number.EPSILON)
|
|
6355
|
+
return "continuous-chart-join";
|
|
6356
|
+
let edge2 = 0;
|
|
6357
|
+
const kinds = [];
|
|
6358
|
+
for (const polygon2 of c.domain)
|
|
6359
|
+
for (const ring of polygon2)
|
|
6360
|
+
for (let j = 1; j < ring.length; j++, edge2++)
|
|
6361
|
+
if (onSegment(a, ring[j - 1], ring[j]) && onSegment(b, ring[j - 1], ring[j])) {
|
|
6362
|
+
const seam = this.seams.find((s) => s.regions.some((id, k2) => id === c.region.id && s.edges[k2] === edge2));
|
|
6363
|
+
kinds.push((seam == null ? void 0 : seam.kind) ?? "boundary");
|
|
6364
|
+
}
|
|
6365
|
+
if (!kinds.length)
|
|
6366
|
+
throw new Error("Unknown Elastic polygon clipping constraint");
|
|
6367
|
+
return kinds.includes("boundary") ? "coverage-boundary" : kinds.includes("cut") ? "chart-cut" : "continuous-chart-join";
|
|
6368
|
+
};
|
|
6369
|
+
const coordinates2 = [], sourceCoordinates = [], edgeProvenance = [];
|
|
6370
|
+
resolved.forEach((ring, r) => {
|
|
6371
|
+
const source = [], xy = [], edges = [];
|
|
6372
|
+
for (let i = 1; i < ring.length; i++) {
|
|
6373
|
+
const owner = traced.owners[r][i - 1], arc = owner ? sourceArc(ring[i - 1], ring[i]) : void 0;
|
|
6374
|
+
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);
|
|
6375
|
+
if (!source.length) {
|
|
6376
|
+
source.push(samples.source[0]);
|
|
6377
|
+
xy.push(samples.xy[0]);
|
|
6378
|
+
} else if (source[source.length - 1].some((v, k2) => Math.abs(v - samples.source[0][k2]) > 1e-10)) {
|
|
6379
|
+
if (angle(geographic(source[source.length - 1]), geographic(samples.source[0])) > 1e-10)
|
|
6380
|
+
throw new Error("Discontinuous Elastic polygon source constraint");
|
|
6381
|
+
if (options.polygonEdgeProvenance)
|
|
6382
|
+
edges.push({
|
|
6383
|
+
kind: "continuous-chart-join",
|
|
6384
|
+
ring: 4294967295,
|
|
6385
|
+
segment: 4294967295,
|
|
6386
|
+
t0: 0,
|
|
6387
|
+
t1: 0
|
|
6388
|
+
});
|
|
6389
|
+
source.push(samples.source[0]);
|
|
6390
|
+
xy.push(samples.xy[0]);
|
|
6391
|
+
}
|
|
6392
|
+
for (let j = 1; j < samples.source.length; j++) {
|
|
6393
|
+
if (options.polygonEdgeProvenance) {
|
|
6394
|
+
if (owner) {
|
|
6395
|
+
const [pr, pe] = owner;
|
|
6396
|
+
edges.push(composePolygonEdge(preparedEdges[pr][pe], prepared[pr][pe], prepared[pr][pe + 1], source[source.length - 1], samples.source[j]));
|
|
6397
|
+
} else
|
|
6398
|
+
edges.push({
|
|
6399
|
+
kind: generated(ring[i - 1], ring[i]),
|
|
6400
|
+
ring: 4294967295,
|
|
6401
|
+
segment: 4294967295,
|
|
6402
|
+
t0: 0,
|
|
6403
|
+
t1: 0
|
|
6404
|
+
});
|
|
6405
|
+
}
|
|
6406
|
+
source.push(samples.source[j]);
|
|
6407
|
+
xy.push(samples.xy[j]);
|
|
6408
|
+
}
|
|
6409
|
+
}
|
|
6410
|
+
if (source.length && source[source.length - 1].some((v, k2) => v !== source[0][k2])) {
|
|
6411
|
+
if (angle(geographic(source[source.length - 1]), geographic(source[0])) > 1e-10)
|
|
6412
|
+
throw new Error("Unclosed Elastic polygon source constraint");
|
|
6413
|
+
if (options.polygonEdgeProvenance)
|
|
6414
|
+
edges.push({
|
|
6415
|
+
kind: "continuous-chart-join",
|
|
6416
|
+
ring: 4294967295,
|
|
6417
|
+
segment: 4294967295,
|
|
6418
|
+
t0: 0,
|
|
6419
|
+
t1: 0
|
|
6420
|
+
});
|
|
6421
|
+
source.push([...source[0]]);
|
|
6422
|
+
xy.push([...xy[0]]);
|
|
6423
|
+
}
|
|
6424
|
+
coordinates2.push(xy);
|
|
6425
|
+
sourceCoordinates.push(source);
|
|
6426
|
+
edgeProvenance.push(edges);
|
|
6427
|
+
});
|
|
5554
6428
|
out.push({
|
|
5555
6429
|
regionId: c.region.id,
|
|
5556
|
-
coordinates:
|
|
5557
|
-
sourceCoordinates
|
|
6430
|
+
coordinates: coordinates2,
|
|
6431
|
+
sourceCoordinates,
|
|
6432
|
+
...options.polygonEdgeProvenance ? { edgeProvenance } : {}
|
|
5558
6433
|
});
|
|
5559
6434
|
}
|
|
5560
6435
|
}
|
|
@@ -5608,7 +6483,7 @@ function wrap3(lon) {
|
|
|
5608
6483
|
return x > 180 ? x - 360 : x < -180 ? x + 360 : x;
|
|
5609
6484
|
}
|
|
5610
6485
|
function snapPolygon(rings) {
|
|
5611
|
-
return rings.map((
|
|
6486
|
+
return rings.map((r) => r.map((p) => p.map((v) => Math.round(v * 1e10) / 1e10)));
|
|
5612
6487
|
}
|
|
5613
6488
|
|
|
5614
6489
|
// dist/discontinuous/petroff.js
|
|
@@ -6844,17 +7719,65 @@ var MercatorMap = class extends DiscontinuousMap {
|
|
|
6844
7719
|
continue;
|
|
6845
7720
|
}
|
|
6846
7721
|
const at = (t) => [a[0] + (b[0] - a[0]) * t, a[1] + dy * t];
|
|
6847
|
-
const
|
|
7722
|
+
const endpoint = (t) => {
|
|
7723
|
+
if (t === 0 || t === 1)
|
|
7724
|
+
return { xy: at(t), source: part.sourceCoordinates[i - 1 + t], t };
|
|
7725
|
+
const va = geographic(part.sourceCoordinates[i - 1]), vb = geographic(part.sourceCoordinates[i]), arc = angle(va, vb);
|
|
7726
|
+
const sourceAt = (t2) => {
|
|
7727
|
+
if (!arc)
|
|
7728
|
+
return part.sourceCoordinates[i - 1];
|
|
7729
|
+
const a2 = Math.sin((1 - t2) * arc) / Math.sin(arc), b2 = Math.sin(t2 * arc) / Math.sin(arc);
|
|
7730
|
+
return coordinates(unit(va.map((v, k2) => a2 * v + b2 * vb[k2])));
|
|
7731
|
+
};
|
|
7732
|
+
const latitude = Math.sign(at(t)[1]) * this.limit;
|
|
7733
|
+
let lo = 0, hi = 1;
|
|
7734
|
+
for (let j = 0; j < 52; j++) {
|
|
7735
|
+
const mid = (lo + hi) / 2;
|
|
7736
|
+
if (sourceAt(mid)[1] < latitude === part.sourceCoordinates[i - 1][1] < latitude)
|
|
7737
|
+
lo = mid;
|
|
7738
|
+
else
|
|
7739
|
+
hi = mid;
|
|
7740
|
+
}
|
|
7741
|
+
const f = (lo + hi) / 2, source = sourceAt(f);
|
|
7742
|
+
const xy = super.projectPoint(source, part.regionId).position;
|
|
7743
|
+
return { xy, source, t: f };
|
|
7744
|
+
};
|
|
7745
|
+
const start = endpoint(t0), end = endpoint(t1);
|
|
7746
|
+
const append2 = (point, index) => {
|
|
7747
|
+
current.coordinates.push(point.xy);
|
|
7748
|
+
current.sourceCoordinates.push(point.source);
|
|
7749
|
+
const source = part.provenance, target = current.provenance;
|
|
7750
|
+
if (!source || !target)
|
|
7751
|
+
return;
|
|
7752
|
+
const segment = source.segments[i];
|
|
7753
|
+
const from = source.segments[i - 1] === segment ? source.parameters[i - 1] : 0;
|
|
7754
|
+
target.segments.push(point.t === 0 || point.t === 1 ? source.segments[index] : segment);
|
|
7755
|
+
target.parameters.push(point.t === 0 || point.t === 1 ? source.parameters[index] : from + point.t * (source.parameters[i] - from));
|
|
7756
|
+
target.vertices.push(point.t === 0 || point.t === 1 ? source.vertices[index] : 4294967295);
|
|
7757
|
+
if (options == null ? void 0 : options.pathDistances)
|
|
7758
|
+
target.angularDistances.push(source.angularDistances[i - 1] + point.t * (source.angularDistances[i] - source.angularDistances[i - 1]));
|
|
7759
|
+
};
|
|
6848
7760
|
if (!current || t0 > 0) {
|
|
6849
7761
|
current = {
|
|
6850
7762
|
regionId: part.regionId,
|
|
6851
|
-
coordinates: [
|
|
6852
|
-
sourceCoordinates: [
|
|
7763
|
+
coordinates: [],
|
|
7764
|
+
sourceCoordinates: [],
|
|
7765
|
+
...part.provenance ? {
|
|
7766
|
+
provenance: {
|
|
7767
|
+
segments: [],
|
|
7768
|
+
parameters: [],
|
|
7769
|
+
vertices: [],
|
|
7770
|
+
angularDistances: [],
|
|
7771
|
+
...(options == null ? void 0 : options.pathBoundaries) ? { startReason: t0 > 0 ? "coverage-boundary" : part.provenance.startReason } : {}
|
|
7772
|
+
}
|
|
7773
|
+
} : {}
|
|
6853
7774
|
};
|
|
6854
7775
|
result.push(current);
|
|
7776
|
+
append2(start, i - 1);
|
|
6855
7777
|
}
|
|
6856
|
-
|
|
6857
|
-
current.
|
|
7778
|
+
append2(end, i);
|
|
7779
|
+
if (current.provenance && (options == null ? void 0 : options.pathBoundaries))
|
|
7780
|
+
current.provenance.endReason = t1 < 1 ? "coverage-boundary" : part.provenance.endReason;
|
|
6858
7781
|
if (t1 < 1)
|
|
6859
7782
|
current = void 0;
|
|
6860
7783
|
}
|
|
@@ -6872,11 +7795,60 @@ var MercatorMap = class extends DiscontinuousMap {
|
|
|
6872
7795
|
[-x, -y]
|
|
6873
7796
|
]
|
|
6874
7797
|
];
|
|
6875
|
-
return super.projectPolygon(rings, options).flatMap((part) => import_polygon_clipping5.default.intersection(part.coordinates, box).map((
|
|
6876
|
-
|
|
6877
|
-
|
|
6878
|
-
|
|
6879
|
-
|
|
7798
|
+
return super.projectPolygon(rings, options).flatMap((part) => import_polygon_clipping5.default.intersection(part.coordinates, box).map((polygon) => {
|
|
7799
|
+
const traced = tracePolygonConstraints(part.coordinates, polygon, 1e-10, part.edgeProvenance);
|
|
7800
|
+
const sources = traced.rings.map((r) => r.map((p) => this.source(p)));
|
|
7801
|
+
traced.owners.forEach((owners, r) => owners.forEach((owner, i) => {
|
|
7802
|
+
if (!owner)
|
|
7803
|
+
return;
|
|
7804
|
+
const [parentRing, parentEdge] = owner, a = part.sourceCoordinates[parentRing][parentEdge], b = part.sourceCoordinates[parentRing][parentEdge + 1], at = sourceArc(a, b);
|
|
7805
|
+
for (const j of [i, i + 1]) {
|
|
7806
|
+
const q = traced.rings[r][j], first = part.coordinates[parentRing][parentEdge], last = part.coordinates[parentRing][parentEdge + 1];
|
|
7807
|
+
if (Math.hypot(q[0] - first[0], q[1] - first[1]) < 1e-10 * this.radius)
|
|
7808
|
+
sources[r][j] = [...a];
|
|
7809
|
+
else if (Math.hypot(q[0] - last[0], q[1] - last[1]) < 1e-10 * this.radius)
|
|
7810
|
+
sources[r][j] = [...b];
|
|
7811
|
+
else {
|
|
7812
|
+
const latitude = Math.sign(q[1]) * this.limit;
|
|
7813
|
+
let lo = 0, hi = 1;
|
|
7814
|
+
if (a[1] < latitude === b[1] < latitude)
|
|
7815
|
+
throw new Error("Unresolved Mercator source constraint intersection");
|
|
7816
|
+
for (let k2 = 0; k2 < 52; k2++) {
|
|
7817
|
+
const mid = (lo + hi) / 2;
|
|
7818
|
+
if (at(mid)[1] < latitude === a[1] < latitude)
|
|
7819
|
+
lo = mid;
|
|
7820
|
+
else
|
|
7821
|
+
hi = mid;
|
|
7822
|
+
}
|
|
7823
|
+
sources[r][j] = at((lo + hi) / 2);
|
|
7824
|
+
}
|
|
7825
|
+
}
|
|
7826
|
+
}));
|
|
7827
|
+
for (const r of sources)
|
|
7828
|
+
r[r.length - 1] = [...r[0]];
|
|
7829
|
+
return {
|
|
7830
|
+
regionId: part.regionId,
|
|
7831
|
+
sourceCoordinates: sources,
|
|
7832
|
+
coordinates: sources.map((r) => r.map((p) => super.projectPoint(p, part.regionId).position)),
|
|
7833
|
+
...(options == null ? void 0 : options.polygonEdgeProvenance) ? {
|
|
7834
|
+
edgeProvenance: traced.owners.map((owners, r) => owners.map((owner, i) => {
|
|
7835
|
+
if (owner) {
|
|
7836
|
+
const [pr, pe] = owner;
|
|
7837
|
+
return composePolygonEdge(part.edgeProvenance[pr][pe], part.sourceCoordinates[pr][pe], part.sourceCoordinates[pr][pe + 1], sources[r][i], sources[r][i + 1]);
|
|
7838
|
+
}
|
|
7839
|
+
if (!sources[r].slice(i, i + 2).every((p) => Math.abs(Math.abs(p[1]) - this.limit) < 1e-7))
|
|
7840
|
+
throw new Error("Unknown Mercator clipping constraint");
|
|
7841
|
+
return {
|
|
7842
|
+
kind: "coverage-boundary",
|
|
7843
|
+
ring: 4294967295,
|
|
7844
|
+
segment: 4294967295,
|
|
7845
|
+
t0: 0,
|
|
7846
|
+
t1: 0
|
|
7847
|
+
};
|
|
7848
|
+
}))
|
|
7849
|
+
} : {}
|
|
7850
|
+
};
|
|
7851
|
+
}));
|
|
6880
7852
|
}
|
|
6881
7853
|
};
|
|
6882
7854
|
|