leaflet-city-mapper 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/leaflet-city-mapper-src.js +1469 -1392
- package/dist/leaflet-city-mapper-src.js.map +4 -4
- package/dist/leaflet-city-mapper.js +3 -3
- package/dist/leaflet-city-mapper.js.map +4 -4
- package/libs/leaflet-lens.js +15 -3
- package/libs/leaflet.js +1 -1
- package/package.json +1 -1
- package/src/collision/collectIntersections.js +16 -0
- package/src/collision/collider.js +3 -2
- package/src/collision/countCrossings.js +15 -0
- package/src/collision/insideMesh.js +4 -24
- package/src/collision/insideWalker.js +2 -2
- package/src/collision/readTriangle.js +7 -4
- package/src/collision/setTrafficNormal.js +9 -0
- package/src/collision/trafficCollision.js +4 -9
- package/src/collision/vertexCount.js +3 -0
- package/src/controls/cameraControls.js +6 -0
- package/src/raster/setRasterOpacity.js +1 -1
- package/src/raster/setRasterZIndex.js +1 -1
- package/src/sources/buildArea.js +3 -12
- package/src/sources/buildAreaFeature.js +2 -5
- package/src/sources/buildAreaFeatures.js +14 -0
- package/src/sources/matchesAreaTile.js +7 -0
- package/src/sources/prepareAreaGeometryJob.js +2 -11
- package/src/sources/projectAreaPolygons.js +15 -0
- package/src/walk/animateWalker.js +2 -13
- package/src/walk/updateWalkerFrame.js +19 -0
- package/src/workers/acquireGeometryWorker.js +2 -5
- package/src/workers/buildAreaInWorker.js +4 -0
- package/src/workers/createGeometryWorker.js +19 -0
|
@@ -214,6 +214,14 @@
|
|
|
214
214
|
}
|
|
215
215
|
});
|
|
216
216
|
|
|
217
|
+
// src/weakmaps/cameraHandlersByMap.js
|
|
218
|
+
var cameraHandlersByMap;
|
|
219
|
+
var init_cameraHandlersByMap = __esm({
|
|
220
|
+
"src/weakmaps/cameraHandlersByMap.js"() {
|
|
221
|
+
cameraHandlersByMap = /* @__PURE__ */ new WeakMap();
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
217
225
|
// src/weakmaps/rotateControlByMap.js
|
|
218
226
|
var rotateControlByMap;
|
|
219
227
|
var init_rotateControlByMap = __esm({
|
|
@@ -222,6 +230,22 @@
|
|
|
222
230
|
}
|
|
223
231
|
});
|
|
224
232
|
|
|
233
|
+
// src/weakmaps/touchPitchByMap.js
|
|
234
|
+
var touchPitchByMap;
|
|
235
|
+
var init_touchPitchByMap = __esm({
|
|
236
|
+
"src/weakmaps/touchPitchByMap.js"() {
|
|
237
|
+
touchPitchByMap = /* @__PURE__ */ new WeakMap();
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// src/weakmaps/touchRotateByMap.js
|
|
242
|
+
var touchRotateByMap;
|
|
243
|
+
var init_touchRotateByMap = __esm({
|
|
244
|
+
"src/weakmaps/touchRotateByMap.js"() {
|
|
245
|
+
touchRotateByMap = /* @__PURE__ */ new WeakMap();
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
225
249
|
// src/globals/Compass.js
|
|
226
250
|
var Compass;
|
|
227
251
|
var init_Compass = __esm({
|
|
@@ -1032,22 +1056,6 @@
|
|
|
1032
1056
|
}
|
|
1033
1057
|
});
|
|
1034
1058
|
|
|
1035
|
-
// src/weakmaps/touchPitchByMap.js
|
|
1036
|
-
var touchPitchByMap;
|
|
1037
|
-
var init_touchPitchByMap = __esm({
|
|
1038
|
-
"src/weakmaps/touchPitchByMap.js"() {
|
|
1039
|
-
touchPitchByMap = /* @__PURE__ */ new WeakMap();
|
|
1040
|
-
}
|
|
1041
|
-
});
|
|
1042
|
-
|
|
1043
|
-
// src/weakmaps/touchRotateByMap.js
|
|
1044
|
-
var touchRotateByMap;
|
|
1045
|
-
var init_touchRotateByMap = __esm({
|
|
1046
|
-
"src/weakmaps/touchRotateByMap.js"() {
|
|
1047
|
-
touchRotateByMap = /* @__PURE__ */ new WeakMap();
|
|
1048
|
-
}
|
|
1049
|
-
});
|
|
1050
|
-
|
|
1051
1059
|
// src/controls/startCameraTouch.js
|
|
1052
1060
|
function startCameraTouch(event) {
|
|
1053
1061
|
const state = touchByContainer.get(this), { map, container } = state;
|
|
@@ -1242,14 +1250,6 @@
|
|
|
1242
1250
|
}
|
|
1243
1251
|
});
|
|
1244
1252
|
|
|
1245
|
-
// src/weakmaps/cameraHandlersByMap.js
|
|
1246
|
-
var cameraHandlersByMap;
|
|
1247
|
-
var init_cameraHandlersByMap = __esm({
|
|
1248
|
-
"src/weakmaps/cameraHandlersByMap.js"() {
|
|
1249
|
-
cameraHandlersByMap = /* @__PURE__ */ new WeakMap();
|
|
1250
|
-
}
|
|
1251
|
-
});
|
|
1252
|
-
|
|
1253
1253
|
// src/controls/addCameraHandler.js
|
|
1254
1254
|
function addCameraHandler(map, name, Type) {
|
|
1255
1255
|
let handlers = cameraHandlersByMap.get(map);
|
|
@@ -1282,6 +1282,8 @@
|
|
|
1282
1282
|
addCameraHandler(map, "compassBearing", Compass.value);
|
|
1283
1283
|
addCameraHandler(map, "touchRotate", TouchMode.value);
|
|
1284
1284
|
addCameraHandler(map, "touchPitch", TouchMode.value);
|
|
1285
|
+
touchRotateByMap.set(map, cameraHandlersByMap.get(map).get("touchRotate"));
|
|
1286
|
+
touchPitchByMap.set(map, cameraHandlersByMap.get(map).get("touchPitch"));
|
|
1285
1287
|
const container = map.getContainer();
|
|
1286
1288
|
const state = (
|
|
1287
1289
|
/* alloc */
|
|
@@ -1296,6 +1298,7 @@
|
|
|
1296
1298
|
container.addEventListener("touchcancel", endCameraTouchEvent, true);
|
|
1297
1299
|
window.addEventListener("blur", endAllCameraTouches);
|
|
1298
1300
|
map.on("cameratouchchange", changeCameraTouch, map);
|
|
1301
|
+
changeCameraTouch.call(map);
|
|
1299
1302
|
if (map.options.rotateControl) {
|
|
1300
1303
|
rotateControlByMap.set(
|
|
1301
1304
|
map,
|
|
@@ -1309,7 +1312,10 @@
|
|
|
1309
1312
|
var init_cameraControls = __esm({
|
|
1310
1313
|
"src/controls/cameraControls.js"() {
|
|
1311
1314
|
init_cameraTouchStateByMap();
|
|
1315
|
+
init_cameraHandlersByMap();
|
|
1312
1316
|
init_rotateControlByMap();
|
|
1317
|
+
init_touchPitchByMap();
|
|
1318
|
+
init_touchRotateByMap();
|
|
1313
1319
|
init_L();
|
|
1314
1320
|
init_Compass();
|
|
1315
1321
|
init_ContainerResize();
|
|
@@ -1707,16 +1713,16 @@
|
|
|
1707
1713
|
}
|
|
1708
1714
|
|
|
1709
1715
|
// src/terrain/getElevation.js
|
|
1710
|
-
function getElevation(layer,
|
|
1716
|
+
function getElevation(layer, location2) {
|
|
1711
1717
|
if (!layer._map || !terrainReadyByLayer.get(layer)) return null;
|
|
1712
|
-
const point =
|
|
1718
|
+
const point = location2 instanceof L.Point ? location2 : layer._map.project(location2, terrainZoomByLayer.get(layer));
|
|
1713
1719
|
return bridgeElevation(point, bridgesByLayer.get(layer)) ?? terrainElevation(point, terrainTilesByLayer.get(layer));
|
|
1714
1720
|
}
|
|
1715
1721
|
|
|
1716
1722
|
// src/terrain/mapElevationOf.js
|
|
1717
|
-
function mapElevationOf(map,
|
|
1723
|
+
function mapElevationOf(map, location2) {
|
|
1718
1724
|
const terrain = terrain3DByMap.get(map);
|
|
1719
|
-
return terrain && getElevation(terrain,
|
|
1725
|
+
return terrain && getElevation(terrain, location2);
|
|
1720
1726
|
}
|
|
1721
1727
|
|
|
1722
1728
|
// src/weakmaps/walkByMap.js
|
|
@@ -6154,18 +6160,24 @@
|
|
|
6154
6160
|
return !(far < near);
|
|
6155
6161
|
}
|
|
6156
6162
|
|
|
6163
|
+
// src/collision/vertexCount.js
|
|
6164
|
+
function vertexCount(position, index) {
|
|
6165
|
+
return index?.count ?? index?.data.length ?? position.count ?? position.data.length / (position.size ?? 3);
|
|
6166
|
+
}
|
|
6167
|
+
|
|
6157
6168
|
// src/collision/readTriangle.js
|
|
6158
6169
|
function readTriangle(mesh, i, a, b, c) {
|
|
6159
6170
|
const { position, index, instanceOffset } = mesh.geometry.attributes;
|
|
6160
|
-
const
|
|
6171
|
+
const size = position.size ?? 3;
|
|
6172
|
+
const vertices = vertexCount(position, index);
|
|
6161
6173
|
const vertex = instanceOffset ? i % vertices : i;
|
|
6162
6174
|
const offset = instanceOffset ? Math.floor(i / vertices) * instanceOffset.size : 0;
|
|
6163
6175
|
const x = instanceOffset?.data[offset] ?? 0;
|
|
6164
6176
|
const y = instanceOffset?.data[offset + 1] ?? 0;
|
|
6165
6177
|
const z = instanceOffset?.data[offset + 2] ?? 0;
|
|
6166
|
-
const ai = (index ? index.data[vertex] : vertex) *
|
|
6167
|
-
const bi = (index ? index.data[vertex + 1] : vertex + 1) *
|
|
6168
|
-
const ci = (index ? index.data[vertex + 2] : vertex + 2) *
|
|
6178
|
+
const ai = (index ? index.data[vertex] : vertex) * size;
|
|
6179
|
+
const bi = (index ? index.data[vertex + 1] : vertex + 1) * size;
|
|
6180
|
+
const ci = (index ? index.data[vertex + 2] : vertex + 2) * size;
|
|
6169
6181
|
a[0] = position.data[ai];
|
|
6170
6182
|
a[1] = position.data[ai + 1];
|
|
6171
6183
|
a[2] = position.data[ai + 2];
|
|
@@ -7621,1274 +7633,1325 @@
|
|
|
7621
7633
|
layer.fire("progress", progress);
|
|
7622
7634
|
}
|
|
7623
7635
|
|
|
7624
|
-
// src/
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
7629
|
-
|
|
7630
|
-
|
|
7631
|
-
const
|
|
7636
|
+
// src/geometry/instanceAreaGeometry.js
|
|
7637
|
+
function instanceAreaGeometry(context) {
|
|
7638
|
+
const { positions, normals, colors, featureFaces } = context;
|
|
7639
|
+
if (context.backend.options.nightLight || featureFaces.length < 2) return context;
|
|
7640
|
+
const vertices = featureFaces[0].vertexEnd;
|
|
7641
|
+
const length = vertices * 3;
|
|
7642
|
+
if (!vertices || positions.length !== length * featureFaces.length) return context;
|
|
7643
|
+
const originX = Math.trunc(positions[0]), originY = Math.trunc(positions[1]), originZ = Math.trunc(positions[2]);
|
|
7644
|
+
const template = (
|
|
7632
7645
|
/* alloc */
|
|
7633
|
-
new
|
|
7646
|
+
new Float32Array(length)
|
|
7647
|
+
);
|
|
7648
|
+
let i, instance, face, start2;
|
|
7649
|
+
for (i = 0; i < length; i++) template[i] = positions[i] - (i % 3 === 0 ? originX : i % 3 === 1 ? originY : originZ);
|
|
7650
|
+
const offsets = (
|
|
7651
|
+
/* alloc */
|
|
7652
|
+
new Float32Array(featureFaces.length * 4)
|
|
7634
7653
|
);
|
|
7635
|
-
|
|
7636
|
-
|
|
7654
|
+
for (instance = 0; instance < featureFaces.length; instance++) {
|
|
7655
|
+
face = featureFaces[instance];
|
|
7656
|
+
start2 = instance * length;
|
|
7657
|
+
if (face.vertexStart !== instance * vertices || face.vertexEnd !== (instance + 1) * vertices) return context;
|
|
7658
|
+
offsets[instance * 4] = originX + positions[start2] - positions[0];
|
|
7659
|
+
offsets[instance * 4 + 1] = originY + positions[start2 + 1] - positions[1];
|
|
7660
|
+
offsets[instance * 4 + 2] = originZ + positions[start2 + 2] - positions[2];
|
|
7661
|
+
offsets[instance * 4 + 3] = instance * vertices;
|
|
7662
|
+
for (i = 0; i < length; i++) {
|
|
7663
|
+
if (Math.fround(template[i] + offsets[instance * 4 + i % 3]) !== Math.fround(positions[start2 + i]) || Math.fround(normals[i]) !== Math.fround(normals[start2 + i]) || Math.fround(colors[i]) !== Math.fround(colors[start2 + i])) return context;
|
|
7664
|
+
}
|
|
7665
|
+
}
|
|
7637
7666
|
return (
|
|
7638
7667
|
/* alloc */
|
|
7639
7668
|
{
|
|
7640
|
-
|
|
7641
|
-
|
|
7642
|
-
|
|
7669
|
+
positions: template,
|
|
7670
|
+
normals: normals.slice(0, length),
|
|
7671
|
+
colors: colors.slice(0, length),
|
|
7672
|
+
instanceOffsets: offsets
|
|
7643
7673
|
}
|
|
7644
7674
|
);
|
|
7645
7675
|
}
|
|
7646
7676
|
|
|
7647
|
-
// src/
|
|
7648
|
-
|
|
7649
|
-
|
|
7650
|
-
|
|
7651
|
-
|
|
7652
|
-
|
|
7653
|
-
}
|
|
7654
|
-
|
|
7655
|
-
// src/geometry/appendAreaTriangle.js
|
|
7656
|
-
function addTriangle(context, a, ah, b, bh, c, ch, nx, ny, nz, color) {
|
|
7657
|
-
const { backend: layer, positions, normals, colors, uvs } = context;
|
|
7658
|
-
const ux = b.x - a.x, uy = bh - ah, uz = a.y - b.y;
|
|
7659
|
-
const vx = c.x - a.x, vy = ch - ah, vz = a.y - c.y;
|
|
7660
|
-
if ((uy * vz - uz * vy) * nx + (uz * vx - ux * vz) * ny + (ux * vy - uy * vx) * nz < 0) {
|
|
7661
|
-
const point = b, height = bh;
|
|
7662
|
-
b = c;
|
|
7663
|
-
bh = ch;
|
|
7664
|
-
c = point;
|
|
7665
|
-
ch = height;
|
|
7666
|
-
}
|
|
7667
|
-
positions.push(
|
|
7668
|
-
a.x,
|
|
7669
|
-
ah + groundOffset(a),
|
|
7670
|
-
-a.y,
|
|
7671
|
-
b.x,
|
|
7672
|
-
bh + groundOffset(b),
|
|
7673
|
-
-b.y,
|
|
7674
|
-
c.x,
|
|
7675
|
-
ch + groundOffset(c),
|
|
7676
|
-
-c.y
|
|
7677
|
-
);
|
|
7678
|
-
normals.push(nx, ny, nz, nx, ny, nz, nx, ny, nz);
|
|
7679
|
-
colors.push(color.r, color.g, color.b, color.r, color.g, color.b, color.r, color.g, color.b);
|
|
7680
|
-
if (layer.options.nightLight) uvs.push(...a.uv, ...b.uv, ...c.uv);
|
|
7681
|
-
}
|
|
7682
|
-
|
|
7683
|
-
// src/geometry/addGeneratedTriangle.js
|
|
7684
|
-
function addGeneratedTriangle(...args) {
|
|
7685
|
-
addTriangle(triangleContexts[triangleContexts.length - 1], ...args);
|
|
7686
|
-
}
|
|
7687
|
-
|
|
7688
|
-
// src/geometry/generateTreeGeometry.js
|
|
7689
|
-
function generateTreeGeometry(context, generator, point, style) {
|
|
7690
|
-
triangleContexts.push(context);
|
|
7691
|
-
try {
|
|
7692
|
-
generator(point, style, addGeneratedTriangle);
|
|
7693
|
-
} finally {
|
|
7694
|
-
triangleContexts.pop();
|
|
7677
|
+
// src/sources/attachAreaMesh.js
|
|
7678
|
+
function attachAreaMesh(context) {
|
|
7679
|
+
const { backend: layer, area: area2 } = context;
|
|
7680
|
+
if (!context.positions.length) {
|
|
7681
|
+
area2.mesh = null, area2.buildings = 0, area2.skipped = context.skipped, area2.done = true;
|
|
7682
|
+
return;
|
|
7695
7683
|
}
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
var lampDirections = [
|
|
7700
|
-
{ x: Math.cos(0 * Math.PI / 3), y: Math.sin(0 * Math.PI / 3), nx: Math.cos(0.5 * Math.PI / 3), nz: -Math.sin(0.5 * Math.PI / 3) },
|
|
7701
|
-
{ x: Math.cos(1 * Math.PI / 3), y: Math.sin(1 * Math.PI / 3), nx: Math.cos(1.5 * Math.PI / 3), nz: -Math.sin(1.5 * Math.PI / 3) },
|
|
7702
|
-
{ x: Math.cos(2 * Math.PI / 3), y: Math.sin(2 * Math.PI / 3), nx: Math.cos(2.5 * Math.PI / 3), nz: -Math.sin(2.5 * Math.PI / 3) },
|
|
7703
|
-
{ x: Math.cos(3 * Math.PI / 3), y: Math.sin(3 * Math.PI / 3), nx: Math.cos(3.5 * Math.PI / 3), nz: -Math.sin(3.5 * Math.PI / 3) },
|
|
7704
|
-
{ x: Math.cos(4 * Math.PI / 3), y: Math.sin(4 * Math.PI / 3), nx: Math.cos(4.5 * Math.PI / 3), nz: -Math.sin(4.5 * Math.PI / 3) },
|
|
7705
|
-
{ x: Math.cos(5 * Math.PI / 3), y: Math.sin(5 * Math.PI / 3), nx: Math.cos(5.5 * Math.PI / 3), nz: -Math.sin(5.5 * Math.PI / 3) }
|
|
7706
|
-
];
|
|
7707
|
-
|
|
7708
|
-
// src/geometry/createLampRing.js
|
|
7709
|
-
function ring(point, radius) {
|
|
7710
|
-
const points = (
|
|
7684
|
+
const device = rendererByLayer.get(layer).device;
|
|
7685
|
+
const data = context.preparedGeometry || instanceAreaGeometry(context);
|
|
7686
|
+
const attributes = (
|
|
7711
7687
|
/* alloc */
|
|
7712
|
-
new Array(lampDirections.length)
|
|
7713
|
-
);
|
|
7714
|
-
let i;
|
|
7715
|
-
for (i = 0; i < points.length; i++) {
|
|
7716
|
-
points[i] = /* alloc */
|
|
7717
7688
|
{
|
|
7718
|
-
|
|
7719
|
-
y: point.y + lampDirections[i].y * radius,
|
|
7720
|
-
ground: point.ground,
|
|
7721
|
-
uv: (
|
|
7689
|
+
position: (
|
|
7722
7690
|
/* alloc */
|
|
7723
|
-
|
|
7691
|
+
{ size: 3, data: data.positions instanceof Float32Array ? data.positions : (
|
|
7692
|
+
/* alloc */
|
|
7693
|
+
new Float32Array(data.positions)
|
|
7694
|
+
) }
|
|
7695
|
+
),
|
|
7696
|
+
normal: (
|
|
7697
|
+
/* alloc */
|
|
7698
|
+
{ size: 3, data: data.normals instanceof Float32Array ? data.normals : (
|
|
7699
|
+
/* alloc */
|
|
7700
|
+
new Float32Array(data.normals)
|
|
7701
|
+
) }
|
|
7702
|
+
),
|
|
7703
|
+
color: (
|
|
7704
|
+
/* alloc */
|
|
7705
|
+
{ size: 3, data: data.colors instanceof Float32Array ? data.colors : (
|
|
7706
|
+
/* alloc */
|
|
7707
|
+
new Float32Array(data.colors)
|
|
7708
|
+
) }
|
|
7724
7709
|
)
|
|
7725
|
-
}
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
if (!Number.isFinite(radius) || radius <= 0) {
|
|
7734
|
-
throw (
|
|
7710
|
+
}
|
|
7711
|
+
);
|
|
7712
|
+
if (data.instanceOffsets) attributes.instanceOffset = /* alloc */
|
|
7713
|
+
{ size: 4, data: data.instanceOffsets };
|
|
7714
|
+
if (layer.options.nightLight) attributes.uv = /* alloc */
|
|
7715
|
+
{
|
|
7716
|
+
size: 2,
|
|
7717
|
+
data: context.uvs instanceof Float32Array ? context.uvs : (
|
|
7735
7718
|
/* alloc */
|
|
7736
|
-
new
|
|
7719
|
+
new Float32Array(context.uvs)
|
|
7720
|
+
)
|
|
7721
|
+
};
|
|
7722
|
+
let name, attribute;
|
|
7723
|
+
for (name in attributes) {
|
|
7724
|
+
attribute = attributes[name];
|
|
7725
|
+
attribute.count = attribute.data.length / attribute.size;
|
|
7726
|
+
attribute.buffer = device.createBuffer(
|
|
7727
|
+
/* alloc */
|
|
7728
|
+
{
|
|
7729
|
+
size: Math.max(4, attribute.data.byteLength),
|
|
7730
|
+
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
7731
|
+
}
|
|
7737
7732
|
);
|
|
7733
|
+
device.queue.writeBuffer(attribute.buffer, 0, attribute.data);
|
|
7738
7734
|
}
|
|
7739
|
-
const
|
|
7735
|
+
const meshGeometry = (
|
|
7740
7736
|
/* alloc */
|
|
7741
7737
|
{
|
|
7742
|
-
|
|
7743
|
-
|
|
7738
|
+
device,
|
|
7739
|
+
bounds: data.bounds,
|
|
7740
|
+
attributes,
|
|
7741
|
+
drawRange: (
|
|
7744
7742
|
/* alloc */
|
|
7745
|
-
|
|
7743
|
+
{ start: 0, count: attributes.position.count }
|
|
7746
7744
|
)
|
|
7747
7745
|
}
|
|
7748
7746
|
);
|
|
7749
|
-
|
|
7750
|
-
for (section = 0; section < 2; section++) {
|
|
7751
|
-
r = section ? radius * 2.5 : radius;
|
|
7752
|
-
low = section ? style.top - 0.25 : 0;
|
|
7753
|
-
high = section ? style.top + 0.15 : style.top;
|
|
7754
|
-
points = ring(point, r);
|
|
7755
|
-
for (i = 0; i < 6; i++) {
|
|
7756
|
-
a = points[i], b = points[(i + 1) % 6];
|
|
7757
|
-
nx = lampDirections[i].nx, nz = lampDirections[i].nz;
|
|
7758
|
-
addTriangle2(a, low, b, low, b, high, nx, 0, nz, color);
|
|
7759
|
-
addTriangle2(a, low, b, high, a, high, nx, 0, nz, color);
|
|
7760
|
-
addTriangle2(center, high, a, high, b, high, 0, 1, 0, color);
|
|
7761
|
-
addTriangle2(center, low, b, low, a, low, 0, -1, 0, color);
|
|
7762
|
-
}
|
|
7763
|
-
}
|
|
7764
|
-
}
|
|
7765
|
-
|
|
7766
|
-
// src/geometry/quad.js
|
|
7767
|
-
function quad(addTriangle2, color, a, b, c, d, height, nx, ny, nz) {
|
|
7768
|
-
if (typeof nx !== "number") {
|
|
7769
|
-
addTriangle2(a, height, b, height, c, height, ...nx, color);
|
|
7770
|
-
addTriangle2(a, height, c, height, d, height, ...nx, color);
|
|
7771
|
-
} else {
|
|
7772
|
-
addTriangle2(a, height, b, height, c, height, nx, ny, nz, color);
|
|
7773
|
-
addTriangle2(a, height, c, height, d, height, nx, ny, nz, color);
|
|
7774
|
-
}
|
|
7775
|
-
}
|
|
7776
|
-
|
|
7777
|
-
// src/geometry/emitter.js
|
|
7778
|
-
function emitter(point, u, v, axis) {
|
|
7779
|
-
const r = 0.65;
|
|
7780
|
-
return (
|
|
7781
|
-
/* alloc */
|
|
7782
|
-
{
|
|
7783
|
-
x: point.x + (axis === 2 ? 0 : u * r),
|
|
7784
|
-
y: point.y + (axis === 1 ? 0 : axis === 2 ? u * r : v * r),
|
|
7785
|
-
ground: point.ground + (axis === 0 ? 0 : v * r),
|
|
7786
|
-
uv: (
|
|
7787
|
-
/* alloc */
|
|
7788
|
-
[u, v]
|
|
7789
|
-
)
|
|
7790
|
-
}
|
|
7791
|
-
);
|
|
7792
|
-
}
|
|
7793
|
-
|
|
7794
|
-
// src/geometry/lightGeometry.js
|
|
7795
|
-
function lightGeometry(point, style, addTriangle2) {
|
|
7796
|
-
if (!Number.isFinite(style.lightRadius) || style.lightRadius <= 0) throw (
|
|
7797
|
-
/* alloc */
|
|
7798
|
-
new Error("Invalid light radius")
|
|
7799
|
-
);
|
|
7800
|
-
const color = parseColor(style.color);
|
|
7801
|
-
let axis;
|
|
7802
|
-
for (axis = 0; axis < 3; axis++) {
|
|
7803
|
-
quad(
|
|
7804
|
-
addTriangle2,
|
|
7805
|
-
color,
|
|
7806
|
-
emitter(point, -1, -1, axis),
|
|
7807
|
-
emitter(point, 1, -1, axis),
|
|
7808
|
-
emitter(point, 1, 1, axis),
|
|
7809
|
-
emitter(point, -1, 1, axis),
|
|
7810
|
-
style.top,
|
|
7811
|
-
axis === 2 ? 1 : 0,
|
|
7812
|
-
axis === 0 ? 1 : 0,
|
|
7813
|
-
axis === 1 ? 1 : 0
|
|
7814
|
-
);
|
|
7815
|
-
}
|
|
7816
|
-
}
|
|
7817
|
-
|
|
7818
|
-
// src/globals/roundProfile.js
|
|
7819
|
-
var roundProfile = [
|
|
7820
|
-
[0, 0],
|
|
7821
|
-
[0.35, 0.8],
|
|
7822
|
-
[0.6, 1],
|
|
7823
|
-
[0.85, 0.7],
|
|
7824
|
-
[1, 0]
|
|
7825
|
-
];
|
|
7826
|
-
|
|
7827
|
-
// src/globals/ringDirections.js
|
|
7828
|
-
var ringDirections = [
|
|
7829
|
-
{
|
|
7830
|
-
x: Math.cos(0 * Math.PI / 4),
|
|
7831
|
-
y: Math.sin(0 * Math.PI / 4),
|
|
7832
|
-
nx: Math.cos((0 + 0.5) * Math.PI / 4),
|
|
7833
|
-
nz: -Math.sin((0 + 0.5) * Math.PI / 4)
|
|
7834
|
-
},
|
|
7835
|
-
{
|
|
7836
|
-
x: Math.cos(1 * Math.PI / 4),
|
|
7837
|
-
y: Math.sin(1 * Math.PI / 4),
|
|
7838
|
-
nx: Math.cos((1 + 0.5) * Math.PI / 4),
|
|
7839
|
-
nz: -Math.sin((1 + 0.5) * Math.PI / 4)
|
|
7840
|
-
},
|
|
7841
|
-
{
|
|
7842
|
-
x: Math.cos(2 * Math.PI / 4),
|
|
7843
|
-
y: Math.sin(2 * Math.PI / 4),
|
|
7844
|
-
nx: Math.cos((2 + 0.5) * Math.PI / 4),
|
|
7845
|
-
nz: -Math.sin((2 + 0.5) * Math.PI / 4)
|
|
7846
|
-
},
|
|
7847
|
-
{
|
|
7848
|
-
x: Math.cos(3 * Math.PI / 4),
|
|
7849
|
-
y: Math.sin(3 * Math.PI / 4),
|
|
7850
|
-
nx: Math.cos((3 + 0.5) * Math.PI / 4),
|
|
7851
|
-
nz: -Math.sin((3 + 0.5) * Math.PI / 4)
|
|
7852
|
-
},
|
|
7853
|
-
{
|
|
7854
|
-
x: Math.cos(4 * Math.PI / 4),
|
|
7855
|
-
y: Math.sin(4 * Math.PI / 4),
|
|
7856
|
-
nx: Math.cos((4 + 0.5) * Math.PI / 4),
|
|
7857
|
-
nz: -Math.sin((4 + 0.5) * Math.PI / 4)
|
|
7858
|
-
},
|
|
7859
|
-
{
|
|
7860
|
-
x: Math.cos(5 * Math.PI / 4),
|
|
7861
|
-
y: Math.sin(5 * Math.PI / 4),
|
|
7862
|
-
nx: Math.cos((5 + 0.5) * Math.PI / 4),
|
|
7863
|
-
nz: -Math.sin((5 + 0.5) * Math.PI / 4)
|
|
7864
|
-
},
|
|
7865
|
-
{
|
|
7866
|
-
x: Math.cos(6 * Math.PI / 4),
|
|
7867
|
-
y: Math.sin(6 * Math.PI / 4),
|
|
7868
|
-
nx: Math.cos((6 + 0.5) * Math.PI / 4),
|
|
7869
|
-
nz: -Math.sin((6 + 0.5) * Math.PI / 4)
|
|
7870
|
-
},
|
|
7747
|
+
area2.mesh = /* alloc */
|
|
7871
7748
|
{
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7888
|
-
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
7892
|
-
|
|
7893
|
-
|
|
7894
|
-
|
|
7749
|
+
...emptyNode(),
|
|
7750
|
+
device,
|
|
7751
|
+
geometry: meshGeometry,
|
|
7752
|
+
program: createProgram(
|
|
7753
|
+
layer,
|
|
7754
|
+
/* alloc */
|
|
7755
|
+
{
|
|
7756
|
+
instanced: Boolean(data.instanceOffsets),
|
|
7757
|
+
vertexColors: true,
|
|
7758
|
+
roofTexture: layer.options.roofTexture,
|
|
7759
|
+
wallTexture: layer.options.wallTexture,
|
|
7760
|
+
nightLight: Boolean(layer.options.nightLight),
|
|
7761
|
+
alphaMode: layer.options.nightLight ? "BLEND" : void 0,
|
|
7762
|
+
doubleSided: Boolean(layer.options.nightLight)
|
|
7763
|
+
}
|
|
7764
|
+
),
|
|
7765
|
+
id: nextId.value++,
|
|
7766
|
+
renderOrder: 0,
|
|
7767
|
+
fadeDuration: 250,
|
|
7768
|
+
extras: (
|
|
7769
|
+
/* alloc */
|
|
7770
|
+
{ featureFaces: context.featureFaces, lights: context.lights }
|
|
7771
|
+
)
|
|
7772
|
+
};
|
|
7773
|
+
area2.buildings = context.featureFaces.length;
|
|
7774
|
+
area2.skipped = context.skipped;
|
|
7775
|
+
area2.done = true;
|
|
7776
|
+
setParent(area2.mesh, rootByLayer.get(layer));
|
|
7777
|
+
update(layer);
|
|
7895
7778
|
}
|
|
7896
7779
|
|
|
7897
|
-
// src/
|
|
7898
|
-
|
|
7899
|
-
const lower = ring2(point, lowRadius), upper = ring2(point, highRadius);
|
|
7900
|
-
let i, next, slope, length, nx, nz, ny, normalX, normalZ;
|
|
7901
|
-
for (i = 0; i < 8; i++) {
|
|
7902
|
-
next = (i + 1) % 8;
|
|
7903
|
-
slope = (lowRadius - highRadius) / (high - low);
|
|
7904
|
-
length = Math.hypot(1, slope);
|
|
7905
|
-
({ nx, nz } = ringDirections[i]);
|
|
7906
|
-
ny = slope / length;
|
|
7907
|
-
normalX = nx / length, normalZ = nz / length;
|
|
7908
|
-
if (lowRadius) addTriangle2(lower[i], low, lower[next], low, upper[next], high, normalX, ny, normalZ, color);
|
|
7909
|
-
if (highRadius) addTriangle2(lower[i], low, upper[next], high, upper[i], high, normalX, ny, normalZ, color);
|
|
7910
|
-
}
|
|
7911
|
-
}
|
|
7780
|
+
// src/globals/archiveDecoder.js
|
|
7781
|
+
var archiveDecoder = new TextDecoder();
|
|
7912
7782
|
|
|
7913
|
-
// src/
|
|
7914
|
-
function
|
|
7915
|
-
if (!Number.
|
|
7783
|
+
// src/archives/tileId.js
|
|
7784
|
+
function tileId(z, x, y) {
|
|
7785
|
+
if (!Number.isInteger(z) || !Number.isInteger(x) || !Number.isInteger(y) || z < 0 || z > 26 || x < 0 || y < 0 || x >= 2 ** z || y >= 2 ** z) {
|
|
7916
7786
|
throw (
|
|
7917
7787
|
/* alloc */
|
|
7918
|
-
new Error("Invalid
|
|
7788
|
+
new Error("Invalid PMTiles tile coordinates")
|
|
7919
7789
|
);
|
|
7920
7790
|
}
|
|
7791
|
+
let id = (4 ** z - 1) / 3;
|
|
7792
|
+
const n = 2 ** z;
|
|
7793
|
+
let s, rx, ry, swap;
|
|
7794
|
+
for (s = n / 2; s >= 1; s /= 2) {
|
|
7795
|
+
rx = x & s ? 1 : 0, ry = y & s ? 1 : 0;
|
|
7796
|
+
id += s * s * (3 * rx ^ ry);
|
|
7797
|
+
if (!ry) {
|
|
7798
|
+
if (rx) {
|
|
7799
|
+
x = n - 1 - x;
|
|
7800
|
+
y = n - 1 - y;
|
|
7801
|
+
}
|
|
7802
|
+
swap = x;
|
|
7803
|
+
x = y;
|
|
7804
|
+
y = swap;
|
|
7805
|
+
}
|
|
7806
|
+
}
|
|
7807
|
+
return id;
|
|
7921
7808
|
}
|
|
7922
7809
|
|
|
7923
|
-
// src/
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
for (i = 1; i < roundProfile.length; i++) {
|
|
7948
|
-
[low, lr] = roundProfile[i - 1], [high, hr] = roundProfile[i];
|
|
7949
|
-
surface(
|
|
7950
|
-
point,
|
|
7951
|
-
addTriangle2,
|
|
7952
|
-
lr * crownRadius,
|
|
7953
|
-
crownBottom + low * (top - crownBottom),
|
|
7954
|
-
hr * crownRadius,
|
|
7955
|
-
crownBottom + high * (top - crownBottom),
|
|
7956
|
-
crown
|
|
7810
|
+
// src/globals/directoryReader.js
|
|
7811
|
+
var directoryReader = {
|
|
7812
|
+
bytes: null,
|
|
7813
|
+
cursor: 0
|
|
7814
|
+
};
|
|
7815
|
+
|
|
7816
|
+
// src/archives/readVarint.js
|
|
7817
|
+
function varint(reader) {
|
|
7818
|
+
const { bytes } = reader;
|
|
7819
|
+
let value = 0;
|
|
7820
|
+
let factor, byte;
|
|
7821
|
+
for (factor = 1; factor <= 2 ** 49; factor *= 128) {
|
|
7822
|
+
if (reader.cursor >= bytes.length) {
|
|
7823
|
+
throw (
|
|
7824
|
+
/* alloc */
|
|
7825
|
+
new Error("Truncated PMTiles directory")
|
|
7826
|
+
);
|
|
7827
|
+
}
|
|
7828
|
+
byte = bytes[reader.cursor++];
|
|
7829
|
+
value += (byte & 127) * factor;
|
|
7830
|
+
if (!Number.isSafeInteger(value)) {
|
|
7831
|
+
throw (
|
|
7832
|
+
/* alloc */
|
|
7833
|
+
new Error("Invalid PMTiles directory integer")
|
|
7957
7834
|
);
|
|
7958
7835
|
}
|
|
7836
|
+
if (byte < 128) return value;
|
|
7959
7837
|
}
|
|
7838
|
+
throw (
|
|
7839
|
+
/* alloc */
|
|
7840
|
+
new Error("Invalid PMTiles directory integer")
|
|
7841
|
+
);
|
|
7960
7842
|
}
|
|
7961
7843
|
|
|
7962
|
-
// src/
|
|
7963
|
-
function
|
|
7964
|
-
const
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
|
|
7972
|
-
|
|
7844
|
+
// src/archives/decodeDirectory.js
|
|
7845
|
+
function decodeDirectory(data) {
|
|
7846
|
+
const reader = directoryReader;
|
|
7847
|
+
const bytes = (
|
|
7848
|
+
/* alloc */
|
|
7849
|
+
new Uint8Array(data)
|
|
7850
|
+
);
|
|
7851
|
+
reader.bytes = bytes;
|
|
7852
|
+
reader.cursor = 0;
|
|
7853
|
+
try {
|
|
7854
|
+
const count = varint(reader);
|
|
7855
|
+
if (count > (bytes.length - reader.cursor) / 4) {
|
|
7856
|
+
throw (
|
|
7857
|
+
/* alloc */
|
|
7858
|
+
new Error("Invalid PMTiles directory count")
|
|
7859
|
+
);
|
|
7973
7860
|
}
|
|
7974
|
-
|
|
7975
|
-
context.lights.push(
|
|
7861
|
+
const entries = (
|
|
7976
7862
|
/* alloc */
|
|
7977
|
-
|
|
7978
|
-
|
|
7863
|
+
new Array(count)
|
|
7864
|
+
);
|
|
7865
|
+
let tileId2 = 0;
|
|
7866
|
+
let i, entry, value;
|
|
7867
|
+
for (i = 0; i < count; i++) {
|
|
7868
|
+
tileId2 += varint(reader);
|
|
7869
|
+
if (!Number.isSafeInteger(tileId2) || i && tileId2 <= entries[i - 1].tileId) {
|
|
7870
|
+
throw (
|
|
7979
7871
|
/* alloc */
|
|
7980
|
-
|
|
7981
|
-
)
|
|
7982
|
-
|
|
7983
|
-
|
|
7872
|
+
new Error("Invalid PMTiles directory tile IDs")
|
|
7873
|
+
);
|
|
7874
|
+
}
|
|
7875
|
+
entries[i] = /* alloc */
|
|
7876
|
+
{ tileId: tileId2, runLength: 0, length: 0, offset: 0 };
|
|
7877
|
+
}
|
|
7878
|
+
for (entry of entries) entry.runLength = varint(reader);
|
|
7879
|
+
for (entry of entries) {
|
|
7880
|
+
entry.length = varint(reader);
|
|
7881
|
+
if (!entry.length) {
|
|
7882
|
+
throw (
|
|
7984
7883
|
/* alloc */
|
|
7985
|
-
|
|
7986
|
-
)
|
|
7987
|
-
flux: style.lightFlux
|
|
7884
|
+
new Error("Invalid PMTiles directory length")
|
|
7885
|
+
);
|
|
7988
7886
|
}
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
|
|
7997
|
-
|
|
7998
|
-
|
|
7999
|
-
// src/projections/projectRing.js
|
|
8000
|
-
init_L();
|
|
8001
|
-
function projectRing(context, ring3) {
|
|
8002
|
-
const { backend: layer, crs, origin, metres, map } = context;
|
|
8003
|
-
if (ring3.length < 4) throw (
|
|
8004
|
-
/* alloc */
|
|
8005
|
-
new Error("Invalid GeoJSON polygon ring")
|
|
8006
|
-
);
|
|
8007
|
-
const path = (
|
|
8008
|
-
/* alloc */
|
|
8009
|
-
[]
|
|
8010
|
-
);
|
|
8011
|
-
const root = rootByLayer.get(layer);
|
|
8012
|
-
let i, lng, lat, location, point, elevation;
|
|
8013
|
-
for (i = 0; i < ring3.length - 1; i++) {
|
|
8014
|
-
lng = ring3[i][0], lat = ring3[i][1];
|
|
8015
|
-
if (!Number.isFinite(lng) || !Number.isFinite(lat)) throw (
|
|
8016
|
-
/* alloc */
|
|
8017
|
-
new Error("Invalid GeoJSON coordinates")
|
|
8018
|
-
);
|
|
8019
|
-
location = /* alloc */
|
|
8020
|
-
new L.LatLng(lat, lng);
|
|
8021
|
-
point = crs.project(location);
|
|
8022
|
-
elevation = mapElevationOf(map, location);
|
|
8023
|
-
path.push(
|
|
8024
|
-
/* alloc */
|
|
8025
|
-
{
|
|
8026
|
-
x: (point.x - origin.x) * metres,
|
|
8027
|
-
y: (point.y - origin.y) * metres,
|
|
8028
|
-
ground: Number.isFinite(elevation) && Number.isFinite(root.position[1]) ? elevation - root.position[1] : 0
|
|
7887
|
+
}
|
|
7888
|
+
for (i = 0; i < entries.length; i++) {
|
|
7889
|
+
entry = entries[i];
|
|
7890
|
+
value = varint(reader);
|
|
7891
|
+
if (!value && !i) {
|
|
7892
|
+
throw (
|
|
7893
|
+
/* alloc */
|
|
7894
|
+
new Error("Invalid PMTiles directory offset")
|
|
7895
|
+
);
|
|
8029
7896
|
}
|
|
8030
|
-
|
|
7897
|
+
entry.offset = value ? value - 1 : entries[i - 1].offset + entries[i - 1].length;
|
|
7898
|
+
}
|
|
7899
|
+
if (reader.cursor !== bytes.length) {
|
|
7900
|
+
throw (
|
|
7901
|
+
/* alloc */
|
|
7902
|
+
new Error("Trailing PMTiles directory data")
|
|
7903
|
+
);
|
|
7904
|
+
}
|
|
7905
|
+
return entries;
|
|
7906
|
+
} finally {
|
|
7907
|
+
reader.bytes = null;
|
|
7908
|
+
reader.cursor = 0;
|
|
8031
7909
|
}
|
|
8032
|
-
return path;
|
|
8033
7910
|
}
|
|
8034
7911
|
|
|
8035
|
-
// src/
|
|
8036
|
-
function
|
|
8037
|
-
|
|
7912
|
+
// src/archives/decompress.js
|
|
7913
|
+
async function decompress(data, compression) {
|
|
7914
|
+
if (compression === 1) return data;
|
|
7915
|
+
if (compression !== 2) {
|
|
7916
|
+
throw (
|
|
7917
|
+
/* alloc */
|
|
7918
|
+
new Error(`Unsupported PMTiles compression: ${compression}`)
|
|
7919
|
+
);
|
|
7920
|
+
}
|
|
7921
|
+
const blob = (
|
|
8038
7922
|
/* alloc */
|
|
8039
|
-
|
|
7923
|
+
new Blob(
|
|
7924
|
+
/* alloc */
|
|
7925
|
+
[data]
|
|
7926
|
+
)
|
|
8040
7927
|
);
|
|
8041
|
-
|
|
8042
|
-
for (path of paths) for (point of path) points.push(point);
|
|
8043
|
-
for ([a, b, c] of triangulate(paths[0], paths.slice(1))) {
|
|
8044
|
-
addTriangle(context, points[a], top, points[b], top, points[c], top, 0, 1, 0, baseColor);
|
|
8045
|
-
if (bottom > 0) addTriangle(context, points[a], bottom, points[b], bottom, points[c], bottom, 0, -1, 0, baseColor);
|
|
8046
|
-
}
|
|
8047
|
-
for (index = 0; index < paths.length; index++) {
|
|
8048
|
-
path = paths[index];
|
|
8049
|
-
sign = isClockWise(path) === (index === 0) ? -1 : 1;
|
|
8050
|
-
for (i = 0; i < path.length; i++) {
|
|
8051
|
-
a = path[i], b = path[(i + 1) % path.length];
|
|
8052
|
-
length = Math.hypot(b.x - a.x, b.y - a.y);
|
|
8053
|
-
if (!length) continue;
|
|
8054
|
-
nx = sign * (b.y - a.y) / length, nz = sign * (b.x - a.x) / length;
|
|
8055
|
-
addTriangle(context, a, bottom, b, bottom, b, top, nx, 0, nz, baseColor);
|
|
8056
|
-
addTriangle(context, a, bottom, b, top, a, top, nx, 0, nz, baseColor);
|
|
8057
|
-
}
|
|
8058
|
-
}
|
|
8059
|
-
}
|
|
8060
|
-
|
|
8061
|
-
// src/geometry/buildExtrudedPolygon.js
|
|
8062
|
-
function buildAreaPolygon(context, rings, top, bottom, baseColor) {
|
|
8063
|
-
if (!rings.length) throw (
|
|
7928
|
+
const stream = (
|
|
8064
7929
|
/* alloc */
|
|
8065
|
-
new
|
|
7930
|
+
new DecompressionStream("gzip")
|
|
8066
7931
|
);
|
|
8067
|
-
|
|
7932
|
+
return (
|
|
8068
7933
|
/* alloc */
|
|
8069
|
-
|
|
7934
|
+
new Response(blob.stream().pipeThrough(stream)).arrayBuffer()
|
|
8070
7935
|
);
|
|
8071
|
-
let ring3;
|
|
8072
|
-
for (ring3 of rings) paths.push(projectRing(context, ring3));
|
|
8073
|
-
buildProjectedPolygon(context, paths, top, bottom, baseColor);
|
|
8074
7936
|
}
|
|
8075
7937
|
|
|
8076
|
-
// src/
|
|
8077
|
-
function
|
|
8078
|
-
|
|
8079
|
-
if (nightLight && !point) throw (
|
|
8080
|
-
/* alloc */
|
|
8081
|
-
new Error("Night lights require Point geometry")
|
|
8082
|
-
);
|
|
8083
|
-
if (geometry?.type !== "Polygon" && geometry?.type !== "MultiPolygon" && !point) throw (
|
|
8084
|
-
/* alloc */
|
|
8085
|
-
new Error("Unsupported GeoJSON geometry")
|
|
8086
|
-
);
|
|
8087
|
-
const coordinates = point ? geometry.coordinates : geometry.type === "Polygon" ? geometry.coordinates[0]?.[0] : geometry.coordinates[0]?.[0]?.[0];
|
|
8088
|
-
if (!Number.isFinite(coordinates?.[0]) || !Number.isFinite(coordinates?.[1])) throw (
|
|
8089
|
-
/* alloc */
|
|
8090
|
-
new Error("Invalid GeoJSON coordinates")
|
|
8091
|
-
);
|
|
8092
|
-
return coordinates;
|
|
7938
|
+
// src/archives/loadDirectory.js
|
|
7939
|
+
async function loadDirectory(layer, offset, length, compression) {
|
|
7940
|
+
return decodeDirectory(await decompress(await read(layer, offset, length), compression));
|
|
8093
7941
|
}
|
|
8094
7942
|
|
|
8095
|
-
// src/
|
|
8096
|
-
function
|
|
8097
|
-
const
|
|
8098
|
-
|
|
8099
|
-
if (!
|
|
8100
|
-
|
|
8101
|
-
|
|
8102
|
-
|
|
8103
|
-
const
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8108
|
-
|
|
7943
|
+
// src/archives/getDirectoryEntries.js
|
|
7944
|
+
async function getDirectoryEntries(layer, offset, length, compression) {
|
|
7945
|
+
const directories = directoriesByLayer.get(layer);
|
|
7946
|
+
const key = `${offset}:${length}`;
|
|
7947
|
+
if (!directories.has(key)) {
|
|
7948
|
+
if (directories.size >= 32) directories.delete(directories.keys().next().value);
|
|
7949
|
+
directories.set(key, loadDirectory(layer, offset, length, compression));
|
|
7950
|
+
}
|
|
7951
|
+
const pending = directories.get(key);
|
|
7952
|
+
try {
|
|
7953
|
+
return await pending;
|
|
7954
|
+
} catch (error) {
|
|
7955
|
+
if (directories.get(key) === pending) directories.delete(key);
|
|
7956
|
+
throw error;
|
|
8109
7957
|
}
|
|
8110
|
-
return style;
|
|
8111
7958
|
}
|
|
8112
7959
|
|
|
8113
|
-
// src/
|
|
8114
|
-
function
|
|
8115
|
-
|
|
8116
|
-
|
|
8117
|
-
|
|
8118
|
-
[]
|
|
8119
|
-
|
|
8120
|
-
const rings = geometry.type === "Polygon" ? (
|
|
8121
|
-
/* alloc */
|
|
8122
|
-
[geometry.coordinates]
|
|
8123
|
-
) : geometry.type === "MultiPolygon" ? geometry.coordinates : (
|
|
8124
|
-
/* alloc */
|
|
8125
|
-
[]
|
|
8126
|
-
);
|
|
8127
|
-
let polygon2, ring3, paths;
|
|
8128
|
-
for (polygon2 of rings) {
|
|
8129
|
-
if (!polygon2.length) throw (
|
|
8130
|
-
/* alloc */
|
|
8131
|
-
new Error("Empty GeoJSON polygon")
|
|
8132
|
-
);
|
|
8133
|
-
paths = /* alloc */
|
|
8134
|
-
[];
|
|
8135
|
-
for (ring3 of polygon2) paths.push(projectRing(context, ring3));
|
|
8136
|
-
polygons.push(paths);
|
|
7960
|
+
// src/archives/findDirectoryEntry.js
|
|
7961
|
+
function findDirectoryEntry(entries, id) {
|
|
7962
|
+
let low = 0, high = entries.length - 1, mid;
|
|
7963
|
+
while (low <= high) {
|
|
7964
|
+
mid = low + high >> 1;
|
|
7965
|
+
if (entries[mid].tileId <= id) low = mid + 1;
|
|
7966
|
+
else high = mid - 1;
|
|
8137
7967
|
}
|
|
8138
|
-
|
|
8139
|
-
const nightLight = context.backend.options.nightLight;
|
|
8140
|
-
const crownColor = point ? parseColor(style.color ?? (nightLight ? void 0 : 5210683)) : baseColor;
|
|
8141
|
-
const trunkColor = point && !nightLight ? parseColor(style.trunkColor ?? 7491898) : null;
|
|
8142
|
-
context.jobs.push(
|
|
8143
|
-
/* alloc */
|
|
8144
|
-
{
|
|
8145
|
-
point,
|
|
8146
|
-
polygons,
|
|
8147
|
-
baseColor: (
|
|
8148
|
-
/* alloc */
|
|
8149
|
-
{ r: baseColor.r, g: baseColor.g, b: baseColor.b }
|
|
8150
|
-
),
|
|
8151
|
-
support: feature.properties?.cod_ouvrag || `${lon},${lat}`,
|
|
8152
|
-
style: (
|
|
8153
|
-
/* alloc */
|
|
8154
|
-
{
|
|
8155
|
-
top: style.top,
|
|
8156
|
-
bottom: style.bottom ?? 0,
|
|
8157
|
-
color: (
|
|
8158
|
-
/* alloc */
|
|
8159
|
-
{ r: crownColor.r, g: crownColor.g, b: crownColor.b }
|
|
8160
|
-
),
|
|
8161
|
-
trunkColor: trunkColor ? (
|
|
8162
|
-
/* alloc */
|
|
8163
|
-
{ r: trunkColor.r, g: trunkColor.g, b: trunkColor.b }
|
|
8164
|
-
) : void 0,
|
|
8165
|
-
trunkRadius: style.trunkRadius,
|
|
8166
|
-
crownRadius: style.crownRadius,
|
|
8167
|
-
crownBottom: style.crownBottom,
|
|
8168
|
-
crownShape: style.crownShape,
|
|
8169
|
-
poleRadius: style.poleRadius,
|
|
8170
|
-
lightRadius: style.lightRadius,
|
|
8171
|
-
lightFlux: style.lightFlux
|
|
8172
|
-
}
|
|
8173
|
-
)
|
|
8174
|
-
}
|
|
8175
|
-
);
|
|
7968
|
+
return entries[high];
|
|
8176
7969
|
}
|
|
8177
7970
|
|
|
8178
|
-
// src/
|
|
8179
|
-
function
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
const geometry = feature.geometry, isTree = geometry.type === "Point";
|
|
8184
|
-
const lon = coordinates[0], lat = coordinates[1];
|
|
8185
|
-
if (coords) {
|
|
8186
|
-
const anchor = map.project(
|
|
8187
|
-
/* alloc */
|
|
8188
|
-
new L.LatLng(lat, lon),
|
|
8189
|
-
coords.z
|
|
8190
|
-
);
|
|
8191
|
-
if (Math.floor(anchor.x / 256) !== coords.x || Math.floor(anchor.y / 256) !== coords.y) return;
|
|
8192
|
-
}
|
|
8193
|
-
const style = extrusionStyle(layer, feature);
|
|
8194
|
-
if (style === null) {
|
|
8195
|
-
context.skipped++;
|
|
8196
|
-
return;
|
|
8197
|
-
}
|
|
8198
|
-
const { top, bottom = 0, color = 14267276 } = style;
|
|
8199
|
-
const baseColor = parseColor(color);
|
|
8200
|
-
if (context.jobs) {
|
|
8201
|
-
prepareAreaGeometryJob(context, feature, lon, lat, style, baseColor);
|
|
8202
|
-
context.featureFaces.push(
|
|
7971
|
+
// src/archives/getTileData.js
|
|
7972
|
+
async function getTileData(layer, header, entry, id, signal) {
|
|
7973
|
+
if (id - entry.tileId >= entry.runLength) return;
|
|
7974
|
+
if (entry.offset + entry.length > header.tileDataLength) {
|
|
7975
|
+
throw (
|
|
8203
7976
|
/* alloc */
|
|
8204
|
-
|
|
8205
|
-
id: feature.id ?? feature.properties?.objectid ?? JSON.stringify(geometry),
|
|
8206
|
-
properties: feature.properties,
|
|
8207
|
-
baseColor
|
|
8208
|
-
}
|
|
7977
|
+
new Error("PMTiles tile outside data section")
|
|
8209
7978
|
);
|
|
8210
|
-
return;
|
|
8211
7979
|
}
|
|
8212
|
-
const
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
context.featureFaces.push(
|
|
7980
|
+
const data = await decompress(
|
|
7981
|
+
await read(layer, header.tileDataOffset + entry.offset, entry.length, signal),
|
|
7982
|
+
header.tileCompression
|
|
7983
|
+
);
|
|
7984
|
+
signal?.throwIfAborted();
|
|
7985
|
+
return (
|
|
8219
7986
|
/* alloc */
|
|
8220
|
-
{
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
7987
|
+
{ data }
|
|
7988
|
+
);
|
|
7989
|
+
}
|
|
7990
|
+
|
|
7991
|
+
// src/archives/findTile.js
|
|
7992
|
+
async function findTile(layer, header, id, signal) {
|
|
7993
|
+
let offset = header.rootDirectoryOffset, length = header.rootDirectoryLength;
|
|
7994
|
+
let firstOffset = -1, secondOffset = -1, thirdOffset = -1;
|
|
7995
|
+
let depth, entries, entry, tile;
|
|
7996
|
+
for (depth = 0; depth < 4; depth++) {
|
|
7997
|
+
if (offset === firstOffset || offset === secondOffset || offset === thirdOffset) {
|
|
7998
|
+
throw (
|
|
7999
|
+
/* alloc */
|
|
8000
|
+
new Error("Cyclic PMTiles directory")
|
|
8001
|
+
);
|
|
8002
|
+
}
|
|
8003
|
+
if (depth === 0) firstOffset = offset;
|
|
8004
|
+
else if (depth === 1) secondOffset = offset;
|
|
8005
|
+
else if (depth === 2) thirdOffset = offset;
|
|
8006
|
+
entries = await getDirectoryEntries(layer, offset, length, header.internalCompression);
|
|
8007
|
+
signal?.throwIfAborted();
|
|
8008
|
+
entry = findDirectoryEntry(entries, id);
|
|
8009
|
+
if (!entry) return;
|
|
8010
|
+
if (entry.runLength) {
|
|
8011
|
+
tile = await getTileData(layer, header, entry, id, signal);
|
|
8012
|
+
return tile;
|
|
8013
|
+
}
|
|
8014
|
+
if (entry.offset + entry.length > header.leafDirectoryLength) {
|
|
8015
|
+
throw (
|
|
8016
|
+
/* alloc */
|
|
8017
|
+
new Error("PMTiles directory outside leaf section")
|
|
8018
|
+
);
|
|
8228
8019
|
}
|
|
8020
|
+
offset = header.leafDirectoryOffset + entry.offset;
|
|
8021
|
+
length = entry.length;
|
|
8022
|
+
}
|
|
8023
|
+
throw (
|
|
8024
|
+
/* alloc */
|
|
8025
|
+
new Error("PMTiles directory depth exceeds four levels")
|
|
8229
8026
|
);
|
|
8230
8027
|
}
|
|
8231
8028
|
|
|
8232
|
-
// src/
|
|
8233
|
-
function
|
|
8234
|
-
|
|
8235
|
-
if (
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
const
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
);
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8258
|
-
|
|
8259
|
-
|
|
8029
|
+
// src/archives/getZxy.js
|
|
8030
|
+
async function getZxy(layer, z, x, y, signal) {
|
|
8031
|
+
if (!sceneLayers.has(layer)) return layer.getZxy(z, x, y, signal);
|
|
8032
|
+
if (layer.options.archive && layer.options.archive !== layer) {
|
|
8033
|
+
return getZxy(layer.options.archive, z, x, y, signal);
|
|
8034
|
+
}
|
|
8035
|
+
const id = tileId(z, x, y);
|
|
8036
|
+
signal?.throwIfAborted();
|
|
8037
|
+
const header = await getHeader(layer);
|
|
8038
|
+
signal?.throwIfAborted();
|
|
8039
|
+
if (z < header.minZoom || z > header.maxZoom) return;
|
|
8040
|
+
return findTile(layer, header, id, signal);
|
|
8041
|
+
}
|
|
8042
|
+
|
|
8043
|
+
// src/archives/loadSource.js
|
|
8044
|
+
async function loadSource(layer, area2) {
|
|
8045
|
+
if (geojsonByLayer.get(layer)) {
|
|
8046
|
+
const { data, url } = layer.options;
|
|
8047
|
+
if (data !== void 0 && url) {
|
|
8048
|
+
throw (
|
|
8049
|
+
/* alloc */
|
|
8050
|
+
new Error("GeoJSON source requires either data or url")
|
|
8051
|
+
);
|
|
8052
|
+
}
|
|
8053
|
+
if (data !== void 0) return data;
|
|
8054
|
+
if (!url) {
|
|
8055
|
+
throw (
|
|
8056
|
+
/* alloc */
|
|
8057
|
+
new Error("GeoJSON source requires either data or url")
|
|
8058
|
+
);
|
|
8059
|
+
}
|
|
8060
|
+
const sourceUrl = (
|
|
8061
|
+
/* alloc */
|
|
8062
|
+
new URL(url, document.baseURI)
|
|
8063
|
+
);
|
|
8064
|
+
const response = await fetch(
|
|
8065
|
+
sourceUrl,
|
|
8066
|
+
/* alloc */
|
|
8067
|
+
{ signal: area2.request.signal }
|
|
8068
|
+
);
|
|
8069
|
+
if (!response.ok) {
|
|
8070
|
+
throw (
|
|
8071
|
+
/* alloc */
|
|
8072
|
+
new Error(`Unable to load GeoJSON: HTTP ${response.status}`)
|
|
8073
|
+
);
|
|
8260
8074
|
}
|
|
8075
|
+
return response.json();
|
|
8261
8076
|
}
|
|
8262
|
-
|
|
8077
|
+
const result = await getZxy(layer, area2.coords.z, area2.coords.x, area2.coords.y, area2.request.signal);
|
|
8078
|
+
return result ? JSON.parse(archiveDecoder.decode(result.data)) : (
|
|
8263
8079
|
/* alloc */
|
|
8264
8080
|
{
|
|
8265
|
-
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
|
|
8081
|
+
type: "FeatureCollection",
|
|
8082
|
+
features: (
|
|
8083
|
+
/* alloc */
|
|
8084
|
+
[]
|
|
8085
|
+
)
|
|
8269
8086
|
}
|
|
8270
8087
|
);
|
|
8271
8088
|
}
|
|
8272
8089
|
|
|
8273
|
-
// src/sources/
|
|
8274
|
-
|
|
8275
|
-
|
|
8276
|
-
|
|
8277
|
-
|
|
8278
|
-
return;
|
|
8279
|
-
}
|
|
8280
|
-
const device = rendererByLayer.get(layer).device;
|
|
8281
|
-
const data = context.preparedGeometry || instanceAreaGeometry(context);
|
|
8282
|
-
const attributes = (
|
|
8090
|
+
// src/sources/sourceAreaContext.js
|
|
8091
|
+
init_radians();
|
|
8092
|
+
function sourceAreaContext(layer, area2, map) {
|
|
8093
|
+
const crs = map.options.crs, origin = crs.project(locationByLayer.get(layer));
|
|
8094
|
+
return (
|
|
8283
8095
|
/* alloc */
|
|
8284
8096
|
{
|
|
8285
|
-
|
|
8097
|
+
backend: layer,
|
|
8098
|
+
area: area2,
|
|
8099
|
+
map,
|
|
8100
|
+
crs,
|
|
8101
|
+
origin,
|
|
8102
|
+
metres: Math.cos(locationByLayer.get(layer).lat * radians),
|
|
8103
|
+
positions: (
|
|
8286
8104
|
/* alloc */
|
|
8287
|
-
|
|
8288
|
-
/* alloc */
|
|
8289
|
-
new Float32Array(data.positions)
|
|
8290
|
-
) }
|
|
8105
|
+
[]
|
|
8291
8106
|
),
|
|
8292
|
-
|
|
8107
|
+
normals: (
|
|
8293
8108
|
/* alloc */
|
|
8294
|
-
|
|
8295
|
-
/* alloc */
|
|
8296
|
-
new Float32Array(data.normals)
|
|
8297
|
-
) }
|
|
8109
|
+
[]
|
|
8298
8110
|
),
|
|
8299
|
-
|
|
8111
|
+
colors: (
|
|
8300
8112
|
/* alloc */
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8113
|
+
[]
|
|
8114
|
+
),
|
|
8115
|
+
uvs: (
|
|
8116
|
+
/* alloc */
|
|
8117
|
+
[]
|
|
8118
|
+
),
|
|
8119
|
+
featureFaces: (
|
|
8120
|
+
/* alloc */
|
|
8121
|
+
[]
|
|
8122
|
+
),
|
|
8123
|
+
lights: (
|
|
8124
|
+
/* alloc */
|
|
8125
|
+
[]
|
|
8126
|
+
),
|
|
8127
|
+
supports: (
|
|
8128
|
+
/* alloc */
|
|
8129
|
+
/* @__PURE__ */ new Set()
|
|
8130
|
+
),
|
|
8131
|
+
skipped: 0
|
|
8306
8132
|
}
|
|
8307
8133
|
);
|
|
8308
|
-
|
|
8309
|
-
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8134
|
+
}
|
|
8135
|
+
|
|
8136
|
+
// src/globals/geometryWorkerUrl.js
|
|
8137
|
+
var geometryWorkerUrl = void 0 ? new URL("../workers/geometryWorker.js", null.url).href : new URL("leaflet-city-mapper-worker.js", document.currentScript?.src || document.baseURI).href;
|
|
8138
|
+
|
|
8139
|
+
// src/workers/settleGeometryWorker.js
|
|
8140
|
+
function settleGeometryWorker(task, event) {
|
|
8141
|
+
if (event.type === "abort") task.reject(task.signal.reason);
|
|
8142
|
+
else if (event.type === "error") task.reject(
|
|
8143
|
+
/* alloc */
|
|
8144
|
+
new Error(`Geometry worker failed: ${event.message}`)
|
|
8145
|
+
);
|
|
8146
|
+
else if (event.type === "messageerror") task.reject(
|
|
8147
|
+
/* alloc */
|
|
8148
|
+
new Error("Unable to receive geometry worker buffers")
|
|
8149
|
+
);
|
|
8150
|
+
else if (event.data.error) {
|
|
8151
|
+
const error = (
|
|
8323
8152
|
/* alloc */
|
|
8324
|
-
|
|
8325
|
-
size: Math.max(4, attribute.data.byteLength),
|
|
8326
|
-
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST
|
|
8327
|
-
}
|
|
8153
|
+
new Error(event.data.error.message)
|
|
8328
8154
|
);
|
|
8329
|
-
|
|
8330
|
-
|
|
8331
|
-
|
|
8155
|
+
error.name = event.data.error.name;
|
|
8156
|
+
task.reject(error);
|
|
8157
|
+
} else task.resolve(event.data);
|
|
8158
|
+
}
|
|
8159
|
+
|
|
8160
|
+
// src/workers/startGeometryWorker.js
|
|
8161
|
+
function startGeometryWorker(task, resolve, reject) {
|
|
8162
|
+
task.resolve = resolve;
|
|
8163
|
+
task.reject = reject;
|
|
8164
|
+
task.onEvent = settleGeometryWorker.bind(null, task);
|
|
8165
|
+
task.worker.addEventListener("message", task.onEvent);
|
|
8166
|
+
task.worker.addEventListener("error", task.onEvent);
|
|
8167
|
+
task.worker.addEventListener("messageerror", task.onEvent);
|
|
8168
|
+
task.signal.addEventListener(
|
|
8169
|
+
"abort",
|
|
8170
|
+
task.onEvent,
|
|
8332
8171
|
/* alloc */
|
|
8333
|
-
{
|
|
8334
|
-
device,
|
|
8335
|
-
bounds: data.bounds,
|
|
8336
|
-
attributes,
|
|
8337
|
-
drawRange: (
|
|
8338
|
-
/* alloc */
|
|
8339
|
-
{ start: 0, count: attributes.position.count }
|
|
8340
|
-
)
|
|
8341
|
-
}
|
|
8172
|
+
{ once: true }
|
|
8342
8173
|
);
|
|
8343
|
-
|
|
8344
|
-
|
|
8345
|
-
|
|
8346
|
-
|
|
8347
|
-
|
|
8348
|
-
program: createProgram(
|
|
8349
|
-
layer,
|
|
8350
|
-
/* alloc */
|
|
8351
|
-
{
|
|
8352
|
-
instanced: Boolean(data.instanceOffsets),
|
|
8353
|
-
vertexColors: true,
|
|
8354
|
-
roofTexture: layer.options.roofTexture,
|
|
8355
|
-
wallTexture: layer.options.wallTexture,
|
|
8356
|
-
nightLight: Boolean(layer.options.nightLight),
|
|
8357
|
-
alphaMode: layer.options.nightLight ? "BLEND" : void 0,
|
|
8358
|
-
doubleSided: Boolean(layer.options.nightLight)
|
|
8359
|
-
}
|
|
8360
|
-
),
|
|
8361
|
-
id: nextId.value++,
|
|
8362
|
-
renderOrder: 0,
|
|
8363
|
-
fadeDuration: 250,
|
|
8364
|
-
extras: (
|
|
8365
|
-
/* alloc */
|
|
8366
|
-
{ featureFaces: context.featureFaces, lights: context.lights }
|
|
8367
|
-
)
|
|
8368
|
-
};
|
|
8369
|
-
area2.buildings = context.featureFaces.length;
|
|
8370
|
-
area2.skipped = context.skipped;
|
|
8371
|
-
area2.done = true;
|
|
8372
|
-
setParent(area2.mesh, rootByLayer.get(layer));
|
|
8373
|
-
update(layer);
|
|
8174
|
+
if (task.signal.aborted) {
|
|
8175
|
+
reject(task.signal.reason);
|
|
8176
|
+
return;
|
|
8177
|
+
}
|
|
8178
|
+
task.worker.postMessage(task.input);
|
|
8374
8179
|
}
|
|
8375
8180
|
|
|
8376
|
-
// src/
|
|
8377
|
-
var
|
|
8181
|
+
// src/weakmaps/geometryWorkersByMap.js
|
|
8182
|
+
var geometryWorkersByMap = /* @__PURE__ */ new WeakMap();
|
|
8378
8183
|
|
|
8379
|
-
// src/
|
|
8380
|
-
function
|
|
8381
|
-
|
|
8382
|
-
|
|
8184
|
+
// src/workers/closeGeometryWorkers.js
|
|
8185
|
+
function closeGeometryWorkers(pool) {
|
|
8186
|
+
pool.closed = true;
|
|
8187
|
+
let entry;
|
|
8188
|
+
for (entry of pool.entries) {
|
|
8189
|
+
entry.closed = true;
|
|
8190
|
+
entry.worker.terminate();
|
|
8191
|
+
if (entry.task) entry.task.reject(
|
|
8383
8192
|
/* alloc */
|
|
8384
|
-
new
|
|
8193
|
+
new DOMException("Map removed", "AbortError")
|
|
8385
8194
|
);
|
|
8386
8195
|
}
|
|
8387
|
-
|
|
8388
|
-
|
|
8389
|
-
let s, rx, ry, swap;
|
|
8390
|
-
for (s = n / 2; s >= 1; s /= 2) {
|
|
8391
|
-
rx = x & s ? 1 : 0, ry = y & s ? 1 : 0;
|
|
8392
|
-
id += s * s * (3 * rx ^ ry);
|
|
8393
|
-
if (!ry) {
|
|
8394
|
-
if (rx) {
|
|
8395
|
-
x = n - 1 - x;
|
|
8396
|
-
y = n - 1 - y;
|
|
8397
|
-
}
|
|
8398
|
-
swap = x;
|
|
8399
|
-
x = y;
|
|
8400
|
-
y = swap;
|
|
8401
|
-
}
|
|
8402
|
-
}
|
|
8403
|
-
return id;
|
|
8196
|
+
pool.entries.clear();
|
|
8197
|
+
pool.idle.length = 0;
|
|
8404
8198
|
}
|
|
8405
8199
|
|
|
8406
|
-
// src/
|
|
8407
|
-
|
|
8408
|
-
|
|
8409
|
-
|
|
8410
|
-
|
|
8411
|
-
|
|
8412
|
-
|
|
8413
|
-
|
|
8414
|
-
|
|
8415
|
-
|
|
8416
|
-
let factor, byte;
|
|
8417
|
-
for (factor = 1; factor <= 2 ** 49; factor *= 128) {
|
|
8418
|
-
if (reader.cursor >= bytes.length) {
|
|
8419
|
-
throw (
|
|
8420
|
-
/* alloc */
|
|
8421
|
-
new Error("Truncated PMTiles directory")
|
|
8422
|
-
);
|
|
8423
|
-
}
|
|
8424
|
-
byte = bytes[reader.cursor++];
|
|
8425
|
-
value += (byte & 127) * factor;
|
|
8426
|
-
if (!Number.isSafeInteger(value)) {
|
|
8427
|
-
throw (
|
|
8200
|
+
// src/workers/createGeometryWorker.js
|
|
8201
|
+
function createGeometryWorker(url, pool) {
|
|
8202
|
+
let workerUrl = url, blobUrl, worker;
|
|
8203
|
+
if (globalThis.location) {
|
|
8204
|
+
const resolved = (
|
|
8205
|
+
/* alloc */
|
|
8206
|
+
new URL(url, location.href)
|
|
8207
|
+
);
|
|
8208
|
+
if ((resolved.protocol === "https:" || resolved.protocol === "http:") && resolved.origin !== location.origin) {
|
|
8209
|
+
blobUrl = URL.createObjectURL(
|
|
8428
8210
|
/* alloc */
|
|
8429
|
-
new
|
|
8211
|
+
new Blob(
|
|
8212
|
+
/* alloc */
|
|
8213
|
+
[`import ${JSON.stringify(resolved.href)};`],
|
|
8214
|
+
/* alloc */
|
|
8215
|
+
{ type: "text/javascript" }
|
|
8216
|
+
)
|
|
8430
8217
|
);
|
|
8218
|
+
workerUrl = blobUrl;
|
|
8431
8219
|
}
|
|
8432
|
-
if (byte < 128) return value;
|
|
8433
8220
|
}
|
|
8434
|
-
|
|
8221
|
+
try {
|
|
8222
|
+
worker = /* alloc */
|
|
8223
|
+
new Worker(
|
|
8224
|
+
workerUrl,
|
|
8225
|
+
/* alloc */
|
|
8226
|
+
{ type: "module" }
|
|
8227
|
+
);
|
|
8228
|
+
} finally {
|
|
8229
|
+
if (!worker && blobUrl) URL.revokeObjectURL(blobUrl);
|
|
8230
|
+
}
|
|
8231
|
+
const entry = (
|
|
8435
8232
|
/* alloc */
|
|
8436
|
-
|
|
8233
|
+
{ url, pool, worker, blobUrl }
|
|
8437
8234
|
);
|
|
8235
|
+
if (pool) pool.entries.add(entry);
|
|
8236
|
+
return entry;
|
|
8438
8237
|
}
|
|
8439
8238
|
|
|
8440
|
-
// src/
|
|
8441
|
-
function
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
/* alloc */
|
|
8445
|
-
|
|
8446
|
-
);
|
|
8447
|
-
reader.bytes = bytes;
|
|
8448
|
-
reader.cursor = 0;
|
|
8449
|
-
try {
|
|
8450
|
-
const count = varint(reader);
|
|
8451
|
-
if (count > (bytes.length - reader.cursor) / 4) {
|
|
8452
|
-
throw (
|
|
8453
|
-
/* alloc */
|
|
8454
|
-
new Error("Invalid PMTiles directory count")
|
|
8455
|
-
);
|
|
8456
|
-
}
|
|
8457
|
-
const entries = (
|
|
8239
|
+
// src/workers/acquireGeometryWorker.js
|
|
8240
|
+
function acquireGeometryWorker(map, url) {
|
|
8241
|
+
let pool = map && geometryWorkersByMap.get(map);
|
|
8242
|
+
if (map && !pool) {
|
|
8243
|
+
pool = /* alloc */
|
|
8244
|
+
{ entries: (
|
|
8458
8245
|
/* alloc */
|
|
8459
|
-
new
|
|
8246
|
+
/* @__PURE__ */ new Set()
|
|
8247
|
+
), idle: (
|
|
8248
|
+
/* alloc */
|
|
8249
|
+
[]
|
|
8250
|
+
), closed: false };
|
|
8251
|
+
geometryWorkersByMap.set(map, pool);
|
|
8252
|
+
map.once("unload", closeGeometryWorkers.bind(null, pool));
|
|
8253
|
+
}
|
|
8254
|
+
let entry, i;
|
|
8255
|
+
if (pool) {
|
|
8256
|
+
if (pool.closed) throw (
|
|
8257
|
+
/* alloc */
|
|
8258
|
+
new DOMException("Map removed", "AbortError")
|
|
8460
8259
|
);
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
|
|
8464
|
-
|
|
8465
|
-
|
|
8466
|
-
throw (
|
|
8467
|
-
/* alloc */
|
|
8468
|
-
new Error("Invalid PMTiles directory tile IDs")
|
|
8469
|
-
);
|
|
8470
|
-
}
|
|
8471
|
-
entries[i] = /* alloc */
|
|
8472
|
-
{ tileId: tileId2, runLength: 0, length: 0, offset: 0 };
|
|
8473
|
-
}
|
|
8474
|
-
for (entry of entries) entry.runLength = varint(reader);
|
|
8475
|
-
for (entry of entries) {
|
|
8476
|
-
entry.length = varint(reader);
|
|
8477
|
-
if (!entry.length) {
|
|
8478
|
-
throw (
|
|
8479
|
-
/* alloc */
|
|
8480
|
-
new Error("Invalid PMTiles directory length")
|
|
8481
|
-
);
|
|
8482
|
-
}
|
|
8260
|
+
for (i = 0; i < pool.idle.length; i++) {
|
|
8261
|
+
if (pool.idle[i].url !== url) continue;
|
|
8262
|
+
entry = pool.idle[i];
|
|
8263
|
+
pool.idle.splice(i, 1);
|
|
8264
|
+
return entry;
|
|
8483
8265
|
}
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
/* alloc */
|
|
8490
|
-
new Error("Invalid PMTiles directory offset")
|
|
8491
|
-
);
|
|
8492
|
-
}
|
|
8493
|
-
entry.offset = value ? value - 1 : entries[i - 1].offset + entries[i - 1].length;
|
|
8266
|
+
entry = pool.idle.pop();
|
|
8267
|
+
if (entry) {
|
|
8268
|
+
entry.closed = true;
|
|
8269
|
+
entry.worker.terminate();
|
|
8270
|
+
pool.entries.delete(entry);
|
|
8494
8271
|
}
|
|
8495
|
-
|
|
8496
|
-
|
|
8272
|
+
}
|
|
8273
|
+
return createGeometryWorker(url, pool);
|
|
8274
|
+
}
|
|
8275
|
+
|
|
8276
|
+
// src/workers/buildAreaInWorker.js
|
|
8277
|
+
async function buildAreaInWorker(context, signal) {
|
|
8278
|
+
const entry = acquireGeometryWorker(context.map || context.backend._map, context.backend.options.workerUrl || geometryWorkerUrl);
|
|
8279
|
+
const { worker, pool } = entry;
|
|
8280
|
+
const task = (
|
|
8281
|
+
/* alloc */
|
|
8282
|
+
{
|
|
8283
|
+
worker,
|
|
8284
|
+
signal,
|
|
8285
|
+
input: (
|
|
8497
8286
|
/* alloc */
|
|
8498
|
-
|
|
8499
|
-
)
|
|
8287
|
+
{ jobs: context.jobs, nightLight: Boolean(context.backend.options.nightLight) }
|
|
8288
|
+
)
|
|
8500
8289
|
}
|
|
8501
|
-
|
|
8290
|
+
);
|
|
8291
|
+
entry.task = task;
|
|
8292
|
+
let completed = false;
|
|
8293
|
+
try {
|
|
8294
|
+
const data = await /* alloc */
|
|
8295
|
+
new Promise(startGeometryWorker.bind(null, task));
|
|
8296
|
+
let i;
|
|
8297
|
+
for (i = 0; i < data.ranges.length; i++) Object.assign(context.featureFaces[i], data.ranges[i]);
|
|
8298
|
+
context.positions = data.positions;
|
|
8299
|
+
context.uvs = data.uvs;
|
|
8300
|
+
context.lights = data.lights;
|
|
8301
|
+
context.preparedGeometry = data;
|
|
8302
|
+
completed = true;
|
|
8303
|
+
} finally {
|
|
8304
|
+
worker.removeEventListener("message", task.onEvent);
|
|
8305
|
+
worker.removeEventListener("error", task.onEvent);
|
|
8306
|
+
worker.removeEventListener("messageerror", task.onEvent);
|
|
8307
|
+
signal.removeEventListener("abort", task.onEvent);
|
|
8308
|
+
entry.task = null;
|
|
8309
|
+
if (completed && pool && !pool.closed && !signal.aborted) pool.idle.push(entry);
|
|
8310
|
+
else {
|
|
8311
|
+
if (!entry.closed) worker.terminate();
|
|
8312
|
+
if (pool) pool.entries.delete(entry);
|
|
8313
|
+
}
|
|
8314
|
+
if (entry.blobUrl) {
|
|
8315
|
+
URL.revokeObjectURL(entry.blobUrl);
|
|
8316
|
+
entry.blobUrl = null;
|
|
8317
|
+
}
|
|
8318
|
+
context.jobs = null;
|
|
8319
|
+
}
|
|
8320
|
+
}
|
|
8321
|
+
|
|
8322
|
+
// src/projections/projectTreePoint.js
|
|
8323
|
+
init_L();
|
|
8324
|
+
function projectedTree(context, lon, lat) {
|
|
8325
|
+
const { backend: layer, crs, origin, metres, map } = context;
|
|
8326
|
+
const location2 = (
|
|
8327
|
+
/* alloc */
|
|
8328
|
+
new L.LatLng(lat, lon)
|
|
8329
|
+
);
|
|
8330
|
+
const point = crs.project(location2);
|
|
8331
|
+
const elevation = mapElevationOf(map, location2), root = rootByLayer.get(layer);
|
|
8332
|
+
return (
|
|
8333
|
+
/* alloc */
|
|
8334
|
+
{
|
|
8335
|
+
x: (point.x - origin.x) * metres,
|
|
8336
|
+
y: (point.y - origin.y) * metres,
|
|
8337
|
+
ground: Number.isFinite(elevation) && Number.isFinite(root.position[1]) ? elevation - root.position[1] : 0
|
|
8338
|
+
}
|
|
8339
|
+
);
|
|
8340
|
+
}
|
|
8341
|
+
|
|
8342
|
+
// src/globals/triangleContexts.js
|
|
8343
|
+
var triangleContexts = [];
|
|
8344
|
+
|
|
8345
|
+
// src/sources/groundOffset.js
|
|
8346
|
+
function groundOffset(point) {
|
|
8347
|
+
return point.ground || 0;
|
|
8348
|
+
}
|
|
8349
|
+
|
|
8350
|
+
// src/geometry/appendAreaTriangle.js
|
|
8351
|
+
function addTriangle(context, a, ah, b, bh, c, ch, nx, ny, nz, color) {
|
|
8352
|
+
const { backend: layer, positions, normals, colors, uvs } = context;
|
|
8353
|
+
const ux = b.x - a.x, uy = bh - ah, uz = a.y - b.y;
|
|
8354
|
+
const vx = c.x - a.x, vy = ch - ah, vz = a.y - c.y;
|
|
8355
|
+
if ((uy * vz - uz * vy) * nx + (uz * vx - ux * vz) * ny + (ux * vy - uy * vx) * nz < 0) {
|
|
8356
|
+
const point = b, height = bh;
|
|
8357
|
+
b = c;
|
|
8358
|
+
bh = ch;
|
|
8359
|
+
c = point;
|
|
8360
|
+
ch = height;
|
|
8361
|
+
}
|
|
8362
|
+
positions.push(
|
|
8363
|
+
a.x,
|
|
8364
|
+
ah + groundOffset(a),
|
|
8365
|
+
-a.y,
|
|
8366
|
+
b.x,
|
|
8367
|
+
bh + groundOffset(b),
|
|
8368
|
+
-b.y,
|
|
8369
|
+
c.x,
|
|
8370
|
+
ch + groundOffset(c),
|
|
8371
|
+
-c.y
|
|
8372
|
+
);
|
|
8373
|
+
normals.push(nx, ny, nz, nx, ny, nz, nx, ny, nz);
|
|
8374
|
+
colors.push(color.r, color.g, color.b, color.r, color.g, color.b, color.r, color.g, color.b);
|
|
8375
|
+
if (layer.options.nightLight) uvs.push(...a.uv, ...b.uv, ...c.uv);
|
|
8376
|
+
}
|
|
8377
|
+
|
|
8378
|
+
// src/geometry/addGeneratedTriangle.js
|
|
8379
|
+
function addGeneratedTriangle(...args) {
|
|
8380
|
+
addTriangle(triangleContexts[triangleContexts.length - 1], ...args);
|
|
8381
|
+
}
|
|
8382
|
+
|
|
8383
|
+
// src/geometry/generateTreeGeometry.js
|
|
8384
|
+
function generateTreeGeometry(context, generator, point, style) {
|
|
8385
|
+
triangleContexts.push(context);
|
|
8386
|
+
try {
|
|
8387
|
+
generator(point, style, addGeneratedTriangle);
|
|
8502
8388
|
} finally {
|
|
8503
|
-
|
|
8504
|
-
reader.cursor = 0;
|
|
8389
|
+
triangleContexts.pop();
|
|
8505
8390
|
}
|
|
8506
8391
|
}
|
|
8507
8392
|
|
|
8508
|
-
// src/
|
|
8509
|
-
|
|
8510
|
-
|
|
8511
|
-
|
|
8393
|
+
// src/globals/lampDirections.js
|
|
8394
|
+
var lampDirections = [
|
|
8395
|
+
{ x: Math.cos(0 * Math.PI / 3), y: Math.sin(0 * Math.PI / 3), nx: Math.cos(0.5 * Math.PI / 3), nz: -Math.sin(0.5 * Math.PI / 3) },
|
|
8396
|
+
{ x: Math.cos(1 * Math.PI / 3), y: Math.sin(1 * Math.PI / 3), nx: Math.cos(1.5 * Math.PI / 3), nz: -Math.sin(1.5 * Math.PI / 3) },
|
|
8397
|
+
{ x: Math.cos(2 * Math.PI / 3), y: Math.sin(2 * Math.PI / 3), nx: Math.cos(2.5 * Math.PI / 3), nz: -Math.sin(2.5 * Math.PI / 3) },
|
|
8398
|
+
{ x: Math.cos(3 * Math.PI / 3), y: Math.sin(3 * Math.PI / 3), nx: Math.cos(3.5 * Math.PI / 3), nz: -Math.sin(3.5 * Math.PI / 3) },
|
|
8399
|
+
{ x: Math.cos(4 * Math.PI / 3), y: Math.sin(4 * Math.PI / 3), nx: Math.cos(4.5 * Math.PI / 3), nz: -Math.sin(4.5 * Math.PI / 3) },
|
|
8400
|
+
{ x: Math.cos(5 * Math.PI / 3), y: Math.sin(5 * Math.PI / 3), nx: Math.cos(5.5 * Math.PI / 3), nz: -Math.sin(5.5 * Math.PI / 3) }
|
|
8401
|
+
];
|
|
8402
|
+
|
|
8403
|
+
// src/geometry/createLampRing.js
|
|
8404
|
+
function ring(point, radius) {
|
|
8405
|
+
const points = (
|
|
8406
|
+
/* alloc */
|
|
8407
|
+
new Array(lampDirections.length)
|
|
8408
|
+
);
|
|
8409
|
+
let i;
|
|
8410
|
+
for (i = 0; i < points.length; i++) {
|
|
8411
|
+
points[i] = /* alloc */
|
|
8412
|
+
{
|
|
8413
|
+
x: point.x + lampDirections[i].x * radius,
|
|
8414
|
+
y: point.y + lampDirections[i].y * radius,
|
|
8415
|
+
ground: point.ground,
|
|
8416
|
+
uv: (
|
|
8417
|
+
/* alloc */
|
|
8418
|
+
[3, 3]
|
|
8419
|
+
)
|
|
8420
|
+
};
|
|
8421
|
+
}
|
|
8422
|
+
return points;
|
|
8423
|
+
}
|
|
8424
|
+
|
|
8425
|
+
// src/geometry/lampPostGeometry.js
|
|
8426
|
+
function lampPostGeometry(point, style, addTriangle2) {
|
|
8427
|
+
const color = parseColor(5264986), radius = style.poleRadius;
|
|
8428
|
+
if (!Number.isFinite(radius) || radius <= 0) {
|
|
8512
8429
|
throw (
|
|
8513
8430
|
/* alloc */
|
|
8514
|
-
new Error(
|
|
8431
|
+
new Error("Invalid lamp pole radius")
|
|
8515
8432
|
);
|
|
8516
8433
|
}
|
|
8517
|
-
const
|
|
8518
|
-
/* alloc */
|
|
8519
|
-
new Blob(
|
|
8520
|
-
/* alloc */
|
|
8521
|
-
[data]
|
|
8522
|
-
)
|
|
8523
|
-
);
|
|
8524
|
-
const stream = (
|
|
8434
|
+
const center = (
|
|
8525
8435
|
/* alloc */
|
|
8526
|
-
|
|
8436
|
+
{
|
|
8437
|
+
...point,
|
|
8438
|
+
uv: (
|
|
8439
|
+
/* alloc */
|
|
8440
|
+
[3, 3]
|
|
8441
|
+
)
|
|
8442
|
+
}
|
|
8527
8443
|
);
|
|
8444
|
+
let r, low, high, points, i, a, b, nx, nz, section;
|
|
8445
|
+
for (section = 0; section < 2; section++) {
|
|
8446
|
+
r = section ? radius * 2.5 : radius;
|
|
8447
|
+
low = section ? style.top - 0.25 : 0;
|
|
8448
|
+
high = section ? style.top + 0.15 : style.top;
|
|
8449
|
+
points = ring(point, r);
|
|
8450
|
+
for (i = 0; i < 6; i++) {
|
|
8451
|
+
a = points[i], b = points[(i + 1) % 6];
|
|
8452
|
+
nx = lampDirections[i].nx, nz = lampDirections[i].nz;
|
|
8453
|
+
addTriangle2(a, low, b, low, b, high, nx, 0, nz, color);
|
|
8454
|
+
addTriangle2(a, low, b, high, a, high, nx, 0, nz, color);
|
|
8455
|
+
addTriangle2(center, high, a, high, b, high, 0, 1, 0, color);
|
|
8456
|
+
addTriangle2(center, low, b, low, a, low, 0, -1, 0, color);
|
|
8457
|
+
}
|
|
8458
|
+
}
|
|
8459
|
+
}
|
|
8460
|
+
|
|
8461
|
+
// src/geometry/quad.js
|
|
8462
|
+
function quad(addTriangle2, color, a, b, c, d, height, nx, ny, nz) {
|
|
8463
|
+
if (typeof nx !== "number") {
|
|
8464
|
+
addTriangle2(a, height, b, height, c, height, ...nx, color);
|
|
8465
|
+
addTriangle2(a, height, c, height, d, height, ...nx, color);
|
|
8466
|
+
} else {
|
|
8467
|
+
addTriangle2(a, height, b, height, c, height, nx, ny, nz, color);
|
|
8468
|
+
addTriangle2(a, height, c, height, d, height, nx, ny, nz, color);
|
|
8469
|
+
}
|
|
8470
|
+
}
|
|
8471
|
+
|
|
8472
|
+
// src/geometry/emitter.js
|
|
8473
|
+
function emitter(point, u, v, axis) {
|
|
8474
|
+
const r = 0.65;
|
|
8528
8475
|
return (
|
|
8529
8476
|
/* alloc */
|
|
8530
|
-
|
|
8477
|
+
{
|
|
8478
|
+
x: point.x + (axis === 2 ? 0 : u * r),
|
|
8479
|
+
y: point.y + (axis === 1 ? 0 : axis === 2 ? u * r : v * r),
|
|
8480
|
+
ground: point.ground + (axis === 0 ? 0 : v * r),
|
|
8481
|
+
uv: (
|
|
8482
|
+
/* alloc */
|
|
8483
|
+
[u, v]
|
|
8484
|
+
)
|
|
8485
|
+
}
|
|
8531
8486
|
);
|
|
8532
8487
|
}
|
|
8533
8488
|
|
|
8534
|
-
// src/
|
|
8535
|
-
|
|
8536
|
-
|
|
8489
|
+
// src/geometry/lightGeometry.js
|
|
8490
|
+
function lightGeometry(point, style, addTriangle2) {
|
|
8491
|
+
if (!Number.isFinite(style.lightRadius) || style.lightRadius <= 0) throw (
|
|
8492
|
+
/* alloc */
|
|
8493
|
+
new Error("Invalid light radius")
|
|
8494
|
+
);
|
|
8495
|
+
const color = parseColor(style.color);
|
|
8496
|
+
let axis;
|
|
8497
|
+
for (axis = 0; axis < 3; axis++) {
|
|
8498
|
+
quad(
|
|
8499
|
+
addTriangle2,
|
|
8500
|
+
color,
|
|
8501
|
+
emitter(point, -1, -1, axis),
|
|
8502
|
+
emitter(point, 1, -1, axis),
|
|
8503
|
+
emitter(point, 1, 1, axis),
|
|
8504
|
+
emitter(point, -1, 1, axis),
|
|
8505
|
+
style.top,
|
|
8506
|
+
axis === 2 ? 1 : 0,
|
|
8507
|
+
axis === 0 ? 1 : 0,
|
|
8508
|
+
axis === 1 ? 1 : 0
|
|
8509
|
+
);
|
|
8510
|
+
}
|
|
8537
8511
|
}
|
|
8538
8512
|
|
|
8539
|
-
// src/
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8513
|
+
// src/globals/roundProfile.js
|
|
8514
|
+
var roundProfile = [
|
|
8515
|
+
[0, 0],
|
|
8516
|
+
[0.35, 0.8],
|
|
8517
|
+
[0.6, 1],
|
|
8518
|
+
[0.85, 0.7],
|
|
8519
|
+
[1, 0]
|
|
8520
|
+
];
|
|
8521
|
+
|
|
8522
|
+
// src/globals/ringDirections.js
|
|
8523
|
+
var ringDirections = [
|
|
8524
|
+
{
|
|
8525
|
+
x: Math.cos(0 * Math.PI / 4),
|
|
8526
|
+
y: Math.sin(0 * Math.PI / 4),
|
|
8527
|
+
nx: Math.cos((0 + 0.5) * Math.PI / 4),
|
|
8528
|
+
nz: -Math.sin((0 + 0.5) * Math.PI / 4)
|
|
8529
|
+
},
|
|
8530
|
+
{
|
|
8531
|
+
x: Math.cos(1 * Math.PI / 4),
|
|
8532
|
+
y: Math.sin(1 * Math.PI / 4),
|
|
8533
|
+
nx: Math.cos((1 + 0.5) * Math.PI / 4),
|
|
8534
|
+
nz: -Math.sin((1 + 0.5) * Math.PI / 4)
|
|
8535
|
+
},
|
|
8536
|
+
{
|
|
8537
|
+
x: Math.cos(2 * Math.PI / 4),
|
|
8538
|
+
y: Math.sin(2 * Math.PI / 4),
|
|
8539
|
+
nx: Math.cos((2 + 0.5) * Math.PI / 4),
|
|
8540
|
+
nz: -Math.sin((2 + 0.5) * Math.PI / 4)
|
|
8541
|
+
},
|
|
8542
|
+
{
|
|
8543
|
+
x: Math.cos(3 * Math.PI / 4),
|
|
8544
|
+
y: Math.sin(3 * Math.PI / 4),
|
|
8545
|
+
nx: Math.cos((3 + 0.5) * Math.PI / 4),
|
|
8546
|
+
nz: -Math.sin((3 + 0.5) * Math.PI / 4)
|
|
8547
|
+
},
|
|
8548
|
+
{
|
|
8549
|
+
x: Math.cos(4 * Math.PI / 4),
|
|
8550
|
+
y: Math.sin(4 * Math.PI / 4),
|
|
8551
|
+
nx: Math.cos((4 + 0.5) * Math.PI / 4),
|
|
8552
|
+
nz: -Math.sin((4 + 0.5) * Math.PI / 4)
|
|
8553
|
+
},
|
|
8554
|
+
{
|
|
8555
|
+
x: Math.cos(5 * Math.PI / 4),
|
|
8556
|
+
y: Math.sin(5 * Math.PI / 4),
|
|
8557
|
+
nx: Math.cos((5 + 0.5) * Math.PI / 4),
|
|
8558
|
+
nz: -Math.sin((5 + 0.5) * Math.PI / 4)
|
|
8559
|
+
},
|
|
8560
|
+
{
|
|
8561
|
+
x: Math.cos(6 * Math.PI / 4),
|
|
8562
|
+
y: Math.sin(6 * Math.PI / 4),
|
|
8563
|
+
nx: Math.cos((6 + 0.5) * Math.PI / 4),
|
|
8564
|
+
nz: -Math.sin((6 + 0.5) * Math.PI / 4)
|
|
8565
|
+
},
|
|
8566
|
+
{
|
|
8567
|
+
x: Math.cos(7 * Math.PI / 4),
|
|
8568
|
+
y: Math.sin(7 * Math.PI / 4),
|
|
8569
|
+
nx: Math.cos((7 + 0.5) * Math.PI / 4),
|
|
8570
|
+
nz: -Math.sin((7 + 0.5) * Math.PI / 4)
|
|
8553
8571
|
}
|
|
8554
|
-
|
|
8572
|
+
];
|
|
8555
8573
|
|
|
8556
|
-
// src/
|
|
8557
|
-
function
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8574
|
+
// src/geometry/createTreeRing.js
|
|
8575
|
+
function ring2(point, radius) {
|
|
8576
|
+
const result = (
|
|
8577
|
+
/* alloc */
|
|
8578
|
+
new Array(ringDirections.length)
|
|
8579
|
+
);
|
|
8580
|
+
let i;
|
|
8581
|
+
for (i = 0; i < result.length; i++) {
|
|
8582
|
+
result[i] = /* alloc */
|
|
8583
|
+
{
|
|
8584
|
+
x: point.x + ringDirections[i].x * radius,
|
|
8585
|
+
y: point.y + ringDirections[i].y * radius,
|
|
8586
|
+
ground: point.ground
|
|
8587
|
+
};
|
|
8563
8588
|
}
|
|
8564
|
-
return
|
|
8589
|
+
return result;
|
|
8565
8590
|
}
|
|
8566
8591
|
|
|
8567
|
-
// src/
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8592
|
+
// src/geometry/surface.js
|
|
8593
|
+
function surface(point, addTriangle2, lowRadius, low, highRadius, high, color) {
|
|
8594
|
+
const lower = ring2(point, lowRadius), upper = ring2(point, highRadius);
|
|
8595
|
+
let i, next, slope, length, nx, nz, ny, normalX, normalZ;
|
|
8596
|
+
for (i = 0; i < 8; i++) {
|
|
8597
|
+
next = (i + 1) % 8;
|
|
8598
|
+
slope = (lowRadius - highRadius) / (high - low);
|
|
8599
|
+
length = Math.hypot(1, slope);
|
|
8600
|
+
({ nx, nz } = ringDirections[i]);
|
|
8601
|
+
ny = slope / length;
|
|
8602
|
+
normalX = nx / length, normalZ = nz / length;
|
|
8603
|
+
if (lowRadius) addTriangle2(lower[i], low, lower[next], low, upper[next], high, normalX, ny, normalZ, color);
|
|
8604
|
+
if (highRadius) addTriangle2(lower[i], low, upper[next], high, upper[i], high, normalX, ny, normalZ, color);
|
|
8605
|
+
}
|
|
8606
|
+
}
|
|
8607
|
+
|
|
8608
|
+
// src/geometry/validateTree.js
|
|
8609
|
+
function validateTree(trunkRadius, crownRadius, crownBottom, bottom, top, crownShape) {
|
|
8610
|
+
if (!Number.isFinite(trunkRadius) || !Number.isFinite(crownRadius) || !Number.isFinite(crownBottom) || trunkRadius <= 0 || crownRadius < trunkRadius || crownBottom <= bottom || crownBottom >= top || crownShape !== "round" && crownShape !== "cone") {
|
|
8571
8611
|
throw (
|
|
8572
8612
|
/* alloc */
|
|
8573
|
-
new Error("
|
|
8613
|
+
new Error("Invalid tree dimensions or crown shape")
|
|
8574
8614
|
);
|
|
8575
8615
|
}
|
|
8576
|
-
const data = await decompress(
|
|
8577
|
-
await read(layer, header.tileDataOffset + entry.offset, entry.length, signal),
|
|
8578
|
-
header.tileCompression
|
|
8579
|
-
);
|
|
8580
|
-
signal?.throwIfAborted();
|
|
8581
|
-
return (
|
|
8582
|
-
/* alloc */
|
|
8583
|
-
{ data }
|
|
8584
|
-
);
|
|
8585
8616
|
}
|
|
8586
8617
|
|
|
8587
|
-
// src/
|
|
8588
|
-
|
|
8589
|
-
|
|
8590
|
-
|
|
8591
|
-
|
|
8592
|
-
|
|
8593
|
-
|
|
8594
|
-
|
|
8595
|
-
|
|
8596
|
-
|
|
8597
|
-
|
|
8598
|
-
|
|
8599
|
-
|
|
8600
|
-
|
|
8601
|
-
|
|
8602
|
-
|
|
8603
|
-
|
|
8604
|
-
|
|
8605
|
-
|
|
8606
|
-
|
|
8607
|
-
|
|
8608
|
-
|
|
8609
|
-
|
|
8610
|
-
|
|
8611
|
-
|
|
8612
|
-
|
|
8613
|
-
|
|
8618
|
+
// src/geometry/treeGeometry.js
|
|
8619
|
+
function treeGeometry(point, style, addTriangle2) {
|
|
8620
|
+
const { top, bottom = 0, trunkRadius, crownRadius, crownBottom, crownShape = "round" } = style;
|
|
8621
|
+
validateTree(trunkRadius, crownRadius, crownBottom, bottom, top, crownShape);
|
|
8622
|
+
const trunk = parseColor(style.trunkColor ?? 7491898);
|
|
8623
|
+
const crown = parseColor(style.color ?? 5210683);
|
|
8624
|
+
surface(point, addTriangle2, trunkRadius, bottom, trunkRadius, crownBottom + (top - crownBottom) * 0.25, trunk);
|
|
8625
|
+
let i, low, lr, high, hr;
|
|
8626
|
+
if (crownShape === "cone") {
|
|
8627
|
+
const base = ring2(point, crownRadius);
|
|
8628
|
+
for (i = 0; i < 8; i++) addTriangle2(
|
|
8629
|
+
point,
|
|
8630
|
+
crownBottom,
|
|
8631
|
+
base[i],
|
|
8632
|
+
crownBottom,
|
|
8633
|
+
base[(i + 1) % 8],
|
|
8634
|
+
crownBottom,
|
|
8635
|
+
0,
|
|
8636
|
+
-1,
|
|
8637
|
+
0,
|
|
8638
|
+
crown
|
|
8639
|
+
);
|
|
8640
|
+
surface(point, addTriangle2, crownRadius, crownBottom, 0, top, crown);
|
|
8641
|
+
} else {
|
|
8642
|
+
for (i = 1; i < roundProfile.length; i++) {
|
|
8643
|
+
[low, lr] = roundProfile[i - 1], [high, hr] = roundProfile[i];
|
|
8644
|
+
surface(
|
|
8645
|
+
point,
|
|
8646
|
+
addTriangle2,
|
|
8647
|
+
lr * crownRadius,
|
|
8648
|
+
crownBottom + low * (top - crownBottom),
|
|
8649
|
+
hr * crownRadius,
|
|
8650
|
+
crownBottom + high * (top - crownBottom),
|
|
8651
|
+
crown
|
|
8614
8652
|
);
|
|
8615
8653
|
}
|
|
8616
|
-
offset = header.leafDirectoryOffset + entry.offset;
|
|
8617
|
-
length = entry.length;
|
|
8618
8654
|
}
|
|
8619
|
-
throw (
|
|
8620
|
-
/* alloc */
|
|
8621
|
-
new Error("PMTiles directory depth exceeds four levels")
|
|
8622
|
-
);
|
|
8623
8655
|
}
|
|
8624
8656
|
|
|
8625
|
-
// src/
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
if (
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
8657
|
+
// src/geometry/buildProjectedPoint.js
|
|
8658
|
+
function buildProjectedPoint(context, projected, style, baseColor, support) {
|
|
8659
|
+
const { top } = style;
|
|
8660
|
+
if (context.backend.options.nightLight) {
|
|
8661
|
+
if (!Number.isFinite(style.lightFlux) || style.lightFlux <= 0) throw (
|
|
8662
|
+
/* alloc */
|
|
8663
|
+
new Error("Invalid light flux")
|
|
8664
|
+
);
|
|
8665
|
+
if (style.poleRadius > 0 && !context.supports.has(support)) {
|
|
8666
|
+
generateTreeGeometry(context, lampPostGeometry, projected, style);
|
|
8667
|
+
context.supports.add(support);
|
|
8668
|
+
}
|
|
8669
|
+
generateTreeGeometry(context, lightGeometry, projected, style);
|
|
8670
|
+
context.lights.push(
|
|
8671
|
+
/* alloc */
|
|
8672
|
+
{
|
|
8673
|
+
position: (
|
|
8674
|
+
/* alloc */
|
|
8675
|
+
[projected.x, projected.ground + top, -projected.y]
|
|
8676
|
+
),
|
|
8677
|
+
radius: Math.hypot(top, style.lightRadius),
|
|
8678
|
+
color: (
|
|
8679
|
+
/* alloc */
|
|
8680
|
+
[baseColor.r, baseColor.g, baseColor.b]
|
|
8681
|
+
),
|
|
8682
|
+
flux: style.lightFlux
|
|
8683
|
+
}
|
|
8684
|
+
);
|
|
8685
|
+
} else generateTreeGeometry(context, treeGeometry, projected, style);
|
|
8637
8686
|
}
|
|
8638
8687
|
|
|
8639
|
-
// src/
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
8644
|
-
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8688
|
+
// src/sources/buildAreaPoint.js
|
|
8689
|
+
function buildAreaPoint(context, feature, lon, lat, style, baseColor) {
|
|
8690
|
+
const projected = projectedTree(context, lon, lat);
|
|
8691
|
+
buildProjectedPoint(context, projected, style, baseColor, feature.properties?.cod_ouvrag || `${lon},${lat}`);
|
|
8692
|
+
}
|
|
8693
|
+
|
|
8694
|
+
// src/projections/projectRing.js
|
|
8695
|
+
init_L();
|
|
8696
|
+
function projectRing(context, ring3) {
|
|
8697
|
+
const { backend: layer, crs, origin, metres, map } = context;
|
|
8698
|
+
if (ring3.length < 4) throw (
|
|
8699
|
+
/* alloc */
|
|
8700
|
+
new Error("Invalid GeoJSON polygon ring")
|
|
8701
|
+
);
|
|
8702
|
+
const path = (
|
|
8703
|
+
/* alloc */
|
|
8704
|
+
[]
|
|
8705
|
+
);
|
|
8706
|
+
const root = rootByLayer.get(layer);
|
|
8707
|
+
let i, lng, lat, location2, point, elevation;
|
|
8708
|
+
for (i = 0; i < ring3.length - 1; i++) {
|
|
8709
|
+
lng = ring3[i][0], lat = ring3[i][1];
|
|
8710
|
+
if (!Number.isFinite(lng) || !Number.isFinite(lat)) throw (
|
|
8657
8711
|
/* alloc */
|
|
8658
|
-
new
|
|
8712
|
+
new Error("Invalid GeoJSON coordinates")
|
|
8659
8713
|
);
|
|
8660
|
-
|
|
8661
|
-
|
|
8714
|
+
location2 = /* alloc */
|
|
8715
|
+
new L.LatLng(lat, lng);
|
|
8716
|
+
point = crs.project(location2);
|
|
8717
|
+
elevation = mapElevationOf(map, location2);
|
|
8718
|
+
path.push(
|
|
8662
8719
|
/* alloc */
|
|
8663
|
-
{
|
|
8720
|
+
{
|
|
8721
|
+
x: (point.x - origin.x) * metres,
|
|
8722
|
+
y: (point.y - origin.y) * metres,
|
|
8723
|
+
ground: Number.isFinite(elevation) && Number.isFinite(root.position[1]) ? elevation - root.position[1] : 0
|
|
8724
|
+
}
|
|
8664
8725
|
);
|
|
8665
|
-
if (!response.ok) {
|
|
8666
|
-
throw (
|
|
8667
|
-
/* alloc */
|
|
8668
|
-
new Error(`Unable to load GeoJSON: HTTP ${response.status}`)
|
|
8669
|
-
);
|
|
8670
|
-
}
|
|
8671
|
-
return response.json();
|
|
8672
8726
|
}
|
|
8673
|
-
|
|
8674
|
-
return result ? JSON.parse(archiveDecoder.decode(result.data)) : (
|
|
8675
|
-
/* alloc */
|
|
8676
|
-
{
|
|
8677
|
-
type: "FeatureCollection",
|
|
8678
|
-
features: (
|
|
8679
|
-
/* alloc */
|
|
8680
|
-
[]
|
|
8681
|
-
)
|
|
8682
|
-
}
|
|
8683
|
-
);
|
|
8727
|
+
return path;
|
|
8684
8728
|
}
|
|
8685
8729
|
|
|
8686
|
-
// src/
|
|
8687
|
-
|
|
8688
|
-
|
|
8689
|
-
const crs = map.options.crs, origin = crs.project(locationByLayer.get(layer));
|
|
8690
|
-
return (
|
|
8730
|
+
// src/geometry/buildProjectedPolygon.js
|
|
8731
|
+
function buildProjectedPolygon(context, paths, top, bottom, baseColor) {
|
|
8732
|
+
const points = (
|
|
8691
8733
|
/* alloc */
|
|
8692
|
-
|
|
8693
|
-
|
|
8694
|
-
|
|
8695
|
-
|
|
8696
|
-
|
|
8697
|
-
|
|
8698
|
-
|
|
8699
|
-
|
|
8700
|
-
|
|
8701
|
-
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
)
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
),
|
|
8711
|
-
uvs: (
|
|
8712
|
-
/* alloc */
|
|
8713
|
-
[]
|
|
8714
|
-
),
|
|
8715
|
-
featureFaces: (
|
|
8716
|
-
/* alloc */
|
|
8717
|
-
[]
|
|
8718
|
-
),
|
|
8719
|
-
lights: (
|
|
8720
|
-
/* alloc */
|
|
8721
|
-
[]
|
|
8722
|
-
),
|
|
8723
|
-
supports: (
|
|
8724
|
-
/* alloc */
|
|
8725
|
-
/* @__PURE__ */ new Set()
|
|
8726
|
-
),
|
|
8727
|
-
skipped: 0
|
|
8734
|
+
[]
|
|
8735
|
+
);
|
|
8736
|
+
let path, point, a, b, c, index, sign, i, length, nx, nz;
|
|
8737
|
+
for (path of paths) for (point of path) points.push(point);
|
|
8738
|
+
for ([a, b, c] of triangulate(paths[0], paths.slice(1))) {
|
|
8739
|
+
addTriangle(context, points[a], top, points[b], top, points[c], top, 0, 1, 0, baseColor);
|
|
8740
|
+
if (bottom > 0) addTriangle(context, points[a], bottom, points[b], bottom, points[c], bottom, 0, -1, 0, baseColor);
|
|
8741
|
+
}
|
|
8742
|
+
for (index = 0; index < paths.length; index++) {
|
|
8743
|
+
path = paths[index];
|
|
8744
|
+
sign = isClockWise(path) === (index === 0) ? -1 : 1;
|
|
8745
|
+
for (i = 0; i < path.length; i++) {
|
|
8746
|
+
a = path[i], b = path[(i + 1) % path.length];
|
|
8747
|
+
length = Math.hypot(b.x - a.x, b.y - a.y);
|
|
8748
|
+
if (!length) continue;
|
|
8749
|
+
nx = sign * (b.y - a.y) / length, nz = sign * (b.x - a.x) / length;
|
|
8750
|
+
addTriangle(context, a, bottom, b, bottom, b, top, nx, 0, nz, baseColor);
|
|
8751
|
+
addTriangle(context, a, bottom, b, top, a, top, nx, 0, nz, baseColor);
|
|
8728
8752
|
}
|
|
8729
|
-
|
|
8753
|
+
}
|
|
8730
8754
|
}
|
|
8731
8755
|
|
|
8732
|
-
// src/
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
// src/workers/settleGeometryWorker.js
|
|
8736
|
-
function settleGeometryWorker(task, event) {
|
|
8737
|
-
if (event.type === "abort") task.reject(task.signal.reason);
|
|
8738
|
-
else if (event.type === "error") task.reject(
|
|
8756
|
+
// src/geometry/buildExtrudedPolygon.js
|
|
8757
|
+
function buildAreaPolygon(context, rings, top, bottom, baseColor) {
|
|
8758
|
+
if (!rings.length) throw (
|
|
8739
8759
|
/* alloc */
|
|
8740
|
-
new Error(
|
|
8760
|
+
new Error("Empty GeoJSON polygon")
|
|
8741
8761
|
);
|
|
8742
|
-
|
|
8762
|
+
const paths = (
|
|
8743
8763
|
/* alloc */
|
|
8744
|
-
|
|
8764
|
+
[]
|
|
8745
8765
|
);
|
|
8746
|
-
|
|
8747
|
-
|
|
8748
|
-
|
|
8749
|
-
new Error(event.data.error.message)
|
|
8750
|
-
);
|
|
8751
|
-
error.name = event.data.error.name;
|
|
8752
|
-
task.reject(error);
|
|
8753
|
-
} else task.resolve(event.data);
|
|
8766
|
+
let ring3;
|
|
8767
|
+
for (ring3 of rings) paths.push(projectRing(context, ring3));
|
|
8768
|
+
buildProjectedPolygon(context, paths, top, bottom, baseColor);
|
|
8754
8769
|
}
|
|
8755
8770
|
|
|
8756
|
-
// src/
|
|
8757
|
-
function
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
task.onEvent = settleGeometryWorker.bind(null, task);
|
|
8761
|
-
task.worker.addEventListener("message", task.onEvent);
|
|
8762
|
-
task.worker.addEventListener("error", task.onEvent);
|
|
8763
|
-
task.worker.addEventListener("messageerror", task.onEvent);
|
|
8764
|
-
task.signal.addEventListener(
|
|
8765
|
-
"abort",
|
|
8766
|
-
task.onEvent,
|
|
8771
|
+
// src/sources/featureAnchor.js
|
|
8772
|
+
function featureAnchor(feature, nightLight) {
|
|
8773
|
+
const geometry = feature?.geometry, point = geometry?.type === "Point";
|
|
8774
|
+
if (nightLight && !point) throw (
|
|
8767
8775
|
/* alloc */
|
|
8768
|
-
|
|
8776
|
+
new Error("Night lights require Point geometry")
|
|
8769
8777
|
);
|
|
8770
|
-
if (
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8778
|
+
if (geometry?.type !== "Polygon" && geometry?.type !== "MultiPolygon" && !point) throw (
|
|
8779
|
+
/* alloc */
|
|
8780
|
+
new Error("Unsupported GeoJSON geometry")
|
|
8781
|
+
);
|
|
8782
|
+
const coordinates = point ? geometry.coordinates : geometry.type === "Polygon" ? geometry.coordinates[0]?.[0] : geometry.coordinates[0]?.[0]?.[0];
|
|
8783
|
+
if (!Number.isFinite(coordinates?.[0]) || !Number.isFinite(coordinates?.[1])) throw (
|
|
8784
|
+
/* alloc */
|
|
8785
|
+
new Error("Invalid GeoJSON coordinates")
|
|
8786
|
+
);
|
|
8787
|
+
return coordinates;
|
|
8775
8788
|
}
|
|
8776
8789
|
|
|
8777
|
-
// src/
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8790
|
+
// src/sources/extrusionStyle.js
|
|
8791
|
+
function extrusionStyle(layer, feature) {
|
|
8792
|
+
const style = layer.options.style(feature);
|
|
8793
|
+
if (style === null) return null;
|
|
8794
|
+
if (!style || typeof style !== "object") throw (
|
|
8795
|
+
/* alloc */
|
|
8796
|
+
new Error("style must return an extrusion style or null")
|
|
8797
|
+
);
|
|
8798
|
+
const { top, bottom = 0 } = style;
|
|
8799
|
+
if (!Number.isFinite(top) || !Number.isFinite(bottom) || bottom < 0 || top <= bottom) {
|
|
8800
|
+
throw (
|
|
8788
8801
|
/* alloc */
|
|
8789
|
-
new
|
|
8802
|
+
new Error("Invalid extrusion heights: expected top > bottom >= 0")
|
|
8790
8803
|
);
|
|
8791
8804
|
}
|
|
8792
|
-
|
|
8793
|
-
pool.idle.length = 0;
|
|
8805
|
+
return style;
|
|
8794
8806
|
}
|
|
8795
8807
|
|
|
8796
|
-
// src/
|
|
8797
|
-
function
|
|
8798
|
-
|
|
8799
|
-
|
|
8800
|
-
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
|
|
8806
|
-
|
|
8807
|
-
|
|
8808
|
-
|
|
8809
|
-
|
|
8810
|
-
|
|
8811
|
-
|
|
8812
|
-
if (pool) {
|
|
8813
|
-
if (pool.closed) throw (
|
|
8808
|
+
// src/sources/projectAreaPolygons.js
|
|
8809
|
+
function projectAreaPolygons(context, geometry) {
|
|
8810
|
+
const rings = geometry.type === "Polygon" ? (
|
|
8811
|
+
/* alloc */
|
|
8812
|
+
[geometry.coordinates]
|
|
8813
|
+
) : geometry.type === "MultiPolygon" ? geometry.coordinates : (
|
|
8814
|
+
/* alloc */
|
|
8815
|
+
[]
|
|
8816
|
+
);
|
|
8817
|
+
const polygons = (
|
|
8818
|
+
/* alloc */
|
|
8819
|
+
[]
|
|
8820
|
+
);
|
|
8821
|
+
let polygon2, ring3, paths;
|
|
8822
|
+
for (polygon2 of rings) {
|
|
8823
|
+
if (!polygon2.length) throw (
|
|
8814
8824
|
/* alloc */
|
|
8815
|
-
new
|
|
8825
|
+
new Error("Empty GeoJSON polygon")
|
|
8816
8826
|
);
|
|
8817
|
-
|
|
8818
|
-
|
|
8819
|
-
|
|
8820
|
-
|
|
8821
|
-
return entry;
|
|
8822
|
-
}
|
|
8823
|
-
entry = pool.idle.pop();
|
|
8824
|
-
if (entry) {
|
|
8825
|
-
entry.closed = true;
|
|
8826
|
-
entry.worker.terminate();
|
|
8827
|
-
pool.entries.delete(entry);
|
|
8828
|
-
}
|
|
8827
|
+
paths = /* alloc */
|
|
8828
|
+
[];
|
|
8829
|
+
for (ring3 of polygon2) paths.push(projectRing(context, ring3));
|
|
8830
|
+
polygons.push(paths);
|
|
8829
8831
|
}
|
|
8830
|
-
|
|
8831
|
-
{
|
|
8832
|
-
url,
|
|
8833
|
-
pool,
|
|
8834
|
-
worker: (
|
|
8835
|
-
/* alloc */
|
|
8836
|
-
new Worker(
|
|
8837
|
-
url,
|
|
8838
|
-
/* alloc */
|
|
8839
|
-
{ type: "module" }
|
|
8840
|
-
)
|
|
8841
|
-
)
|
|
8842
|
-
};
|
|
8843
|
-
if (pool) pool.entries.add(entry);
|
|
8844
|
-
return entry;
|
|
8832
|
+
return polygons;
|
|
8845
8833
|
}
|
|
8846
8834
|
|
|
8847
|
-
// src/
|
|
8848
|
-
|
|
8849
|
-
const
|
|
8850
|
-
const
|
|
8851
|
-
const
|
|
8835
|
+
// src/sources/prepareAreaGeometryJob.js
|
|
8836
|
+
function prepareAreaGeometryJob(context, feature, lon, lat, style, baseColor) {
|
|
8837
|
+
const geometry = feature.geometry;
|
|
8838
|
+
const polygons = projectAreaPolygons(context, geometry);
|
|
8839
|
+
const point = geometry.type === "Point" ? projectedTree(context, lon, lat) : null;
|
|
8840
|
+
const nightLight = context.backend.options.nightLight;
|
|
8841
|
+
const crownColor = point ? parseColor(style.color ?? (nightLight ? void 0 : 5210683)) : baseColor;
|
|
8842
|
+
const trunkColor = point && !nightLight ? parseColor(style.trunkColor ?? 7491898) : null;
|
|
8843
|
+
context.jobs.push(
|
|
8852
8844
|
/* alloc */
|
|
8853
8845
|
{
|
|
8854
|
-
|
|
8855
|
-
|
|
8856
|
-
|
|
8846
|
+
point,
|
|
8847
|
+
polygons,
|
|
8848
|
+
baseColor: (
|
|
8857
8849
|
/* alloc */
|
|
8858
|
-
{
|
|
8850
|
+
{ r: baseColor.r, g: baseColor.g, b: baseColor.b }
|
|
8851
|
+
),
|
|
8852
|
+
support: feature.properties?.cod_ouvrag || `${lon},${lat}`,
|
|
8853
|
+
style: (
|
|
8854
|
+
/* alloc */
|
|
8855
|
+
{
|
|
8856
|
+
top: style.top,
|
|
8857
|
+
bottom: style.bottom ?? 0,
|
|
8858
|
+
color: (
|
|
8859
|
+
/* alloc */
|
|
8860
|
+
{ r: crownColor.r, g: crownColor.g, b: crownColor.b }
|
|
8861
|
+
),
|
|
8862
|
+
trunkColor: trunkColor ? (
|
|
8863
|
+
/* alloc */
|
|
8864
|
+
{ r: trunkColor.r, g: trunkColor.g, b: trunkColor.b }
|
|
8865
|
+
) : void 0,
|
|
8866
|
+
trunkRadius: style.trunkRadius,
|
|
8867
|
+
crownRadius: style.crownRadius,
|
|
8868
|
+
crownBottom: style.crownBottom,
|
|
8869
|
+
crownShape: style.crownShape,
|
|
8870
|
+
poleRadius: style.poleRadius,
|
|
8871
|
+
lightRadius: style.lightRadius,
|
|
8872
|
+
lightFlux: style.lightFlux
|
|
8873
|
+
}
|
|
8859
8874
|
)
|
|
8860
8875
|
}
|
|
8861
8876
|
);
|
|
8862
|
-
|
|
8863
|
-
|
|
8864
|
-
|
|
8865
|
-
|
|
8866
|
-
|
|
8867
|
-
|
|
8868
|
-
|
|
8869
|
-
|
|
8870
|
-
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
8874
|
-
|
|
8875
|
-
|
|
8876
|
-
|
|
8877
|
-
|
|
8878
|
-
|
|
8879
|
-
|
|
8880
|
-
|
|
8881
|
-
|
|
8882
|
-
|
|
8883
|
-
|
|
8877
|
+
}
|
|
8878
|
+
|
|
8879
|
+
// src/sources/matchesAreaTile.js
|
|
8880
|
+
init_L();
|
|
8881
|
+
function matchesAreaTile(map, coords, lon, lat) {
|
|
8882
|
+
if (!coords) return true;
|
|
8883
|
+
const anchor = map.project(
|
|
8884
|
+
/* alloc */
|
|
8885
|
+
new L.LatLng(lat, lon),
|
|
8886
|
+
coords.z
|
|
8887
|
+
);
|
|
8888
|
+
return Math.floor(anchor.x / 256) === coords.x && Math.floor(anchor.y / 256) === coords.y;
|
|
8889
|
+
}
|
|
8890
|
+
|
|
8891
|
+
// src/sources/buildAreaFeature.js
|
|
8892
|
+
function buildAreaFeature(context, feature) {
|
|
8893
|
+
const { backend: layer, area: area2, map } = context;
|
|
8894
|
+
const coords = area2.coords;
|
|
8895
|
+
const coordinates = featureAnchor(feature, layer.options.nightLight);
|
|
8896
|
+
const geometry = feature.geometry, isTree = geometry.type === "Point";
|
|
8897
|
+
const lon = coordinates[0], lat = coordinates[1];
|
|
8898
|
+
if (!matchesAreaTile(map, coords, lon, lat)) return;
|
|
8899
|
+
const style = extrusionStyle(layer, feature);
|
|
8900
|
+
if (style === null) {
|
|
8901
|
+
context.skipped++;
|
|
8902
|
+
return;
|
|
8903
|
+
}
|
|
8904
|
+
const { top, bottom = 0, color = 14267276 } = style;
|
|
8905
|
+
const baseColor = parseColor(color);
|
|
8906
|
+
if (context.jobs) {
|
|
8907
|
+
prepareAreaGeometryJob(context, feature, lon, lat, style, baseColor);
|
|
8908
|
+
context.featureFaces.push(
|
|
8909
|
+
/* alloc */
|
|
8910
|
+
{
|
|
8911
|
+
id: feature.id ?? feature.properties?.objectid ?? JSON.stringify(geometry),
|
|
8912
|
+
properties: feature.properties,
|
|
8913
|
+
baseColor
|
|
8914
|
+
}
|
|
8915
|
+
);
|
|
8916
|
+
return;
|
|
8917
|
+
}
|
|
8918
|
+
const vertexStart = context.positions.length / 3;
|
|
8919
|
+
if (isTree) buildAreaPoint(context, feature, lon, lat, style, baseColor);
|
|
8920
|
+
let polygon2;
|
|
8921
|
+
if (geometry.type === "Polygon") buildAreaPolygon(context, geometry.coordinates, top, bottom, baseColor);
|
|
8922
|
+
else if (geometry.type === "MultiPolygon") for (polygon2 of geometry.coordinates) buildAreaPolygon(context, polygon2, top, bottom, baseColor);
|
|
8923
|
+
const vertexEnd = context.positions.length / 3;
|
|
8924
|
+
context.featureFaces.push(
|
|
8925
|
+
/* alloc */
|
|
8926
|
+
{
|
|
8927
|
+
id: feature.id ?? feature.properties?.objectid ?? JSON.stringify(geometry),
|
|
8928
|
+
properties: feature.properties,
|
|
8929
|
+
baseColor,
|
|
8930
|
+
faceStart: vertexStart / 3,
|
|
8931
|
+
faceEnd: vertexEnd / 3,
|
|
8932
|
+
vertexStart,
|
|
8933
|
+
vertexEnd
|
|
8884
8934
|
}
|
|
8885
|
-
|
|
8935
|
+
);
|
|
8936
|
+
}
|
|
8937
|
+
|
|
8938
|
+
// src/sources/buildAreaFeatures.js
|
|
8939
|
+
async function buildAreaFeatures(context, area2, features) {
|
|
8940
|
+
let deadline = performance.now() + 4, feature;
|
|
8941
|
+
for (feature of features) {
|
|
8942
|
+
if (area2.request.signal.aborted) return;
|
|
8943
|
+
if (performance.now() >= deadline) {
|
|
8944
|
+
await /* alloc */
|
|
8945
|
+
new Promise(requestAnimationFrame);
|
|
8946
|
+
if (area2.request.signal.aborted) return;
|
|
8947
|
+
deadline = performance.now() + 4;
|
|
8948
|
+
}
|
|
8949
|
+
buildAreaFeature(context, feature);
|
|
8886
8950
|
}
|
|
8887
8951
|
}
|
|
8888
8952
|
|
|
8889
8953
|
// src/sources/buildArea.js
|
|
8890
8954
|
async function buildArea(layer, area2, map) {
|
|
8891
|
-
let feature;
|
|
8892
8955
|
try {
|
|
8893
8956
|
await /* alloc */
|
|
8894
8957
|
new Promise(requestAnimationFrame);
|
|
@@ -8913,17 +8976,8 @@
|
|
|
8913
8976
|
context.jobs = /* alloc */
|
|
8914
8977
|
[];
|
|
8915
8978
|
}
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
if (area2.request.signal.aborted) return;
|
|
8919
|
-
if (performance.now() >= deadline) {
|
|
8920
|
-
await /* alloc */
|
|
8921
|
-
new Promise(requestAnimationFrame);
|
|
8922
|
-
if (area2.request.signal.aborted) return;
|
|
8923
|
-
deadline = performance.now() + 4;
|
|
8924
|
-
}
|
|
8925
|
-
buildAreaFeature(context, feature);
|
|
8926
|
-
}
|
|
8979
|
+
await buildAreaFeatures(context, area2, data.features);
|
|
8980
|
+
if (area2.request.signal.aborted) return;
|
|
8927
8981
|
if (context.jobs) await buildAreaInWorker(context, area2.request.signal);
|
|
8928
8982
|
if (area2.request.signal.aborted) return;
|
|
8929
8983
|
attachAreaMesh(context);
|
|
@@ -10261,26 +10315,26 @@
|
|
|
10261
10315
|
/* alloc */
|
|
10262
10316
|
new Error("glTF mesh has no positions")
|
|
10263
10317
|
);
|
|
10264
|
-
const
|
|
10265
|
-
if (attributes.position.size !== 3 ||
|
|
10318
|
+
const vertexCount2 = attributes.position.data.length / 3;
|
|
10319
|
+
if (attributes.position.size !== 3 || vertexCount2 < 3) throw (
|
|
10266
10320
|
/* alloc */
|
|
10267
10321
|
new Error("Invalid glTF vertex attributes")
|
|
10268
10322
|
);
|
|
10269
10323
|
let attribute;
|
|
10270
10324
|
for (attribute of Object.values(attributes)) {
|
|
10271
|
-
if (attribute.data.length / attribute.size !==
|
|
10325
|
+
if (attribute.data.length / attribute.size !== vertexCount2) throw (
|
|
10272
10326
|
/* alloc */
|
|
10273
10327
|
new Error("Invalid glTF vertex attributes")
|
|
10274
10328
|
);
|
|
10275
10329
|
}
|
|
10276
10330
|
return (
|
|
10277
10331
|
/* alloc */
|
|
10278
|
-
{ attributes, vertexCount }
|
|
10332
|
+
{ attributes, vertexCount: vertexCount2 }
|
|
10279
10333
|
);
|
|
10280
10334
|
}
|
|
10281
10335
|
|
|
10282
10336
|
// src/models/readModelIndices.js
|
|
10283
|
-
function readModelIndices(description, primitive, attributes,
|
|
10337
|
+
function readModelIndices(description, primitive, attributes, vertexCount2) {
|
|
10284
10338
|
if (primitive.indices !== void 0) {
|
|
10285
10339
|
const index = readAccessor(description, primitive.indices);
|
|
10286
10340
|
attributes.index = /* alloc */
|
|
@@ -10292,11 +10346,11 @@
|
|
|
10292
10346
|
);
|
|
10293
10347
|
}
|
|
10294
10348
|
let value;
|
|
10295
|
-
for (value of index.indices) if (value >=
|
|
10349
|
+
for (value of index.indices) if (value >= vertexCount2) throw (
|
|
10296
10350
|
/* alloc */
|
|
10297
10351
|
new Error("Invalid glTF triangle indices")
|
|
10298
10352
|
);
|
|
10299
|
-
} else if (
|
|
10353
|
+
} else if (vertexCount2 % 3) {
|
|
10300
10354
|
throw (
|
|
10301
10355
|
/* alloc */
|
|
10302
10356
|
new Error("Incomplete glTF triangle")
|
|
@@ -10383,13 +10437,13 @@
|
|
|
10383
10437
|
}
|
|
10384
10438
|
);
|
|
10385
10439
|
group.matrix = nodeMatrix(spec);
|
|
10386
|
-
let primitive, attributeData, attributes,
|
|
10440
|
+
let primitive, attributeData, attributes, vertexCount2, built, mesh, child;
|
|
10387
10441
|
if (spec.mesh !== void 0) {
|
|
10388
10442
|
for (primitive of description.meshes[spec.mesh].primitives) {
|
|
10389
10443
|
attributeData = readModelAttributes(description, primitive);
|
|
10390
10444
|
attributes = attributeData.attributes;
|
|
10391
|
-
|
|
10392
|
-
readModelIndices(description, primitive, attributes,
|
|
10445
|
+
vertexCount2 = attributeData.vertexCount;
|
|
10446
|
+
readModelIndices(description, primitive, attributes, vertexCount2);
|
|
10393
10447
|
built = createModelGeometry(context, primitive, attributes);
|
|
10394
10448
|
mesh = /* alloc */
|
|
10395
10449
|
{
|
|
@@ -14446,8 +14500,8 @@
|
|
|
14446
14500
|
function local2(output) {
|
|
14447
14501
|
const { layer, state } = this;
|
|
14448
14502
|
const map = layer._map, crs = map.options.crs;
|
|
14449
|
-
const
|
|
14450
|
-
const origin = crs.project(
|
|
14503
|
+
const location2 = locationByLayer.get(layer), root = rootByLayer.get(layer);
|
|
14504
|
+
const origin = crs.project(location2), metres = Math.cos(location2.lat * radians);
|
|
14451
14505
|
const p = crs.project(state.latlng);
|
|
14452
14506
|
const ground = mapElevationOf(map, state.latlng) || 0;
|
|
14453
14507
|
output[0] = (p.x - origin.x) * metres;
|
|
@@ -14534,49 +14588,21 @@
|
|
|
14534
14588
|
init_mapGetBearing();
|
|
14535
14589
|
init_mapSetPitch();
|
|
14536
14590
|
|
|
14537
|
-
// src/
|
|
14538
|
-
function
|
|
14539
|
-
|
|
14540
|
-
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
function shouldSkipOther(other, layer) {
|
|
14544
|
-
return other === layer || typeByLayer.get(other) === "terrain" || typeByLayer.get(other) === "traffic";
|
|
14545
|
-
}
|
|
14546
|
-
|
|
14547
|
-
// src/walk/landWalker.js
|
|
14548
|
-
function land(previousY) {
|
|
14549
|
-
const ray = raycasterByLayer.get(this.layer);
|
|
14550
|
-
const feet = local2.call(this, this.local), root = rootByLayer.get(this.layer);
|
|
14551
|
-
const x = root.position[0] + feet[0] * root.scale[0];
|
|
14552
|
-
const y = root.position[1] + feet[1] * root.scale[1];
|
|
14553
|
-
const z = root.position[2] + feet[2] * root.scale[2];
|
|
14554
|
-
if (y > previousY || this.verticalSpeed > 0) return;
|
|
14555
|
-
updateWorldMatrix(sceneByLayer.get(this.layer));
|
|
14556
|
-
ray.origin[0] = x;
|
|
14557
|
-
ray.origin[1] = previousY + 0.01;
|
|
14558
|
-
ray.origin[2] = z;
|
|
14559
|
-
ray.direction[0] = 0;
|
|
14560
|
-
ray.direction[1] = -1;
|
|
14561
|
-
ray.direction[2] = 0;
|
|
14562
|
-
ray.meshes.length = 0;
|
|
14563
|
-
let layer, hit2;
|
|
14564
|
-
for (layer of layersByLayer.get(sharedByLayer.get(this.layer))) {
|
|
14565
|
-
if (shouldSkipOther(layer, this.layer) || kindByLayer.get(layer) === "raster" || layer.options.nightLight) continue;
|
|
14566
|
-
traverse(rootByLayer.get(layer), collectVisibleMesh2, ray.meshes);
|
|
14567
|
-
}
|
|
14568
|
-
for (hit2 of intersectMeshes(ray, ray.meshes)) {
|
|
14569
|
-
if (hit2.point[1] < y - 1e-3) break;
|
|
14570
|
-
this.state.height += (hit2.point[1] - y) / root.scale[1];
|
|
14571
|
-
this.verticalSpeed = 0;
|
|
14572
|
-
break;
|
|
14591
|
+
// src/walk/stepWalkerHeight.js
|
|
14592
|
+
function stepWalkerHeight(dt) {
|
|
14593
|
+
if (this.keys.has("Space")) {
|
|
14594
|
+
this.verticalSpeed = 6;
|
|
14595
|
+
this.state.height += this.verticalSpeed * dt;
|
|
14596
|
+
return true;
|
|
14573
14597
|
}
|
|
14574
|
-
|
|
14598
|
+
if (!this.verticalSpeed && !this.state.height) return false;
|
|
14599
|
+
this.state.height = Math.max(0, this.state.height + this.verticalSpeed * dt - 9.81 * dt * dt / 2);
|
|
14600
|
+
this.verticalSpeed = this.state.height > 0 ? this.verticalSpeed - 9.81 * dt : 0;
|
|
14601
|
+
return true;
|
|
14575
14602
|
}
|
|
14576
14603
|
|
|
14577
|
-
// src/walk/
|
|
14604
|
+
// src/walk/resolveWalkerPosition.js
|
|
14578
14605
|
init_L();
|
|
14579
|
-
init_radians();
|
|
14580
14606
|
|
|
14581
14607
|
// src/globals/CELL.js
|
|
14582
14608
|
var CELL = 8;
|
|
@@ -14603,8 +14629,8 @@
|
|
|
14603
14629
|
function collider(mesh) {
|
|
14604
14630
|
let c = colliders.get(mesh.geometry);
|
|
14605
14631
|
if (c) return c;
|
|
14606
|
-
const m = mesh.worldMatrix, { position
|
|
14607
|
-
const vertices =
|
|
14632
|
+
const m = mesh.worldMatrix, { position, index, normal, uv, instanceOffset } = mesh.geometry.attributes;
|
|
14633
|
+
const vertices = vertexCount(position, index);
|
|
14608
14634
|
const count = vertices * (instanceOffset?.count ?? 1);
|
|
14609
14635
|
const tri = (
|
|
14610
14636
|
/* alloc */
|
|
@@ -14667,34 +14693,269 @@
|
|
|
14667
14693
|
nrm.push(nx / h, nz / h);
|
|
14668
14694
|
indexTriangle(cells, v, t);
|
|
14669
14695
|
}
|
|
14670
|
-
c = /* alloc */
|
|
14671
|
-
{
|
|
14672
|
-
tri: Float32Array.from(tri),
|
|
14673
|
-
nrm: Float32Array.from(nrm),
|
|
14674
|
-
cells,
|
|
14675
|
-
maxX,
|
|
14676
|
-
origin: (
|
|
14677
|
-
/* alloc */
|
|
14678
|
-
[m[12], m[13], m[14]]
|
|
14679
|
-
)
|
|
14680
|
-
};
|
|
14681
|
-
colliders.set(mesh.geometry, c);
|
|
14682
|
-
return c;
|
|
14696
|
+
c = /* alloc */
|
|
14697
|
+
{
|
|
14698
|
+
tri: Float32Array.from(tri),
|
|
14699
|
+
nrm: Float32Array.from(nrm),
|
|
14700
|
+
cells,
|
|
14701
|
+
maxX,
|
|
14702
|
+
origin: (
|
|
14703
|
+
/* alloc */
|
|
14704
|
+
[m[12], m[13], m[14]]
|
|
14705
|
+
)
|
|
14706
|
+
};
|
|
14707
|
+
colliders.set(mesh.geometry, c);
|
|
14708
|
+
return c;
|
|
14709
|
+
}
|
|
14710
|
+
|
|
14711
|
+
// src/collision/horizontalRay.js
|
|
14712
|
+
function horizontalRay(v, t, ox, oy, oz, dx, dz) {
|
|
14713
|
+
const i = t * 9, ex = v[i + 3] - v[i], ey = v[i + 4] - v[i + 1], ez = v[i + 5] - v[i + 2];
|
|
14714
|
+
const fx = v[i + 6] - v[i], fy = v[i + 7] - v[i + 1], fz = v[i + 8] - v[i + 2];
|
|
14715
|
+
const px = -dz * fy, py = dz * fx - dx * fz, pz = dx * fy, det = ex * px + ey * py + ez * pz;
|
|
14716
|
+
if (Math.abs(det) < 1e-9) return -1;
|
|
14717
|
+
const tx = ox - v[i], ty = oy - v[i + 1], tz = oz - v[i + 2], u = (tx * px + ty * py + tz * pz) / det;
|
|
14718
|
+
if (u < 0 || u > 1) return -1;
|
|
14719
|
+
const qx = ty * ez - tz * ey, qy = tz * ex - tx * ez, qz = tx * ey - ty * ex, w = (dx * qx + dz * qz) / det;
|
|
14720
|
+
if (w < 0 || u + w > 1) return -1;
|
|
14721
|
+
return (fx * qx + fy * qy + fz * qz) / det;
|
|
14722
|
+
}
|
|
14723
|
+
|
|
14724
|
+
// src/collision/collectIntersections.js
|
|
14725
|
+
function collectIntersections(shape, x, y, z, seen, hits, end, iz) {
|
|
14726
|
+
let ix, cell, triangle3, distance;
|
|
14727
|
+
for (ix = Math.floor(x / CELL); ix <= end; ix++) {
|
|
14728
|
+
cell = shape.cells.get(`${ix},${iz}`);
|
|
14729
|
+
if (!cell) continue;
|
|
14730
|
+
for (triangle3 of cell) {
|
|
14731
|
+
if (seen.has(triangle3)) continue;
|
|
14732
|
+
seen.add(triangle3);
|
|
14733
|
+
distance = horizontalRay(shape.tri, triangle3, x, y, z, 1, 0);
|
|
14734
|
+
if (distance > 1e-4) hits.push(distance);
|
|
14735
|
+
}
|
|
14736
|
+
}
|
|
14737
|
+
}
|
|
14738
|
+
|
|
14739
|
+
// src/collision/countCrossings.js
|
|
14740
|
+
function countCrossings(hits) {
|
|
14741
|
+
let ix, j, distance;
|
|
14742
|
+
for (ix = 1; ix < hits.length; ix++) {
|
|
14743
|
+
distance = hits[ix];
|
|
14744
|
+
j = ix - 1;
|
|
14745
|
+
while (j >= 0 && hits[j] > distance) hits[j + 1] = hits[j--];
|
|
14746
|
+
hits[j + 1] = distance;
|
|
14747
|
+
}
|
|
14748
|
+
let crossings = 0, previous = -Infinity;
|
|
14749
|
+
for (distance of hits) {
|
|
14750
|
+
if (distance - previous > 1e-4) crossings++;
|
|
14751
|
+
previous = distance;
|
|
14752
|
+
}
|
|
14753
|
+
return crossings;
|
|
14754
|
+
}
|
|
14755
|
+
|
|
14756
|
+
// src/collision/insideMesh.js
|
|
14757
|
+
function insideMesh(mesh, x, y, z, seen, intersections) {
|
|
14758
|
+
const geometry = mesh.geometry;
|
|
14759
|
+
if (!mesh.visible || !geometry?.attributes?.position?.data || mesh.program?.depthTest === false) return false;
|
|
14760
|
+
if (!geometry.bounds) computeBounds(geometry);
|
|
14761
|
+
const bounds = geometry.bounds;
|
|
14762
|
+
const world = mesh.worldMatrix;
|
|
14763
|
+
const center = bounds.center;
|
|
14764
|
+
const cx = world[0] * center[0] + world[4] * center[1] + world[8] * center[2] + world[12];
|
|
14765
|
+
const cy = world[1] * center[0] + world[5] * center[1] + world[9] * center[2] + world[13];
|
|
14766
|
+
const cz = world[2] * center[0] + world[6] * center[1] + world[10] * center[2] + world[14];
|
|
14767
|
+
const radius = bounds.radius * Math.max(
|
|
14768
|
+
Math.hypot(world[0], world[1], world[2]),
|
|
14769
|
+
Math.hypot(world[4], world[5], world[6]),
|
|
14770
|
+
Math.hypot(world[8], world[9], world[10])
|
|
14771
|
+
);
|
|
14772
|
+
if (Math.hypot(cx - x, cy - y, cz - z) > radius) return false;
|
|
14773
|
+
const shape = collider(mesh);
|
|
14774
|
+
const end = Math.floor(shape.maxX / CELL);
|
|
14775
|
+
if (x >= shape.maxX) return false;
|
|
14776
|
+
const iz = Math.floor(z / CELL);
|
|
14777
|
+
const hits = intersections;
|
|
14778
|
+
hits.length = 0;
|
|
14779
|
+
seen.clear();
|
|
14780
|
+
collectIntersections(shape, x, y, z, seen, hits, end, iz);
|
|
14781
|
+
return countCrossings(hits) % 2 === 1;
|
|
14782
|
+
}
|
|
14783
|
+
|
|
14784
|
+
// src/collision/setTrafficNormal.js
|
|
14785
|
+
function setTrafficNormal(data, x, z, distance, dx, dz) {
|
|
14786
|
+
if (distance < 1e-6) {
|
|
14787
|
+
data.normal[0] = -dx;
|
|
14788
|
+
data.normal[1] = -dz;
|
|
14789
|
+
} else {
|
|
14790
|
+
data.normal[0] = x / distance;
|
|
14791
|
+
data.normal[1] = z / distance;
|
|
14792
|
+
}
|
|
14793
|
+
}
|
|
14794
|
+
|
|
14795
|
+
// src/collision/trafficCollision.js
|
|
14796
|
+
function trafficCollision(layer, x, y, z, dx, dz, reach, data) {
|
|
14797
|
+
const state = trafficByLayer.get(layer);
|
|
14798
|
+
if (!state?.mesh || !state.trips.length) return false;
|
|
14799
|
+
let bounds = state.collisionBounds;
|
|
14800
|
+
if (!bounds) {
|
|
14801
|
+
bounds = state.collisionBounds = /* alloc */
|
|
14802
|
+
{ radius: 0, minY: Infinity, maxY: -Infinity };
|
|
14803
|
+
let i, px2, py, pz2;
|
|
14804
|
+
for (i = 0; i < state.template.position.length; i += 3) {
|
|
14805
|
+
px2 = state.template.position[i];
|
|
14806
|
+
py = state.template.position[i + 1];
|
|
14807
|
+
pz2 = state.template.position[i + 2];
|
|
14808
|
+
bounds.radius = Math.max(bounds.radius, Math.hypot(px2, pz2));
|
|
14809
|
+
bounds.minY = Math.min(bounds.minY, py);
|
|
14810
|
+
bounds.maxY = Math.max(bounds.maxY, py);
|
|
14811
|
+
}
|
|
14812
|
+
}
|
|
14813
|
+
const root = rootByLayer.get(layer), position = state.position ||= /* alloc */
|
|
14814
|
+
{};
|
|
14815
|
+
const scale = Math.max(root.scale[0], root.scale[1], root.scale[2]);
|
|
14816
|
+
const radius = bounds.radius * scale + 0.35;
|
|
14817
|
+
let trip, projection, closest, rx, rz, perpendicular, entry, distance, bottom, top, px, pz;
|
|
14818
|
+
for (trip of state.trips) {
|
|
14819
|
+
({ x: px, y: bottom, z: pz } = locateTraffic(state, trip, position));
|
|
14820
|
+
bottom = root.position[1] + (bottom + bounds.minY) * root.scale[1];
|
|
14821
|
+
top = root.position[1] + (position.y + bounds.maxY) * root.scale[1];
|
|
14822
|
+
if (bottom > y + 1.7 * scale || top < y + 0.2 * scale) continue;
|
|
14823
|
+
px = root.position[0] + px * root.scale[0];
|
|
14824
|
+
pz = root.position[2] + pz * root.scale[2];
|
|
14825
|
+
projection = (px - x) * dx + (pz - z) * dz;
|
|
14826
|
+
closest = Math.max(0, Math.min(reach, projection));
|
|
14827
|
+
rx = x + closest * dx - px;
|
|
14828
|
+
rz = z + closest * dz - pz;
|
|
14829
|
+
perpendicular = rx * rx + rz * rz;
|
|
14830
|
+
if (perpendicular >= radius * radius) continue;
|
|
14831
|
+
if (reach === 0) {
|
|
14832
|
+
data.found = true;
|
|
14833
|
+
distance = Math.hypot(x - px, z - pz);
|
|
14834
|
+
data.normal[0] = distance ? (x - px) / distance : 0;
|
|
14835
|
+
data.normal[1] = distance ? (z - pz) / distance : 0;
|
|
14836
|
+
continue;
|
|
14837
|
+
}
|
|
14838
|
+
entry = Math.max(0, projection - Math.sqrt(radius * radius - perpendicular));
|
|
14839
|
+
if (entry > reach || entry >= data.best) continue;
|
|
14840
|
+
data.best = entry;
|
|
14841
|
+
data.found = true;
|
|
14842
|
+
distance = Math.hypot(x + entry * dx - px, z + entry * dz - pz);
|
|
14843
|
+
setTrafficNormal(data, x + entry * dx - px, z + entry * dz - pz, distance, dx, dz);
|
|
14844
|
+
}
|
|
14845
|
+
return data.found;
|
|
14846
|
+
}
|
|
14847
|
+
|
|
14848
|
+
// src/collision/insideWalker.js
|
|
14849
|
+
function insideWalker(context) {
|
|
14850
|
+
const { layer, local: localBuffer, hitData } = context;
|
|
14851
|
+
const shared = sharedByLayer.get(layer);
|
|
14852
|
+
if (!shared || !layersByLayer.get(shared)) return false;
|
|
14853
|
+
updateWorldMatrix(sceneByLayer.get(layer));
|
|
14854
|
+
const root = rootByLayer.get(layer);
|
|
14855
|
+
const feet = local2.call(context, localBuffer);
|
|
14856
|
+
const x = root.position[0] + feet[0] * root.scale[0];
|
|
14857
|
+
const y = root.position[1] + feet[1] * root.scale[1];
|
|
14858
|
+
const z = root.position[2] + feet[2] * root.scale[2];
|
|
14859
|
+
const layers = layersByLayer.get(shared);
|
|
14860
|
+
let other, node, child, nodes;
|
|
14861
|
+
for (other of layers) {
|
|
14862
|
+
if (other === layer || kindByLayer.get(other) === "terrain") continue;
|
|
14863
|
+
if (kindByLayer.get(other) === "traffic") {
|
|
14864
|
+
hitData.best = 0;
|
|
14865
|
+
hitData.found = false;
|
|
14866
|
+
if (trafficCollision(other, x, y, z, 0, 0, 0, hitData)) return true;
|
|
14867
|
+
continue;
|
|
14868
|
+
}
|
|
14869
|
+
nodes = hitData.nodes;
|
|
14870
|
+
nodes.length = 0;
|
|
14871
|
+
if (rootByLayer.get(other)) nodes.push(rootByLayer.get(other));
|
|
14872
|
+
while (nodes.length) {
|
|
14873
|
+
node = nodes.pop();
|
|
14874
|
+
if (!node.visible) continue;
|
|
14875
|
+
if (node.geometry && (insideMesh(node, x, y + 0.45 * root.scale[1], z, hitData.seen, hitData.intersections) || insideMesh(node, x, y + 1.35 * root.scale[1], z, hitData.seen, hitData.intersections))) return true;
|
|
14876
|
+
for (child of node.children) nodes.push(child);
|
|
14877
|
+
}
|
|
14878
|
+
}
|
|
14879
|
+
return false;
|
|
14880
|
+
}
|
|
14881
|
+
|
|
14882
|
+
// src/walk/resolveWalkerPosition.js
|
|
14883
|
+
function resolveWalkerPosition() {
|
|
14884
|
+
if (!this.saved || !insideWalker(this)) return false;
|
|
14885
|
+
const map = this.layer._map;
|
|
14886
|
+
const origin = this.state.latlng;
|
|
14887
|
+
const height = this.state.height;
|
|
14888
|
+
let distance, angle, candidate;
|
|
14889
|
+
for (distance = 0.5; distance <= 20; distance += 0.5) {
|
|
14890
|
+
for (angle = 0; angle < Math.PI * 2; angle += Math.PI / 4) {
|
|
14891
|
+
candidate = /* alloc */
|
|
14892
|
+
new L.LatLng(
|
|
14893
|
+
origin.lat + Math.cos(angle) * distance / 111320,
|
|
14894
|
+
origin.lng + Math.sin(angle) * distance / (111320 * Math.cos(origin.lat * Math.PI / 180))
|
|
14895
|
+
);
|
|
14896
|
+
this.state.latlng = candidate;
|
|
14897
|
+
this.state.height = 0;
|
|
14898
|
+
if (!insideWalker(this)) {
|
|
14899
|
+
this.verticalSpeed = 0;
|
|
14900
|
+
map.setView(
|
|
14901
|
+
candidate,
|
|
14902
|
+
map.getZoom(),
|
|
14903
|
+
/* alloc */
|
|
14904
|
+
{ animate: false }
|
|
14905
|
+
);
|
|
14906
|
+
return true;
|
|
14907
|
+
}
|
|
14908
|
+
}
|
|
14909
|
+
}
|
|
14910
|
+
this.state.latlng = origin;
|
|
14911
|
+
this.state.height = height;
|
|
14912
|
+
return false;
|
|
14683
14913
|
}
|
|
14684
14914
|
|
|
14685
|
-
// src/
|
|
14686
|
-
function
|
|
14687
|
-
|
|
14688
|
-
|
|
14689
|
-
|
|
14690
|
-
|
|
14691
|
-
|
|
14692
|
-
|
|
14693
|
-
|
|
14694
|
-
|
|
14695
|
-
|
|
14915
|
+
// src/utils/wrap.js
|
|
14916
|
+
function wrap(angle) {
|
|
14917
|
+
return Math.atan2(Math.sin(angle), Math.cos(angle));
|
|
14918
|
+
}
|
|
14919
|
+
|
|
14920
|
+
// src/picking/shouldSkipOther.js
|
|
14921
|
+
function shouldSkipOther(other, layer) {
|
|
14922
|
+
return other === layer || typeByLayer.get(other) === "terrain" || typeByLayer.get(other) === "traffic";
|
|
14923
|
+
}
|
|
14924
|
+
|
|
14925
|
+
// src/walk/landWalker.js
|
|
14926
|
+
function land(previousY) {
|
|
14927
|
+
const ray = raycasterByLayer.get(this.layer);
|
|
14928
|
+
const feet = local2.call(this, this.local), root = rootByLayer.get(this.layer);
|
|
14929
|
+
const x = root.position[0] + feet[0] * root.scale[0];
|
|
14930
|
+
const y = root.position[1] + feet[1] * root.scale[1];
|
|
14931
|
+
const z = root.position[2] + feet[2] * root.scale[2];
|
|
14932
|
+
if (y > previousY || this.verticalSpeed > 0) return;
|
|
14933
|
+
updateWorldMatrix(sceneByLayer.get(this.layer));
|
|
14934
|
+
ray.origin[0] = x;
|
|
14935
|
+
ray.origin[1] = previousY + 0.01;
|
|
14936
|
+
ray.origin[2] = z;
|
|
14937
|
+
ray.direction[0] = 0;
|
|
14938
|
+
ray.direction[1] = -1;
|
|
14939
|
+
ray.direction[2] = 0;
|
|
14940
|
+
ray.meshes.length = 0;
|
|
14941
|
+
let layer, hit2;
|
|
14942
|
+
for (layer of layersByLayer.get(sharedByLayer.get(this.layer))) {
|
|
14943
|
+
if (shouldSkipOther(layer, this.layer) || kindByLayer.get(layer) === "raster" || layer.options.nightLight) continue;
|
|
14944
|
+
traverse(rootByLayer.get(layer), collectVisibleMesh2, ray.meshes);
|
|
14945
|
+
}
|
|
14946
|
+
for (hit2 of intersectMeshes(ray, ray.meshes)) {
|
|
14947
|
+
if (hit2.point[1] < y - 1e-3) break;
|
|
14948
|
+
this.state.height += (hit2.point[1] - y) / root.scale[1];
|
|
14949
|
+
this.verticalSpeed = 0;
|
|
14950
|
+
break;
|
|
14951
|
+
}
|
|
14952
|
+
ray.meshes.length = 0;
|
|
14696
14953
|
}
|
|
14697
14954
|
|
|
14955
|
+
// src/walk/moveWalker.js
|
|
14956
|
+
init_L();
|
|
14957
|
+
init_radians();
|
|
14958
|
+
|
|
14698
14959
|
// src/picking/hitColliderCell.js
|
|
14699
14960
|
function hitColliderCell(cell, c, data, ox, oy, oz) {
|
|
14700
14961
|
const { dx, dz, seen } = data;
|
|
@@ -14734,63 +14995,6 @@
|
|
|
14734
14995
|
}
|
|
14735
14996
|
}
|
|
14736
14997
|
|
|
14737
|
-
// src/collision/trafficCollision.js
|
|
14738
|
-
function trafficCollision(layer, x, y, z, dx, dz, reach, data) {
|
|
14739
|
-
const state = trafficByLayer.get(layer);
|
|
14740
|
-
if (!state?.mesh || !state.trips.length) return false;
|
|
14741
|
-
let bounds = state.collisionBounds;
|
|
14742
|
-
if (!bounds) {
|
|
14743
|
-
bounds = state.collisionBounds = { radius: 0, minY: Infinity, maxY: -Infinity };
|
|
14744
|
-
let i, px2, py, pz2;
|
|
14745
|
-
for (i = 0; i < state.template.position.length; i += 3) {
|
|
14746
|
-
px2 = state.template.position[i];
|
|
14747
|
-
py = state.template.position[i + 1];
|
|
14748
|
-
pz2 = state.template.position[i + 2];
|
|
14749
|
-
bounds.radius = Math.max(bounds.radius, Math.hypot(px2, pz2));
|
|
14750
|
-
bounds.minY = Math.min(bounds.minY, py);
|
|
14751
|
-
bounds.maxY = Math.max(bounds.maxY, py);
|
|
14752
|
-
}
|
|
14753
|
-
}
|
|
14754
|
-
const root = rootByLayer.get(layer), position = state.position ||= {};
|
|
14755
|
-
const scale = Math.max(root.scale[0], root.scale[1], root.scale[2]);
|
|
14756
|
-
const radius = bounds.radius * scale + 0.35;
|
|
14757
|
-
let trip, projection, closest, rx, rz, perpendicular, entry, distance, bottom, top, px, pz;
|
|
14758
|
-
for (trip of state.trips) {
|
|
14759
|
-
({ x: px, y: bottom, z: pz } = locateTraffic(state, trip, position));
|
|
14760
|
-
bottom = root.position[1] + (bottom + bounds.minY) * root.scale[1];
|
|
14761
|
-
top = root.position[1] + (position.y + bounds.maxY) * root.scale[1];
|
|
14762
|
-
if (bottom > y + 1.7 * scale || top < y + 0.2 * scale) continue;
|
|
14763
|
-
px = root.position[0] + px * root.scale[0];
|
|
14764
|
-
pz = root.position[2] + pz * root.scale[2];
|
|
14765
|
-
projection = (px - x) * dx + (pz - z) * dz;
|
|
14766
|
-
closest = Math.max(0, Math.min(reach, projection));
|
|
14767
|
-
rx = x + closest * dx - px;
|
|
14768
|
-
rz = z + closest * dz - pz;
|
|
14769
|
-
perpendicular = rx * rx + rz * rz;
|
|
14770
|
-
if (perpendicular >= radius * radius) continue;
|
|
14771
|
-
if (reach === 0) {
|
|
14772
|
-
data.found = true;
|
|
14773
|
-
distance = Math.hypot(x - px, z - pz);
|
|
14774
|
-
data.normal[0] = distance ? (x - px) / distance : 0;
|
|
14775
|
-
data.normal[1] = distance ? (z - pz) / distance : 0;
|
|
14776
|
-
continue;
|
|
14777
|
-
}
|
|
14778
|
-
entry = Math.max(0, projection - Math.sqrt(radius * radius - perpendicular));
|
|
14779
|
-
if (entry > reach || entry >= data.best) continue;
|
|
14780
|
-
data.best = entry;
|
|
14781
|
-
data.found = true;
|
|
14782
|
-
distance = Math.hypot(x + entry * dx - px, z + entry * dz - pz);
|
|
14783
|
-
if (distance < 1e-6) {
|
|
14784
|
-
data.normal[0] = -dx;
|
|
14785
|
-
data.normal[1] = -dz;
|
|
14786
|
-
} else {
|
|
14787
|
-
data.normal[0] = (x + entry * dx - px) / distance;
|
|
14788
|
-
data.normal[1] = (z + entry * dz - pz) / distance;
|
|
14789
|
-
}
|
|
14790
|
-
}
|
|
14791
|
-
return data.found;
|
|
14792
|
-
}
|
|
14793
|
-
|
|
14794
14998
|
// src/picking/hit.js
|
|
14795
14999
|
function hit(layer, x, y, z, dx, dz, reach, data) {
|
|
14796
15000
|
updateWorldMatrix(sceneByLayer.get(layer));
|
|
@@ -14834,19 +15038,6 @@
|
|
|
14834
15038
|
this.state.phase += Math.hypot(east, north) / 1.6 * Math.PI;
|
|
14835
15039
|
}
|
|
14836
15040
|
|
|
14837
|
-
// src/walk/stepWalkerHeight.js
|
|
14838
|
-
function stepWalkerHeight(dt) {
|
|
14839
|
-
if (this.keys.has("Space")) {
|
|
14840
|
-
this.verticalSpeed = 6;
|
|
14841
|
-
this.state.height += this.verticalSpeed * dt;
|
|
14842
|
-
return true;
|
|
14843
|
-
}
|
|
14844
|
-
if (!this.verticalSpeed && !this.state.height) return false;
|
|
14845
|
-
this.state.height = Math.max(0, this.state.height + this.verticalSpeed * dt - 9.81 * dt * dt / 2);
|
|
14846
|
-
this.verticalSpeed = this.state.height > 0 ? this.verticalSpeed - 9.81 * dt : 0;
|
|
14847
|
-
return true;
|
|
14848
|
-
}
|
|
14849
|
-
|
|
14850
15041
|
// src/walk/updateWalkerView.js
|
|
14851
15042
|
init_degrees();
|
|
14852
15043
|
init_radians();
|
|
@@ -14873,123 +15064,19 @@
|
|
|
14873
15064
|
return false;
|
|
14874
15065
|
}
|
|
14875
15066
|
|
|
14876
|
-
// src/walk/
|
|
14877
|
-
|
|
14878
|
-
|
|
14879
|
-
|
|
14880
|
-
|
|
14881
|
-
const geometry = mesh.geometry;
|
|
14882
|
-
if (!mesh.visible || !geometry?.attributes?.position?.data || mesh.program?.depthTest === false) return false;
|
|
14883
|
-
if (!geometry.bounds) computeBounds(geometry);
|
|
14884
|
-
const bounds = geometry.bounds;
|
|
14885
|
-
const world = mesh.worldMatrix;
|
|
14886
|
-
const center = bounds.center;
|
|
14887
|
-
const cx = world[0] * center[0] + world[4] * center[1] + world[8] * center[2] + world[12];
|
|
14888
|
-
const cy = world[1] * center[0] + world[5] * center[1] + world[9] * center[2] + world[13];
|
|
14889
|
-
const cz = world[2] * center[0] + world[6] * center[1] + world[10] * center[2] + world[14];
|
|
14890
|
-
const radius = bounds.radius * Math.max(
|
|
14891
|
-
Math.hypot(world[0], world[1], world[2]),
|
|
14892
|
-
Math.hypot(world[4], world[5], world[6]),
|
|
14893
|
-
Math.hypot(world[8], world[9], world[10])
|
|
14894
|
-
);
|
|
14895
|
-
if (Math.hypot(cx - x, cy - y, cz - z) > radius) return false;
|
|
14896
|
-
const shape = collider(mesh);
|
|
14897
|
-
const end = Math.floor(shape.maxX / CELL);
|
|
14898
|
-
if (x >= shape.maxX) return false;
|
|
14899
|
-
const iz = Math.floor(z / CELL);
|
|
14900
|
-
const hits = intersections;
|
|
14901
|
-
hits.length = 0;
|
|
14902
|
-
seen.clear();
|
|
14903
|
-
let ix, cell, triangle3, distance;
|
|
14904
|
-
for (ix = Math.floor(x / CELL); ix <= end; ix++) {
|
|
14905
|
-
cell = shape.cells.get(`${ix},${iz}`);
|
|
14906
|
-
if (!cell) continue;
|
|
14907
|
-
for (triangle3 of cell) {
|
|
14908
|
-
if (seen.has(triangle3)) continue;
|
|
14909
|
-
seen.add(triangle3);
|
|
14910
|
-
distance = horizontalRay(shape.tri, triangle3, x, y, z, 1, 0);
|
|
14911
|
-
if (distance > 1e-4) hits.push(distance);
|
|
14912
|
-
}
|
|
14913
|
-
}
|
|
14914
|
-
for (ix = 1; ix < hits.length; ix++) {
|
|
14915
|
-
distance = hits[ix];
|
|
14916
|
-
let j = ix - 1;
|
|
14917
|
-
while (j >= 0 && hits[j] > distance) hits[j + 1] = hits[j--];
|
|
14918
|
-
hits[j + 1] = distance;
|
|
14919
|
-
}
|
|
14920
|
-
let crossings = 0, previous = -Infinity;
|
|
14921
|
-
for (distance of hits) {
|
|
14922
|
-
if (distance - previous > 1e-4) crossings++;
|
|
14923
|
-
previous = distance;
|
|
14924
|
-
}
|
|
14925
|
-
return crossings % 2 === 1;
|
|
14926
|
-
}
|
|
14927
|
-
|
|
14928
|
-
// src/collision/insideWalker.js
|
|
14929
|
-
function insideWalker(context) {
|
|
14930
|
-
const { layer, local: localBuffer, hitData } = context;
|
|
14931
|
-
const shared = sharedByLayer.get(layer);
|
|
14932
|
-
if (!shared || !layersByLayer.get(shared)) return false;
|
|
14933
|
-
updateWorldMatrix(sceneByLayer.get(layer));
|
|
14934
|
-
const root = rootByLayer.get(layer);
|
|
14935
|
-
const feet = local2.call(context, localBuffer);
|
|
14936
|
-
const x = root.position[0] + feet[0] * root.scale[0];
|
|
14937
|
-
const y = root.position[1] + feet[1] * root.scale[1];
|
|
14938
|
-
const z = root.position[2] + feet[2] * root.scale[2];
|
|
14939
|
-
const layers = layersByLayer.get(shared);
|
|
14940
|
-
let other, node, child;
|
|
14941
|
-
for (other of layers) {
|
|
14942
|
-
if (other === layer || kindByLayer.get(other) === "terrain") continue;
|
|
14943
|
-
if (kindByLayer.get(other) === "traffic") {
|
|
14944
|
-
hitData.best = 0;
|
|
14945
|
-
hitData.found = false;
|
|
14946
|
-
if (trafficCollision(other, x, y, z, 0, 0, 0, hitData)) return true;
|
|
14947
|
-
continue;
|
|
14948
|
-
}
|
|
14949
|
-
const nodes = hitData.nodes;
|
|
14950
|
-
nodes.length = 0;
|
|
14951
|
-
if (rootByLayer.get(other)) nodes.push(rootByLayer.get(other));
|
|
14952
|
-
while (nodes.length) {
|
|
14953
|
-
node = nodes.pop();
|
|
14954
|
-
if (!node.visible) continue;
|
|
14955
|
-
if (node.geometry && (insideMesh(node, x, y + 0.45 * root.scale[1], z, hitData.seen, hitData.intersections) || insideMesh(node, x, y + 1.35 * root.scale[1], z, hitData.seen, hitData.intersections))) return true;
|
|
14956
|
-
for (child of node.children) nodes.push(child);
|
|
14957
|
-
}
|
|
15067
|
+
// src/walk/updateWalkerFrame.js
|
|
15068
|
+
function updateWalkerFrame(walker, previousY, forward, turn, dt, changed) {
|
|
15069
|
+
if (turn) {
|
|
15070
|
+
walker.state.heading = wrap(walker.state.heading + turn * 2.5 * dt);
|
|
15071
|
+
changed = true;
|
|
14958
15072
|
}
|
|
14959
|
-
|
|
14960
|
-
|
|
14961
|
-
|
|
14962
|
-
// src/walk/resolveWalkerPosition.js
|
|
14963
|
-
function resolveWalkerPosition() {
|
|
14964
|
-
if (!this.saved || !insideWalker(this)) return false;
|
|
14965
|
-
const map = this.layer._map;
|
|
14966
|
-
const origin = this.state.latlng;
|
|
14967
|
-
const height = this.state.height;
|
|
14968
|
-
let distance, angle, candidate;
|
|
14969
|
-
for (distance = 0.5; distance <= 20; distance += 0.5) {
|
|
14970
|
-
for (angle = 0; angle < Math.PI * 2; angle += Math.PI / 4) {
|
|
14971
|
-
candidate = /* alloc */
|
|
14972
|
-
new L.LatLng(
|
|
14973
|
-
origin.lat + Math.cos(angle) * distance / 111320,
|
|
14974
|
-
origin.lng + Math.sin(angle) * distance / (111320 * Math.cos(origin.lat * Math.PI / 180))
|
|
14975
|
-
);
|
|
14976
|
-
this.state.latlng = candidate;
|
|
14977
|
-
this.state.height = 0;
|
|
14978
|
-
if (!insideWalker(this)) {
|
|
14979
|
-
this.verticalSpeed = 0;
|
|
14980
|
-
map.setView(
|
|
14981
|
-
candidate,
|
|
14982
|
-
map.getZoom(),
|
|
14983
|
-
/* alloc */
|
|
14984
|
-
{ animate: false }
|
|
14985
|
-
);
|
|
14986
|
-
return true;
|
|
14987
|
-
}
|
|
14988
|
-
}
|
|
15073
|
+
if (forward) {
|
|
15074
|
+
moveWalker.call(walker, forward, dt);
|
|
15075
|
+
changed = true;
|
|
14989
15076
|
}
|
|
14990
|
-
|
|
14991
|
-
|
|
14992
|
-
|
|
15077
|
+
if (changed) land.call(walker, previousY);
|
|
15078
|
+
if (updateWalkerView.call(walker, forward, turn, dt)) changed = true;
|
|
15079
|
+
if (changed) place.call(walker);
|
|
14993
15080
|
}
|
|
14994
15081
|
|
|
14995
15082
|
// src/walk/animateWalker.js
|
|
@@ -15020,17 +15107,7 @@
|
|
|
15020
15107
|
}
|
|
15021
15108
|
forward = Math.sign(forward);
|
|
15022
15109
|
turn = Math.sign(turn);
|
|
15023
|
-
|
|
15024
|
-
this.state.heading = wrap(this.state.heading + turn * 2.5 * dt);
|
|
15025
|
-
changed = true;
|
|
15026
|
-
}
|
|
15027
|
-
if (forward) {
|
|
15028
|
-
moveWalker.call(this, forward, dt);
|
|
15029
|
-
changed = true;
|
|
15030
|
-
}
|
|
15031
|
-
if (changed) land.call(this, previousY);
|
|
15032
|
-
if (updateWalkerView.call(this, forward, turn, dt)) changed = true;
|
|
15033
|
-
if (changed) place.call(this);
|
|
15110
|
+
updateWalkerFrame(this, previousY, forward, turn, dt, changed);
|
|
15034
15111
|
}
|
|
15035
15112
|
|
|
15036
15113
|
// src/walk/startWalking.js
|