leaflet-city-mapper 0.0.6 → 0.0.7
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 +10 -5
- package/dist/leaflet-city-mapper-src.js +7059 -6566
- package/dist/leaflet-city-mapper-src.js.map +4 -4
- package/dist/leaflet-city-mapper-worker-src.js +2766 -0
- package/dist/leaflet-city-mapper-worker-src.js.map +4 -4
- package/dist/leaflet-city-mapper-worker.js +1 -1
- package/dist/leaflet-city-mapper-worker.js.map +4 -4
- package/dist/leaflet-city-mapper.js +5 -3
- package/dist/leaflet-city-mapper.js.map +4 -4
- package/libs/leaflet.js +1 -1
- package/package.json +1 -1
- package/src/camera/setBearing.js +5 -0
- package/src/camera/setPitch.js +5 -0
- package/src/cog/initCog.js +2 -2
- package/src/core/gridlayerGetTiledPixelBounds.js +37 -4
- package/src/core/markerSetPos.js +1 -1
- package/src/core/popupGetEvents.js +1 -1
- package/src/core/popupUpdatePosition.js +8 -8
- package/src/core/tooltipGetEvents.js +1 -1
- package/src/core/tooltipSetPosition.js +2 -2
- package/src/geometry/appendNativeTriangle.js +2 -2
- package/src/geometry/createModelGeometry.js +2 -9
- package/src/geometry/dashedSegment.js +10 -5
- package/src/geometry/disk.js +1 -1
- package/src/geometry/fillNativePolygon.js +20 -0
- package/src/geometry/lineJoin.js +2 -2
- package/src/geometry/markerQuadCorners.js +6 -0
- package/src/geometry/nativeGeometry.js +1 -1
- package/src/geometry/polygon.js +4 -10
- package/src/geometry/segment.js +4 -3
- package/src/globals/colorTexture.js +6 -0
- package/src/globals/depthTexture.js +1 -0
- package/src/globals/drawMeshEntry.js +1 -1
- package/src/globals/meshPipeline.js +1 -0
- package/src/globals/mvtTextDecoder.js +1 -0
- package/src/globals/nativeScalableStyleKeys.js +1 -0
- package/src/globals/scenePass.js +1 -0
- package/src/globals/vectorStyleNamedColors.js +8 -0
- package/src/globals/vectorTileEvents.js +1 -0
- package/src/globals/workerCogSource.js +1 -0
- package/src/gpu/mountRenderer.js +4 -11
- package/src/gpu/releaseRenderer.js +1 -0
- package/src/index.js +6 -12
- package/src/materials/createProgramUniforms.js +1 -0
- package/src/models/loadModel.js +6 -10
- package/src/models/loadModelResources.js +2 -8
- package/src/models/modelNode.js +3 -7
- package/src/models/prepareModel.js +19 -0
- package/src/models/prepareModelGeometry.js +25 -0
- package/src/models/prepareModelPrimitive.js +17 -0
- package/src/mvt/addMvtCrossings.js +17 -0
- package/src/mvt/appendMvtBandTriangles.js +31 -0
- package/src/mvt/appendMvtCoordinates.js +11 -0
- package/src/mvt/appendMvtPolygonTriangles.js +19 -0
- package/src/mvt/beginMvtPath.js +9 -0
- package/src/mvt/closeMvtPath.js +7 -0
- package/src/mvt/collectMvtEdges.js +19 -0
- package/src/mvt/createMvtReader.js +7 -0
- package/src/mvt/decodeVectorTile.js +32 -0
- package/src/mvt/expectMvtWire.js +3 -0
- package/src/mvt/finishMvtPath.js +5 -0
- package/src/mvt/finiteMvtCoordinate.js +7 -0
- package/src/mvt/groupMvtPolygons.js +25 -0
- package/src/mvt/isMvtFallbackError.js +6 -0
- package/src/mvt/mergeMvtActiveEdges.js +9 -0
- package/src/mvt/mvtEdgeX.js +4 -0
- package/src/mvt/mvtPathsVertices.js +8 -0
- package/src/mvt/mvtPolygonPaths.js +12 -0
- package/src/mvt/numericMvtValue.js +4 -0
- package/src/mvt/readMvtFeature.js +34 -0
- package/src/mvt/readMvtField.js +8 -0
- package/src/mvt/readMvtGeometry.js +29 -0
- package/src/mvt/readMvtInteger.js +12 -0
- package/src/mvt/readMvtKnownValue.js +21 -0
- package/src/mvt/readMvtLayer.js +31 -0
- package/src/mvt/readMvtMessage.js +10 -0
- package/src/mvt/readMvtNumber.js +9 -0
- package/src/mvt/readMvtNumbers.js +11 -0
- package/src/mvt/readMvtString.js +6 -0
- package/src/mvt/readMvtValue.js +19 -0
- package/src/mvt/skipMvtField.js +14 -0
- package/src/mvt/sortMvtActiveEdges.js +15 -0
- package/src/mvt/sortedMvtLevels.js +22 -0
- package/src/mvt/takeMvtBytes.js +8 -0
- package/src/mvt/tessellateVectorRings.js +19 -0
- package/src/mvt/triangulateVectorRings.js +19 -0
- package/src/native/beforeNativeRender.js +6 -0
- package/src/native/canScaleNativeStyle.js +17 -0
- package/src/native/createNativeMesh.js +31 -0
- package/src/native/disposeNativeLayer.js +1 -1
- package/src/native/getGridTerrainTile.js +34 -0
- package/src/native/gridTerrainElevation.js +30 -0
- package/src/native/loadGridTerrain.js +26 -0
- package/src/native/nativeLayer.js +2 -2
- package/src/native/nativeLayerMethod.js +5 -14
- package/src/native/nativeProgram.js +20 -0
- package/src/native/nativeVectorGeometry.js +23 -0
- package/src/native/orderNativeGridLayer.js +14 -0
- package/src/native/putNativeMesh.js +15 -21
- package/src/native/refreshNativeEvent.js +13 -2
- package/src/native/refreshNativeLayer.js +1 -0
- package/src/native/syncGridLayer.js +48 -3
- package/src/native/syncNativeStrokeAnchors.js +12 -0
- package/src/native/syncNativeStrokeZoom.js +29 -0
- package/src/native/syncVectorLayer.js +15 -13
- package/src/native/terrainGridMesh.js +34 -0
- package/src/native/updateNativeStrokeRadius.js +9 -0
- package/src/projections/displayContainerPoint.js +23 -3
- package/src/projections/groundBounds.js +2 -2
- package/src/projections/localPixel.js +7 -2
- package/src/projections/localPixelForGeometry.js +4 -2
- package/src/projections/projectCameraPoint.js +6 -5
- package/src/rendering/collectVisibleMesh.js +5 -2
- package/src/rendering/drawSceneMeshes.js +3 -1
- package/src/rendering/nativeStrokeExpansion.js +4 -0
- package/src/rendering/prepareMeshUniforms.js +2 -0
- package/src/rendering/resizeRenderer.js +9 -0
- package/src/scene/initializerFor.js +3 -5
- package/src/scene/layerInitialize.js +14 -12
- package/src/scene/resolveNextInitialization.js +1 -1
- package/src/shaders/materialShaders.js +1 -0
- package/src/shaders/materialVertexShader.js +7 -2
- package/src/shaders/nativeStrokeShader.js +6 -0
- package/src/sources/attachAreaMesh.js +5 -6
- package/src/sources/buildArea.js +4 -5
- package/src/sources/buildAreaFeature.js +3 -19
- package/src/sources/initVectorTiles.js +15 -0
- package/src/sources/isVectorTileSource.js +4 -0
- package/src/sources/readyVectorTiles.js +10 -0
- package/src/sources/sourceAreaContext.js +1 -6
- package/src/sunlight/createSun.js +0 -1
- package/src/terrain/initTerrain.js +7 -1
- package/src/terrain/loadTerrain.js +4 -1
- package/src/terrain/mapElevationOf.js +5 -1
- package/src/terrain/onTerrainAdd.js +11 -1
- package/src/terrain/onTerrainRemove.js +10 -1
- package/src/utils/yieldTask.js +5 -0
- package/src/vector-style/appendQuotedStyleCharacter.js +22 -0
- package/src/vector-style/arrayContainsRange.js +8 -0
- package/src/vector-style/evaluateBoolean.js +18 -0
- package/src/vector-style/evaluateCoalesceOrCase.js +21 -0
- package/src/vector-style/evaluateComparison.js +16 -0
- package/src/vector-style/evaluateIExpression.js +8 -0
- package/src/vector-style/evaluateInput.js +6 -0
- package/src/vector-style/evaluateInterpolate.js +27 -0
- package/src/vector-style/evaluateMatch.js +12 -0
- package/src/vector-style/evaluateMath.js +14 -0
- package/src/vector-style/evaluateMembership.js +18 -0
- package/src/vector-style/evaluateNegation.js +13 -0
- package/src/vector-style/evaluatePrimitive.js +9 -0
- package/src/vector-style/evaluateStep.js +11 -0
- package/src/vector-style/evaluateStyle.js +33 -0
- package/src/vector-style/evaluateToExpression.js +14 -0
- package/src/vector-style/fillVectorPaint.js +17 -0
- package/src/vector-style/lineVectorPaint.js +21 -0
- package/src/vector-style/parseFunctionalColor.js +14 -0
- package/src/vector-style/parseHexColor.js +13 -0
- package/src/vector-style/parseVectorStyle.js +13 -0
- package/src/vector-style/readPaintValue.js +6 -0
- package/src/vector-style/removeTrailingCommas.js +12 -0
- package/src/vector-style/scaleDashArray.js +13 -0
- package/src/vector-style/skipStyleComment.js +9 -0
- package/src/vector-style/stripStyleComments.js +21 -0
- package/src/vector-style/styleColor.js +11 -0
- package/src/vector-style/validateVectorLayers.js +10 -0
- package/src/vector-style/vectorPaint.js +8 -0
- package/src/vector-style/visibleStyle.js +7 -0
- package/src/vector-tiles/appendVectorBatch.js +22 -0
- package/src/vector-tiles/attachVectorTileBatch.js +17 -0
- package/src/vector-tiles/attachVectorTileBatches.js +15 -0
- package/src/vector-tiles/compareVectorLabelPriority.js +3 -0
- package/src/vector-tiles/compareVectorTileDistance.js +3 -0
- package/src/vector-tiles/configureVectorTileLayer.js +28 -0
- package/src/vector-tiles/forwardVectorTileError.js +5 -0
- package/src/vector-tiles/loadVectorSprite.js +5 -0
- package/src/vector-tiles/loadVectorTile.js +36 -0
- package/src/vector-tiles/onVectorTileAdd.js +39 -0
- package/src/vector-tiles/onVectorTileMessage.js +10 -0
- package/src/vector-tiles/onVectorTileRemove.js +20 -0
- package/src/vector-tiles/onVectorTileWorkerError.js +11 -0
- package/src/vector-tiles/paintVectorTileBatch.js +12 -0
- package/src/vector-tiles/prepareVectorLabel.js +43 -0
- package/src/vector-tiles/prepareVectorStyleLayer.js +30 -0
- package/src/vector-tiles/prepareVectorTile.js +16 -0
- package/src/vector-tiles/projectVectorPaths.js +15 -0
- package/src/vector-tiles/projectVectorPoint.js +6 -0
- package/src/vector-tiles/projectVectorTriangles.js +18 -0
- package/src/vector-tiles/pruneVectorTiles.js +11 -0
- package/src/vector-tiles/pumpVectorTiles.js +18 -0
- package/src/vector-tiles/readTileJSON.js +17 -0
- package/src/vector-tiles/readVectorStyle.js +17 -0
- package/src/vector-tiles/refreshVectorTiles.js +5 -0
- package/src/vector-tiles/reserveVectorLabelCells.js +6 -0
- package/src/vector-tiles/retireVectorTileGroup.js +13 -0
- package/src/vector-tiles/revokeVectorWorkerUrl.js +9 -0
- package/src/vector-tiles/rotateVectorLabel.js +12 -0
- package/src/vector-tiles/rotateVectorLabels.js +6 -0
- package/src/vector-tiles/simplifyVectorPath.js +21 -0
- package/src/vector-tiles/updateVectorLabelMarker.js +27 -0
- package/src/vector-tiles/updateVectorTileLabels.js +28 -0
- package/src/vector-tiles/updateVectorTilePaint.js +20 -0
- package/src/vector-tiles/updateVectorTiles.js +29 -0
- package/src/vector-tiles/validateVectorTileZooms.js +6 -0
- package/src/vector-tiles/vectorFeaturePaint.js +15 -0
- package/src/vector-tiles/vectorFeaturePaths.js +16 -0
- package/src/vector-tiles/vectorFeatureZoom.js +8 -0
- package/src/vector-tiles/vectorLabelAnchors.js +24 -0
- package/src/vector-tiles/vectorLabelCandidates.js +11 -0
- package/src/vector-tiles/vectorLabelCells.js +26 -0
- package/src/vector-tiles/vectorLabelIcon.js +30 -0
- package/src/vector-tiles/vectorLabelProperty.js +3 -0
- package/src/vector-tiles/vectorSpriteIcon.js +11 -0
- package/src/vector-tiles/vectorStraightRun.js +14 -0
- package/src/vector-tiles/vectorStyleDependencies.js +15 -0
- package/src/vector-tiles/vectorStyleValue.js +5 -0
- package/src/vector-tiles/vectorStyleZoom.js +6 -0
- package/src/vector-tiles/vectorTileAwaited.js +9 -0
- package/src/vector-tiles/vectorTileOverlaps.js +4 -0
- package/src/vector-tiles/vectorTilePaint.js +10 -0
- package/src/vector-tiles/vectorTileSettings.js +17 -0
- package/src/vector-tiles/vectorTilesIdle.js +3 -0
- package/src/vector-tiles/vectorTolerance.js +4 -0
- package/src/vector-tiles/wrapVectorLabel.js +11 -0
- package/src/weakmaps/nativeProgramsByRenderer.js +1 -0
- package/src/weakmaps/streamTerrainByLayer.js +1 -0
- package/src/weakmaps/streamTerrainByMap.js +1 -0
- package/src/weakmaps/vectorTileOptionsByLayer.js +1 -0
- package/src/weakmaps/vectorWorkerByLayer.js +1 -0
- package/src/weakmaps/workerMapByLayer.js +1 -0
- package/src/workers/buildAreaInWorker.js +3 -27
- package/src/workers/cogWorker.js +21 -0
- package/src/workers/createGeometryWorker.js +1 -0
- package/src/workers/geometryWorker.js +15 -0
- package/src/workers/getCogInWorker.js +7 -0
- package/src/workers/modelWorker.js +10 -0
- package/src/workers/openCogInWorker.js +14 -0
- package/src/workers/runSourceWorker.js +32 -0
- package/src/workers/settleGeometryWorker.js +1 -1
- package/src/workers/vectorTileWorker.js +10 -0
- package/src/geometry/buildExtrudedPolygon.js +0 -10
- package/src/sources/buildAreaPoint.js +0 -7
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { L } from '../globals/L.js';
|
|
2
|
+
import { nativeScalableStyleKeys } from '../globals/nativeScalableStyleKeys.js';
|
|
3
|
+
|
|
4
|
+
export function canScaleNativeStyle(name, state, args) {
|
|
5
|
+
const { source } = state;
|
|
6
|
+
if (name !== 'setStyle' || source.options.interactive !== false || state.dirty && !state.zoomOnly) return false;
|
|
7
|
+
const stroke = state.strokeCoordinates && state.meshes.get('stroke')?.program.uniforms.strokeScale;
|
|
8
|
+
const fill = source instanceof L.Polygon && !source.options.stroke && state.meshes.has('fill');
|
|
9
|
+
if (!stroke && !fill) return false;
|
|
10
|
+
let key;
|
|
11
|
+
if (args[0]) {
|
|
12
|
+
for (key of Object.keys(args[0])) {
|
|
13
|
+
if (!nativeScalableStyleKeys.has(key)) return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { L } from '../globals/L.js';
|
|
2
|
+
import { disposeMesh } from '../rendering/disposeMesh.js';
|
|
3
|
+
import { createMesh } from '../rendering/createMesh.js';
|
|
4
|
+
import { nativeProgram } from './nativeProgram.js';
|
|
5
|
+
|
|
6
|
+
export function createNativeMesh(state, key, position, color, opacity, texture, uv, terrain, nativeStroke) {
|
|
7
|
+
const { backend: layer, source, meshes } = state;
|
|
8
|
+
// Unlit, noninteractive strokes use the normal slot for stationary anchors.
|
|
9
|
+
const normal = nativeStroke ? state.strokeAnchors : /* alloc */ [];
|
|
10
|
+
let index, mesh = meshes.get(key);
|
|
11
|
+
if (!nativeStroke) {
|
|
12
|
+
for (index = 0; index < position.length; index++) normal.push(index % 3 === 1 ? 1 : 0);
|
|
13
|
+
}
|
|
14
|
+
const data = /* alloc */ { position, normal };
|
|
15
|
+
if (uv) data.uv = uv;
|
|
16
|
+
const material = /* alloc */ {
|
|
17
|
+
vertexColors: false, color, opacity, unlit: true, alphaMode: 'BLEND', depthWrite: terrain, nativeStroke,
|
|
18
|
+
};
|
|
19
|
+
if (texture) material.baseTexture = texture;
|
|
20
|
+
if (mesh) disposeMesh(layer, mesh);
|
|
21
|
+
mesh = createMesh(layer, data, material, 0, source instanceof L.GridLayer
|
|
22
|
+
? (terrain ? state.terrainRasterProgram : state.rasterProgram) || nativeProgram(layer, material)
|
|
23
|
+
: nativeProgram(layer, material));
|
|
24
|
+
if (source instanceof L.GridLayer) {
|
|
25
|
+
if (terrain) state.terrainRasterProgram ||= mesh.program;
|
|
26
|
+
else state.rasterProgram ||= mesh.program;
|
|
27
|
+
mesh.texture = texture;
|
|
28
|
+
}
|
|
29
|
+
meshes.set(key, mesh);
|
|
30
|
+
return mesh;
|
|
31
|
+
}
|
|
@@ -17,7 +17,7 @@ export function disposeNativeLayer() {
|
|
|
17
17
|
const { source, map, backend: layer, meshes, textures, images } = state;
|
|
18
18
|
const events = 'load tileload tileunload move drag';
|
|
19
19
|
source.off(events, refreshNativeEvent, state);
|
|
20
|
-
map.off('zoomend', refreshNativeEvent, state);
|
|
20
|
+
map.off('zoomend terrainchange', refreshNativeEvent, state);
|
|
21
21
|
if (state.marker) map.off('move zoom rotate pitch resize viewreset', updateNativeLayerView, state);
|
|
22
22
|
removeNativeEvents(state);
|
|
23
23
|
let name, methods, mesh, texture, image;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export async function getGridTerrainTile(state, z, x, y) {
|
|
2
|
+
const limit = 2 ** z;
|
|
3
|
+
x = ((x % limit) + limit) % limit;
|
|
4
|
+
y = Math.max(0, Math.min(limit - 1, y));
|
|
5
|
+
const key = `${z}/${x}/${y}`;
|
|
6
|
+
let entry = state.terrainCache.get(key);
|
|
7
|
+
if (!entry) {
|
|
8
|
+
entry = /* alloc */ { promise: state.layer.options.getTile(z, x, y, state.terrainController.signal) };
|
|
9
|
+
state.terrainCache.set(key, entry);
|
|
10
|
+
} else {
|
|
11
|
+
state.terrainCache.delete(key);
|
|
12
|
+
state.terrainCache.set(key, entry);
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
if (!entry.data) entry.data = await entry.promise;
|
|
16
|
+
if (!(entry.data instanceof Float32Array) || entry.data.length !== 65536) {
|
|
17
|
+
throw /* alloc */ new Error(`Invalid elevation tile ${key}: expected 256x256 Float32Array`);
|
|
18
|
+
}
|
|
19
|
+
if (!entry.range) {
|
|
20
|
+
let minimum = Infinity, maximum = -Infinity, elevation;
|
|
21
|
+
for (elevation of entry.data) {
|
|
22
|
+
if (!Number.isFinite(elevation) || elevation <= -1000) continue;
|
|
23
|
+
minimum = Math.min(minimum, elevation);
|
|
24
|
+
maximum = Math.max(maximum, elevation);
|
|
25
|
+
}
|
|
26
|
+
entry.range = /* alloc */ [minimum, maximum];
|
|
27
|
+
}
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (state.terrainCache.get(key) === entry) state.terrainCache.delete(key);
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
while (state.terrainCache.size > 256) state.terrainCache.delete(state.terrainCache.keys().next().value);
|
|
33
|
+
return entry.data;
|
|
34
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { terrainElevation } from '../terrain/terrainElevation.js';
|
|
2
|
+
import { nativeGPUByLayer } from '../weakmaps/nativeGPUByLayer.js';
|
|
3
|
+
|
|
4
|
+
export function gridTerrainElevation(state, location) {
|
|
5
|
+
let z = Math.max(0, Math.min(24, Math.round(state.map.getZoom())));
|
|
6
|
+
const tiles = /* alloc */ new Map();
|
|
7
|
+
let point, limit, x, y, dx, dy, tx, ty, entry, elevation, layer, native, request;
|
|
8
|
+
for (; z >= 0; z--) {
|
|
9
|
+
point = state.map.project(location, z), limit = 2 ** z;
|
|
10
|
+
x = Math.floor(point.x / 256), y = Math.floor(point.y / 256);
|
|
11
|
+
for (layer of Object.values(state.map._layers)) {
|
|
12
|
+
native = nativeGPUByLayer.get(layer);
|
|
13
|
+
if (native?.disposed || native?.terrainStream !== state) continue;
|
|
14
|
+
request = native.terrainRequests?.get(`${x}:${y}:${z}`);
|
|
15
|
+
if (!request?.tiles || layer._tiles[`${x}:${y}:${z}`] !== request.tile) continue;
|
|
16
|
+
elevation = terrainElevation(point, request.tiles);
|
|
17
|
+
if (Number.isFinite(elevation)) return elevation;
|
|
18
|
+
}
|
|
19
|
+
tiles.clear();
|
|
20
|
+
for (dy = -1; dy <= 1; dy++) for (dx = -1; dx <= 1; dx++) {
|
|
21
|
+
tx = ((x + dx) % limit + limit) % limit;
|
|
22
|
+
ty = Math.max(0, Math.min(limit - 1, y + dy));
|
|
23
|
+
entry = state.terrainCache.get(`${z}/${tx}/${ty}`);
|
|
24
|
+
if (entry?.data) tiles.set(`${x + dx}/${y + dy}`, entry.data);
|
|
25
|
+
}
|
|
26
|
+
elevation = terrainElevation(point, tiles);
|
|
27
|
+
if (Number.isFinite(elevation)) return elevation;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getGridTerrainTile } from './getGridTerrainTile.js';
|
|
2
|
+
import { refreshNativeLayer } from './refreshNativeLayer.js';
|
|
3
|
+
|
|
4
|
+
export async function loadGridTerrain(state, key, tile, request) {
|
|
5
|
+
const { x, y, z } = tile.coords, stream = request.stream;
|
|
6
|
+
const jobs = /* alloc */ [], tiles = /* alloc */ new Map();
|
|
7
|
+
let dx, dy, i = 0;
|
|
8
|
+
try {
|
|
9
|
+
for (dy = -1; dy <= 1; dy++) for (dx = -1; dx <= 1; dx++) {
|
|
10
|
+
jobs.push(getGridTerrainTile(stream, z, x + dx, y + dy));
|
|
11
|
+
}
|
|
12
|
+
const values = await Promise.all(jobs);
|
|
13
|
+
if (state.disposed || stream.terrainController.signal.aborted ||
|
|
14
|
+
state.source._tiles[key] !== tile || state.terrainRequests.get(key) !== request) return;
|
|
15
|
+
for (dy = -1; dy <= 1; dy++) for (dx = -1; dx <= 1; dx++) tiles.set(`${x + dx}/${y + dy}`, values[i++]);
|
|
16
|
+
request.tiles = tiles;
|
|
17
|
+
refreshNativeLayer(state);
|
|
18
|
+
state.map.fire('terrainchange');
|
|
19
|
+
state.source._update();
|
|
20
|
+
} catch (error) {
|
|
21
|
+
if (!state.disposed && !stream.terrainController.signal.aborted && state.source._tiles[key] === tile) {
|
|
22
|
+
request.error = error;
|
|
23
|
+
stream.layer.fire('error', /* alloc */ { error, coords: tile.coords });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -25,7 +25,7 @@ import { synchronizeNativeLayer } from './synchronizeNativeLayer.js';
|
|
|
25
25
|
export async function nativeLayer(state) {
|
|
26
26
|
const { source, map } = state;
|
|
27
27
|
const layer = state.backend = createLayer(/* alloc */ {
|
|
28
|
-
source: /* alloc */ { type: '
|
|
28
|
+
source: /* alloc */ { type: 'vector' },
|
|
29
29
|
});
|
|
30
30
|
state.meshes = /* alloc */ new Map();
|
|
31
31
|
state.textures = /* alloc */ new Map();
|
|
@@ -43,7 +43,7 @@ export async function nativeLayer(state) {
|
|
|
43
43
|
state.disposed = false;
|
|
44
44
|
const currentEvents = 'load tileload tileunload move drag';
|
|
45
45
|
source.on(currentEvents, refreshNativeEvent, state);
|
|
46
|
-
map.on('zoomend', refreshNativeEvent, state);
|
|
46
|
+
map.on('zoomend terrainchange', refreshNativeEvent, state);
|
|
47
47
|
if (state.marker) map.on('move zoom rotate pitch resize viewreset', updateNativeLayerView, state);
|
|
48
48
|
nativeEvents(state);
|
|
49
49
|
let name, own, original;
|
|
@@ -3,25 +3,15 @@ import { nativeGPUBackByMap } from '../weakmaps/nativeGPUBackByMap.js';
|
|
|
3
3
|
import { nativeGPUOrderByMap } from '../weakmaps/nativeGPUOrderByMap.js';
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
import { L } from '../globals/L.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
6
|
import { refreshNativeLayer } from './refreshNativeLayer.js';
|
|
7
|
+
import { canScaleNativeStyle } from './canScaleNativeStyle.js';
|
|
8
|
+
import { orderNativeGridLayer } from './orderNativeGridLayer.js';
|
|
10
9
|
|
|
11
10
|
export function nativeLayerMethod(name, source, args) {
|
|
12
11
|
const state = nativeGPUByLayer.get(source), original = state.methods.get(name).original;
|
|
12
|
+
const scalable = canScaleNativeStyle(name, state, args);
|
|
13
13
|
const result = original.apply(source, args);
|
|
14
|
-
|
|
15
|
-
if ((name === 'bringToFront' || name === 'bringToBack') && source instanceof L.GridLayer) {
|
|
16
|
-
let extreme = name === 'bringToFront' ? -Infinity : Infinity;
|
|
17
|
-
for (layer of Object.values(state.map._layers)) {
|
|
18
|
-
if (layer === source || !(layer instanceof L.GridLayer) || layer.getPane() !== source.getPane()) continue;
|
|
19
|
-
zIndex = layer.options.zIndex || 0;
|
|
20
|
-
extreme = name === 'bringToFront' ? Math.max(extreme, zIndex) : Math.min(extreme, zIndex);
|
|
21
|
-
}
|
|
22
|
-
const edge = name === 'bringToFront' ? extreme + 1 : extreme - 1;
|
|
23
|
-
if (Number.isFinite(edge)) source.setZIndex(edge);
|
|
24
|
-
}
|
|
14
|
+
orderNativeGridLayer(state, name);
|
|
25
15
|
if (name === 'bringToFront') {
|
|
26
16
|
state.order = nativeGPUOrderByMap.get(state.map) + 1;
|
|
27
17
|
nativeGPUOrderByMap.set(state.map, state.order);
|
|
@@ -31,5 +21,6 @@ export function nativeLayerMethod(name, source, args) {
|
|
|
31
21
|
nativeGPUBackByMap.set(state.map, state.order);
|
|
32
22
|
}
|
|
33
23
|
refreshNativeLayer(state);
|
|
24
|
+
if (scalable && (!source.options.stroke || Number(source.options.weight) > 0)) state.zoomOnly = true;
|
|
34
25
|
return result;
|
|
35
26
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { rendererByLayer } from '../weakmaps/rendererByLayer.js';
|
|
2
|
+
import { nativeProgramsByRenderer } from '../weakmaps/nativeProgramsByRenderer.js';
|
|
3
|
+
import { createProgram } from '../materials/createProgram.js';
|
|
4
|
+
import { createProgramUniforms } from '../materials/createProgramUniforms.js';
|
|
5
|
+
|
|
6
|
+
export function nativeProgram(layer, material) {
|
|
7
|
+
const renderer = rendererByLayer.get(layer);
|
|
8
|
+
let programs = nativeProgramsByRenderer.get(renderer);
|
|
9
|
+
if (!programs) {
|
|
10
|
+
programs = /* alloc */ new Map();
|
|
11
|
+
nativeProgramsByRenderer.set(renderer, programs);
|
|
12
|
+
}
|
|
13
|
+
const key = `${Boolean(material.baseTexture)}:${Boolean(material.nativeStroke)}:${Boolean(material.depthWrite)}`;
|
|
14
|
+
let template = programs.get(key);
|
|
15
|
+
if (!template) {
|
|
16
|
+
template = createProgram(layer, /* alloc */ { doubleSided: true, ...material });
|
|
17
|
+
programs.set(key, template);
|
|
18
|
+
}
|
|
19
|
+
return /* alloc */ { ...template, uniforms: createProgramUniforms(material), _layerMaterial: material };
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { geometryPixelStates } from '../globals/geometryPixelStates.js';
|
|
2
|
+
import { nativeGeometry } from '../geometry/nativeGeometry.js';
|
|
3
|
+
import { localPixelForGeometry } from '../projections/localPixelForGeometry.js';
|
|
4
|
+
import { locationByLayer } from '../weakmaps/locationByLayer.js';
|
|
5
|
+
import { radians } from '../globals/radians.js';
|
|
6
|
+
import { L } from '../globals/L.js';
|
|
7
|
+
|
|
8
|
+
export function nativeVectorGeometry(state) {
|
|
9
|
+
const { source } = state;
|
|
10
|
+
state.strokeCoordinates = null;
|
|
11
|
+
state.strokeAnchors = source instanceof L.Polyline && !source.options.dashArray ? /* alloc */ [] : null;
|
|
12
|
+
const crs = state.map.options.crs, origin = locationByLayer.get(state.backend);
|
|
13
|
+
state.pixelProjection = /* alloc */ {
|
|
14
|
+
transformation: crs.transformation, scale: crs.scale(state.map.getZoom()),
|
|
15
|
+
origin: crs.project(origin), metres: Math.cos(origin.lat * radians),
|
|
16
|
+
};
|
|
17
|
+
geometryPixelStates.push(state);
|
|
18
|
+
try {
|
|
19
|
+
return nativeGeometry(source, state.map, localPixelForGeometry);
|
|
20
|
+
} finally {
|
|
21
|
+
geometryPixelStates.pop();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { L } from '../globals/L.js';
|
|
2
|
+
|
|
3
|
+
export function orderNativeGridLayer(state, name) {
|
|
4
|
+
const { source } = state;
|
|
5
|
+
if (!(source instanceof L.GridLayer) || name !== 'bringToFront' && name !== 'bringToBack') return;
|
|
6
|
+
let extreme = name === 'bringToFront' ? -Infinity : Infinity, layer, zIndex;
|
|
7
|
+
for (layer of Object.values(state.map._layers)) {
|
|
8
|
+
if (layer === source || !(layer instanceof L.GridLayer) || layer.getPane() !== source.getPane()) continue;
|
|
9
|
+
zIndex = layer.options.zIndex || 0;
|
|
10
|
+
extreme = name === 'bringToFront' ? Math.max(extreme, zIndex) : Math.min(extreme, zIndex);
|
|
11
|
+
}
|
|
12
|
+
const edge = name === 'bringToFront' ? extreme + 1 : extreme - 1;
|
|
13
|
+
if (Number.isFinite(edge)) source.setZIndex(edge);
|
|
14
|
+
}
|
|
@@ -1,36 +1,30 @@
|
|
|
1
1
|
import { L } from '../globals/L.js';
|
|
2
|
-
import { disposeMesh } from '../rendering/disposeMesh.js';
|
|
3
|
-
import { createMesh } from '../rendering/createMesh.js';
|
|
4
2
|
import { styleNativeMesh } from './styleNativeMesh.js';
|
|
3
|
+
import { createNativeMesh } from './createNativeMesh.js';
|
|
4
|
+
import { updateNativeStrokeRadius } from './updateNativeStrokeRadius.js';
|
|
5
5
|
|
|
6
|
-
export function putNativeMesh(state, key, position, color, opacity, texture, uv) {
|
|
7
|
-
const {
|
|
6
|
+
export function putNativeMesh(state, key, position, color, opacity, texture, uv, terrain = false) {
|
|
7
|
+
const { source, meshes } = state;
|
|
8
8
|
if (!position.length) return;
|
|
9
|
+
const nativeStroke = key === 'stroke' && Boolean(state.strokeCoordinates) && source.options.interactive === false;
|
|
9
10
|
let mesh = meshes.get(key);
|
|
10
11
|
if (!mesh || mesh.geometry.attributes.position.data.length !== position.length ||
|
|
11
|
-
mesh.program.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const data = /* alloc */ { position, normal };
|
|
16
|
-
if (uv) data.uv = uv;
|
|
17
|
-
const material = /* alloc */ {
|
|
18
|
-
vertexColors: false, color, opacity, unlit: true, alphaMode: 'BLEND',
|
|
19
|
-
};
|
|
20
|
-
if (texture) material.baseTexture = texture;
|
|
21
|
-
if (mesh) disposeMesh(layer, mesh);
|
|
22
|
-
mesh = createMesh(layer, data, material, 0, source instanceof L.GridLayer ? state.rasterProgram : undefined);
|
|
23
|
-
if (source instanceof L.GridLayer) {
|
|
24
|
-
state.rasterProgram ||= mesh.program;
|
|
25
|
-
mesh.texture = texture;
|
|
26
|
-
}
|
|
27
|
-
meshes.set(key, mesh);
|
|
12
|
+
(source instanceof L.GridLayer && mesh.program.depthWrite !== terrain) ||
|
|
13
|
+
mesh.program.uniforms.baseTexture?.value !== texture ||
|
|
14
|
+
Boolean(mesh.program._layerMaterial.nativeStroke) !== nativeStroke) {
|
|
15
|
+
mesh = createNativeMesh(state, key, position, color, opacity, texture, uv, terrain, nativeStroke);
|
|
28
16
|
} else {
|
|
29
17
|
const attribute = mesh.geometry.attributes.position;
|
|
30
18
|
attribute.data.set(position);
|
|
31
19
|
attribute.needsUpdate = true;
|
|
32
20
|
mesh.geometry.bounds = null;
|
|
21
|
+
if (nativeStroke) {
|
|
22
|
+
mesh.geometry.attributes.normal.data.set(state.strokeAnchors);
|
|
23
|
+
mesh.geometry.attributes.normal.needsUpdate = true;
|
|
24
|
+
}
|
|
33
25
|
}
|
|
26
|
+
if (nativeStroke) updateNativeStrokeRadius(mesh);
|
|
27
|
+
if (mesh.program.uniforms.strokeScale) mesh.program.uniforms.strokeScale.value = 1;
|
|
34
28
|
styleNativeMesh(state, mesh, color, opacity);
|
|
35
29
|
return mesh;
|
|
36
30
|
}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { refreshNativeLayer } from './refreshNativeLayer.js';
|
|
2
|
+
import { L } from '../globals/L.js';
|
|
3
|
+
import { update } from '../scene/scheduleSceneUpdate.js';
|
|
2
4
|
|
|
3
|
-
export function refreshNativeEvent() {
|
|
4
|
-
|
|
5
|
+
export function refreshNativeEvent(event) {
|
|
6
|
+
if (event?.type === 'zoomend' && this.source instanceof L.Polyline &&
|
|
7
|
+
(!this.source.options.stroke || !(Number(this.source.options.weight) > 0))) return;
|
|
8
|
+
if (event?.type === 'zoomend' && this.strokeCoordinates && (!this.dirty || this.zoomOnly)) {
|
|
9
|
+
this.zoomOnly = true;
|
|
10
|
+
this.dirty = true;
|
|
11
|
+
update(this.backend);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (event?.type === 'terrainchange' && this.marker) this.source.update();
|
|
15
|
+
refreshNativeLayer(this);
|
|
5
16
|
}
|
|
@@ -10,6 +10,7 @@ import { update } from '../scene/scheduleSceneUpdate.js';
|
|
|
10
10
|
import { hideTargets } from './hideTargets.js';
|
|
11
11
|
|
|
12
12
|
export function refreshNativeLayer(state = this) {
|
|
13
|
+
state.zoomOnly = false;
|
|
13
14
|
state.dirty = true;
|
|
14
15
|
state.viewDirty = true;
|
|
15
16
|
state.failed = false;
|
|
@@ -1,22 +1,58 @@
|
|
|
1
1
|
import { L } from '../globals/L.js';
|
|
2
2
|
import { coreWhite } from '../globals/coreWhite.js';
|
|
3
|
+
import { streamTerrainByMap } from '../weakmaps/streamTerrainByMap.js';
|
|
3
4
|
|
|
4
5
|
import { styleNativeMesh } from './styleNativeMesh.js';
|
|
5
6
|
import { quadNativeMesh } from './quadNativeMesh.js';
|
|
6
7
|
import { boundsQuad } from '../geometry/boundsQuad.js';
|
|
8
|
+
import { loadGridTerrain } from './loadGridTerrain.js';
|
|
9
|
+
import { terrainGridMesh } from './terrainGridMesh.js';
|
|
7
10
|
|
|
8
11
|
|
|
9
12
|
export function syncGridLayer(state) {
|
|
10
13
|
const { source, textures, meshes } = state;
|
|
11
|
-
|
|
14
|
+
const stream = streamTerrainByMap.get(state.map);
|
|
15
|
+
if (state.terrainStream !== stream) {
|
|
16
|
+
state.terrainStream = stream;
|
|
17
|
+
state.terrainRequests = stream ? /* alloc */ new Map() : null;
|
|
18
|
+
}
|
|
19
|
+
let key, tile, opacity, retained, mesh, nw, se, request, pending = false;
|
|
20
|
+
if (state.terrainRequests) {
|
|
21
|
+
for (key of state.terrainRequests.keys()) {
|
|
22
|
+
if (!source._tiles[key]) state.terrainRequests.delete(key);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
12
25
|
for (key in source._tiles) {
|
|
13
26
|
if (!Object.hasOwn(source._tiles, key)) continue;
|
|
14
27
|
tile = source._tiles[key];
|
|
15
|
-
if (!tile.loaded || tile.el instanceof HTMLImageElement && !tile.el.naturalWidth)
|
|
28
|
+
if (!tile.loaded || tile.el instanceof HTMLImageElement && !tile.el.naturalWidth) {
|
|
29
|
+
if (stream) pending = true;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
16
32
|
opacity = (source.options.opacity ?? 1) * (tile._gpuOpacity ?? 1);
|
|
17
33
|
retained = textures.get(key);
|
|
18
34
|
mesh = meshes.get(key);
|
|
19
|
-
if (
|
|
35
|
+
if (state.terrainRequests) {
|
|
36
|
+
request = state.terrainRequests.get(key);
|
|
37
|
+
if (!request || request.tile !== tile) {
|
|
38
|
+
request = /* alloc */ { tile, stream };
|
|
39
|
+
state.terrainRequests.set(key, request);
|
|
40
|
+
loadGridTerrain(state, key, tile, request);
|
|
41
|
+
}
|
|
42
|
+
if (!request.tiles) {
|
|
43
|
+
pending = true;
|
|
44
|
+
if (mesh && retained?.image === tile.el) {
|
|
45
|
+
retained.used = true;
|
|
46
|
+
styleNativeMesh(state, mesh, coreWhite, opacity);
|
|
47
|
+
}
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (mesh && mesh._terrainRequest === request && retained?.image === tile.el &&
|
|
51
|
+
retained.url === (tile.el.currentSrc || tile.el.src)) {
|
|
52
|
+
retained.used = true;
|
|
53
|
+
styleNativeMesh(state, mesh, coreWhite, opacity);
|
|
54
|
+
} else mesh = terrainGridMesh(state, key, tile, request, opacity);
|
|
55
|
+
} else if (mesh && !mesh._terrainRequest && retained?.image === tile.el && retained.url === (tile.el.currentSrc || tile.el.src)) {
|
|
20
56
|
retained.used = true;
|
|
21
57
|
styleNativeMesh(state, mesh, coreWhite, opacity);
|
|
22
58
|
} else {
|
|
@@ -26,4 +62,13 @@ export function syncGridLayer(state) {
|
|
|
26
62
|
}
|
|
27
63
|
if (mesh) mesh.renderOrder += tile.coords.z / 100;
|
|
28
64
|
}
|
|
65
|
+
if (stream && (pending || !Object.keys(source._tiles).length)) {
|
|
66
|
+
for ([key, mesh] of meshes) {
|
|
67
|
+
if (source._tiles[key] || !mesh._terrainRequest) continue;
|
|
68
|
+
retained = textures.get(key);
|
|
69
|
+
if (!retained) continue;
|
|
70
|
+
retained.used = true;
|
|
71
|
+
mesh._nativeUsed = true;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
29
74
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function syncNativeStrokeAnchors(state, stroke) {
|
|
2
|
+
const { source } = state;
|
|
3
|
+
if (state.strokeAnchors?.length === stroke.length && stroke.length) {
|
|
4
|
+
if (source.options.interactive === false) state.strokeCoordinates = stroke;
|
|
5
|
+
else {
|
|
6
|
+
state.strokeCoordinates = /* alloc */ new Float64Array(stroke);
|
|
7
|
+
state.strokeAnchors = /* alloc */ new Float64Array(state.strokeAnchors);
|
|
8
|
+
}
|
|
9
|
+
state.strokeZoom = state.map.getZoom();
|
|
10
|
+
state.strokeWeight = Number(source.options.weight);
|
|
11
|
+
} else state.strokeAnchors = null;
|
|
12
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { styleNativeMesh } from './styleNativeMesh.js';
|
|
2
|
+
import { parseColor } from '../colors/parseColor.js';
|
|
3
|
+
|
|
4
|
+
export function syncNativeStrokeZoom(state) {
|
|
5
|
+
const { source, meshes, strokeCoordinates, strokeAnchors } = state;
|
|
6
|
+
const mesh = meshes.get('stroke');
|
|
7
|
+
let i, r, g, b, fill;
|
|
8
|
+
if (mesh) {
|
|
9
|
+
const factor = 2 ** (state.strokeZoom - state.map.getZoom()) *
|
|
10
|
+
Number(source.options.weight) / state.strokeWeight;
|
|
11
|
+
const attribute = mesh.geometry.attributes.position;
|
|
12
|
+
if (mesh.program.uniforms.strokeScale) {
|
|
13
|
+
mesh.program.uniforms.strokeScale.value = factor;
|
|
14
|
+
} else {
|
|
15
|
+
for (i = 0; i < strokeCoordinates.length; i++) {
|
|
16
|
+
attribute.data[i] = strokeAnchors[i] + (strokeCoordinates[i] - strokeAnchors[i]) * factor;
|
|
17
|
+
}
|
|
18
|
+
attribute.needsUpdate = true;
|
|
19
|
+
mesh.geometry.bounds = null;
|
|
20
|
+
}
|
|
21
|
+
({ r, g, b } = parseColor(source.options.color));
|
|
22
|
+
styleNativeMesh(state, mesh, /* alloc */ [r, g, b], source.options.opacity ?? 1);
|
|
23
|
+
}
|
|
24
|
+
fill = meshes.get('fill');
|
|
25
|
+
if (fill) {
|
|
26
|
+
({ r, g, b } = parseColor(source.options.fillColor || source.options.color));
|
|
27
|
+
styleNativeMesh(state, fill, /* alloc */ [r, g, b], source.options.fillOpacity ?? 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -1,22 +1,19 @@
|
|
|
1
|
-
import { geometryPixelStates } from '../globals/geometryPixelStates.js';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import { nativeGeometry } from '../geometry/nativeGeometry.js';
|
|
5
|
-
import { localPixelForGeometry } from '../projections/localPixelForGeometry.js';
|
|
6
1
|
import { parseColor } from '../colors/parseColor.js';
|
|
7
2
|
import { putNativeMesh } from './putNativeMesh.js';
|
|
3
|
+
import { syncNativeStrokeZoom } from './syncNativeStrokeZoom.js';
|
|
4
|
+
import { nativeVectorGeometry } from './nativeVectorGeometry.js';
|
|
5
|
+
import { syncNativeStrokeAnchors } from './syncNativeStrokeAnchors.js';
|
|
8
6
|
|
|
9
7
|
export function syncVectorLayer(state) {
|
|
10
8
|
const { source } = state;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
} finally {
|
|
16
|
-
geometryPixelStates.pop();
|
|
9
|
+
if (state.zoomOnly) {
|
|
10
|
+
syncNativeStrokeZoom(state);
|
|
11
|
+
state.zoomOnly = false;
|
|
12
|
+
return;
|
|
17
13
|
}
|
|
18
|
-
const { fill, stroke } =
|
|
19
|
-
|
|
14
|
+
const { fill, stroke } = nativeVectorGeometry(state);
|
|
15
|
+
syncNativeStrokeAnchors(state, stroke);
|
|
16
|
+
let i, key, positions, color, opacity, r, g, b, attributes;
|
|
20
17
|
for (i = 0; i < 2; i++) {
|
|
21
18
|
key = i ? 'stroke' : 'fill';
|
|
22
19
|
positions = i ? stroke : fill;
|
|
@@ -25,5 +22,10 @@ export function syncVectorLayer(state) {
|
|
|
25
22
|
if (!positions.length) continue;
|
|
26
23
|
({ r, g, b } = parseColor(color));
|
|
27
24
|
putNativeMesh(state, key, positions, /* alloc */ [r, g, b], opacity ?? 1);
|
|
25
|
+
if (key === 'stroke' && source.options.interactive === false && state.strokeCoordinates) {
|
|
26
|
+
attributes = state.meshes.get(key).geometry.attributes;
|
|
27
|
+
state.strokeCoordinates = attributes.position.data;
|
|
28
|
+
state.strokeAnchors = attributes.normal.data;
|
|
29
|
+
}
|
|
28
30
|
}
|
|
29
31
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { rootByLayer } from '../weakmaps/rootByLayer.js';
|
|
2
|
+
import { coreWhite } from '../globals/coreWhite.js';
|
|
3
|
+
import { textureFor } from '../textures/nativeTextureFor.js';
|
|
4
|
+
import { terrainElevation } from '../terrain/terrainElevation.js';
|
|
5
|
+
import { localPosition } from '../projections/localPosition.js';
|
|
6
|
+
import { putNativeMesh } from './putNativeMesh.js';
|
|
7
|
+
|
|
8
|
+
export function terrainGridMesh(state, key, tile, request, opacity) {
|
|
9
|
+
const texture = textureFor(state, key, tile.el);
|
|
10
|
+
if (!texture) return;
|
|
11
|
+
const { x, y, z } = tile.coords, divisions = 32;
|
|
12
|
+
const northwest = localPosition(state, state.map.unproject(/* alloc */ [x * 256, y * 256], z));
|
|
13
|
+
const southeast = localPosition(state, state.map.unproject(/* alloc */ [(x + 1) * 256, (y + 1) * 256], z));
|
|
14
|
+
const vertices = /* alloc */ [], position = /* alloc */ [], uv = /* alloc */ [];
|
|
15
|
+
const base = rootByLayer.get(state.backend).position[1];
|
|
16
|
+
let row, col, u, v, elevation, a, b, c, d, index;
|
|
17
|
+
for (row = 0; row <= divisions; row++) for (col = 0; col <= divisions; col++) {
|
|
18
|
+
u = col / divisions; v = row / divisions;
|
|
19
|
+
elevation = terrainElevation(/* alloc */ { x: (x + u) * 256, y: (y + v) * 256 }, request.tiles);
|
|
20
|
+
if (!Number.isFinite(elevation)) throw /* alloc */ new Error(`Missing elevation sample in ${z}/${x}/${y}`);
|
|
21
|
+
vertices.push(/* alloc */ [northwest[0] + (southeast[0] - northwest[0]) * u, elevation - base,
|
|
22
|
+
northwest[2] + (southeast[2] - northwest[2]) * v, u, v]);
|
|
23
|
+
}
|
|
24
|
+
for (row = 0; row < divisions; row++) for (col = 0; col < divisions; col++) {
|
|
25
|
+
a = row * (divisions + 1) + col; b = a + 1; c = a + divisions + 1; d = c + 1;
|
|
26
|
+
for (index of /* alloc */ [a, c, b, b, c, d]) {
|
|
27
|
+
position.push(vertices[index][0], vertices[index][1], vertices[index][2]);
|
|
28
|
+
uv.push(vertices[index][3], vertices[index][4]);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const mesh = putNativeMesh(state, key, position, coreWhite, opacity, texture, uv, true);
|
|
32
|
+
mesh._terrainRequest = request;
|
|
33
|
+
return mesh;
|
|
34
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function updateNativeStrokeRadius(mesh) {
|
|
2
|
+
const attributes = mesh.geometry.attributes, positions = attributes.position.data, anchors = attributes.normal.data;
|
|
3
|
+
let i, radius = 0;
|
|
4
|
+
for (i = 0; i < positions.length; i += 3) {
|
|
5
|
+
radius = Math.max(radius, Math.hypot(positions[i] - anchors[i],
|
|
6
|
+
positions[i + 1] - anchors[i + 1], positions[i + 2] - anchors[i + 2]));
|
|
7
|
+
}
|
|
8
|
+
mesh.geometry.nativeStrokeRadius = radius;
|
|
9
|
+
}
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
}
|
|
1
|
+
import { streamTerrainByMap } from '../weakmaps/streamTerrainByMap.js';
|
|
2
|
+
import { renderers } from '../weakmaps/renderers.js';
|
|
3
|
+
import { sceneOriginByLayer } from '../weakmaps/sceneOriginByLayer.js';
|
|
4
|
+
import { cameraViewByMap } from '../weakmaps/cameraViewByMap.js';
|
|
5
|
+
import { mapMethods } from '../globals/mapMethods.js';
|
|
6
|
+
import { radians } from '../globals/radians.js';
|
|
7
|
+
import { earthCirc } from '../globals/earthCirc.js';
|
|
8
|
+
import { mapElevationOf } from '../terrain/mapElevationOf.js';
|
|
9
|
+
import { animationPoint } from './transformZoomAnimationPoint.js';
|
|
10
|
+
import { project } from './projectCameraPoint.js';
|
|
11
|
+
|
|
12
|
+
export function displayPoint(map, point, location) {
|
|
13
|
+
const shared = renderers.get(map), origin = shared && sceneOriginByLayer.get(shared);
|
|
14
|
+
if (!streamTerrainByMap.get(map) || !origin) {
|
|
15
|
+
return map.layerPointToContainerPoint(point).subtract(map._getMapPanePos());
|
|
16
|
+
}
|
|
17
|
+
const elevation = mapElevationOf(map, location || map.layerPointToLatLng(point)) ?? 0;
|
|
18
|
+
const center = mapElevationOf(map, map.getCenter()) ?? 0;
|
|
19
|
+
const zoom = cameraViewByMap.get(map)?.zoom ?? map.getZoom();
|
|
20
|
+
const height = (elevation - center) * map.options.crs.scale(zoom) / (earthCirc * Math.cos(origin.lat * radians));
|
|
21
|
+
const raw = animationPoint(map, mapMethods.value.layerPointToContainerPoint.call(map, point));
|
|
22
|
+
return project(map, raw, false, false, height).subtract(map._getMapPanePos());
|
|
23
|
+
}
|
|
@@ -4,7 +4,7 @@ import { pointOf } from './toPoint.js';
|
|
|
4
4
|
import { project } from './projectCameraPoint.js';
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
export function groundBounds(map, padding = cameraZeroPadding) {
|
|
7
|
+
export function groundBounds(map, padding = cameraZeroPadding, height = 0) {
|
|
8
8
|
const min = pointOf(padding).divideBy(2), max = map.getSize().subtract(min);
|
|
9
9
|
const bounds = /* alloc */ new L.Bounds();
|
|
10
10
|
const minX = min.x, minY = min.y;
|
|
@@ -12,7 +12,7 @@ export function groundBounds(map, padding = cameraZeroPadding) {
|
|
|
12
12
|
for (i = 0; i < 4; i++) {
|
|
13
13
|
min.x = i % 2 ? max.x : minX;
|
|
14
14
|
min.y = i < 2 ? minY : max.y;
|
|
15
|
-
bounds.extend(project(map, min, true, true));
|
|
15
|
+
bounds.extend(project(map, min, true, true, height));
|
|
16
16
|
}
|
|
17
17
|
return bounds;
|
|
18
18
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { localPosition } from './localPosition.js';
|
|
2
2
|
|
|
3
|
-
export function localPixel(state, point) {
|
|
4
|
-
|
|
3
|
+
export function localPixel(state, point) {
|
|
4
|
+
if (state.pixelProjection) {
|
|
5
|
+
const { transformation, scale, origin, metres } = state.pixelProjection;
|
|
6
|
+
const projected = transformation.untransform(point, scale);
|
|
7
|
+
return /* alloc */ [(projected.x - origin.x) * metres, 0, -(projected.y - origin.y) * metres];
|
|
8
|
+
}
|
|
9
|
+
return localPosition(state, state.map.unproject(point));
|
|
5
10
|
}
|
|
@@ -2,6 +2,8 @@ import { geometryPixelStates } from '../globals/geometryPixelStates.js';
|
|
|
2
2
|
|
|
3
3
|
import { localPixel } from './localPixel.js';
|
|
4
4
|
|
|
5
|
-
export function localPixelForGeometry(point) {
|
|
6
|
-
|
|
5
|
+
export function localPixelForGeometry(point, anchor) {
|
|
6
|
+
const state = geometryPixelStates[geometryPixelStates.length - 1];
|
|
7
|
+
if (anchor && state.strokeAnchors) state.strokeAnchors.push(...localPixel(state, anchor));
|
|
8
|
+
return localPixel(state, point);
|
|
7
9
|
}
|