mapshaper 0.7.46 → 0.7.47
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/mapshaper.js +1969 -202
- package/package.json +1 -1
- package/www/mapshaper.js +1969 -202
package/mapshaper.js
CHANGED
|
@@ -2053,12 +2053,12 @@
|
|
|
2053
2053
|
// TODO: remove this constant, use actual data from dataset CRS,
|
|
2054
2054
|
// also consider using ellipsoidal formulas where greater accuracy might be important.
|
|
2055
2055
|
var R$3 = WGS84.SEMIMAJOR_AXIS;
|
|
2056
|
-
var D2R$
|
|
2057
|
-
var R2D$
|
|
2056
|
+
var D2R$8 = Math.PI / 180;
|
|
2057
|
+
var R2D$7 = 180 / Math.PI;
|
|
2058
2058
|
|
|
2059
2059
|
// Equirectangular projection
|
|
2060
2060
|
function degreesToMeters(deg) {
|
|
2061
|
-
return deg * D2R$
|
|
2061
|
+
return deg * D2R$8 * R$3;
|
|
2062
2062
|
}
|
|
2063
2063
|
|
|
2064
2064
|
function distance3D(ax, ay, az, bx, by, bz) {
|
|
@@ -2205,16 +2205,16 @@
|
|
|
2205
2205
|
|
|
2206
2206
|
function xyzToLngLat(x, y, z, p) {
|
|
2207
2207
|
var d = distance3D(0, 0, 0, x, y, z); // normalize
|
|
2208
|
-
var lat = Math.asin(z / d) / D2R$
|
|
2209
|
-
var lng = Math.atan2(y / d, x / d) / D2R$
|
|
2208
|
+
var lat = Math.asin(z / d) / D2R$8;
|
|
2209
|
+
var lng = Math.atan2(y / d, x / d) / D2R$8;
|
|
2210
2210
|
p[0] = lng;
|
|
2211
2211
|
p[1] = lat;
|
|
2212
2212
|
}
|
|
2213
2213
|
|
|
2214
2214
|
function lngLatToXYZ(lng, lat, p) {
|
|
2215
2215
|
var cosLat;
|
|
2216
|
-
lng *= D2R$
|
|
2217
|
-
lat *= D2R$
|
|
2216
|
+
lng *= D2R$8;
|
|
2217
|
+
lat *= D2R$8;
|
|
2218
2218
|
cosLat = Math.cos(lat);
|
|
2219
2219
|
p[0] = Math.cos(lng) * cosLat * R$3;
|
|
2220
2220
|
p[1] = Math.sin(lng) * cosLat * R$3;
|
|
@@ -2334,9 +2334,9 @@
|
|
|
2334
2334
|
|
|
2335
2335
|
var Geom = /*#__PURE__*/Object.freeze({
|
|
2336
2336
|
__proto__: null,
|
|
2337
|
-
D2R: D2R$
|
|
2337
|
+
D2R: D2R$8,
|
|
2338
2338
|
R: R$3,
|
|
2339
|
-
R2D: R2D$
|
|
2339
|
+
R2D: R2D$7,
|
|
2340
2340
|
bearing: bearing,
|
|
2341
2341
|
bearing2D: bearing2D,
|
|
2342
2342
|
containsBounds: containsBounds,
|
|
@@ -6264,9 +6264,9 @@
|
|
|
6264
6264
|
* ISC License: https://github.com/d3/d3-geo-polygon/blob/main/LICENSE
|
|
6265
6265
|
*/
|
|
6266
6266
|
|
|
6267
|
-
var D2R$
|
|
6268
|
-
var R2D$
|
|
6269
|
-
var EPS$
|
|
6267
|
+
var D2R$7 = Math.PI / 180;
|
|
6268
|
+
var R2D$6 = 180 / Math.PI;
|
|
6269
|
+
var EPS$3 = 1e-12;
|
|
6270
6270
|
|
|
6271
6271
|
// Build a forward-only spherical polyhedral projection.
|
|
6272
6272
|
//
|
|
@@ -6304,10 +6304,10 @@
|
|
|
6304
6304
|
throw new Error('Invalid polyhedral face tree');
|
|
6305
6305
|
}
|
|
6306
6306
|
var childEdge = shared.map(function(p) {
|
|
6307
|
-
return face.project(p[0] * D2R$
|
|
6307
|
+
return face.project(p[0] * D2R$7, p[1] * D2R$7);
|
|
6308
6308
|
});
|
|
6309
6309
|
var parentEdge = shared.map(function(p) {
|
|
6310
|
-
return parent.project(p[0] * D2R$
|
|
6310
|
+
return parent.project(p[0] * D2R$7, p[1] * D2R$7);
|
|
6311
6311
|
});
|
|
6312
6312
|
face.transform = multiplyMatrices(
|
|
6313
6313
|
parent.transform,
|
|
@@ -6318,12 +6318,12 @@
|
|
|
6318
6318
|
|
|
6319
6319
|
var rootEdge = findLongestEdge(faces[0].coords);
|
|
6320
6320
|
var rootPlanarEdge = rootEdge.map(function(p) {
|
|
6321
|
-
return faces[0].project(p[0] * D2R$
|
|
6321
|
+
return faces[0].project(p[0] * D2R$7, p[1] * D2R$7);
|
|
6322
6322
|
});
|
|
6323
6323
|
var sphericalEdgeLength = angularDistance(rootEdge[0], rootEdge[1]);
|
|
6324
6324
|
var planarEdgeLength = distance2D(rootPlanarEdge[0], rootPlanarEdge[1]);
|
|
6325
6325
|
var scale = sphericalEdgeLength / planarEdgeLength;
|
|
6326
|
-
var planarAngle = (config.angle || 0) * D2R$
|
|
6326
|
+
var planarAngle = (config.angle || 0) * D2R$7;
|
|
6327
6327
|
var edgeIndex = indexEdges(faces, attachedPairs);
|
|
6328
6328
|
var outline = buildOutline(faces, attachedPairs).map(function(ring) {
|
|
6329
6329
|
return ring.map(transformOutputPoint);
|
|
@@ -6344,6 +6344,7 @@
|
|
|
6344
6344
|
faces: faces,
|
|
6345
6345
|
outline: outline,
|
|
6346
6346
|
forward: forward,
|
|
6347
|
+
forwardFace: forwardFace,
|
|
6347
6348
|
findFace: findFace,
|
|
6348
6349
|
findTransitionRegion: findTransitionRegion,
|
|
6349
6350
|
getTopology: getTopology
|
|
@@ -6353,14 +6354,30 @@
|
|
|
6353
6354
|
var rotated = rotateRadians(
|
|
6354
6355
|
lam,
|
|
6355
6356
|
phi,
|
|
6356
|
-
config.rotation[0] * D2R$
|
|
6357
|
-
config.rotation[1] * D2R$
|
|
6358
|
-
config.rotation[2] * D2R$
|
|
6357
|
+
config.rotation[0] * D2R$7,
|
|
6358
|
+
config.rotation[1] * D2R$7,
|
|
6359
|
+
config.rotation[2] * D2R$7
|
|
6359
6360
|
);
|
|
6360
6361
|
var face = findFaceRotated(rotated[0], rotated[1]);
|
|
6361
6362
|
if (!face) return null;
|
|
6362
|
-
|
|
6363
|
-
|
|
6363
|
+
return projectFacePoint(face, rotated[0], rotated[1]);
|
|
6364
|
+
}
|
|
6365
|
+
|
|
6366
|
+
function forwardFace(lam, phi, faceId) {
|
|
6367
|
+
var rotated = rotateRadians(
|
|
6368
|
+
lam,
|
|
6369
|
+
phi,
|
|
6370
|
+
config.rotation[0] * D2R$7,
|
|
6371
|
+
config.rotation[1] * D2R$7,
|
|
6372
|
+
config.rotation[2] * D2R$7
|
|
6373
|
+
);
|
|
6374
|
+
var face = faces[faceId];
|
|
6375
|
+
return face ? projectFacePoint(face, rotated[0], rotated[1]) : null;
|
|
6376
|
+
}
|
|
6377
|
+
|
|
6378
|
+
function projectFacePoint(face, lam, phi) {
|
|
6379
|
+
var p = face.project(lam, phi);
|
|
6380
|
+
p = applyMatrix$1(face.transform, p);
|
|
6364
6381
|
p = transformOutputPoint(p);
|
|
6365
6382
|
p[0] -= centerX;
|
|
6366
6383
|
p[1] -= centerY;
|
|
@@ -6371,9 +6388,9 @@
|
|
|
6371
6388
|
var rotated = rotateRadians(
|
|
6372
6389
|
lam,
|
|
6373
6390
|
phi,
|
|
6374
|
-
config.rotation[0] * D2R$
|
|
6375
|
-
config.rotation[1] * D2R$
|
|
6376
|
-
config.rotation[2] * D2R$
|
|
6391
|
+
config.rotation[0] * D2R$7,
|
|
6392
|
+
config.rotation[1] * D2R$7,
|
|
6393
|
+
config.rotation[2] * D2R$7
|
|
6377
6394
|
);
|
|
6378
6395
|
var face = findFaceRotated(rotated[0], rotated[1]);
|
|
6379
6396
|
return face ? face.id : -1;
|
|
@@ -6383,9 +6400,9 @@
|
|
|
6383
6400
|
var rotated = rotateRadians(
|
|
6384
6401
|
lam,
|
|
6385
6402
|
phi,
|
|
6386
|
-
config.rotation[0] * D2R$
|
|
6387
|
-
config.rotation[1] * D2R$
|
|
6388
|
-
config.rotation[2] * D2R$
|
|
6403
|
+
config.rotation[0] * D2R$7,
|
|
6404
|
+
config.rotation[1] * D2R$7,
|
|
6405
|
+
config.rotation[2] * D2R$7
|
|
6389
6406
|
);
|
|
6390
6407
|
var face = findFaceRotated(rotated[0], rotated[1]);
|
|
6391
6408
|
var region;
|
|
@@ -6427,14 +6444,14 @@
|
|
|
6427
6444
|
var seams = edgeIndex.map(function(edge) {
|
|
6428
6445
|
var endpoints = edge.points.map(function(p) {
|
|
6429
6446
|
var q = rotateRadians(
|
|
6430
|
-
p[0] * D2R$
|
|
6431
|
-
p[1] * D2R$
|
|
6432
|
-
config.rotation[0] * D2R$
|
|
6433
|
-
config.rotation[1] * D2R$
|
|
6434
|
-
config.rotation[2] * D2R$
|
|
6447
|
+
p[0] * D2R$7,
|
|
6448
|
+
p[1] * D2R$7,
|
|
6449
|
+
config.rotation[0] * D2R$7,
|
|
6450
|
+
config.rotation[1] * D2R$7,
|
|
6451
|
+
config.rotation[2] * D2R$7,
|
|
6435
6452
|
true
|
|
6436
6453
|
);
|
|
6437
|
-
return [normalizeLongitude$
|
|
6454
|
+
return [normalizeLongitude$3(q[0] * R2D$6 + lon0), q[1] * R2D$6];
|
|
6438
6455
|
});
|
|
6439
6456
|
var paths = splitPathAtAntimeridian$2(
|
|
6440
6457
|
interpolateGreatCircle(endpoints[0], endpoints[1], 0.05)
|
|
@@ -6457,16 +6474,23 @@
|
|
|
6457
6474
|
});
|
|
6458
6475
|
return {
|
|
6459
6476
|
regions: faces.map(function(face) {
|
|
6460
|
-
return {
|
|
6477
|
+
return {
|
|
6478
|
+
id: face.id,
|
|
6479
|
+
projected_boundary: getProjectedFaceBoundary(face)
|
|
6480
|
+
};
|
|
6461
6481
|
}),
|
|
6462
6482
|
seams: seams,
|
|
6463
6483
|
findRegion: function(lon, lat) {
|
|
6464
|
-
var lam = normalizeLongitude$
|
|
6465
|
-
return findFace(lam, lat * D2R$
|
|
6484
|
+
var lam = normalizeLongitude$3(lon - lon0) * D2R$7;
|
|
6485
|
+
return findFace(lam, lat * D2R$7);
|
|
6466
6486
|
},
|
|
6467
6487
|
findTransitionRegion: function(lon, lat) {
|
|
6468
|
-
var lam = normalizeLongitude$
|
|
6469
|
-
return findTransitionRegion(lam, lat * D2R$
|
|
6488
|
+
var lam = normalizeLongitude$3(lon - lon0) * D2R$7;
|
|
6489
|
+
return findTransitionRegion(lam, lat * D2R$7);
|
|
6490
|
+
},
|
|
6491
|
+
projectRegion: function(lon, lat, regionId) {
|
|
6492
|
+
var lam = normalizeLongitude$3(lon - lon0) * D2R$7;
|
|
6493
|
+
return forwardFace(lam, lat * D2R$7, regionId);
|
|
6470
6494
|
},
|
|
6471
6495
|
regionsAreAttached: function(a, b) {
|
|
6472
6496
|
return regionPairs.get(pairKey(a, b)) === true;
|
|
@@ -6478,15 +6502,29 @@
|
|
|
6478
6502
|
})
|
|
6479
6503
|
};
|
|
6480
6504
|
}
|
|
6505
|
+
|
|
6506
|
+
function getProjectedFaceBoundary(face) {
|
|
6507
|
+
var ring = [];
|
|
6508
|
+
for (var i = 0; i < face.coords.length; i++) {
|
|
6509
|
+
var a = face.coords[i];
|
|
6510
|
+
var b = face.coords[(i + 1) % face.coords.length];
|
|
6511
|
+
var edge = interpolateGreatCircle(a, b, 0.5);
|
|
6512
|
+
for (var j = 0; j < edge.length - 1; j++) {
|
|
6513
|
+
ring.push(projectFacePoint(face, edge[j][0] * D2R$7, edge[j][1] * D2R$7));
|
|
6514
|
+
}
|
|
6515
|
+
}
|
|
6516
|
+
ring.push(ring[0].concat());
|
|
6517
|
+
return ring;
|
|
6518
|
+
}
|
|
6481
6519
|
}
|
|
6482
6520
|
|
|
6483
6521
|
function rotateSphericalRadians(lam, phi, rotation, invert) {
|
|
6484
6522
|
return rotateRadians(
|
|
6485
6523
|
lam,
|
|
6486
6524
|
phi,
|
|
6487
|
-
(rotation[0] || 0) * D2R$
|
|
6488
|
-
(rotation[1] || 0) * D2R$
|
|
6489
|
-
(rotation[2] || 0) * D2R$
|
|
6525
|
+
(rotation[0] || 0) * D2R$7,
|
|
6526
|
+
(rotation[1] || 0) * D2R$7,
|
|
6527
|
+
(rotation[2] || 0) * D2R$7,
|
|
6490
6528
|
invert
|
|
6491
6529
|
);
|
|
6492
6530
|
}
|
|
@@ -6523,7 +6561,7 @@
|
|
|
6523
6561
|
function faceContainsVector(face, p) {
|
|
6524
6562
|
for (var i = 0; i < face.edges.length; i++) {
|
|
6525
6563
|
var edge = face.edges[i];
|
|
6526
|
-
if (dot$2(edge.normal, p) * edge.sign < -EPS$
|
|
6564
|
+
if (dot$2(edge.normal, p) * edge.sign < -EPS$3) return false;
|
|
6527
6565
|
}
|
|
6528
6566
|
return true;
|
|
6529
6567
|
}
|
|
@@ -6559,8 +6597,8 @@
|
|
|
6559
6597
|
var adjacent = findAdjacentFace(faces, face.id, a, b);
|
|
6560
6598
|
if (adjacent >= 0 && attachedPairs.has(pairKey(face.id, adjacent))) continue;
|
|
6561
6599
|
edges.push([
|
|
6562
|
-
applyMatrix(face.transform, face.project(a[0] * D2R$
|
|
6563
|
-
applyMatrix(face.transform, face.project(b[0] * D2R$
|
|
6600
|
+
applyMatrix$1(face.transform, face.project(a[0] * D2R$7, a[1] * D2R$7)),
|
|
6601
|
+
applyMatrix$1(face.transform, face.project(b[0] * D2R$7, b[1] * D2R$7))
|
|
6564
6602
|
]);
|
|
6565
6603
|
}
|
|
6566
6604
|
});
|
|
@@ -6677,7 +6715,7 @@
|
|
|
6677
6715
|
];
|
|
6678
6716
|
}
|
|
6679
6717
|
|
|
6680
|
-
function applyMatrix(m, p) {
|
|
6718
|
+
function applyMatrix$1(m, p) {
|
|
6681
6719
|
return [
|
|
6682
6720
|
m[0] * p[0] + m[1] * p[1] + m[2],
|
|
6683
6721
|
m[3] * p[0] + m[4] * p[1] + m[5]
|
|
@@ -6724,13 +6762,13 @@
|
|
|
6724
6762
|
var av = degreesToVector$2(a[0], a[1]);
|
|
6725
6763
|
var bv = degreesToVector$2(b[0], b[1]);
|
|
6726
6764
|
var angle = Math.acos(clamp$3(dot$2(av, bv), -1, 1));
|
|
6727
|
-
var n = Math.max(1, Math.ceil(angle * R2D$
|
|
6765
|
+
var n = Math.max(1, Math.ceil(angle * R2D$6 / interval));
|
|
6728
6766
|
var sinAngle = Math.sin(angle);
|
|
6729
6767
|
var points = [];
|
|
6730
6768
|
for (var i = 0; i <= n; i++) {
|
|
6731
6769
|
var t = i / n;
|
|
6732
6770
|
var p;
|
|
6733
|
-
if (sinAngle < EPS$
|
|
6771
|
+
if (sinAngle < EPS$3) {
|
|
6734
6772
|
p = av;
|
|
6735
6773
|
} else {
|
|
6736
6774
|
var ka = Math.sin((1 - t) * angle) / sinAngle;
|
|
@@ -6787,7 +6825,7 @@
|
|
|
6787
6825
|
}
|
|
6788
6826
|
|
|
6789
6827
|
function degreesToVector$2(lon, lat) {
|
|
6790
|
-
return radiansToVector$1(lon * D2R$
|
|
6828
|
+
return radiansToVector$1(lon * D2R$7, lat * D2R$7);
|
|
6791
6829
|
}
|
|
6792
6830
|
|
|
6793
6831
|
function radiansToVector$1(lam, phi) {
|
|
@@ -6797,8 +6835,8 @@
|
|
|
6797
6835
|
|
|
6798
6836
|
function vectorToDegrees$2(p) {
|
|
6799
6837
|
return [
|
|
6800
|
-
Math.atan2(p[1], p[0]) * R2D$
|
|
6801
|
-
Math.asin(clamp$3(p[2], -1, 1)) * R2D$
|
|
6838
|
+
Math.atan2(p[1], p[0]) * R2D$6,
|
|
6839
|
+
Math.asin(clamp$3(p[2], -1, 1)) * R2D$6
|
|
6802
6840
|
];
|
|
6803
6841
|
}
|
|
6804
6842
|
|
|
@@ -6826,7 +6864,7 @@
|
|
|
6826
6864
|
}
|
|
6827
6865
|
|
|
6828
6866
|
function sameSphericalPoint(a, b) {
|
|
6829
|
-
return Math.abs(a[0] - b[0]) < EPS$
|
|
6867
|
+
return Math.abs(a[0] - b[0]) < EPS$3 && Math.abs(a[1] - b[1]) < EPS$3;
|
|
6830
6868
|
}
|
|
6831
6869
|
|
|
6832
6870
|
function pointsAlmostEqual(a, b) {
|
|
@@ -6853,7 +6891,7 @@
|
|
|
6853
6891
|
return lam;
|
|
6854
6892
|
}
|
|
6855
6893
|
|
|
6856
|
-
function normalizeLongitude$
|
|
6894
|
+
function normalizeLongitude$3(lon) {
|
|
6857
6895
|
while (lon > 180) lon -= 360;
|
|
6858
6896
|
while (lon < -180) lon += 360;
|
|
6859
6897
|
return lon;
|
|
@@ -6875,9 +6913,9 @@
|
|
|
6875
6913
|
*/
|
|
6876
6914
|
|
|
6877
6915
|
|
|
6878
|
-
var D2R$
|
|
6879
|
-
var R2D$
|
|
6880
|
-
var SQRT3$
|
|
6916
|
+
var D2R$6 = Math.PI / 180;
|
|
6917
|
+
var R2D$5 = 180 / Math.PI;
|
|
6918
|
+
var SQRT3$2 = Math.sqrt(3);
|
|
6881
6919
|
var GRAY_Z = Math.sqrt(5 + 2 * Math.sqrt(5)) / Math.sqrt(15);
|
|
6882
6920
|
var GRAY_EL = Math.sqrt(8) / Math.sqrt(5 + Math.sqrt(5));
|
|
6883
6921
|
var GRAY_DVE = Math.sqrt(3 + Math.sqrt(5)) / Math.sqrt(5 + Math.sqrt(5));
|
|
@@ -6889,7 +6927,7 @@
|
|
|
6889
6927
|
6, 8, 10, 17, 21,
|
|
6890
6928
|
16, 15, 19, 19
|
|
6891
6929
|
];
|
|
6892
|
-
var engines$
|
|
6930
|
+
var engines$3 = {};
|
|
6893
6931
|
|
|
6894
6932
|
function registerDymaxionProjections(mproj) {
|
|
6895
6933
|
// Some unit tests import source modules directly in an ESM context where
|
|
@@ -6908,9 +6946,9 @@
|
|
|
6908
6946
|
|
|
6909
6947
|
function getDymaxionEngine(method) {
|
|
6910
6948
|
method = method || 'fuller';
|
|
6911
|
-
if (!engines$
|
|
6949
|
+
if (!engines$3[method]) {
|
|
6912
6950
|
var data = createAiroceanFaces();
|
|
6913
|
-
engines$
|
|
6951
|
+
engines$3[method] = createPolyhedralProjection({
|
|
6914
6952
|
faces: data.faces,
|
|
6915
6953
|
faceSites: data.sites,
|
|
6916
6954
|
parents: PARENTS,
|
|
@@ -6921,7 +6959,7 @@
|
|
|
6921
6959
|
createGrayFullerFaceProjector
|
|
6922
6960
|
});
|
|
6923
6961
|
}
|
|
6924
|
-
return engines$
|
|
6962
|
+
return engines$3[method];
|
|
6925
6963
|
}
|
|
6926
6964
|
|
|
6927
6965
|
function initDymaxion(P, method) {
|
|
@@ -6937,12 +6975,12 @@
|
|
|
6937
6975
|
xy.y = p[1];
|
|
6938
6976
|
}
|
|
6939
6977
|
};
|
|
6940
|
-
P.__projection_topology = engine.getTopology(P.lam0 * R2D$
|
|
6978
|
+
P.__projection_topology = engine.getTopology(P.lam0 * R2D$5);
|
|
6941
6979
|
P.__projected_outline = engine.outline;
|
|
6942
6980
|
}
|
|
6943
6981
|
|
|
6944
6982
|
function createAiroceanFaces() {
|
|
6945
|
-
var theta = Math.atan(0.5) * R2D$
|
|
6983
|
+
var theta = Math.atan(0.5) * R2D$5;
|
|
6946
6984
|
var vertices = [[0, 90], [0, -90]];
|
|
6947
6985
|
var faces;
|
|
6948
6986
|
var sites;
|
|
@@ -7039,10 +7077,10 @@
|
|
|
7039
7077
|
var s = GRAY_Z / (cosPhi * Math.cos(lam));
|
|
7040
7078
|
var x = cosPhi * Math.sin(lam) * s;
|
|
7041
7079
|
var y = Math.sin(phi) * s;
|
|
7042
|
-
var a1p = Math.atan2(2 * y / SQRT3$
|
|
7043
|
-
var a2p = Math.atan2(x - y / SQRT3$
|
|
7044
|
-
var a3p = Math.atan2(GRAY_EL / 3 - x - y / SQRT3$
|
|
7045
|
-
return [SQRT3$
|
|
7080
|
+
var a1p = Math.atan2(2 * y / SQRT3$2 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
|
|
7081
|
+
var a2p = Math.atan2(x - y / SQRT3$2 + GRAY_EL / 3 - GRAY_EL / 2, GRAY_DVE);
|
|
7082
|
+
var a3p = Math.atan2(GRAY_EL / 3 - x - y / SQRT3$2 - GRAY_EL / 2, GRAY_DVE);
|
|
7083
|
+
return [SQRT3$2 * (a2p - a3p), 2 * a1p - a2p - a3p];
|
|
7046
7084
|
}
|
|
7047
7085
|
|
|
7048
7086
|
function getSphericalCentroid(coords) {
|
|
@@ -7067,16 +7105,16 @@
|
|
|
7067
7105
|
}
|
|
7068
7106
|
|
|
7069
7107
|
function degreesToVector$1(p) {
|
|
7070
|
-
var lam = p[0] * D2R$
|
|
7071
|
-
var phi = p[1] * D2R$
|
|
7108
|
+
var lam = p[0] * D2R$6;
|
|
7109
|
+
var phi = p[1] * D2R$6;
|
|
7072
7110
|
var cosPhi = Math.cos(phi);
|
|
7073
7111
|
return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
|
|
7074
7112
|
}
|
|
7075
7113
|
|
|
7076
7114
|
function vectorToDegrees$1(p) {
|
|
7077
7115
|
return [
|
|
7078
|
-
Math.atan2(p[1], p[0]) * R2D$
|
|
7079
|
-
Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$
|
|
7116
|
+
Math.atan2(p[1], p[0]) * R2D$5,
|
|
7117
|
+
Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$5
|
|
7080
7118
|
];
|
|
7081
7119
|
}
|
|
7082
7120
|
|
|
@@ -7124,8 +7162,8 @@
|
|
|
7124
7162
|
* ISC License: https://github.com/d3/d3-geo-polygon/blob/main/LICENSE
|
|
7125
7163
|
*/
|
|
7126
7164
|
|
|
7127
|
-
var D2R$
|
|
7128
|
-
var R2D$
|
|
7165
|
+
var D2R$5 = Math.PI / 180;
|
|
7166
|
+
var R2D$4 = 180 / Math.PI;
|
|
7129
7167
|
|
|
7130
7168
|
function createCahillKeyesRaw(mg) {
|
|
7131
7169
|
return createCahillKeyesTransform(mg, false);
|
|
@@ -7137,12 +7175,12 @@
|
|
|
7137
7175
|
|
|
7138
7176
|
return function(lambda, phi) {
|
|
7139
7177
|
if (faceOnly) {
|
|
7140
|
-
var lon = lambda * R2D$
|
|
7178
|
+
var lon = lambda * R2D$4;
|
|
7141
7179
|
var side = lon < 0 ? -1 : lon > 0 ? 1 : 0;
|
|
7142
|
-
var local = mp2xy(Math.abs(lon), Math.abs(phi * R2D$
|
|
7180
|
+
var local = mp2xy(Math.abs(lon), Math.abs(phi * R2D$4));
|
|
7143
7181
|
return [local[0], side * local[1]];
|
|
7144
7182
|
}
|
|
7145
|
-
var res = ll2mp(lambda * R2D$
|
|
7183
|
+
var res = ll2mp(lambda * R2D$4, phi * R2D$4);
|
|
7146
7184
|
var xy = mp2xy(res[0], res[1]);
|
|
7147
7185
|
var p = [xy[0], res[2] * xy[1]];
|
|
7148
7186
|
return mj2g(p, res[3]);
|
|
@@ -7160,7 +7198,7 @@
|
|
|
7160
7198
|
CK.cos60 = 0.5;
|
|
7161
7199
|
CK.pointM = [0, 0];
|
|
7162
7200
|
CK.pointG = [CK.lengthMG, 0];
|
|
7163
|
-
pointN = [CK.lengthMG, CK.lengthMG * Math.tan(30 * D2R$
|
|
7201
|
+
pointN = [CK.lengthMG, CK.lengthMG * Math.tan(30 * D2R$5)];
|
|
7164
7202
|
CK.pointA = [CK.lengthMA, 0];
|
|
7165
7203
|
CK.pointB = lineIntersection(CK.pointM, 30, CK.pointA, 45);
|
|
7166
7204
|
CK.lengthAG = distance(CK.pointA, CK.pointG);
|
|
@@ -7171,8 +7209,8 @@
|
|
|
7171
7209
|
CK.pointD = interpolate(lengthMB, lengthMN, pointN, CK.pointM);
|
|
7172
7210
|
CK.pointF = [CK.lengthMG, lengthNG - lengthMB];
|
|
7173
7211
|
CK.pointE = [
|
|
7174
|
-
pointN[0] - CK.lengthMA * Math.sin(30 * D2R$
|
|
7175
|
-
pointN[1] - CK.lengthMA * Math.cos(30 * D2R$
|
|
7212
|
+
pointN[0] - CK.lengthMA * Math.sin(30 * D2R$5),
|
|
7213
|
+
pointN[1] - CK.lengthMA * Math.cos(30 * D2R$5)
|
|
7176
7214
|
];
|
|
7177
7215
|
CK.lengthGF = distance(CK.pointG, CK.pointF);
|
|
7178
7216
|
CK.lengthBD = distance(CK.pointB, CK.pointD);
|
|
@@ -7182,8 +7220,8 @@
|
|
|
7182
7220
|
CK.lengthAP73 = CK.lengthMG - CK.lengthMA -
|
|
7183
7221
|
CK.lengthParallel0to73At0 * 73;
|
|
7184
7222
|
pointU = [
|
|
7185
|
-
CK.pointA[0] + CK.lengthAP73 * Math.cos(30 * D2R$
|
|
7186
|
-
CK.pointA[1] + CK.lengthAP73 * Math.sin(30 * D2R$
|
|
7223
|
+
CK.pointA[0] + CK.lengthAP73 * Math.cos(30 * D2R$5),
|
|
7224
|
+
CK.pointA[1] + CK.lengthAP73 * Math.sin(30 * D2R$5)
|
|
7187
7225
|
];
|
|
7188
7226
|
CK.pointT = lineIntersection(pointU, -60, CK.pointB, 30);
|
|
7189
7227
|
|
|
@@ -7424,8 +7462,8 @@
|
|
|
7424
7462
|
|
|
7425
7463
|
function radialPoint(origin, length, angle) {
|
|
7426
7464
|
return [
|
|
7427
|
-
origin[0] + length * Math.cos(angle * D2R$
|
|
7428
|
-
origin[1] + length * Math.sin(angle * D2R$
|
|
7465
|
+
origin[0] + length * Math.cos(angle * D2R$5),
|
|
7466
|
+
origin[1] + length * Math.sin(angle * D2R$5)
|
|
7429
7467
|
];
|
|
7430
7468
|
}
|
|
7431
7469
|
|
|
@@ -7442,8 +7480,8 @@
|
|
|
7442
7480
|
-xy[0] * CK.sin60 - xy[1] * CK.cos60
|
|
7443
7481
|
];
|
|
7444
7482
|
}
|
|
7445
|
-
var cos = Math.cos(angle * D2R$
|
|
7446
|
-
var sin = Math.sin(angle * D2R$
|
|
7483
|
+
var cos = Math.cos(angle * D2R$5);
|
|
7484
|
+
var sin = Math.sin(angle * D2R$5);
|
|
7447
7485
|
return [xy[0] * cos - xy[1] * sin, xy[0] * sin + xy[1] * cos];
|
|
7448
7486
|
}
|
|
7449
7487
|
}
|
|
@@ -7464,8 +7502,8 @@
|
|
|
7464
7502
|
}
|
|
7465
7503
|
|
|
7466
7504
|
function lineIntersection(p1, slope1, p2, slope2) {
|
|
7467
|
-
var m1 = Math.tan(slope1 * D2R$
|
|
7468
|
-
var m2 = Math.tan(slope2 * D2R$
|
|
7505
|
+
var m1 = Math.tan(slope1 * D2R$5);
|
|
7506
|
+
var m2 = Math.tan(slope2 * D2R$5);
|
|
7469
7507
|
var x = (m1 * p1[0] - m2 * p2[0] - p1[1] + p2[1]) / (m1 - m2);
|
|
7470
7508
|
return [x, m1 * (x - p1[0]) + p1[1]];
|
|
7471
7509
|
}
|
|
@@ -7493,8 +7531,8 @@
|
|
|
7493
7531
|
return n > 0 ? Math.floor(n) : Math.ceil(n);
|
|
7494
7532
|
}
|
|
7495
7533
|
|
|
7496
|
-
var D2R$
|
|
7497
|
-
var EPS$
|
|
7534
|
+
var D2R$4 = Math.PI / 180;
|
|
7535
|
+
var EPS$2 = 1e-12;
|
|
7498
7536
|
|
|
7499
7537
|
// Create a smooth facet projection from any radial azimuthal projection.
|
|
7500
7538
|
// The azimuthal coordinates are warped back to the gnomonic polygon along
|
|
@@ -7504,7 +7542,7 @@
|
|
|
7504
7542
|
var center = options.planarCenter || getSphericalCenter(coords);
|
|
7505
7543
|
var gnomonic = createGnomonicProjector(center);
|
|
7506
7544
|
var planar = coords.map(function(p) {
|
|
7507
|
-
return gnomonic(p[0] * D2R$
|
|
7545
|
+
return gnomonic(p[0] * D2R$4, p[1] * D2R$4);
|
|
7508
7546
|
});
|
|
7509
7547
|
var edges = createNormalizedEdges(planar);
|
|
7510
7548
|
var radial = createRadialFunction(
|
|
@@ -7523,7 +7561,7 @@
|
|
|
7523
7561
|
function project(lam, phi) {
|
|
7524
7562
|
var p = gnomonic(lam, phi);
|
|
7525
7563
|
var r = Math.hypot(p[0], p[1]);
|
|
7526
|
-
if (r < EPS$
|
|
7564
|
+
if (r < EPS$2) return [0, 0];
|
|
7527
7565
|
var c = Math.atan(r);
|
|
7528
7566
|
var azimuthalRadius = radial(c) * radialScale;
|
|
7529
7567
|
var boundaryWeight = getBoundaryWeight(p, edges, boundaryStrength);
|
|
@@ -7613,8 +7651,8 @@
|
|
|
7613
7651
|
|
|
7614
7652
|
function getSphericalCenter(coords) {
|
|
7615
7653
|
var sum = coords.reduce(function(memo, p) {
|
|
7616
|
-
var lam = p[0] * D2R$
|
|
7617
|
-
var phi = p[1] * D2R$
|
|
7654
|
+
var lam = p[0] * D2R$4;
|
|
7655
|
+
var phi = p[1] * D2R$4;
|
|
7618
7656
|
var cosPhi = Math.cos(phi);
|
|
7619
7657
|
memo[0] += Math.cos(lam) * cosPhi;
|
|
7620
7658
|
memo[1] += Math.sin(lam) * cosPhi;
|
|
@@ -7622,8 +7660,8 @@
|
|
|
7622
7660
|
return memo;
|
|
7623
7661
|
}, [0, 0, 0]);
|
|
7624
7662
|
return [
|
|
7625
|
-
Math.atan2(sum[1], sum[0]) / D2R$
|
|
7626
|
-
Math.atan2(sum[2], Math.hypot(sum[0], sum[1])) / D2R$
|
|
7663
|
+
Math.atan2(sum[1], sum[0]) / D2R$4,
|
|
7664
|
+
Math.atan2(sum[2], Math.hypot(sum[0], sum[1])) / D2R$4
|
|
7627
7665
|
];
|
|
7628
7666
|
}
|
|
7629
7667
|
|
|
@@ -7638,8 +7676,8 @@
|
|
|
7638
7676
|
*/
|
|
7639
7677
|
|
|
7640
7678
|
|
|
7641
|
-
var D2R$
|
|
7642
|
-
var R2D$
|
|
7679
|
+
var D2R$3 = Math.PI / 180;
|
|
7680
|
+
var R2D$3 = 180 / Math.PI;
|
|
7643
7681
|
var RADIAL_BOUNDARY_STRENGTH = 1;
|
|
7644
7682
|
var OCTAHEDRON = createOctahedron();
|
|
7645
7683
|
var BUTTERFLY_PARENTS = [-1, 0, 0, 1, 0, 1, 4, 5];
|
|
@@ -7648,7 +7686,7 @@
|
|
|
7648
7686
|
butterfly2: -20,
|
|
7649
7687
|
cahill_keyes: -20
|
|
7650
7688
|
};
|
|
7651
|
-
var engines$
|
|
7689
|
+
var engines$2 = {};
|
|
7652
7690
|
|
|
7653
7691
|
function registerButterflyProjections(mproj) {
|
|
7654
7692
|
if (!mproj) return;
|
|
@@ -7666,22 +7704,22 @@
|
|
|
7666
7704
|
|
|
7667
7705
|
function getButterflyEngine(method) {
|
|
7668
7706
|
var key = method == 'butterfly2' ? 'butterfly' : method;
|
|
7669
|
-
if (!engines$
|
|
7707
|
+
if (!engines$2[key]) {
|
|
7670
7708
|
if (key == 'cahill_keyes') {
|
|
7671
|
-
engines$
|
|
7709
|
+
engines$2[key] = createCahillKeyesEngine();
|
|
7672
7710
|
} else if (key == 'butterfly') {
|
|
7673
|
-
engines$
|
|
7711
|
+
engines$2[key] = createButterflyEngine();
|
|
7674
7712
|
} else {
|
|
7675
7713
|
throw new Error('Unknown butterfly projection: ' + method);
|
|
7676
7714
|
}
|
|
7677
7715
|
}
|
|
7678
|
-
return engines$
|
|
7716
|
+
return engines$2[key];
|
|
7679
7717
|
}
|
|
7680
7718
|
|
|
7681
7719
|
function initButterfly(P, method) {
|
|
7682
7720
|
var engine = getButterflyEngine(method);
|
|
7683
7721
|
if (!P.params.lon_0) {
|
|
7684
|
-
P.lam0 = DEFAULT_LON0[method] * D2R$
|
|
7722
|
+
P.lam0 = DEFAULT_LON0[method] * D2R$3;
|
|
7685
7723
|
}
|
|
7686
7724
|
P.es = 0;
|
|
7687
7725
|
P.inv = null;
|
|
@@ -7694,7 +7732,7 @@
|
|
|
7694
7732
|
xy.y = p[1];
|
|
7695
7733
|
}
|
|
7696
7734
|
};
|
|
7697
|
-
P.__projection_topology = engine.getTopology(P.lam0 * R2D$
|
|
7735
|
+
P.__projection_topology = engine.getTopology(P.lam0 * R2D$3);
|
|
7698
7736
|
if (engine.removeOutlineExtremeConnectors) {
|
|
7699
7737
|
P.__remove_outline_extreme_connectors = true;
|
|
7700
7738
|
}
|
|
@@ -7708,8 +7746,8 @@
|
|
|
7708
7746
|
// Reuse the Cahill-Keyes polar incisions and 12-zone octant transform,
|
|
7709
7747
|
// then unfold the faces with the butterfly attachment tree.
|
|
7710
7748
|
var data = createTruncatedOctahedronFaces(
|
|
7711
|
-
Math.cos(17 * D2R$
|
|
7712
|
-
Math.sin(17 * D2R$
|
|
7749
|
+
Math.cos(17 * D2R$3),
|
|
7750
|
+
Math.sin(17 * D2R$3),
|
|
7713
7751
|
BUTTERFLY_PARENTS
|
|
7714
7752
|
);
|
|
7715
7753
|
var faceRaw = createCahillKeyesFaceRaw(10000);
|
|
@@ -7722,7 +7760,7 @@
|
|
|
7722
7760
|
findFace: createTruncatedFaceFinder(data.cornerNormals),
|
|
7723
7761
|
faceProjector: function(face) {
|
|
7724
7762
|
var baseId = face.id < 8 ? face.id : data.parents[face.id];
|
|
7725
|
-
var center = faceCenters[baseId] * D2R$
|
|
7763
|
+
var center = faceCenters[baseId] * D2R$3;
|
|
7726
7764
|
var raw = function(lam, phi) {
|
|
7727
7765
|
return faceRaw(normalizeRadians$1(lam - center), phi);
|
|
7728
7766
|
};
|
|
@@ -7737,7 +7775,7 @@
|
|
|
7737
7775
|
// Remove the global placement and scale of a raw facet while preserving its
|
|
7738
7776
|
// internal shape. The polyhedral engine then controls how facets unfold.
|
|
7739
7777
|
var points = coords.map(function(p) {
|
|
7740
|
-
return raw(p[0] * D2R$
|
|
7778
|
+
return raw(p[0] * D2R$3, p[1] * D2R$3);
|
|
7741
7779
|
});
|
|
7742
7780
|
var edge = 0;
|
|
7743
7781
|
var maxLengthSq = -1;
|
|
@@ -7826,8 +7864,8 @@
|
|
|
7826
7864
|
|
|
7827
7865
|
function createCahillKeyesEngine() {
|
|
7828
7866
|
var data = createTruncatedOctahedronFaces(
|
|
7829
|
-
Math.cos(17 * D2R$
|
|
7830
|
-
Math.sin(17 * D2R$
|
|
7867
|
+
Math.cos(17 * D2R$3),
|
|
7868
|
+
Math.sin(17 * D2R$3),
|
|
7831
7869
|
[-1, 3, 0, 2, 0, 1, 4, 5]
|
|
7832
7870
|
);
|
|
7833
7871
|
var raw = createCahillKeyesRaw(10000);
|
|
@@ -7972,7 +8010,7 @@
|
|
|
7972
8010
|
}
|
|
7973
8011
|
|
|
7974
8012
|
function planarAngle(p, project) {
|
|
7975
|
-
var q = project(p[0] * D2R$
|
|
8013
|
+
var q = project(p[0] * D2R$3, p[1] * D2R$3);
|
|
7976
8014
|
return Math.atan2(q[1], q[0]);
|
|
7977
8015
|
}
|
|
7978
8016
|
|
|
@@ -8006,16 +8044,16 @@
|
|
|
8006
8044
|
}
|
|
8007
8045
|
|
|
8008
8046
|
function degreesToVector(p) {
|
|
8009
|
-
var lam = p[0] * D2R$
|
|
8010
|
-
var phi = p[1] * D2R$
|
|
8047
|
+
var lam = p[0] * D2R$3;
|
|
8048
|
+
var phi = p[1] * D2R$3;
|
|
8011
8049
|
var cosPhi = Math.cos(phi);
|
|
8012
8050
|
return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
|
|
8013
8051
|
}
|
|
8014
8052
|
|
|
8015
8053
|
function vectorToDegrees(p) {
|
|
8016
8054
|
return [
|
|
8017
|
-
Math.atan2(p[1], p[0]) * R2D$
|
|
8018
|
-
Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$
|
|
8055
|
+
Math.atan2(p[1], p[0]) * R2D$3,
|
|
8056
|
+
Math.asin(Math.max(-1, Math.min(1, p[2]))) * R2D$3
|
|
8019
8057
|
];
|
|
8020
8058
|
}
|
|
8021
8059
|
|
|
@@ -8068,21 +8106,21 @@
|
|
|
8068
8106
|
* equations, not Imago's power-law approximation.
|
|
8069
8107
|
*/
|
|
8070
8108
|
|
|
8071
|
-
var D2R$
|
|
8072
|
-
var R2D$
|
|
8109
|
+
var D2R$2 = Math.PI / 180;
|
|
8110
|
+
var R2D$2 = 180 / Math.PI;
|
|
8073
8111
|
var HALF_PI = Math.PI / 2;
|
|
8074
|
-
var SQRT2 = Math.sqrt(2);
|
|
8075
|
-
var SQRT3 = Math.sqrt(3);
|
|
8076
|
-
var ASIN_ONE_THIRD = Math.asin(1 / 3);
|
|
8112
|
+
var SQRT2$1 = Math.sqrt(2);
|
|
8113
|
+
var SQRT3$1 = Math.sqrt(3);
|
|
8114
|
+
var ASIN_ONE_THIRD$1 = Math.asin(1 / 3);
|
|
8077
8115
|
var EDGE_SCALE = Math.acos(-1 / 3) / 2;
|
|
8078
|
-
var XMIN = -2 * SQRT3;
|
|
8079
|
-
var XMAX = 2 * SQRT3;
|
|
8116
|
+
var XMIN = -2 * SQRT3$1;
|
|
8117
|
+
var XMAX = 2 * SQRT3$1;
|
|
8080
8118
|
var YMIN = -1.5;
|
|
8081
8119
|
var YMAX = 1.5;
|
|
8082
|
-
var BLOCK_HEIGHT = 2 * SQRT3;
|
|
8120
|
+
var BLOCK_HEIGHT = 2 * SQRT3$1;
|
|
8083
8121
|
var LAYOUT_SHIFT = 1.16;
|
|
8084
|
-
var EPS = 1e-12;
|
|
8085
|
-
var engines = {};
|
|
8122
|
+
var EPS$1 = 1e-12;
|
|
8123
|
+
var engines$1 = {};
|
|
8086
8124
|
|
|
8087
8125
|
// The four tetrahedron vertices published by Narukawa, in latitude-longitude
|
|
8088
8126
|
// order. The extra precision preserves the regular tetrahedron to about 1e-9
|
|
@@ -8097,10 +8135,10 @@
|
|
|
8097
8135
|
// D3 Imago's vertex-oriented tetrahedral block. Each entry contains the
|
|
8098
8136
|
// spherical center, local meridian, planar rotation and planar center.
|
|
8099
8137
|
var FACET_DEFS = [
|
|
8100
|
-
[0, SQRT3, HALF_PI, 0, 0, -HALF_PI],
|
|
8101
|
-
[0, -SQRT3, -ASIN_ONE_THIRD, 0, Math.PI, HALF_PI],
|
|
8102
|
-
[3, 0, -ASIN_ONE_THIRD, 2 * Math.PI / 3, Math.PI, 5 * Math.PI / 6],
|
|
8103
|
-
[-3, 0, -ASIN_ONE_THIRD, -2 * Math.PI / 3, Math.PI, Math.PI / 6]
|
|
8138
|
+
[0, SQRT3$1, HALF_PI, 0, 0, -HALF_PI],
|
|
8139
|
+
[0, -SQRT3$1, -ASIN_ONE_THIRD$1, 0, Math.PI, HALF_PI],
|
|
8140
|
+
[3, 0, -ASIN_ONE_THIRD$1, 2 * Math.PI / 3, Math.PI, 5 * Math.PI / 6],
|
|
8141
|
+
[-3, 0, -ASIN_ONE_THIRD$1, -2 * Math.PI / 3, Math.PI, Math.PI / 6]
|
|
8104
8142
|
];
|
|
8105
8143
|
|
|
8106
8144
|
function registerNarukawa2022Projection(mproj) {
|
|
@@ -8111,10 +8149,10 @@
|
|
|
8111
8149
|
}
|
|
8112
8150
|
|
|
8113
8151
|
function getNarukawa2022Engine() {
|
|
8114
|
-
if (!engines.default) {
|
|
8115
|
-
engines.default = createNarukawa2022Engine();
|
|
8152
|
+
if (!engines$1.default) {
|
|
8153
|
+
engines$1.default = createNarukawa2022Engine();
|
|
8116
8154
|
}
|
|
8117
|
-
return engines.default;
|
|
8155
|
+
return engines$1.default;
|
|
8118
8156
|
}
|
|
8119
8157
|
|
|
8120
8158
|
function initNarukawa2022(P) {
|
|
@@ -8126,7 +8164,7 @@
|
|
|
8126
8164
|
xy.x = p[0];
|
|
8127
8165
|
xy.y = p[1];
|
|
8128
8166
|
};
|
|
8129
|
-
P.__projection_topology = engine.getTopology(P.lam0 * R2D$
|
|
8167
|
+
P.__projection_topology = engine.getTopology(P.lam0 * R2D$2);
|
|
8130
8168
|
P.__projected_outline = engine.outline;
|
|
8131
8169
|
}
|
|
8132
8170
|
|
|
@@ -8143,6 +8181,13 @@
|
|
|
8143
8181
|
rotation: def[5]
|
|
8144
8182
|
};
|
|
8145
8183
|
});
|
|
8184
|
+
var rasterSectors = facets.reduce(function(memo, facet) {
|
|
8185
|
+
return memo.concat(getRawFacetSectorBoundaries(facets, facet));
|
|
8186
|
+
}, []);
|
|
8187
|
+
var rasterPieces = createNarukawaRasterPieces(facets, rasterSectors);
|
|
8188
|
+
var rasterPieceIndex = new Map(rasterPieces.map(function(piece) {
|
|
8189
|
+
return [piece.key, piece.id];
|
|
8190
|
+
}));
|
|
8146
8191
|
var outline = [[
|
|
8147
8192
|
[XMIN * EDGE_SCALE, YMIN * EDGE_SCALE],
|
|
8148
8193
|
[XMAX * EDGE_SCALE, YMIN * EDGE_SCALE],
|
|
@@ -8155,6 +8200,7 @@
|
|
|
8155
8200
|
forward: forward,
|
|
8156
8201
|
inverse: inverse,
|
|
8157
8202
|
outline: outline,
|
|
8203
|
+
rasterPieces: rasterPieces,
|
|
8158
8204
|
getTopology: getTopology
|
|
8159
8205
|
};
|
|
8160
8206
|
|
|
@@ -8188,6 +8234,41 @@
|
|
|
8188
8234
|
}],
|
|
8189
8235
|
findRegion: findRegion,
|
|
8190
8236
|
findTransitionRegion: findRegion,
|
|
8237
|
+
raster_regions: rasterPieces.map(function(piece) {
|
|
8238
|
+
return {
|
|
8239
|
+
id: piece.id,
|
|
8240
|
+
facet: piece.facet,
|
|
8241
|
+
sector: piece.sector,
|
|
8242
|
+
source_region: piece.facet * 3 + piece.sector,
|
|
8243
|
+
projected_boundary: piece.boundary.map(function(p) {
|
|
8244
|
+
return [p[0] * EDGE_SCALE, p[1] * EDGE_SCALE];
|
|
8245
|
+
})
|
|
8246
|
+
};
|
|
8247
|
+
}),
|
|
8248
|
+
raster_source_regions: rasterSectors.map(function(sector) {
|
|
8249
|
+
return {
|
|
8250
|
+
id: sector.facet * 3 + sector.sector,
|
|
8251
|
+
source_region: sector.facet * 3 + sector.sector,
|
|
8252
|
+
facet: sector.facet,
|
|
8253
|
+
sector: sector.sector,
|
|
8254
|
+
boundary: sector.sphericalBoundary.map(function(p) {
|
|
8255
|
+
var q = fromCanonical(p[0], p[1], orientation);
|
|
8256
|
+
return [
|
|
8257
|
+
normalizeLongitude$2(q[0] * R2D$2 + lon0),
|
|
8258
|
+
q[1] * R2D$2
|
|
8259
|
+
];
|
|
8260
|
+
})
|
|
8261
|
+
};
|
|
8262
|
+
}),
|
|
8263
|
+
raster_mesh_interval: 32,
|
|
8264
|
+
raster_cell_halo: false,
|
|
8265
|
+
fill_raster_mask: true,
|
|
8266
|
+
fill_raster_coverage: true,
|
|
8267
|
+
findRasterRegion: findRasterRegion,
|
|
8268
|
+
projectRasterRegion: projectRasterRegion,
|
|
8269
|
+
projectRasterSourceRegion: projectRasterSourceRegion,
|
|
8270
|
+
projectRasterSector: projectRasterSector,
|
|
8271
|
+
clipRasterRegionPolygon: clipRasterRegionPolygon,
|
|
8191
8272
|
outline: outline.map(function(ring) {
|
|
8192
8273
|
return ring.map(function(p) {
|
|
8193
8274
|
return p.concat();
|
|
@@ -8196,30 +8277,422 @@
|
|
|
8196
8277
|
};
|
|
8197
8278
|
|
|
8198
8279
|
function findRegion(lon, lat) {
|
|
8199
|
-
var lam = normalizeRadians((lon - lon0) * D2R$
|
|
8200
|
-
return projectState(lam, lat * D2R$
|
|
8280
|
+
var lam = normalizeRadians((lon - lon0) * D2R$2);
|
|
8281
|
+
return projectState(lam, lat * D2R$2).region;
|
|
8201
8282
|
}
|
|
8283
|
+
|
|
8284
|
+
function findRasterRegion(lon, lat) {
|
|
8285
|
+
var lam = normalizeRadians((lon - lon0) * D2R$2);
|
|
8286
|
+
var p = toCanonical(lam, lat * D2R$2, orientation);
|
|
8287
|
+
var facet = findForwardFacet(p[0], p[1], facets);
|
|
8288
|
+
var state = applyConditionalLayout(projectFacetRaw(p[0], p[1], facet), facet);
|
|
8289
|
+
return rasterPieceIndex.get(getRasterPieceKey(
|
|
8290
|
+
state.facet, state.sector, state.oobKey, state.folded, state.wrap
|
|
8291
|
+
));
|
|
8292
|
+
}
|
|
8293
|
+
|
|
8294
|
+
function projectRasterRegion(lon, lat, regionId) {
|
|
8295
|
+
var piece = rasterPieces[regionId];
|
|
8296
|
+
var lam = normalizeRadians((lon - lon0) * D2R$2);
|
|
8297
|
+
var p = toCanonical(lam, lat * D2R$2, orientation);
|
|
8298
|
+
var facet = facets[piece.facet];
|
|
8299
|
+
var raw = projectFacetRaw(p[0], p[1], facet, piece.sector);
|
|
8300
|
+
var q = applyRasterPieceLayout(raw, facet, piece);
|
|
8301
|
+
return [q[0] * EDGE_SCALE, q[1] * EDGE_SCALE];
|
|
8302
|
+
}
|
|
8303
|
+
|
|
8304
|
+
function projectRasterSector(lon, lat, facetId, sector) {
|
|
8305
|
+
var lam = normalizeRadians((lon - lon0) * D2R$2);
|
|
8306
|
+
var p = toCanonical(lam, lat * D2R$2, orientation);
|
|
8307
|
+
var raw = projectFacetRaw(p[0], p[1], facets[facetId], sector);
|
|
8308
|
+
return [raw.x, raw.y];
|
|
8309
|
+
}
|
|
8310
|
+
|
|
8311
|
+
function projectRasterSourceRegion(lon, lat, sourceRegionId) {
|
|
8312
|
+
return projectRasterSector(
|
|
8313
|
+
lon, lat, Math.floor(sourceRegionId / 3), sourceRegionId % 3);
|
|
8314
|
+
}
|
|
8315
|
+
|
|
8316
|
+
function clipRasterRegionPolygon(vertices, regionId) {
|
|
8317
|
+
return clipRasterPiecePolygon(
|
|
8318
|
+
vertices, facets[rasterPieces[regionId].facet],
|
|
8319
|
+
rasterPieces[regionId]);
|
|
8320
|
+
}
|
|
8321
|
+
}
|
|
8322
|
+
}
|
|
8323
|
+
|
|
8324
|
+
function createNarukawaRasterPieces(facets, rasterSectors) {
|
|
8325
|
+
var pieces = [];
|
|
8326
|
+
facets.forEach(function(facet) {
|
|
8327
|
+
rasterSectors.filter(function(o) {
|
|
8328
|
+
return o.facet == facet.id;
|
|
8329
|
+
}).forEach(function(sectorData) {
|
|
8330
|
+
['normal', 'xpos', 'xneg', 'ypos', 'yneg'].forEach(function(oobKey) {
|
|
8331
|
+
var oobPolygon = clipOobPolygon(sectorData.boundary, oobKey);
|
|
8332
|
+
if (oobPolygon.length < 3) return;
|
|
8333
|
+
oobPolygon = oobPolygon.map(function(p) {
|
|
8334
|
+
return applyOobTransform(p, facet, oobKey);
|
|
8335
|
+
});
|
|
8336
|
+
[0, 1].forEach(function(folded) {
|
|
8337
|
+
var foldedPolygon = clipPolygonAxis$1(oobPolygon, 0, 0, folded == 0);
|
|
8338
|
+
if (foldedPolygon.length < 3) return;
|
|
8339
|
+
foldedPolygon = foldedPolygon.map(function(p) {
|
|
8340
|
+
return applyFoldTransform(p, folded);
|
|
8341
|
+
});
|
|
8342
|
+
[0, 1].forEach(function(wrap) {
|
|
8343
|
+
var finalPolygon = foldedPolygon.map(function(p) {
|
|
8344
|
+
return [
|
|
8345
|
+
p[0] + LAYOUT_SHIFT + wrap * 2 * BLOCK_HEIGHT - BLOCK_HEIGHT,
|
|
8346
|
+
p[1] + 1.5
|
|
8347
|
+
];
|
|
8348
|
+
});
|
|
8349
|
+
finalPolygon = clipRectangle(
|
|
8350
|
+
finalPolygon, XMIN, YMIN, XMAX, YMAX);
|
|
8351
|
+
if (finalPolygon.length < 3 ||
|
|
8352
|
+
Math.abs(getPlanarRingArea(finalPolygon)) < EPS$1) return;
|
|
8353
|
+
var id = pieces.length;
|
|
8354
|
+
pieces.push({
|
|
8355
|
+
id: id,
|
|
8356
|
+
key: getRasterPieceKey(
|
|
8357
|
+
facet.id, sectorData.sector, oobKey, folded, wrap),
|
|
8358
|
+
facet: facet.id,
|
|
8359
|
+
sector: sectorData.sector,
|
|
8360
|
+
oobKey: oobKey,
|
|
8361
|
+
folded: folded,
|
|
8362
|
+
wrap: wrap,
|
|
8363
|
+
boundary: finalPolygon.concat([finalPolygon[0].concat()])
|
|
8364
|
+
});
|
|
8365
|
+
});
|
|
8366
|
+
});
|
|
8367
|
+
});
|
|
8368
|
+
});
|
|
8369
|
+
});
|
|
8370
|
+
return pieces;
|
|
8371
|
+
}
|
|
8372
|
+
|
|
8373
|
+
function getRawFacetSectorBoundaries(facets, facet) {
|
|
8374
|
+
var corners = facets.filter(function(o) {
|
|
8375
|
+
return o.id != facet.id;
|
|
8376
|
+
}).map(function(o) {
|
|
8377
|
+
var v = radiansToVector(o.lon, o.lat);
|
|
8378
|
+
return vectorToRadians([-v[0], -v[1], -v[2]]);
|
|
8379
|
+
});
|
|
8380
|
+
corners.sort(function(a, b) {
|
|
8381
|
+
return obliquifySpherical(a[1], a[0], facet)[1] -
|
|
8382
|
+
obliquifySpherical(b[1], b[0], facet)[1];
|
|
8383
|
+
});
|
|
8384
|
+
var samples = [];
|
|
8385
|
+
for (var i = 0; i < corners.length; i++) {
|
|
8386
|
+
var edge = interpolateSphericalRadians(
|
|
8387
|
+
corners[i], corners[(i + 1) % corners.length], 0.05 * D2R$2);
|
|
8388
|
+
for (var j = 0; j < edge.length - 1; j++) {
|
|
8389
|
+
var p = edge[j];
|
|
8390
|
+
var q = projectFacetRaw(p[0], p[1], facet);
|
|
8391
|
+
samples.push({
|
|
8392
|
+
sector: q.sector,
|
|
8393
|
+
point: [q.x, q.y],
|
|
8394
|
+
spherical: p.concat()
|
|
8395
|
+
});
|
|
8396
|
+
}
|
|
8397
|
+
}
|
|
8398
|
+
return [0, 1, 2].map(function(sector) {
|
|
8399
|
+
var run = getLongestCircularSectorRun(samples, sector);
|
|
8400
|
+
var middle = getFarthestSphericalSample(
|
|
8401
|
+
run, [facet.lon, facet.lat]);
|
|
8402
|
+
return {
|
|
8403
|
+
facet: facet.id,
|
|
8404
|
+
sector: sector,
|
|
8405
|
+
sphericalBoundary: [
|
|
8406
|
+
[facet.lon, facet.lat],
|
|
8407
|
+
run[0].spherical,
|
|
8408
|
+
middle.spherical,
|
|
8409
|
+
run[run.length - 1].spherical,
|
|
8410
|
+
[facet.lon, facet.lat]
|
|
8411
|
+
],
|
|
8412
|
+
boundary: [[facet.x, facet.y]].concat(run.map(function(o) {
|
|
8413
|
+
return o.point;
|
|
8414
|
+
}))
|
|
8415
|
+
};
|
|
8416
|
+
});
|
|
8417
|
+
}
|
|
8418
|
+
|
|
8419
|
+
function getFarthestSphericalSample(samples, center) {
|
|
8420
|
+
var centerVector = radiansToVector(center[0], center[1]);
|
|
8421
|
+
var best = samples[0];
|
|
8422
|
+
var minDot = Infinity;
|
|
8423
|
+
samples.forEach(function(sample) {
|
|
8424
|
+
var v = radiansToVector(sample.spherical[0], sample.spherical[1]);
|
|
8425
|
+
var d = dot$1(centerVector, v);
|
|
8426
|
+
if (d < minDot) {
|
|
8427
|
+
minDot = d;
|
|
8428
|
+
best = sample;
|
|
8429
|
+
}
|
|
8430
|
+
});
|
|
8431
|
+
return best;
|
|
8432
|
+
}
|
|
8433
|
+
|
|
8434
|
+
function getLongestCircularSectorRun(samples, sector) {
|
|
8435
|
+
var runs = [];
|
|
8436
|
+
var run = [];
|
|
8437
|
+
for (var i = 0; i < samples.length * 2; i++) {
|
|
8438
|
+
var sample = samples[i % samples.length];
|
|
8439
|
+
if (sample.sector == sector) {
|
|
8440
|
+
run.push(sample);
|
|
8441
|
+
} else if (run.length) {
|
|
8442
|
+
runs.push(run);
|
|
8443
|
+
run = [];
|
|
8444
|
+
}
|
|
8445
|
+
}
|
|
8446
|
+
if (run.length) runs.push(run);
|
|
8447
|
+
runs.sort(function(a, b) { return b.length - a.length; });
|
|
8448
|
+
run = runs[0] || [];
|
|
8449
|
+
if (run.length > samples.length) run = run.slice(0, samples.length);
|
|
8450
|
+
return run;
|
|
8451
|
+
}
|
|
8452
|
+
|
|
8453
|
+
function applyRasterPieceLayout(raw, facet, piece) {
|
|
8454
|
+
var p = applyOobTransform([raw.x, raw.y], facet, piece.oobKey);
|
|
8455
|
+
p = applyFoldTransform(p, piece.folded);
|
|
8456
|
+
return [
|
|
8457
|
+
p[0] + LAYOUT_SHIFT + piece.wrap * 2 * BLOCK_HEIGHT - BLOCK_HEIGHT,
|
|
8458
|
+
p[1] + 1.5
|
|
8459
|
+
];
|
|
8460
|
+
}
|
|
8461
|
+
|
|
8462
|
+
function clipRasterPiecePolygon(vertices, facet, piece) {
|
|
8463
|
+
var polygon = clipRasterOobPolygon(vertices, piece.oobKey);
|
|
8464
|
+
polygon = polygon.map(function(vertex) {
|
|
8465
|
+
var p = applyOobTransform([vertex.x, vertex.y], facet, piece.oobKey);
|
|
8466
|
+
return copyRasterVertex$1(vertex, p[0], p[1]);
|
|
8467
|
+
});
|
|
8468
|
+
polygon = clipRasterPolygonAxis$1(
|
|
8469
|
+
polygon, 'x', 0, piece.folded == 0);
|
|
8470
|
+
polygon = polygon.map(function(vertex) {
|
|
8471
|
+
var p = applyFoldTransform([vertex.x, vertex.y], piece.folded);
|
|
8472
|
+
return copyRasterVertex$1(vertex, p[0], p[1]);
|
|
8473
|
+
});
|
|
8474
|
+
polygon = polygon.map(function(vertex) {
|
|
8475
|
+
return copyRasterVertex$1(
|
|
8476
|
+
vertex,
|
|
8477
|
+
vertex.x + LAYOUT_SHIFT +
|
|
8478
|
+
piece.wrap * 2 * BLOCK_HEIGHT - BLOCK_HEIGHT,
|
|
8479
|
+
vertex.y + 1.5
|
|
8480
|
+
);
|
|
8481
|
+
});
|
|
8482
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'x', XMIN, true);
|
|
8483
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'x', XMAX, false);
|
|
8484
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'y', YMIN, true);
|
|
8485
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'y', YMAX, false);
|
|
8486
|
+
polygon.forEach(function(vertex) {
|
|
8487
|
+
vertex.x *= EDGE_SCALE;
|
|
8488
|
+
vertex.y *= EDGE_SCALE;
|
|
8489
|
+
});
|
|
8490
|
+
return polygon;
|
|
8491
|
+
}
|
|
8492
|
+
|
|
8493
|
+
function clipRasterOobPolygon(polygon, oobKey) {
|
|
8494
|
+
if (oobKey == 'xpos') {
|
|
8495
|
+
return clipRasterPolygonAxis$1(polygon, 'x', 3, true);
|
|
8496
|
+
}
|
|
8497
|
+
if (oobKey == 'xneg') {
|
|
8498
|
+
return clipRasterPolygonAxis$1(polygon, 'x', -3, false);
|
|
8499
|
+
}
|
|
8500
|
+
if (oobKey == 'ypos' || oobKey == 'yneg') {
|
|
8501
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'x', -3, true);
|
|
8502
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'x', 3, false);
|
|
8503
|
+
return clipRasterPolygonAxis$1(
|
|
8504
|
+
polygon, 'y', oobKey == 'ypos' ? SQRT3$1 : -SQRT3$1,
|
|
8505
|
+
oobKey == 'ypos');
|
|
8202
8506
|
}
|
|
8507
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'x', -3, true);
|
|
8508
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'x', 3, false);
|
|
8509
|
+
polygon = clipRasterPolygonAxis$1(polygon, 'y', -SQRT3$1, true);
|
|
8510
|
+
return clipRasterPolygonAxis$1(polygon, 'y', SQRT3$1, false);
|
|
8511
|
+
}
|
|
8512
|
+
|
|
8513
|
+
function clipRasterPolygonAxis$1(polygon, axis, value, keepGreater) {
|
|
8514
|
+
var output = [];
|
|
8515
|
+
if (polygon.length === 0) return output;
|
|
8516
|
+
var a = polygon[polygon.length - 1];
|
|
8517
|
+
var aInside = keepGreater ?
|
|
8518
|
+
a[axis] >= value - EPS$1 : a[axis] <= value + EPS$1;
|
|
8519
|
+
polygon.forEach(function(b) {
|
|
8520
|
+
var bInside = keepGreater ?
|
|
8521
|
+
b[axis] >= value - EPS$1 : b[axis] <= value + EPS$1;
|
|
8522
|
+
if (aInside != bInside) {
|
|
8523
|
+
var t = (value - a[axis]) / (b[axis] - a[axis]);
|
|
8524
|
+
var vertex = {
|
|
8525
|
+
x: a.x + (b.x - a.x) * t,
|
|
8526
|
+
y: a.y + (b.y - a.y) * t,
|
|
8527
|
+
sx: a.sx + (b.sx - a.sx) * t,
|
|
8528
|
+
sy: a.sy + (b.sy - a.sy) * t,
|
|
8529
|
+
lon: a.lon + (b.lon - a.lon) * t,
|
|
8530
|
+
lat: a.lat + (b.lat - a.lat) * t
|
|
8531
|
+
};
|
|
8532
|
+
vertex[axis] = value;
|
|
8533
|
+
output.push(vertex);
|
|
8534
|
+
}
|
|
8535
|
+
if (bInside) output.push(copyRasterVertex$1(b, b.x, b.y));
|
|
8536
|
+
a = b;
|
|
8537
|
+
aInside = bInside;
|
|
8538
|
+
});
|
|
8539
|
+
return output;
|
|
8540
|
+
}
|
|
8541
|
+
|
|
8542
|
+
function copyRasterVertex$1(vertex, x, y) {
|
|
8543
|
+
return {
|
|
8544
|
+
x: x,
|
|
8545
|
+
y: y,
|
|
8546
|
+
sx: vertex.sx,
|
|
8547
|
+
sy: vertex.sy,
|
|
8548
|
+
lon: vertex.lon,
|
|
8549
|
+
lat: vertex.lat
|
|
8550
|
+
};
|
|
8551
|
+
}
|
|
8552
|
+
|
|
8553
|
+
function applyOobTransform(p, facet, oobKey) {
|
|
8554
|
+
if (oobKey == 'xpos' || oobKey == 'xneg') {
|
|
8555
|
+
return [2 * facet.x - p[0], -p[1]];
|
|
8556
|
+
}
|
|
8557
|
+
if (oobKey == 'ypos') {
|
|
8558
|
+
return [-p[0], BLOCK_HEIGHT - p[1]];
|
|
8559
|
+
}
|
|
8560
|
+
if (oobKey == 'yneg') {
|
|
8561
|
+
return [-p[0], -BLOCK_HEIGHT - p[1]];
|
|
8562
|
+
}
|
|
8563
|
+
return p.concat();
|
|
8564
|
+
}
|
|
8565
|
+
|
|
8566
|
+
function applyFoldTransform(p, folded) {
|
|
8567
|
+
return folded ? [BLOCK_HEIGHT - p[1], p[0]] : [p[1], -p[0]];
|
|
8568
|
+
}
|
|
8569
|
+
|
|
8570
|
+
function clipOobPolygon(polygon, oobKey) {
|
|
8571
|
+
if (oobKey == 'xpos') return clipPolygonAxis$1(polygon, 0, 3, true);
|
|
8572
|
+
if (oobKey == 'xneg') return clipPolygonAxis$1(polygon, 0, -3, false);
|
|
8573
|
+
if (oobKey == 'ypos') {
|
|
8574
|
+
return clipPolygonAxis$1(
|
|
8575
|
+
clipPolygonAxis$1(
|
|
8576
|
+
clipPolygonAxis$1(polygon, 0, -3, true), 0, 3, false),
|
|
8577
|
+
1, SQRT3$1, true);
|
|
8578
|
+
}
|
|
8579
|
+
if (oobKey == 'yneg') {
|
|
8580
|
+
return clipPolygonAxis$1(
|
|
8581
|
+
clipPolygonAxis$1(
|
|
8582
|
+
clipPolygonAxis$1(polygon, 0, -3, true), 0, 3, false),
|
|
8583
|
+
1, -SQRT3$1, false);
|
|
8584
|
+
}
|
|
8585
|
+
return clipRectangle(polygon, -3, -SQRT3$1, 3, SQRT3$1);
|
|
8586
|
+
}
|
|
8587
|
+
|
|
8588
|
+
function clipRectangle(polygon, xmin, ymin, xmax, ymax) {
|
|
8589
|
+
polygon = clipPolygonAxis$1(polygon, 0, xmin, true);
|
|
8590
|
+
polygon = clipPolygonAxis$1(polygon, 0, xmax, false);
|
|
8591
|
+
polygon = clipPolygonAxis$1(polygon, 1, ymin, true);
|
|
8592
|
+
return clipPolygonAxis$1(polygon, 1, ymax, false);
|
|
8593
|
+
}
|
|
8594
|
+
|
|
8595
|
+
function clipPolygonAxis$1(polygon, axis, value, keepGreater) {
|
|
8596
|
+
var output = [];
|
|
8597
|
+
if (polygon.length === 0) return output;
|
|
8598
|
+
var a = polygon[polygon.length - 1];
|
|
8599
|
+
var aInside = keepGreater ? a[axis] >= value - EPS$1 : a[axis] <= value + EPS$1;
|
|
8600
|
+
polygon.forEach(function(b) {
|
|
8601
|
+
var bInside = keepGreater ? b[axis] >= value - EPS$1 : b[axis] <= value + EPS$1;
|
|
8602
|
+
if (aInside != bInside) {
|
|
8603
|
+
var t = (value - a[axis]) / (b[axis] - a[axis]);
|
|
8604
|
+
var p = [
|
|
8605
|
+
a[0] + (b[0] - a[0]) * t,
|
|
8606
|
+
a[1] + (b[1] - a[1]) * t
|
|
8607
|
+
];
|
|
8608
|
+
p[axis] = value;
|
|
8609
|
+
output.push(p);
|
|
8610
|
+
}
|
|
8611
|
+
if (bInside) output.push(b.concat());
|
|
8612
|
+
a = b;
|
|
8613
|
+
aInside = bInside;
|
|
8614
|
+
});
|
|
8615
|
+
return output;
|
|
8616
|
+
}
|
|
8617
|
+
|
|
8618
|
+
function interpolateSphericalRadians(a, b, interval) {
|
|
8619
|
+
var av = radiansToVector(a[0], a[1]);
|
|
8620
|
+
var bv = radiansToVector(b[0], b[1]);
|
|
8621
|
+
var angle = Math.acos(clamp$2(dot$1(av, bv), -1, 1));
|
|
8622
|
+
var count = Math.max(1, Math.ceil(angle / interval));
|
|
8623
|
+
var sinAngle = Math.sin(angle);
|
|
8624
|
+
var points = [];
|
|
8625
|
+
for (var i = 0; i <= count; i++) {
|
|
8626
|
+
var t = i / count;
|
|
8627
|
+
var ka = Math.sin((1 - t) * angle) / sinAngle;
|
|
8628
|
+
var kb = Math.sin(t * angle) / sinAngle;
|
|
8629
|
+
points.push(vectorToRadians(normalizeVector([
|
|
8630
|
+
av[0] * ka + bv[0] * kb,
|
|
8631
|
+
av[1] * ka + bv[1] * kb,
|
|
8632
|
+
av[2] * ka + bv[2] * kb
|
|
8633
|
+
])));
|
|
8634
|
+
}
|
|
8635
|
+
return points;
|
|
8636
|
+
}
|
|
8637
|
+
|
|
8638
|
+
function vectorToRadians(p) {
|
|
8639
|
+
return [
|
|
8640
|
+
Math.atan2(p[1], p[0]),
|
|
8641
|
+
Math.asin(clamp$2(p[2], -1, 1))
|
|
8642
|
+
];
|
|
8643
|
+
}
|
|
8644
|
+
|
|
8645
|
+
function getPlanarRingArea(ring) {
|
|
8646
|
+
var area = 0;
|
|
8647
|
+
for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
8648
|
+
area += ring[j][0] * ring[i][1] - ring[i][0] * ring[j][1];
|
|
8649
|
+
}
|
|
8650
|
+
return area / 2;
|
|
8651
|
+
}
|
|
8652
|
+
|
|
8653
|
+
function getRasterPieceKey(facet, sector, oobKey, folded, wrap) {
|
|
8654
|
+
return [facet, sector, oobKey, folded, wrap].join(':');
|
|
8203
8655
|
}
|
|
8204
8656
|
|
|
8205
8657
|
function projectCanonical(lam, phi, facets) {
|
|
8206
8658
|
var facet = findForwardFacet(lam, phi, facets);
|
|
8659
|
+
var state = projectFacetRaw(lam, phi, facet);
|
|
8660
|
+
return applyConditionalLayout(state, facet);
|
|
8661
|
+
}
|
|
8662
|
+
|
|
8663
|
+
function projectFacetRaw(lam, phi, facet, forcedSector) {
|
|
8207
8664
|
var relative = obliquifySpherical(phi, lam, facet);
|
|
8208
|
-
var sector =
|
|
8665
|
+
var sector = forcedSector == null ?
|
|
8666
|
+
Math.floor((relative[1] + Math.PI / 3) / (2 * Math.PI / 3)) :
|
|
8667
|
+
forcedSector == 2 ? -1 : forcedSector;
|
|
8209
8668
|
var base = sector * 2 * Math.PI / 3;
|
|
8210
8669
|
var polar = narukawaFaceForward(relative[1] - base, relative[0]);
|
|
8211
8670
|
var angle = polar[1] + facet.rotation + base / 2;
|
|
8212
8671
|
var x = polar[0] * Math.cos(angle) + facet.x;
|
|
8213
8672
|
var y = polar[0] * Math.sin(angle) + facet.y;
|
|
8673
|
+
return {
|
|
8674
|
+
x: x,
|
|
8675
|
+
y: y,
|
|
8676
|
+
facet: facet.id,
|
|
8677
|
+
sector: mod(sector, 3)
|
|
8678
|
+
};
|
|
8679
|
+
}
|
|
8680
|
+
|
|
8681
|
+
function applyConditionalLayout(raw, facet) {
|
|
8682
|
+
var x = raw.x;
|
|
8683
|
+
var y = raw.y;
|
|
8214
8684
|
var oob = 0;
|
|
8685
|
+
var oobKey = 'normal';
|
|
8215
8686
|
var folded = 0;
|
|
8216
8687
|
var wrap = 0;
|
|
8217
8688
|
|
|
8218
|
-
if (Math.abs(x) > 3 + EPS) {
|
|
8689
|
+
if (Math.abs(x) > 3 + EPS$1) {
|
|
8690
|
+
oobKey = x > 0 ? 'xpos' : 'xneg';
|
|
8219
8691
|
x = 2 * facet.x - x;
|
|
8220
8692
|
y = -y;
|
|
8221
8693
|
oob = 1;
|
|
8222
|
-
} else if (Math.abs(y) > SQRT3 + EPS) {
|
|
8694
|
+
} else if (Math.abs(y) > SQRT3$1 + EPS$1) {
|
|
8695
|
+
oobKey = y > 0 ? 'ypos' : 'yneg';
|
|
8223
8696
|
x = -x;
|
|
8224
8697
|
y = BLOCK_HEIGHT * Math.sign(y) - y;
|
|
8225
8698
|
oob = 2;
|
|
@@ -8227,7 +8700,7 @@
|
|
|
8227
8700
|
|
|
8228
8701
|
var qx = y;
|
|
8229
8702
|
var qy = -x;
|
|
8230
|
-
if (qy > EPS) {
|
|
8703
|
+
if (qy > EPS$1) {
|
|
8231
8704
|
qx = BLOCK_HEIGHT - qx;
|
|
8232
8705
|
qy = -qy;
|
|
8233
8706
|
folded = 1;
|
|
@@ -8244,9 +8717,10 @@
|
|
|
8244
8717
|
return {
|
|
8245
8718
|
x: x,
|
|
8246
8719
|
y: y,
|
|
8247
|
-
facet: facet
|
|
8248
|
-
sector:
|
|
8720
|
+
facet: raw.facet,
|
|
8721
|
+
sector: raw.sector,
|
|
8249
8722
|
oob: oob,
|
|
8723
|
+
oobKey: oobKey,
|
|
8250
8724
|
folded: folded,
|
|
8251
8725
|
wrap: wrap
|
|
8252
8726
|
};
|
|
@@ -8267,29 +8741,29 @@
|
|
|
8267
8741
|
}
|
|
8268
8742
|
|
|
8269
8743
|
function narukawaFaceForward(lam, phi) {
|
|
8270
|
-
var a = lam - Math.asin(Math.sin(lam) / SQRT3);
|
|
8271
|
-
var theta = Math.atan(2 * SQRT3 / Math.PI * a);
|
|
8272
|
-
var denominator = 2 + SQRT2 * Math.tan(phi);
|
|
8744
|
+
var a = lam - Math.asin(Math.sin(lam) / SQRT3$1);
|
|
8745
|
+
var theta = Math.atan(2 * SQRT3$1 / Math.PI * a);
|
|
8746
|
+
var denominator = 2 + SQRT2$1 * Math.tan(phi);
|
|
8273
8747
|
var q = denominator > 0 ? (2 + Math.cos(lam)) / denominator : 0;
|
|
8274
|
-
var r = q * SQRT3 / Math.cos(theta);
|
|
8748
|
+
var r = q * SQRT3$1 / Math.cos(theta);
|
|
8275
8749
|
return [r, theta];
|
|
8276
8750
|
}
|
|
8277
8751
|
|
|
8278
8752
|
function narukawaFaceInverse(r, theta) {
|
|
8279
|
-
var target = Math.tan(theta) * Math.PI / (2 * SQRT3);
|
|
8753
|
+
var target = Math.tan(theta) * Math.PI / (2 * SQRT3$1);
|
|
8280
8754
|
var lo = -Math.PI / 3;
|
|
8281
8755
|
var hi = Math.PI / 3;
|
|
8282
8756
|
var lam;
|
|
8283
8757
|
for (var i = 0; i < 55; i++) {
|
|
8284
8758
|
lam = (lo + hi) / 2;
|
|
8285
|
-
var a = lam - Math.asin(Math.sin(lam) / SQRT3);
|
|
8759
|
+
var a = lam - Math.asin(Math.sin(lam) / SQRT3$1);
|
|
8286
8760
|
if (a < target) lo = lam;
|
|
8287
8761
|
else hi = lam;
|
|
8288
8762
|
}
|
|
8289
8763
|
lam = (lo + hi) / 2;
|
|
8290
|
-
var q = r * Math.cos(theta) / SQRT3;
|
|
8291
|
-
var phi = q < EPS ? HALF_PI :
|
|
8292
|
-
Math.atan(((2 + Math.cos(lam)) / q - 2) / SQRT2);
|
|
8764
|
+
var q = r * Math.cos(theta) / SQRT3$1;
|
|
8765
|
+
var phi = q < EPS$1 ? HALF_PI :
|
|
8766
|
+
Math.atan(((2 + Math.cos(lam)) / q - 2) / SQRT2$1);
|
|
8293
8767
|
return [phi, lam];
|
|
8294
8768
|
}
|
|
8295
8769
|
|
|
@@ -8370,7 +8844,7 @@
|
|
|
8370
8844
|
var theta0 = pole.meridian;
|
|
8371
8845
|
var lat1;
|
|
8372
8846
|
var lon1;
|
|
8373
|
-
if (Math.abs(lat0 - HALF_PI) < EPS) {
|
|
8847
|
+
if (Math.abs(lat0 - HALF_PI) < EPS$1) {
|
|
8374
8848
|
lat1 = lat;
|
|
8375
8849
|
lon1 = lon - lon0;
|
|
8376
8850
|
} else {
|
|
@@ -8381,7 +8855,7 @@
|
|
|
8381
8855
|
1
|
|
8382
8856
|
));
|
|
8383
8857
|
var denominator = Math.cos(lat1);
|
|
8384
|
-
var value = denominator < EPS ? 1 :
|
|
8858
|
+
var value = denominator < EPS$1 ? 1 :
|
|
8385
8859
|
(Math.cos(lat0) * Math.sin(lat) -
|
|
8386
8860
|
Math.sin(lat0) * Math.cos(lat) * Math.cos(lon0 - lon)) /
|
|
8387
8861
|
denominator;
|
|
@@ -8402,7 +8876,7 @@
|
|
|
8402
8876
|
1
|
|
8403
8877
|
));
|
|
8404
8878
|
var lonOut;
|
|
8405
|
-
if (Math.abs(lat0 - HALF_PI) < EPS) {
|
|
8879
|
+
if (Math.abs(lat0 - HALF_PI) < EPS$1) {
|
|
8406
8880
|
lonOut = lon + lon0;
|
|
8407
8881
|
} else {
|
|
8408
8882
|
var value = Math.sin(lat) / Math.cos(lat0) / Math.cos(latOut) -
|
|
@@ -8431,8 +8905,8 @@
|
|
|
8431
8905
|
var y = edge[0][1] + (edge[1][1] - edge[0][1]) * t;
|
|
8432
8906
|
var p = inverse(x * EDGE_SCALE, y * EDGE_SCALE);
|
|
8433
8907
|
path.push([
|
|
8434
|
-
normalizeLongitude$
|
|
8435
|
-
p[1] * R2D$
|
|
8908
|
+
normalizeLongitude$2(p[0] * R2D$2 + lon0),
|
|
8909
|
+
p[1] * R2D$2
|
|
8436
8910
|
]);
|
|
8437
8911
|
}
|
|
8438
8912
|
return memo.concat(splitPathAtAntimeridian$1(path));
|
|
@@ -8479,7 +8953,7 @@
|
|
|
8479
8953
|
}
|
|
8480
8954
|
|
|
8481
8955
|
function latLonToVector(p) {
|
|
8482
|
-
return radiansToVector(p[1] * D2R$
|
|
8956
|
+
return radiansToVector(p[1] * D2R$2, p[0] * D2R$2);
|
|
8483
8957
|
}
|
|
8484
8958
|
|
|
8485
8959
|
function radiansToVector(lam, phi) {
|
|
@@ -8522,7 +8996,7 @@
|
|
|
8522
8996
|
return lam;
|
|
8523
8997
|
}
|
|
8524
8998
|
|
|
8525
|
-
function normalizeLongitude$
|
|
8999
|
+
function normalizeLongitude$2(lon) {
|
|
8526
9000
|
while (lon > 180) lon -= 360;
|
|
8527
9001
|
while (lon < -180) lon += 360;
|
|
8528
9002
|
return lon;
|
|
@@ -8538,10 +9012,541 @@
|
|
|
8538
9012
|
registerNarukawa2022Projection: registerNarukawa2022Projection
|
|
8539
9013
|
});
|
|
8540
9014
|
|
|
9015
|
+
/*
|
|
9016
|
+
* Rectangular conformal tetrahedral projections based on L. P. Lee's
|
|
9017
|
+
* conformal face transform.
|
|
9018
|
+
*
|
|
9019
|
+
* Lee transform and tetrahedral net adapted from d3-geo-polygon:
|
|
9020
|
+
* Copyright 2017-2024 Mike Bostock, ISC license.
|
|
9021
|
+
* https://github.com/d3/d3-geo-polygon/blob/main/src/tetrahedralLee.js
|
|
9022
|
+
*
|
|
9023
|
+
* The rectangular layout below is derived from Markley's repeated-face
|
|
9024
|
+
* construction: four affine copies of the triangular Lee net are clipped to
|
|
9025
|
+
* a 4/sqrt(3) frame. See F. Landis Markley, "Tetrahedral Map Projection"
|
|
9026
|
+
* (2020), and https://blog.map-projections.net/lee-markley-calm-and-grieger.
|
|
9027
|
+
*/
|
|
9028
|
+
|
|
9029
|
+
|
|
9030
|
+
var D2R$1 = Math.PI / 180;
|
|
9031
|
+
var R2D$1 = 180 / Math.PI;
|
|
9032
|
+
var SQRT2 = Math.sqrt(2);
|
|
9033
|
+
var SQRT3 = Math.sqrt(3);
|
|
9034
|
+
var ASIN_ONE_THIRD = Math.asin(1 / 3);
|
|
9035
|
+
var MARKLEY_LATITUDE = Math.acos(1 / 3) * 0.5 * R2D$1;
|
|
9036
|
+
var RECT_XMIN = -7;
|
|
9037
|
+
var RECT_XMAX = 1;
|
|
9038
|
+
var RECT_YMIN = -2 * SQRT3;
|
|
9039
|
+
var RECT_YMAX = 0;
|
|
9040
|
+
var EPS = 1e-12;
|
|
9041
|
+
var engines = {};
|
|
9042
|
+
|
|
9043
|
+
var TETRAHEDRON_VERTICES = [
|
|
9044
|
+
[0, 90],
|
|
9045
|
+
[-180, -ASIN_ONE_THIRD * R2D$1],
|
|
9046
|
+
[-60, -ASIN_ONE_THIRD * R2D$1],
|
|
9047
|
+
[60, -ASIN_ONE_THIRD * R2D$1]
|
|
9048
|
+
];
|
|
9049
|
+
|
|
9050
|
+
var TETRAHEDRON_FACES = [
|
|
9051
|
+
[1, 2, 3],
|
|
9052
|
+
[0, 2, 1],
|
|
9053
|
+
[0, 3, 2],
|
|
9054
|
+
[0, 1, 3]
|
|
9055
|
+
].map(function(face) {
|
|
9056
|
+
return face.map(function(i) {
|
|
9057
|
+
return TETRAHEDRON_VERTICES[i];
|
|
9058
|
+
});
|
|
9059
|
+
});
|
|
9060
|
+
|
|
9061
|
+
var LAYOUT_COPIES = [
|
|
9062
|
+
{id: 0, name: 'green', matrix: [1, 0, 0, 0, -1, 0]},
|
|
9063
|
+
{id: 1, name: 'red', matrix: [-1, 0, -4, 0, 1, 0]},
|
|
9064
|
+
{id: 2, name: 'blue', matrix: [1, 0, -8, 0, -1, 0]},
|
|
9065
|
+
{id: 3, name: 'orange', matrix: [-1, 0, 4, 0, 1, 0]}
|
|
9066
|
+
];
|
|
9067
|
+
|
|
9068
|
+
function registerLeeTetrahedralProjections(mproj) {
|
|
9069
|
+
if (!mproj) return;
|
|
9070
|
+
register('markley', 'Markley conformal tetrahedral world map');
|
|
9071
|
+
register('calm', 'Conformal Authagraph-Like Map');
|
|
9072
|
+
|
|
9073
|
+
function register(id, name) {
|
|
9074
|
+
if (mproj.internal.pj_list[id]) return;
|
|
9075
|
+
mproj.pj_add(function(P) {
|
|
9076
|
+
initLeeTetrahedral(P, id);
|
|
9077
|
+
}, id, name);
|
|
9078
|
+
}
|
|
9079
|
+
}
|
|
9080
|
+
|
|
9081
|
+
function getLeeTetrahedralEngine(id) {
|
|
9082
|
+
id = id || 'markley';
|
|
9083
|
+
if (!engines[id]) {
|
|
9084
|
+
engines[id] = createLeeTetrahedralEngine(getProjectionRotation(id));
|
|
9085
|
+
}
|
|
9086
|
+
return engines[id];
|
|
9087
|
+
}
|
|
9088
|
+
|
|
9089
|
+
function initLeeTetrahedral(P, id) {
|
|
9090
|
+
var engine = getLeeTetrahedralEngine(id);
|
|
9091
|
+
P.es = 0;
|
|
9092
|
+
P.inv = null;
|
|
9093
|
+
P.fwd = function(lp, xy) {
|
|
9094
|
+
var p = engine.forward(lp.lam, lp.phi);
|
|
9095
|
+
xy.x = p[0];
|
|
9096
|
+
xy.y = p[1];
|
|
9097
|
+
};
|
|
9098
|
+
P.__projection_topology = engine.getTopology(P.lam0 * R2D$1);
|
|
9099
|
+
P.__projected_outline = engine.outline;
|
|
9100
|
+
}
|
|
9101
|
+
|
|
9102
|
+
function getProjectionRotation(id) {
|
|
9103
|
+
if (id == 'calm') {
|
|
9104
|
+
// Exact D3 Euler equivalent of MapDesigner's published CALM aspect:
|
|
9105
|
+
// latitude 77°, longitude 143°, central meridian -163°.
|
|
9106
|
+
return [
|
|
9107
|
+
19.57956907750618,
|
|
9108
|
+
-12.42267097553935,
|
|
9109
|
+
3.8615690020132067
|
|
9110
|
+
];
|
|
9111
|
+
}
|
|
9112
|
+
// Markley's singularities are at ±35.26439°, in the oceans.
|
|
9113
|
+
return [115, MARKLEY_LATITUDE - 90, 180];
|
|
9114
|
+
}
|
|
9115
|
+
|
|
9116
|
+
function createLeeTetrahedralEngine(rotation) {
|
|
9117
|
+
var base = createPolyhedralProjection({
|
|
9118
|
+
faces: TETRAHEDRON_FACES,
|
|
9119
|
+
parents: [-1, 0, 0, 0],
|
|
9120
|
+
rotation: rotation,
|
|
9121
|
+
angle: 30,
|
|
9122
|
+
faceProjector: createLeeFaceProjector
|
|
9123
|
+
});
|
|
9124
|
+
var normalization = getBaseNormalization(base.outline);
|
|
9125
|
+
var baseTopology = base.getTopology(0);
|
|
9126
|
+
var sourceRegions = createSourceRegions(rotation);
|
|
9127
|
+
var pieces = createLayoutPieces(baseTopology.regions, normalization);
|
|
9128
|
+
var pieceIndex = new Map(pieces.map(function(piece) {
|
|
9129
|
+
return [getPieceKey(piece.face, piece.copy), piece.id];
|
|
9130
|
+
}));
|
|
9131
|
+
var outline = [[
|
|
9132
|
+
centerOutputPoint([RECT_XMIN, RECT_YMIN]),
|
|
9133
|
+
centerOutputPoint([RECT_XMAX, RECT_YMIN]),
|
|
9134
|
+
centerOutputPoint([RECT_XMAX, RECT_YMAX]),
|
|
9135
|
+
centerOutputPoint([RECT_XMIN, RECT_YMAX]),
|
|
9136
|
+
centerOutputPoint([RECT_XMIN, RECT_YMIN])
|
|
9137
|
+
]];
|
|
9138
|
+
|
|
9139
|
+
return {
|
|
9140
|
+
forward: forward,
|
|
9141
|
+
outline: outline,
|
|
9142
|
+
getTopology: getTopology
|
|
9143
|
+
};
|
|
9144
|
+
|
|
9145
|
+
function forward(lam, phi) {
|
|
9146
|
+
var p = normalizeBasePoint(base.forward(lam, phi), normalization);
|
|
9147
|
+
var copy = getLayoutCopy(p);
|
|
9148
|
+
return centerOutputPoint(applyMatrix(copy.matrix, p));
|
|
9149
|
+
}
|
|
9150
|
+
|
|
9151
|
+
function getTopology(lon0) {
|
|
9152
|
+
var topology = base.getTopology(lon0);
|
|
9153
|
+
return {
|
|
9154
|
+
regions: pieces.map(copyProjectedPiece),
|
|
9155
|
+
seams: topology.seams.map(function(seam) {
|
|
9156
|
+
return {
|
|
9157
|
+
type: 'cut',
|
|
9158
|
+
faces: seam.faces,
|
|
9159
|
+
paths: seam.paths
|
|
9160
|
+
};
|
|
9161
|
+
}),
|
|
9162
|
+
findRegion: findRegion,
|
|
9163
|
+
findTransitionRegion: findRegion,
|
|
9164
|
+
projectRegion: projectRegion,
|
|
9165
|
+
raster_regions: pieces.map(copyRasterPiece),
|
|
9166
|
+
raster_source_regions: sourceRegions.map(function(region) {
|
|
9167
|
+
return {
|
|
9168
|
+
id: region.id,
|
|
9169
|
+
boundary: region.boundary.map(function(p) {
|
|
9170
|
+
return [
|
|
9171
|
+
normalizeLongitude$1(p[0] + lon0),
|
|
9172
|
+
p[1]
|
|
9173
|
+
];
|
|
9174
|
+
})
|
|
9175
|
+
};
|
|
9176
|
+
}),
|
|
9177
|
+
raster_mesh_interval: 32,
|
|
9178
|
+
raster_cell_halo: false,
|
|
9179
|
+
fill_raster_mask: true,
|
|
9180
|
+
fill_raster_coverage: true,
|
|
9181
|
+
findRasterRegion: findRegion,
|
|
9182
|
+
projectRasterRegion: projectRegion,
|
|
9183
|
+
projectRasterSourceRegion: projectRasterSourceRegion,
|
|
9184
|
+
clipRasterRegionPolygon: clipRasterRegionPolygon,
|
|
9185
|
+
outline: outline.map(function(ring) {
|
|
9186
|
+
return ring.map(function(p) { return p.concat(); });
|
|
9187
|
+
})
|
|
9188
|
+
};
|
|
9189
|
+
|
|
9190
|
+
function findRegion(lon, lat) {
|
|
9191
|
+
var lam = normalizeLongitude$1(lon - lon0) * D2R$1;
|
|
9192
|
+
var phi = lat * D2R$1;
|
|
9193
|
+
var face = base.findFace(lam, phi);
|
|
9194
|
+
var p = normalizeBasePoint(base.forwardFace(lam, phi, face), normalization);
|
|
9195
|
+
var copy = getLayoutCopy(p);
|
|
9196
|
+
return pieceIndex.get(getPieceKey(face, copy.id));
|
|
9197
|
+
}
|
|
9198
|
+
|
|
9199
|
+
function projectRegion(lon, lat, regionId) {
|
|
9200
|
+
var piece = pieces[regionId];
|
|
9201
|
+
var lam = normalizeLongitude$1(lon - lon0) * D2R$1;
|
|
9202
|
+
var p = normalizeBasePoint(
|
|
9203
|
+
base.forwardFace(lam, lat * D2R$1, piece.face),
|
|
9204
|
+
normalization
|
|
9205
|
+
);
|
|
9206
|
+
return centerOutputPoint(applyMatrix(piece.matrix, p));
|
|
9207
|
+
}
|
|
9208
|
+
|
|
9209
|
+
function projectRasterSourceRegion(lon, lat, sourceRegionId) {
|
|
9210
|
+
var lam = normalizeLongitude$1(lon - lon0) * D2R$1;
|
|
9211
|
+
return normalizeBasePoint(
|
|
9212
|
+
base.forwardFace(lam, lat * D2R$1, sourceRegionId),
|
|
9213
|
+
normalization
|
|
9214
|
+
);
|
|
9215
|
+
}
|
|
9216
|
+
|
|
9217
|
+
function clipRasterRegionPolygon(vertices, regionId) {
|
|
9218
|
+
var piece = pieces[regionId];
|
|
9219
|
+
var polygon = vertices.map(function(vertex) {
|
|
9220
|
+
var p = applyMatrix(piece.matrix, [vertex.x, vertex.y]);
|
|
9221
|
+
return copyRasterVertex(vertex, p[0], p[1]);
|
|
9222
|
+
});
|
|
9223
|
+
polygon = clipRasterPolygonAxis(polygon, 'x', RECT_XMIN, true);
|
|
9224
|
+
polygon = clipRasterPolygonAxis(polygon, 'x', RECT_XMAX, false);
|
|
9225
|
+
polygon = clipRasterPolygonAxis(polygon, 'y', RECT_YMIN, true);
|
|
9226
|
+
polygon = clipRasterPolygonAxis(polygon, 'y', RECT_YMAX, false);
|
|
9227
|
+
polygon.forEach(function(vertex) {
|
|
9228
|
+
var p = centerOutputPoint([vertex.x, vertex.y]);
|
|
9229
|
+
vertex.x = p[0];
|
|
9230
|
+
vertex.y = p[1];
|
|
9231
|
+
});
|
|
9232
|
+
return polygon;
|
|
9233
|
+
}
|
|
9234
|
+
}
|
|
9235
|
+
}
|
|
9236
|
+
|
|
9237
|
+
function createSourceRegions(rotation) {
|
|
9238
|
+
return TETRAHEDRON_FACES.map(function(face, id) {
|
|
9239
|
+
var boundary = face.map(function(p) {
|
|
9240
|
+
var q = rotateSphericalRadians(
|
|
9241
|
+
p[0] * D2R$1, p[1] * D2R$1, rotation, true);
|
|
9242
|
+
return [normalizeLongitude$1(q[0] * R2D$1), q[1] * R2D$1];
|
|
9243
|
+
});
|
|
9244
|
+
boundary.push(boundary[0].concat());
|
|
9245
|
+
return {id: id, boundary: boundary};
|
|
9246
|
+
});
|
|
9247
|
+
}
|
|
9248
|
+
|
|
9249
|
+
function createLayoutPieces(regions, normalization) {
|
|
9250
|
+
var pieces = [];
|
|
9251
|
+
regions.forEach(function(region) {
|
|
9252
|
+
var boundary = region.projected_boundary.map(function(p) {
|
|
9253
|
+
return normalizeBasePoint(p, normalization);
|
|
9254
|
+
});
|
|
9255
|
+
LAYOUT_COPIES.forEach(function(copy) {
|
|
9256
|
+
var polygon = boundary.map(function(p) {
|
|
9257
|
+
return applyMatrix(copy.matrix, p);
|
|
9258
|
+
});
|
|
9259
|
+
polygon = clipPolygonAxis(polygon, 0, RECT_XMIN, true);
|
|
9260
|
+
polygon = clipPolygonAxis(polygon, 0, RECT_XMAX, false);
|
|
9261
|
+
polygon = clipPolygonAxis(polygon, 1, RECT_YMIN, true);
|
|
9262
|
+
polygon = clipPolygonAxis(polygon, 1, RECT_YMAX, false);
|
|
9263
|
+
if (polygon.length < 3 || Math.abs(getRingArea$2(polygon)) < EPS) return;
|
|
9264
|
+
var id = pieces.length;
|
|
9265
|
+
pieces.push({
|
|
9266
|
+
id: id,
|
|
9267
|
+
face: region.id,
|
|
9268
|
+
source_region: region.id,
|
|
9269
|
+
copy: copy.id,
|
|
9270
|
+
matrix: copy.matrix,
|
|
9271
|
+
boundary: polygon.map(centerOutputPoint)
|
|
9272
|
+
});
|
|
9273
|
+
});
|
|
9274
|
+
});
|
|
9275
|
+
return pieces;
|
|
9276
|
+
}
|
|
9277
|
+
|
|
9278
|
+
function copyProjectedPiece(piece) {
|
|
9279
|
+
return {
|
|
9280
|
+
id: piece.id,
|
|
9281
|
+
source_region: piece.source_region,
|
|
9282
|
+
projected_boundary: closeRing$1(piece.boundary)
|
|
9283
|
+
};
|
|
9284
|
+
}
|
|
9285
|
+
|
|
9286
|
+
function copyRasterPiece(piece) {
|
|
9287
|
+
return {
|
|
9288
|
+
id: piece.id,
|
|
9289
|
+
source_region: piece.source_region,
|
|
9290
|
+
projected_boundary: closeRing$1(piece.boundary)
|
|
9291
|
+
};
|
|
9292
|
+
}
|
|
9293
|
+
|
|
9294
|
+
function closeRing$1(ring) {
|
|
9295
|
+
var copy = ring.map(function(p) { return p.concat(); });
|
|
9296
|
+
if (copy.length && !pointsEqual$1(copy[0], copy[copy.length - 1])) {
|
|
9297
|
+
copy.push(copy[0].concat());
|
|
9298
|
+
}
|
|
9299
|
+
return copy;
|
|
9300
|
+
}
|
|
9301
|
+
|
|
9302
|
+
function getLayoutCopy(p) {
|
|
9303
|
+
// The four transformed triangular nets tile the frame. These two straight
|
|
9304
|
+
// cuts select the unique copy containing a point from the base net.
|
|
9305
|
+
if (p[1] >= 0) return p[0] > 3 ? LAYOUT_COPIES[2] : LAYOUT_COPIES[0];
|
|
9306
|
+
return p[0] > 1 ? LAYOUT_COPIES[3] : LAYOUT_COPIES[1];
|
|
9307
|
+
}
|
|
9308
|
+
|
|
9309
|
+
function centerOutputPoint(p) {
|
|
9310
|
+
return [
|
|
9311
|
+
p[0] - (RECT_XMIN + RECT_XMAX) / 2,
|
|
9312
|
+
p[1] - (RECT_YMIN + RECT_YMAX) / 2
|
|
9313
|
+
];
|
|
9314
|
+
}
|
|
9315
|
+
|
|
9316
|
+
function getBaseNormalization(outline) {
|
|
9317
|
+
var xmin = Infinity;
|
|
9318
|
+
var ymin = Infinity;
|
|
9319
|
+
var xmax = -Infinity;
|
|
9320
|
+
var ymax = -Infinity;
|
|
9321
|
+
outline.forEach(function(ring) {
|
|
9322
|
+
ring.forEach(function(p) {
|
|
9323
|
+
xmin = Math.min(xmin, p[0]);
|
|
9324
|
+
ymin = Math.min(ymin, p[1]);
|
|
9325
|
+
xmax = Math.max(xmax, p[0]);
|
|
9326
|
+
ymax = Math.max(ymax, p[1]);
|
|
9327
|
+
});
|
|
9328
|
+
});
|
|
9329
|
+
return {
|
|
9330
|
+
cx: (xmin + xmax) / 2,
|
|
9331
|
+
cy: (ymin + ymax) / 2,
|
|
9332
|
+
scale: 8 / (xmax - xmin)
|
|
9333
|
+
};
|
|
9334
|
+
}
|
|
9335
|
+
|
|
9336
|
+
function normalizeBasePoint(p, normalization) {
|
|
9337
|
+
return [
|
|
9338
|
+
(p[0] - normalization.cx) * normalization.scale,
|
|
9339
|
+
-(p[1] - normalization.cy) * normalization.scale
|
|
9340
|
+
];
|
|
9341
|
+
}
|
|
9342
|
+
|
|
9343
|
+
function createLeeFaceProjector(face) {
|
|
9344
|
+
var c = face.centroid;
|
|
9345
|
+
var rotation = Math.abs(c[1]) == 90 ?
|
|
9346
|
+
[0, -c[1], -30] :
|
|
9347
|
+
[-c[0], -c[1], 30];
|
|
9348
|
+
return function(lam, phi) {
|
|
9349
|
+
var p = rotateSphericalRadians(lam, phi, rotation);
|
|
9350
|
+
var q = leeRaw(p[0], p[1]);
|
|
9351
|
+
return [q[0], -q[1]];
|
|
9352
|
+
};
|
|
9353
|
+
}
|
|
9354
|
+
|
|
9355
|
+
function leeRaw(lam, phi) {
|
|
9356
|
+
var w = [-0.5, SQRT3 / 2];
|
|
9357
|
+
var z = complexMultiply(stereographicRaw(lam, phi), [SQRT2, 0]);
|
|
9358
|
+
var powers = [0, 1, 2].map(function(i) {
|
|
9359
|
+
return complexPower(w, [i, 0]);
|
|
9360
|
+
});
|
|
9361
|
+
var sector = 0;
|
|
9362
|
+
for (var i = 1; i < powers.length; i++) {
|
|
9363
|
+
if (complexMultiply(z, powers[i])[0] >
|
|
9364
|
+
complexMultiply(z, powers[sector])[0]) sector = i;
|
|
9365
|
+
}
|
|
9366
|
+
var rot = powers[sector];
|
|
9367
|
+
var n = complexNorm(z);
|
|
9368
|
+
var h = [0, 0];
|
|
9369
|
+
var k = [0, 0];
|
|
9370
|
+
|
|
9371
|
+
if (n > 0.3) {
|
|
9372
|
+
var y = complexSubtract([1, 0], complexMultiply(rot, z));
|
|
9373
|
+
var w1 = 1.4021821053254548;
|
|
9374
|
+
var coefficients = [
|
|
9375
|
+
1.15470053837925, 0.192450089729875, 0.0481125224324687,
|
|
9376
|
+
0.010309826235529, 3.34114739114366e-4, -0.00150351632601465,
|
|
9377
|
+
-0.0012304417796231, -675190201960282e-18,
|
|
9378
|
+
-284084537293856e-18, -821205120500051e-19,
|
|
9379
|
+
-159257630018706e-20, 1.91691805888369e-5,
|
|
9380
|
+
1.73095888028726e-5, 1.03865580818367e-5,
|
|
9381
|
+
4.70614523937179e-6, 1.4413500104181e-6,
|
|
9382
|
+
1.92757960170179e-8, -3.82869799649063e-7,
|
|
9383
|
+
-3.57526015225576e-7, -2.2175964844211e-7
|
|
9384
|
+
];
|
|
9385
|
+
var g = [0, 0];
|
|
9386
|
+
for (i = coefficients.length - 1; i >= 0; i--) {
|
|
9387
|
+
g = complexAdd([coefficients[i], 0], complexMultiply(g, y));
|
|
9388
|
+
}
|
|
9389
|
+
k = complexSubtract([w1, 0], complexMultiply(complexPower(y, 0.5), g));
|
|
9390
|
+
k = complexMultiply(complexMultiply(k, rot), rot);
|
|
9391
|
+
}
|
|
9392
|
+
|
|
9393
|
+
if (n < 0.5) {
|
|
9394
|
+
var h0 = [1, 1 / 8, 3 / 56, 1 / 32, 35 / 1664, 63 / 4096, 231 / 19456];
|
|
9395
|
+
var z3 = complexPower(z, [3, 0]);
|
|
9396
|
+
for (i = h0.length - 1; i >= 0; i--) {
|
|
9397
|
+
h = complexAdd([h0[i], 0], complexMultiply(h, z3));
|
|
9398
|
+
}
|
|
9399
|
+
h = complexMultiply(h, z);
|
|
9400
|
+
}
|
|
9401
|
+
|
|
9402
|
+
if (n < 0.3) return h;
|
|
9403
|
+
if (n > 0.5) return k;
|
|
9404
|
+
var t = (n - 0.3) / 0.2;
|
|
9405
|
+
return complexAdd(
|
|
9406
|
+
complexMultiply(k, [t, 0]),
|
|
9407
|
+
complexMultiply(h, [1 - t, 0])
|
|
9408
|
+
);
|
|
9409
|
+
}
|
|
9410
|
+
|
|
9411
|
+
function stereographicRaw(lam, phi) {
|
|
9412
|
+
var cosPhi = Math.cos(phi);
|
|
9413
|
+
var k = 1 / (1 + cosPhi * Math.cos(lam));
|
|
9414
|
+
return [k * cosPhi * Math.sin(lam), k * Math.sin(phi)];
|
|
9415
|
+
}
|
|
9416
|
+
|
|
9417
|
+
function complexAdd(a, b) {
|
|
9418
|
+
return [a[0] + b[0], a[1] + b[1]];
|
|
9419
|
+
}
|
|
9420
|
+
|
|
9421
|
+
function complexSubtract(a, b) {
|
|
9422
|
+
return [a[0] - b[0], a[1] - b[1]];
|
|
9423
|
+
}
|
|
9424
|
+
|
|
9425
|
+
function complexMultiply(a, b) {
|
|
9426
|
+
return [a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]];
|
|
9427
|
+
}
|
|
9428
|
+
|
|
9429
|
+
function complexNorm(a) {
|
|
9430
|
+
return Math.hypot(a[0], a[1]);
|
|
9431
|
+
}
|
|
9432
|
+
|
|
9433
|
+
function complexPower(value, exponent) {
|
|
9434
|
+
var a = value[0];
|
|
9435
|
+
var b = value[1];
|
|
9436
|
+
var n = typeof exponent == 'number' ? [exponent, 0] : exponent;
|
|
9437
|
+
if (a === 0 && b === 0) return [0, 0];
|
|
9438
|
+
if (!n[1] && b === 0 && a >= 0) {
|
|
9439
|
+
return [Math.pow(a, n[0]), 0];
|
|
9440
|
+
}
|
|
9441
|
+
var arg = Math.atan2(b, a);
|
|
9442
|
+
var logNorm = Math.log(Math.hypot(a, b));
|
|
9443
|
+
var magnitude = Math.exp(n[0] * logNorm - n[1] * arg);
|
|
9444
|
+
var angle = n[1] * logNorm + n[0] * arg;
|
|
9445
|
+
return [magnitude * Math.cos(angle), magnitude * Math.sin(angle)];
|
|
9446
|
+
}
|
|
9447
|
+
|
|
9448
|
+
function applyMatrix(m, p) {
|
|
9449
|
+
return [
|
|
9450
|
+
m[0] * p[0] + m[1] * p[1] + m[2],
|
|
9451
|
+
m[3] * p[0] + m[4] * p[1] + m[5]
|
|
9452
|
+
];
|
|
9453
|
+
}
|
|
9454
|
+
|
|
9455
|
+
function clipPolygonAxis(polygon, axis, value, keepGreater) {
|
|
9456
|
+
var output = [];
|
|
9457
|
+
if (!polygon.length) return output;
|
|
9458
|
+
var a = polygon[polygon.length - 1];
|
|
9459
|
+
var aInside = keepGreater ? a[axis] >= value - EPS : a[axis] <= value + EPS;
|
|
9460
|
+
polygon.forEach(function(b) {
|
|
9461
|
+
var bInside = keepGreater ? b[axis] >= value - EPS : b[axis] <= value + EPS;
|
|
9462
|
+
if (aInside != bInside) {
|
|
9463
|
+
var t = (value - a[axis]) / (b[axis] - a[axis]);
|
|
9464
|
+
var p = [
|
|
9465
|
+
a[0] + (b[0] - a[0]) * t,
|
|
9466
|
+
a[1] + (b[1] - a[1]) * t
|
|
9467
|
+
];
|
|
9468
|
+
p[axis] = value;
|
|
9469
|
+
output.push(p);
|
|
9470
|
+
}
|
|
9471
|
+
if (bInside) output.push(b.concat());
|
|
9472
|
+
a = b;
|
|
9473
|
+
aInside = bInside;
|
|
9474
|
+
});
|
|
9475
|
+
return output;
|
|
9476
|
+
}
|
|
9477
|
+
|
|
9478
|
+
function clipRasterPolygonAxis(polygon, axis, value, keepGreater) {
|
|
9479
|
+
var output = [];
|
|
9480
|
+
if (!polygon.length) return output;
|
|
9481
|
+
var a = polygon[polygon.length - 1];
|
|
9482
|
+
var aInside = keepGreater ? a[axis] >= value - EPS : a[axis] <= value + EPS;
|
|
9483
|
+
polygon.forEach(function(b) {
|
|
9484
|
+
var bInside = keepGreater ? b[axis] >= value - EPS : b[axis] <= value + EPS;
|
|
9485
|
+
if (aInside != bInside) {
|
|
9486
|
+
var t = (value - a[axis]) / (b[axis] - a[axis]);
|
|
9487
|
+
var vertex = {
|
|
9488
|
+
x: a.x + (b.x - a.x) * t,
|
|
9489
|
+
y: a.y + (b.y - a.y) * t,
|
|
9490
|
+
sx: a.sx + (b.sx - a.sx) * t,
|
|
9491
|
+
sy: a.sy + (b.sy - a.sy) * t,
|
|
9492
|
+
lon: interpolateLongitude(a.lon, b.lon, t),
|
|
9493
|
+
lat: a.lat + (b.lat - a.lat) * t
|
|
9494
|
+
};
|
|
9495
|
+
vertex[axis] = value;
|
|
9496
|
+
output.push(vertex);
|
|
9497
|
+
}
|
|
9498
|
+
if (bInside) output.push(copyRasterVertex(b, b.x, b.y));
|
|
9499
|
+
a = b;
|
|
9500
|
+
aInside = bInside;
|
|
9501
|
+
});
|
|
9502
|
+
return output;
|
|
9503
|
+
}
|
|
9504
|
+
|
|
9505
|
+
function copyRasterVertex(vertex, x, y) {
|
|
9506
|
+
return {
|
|
9507
|
+
x: x,
|
|
9508
|
+
y: y,
|
|
9509
|
+
sx: vertex.sx,
|
|
9510
|
+
sy: vertex.sy,
|
|
9511
|
+
lon: vertex.lon,
|
|
9512
|
+
lat: vertex.lat
|
|
9513
|
+
};
|
|
9514
|
+
}
|
|
9515
|
+
|
|
9516
|
+
function interpolateLongitude(a, b, t) {
|
|
9517
|
+
var delta = b - a;
|
|
9518
|
+
if (delta > 180) delta -= 360;
|
|
9519
|
+
if (delta < -180) delta += 360;
|
|
9520
|
+
return normalizeLongitude$1(a + delta * t);
|
|
9521
|
+
}
|
|
9522
|
+
|
|
9523
|
+
function getRingArea$2(ring) {
|
|
9524
|
+
var area = 0;
|
|
9525
|
+
for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {
|
|
9526
|
+
area += ring[j][0] * ring[i][1] - ring[i][0] * ring[j][1];
|
|
9527
|
+
}
|
|
9528
|
+
return area / 2;
|
|
9529
|
+
}
|
|
9530
|
+
|
|
9531
|
+
function getPieceKey(face, copy) {
|
|
9532
|
+
return face + ':' + copy;
|
|
9533
|
+
}
|
|
9534
|
+
|
|
9535
|
+
function pointsEqual$1(a, b) {
|
|
9536
|
+
return Math.abs(a[0] - b[0]) < EPS && Math.abs(a[1] - b[1]) < EPS;
|
|
9537
|
+
}
|
|
9538
|
+
|
|
9539
|
+
function normalizeLongitude$1(lon) {
|
|
9540
|
+
lon = (lon + 180) % 360;
|
|
9541
|
+
if (lon < 0) lon += 360;
|
|
9542
|
+
return lon - 180;
|
|
9543
|
+
}
|
|
9544
|
+
|
|
8541
9545
|
var mproj$1 = require$1('mproj');
|
|
8542
9546
|
registerDymaxionProjections(mproj$1);
|
|
8543
9547
|
registerButterflyProjections(mproj$1);
|
|
8544
9548
|
registerNarukawa2022Projection(mproj$1);
|
|
9549
|
+
registerLeeTetrahedralProjections(mproj$1);
|
|
8545
9550
|
|
|
8546
9551
|
var asyncLoader = null;
|
|
8547
9552
|
|
|
@@ -45620,7 +46625,7 @@ ${svg}
|
|
|
45620
46625
|
|
|
45621
46626
|
function stopIfBufferReachesPole(shape, dist) {
|
|
45622
46627
|
var maxAbsLat = 0;
|
|
45623
|
-
var angularDist = dist / R$3 * R2D$
|
|
46628
|
+
var angularDist = dist / R$3 * R2D$7;
|
|
45624
46629
|
(shape || []).forEach(function(path) {
|
|
45625
46630
|
latLngPathIter.init(path);
|
|
45626
46631
|
while (latLngPathIter.hasNext()) {
|
|
@@ -47737,12 +48742,12 @@ ${svg}
|
|
|
47737
48742
|
}
|
|
47738
48743
|
|
|
47739
48744
|
function projectBufferPoint(x, y, spherical) {
|
|
47740
|
-
return spherical ? [x * D2R$
|
|
48745
|
+
return spherical ? [x * D2R$8 * R$3, Math.log(Math.tan(Math.PI / 4 + y * D2R$8 / 2)) * R$3] :
|
|
47741
48746
|
[x, y];
|
|
47742
48747
|
}
|
|
47743
48748
|
|
|
47744
48749
|
function unprojectBufferPoint(x, y, spherical) {
|
|
47745
|
-
return spherical ? [x / (D2R$
|
|
48750
|
+
return spherical ? [x / (D2R$8 * R$3), (2 * Math.atan(Math.exp(y / R$3)) - Math.PI / 2) / (D2R$8)] :
|
|
47746
48751
|
[x, y];
|
|
47747
48752
|
}
|
|
47748
48753
|
|
|
@@ -52413,7 +53418,7 @@ ${svg}
|
|
|
52413
53418
|
var maxAbsLat = Math.max(Math.abs(bounds.ymin), Math.abs(bounds.ymax));
|
|
52414
53419
|
var maxPositiveDistance = getMaxPositiveBufferDistance(lyr, dataset, opts);
|
|
52415
53420
|
if (!(maxPositiveDistance > 0)) return false;
|
|
52416
|
-
return maxAbsLat + maxPositiveDistance / R$3 * R2D$
|
|
53421
|
+
return maxAbsLat + maxPositiveDistance / R$3 * R2D$7 >= 90 - POLAR_BUFFER_MARGIN_DEGREES;
|
|
52417
53422
|
}
|
|
52418
53423
|
|
|
52419
53424
|
function getMaxPositiveBufferDistance(lyr, dataset, opts) {
|
|
@@ -53665,7 +54670,7 @@ ${svg}
|
|
|
53665
54670
|
}
|
|
53666
54671
|
|
|
53667
54672
|
function getCoordinateDistance(distance, arcs) {
|
|
53668
|
-
return arcs.isPlanar() ? distance : distance / R$3 * R2D$
|
|
54673
|
+
return arcs.isPlanar() ? distance : distance / R$3 * R2D$7;
|
|
53669
54674
|
}
|
|
53670
54675
|
|
|
53671
54676
|
// @shapeIndex: chunk-bounds index of the source shape (see buildShapeSegmentIndex)
|
|
@@ -54334,7 +55339,7 @@ ${svg}
|
|
|
54334
55339
|
// depending on parameters
|
|
54335
55340
|
if (inList(P, 'cassini,gnom,bertin1953,chamb,ob_tran,tpeqd,healpix,rhealpix,' +
|
|
54336
55341
|
'ocea,omerc,tmerc,etmerc,nicol,dymaxion,dymaxion2,butterfly,butterfly2,' +
|
|
54337
|
-
'cahill_keyes,narukawa2022')) {
|
|
55342
|
+
'cahill_keyes,narukawa2022,markley,calm')) {
|
|
54338
55343
|
return false;
|
|
54339
55344
|
}
|
|
54340
55345
|
if (isAzimuthal(P)) {
|
|
@@ -54386,16 +55391,16 @@ ${svg}
|
|
|
54386
55391
|
}
|
|
54387
55392
|
|
|
54388
55393
|
function getRotationFunction2(rotation, inv) {
|
|
54389
|
-
var a = (rotation[0] || 0) * D2R$
|
|
54390
|
-
b = (rotation[1] || 0) * D2R$
|
|
54391
|
-
c = (rotation[2] || 0) * D2R$
|
|
55394
|
+
var a = (rotation[0] || 0) * D2R$8,
|
|
55395
|
+
b = (rotation[1] || 0) * D2R$8,
|
|
55396
|
+
c = (rotation[2] || 0) * D2R$8;
|
|
54392
55397
|
return function(p) {
|
|
54393
|
-
p[0] *= D2R$
|
|
54394
|
-
p[1] *= D2R$
|
|
55398
|
+
p[0] *= D2R$8;
|
|
55399
|
+
p[1] *= D2R$8;
|
|
54395
55400
|
var rotate = inv ? rotatePointInv : rotatePoint;
|
|
54396
55401
|
rotate(p, a, b, c);
|
|
54397
|
-
p[0] *= R2D$
|
|
54398
|
-
p[1] *= R2D$
|
|
55402
|
+
p[0] *= R2D$7;
|
|
55403
|
+
p[1] *= R2D$7;
|
|
54399
55404
|
return p;
|
|
54400
55405
|
};
|
|
54401
55406
|
}
|
|
@@ -54875,7 +55880,19 @@ ${svg}
|
|
|
54875
55880
|
type: o.type,
|
|
54876
55881
|
coordinates: rotatePath(o.coordinates, lon0)
|
|
54877
55882
|
};
|
|
54878
|
-
})
|
|
55883
|
+
}),
|
|
55884
|
+
findRegion: function(lon, lat) {
|
|
55885
|
+
return findClassicRegion(defn, normalizeLongitude(lon - lon0), lat);
|
|
55886
|
+
},
|
|
55887
|
+
findTransitionRegion: function(lon, lat) {
|
|
55888
|
+
return findClassicRegion(defn, normalizeLongitude(lon - lon0), lat);
|
|
55889
|
+
},
|
|
55890
|
+
constrainRegionPoint: function(lon, lat, regionId) {
|
|
55891
|
+
return constrainClassicRegionPoint(defn, lon0, lon, lat, regionId);
|
|
55892
|
+
},
|
|
55893
|
+
getRegionBoundary: function(regionId) {
|
|
55894
|
+
return getClassicRegionBoundary(defn, lon0, regionId, 0.5);
|
|
55895
|
+
}
|
|
54879
55896
|
};
|
|
54880
55897
|
}
|
|
54881
55898
|
|
|
@@ -54905,6 +55922,68 @@ ${svg}
|
|
|
54905
55922
|
};
|
|
54906
55923
|
}
|
|
54907
55924
|
|
|
55925
|
+
function findClassicRegion(defn, lon, lat) {
|
|
55926
|
+
for (var i = 0; i < defn.regions.length; i++) {
|
|
55927
|
+
var region = defn.regions[i];
|
|
55928
|
+
var ring = region.boundary;
|
|
55929
|
+
if (lon >= ring[0][0] && lon <= ring[2][0] &&
|
|
55930
|
+
lat >= ring[0][1] && lat <= ring[2][1]) {
|
|
55931
|
+
return region.id;
|
|
55932
|
+
}
|
|
55933
|
+
}
|
|
55934
|
+
return null;
|
|
55935
|
+
}
|
|
55936
|
+
|
|
55937
|
+
function constrainClassicRegionPoint(defn, lon0, lon, lat, regionId) {
|
|
55938
|
+
var region = findRegionById(defn, regionId);
|
|
55939
|
+
if (!region) return null;
|
|
55940
|
+
var ring = region.boundary;
|
|
55941
|
+
var xmin = ring[0][0];
|
|
55942
|
+
var ymin = ring[0][1];
|
|
55943
|
+
var xmax = ring[2][0];
|
|
55944
|
+
var ymax = ring[2][1];
|
|
55945
|
+
var localLon = normalizeLongitude(lon - lon0);
|
|
55946
|
+
var x = Math.max(xmin, Math.min(xmax, localLon));
|
|
55947
|
+
var y = Math.max(ymin, Math.min(ymax, lat));
|
|
55948
|
+
var cx = (xmin + xmax) / 2;
|
|
55949
|
+
var cy = (ymin + ymax) / 2;
|
|
55950
|
+
var inset = 1e-8;
|
|
55951
|
+
if (x == xmin || x == xmax) x += (cx - x) * inset;
|
|
55952
|
+
if (y == ymin || y == ymax) y += (cy - y) * inset;
|
|
55953
|
+
return [normalizeLongitude(x + lon0), y];
|
|
55954
|
+
}
|
|
55955
|
+
|
|
55956
|
+
function getClassicRegionBoundary(defn, lon0, regionId, interval) {
|
|
55957
|
+
var region = findRegionById(defn, regionId);
|
|
55958
|
+
if (!region) return null;
|
|
55959
|
+
var ring = region.boundary;
|
|
55960
|
+
var corners = [ring[0], ring[1], ring[2], ring[3], ring[0]];
|
|
55961
|
+
var points = [];
|
|
55962
|
+
for (var i = 1; i < corners.length; i++) {
|
|
55963
|
+
var a = corners[i - 1];
|
|
55964
|
+
var b = corners[i];
|
|
55965
|
+
var n = Math.max(1, Math.ceil(Math.max(
|
|
55966
|
+
Math.abs(b[0] - a[0]),
|
|
55967
|
+
Math.abs(b[1] - a[1])
|
|
55968
|
+
) / interval));
|
|
55969
|
+
for (var j = 0; j < n; j++) {
|
|
55970
|
+
points.push([
|
|
55971
|
+
normalizeLongitude(a[0] + (b[0] - a[0]) * j / n + lon0),
|
|
55972
|
+
a[1] + (b[1] - a[1]) * j / n
|
|
55973
|
+
]);
|
|
55974
|
+
}
|
|
55975
|
+
}
|
|
55976
|
+
points.push(points[0].concat());
|
|
55977
|
+
return points;
|
|
55978
|
+
}
|
|
55979
|
+
|
|
55980
|
+
function findRegionById(defn, regionId) {
|
|
55981
|
+
for (var i = 0; i < defn.regions.length; i++) {
|
|
55982
|
+
if (defn.regions[i].id == regionId) return defn.regions[i];
|
|
55983
|
+
}
|
|
55984
|
+
return null;
|
|
55985
|
+
}
|
|
55986
|
+
|
|
54908
55987
|
function cutSeam(coordinates) {
|
|
54909
55988
|
return {
|
|
54910
55989
|
type: 'cut',
|
|
@@ -55611,6 +56690,13 @@ ${svg}
|
|
|
55611
56690
|
|
|
55612
56691
|
var DEFAULT_MESH_INTERVAL = 32;
|
|
55613
56692
|
var DEFAULT_MAX_EDGE_FACTOR = 20;
|
|
56693
|
+
var DEFAULT_TOPOLOGY_MIN_CELL_SIZE = 0.5;
|
|
56694
|
+
var MAX_TOPOLOGY_SUBDIVISION_DEPTH = 12;
|
|
56695
|
+
var TOPOLOGY_SAMPLE_STEPS = 4;
|
|
56696
|
+
var TOPOLOGY_VERTEX_INSET = 1e-7;
|
|
56697
|
+
var PIECE_SAMPLE_STEPS = 4;
|
|
56698
|
+
var EXPANDED_FACET_MAX_EDGE_DEGREES = 2;
|
|
56699
|
+
var EXPANDED_FACET_MAX_CLIP_ERROR = 0.02;
|
|
55614
56700
|
|
|
55615
56701
|
function projectRasterGridForward(raster, srcCRS, destCRS, optsArg) {
|
|
55616
56702
|
var opts = optsArg || {};
|
|
@@ -55621,8 +56707,8 @@ ${svg}
|
|
|
55621
56707
|
var mesh, bbox, outSize, outGrid;
|
|
55622
56708
|
validateRasterGridForProjection(grid);
|
|
55623
56709
|
timeStart(timing, 'mesh');
|
|
55624
|
-
mesh =
|
|
55625
|
-
|
|
56710
|
+
mesh = buildRasterProjectionMesh(grid, srcCRS, destCRS, transform, interval, opts);
|
|
56711
|
+
classifyRasterMesh(mesh, opts);
|
|
55626
56712
|
timeEnd(timing, 'mesh');
|
|
55627
56713
|
bbox = opts.output_bbox || opts.outputBbox || getProjectedMeshBBox(mesh);
|
|
55628
56714
|
if (!bbox) stop$1('Unable to project raster layer');
|
|
@@ -55630,12 +56716,17 @@ ${svg}
|
|
|
55630
56716
|
outGrid = createProjectedRasterGrid(grid, raster, bbox, outSize.width, outSize.height, opts);
|
|
55631
56717
|
timeStart(timing, 'rasterize');
|
|
55632
56718
|
rasterizeProjectedMesh(grid, outGrid, mesh, getRasterProjectionSampleMethod(raster, opts));
|
|
56719
|
+
if (mesh.fillOutputCoverage) {
|
|
56720
|
+
fillProjectedRasterCoverage(outGrid);
|
|
56721
|
+
} else {
|
|
56722
|
+
fillIsolatedProjectedRasterHoles(outGrid);
|
|
56723
|
+
}
|
|
55633
56724
|
timeEnd(timing, 'rasterize');
|
|
55634
56725
|
if (timing) {
|
|
55635
56726
|
timing.outputWidth = outGrid.width;
|
|
55636
56727
|
timing.outputHeight = outGrid.height;
|
|
55637
56728
|
timing.meshVertices = mesh.vertices.length;
|
|
55638
|
-
timing.meshCells = mesh.cells.length;
|
|
56729
|
+
timing.meshCells = mesh.triangles ? mesh.triangles.length : mesh.cells.length;
|
|
55639
56730
|
timing.meshSkippedCells = mesh.skippedCellCount;
|
|
55640
56731
|
}
|
|
55641
56732
|
return outGrid;
|
|
@@ -55672,17 +56763,34 @@ ${svg}
|
|
|
55672
56763
|
var transform = getProjTransform2(srcCRS, destCRS);
|
|
55673
56764
|
var mesh, bbox;
|
|
55674
56765
|
validateRasterGridForProjection(grid);
|
|
55675
|
-
mesh =
|
|
55676
|
-
|
|
56766
|
+
mesh = buildRasterProjectionMesh(grid, srcCRS, destCRS, transform, interval, opts);
|
|
56767
|
+
classifyRasterMesh(mesh, opts);
|
|
55677
56768
|
bbox = getProjectedMeshBBox(mesh);
|
|
55678
56769
|
return bbox;
|
|
55679
56770
|
}
|
|
55680
56771
|
|
|
55681
56772
|
function getProjectedRasterMeshBBox(mesh, optsArg) {
|
|
55682
|
-
|
|
56773
|
+
classifyRasterMesh(mesh, optsArg || {});
|
|
55683
56774
|
return getProjectedMeshBBox(mesh);
|
|
55684
56775
|
}
|
|
55685
56776
|
|
|
56777
|
+
function buildRasterProjectionMesh(grid, srcCRS, destCRS, transform, interval, opts) {
|
|
56778
|
+
var topology = getProjectionTopology(destCRS);
|
|
56779
|
+
if (topology && (topology.raster_source_regions ||
|
|
56780
|
+
topology.raster_spherical_regions)) {
|
|
56781
|
+
return buildExpandedFacetRasterMesh(
|
|
56782
|
+
grid, srcCRS, destCRS, interval, topology);
|
|
56783
|
+
}
|
|
56784
|
+
if (topology && (topology.projectRasterRegion ||
|
|
56785
|
+
topology.projectRegion || topology.constrainRegionPoint)) {
|
|
56786
|
+
return buildPiecewiseProjectedRasterMesh(grid, srcCRS, destCRS, interval, topology);
|
|
56787
|
+
}
|
|
56788
|
+
if (topology && (topology.findTransitionRegion || topology.findRegion)) {
|
|
56789
|
+
return buildTopologyAwareProjectedRasterMesh(grid, srcCRS, destCRS, interval, opts);
|
|
56790
|
+
}
|
|
56791
|
+
return buildProjectedRasterMesh(grid, transform, interval);
|
|
56792
|
+
}
|
|
56793
|
+
|
|
55686
56794
|
function buildProjectedRasterMesh(grid, transform, interval) {
|
|
55687
56795
|
var xs = getMeshStops(grid.width, interval);
|
|
55688
56796
|
var ys = getMeshStops(grid.height, interval);
|
|
@@ -55699,6 +56807,494 @@ ${svg}
|
|
|
55699
56807
|
};
|
|
55700
56808
|
}
|
|
55701
56809
|
|
|
56810
|
+
function buildPiecewiseProjectedRasterMesh(grid, srcCRS, destCRS, interval, topology) {
|
|
56811
|
+
var wgs84 = parseCrsString$1('wgs84');
|
|
56812
|
+
var toGeographic = getProjTransform2(srcCRS, wgs84);
|
|
56813
|
+
var fromGeographic = getProjTransform2(wgs84, srcCRS);
|
|
56814
|
+
var toDestination = getProjTransform2(wgs84, destCRS);
|
|
56815
|
+
interval = Math.min(interval, topology.raster_mesh_interval || interval);
|
|
56816
|
+
var xs = getMeshStops(grid.width, interval);
|
|
56817
|
+
var ys = getMeshStops(grid.height, interval);
|
|
56818
|
+
var regions = topology.raster_regions || topology.regions;
|
|
56819
|
+
var mesh = {
|
|
56820
|
+
xs: xs,
|
|
56821
|
+
ys: ys,
|
|
56822
|
+
vertices: [],
|
|
56823
|
+
cells: [],
|
|
56824
|
+
topologyAware: true,
|
|
56825
|
+
subdivisionSkippedCellCount: 0,
|
|
56826
|
+
fillRegionMask: topology.fill_raster_mask,
|
|
56827
|
+
fillOutputCoverage: topology.fill_raster_coverage,
|
|
56828
|
+
projectedRegions: getProjectedRasterRegions(
|
|
56829
|
+
topology, regions, destCRS, toDestination)
|
|
56830
|
+
};
|
|
56831
|
+
var context = {
|
|
56832
|
+
grid: grid,
|
|
56833
|
+
topology: topology,
|
|
56834
|
+
destCRS: destCRS,
|
|
56835
|
+
toGeographic: toGeographic,
|
|
56836
|
+
fromGeographic: fromGeographic,
|
|
56837
|
+
toDestination: toDestination,
|
|
56838
|
+
findRegion: topology.findRasterRegion || topology.findRegion,
|
|
56839
|
+
projectRegion: topology.projectRasterRegion || topology.projectRegion,
|
|
56840
|
+
pieceHalo: topology.raster_cell_halo === false ? 0 : interval,
|
|
56841
|
+
mesh: mesh
|
|
56842
|
+
};
|
|
56843
|
+
for (var y = 0; y < ys.length - 1; y++) {
|
|
56844
|
+
for (var x = 0; x < xs.length - 1; x++) {
|
|
56845
|
+
appendPiecewiseMeshCells(context, xs[x], ys[y], xs[x + 1], ys[y + 1]);
|
|
56846
|
+
}
|
|
56847
|
+
}
|
|
56848
|
+
return mesh;
|
|
56849
|
+
}
|
|
56850
|
+
|
|
56851
|
+
function buildExpandedFacetRasterMesh(grid, srcCRS, destCRS, interval, topology) {
|
|
56852
|
+
var wgs84 = parseCrsString$1('wgs84');
|
|
56853
|
+
var fromGeographic = getProjTransform2(wgs84, srcCRS);
|
|
56854
|
+
var regions = topology.raster_regions;
|
|
56855
|
+
var mesh = {
|
|
56856
|
+
vertices: [],
|
|
56857
|
+
cells: [],
|
|
56858
|
+
triangles: [],
|
|
56859
|
+
topologyAware: true,
|
|
56860
|
+
subdivisionSkippedCellCount: 0,
|
|
56861
|
+
fillRegionMask: topology.fill_raster_mask,
|
|
56862
|
+
fillOutputCoverage: topology.fill_raster_coverage,
|
|
56863
|
+
projectedRegions: getProjectedRasterRegions(
|
|
56864
|
+
topology, regions, destCRS, getProjTransform2(wgs84, destCRS)),
|
|
56865
|
+
sourceWrapX: isLatLngCRS(srcCRS) &&
|
|
56866
|
+
Math.abs(grid.bbox[2] - grid.bbox[0] - 360) < 1e-3
|
|
56867
|
+
};
|
|
56868
|
+
var sourceRegions = topology.raster_source_regions ||
|
|
56869
|
+
topology.raster_spherical_regions;
|
|
56870
|
+
var piecesBySourceRegion = new Map();
|
|
56871
|
+
regions.forEach(function(region) {
|
|
56872
|
+
var key = getRasterSourceRegionKey(region);
|
|
56873
|
+
var pieces = piecesBySourceRegion.get(key) || [];
|
|
56874
|
+
pieces.push(region);
|
|
56875
|
+
piecesBySourceRegion.set(key, pieces);
|
|
56876
|
+
});
|
|
56877
|
+
var context = {
|
|
56878
|
+
grid: grid,
|
|
56879
|
+
topology: topology,
|
|
56880
|
+
destCRS: destCRS,
|
|
56881
|
+
fromGeographic: fromGeographic,
|
|
56882
|
+
mesh: mesh
|
|
56883
|
+
};
|
|
56884
|
+
sourceRegions.forEach(function(region) {
|
|
56885
|
+
var boundary = region.boundary;
|
|
56886
|
+
var pieces = piecesBySourceRegion.get(getRasterSourceRegionKey(region));
|
|
56887
|
+
var triangles = [];
|
|
56888
|
+
var end = pointsEqual2D(boundary[0], boundary[boundary.length - 1]) ?
|
|
56889
|
+
boundary.length - 1 : boundary.length;
|
|
56890
|
+
for (var i = 1; i < end - 1; i++) {
|
|
56891
|
+
triangles.push([boundary[0], boundary[i], boundary[i + 1]]);
|
|
56892
|
+
}
|
|
56893
|
+
triangles.forEach(function(triangle) {
|
|
56894
|
+
var depth = getSphericalTriangleSubdivisionDepth(
|
|
56895
|
+
triangle, EXPANDED_FACET_MAX_EDGE_DEGREES);
|
|
56896
|
+
subdivideSphericalRasterTriangle(
|
|
56897
|
+
context, triangle, region, pieces, depth);
|
|
56898
|
+
});
|
|
56899
|
+
});
|
|
56900
|
+
return mesh;
|
|
56901
|
+
}
|
|
56902
|
+
|
|
56903
|
+
function getRasterSourceRegionKey(region) {
|
|
56904
|
+
if (region.source_region != null) return String(region.source_region);
|
|
56905
|
+
if (region.facet != null && region.sector != null) {
|
|
56906
|
+
return region.facet + ':' + region.sector;
|
|
56907
|
+
}
|
|
56908
|
+
return String(region.id);
|
|
56909
|
+
}
|
|
56910
|
+
|
|
56911
|
+
function pointsEqual2D(a, b) {
|
|
56912
|
+
return a && b && Math.abs(a[0] - b[0]) < 1e-10 &&
|
|
56913
|
+
Math.abs(a[1] - b[1]) < 1e-10;
|
|
56914
|
+
}
|
|
56915
|
+
|
|
56916
|
+
function getSphericalTriangleSubdivisionDepth(triangle, maxDegrees) {
|
|
56917
|
+
var max = Math.max(
|
|
56918
|
+
sphericalPointDistance(triangle[0], triangle[1]),
|
|
56919
|
+
sphericalPointDistance(triangle[1], triangle[2]),
|
|
56920
|
+
sphericalPointDistance(triangle[2], triangle[0])
|
|
56921
|
+
);
|
|
56922
|
+
return Math.max(0, Math.ceil(Math.log(max / maxDegrees) / Math.LN2));
|
|
56923
|
+
}
|
|
56924
|
+
|
|
56925
|
+
function subdivideSphericalRasterTriangle(context, triangle, region, pieces, depth) {
|
|
56926
|
+
if (depth > 0) {
|
|
56927
|
+
var ab = sphericalPointMidpoint(triangle[0], triangle[1]);
|
|
56928
|
+
var bc = sphericalPointMidpoint(triangle[1], triangle[2]);
|
|
56929
|
+
var ca = sphericalPointMidpoint(triangle[2], triangle[0]);
|
|
56930
|
+
subdivideSphericalRasterTriangle(
|
|
56931
|
+
context, [triangle[0], ab, ca], region, pieces, depth - 1);
|
|
56932
|
+
subdivideSphericalRasterTriangle(
|
|
56933
|
+
context, [ab, triangle[1], bc], region, pieces, depth - 1);
|
|
56934
|
+
subdivideSphericalRasterTriangle(
|
|
56935
|
+
context, [ca, bc, triangle[2]], region, pieces, depth - 1);
|
|
56936
|
+
subdivideSphericalRasterTriangle(
|
|
56937
|
+
context, [ab, bc, ca], region, pieces, depth - 1);
|
|
56938
|
+
return;
|
|
56939
|
+
}
|
|
56940
|
+
var rawVertices = triangle.map(function(lonlat) {
|
|
56941
|
+
return projectSphericalRawVertex(context, lonlat, region);
|
|
56942
|
+
});
|
|
56943
|
+
normalizeWrappedTrianglePixels(
|
|
56944
|
+
rawVertices, context.grid.width, context.mesh.sourceWrapX);
|
|
56945
|
+
pieces.forEach(function(piece) {
|
|
56946
|
+
var polygon = context.topology.clipRasterRegionPolygon(
|
|
56947
|
+
rawVertices, piece.id);
|
|
56948
|
+
if (!rasterPiecePolygonIsAccurate(
|
|
56949
|
+
context.topology, polygon, piece.id)) return;
|
|
56950
|
+
polygon.forEach(function(vertex) {
|
|
56951
|
+
var p = scaleRawProjectionPoint(
|
|
56952
|
+
context.destCRS, [vertex.x, vertex.y]);
|
|
56953
|
+
vertex.x = p[0];
|
|
56954
|
+
vertex.y = p[1];
|
|
56955
|
+
});
|
|
56956
|
+
for (var i = 1; i < polygon.length - 1; i++) {
|
|
56957
|
+
var vertices = [polygon[0], polygon[i], polygon[i + 1]];
|
|
56958
|
+
context.mesh.vertices.push(vertices[0], vertices[1], vertices[2]);
|
|
56959
|
+
context.mesh.triangles.push({
|
|
56960
|
+
a: vertices[0],
|
|
56961
|
+
b: vertices[1],
|
|
56962
|
+
c: vertices[2],
|
|
56963
|
+
region: piece.id,
|
|
56964
|
+
valid: vertices.every(vertexIsValid)
|
|
56965
|
+
});
|
|
56966
|
+
}
|
|
56967
|
+
});
|
|
56968
|
+
}
|
|
56969
|
+
|
|
56970
|
+
function projectSphericalRawVertex(context, lonlat, region) {
|
|
56971
|
+
var sourceXY = context.fromGeographic(lonlat[0], lonlat[1]);
|
|
56972
|
+
var sourcePixel = sourceXY &&
|
|
56973
|
+
rasterMapXYToPixel(context.grid, sourceXY[0], sourceXY[1]);
|
|
56974
|
+
var p = context.topology.projectRasterSourceRegion ?
|
|
56975
|
+
context.topology.projectRasterSourceRegion(
|
|
56976
|
+
lonlat[0], lonlat[1], region.id) :
|
|
56977
|
+
context.topology.projectRasterSector(
|
|
56978
|
+
lonlat[0], lonlat[1], region.facet, region.sector);
|
|
56979
|
+
return {
|
|
56980
|
+
sx: sourcePixel ? sourcePixel[0] : NaN,
|
|
56981
|
+
sy: sourcePixel ? sourcePixel[1] : NaN,
|
|
56982
|
+
x: p && isFinite(p[0]) ? p[0] : NaN,
|
|
56983
|
+
y: p && isFinite(p[1]) ? p[1] : NaN,
|
|
56984
|
+
lon: lonlat[0],
|
|
56985
|
+
lat: lonlat[1]
|
|
56986
|
+
};
|
|
56987
|
+
}
|
|
56988
|
+
|
|
56989
|
+
function rasterPiecePolygonIsAccurate(topology, polygon, regionId) {
|
|
56990
|
+
// A triangle that crosses a forced sector discontinuity can yield invalid
|
|
56991
|
+
// interpolated clip vertices. Adjacent triangles cover the rejected sliver.
|
|
56992
|
+
return polygon.every(function(vertex) {
|
|
56993
|
+
var p = topology.projectRasterRegion(
|
|
56994
|
+
vertex.lon, vertex.lat, regionId);
|
|
56995
|
+
return p && Math.hypot(vertex.x - p[0], vertex.y - p[1]) <
|
|
56996
|
+
EXPANDED_FACET_MAX_CLIP_ERROR;
|
|
56997
|
+
});
|
|
56998
|
+
}
|
|
56999
|
+
|
|
57000
|
+
function normalizeWrappedTrianglePixels(vertices, width, wrap) {
|
|
57001
|
+
if (!wrap) return;
|
|
57002
|
+
var xmin = Math.min(vertices[0].sx, vertices[1].sx, vertices[2].sx);
|
|
57003
|
+
var xmax = Math.max(vertices[0].sx, vertices[1].sx, vertices[2].sx);
|
|
57004
|
+
if (xmax - xmin <= width / 2) return;
|
|
57005
|
+
vertices.forEach(function(vertex) {
|
|
57006
|
+
if (vertex.sx < width / 2) vertex.sx += width;
|
|
57007
|
+
});
|
|
57008
|
+
}
|
|
57009
|
+
|
|
57010
|
+
function sphericalPointMidpoint(a, b) {
|
|
57011
|
+
var av = lonLatToVector(a);
|
|
57012
|
+
var bv = lonLatToVector(b);
|
|
57013
|
+
return vectorToLonLat(normalizeVector3([
|
|
57014
|
+
av[0] + bv[0],
|
|
57015
|
+
av[1] + bv[1],
|
|
57016
|
+
av[2] + bv[2]
|
|
57017
|
+
]));
|
|
57018
|
+
}
|
|
57019
|
+
|
|
57020
|
+
function sphericalPointDistance(a, b) {
|
|
57021
|
+
var av = lonLatToVector(a);
|
|
57022
|
+
var bv = lonLatToVector(b);
|
|
57023
|
+
return Math.acos(clamp$1(
|
|
57024
|
+
av[0] * bv[0] + av[1] * bv[1] + av[2] * bv[2], -1, 1
|
|
57025
|
+
)) * 180 / Math.PI;
|
|
57026
|
+
}
|
|
57027
|
+
|
|
57028
|
+
function lonLatToVector(p) {
|
|
57029
|
+
var lam = p[0] * Math.PI / 180;
|
|
57030
|
+
var phi = p[1] * Math.PI / 180;
|
|
57031
|
+
var cosPhi = Math.cos(phi);
|
|
57032
|
+
return [Math.cos(lam) * cosPhi, Math.sin(lam) * cosPhi, Math.sin(phi)];
|
|
57033
|
+
}
|
|
57034
|
+
|
|
57035
|
+
function vectorToLonLat(p) {
|
|
57036
|
+
return [
|
|
57037
|
+
Math.atan2(p[1], p[0]) * 180 / Math.PI,
|
|
57038
|
+
Math.asin(clamp$1(p[2], -1, 1)) * 180 / Math.PI
|
|
57039
|
+
];
|
|
57040
|
+
}
|
|
57041
|
+
|
|
57042
|
+
function normalizeVector3(p) {
|
|
57043
|
+
var k = 1 / Math.hypot(p[0], p[1], p[2]);
|
|
57044
|
+
return [p[0] * k, p[1] * k, p[2] * k];
|
|
57045
|
+
}
|
|
57046
|
+
|
|
57047
|
+
function appendPiecewiseMeshCells(context, x0, y0, x1, y1) {
|
|
57048
|
+
getPieceRegionsInCell(context, x0, y0, x1, y1).forEach(function(regionId) {
|
|
57049
|
+
var v00 = projectPiecewiseMeshVertex(context, x0, y0, regionId);
|
|
57050
|
+
var v10 = projectPiecewiseMeshVertex(context, x1, y0, regionId);
|
|
57051
|
+
var v01 = projectPiecewiseMeshVertex(context, x0, y1, regionId);
|
|
57052
|
+
var v11 = projectPiecewiseMeshVertex(context, x1, y1, regionId);
|
|
57053
|
+
var cell = {
|
|
57054
|
+
v00: v00,
|
|
57055
|
+
v10: v10,
|
|
57056
|
+
v01: v01,
|
|
57057
|
+
v11: v11,
|
|
57058
|
+
region: regionId,
|
|
57059
|
+
valid: vertexIsValid(v00) && vertexIsValid(v10) &&
|
|
57060
|
+
vertexIsValid(v01) && vertexIsValid(v11)
|
|
57061
|
+
};
|
|
57062
|
+
context.mesh.vertices.push(v00, v10, v01, v11);
|
|
57063
|
+
context.mesh.cells.push(cell);
|
|
57064
|
+
});
|
|
57065
|
+
}
|
|
57066
|
+
|
|
57067
|
+
function getPieceRegionsInCell(context, x0, y0, x1, y1) {
|
|
57068
|
+
var ids = [];
|
|
57069
|
+
var halo = context.pieceHalo;
|
|
57070
|
+
samplePieceRegions(context, ids, x0, y0, x1, y1);
|
|
57071
|
+
if (halo > 0) {
|
|
57072
|
+
samplePieceRegions(
|
|
57073
|
+
context,
|
|
57074
|
+
ids,
|
|
57075
|
+
Math.max(0, x0 - halo),
|
|
57076
|
+
Math.max(0, y0 - halo),
|
|
57077
|
+
Math.min(context.grid.width, x1 + halo),
|
|
57078
|
+
Math.min(context.grid.height, y1 + halo)
|
|
57079
|
+
);
|
|
57080
|
+
}
|
|
57081
|
+
return ids;
|
|
57082
|
+
}
|
|
57083
|
+
|
|
57084
|
+
function samplePieceRegions(context, ids, x0, y0, x1, y1) {
|
|
57085
|
+
for (var iy = 0; iy <= PIECE_SAMPLE_STEPS; iy++) {
|
|
57086
|
+
for (var ix = 0; ix <= PIECE_SAMPLE_STEPS; ix++) {
|
|
57087
|
+
var px = x0 + (x1 - x0) * ix / PIECE_SAMPLE_STEPS;
|
|
57088
|
+
var py = y0 + (y1 - y0) * iy / PIECE_SAMPLE_STEPS;
|
|
57089
|
+
var xy = rasterPixelToMapXY(context.grid, px, py);
|
|
57090
|
+
var lonlat = context.toGeographic(xy[0], xy[1]);
|
|
57091
|
+
var id = lonlat && context.findRegion(lonlat[0], lonlat[1]);
|
|
57092
|
+
if (id != null && id !== -1 && ids.indexOf(id) == -1) ids.push(id);
|
|
57093
|
+
}
|
|
57094
|
+
}
|
|
57095
|
+
}
|
|
57096
|
+
|
|
57097
|
+
function projectPiecewiseMeshVertex(context, px, py, regionId) {
|
|
57098
|
+
var xy = rasterPixelToMapXY(context.grid, px, py);
|
|
57099
|
+
var lonlat = context.toGeographic(xy[0], xy[1]);
|
|
57100
|
+
var p, sourcePixel;
|
|
57101
|
+
if (!lonlat) return {sx: px, sy: py, x: NaN, y: NaN};
|
|
57102
|
+
if (context.projectRegion) {
|
|
57103
|
+
p = context.projectRegion(lonlat[0], lonlat[1], regionId);
|
|
57104
|
+
p = scaleRawProjectionPoint(context.destCRS, p);
|
|
57105
|
+
sourcePixel = [px, py];
|
|
57106
|
+
} else {
|
|
57107
|
+
lonlat = context.topology.constrainRegionPoint(lonlat[0], lonlat[1], regionId);
|
|
57108
|
+
xy = lonlat && context.fromGeographic(lonlat[0], lonlat[1]);
|
|
57109
|
+
p = lonlat && context.toDestination(lonlat[0], lonlat[1]);
|
|
57110
|
+
sourcePixel = xy && rasterMapXYToPixel(context.grid, xy[0], xy[1]);
|
|
57111
|
+
}
|
|
57112
|
+
return {
|
|
57113
|
+
sx: sourcePixel ? sourcePixel[0] : px,
|
|
57114
|
+
sy: sourcePixel ? sourcePixel[1] : py,
|
|
57115
|
+
x: p && isFinite(p[0]) ? p[0] : NaN,
|
|
57116
|
+
y: p && isFinite(p[1]) ? p[1] : NaN
|
|
57117
|
+
};
|
|
57118
|
+
}
|
|
57119
|
+
|
|
57120
|
+
function getProjectedRasterRegions(topology, regions, destCRS, toDestination) {
|
|
57121
|
+
return regions.map(function(region) {
|
|
57122
|
+
var boundary;
|
|
57123
|
+
if (region.projected_boundary) {
|
|
57124
|
+
boundary = region.projected_boundary.map(function(p) {
|
|
57125
|
+
return scaleRawProjectionPoint(destCRS, p);
|
|
57126
|
+
});
|
|
57127
|
+
} else {
|
|
57128
|
+
boundary = topology.getRegionBoundary(region.id).map(function(p) {
|
|
57129
|
+
var q = topology.constrainRegionPoint(p[0], p[1], region.id);
|
|
57130
|
+
return toDestination(q[0], q[1]);
|
|
57131
|
+
});
|
|
57132
|
+
}
|
|
57133
|
+
return {
|
|
57134
|
+
id: region.id,
|
|
57135
|
+
boundary: boundary
|
|
57136
|
+
};
|
|
57137
|
+
});
|
|
57138
|
+
}
|
|
57139
|
+
|
|
57140
|
+
function scaleRawProjectionPoint(P, p) {
|
|
57141
|
+
if (!p) return null;
|
|
57142
|
+
return [
|
|
57143
|
+
P.fr_meter * (P.a * p[0] + P.x0),
|
|
57144
|
+
P.fr_meter * (P.a * p[1] + P.y0)
|
|
57145
|
+
];
|
|
57146
|
+
}
|
|
57147
|
+
|
|
57148
|
+
function buildTopologyAwareProjectedRasterMesh(grid, srcCRS, destCRS, interval, optsArg) {
|
|
57149
|
+
var opts = optsArg || {};
|
|
57150
|
+
var topology = getProjectionTopology(destCRS);
|
|
57151
|
+
var findRegion = topology && (topology.findTransitionRegion || topology.findRegion);
|
|
57152
|
+
var wgs84 = parseCrsString$1('wgs84');
|
|
57153
|
+
var toGeographic = getProjTransform2(srcCRS, wgs84);
|
|
57154
|
+
var toDestination = getProjTransform2(wgs84, destCRS);
|
|
57155
|
+
var xs = getMeshStops(grid.width, interval);
|
|
57156
|
+
var ys = getMeshStops(grid.height, interval);
|
|
57157
|
+
var minCellSize = opts.raster_topology_min_cell_size ||
|
|
57158
|
+
opts.rasterTopologyMinCellSize ||
|
|
57159
|
+
DEFAULT_TOPOLOGY_MIN_CELL_SIZE;
|
|
57160
|
+
var mesh = {
|
|
57161
|
+
xs: xs,
|
|
57162
|
+
ys: ys,
|
|
57163
|
+
vertices: [],
|
|
57164
|
+
cells: [],
|
|
57165
|
+
topologyAware: true,
|
|
57166
|
+
subdivisionSkippedCellCount: 0
|
|
57167
|
+
};
|
|
57168
|
+
var context = {
|
|
57169
|
+
grid: grid,
|
|
57170
|
+
findRegion: findRegion,
|
|
57171
|
+
toGeographic: toGeographic,
|
|
57172
|
+
toDestination: toDestination,
|
|
57173
|
+
minCellSize: Math.max(0.01, minCellSize),
|
|
57174
|
+
maxDepth: MAX_TOPOLOGY_SUBDIVISION_DEPTH,
|
|
57175
|
+
mesh: mesh
|
|
57176
|
+
};
|
|
57177
|
+
if (!findRegion) return buildProjectedRasterMesh(grid, getProjTransform2(srcCRS, destCRS), interval);
|
|
57178
|
+
for (var y = 0; y < ys.length - 1; y++) {
|
|
57179
|
+
for (var x = 0; x < xs.length - 1; x++) {
|
|
57180
|
+
addTopologyMeshCell(context, xs[x], ys[y], xs[x + 1], ys[y + 1], 0);
|
|
57181
|
+
}
|
|
57182
|
+
}
|
|
57183
|
+
return mesh;
|
|
57184
|
+
}
|
|
57185
|
+
|
|
57186
|
+
function addTopologyMeshCell(context, x0, y0, x1, y1, depth) {
|
|
57187
|
+
var classification = classifyTopologyCell(context, x0, y0, x1, y1);
|
|
57188
|
+
var width = x1 - x0;
|
|
57189
|
+
var height = y1 - y0;
|
|
57190
|
+
var splitX = width > context.minCellSize && depth < context.maxDepth;
|
|
57191
|
+
var splitY = height > context.minCellSize && depth < context.maxDepth;
|
|
57192
|
+
if (classification.mixed && (splitX || splitY)) {
|
|
57193
|
+
subdivideTopologyMeshCell(context, x0, y0, x1, y1, depth, splitX, splitY);
|
|
57194
|
+
return;
|
|
57195
|
+
}
|
|
57196
|
+
if (classification.region == null || classification.mixed) {
|
|
57197
|
+
context.mesh.subdivisionSkippedCellCount++;
|
|
57198
|
+
return;
|
|
57199
|
+
}
|
|
57200
|
+
appendTopologyMeshCell(context, x0, y0, x1, y1, classification.region);
|
|
57201
|
+
}
|
|
57202
|
+
|
|
57203
|
+
function subdivideTopologyMeshCell(context, x0, y0, x1, y1, depth, splitX, splitY) {
|
|
57204
|
+
var xm = splitX ? (x0 + x1) / 2 : x1;
|
|
57205
|
+
var ym = splitY ? (y0 + y1) / 2 : y1;
|
|
57206
|
+
addTopologyMeshCell(context, x0, y0, xm, ym, depth + 1);
|
|
57207
|
+
if (splitX) addTopologyMeshCell(context, xm, y0, x1, ym, depth + 1);
|
|
57208
|
+
if (splitY) addTopologyMeshCell(context, x0, ym, xm, y1, depth + 1);
|
|
57209
|
+
if (splitX && splitY) addTopologyMeshCell(context, xm, ym, x1, y1, depth + 1);
|
|
57210
|
+
}
|
|
57211
|
+
|
|
57212
|
+
function classifyTopologyCell(context, x0, y0, x1, y1) {
|
|
57213
|
+
var cx = (x0 + x1) / 2;
|
|
57214
|
+
var cy = (y0 + y1) / 2;
|
|
57215
|
+
var region = getTopologyRegionAtPixel(context, cx, cy);
|
|
57216
|
+
var mixed = false;
|
|
57217
|
+
for (var iy = 0; iy <= TOPOLOGY_SAMPLE_STEPS && !mixed; iy++) {
|
|
57218
|
+
for (var ix = 0; ix <= TOPOLOGY_SAMPLE_STEPS; ix++) {
|
|
57219
|
+
var px = x0 + (x1 - x0) * ix / TOPOLOGY_SAMPLE_STEPS;
|
|
57220
|
+
var py = y0 + (y1 - y0) * iy / TOPOLOGY_SAMPLE_STEPS;
|
|
57221
|
+
px += (cx - px) * TOPOLOGY_VERTEX_INSET;
|
|
57222
|
+
py += (cy - py) * TOPOLOGY_VERTEX_INSET;
|
|
57223
|
+
if (getTopologyRegionAtPixel(context, px, py) !== region) {
|
|
57224
|
+
mixed = true;
|
|
57225
|
+
break;
|
|
57226
|
+
}
|
|
57227
|
+
}
|
|
57228
|
+
}
|
|
57229
|
+
return {region: region, mixed: mixed};
|
|
57230
|
+
}
|
|
57231
|
+
|
|
57232
|
+
function getTopologyRegionAtPixel(context, px, py) {
|
|
57233
|
+
var xy = rasterPixelToMapXY(context.grid, px, py);
|
|
57234
|
+
var lonlat = context.toGeographic(xy[0], xy[1]);
|
|
57235
|
+
if (!lonlat) return null;
|
|
57236
|
+
return context.findRegion(lonlat[0], lonlat[1]);
|
|
57237
|
+
}
|
|
57238
|
+
|
|
57239
|
+
function appendTopologyMeshCell(context, x0, y0, x1, y1, region) {
|
|
57240
|
+
var cx = (x0 + x1) / 2;
|
|
57241
|
+
var cy = (y0 + y1) / 2;
|
|
57242
|
+
var v00 = projectTopologyMeshVertex(context, x0, y0, cx, cy);
|
|
57243
|
+
var v10 = projectTopologyMeshVertex(context, x1, y0, cx, cy);
|
|
57244
|
+
var v01 = projectTopologyMeshVertex(context, x0, y1, cx, cy);
|
|
57245
|
+
var v11 = projectTopologyMeshVertex(context, x1, y1, cx, cy);
|
|
57246
|
+
var cell = {
|
|
57247
|
+
v00: v00,
|
|
57248
|
+
v10: v10,
|
|
57249
|
+
v01: v01,
|
|
57250
|
+
v11: v11,
|
|
57251
|
+
region: region,
|
|
57252
|
+
valid: vertexIsValid(v00) && vertexIsValid(v10) &&
|
|
57253
|
+
vertexIsValid(v01) && vertexIsValid(v11)
|
|
57254
|
+
};
|
|
57255
|
+
context.mesh.vertices.push(v00, v10, v01, v11);
|
|
57256
|
+
context.mesh.cells.push(cell);
|
|
57257
|
+
}
|
|
57258
|
+
|
|
57259
|
+
function projectTopologyMeshVertex(context, px, py, cx, cy) {
|
|
57260
|
+
var insetX = px + (cx - px) * TOPOLOGY_VERTEX_INSET;
|
|
57261
|
+
var insetY = py + (cy - py) * TOPOLOGY_VERTEX_INSET;
|
|
57262
|
+
var xy = rasterPixelToMapXY(context.grid, insetX, insetY);
|
|
57263
|
+
var lonlat = context.toGeographic(xy[0], xy[1]);
|
|
57264
|
+
var p = lonlat && context.toDestination(lonlat[0], lonlat[1]);
|
|
57265
|
+
return {
|
|
57266
|
+
sx: px,
|
|
57267
|
+
sy: py,
|
|
57268
|
+
x: p && isFinite(p[0]) ? p[0] : NaN,
|
|
57269
|
+
y: p && isFinite(p[1]) ? p[1] : NaN
|
|
57270
|
+
};
|
|
57271
|
+
}
|
|
57272
|
+
|
|
57273
|
+
function classifyRasterMesh(mesh, opts) {
|
|
57274
|
+
if (mesh.topologyAware) {
|
|
57275
|
+
classifyTopologyMeshCells(mesh);
|
|
57276
|
+
} else {
|
|
57277
|
+
classifyProjectedMeshCells(mesh, opts);
|
|
57278
|
+
}
|
|
57279
|
+
}
|
|
57280
|
+
|
|
57281
|
+
function classifyTopologyMeshCells(mesh) {
|
|
57282
|
+
var filtered = 0;
|
|
57283
|
+
mesh.cells.forEach(function(cell) {
|
|
57284
|
+
cell.maxEdge = getCellMaxEdge(cell);
|
|
57285
|
+
if (!cell.valid) {
|
|
57286
|
+
cell.valid = false;
|
|
57287
|
+
filtered++;
|
|
57288
|
+
}
|
|
57289
|
+
});
|
|
57290
|
+
// Topology-aware cells never span projection branches. Do not apply the
|
|
57291
|
+
// regular mesh's median-edge outlier filter here: adaptive subdivision
|
|
57292
|
+
// creates many small boundary cells that would make valid interior cells
|
|
57293
|
+
// appear to be outliers.
|
|
57294
|
+
mesh.maxEdge = Infinity;
|
|
57295
|
+
mesh.skippedCellCount = mesh.subdivisionSkippedCellCount + filtered;
|
|
57296
|
+
}
|
|
57297
|
+
|
|
55702
57298
|
function classifyProjectedMeshCells(mesh, opts) {
|
|
55703
57299
|
var cols = mesh.xs.length;
|
|
55704
57300
|
var cells = [];
|
|
@@ -55882,17 +57478,41 @@ ${svg}
|
|
|
55882
57478
|
];
|
|
55883
57479
|
}
|
|
55884
57480
|
|
|
57481
|
+
function rasterMapXYToPixel(grid, x, y) {
|
|
57482
|
+
var t = grid.transform;
|
|
57483
|
+
if (t) {
|
|
57484
|
+
return [
|
|
57485
|
+
(x - t[2]) / t[0],
|
|
57486
|
+
(y - t[5]) / t[4]
|
|
57487
|
+
];
|
|
57488
|
+
}
|
|
57489
|
+
return [
|
|
57490
|
+
(x - grid.bbox[0]) / (grid.bbox[2] - grid.bbox[0]) * grid.width,
|
|
57491
|
+
(grid.bbox[3] - y) / (grid.bbox[3] - grid.bbox[1]) * grid.height
|
|
57492
|
+
];
|
|
57493
|
+
}
|
|
57494
|
+
|
|
55885
57495
|
function getProjectedMeshBBox(mesh) {
|
|
55886
57496
|
var xmin = Infinity, ymin = Infinity, xmax = -Infinity, ymax = -Infinity;
|
|
55887
|
-
mesh.
|
|
55888
|
-
|
|
55889
|
-
|
|
55890
|
-
if (p.x < xmin) xmin = p.x;
|
|
55891
|
-
if (p.x > xmax) xmax = p.x;
|
|
55892
|
-
if (p.y < ymin) ymin = p.y;
|
|
55893
|
-
if (p.y > ymax) ymax = p.y;
|
|
57497
|
+
if (mesh.projectedRegions) {
|
|
57498
|
+
mesh.projectedRegions.forEach(function(region) {
|
|
57499
|
+
region.boundary.forEach(expand);
|
|
55894
57500
|
});
|
|
55895
|
-
}
|
|
57501
|
+
} else {
|
|
57502
|
+
mesh.cells.forEach(function(cell) {
|
|
57503
|
+
if (!cell.valid) return;
|
|
57504
|
+
[cell.v00, cell.v10, cell.v01, cell.v11].forEach(expand);
|
|
57505
|
+
});
|
|
57506
|
+
}
|
|
57507
|
+
function expand(p) {
|
|
57508
|
+
if (!p) return;
|
|
57509
|
+
var x = Array.isArray(p) ? p[0] : p.x;
|
|
57510
|
+
var y = Array.isArray(p) ? p[1] : p.y;
|
|
57511
|
+
if (x < xmin) xmin = x;
|
|
57512
|
+
if (x > xmax) xmax = x;
|
|
57513
|
+
if (y < ymin) ymin = y;
|
|
57514
|
+
if (y > ymax) ymax = y;
|
|
57515
|
+
}
|
|
55896
57516
|
return xmin < Infinity && xmax > xmin && ymax > ymin ? [xmin, ymin, xmax, ymax] : null;
|
|
55897
57517
|
}
|
|
55898
57518
|
|
|
@@ -55985,14 +57605,151 @@ ${svg}
|
|
|
55985
57605
|
}
|
|
55986
57606
|
|
|
55987
57607
|
function rasterizeProjectedMesh(srcGrid, destGrid, mesh, sampleMethod) {
|
|
57608
|
+
var regionData = mesh.projectedRegions ?
|
|
57609
|
+
createProjectedRegionMask(
|
|
57610
|
+
destGrid, mesh.projectedRegions, mesh.fillRegionMask) :
|
|
57611
|
+
null;
|
|
57612
|
+
(mesh.triangles || []).forEach(function(triangle) {
|
|
57613
|
+
if (!triangle.valid) return;
|
|
57614
|
+
var regionValue = regionData && regionData.values.get(triangle.region);
|
|
57615
|
+
rasterizeProjectedTriangle(
|
|
57616
|
+
srcGrid, destGrid, triangle.a, triangle.b, triangle.c,
|
|
57617
|
+
sampleMethod, regionData && regionData.mask, regionValue,
|
|
57618
|
+
mesh.sourceWrapX
|
|
57619
|
+
);
|
|
57620
|
+
});
|
|
55988
57621
|
mesh.cells.forEach(function(cell) {
|
|
55989
57622
|
if (!cell.valid) return;
|
|
55990
|
-
|
|
55991
|
-
rasterizeProjectedTriangle(
|
|
57623
|
+
var regionValue = regionData && regionData.values.get(cell.region);
|
|
57624
|
+
rasterizeProjectedTriangle(
|
|
57625
|
+
srcGrid, destGrid, cell.v00, cell.v10, cell.v11,
|
|
57626
|
+
sampleMethod, regionData && regionData.mask, regionValue, false
|
|
57627
|
+
);
|
|
57628
|
+
rasterizeProjectedTriangle(
|
|
57629
|
+
srcGrid, destGrid, cell.v00, cell.v11, cell.v01,
|
|
57630
|
+
sampleMethod, regionData && regionData.mask, regionValue, false
|
|
57631
|
+
);
|
|
57632
|
+
});
|
|
57633
|
+
}
|
|
57634
|
+
|
|
57635
|
+
function fillIsolatedProjectedRasterHoles(grid) {
|
|
57636
|
+
var holes = [];
|
|
57637
|
+
var width = grid.width;
|
|
57638
|
+
var height = grid.height;
|
|
57639
|
+
var coverage = grid.coverage;
|
|
57640
|
+
for (var y = 1; y < height - 1; y++) {
|
|
57641
|
+
for (var x = 1; x < width - 1; x++) {
|
|
57642
|
+
var i = y * width + x;
|
|
57643
|
+
if (!coverage[i] &&
|
|
57644
|
+
coverage[i - 1] && coverage[i + 1] &&
|
|
57645
|
+
coverage[i - width] && coverage[i + width]) {
|
|
57646
|
+
holes.push(i);
|
|
57647
|
+
}
|
|
57648
|
+
}
|
|
57649
|
+
}
|
|
57650
|
+
holes.forEach(function(i) {
|
|
57651
|
+
var src = (i - 1) * grid.bands;
|
|
57652
|
+
var dest = i * grid.bands;
|
|
57653
|
+
for (var band = 0; band < grid.bands; band++) {
|
|
57654
|
+
grid.samples[dest + band] = grid.samples[src + band];
|
|
57655
|
+
}
|
|
57656
|
+
coverage[i] = 1;
|
|
55992
57657
|
});
|
|
55993
57658
|
}
|
|
55994
57659
|
|
|
55995
|
-
function
|
|
57660
|
+
function fillProjectedRasterCoverage(grid) {
|
|
57661
|
+
// Used only for layouts whose projected outline fills the output rectangle.
|
|
57662
|
+
var width = grid.width;
|
|
57663
|
+
var height = grid.height;
|
|
57664
|
+
var coverage = grid.coverage;
|
|
57665
|
+
for (var y = 0; y < height; y++) {
|
|
57666
|
+
var row = y * width;
|
|
57667
|
+
var source = -1;
|
|
57668
|
+
for (var x = 0; x < width; x++) {
|
|
57669
|
+
var i = row + x;
|
|
57670
|
+
if (coverage[i]) {
|
|
57671
|
+
source = i;
|
|
57672
|
+
} else if (source >= 0) {
|
|
57673
|
+
copyProjectedRasterPixel(grid, source, i);
|
|
57674
|
+
}
|
|
57675
|
+
}
|
|
57676
|
+
source = -1;
|
|
57677
|
+
for (x = width - 1; x >= 0; x--) {
|
|
57678
|
+
i = row + x;
|
|
57679
|
+
if (coverage[i]) {
|
|
57680
|
+
source = i;
|
|
57681
|
+
} else if (source >= 0) {
|
|
57682
|
+
copyProjectedRasterPixel(grid, source, i);
|
|
57683
|
+
}
|
|
57684
|
+
}
|
|
57685
|
+
}
|
|
57686
|
+
}
|
|
57687
|
+
|
|
57688
|
+
function copyProjectedRasterPixel(grid, sourceIndex, destIndex) {
|
|
57689
|
+
var source = sourceIndex * grid.bands;
|
|
57690
|
+
var dest = destIndex * grid.bands;
|
|
57691
|
+
for (var band = 0; band < grid.bands; band++) {
|
|
57692
|
+
grid.samples[dest + band] = grid.samples[source + band];
|
|
57693
|
+
}
|
|
57694
|
+
grid.coverage[destIndex] = 1;
|
|
57695
|
+
}
|
|
57696
|
+
|
|
57697
|
+
function createProjectedRegionMask(grid, regions, fill) {
|
|
57698
|
+
var mask = new Uint8Array(grid.width * grid.height);
|
|
57699
|
+
var values = new Map();
|
|
57700
|
+
regions.forEach(function(region, i) {
|
|
57701
|
+
var value = i + 1;
|
|
57702
|
+
values.set(region.id, value);
|
|
57703
|
+
rasterizeRegionMask(grid, mask, region.boundary, value);
|
|
57704
|
+
});
|
|
57705
|
+
if (fill) fillRegionMask(mask, grid.width, grid.height);
|
|
57706
|
+
return {mask: mask, values: values};
|
|
57707
|
+
}
|
|
57708
|
+
|
|
57709
|
+
function fillRegionMask(mask, width, height) {
|
|
57710
|
+
for (var y = 0; y < height; y++) {
|
|
57711
|
+
var row = y * width;
|
|
57712
|
+
var value = 0;
|
|
57713
|
+
for (var x = 0; x < width; x++) {
|
|
57714
|
+
if (mask[row + x]) value = mask[row + x];
|
|
57715
|
+
else if (value) mask[row + x] = value;
|
|
57716
|
+
}
|
|
57717
|
+
value = 0;
|
|
57718
|
+
for (x = width - 1; x >= 0; x--) {
|
|
57719
|
+
if (mask[row + x]) value = mask[row + x];
|
|
57720
|
+
else if (value) mask[row + x] = value;
|
|
57721
|
+
}
|
|
57722
|
+
}
|
|
57723
|
+
}
|
|
57724
|
+
|
|
57725
|
+
function rasterizeRegionMask(grid, mask, boundary, value) {
|
|
57726
|
+
var ring = boundary.map(function(p) {
|
|
57727
|
+
return mapXYToRasterPixel(grid, p[0], p[1]);
|
|
57728
|
+
});
|
|
57729
|
+
var ymin = Math.max(0, Math.floor(Math.min.apply(null, ring.map(function(p) { return p[1]; }))));
|
|
57730
|
+
var ymax = Math.min(grid.height - 1, Math.ceil(Math.max.apply(null, ring.map(function(p) { return p[1]; }))));
|
|
57731
|
+
var intersections = [];
|
|
57732
|
+
for (var y = ymin; y <= ymax; y++) {
|
|
57733
|
+
var py = y + 0.5;
|
|
57734
|
+
intersections.length = 0;
|
|
57735
|
+
for (var i = 1; i < ring.length; i++) {
|
|
57736
|
+
var a = ring[i - 1];
|
|
57737
|
+
var b = ring[i];
|
|
57738
|
+
if ((a[1] > py) == (b[1] > py)) continue;
|
|
57739
|
+
intersections.push(a[0] + (py - a[1]) * (b[0] - a[0]) / (b[1] - a[1]));
|
|
57740
|
+
}
|
|
57741
|
+
intersections.sort(function(a, b) { return a - b; });
|
|
57742
|
+
for (var j = 1; j < intersections.length; j += 2) {
|
|
57743
|
+
var x0 = Math.max(0, Math.ceil(intersections[j - 1] - 0.5));
|
|
57744
|
+
var x1 = Math.min(grid.width - 1, Math.floor(intersections[j] - 0.5));
|
|
57745
|
+
for (var x = x0; x <= x1; x++) {
|
|
57746
|
+
mask[y * grid.width + x] = value;
|
|
57747
|
+
}
|
|
57748
|
+
}
|
|
57749
|
+
}
|
|
57750
|
+
}
|
|
57751
|
+
|
|
57752
|
+
function rasterizeProjectedTriangle(srcGrid, destGrid, a, b, c, sampleMethod, regionMask, regionValue, sourceWrapX) {
|
|
55996
57753
|
var bbox, x0, x1, y0, y1, det, w1, w2, w3, sx, sy, ap, bp, cp;
|
|
55997
57754
|
if (!vertexIsValid(a) || !vertexIsValid(b) || !vertexIsValid(c)) return;
|
|
55998
57755
|
ap = vertexToDestPixel(destGrid, a);
|
|
@@ -56004,13 +57761,15 @@ ${svg}
|
|
|
56004
57761
|
x0 = bbox[0]; y0 = bbox[1]; x1 = bbox[2]; y1 = bbox[3];
|
|
56005
57762
|
for (var y = y0; y <= y1; y++) {
|
|
56006
57763
|
for (var x = x0; x <= x1; x++) {
|
|
57764
|
+
if (regionMask && regionMask[y * destGrid.width + x] != regionValue) continue;
|
|
56007
57765
|
w1 = edgeFunction(bp, cp, x + 0.5, y + 0.5) / det;
|
|
56008
57766
|
w2 = edgeFunction(cp, ap, x + 0.5, y + 0.5) / det;
|
|
56009
57767
|
w3 = 1 - w1 - w2;
|
|
56010
57768
|
if (w1 < -1e-9 || w2 < -1e-9 || w3 < -1e-9) continue;
|
|
56011
57769
|
sx = w1 * a.sx + w2 * b.sx + w3 * c.sx;
|
|
56012
57770
|
sy = w1 * a.sy + w2 * b.sy + w3 * c.sy;
|
|
56013
|
-
copyRasterSample(
|
|
57771
|
+
copyRasterSample(
|
|
57772
|
+
srcGrid, destGrid, sx, sy, x, y, sampleMethod, sourceWrapX);
|
|
56014
57773
|
}
|
|
56015
57774
|
}
|
|
56016
57775
|
}
|
|
@@ -56042,16 +57801,18 @@ ${svg}
|
|
|
56042
57801
|
];
|
|
56043
57802
|
}
|
|
56044
57803
|
|
|
56045
|
-
function copyRasterSample(srcGrid, destGrid, sx, sy, dx, dy, sampleMethod) {
|
|
57804
|
+
function copyRasterSample(srcGrid, destGrid, sx, sy, dx, dy, sampleMethod, wrapX) {
|
|
56046
57805
|
if (sampleMethod == 'bilinear') {
|
|
56047
|
-
copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy);
|
|
57806
|
+
copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX);
|
|
56048
57807
|
} else {
|
|
56049
|
-
copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy);
|
|
57808
|
+
copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX);
|
|
56050
57809
|
}
|
|
56051
57810
|
}
|
|
56052
57811
|
|
|
56053
|
-
function copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy) {
|
|
56054
|
-
var srcX =
|
|
57812
|
+
function copyNearestRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX) {
|
|
57813
|
+
var srcX = wrapX ?
|
|
57814
|
+
modulo(Math.floor(sx), srcGrid.width) :
|
|
57815
|
+
clamp$1(Math.floor(sx), 0, srcGrid.width - 1);
|
|
56055
57816
|
var srcY = clamp$1(Math.floor(sy), 0, srcGrid.height - 1);
|
|
56056
57817
|
var src = (srcY * srcGrid.width + srcX) * srcGrid.bands;
|
|
56057
57818
|
var dest = (dy * destGrid.width + dx) * destGrid.bands;
|
|
@@ -56063,10 +57824,14 @@ ${svg}
|
|
|
56063
57824
|
if (destGrid.coverage) destGrid.coverage[dy * destGrid.width + dx] = 1;
|
|
56064
57825
|
}
|
|
56065
57826
|
|
|
56066
|
-
function copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy) {
|
|
56067
|
-
|
|
57827
|
+
function copyBilinearRasterSample(srcGrid, destGrid, sx, sy, dx, dy, wrapX) {
|
|
57828
|
+
if (wrapX) sx = modulo(sx, srcGrid.width);
|
|
57829
|
+
var srcX = wrapX ?
|
|
57830
|
+
modulo(Math.floor(sx - 0.5), srcGrid.width) :
|
|
57831
|
+
clamp$1(Math.floor(sx - 0.5), 0, srcGrid.width - 1);
|
|
56068
57832
|
var srcY = clamp$1(Math.floor(sy - 0.5), 0, srcGrid.height - 1);
|
|
56069
|
-
var srcX2 =
|
|
57833
|
+
var srcX2 = wrapX ? (srcX + 1) % srcGrid.width :
|
|
57834
|
+
clamp$1(srcX + 1, 0, srcGrid.width - 1);
|
|
56070
57835
|
var srcY2 = clamp$1(srcY + 1, 0, srcGrid.height - 1);
|
|
56071
57836
|
var tx = clamp$1(sx - 0.5 - srcX, 0, 1);
|
|
56072
57837
|
var ty = clamp$1(sy - 0.5 - srcY, 0, 1);
|
|
@@ -56178,9 +57943,14 @@ ${svg}
|
|
|
56178
57943
|
return val < min ? min : val > max ? max : val;
|
|
56179
57944
|
}
|
|
56180
57945
|
|
|
57946
|
+
function modulo(val, base) {
|
|
57947
|
+
return (val % base + base) % base;
|
|
57948
|
+
}
|
|
57949
|
+
|
|
56181
57950
|
var RasterReprojection = /*#__PURE__*/Object.freeze({
|
|
56182
57951
|
__proto__: null,
|
|
56183
57952
|
buildProjectedRasterMesh: buildProjectedRasterMesh,
|
|
57953
|
+
buildTopologyAwareProjectedRasterMesh: buildTopologyAwareProjectedRasterMesh,
|
|
56184
57954
|
getProjectedRasterGridBBox: getProjectedRasterGridBBox,
|
|
56185
57955
|
getProjectedRasterMeshBBox: getProjectedRasterMeshBBox,
|
|
56186
57956
|
projectRasterGridForward: projectRasterGridForward
|
|
@@ -56331,9 +58101,6 @@ ${svg}
|
|
|
56331
58101
|
if (isProjectedCRS(src) && !isInvertibleCRS(src)) {
|
|
56332
58102
|
stop$1('Unable to project from a coordinate system that has no inverse transform');
|
|
56333
58103
|
}
|
|
56334
|
-
if (isInterruptedProjection(dest) && dataset.layers.some(layerHasRaster)) {
|
|
56335
|
-
stop$1('Raster reprojection is not currently supported for interrupted projections');
|
|
56336
|
-
}
|
|
56337
58104
|
var proj = getProjTransform2(src, dest); // v2 returns null points instead of throwing an error
|
|
56338
58105
|
var badArcs = 0;
|
|
56339
58106
|
var badPoints = 0;
|
|
@@ -60733,7 +62500,7 @@ ${svg}
|
|
|
60733
62500
|
// Isometric ("Mercator-stretched") latitude in degrees-in; returns +/-Infinity at
|
|
60734
62501
|
// the poles.
|
|
60735
62502
|
function isometricLatitude(latDeg) {
|
|
60736
|
-
return Math.log(Math.tan(Math.PI / 4 + latDeg * D2R$
|
|
62503
|
+
return Math.log(Math.tan(Math.PI / 4 + latDeg * D2R$8 / 2));
|
|
60737
62504
|
}
|
|
60738
62505
|
|
|
60739
62506
|
// Rhumb-line (loxodrome) interpolation, fraction k of the way from A to B.
|
|
@@ -60758,9 +62525,9 @@ ${svg}
|
|
|
60758
62525
|
// Rhumb-line distance in meters, using the raw longitude delta (so a full-parallel
|
|
60759
62526
|
// sweep returns the parallel's length rather than 0).
|
|
60760
62527
|
function rhumbDistance(a, b) {
|
|
60761
|
-
var phi1 = a[1] * D2R$
|
|
62528
|
+
var phi1 = a[1] * D2R$8, phi2 = b[1] * D2R$8;
|
|
60762
62529
|
var dPhi = phi2 - phi1;
|
|
60763
|
-
var dLambda = (b[0] - a[0]) * D2R$
|
|
62530
|
+
var dLambda = (b[0] - a[0]) * D2R$8; // raw
|
|
60764
62531
|
var dPsi = Math.log(Math.tan(Math.PI / 4 + phi2 / 2) / Math.tan(Math.PI / 4 + phi1 / 2));
|
|
60765
62532
|
var q = Math.abs(dPsi) > 1e-12 ? dPhi / dPsi : Math.cos(phi1);
|
|
60766
62533
|
return Math.sqrt(dPhi * dPhi + q * q * dLambda * dLambda) * R$3;
|
|
@@ -71096,7 +72863,7 @@ ${svg}
|
|
|
71096
72863
|
return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
|
|
71097
72864
|
}
|
|
71098
72865
|
|
|
71099
|
-
var version = "0.7.
|
|
72866
|
+
var version = "0.7.47";
|
|
71100
72867
|
|
|
71101
72868
|
// Parse command line args into commands and run them
|
|
71102
72869
|
// Function takes an optional Node-style callback. A Promise is returned if no callback is given.
|