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.
Files changed (241) hide show
  1. package/README.md +10 -5
  2. package/dist/leaflet-city-mapper-src.js +7059 -6566
  3. package/dist/leaflet-city-mapper-src.js.map +4 -4
  4. package/dist/leaflet-city-mapper-worker-src.js +2766 -0
  5. package/dist/leaflet-city-mapper-worker-src.js.map +4 -4
  6. package/dist/leaflet-city-mapper-worker.js +1 -1
  7. package/dist/leaflet-city-mapper-worker.js.map +4 -4
  8. package/dist/leaflet-city-mapper.js +5 -3
  9. package/dist/leaflet-city-mapper.js.map +4 -4
  10. package/libs/leaflet.js +1 -1
  11. package/package.json +1 -1
  12. package/src/camera/setBearing.js +5 -0
  13. package/src/camera/setPitch.js +5 -0
  14. package/src/cog/initCog.js +2 -2
  15. package/src/core/gridlayerGetTiledPixelBounds.js +37 -4
  16. package/src/core/markerSetPos.js +1 -1
  17. package/src/core/popupGetEvents.js +1 -1
  18. package/src/core/popupUpdatePosition.js +8 -8
  19. package/src/core/tooltipGetEvents.js +1 -1
  20. package/src/core/tooltipSetPosition.js +2 -2
  21. package/src/geometry/appendNativeTriangle.js +2 -2
  22. package/src/geometry/createModelGeometry.js +2 -9
  23. package/src/geometry/dashedSegment.js +10 -5
  24. package/src/geometry/disk.js +1 -1
  25. package/src/geometry/fillNativePolygon.js +20 -0
  26. package/src/geometry/lineJoin.js +2 -2
  27. package/src/geometry/markerQuadCorners.js +6 -0
  28. package/src/geometry/nativeGeometry.js +1 -1
  29. package/src/geometry/polygon.js +4 -10
  30. package/src/geometry/segment.js +4 -3
  31. package/src/globals/colorTexture.js +6 -0
  32. package/src/globals/depthTexture.js +1 -0
  33. package/src/globals/drawMeshEntry.js +1 -1
  34. package/src/globals/meshPipeline.js +1 -0
  35. package/src/globals/mvtTextDecoder.js +1 -0
  36. package/src/globals/nativeScalableStyleKeys.js +1 -0
  37. package/src/globals/scenePass.js +1 -0
  38. package/src/globals/vectorStyleNamedColors.js +8 -0
  39. package/src/globals/vectorTileEvents.js +1 -0
  40. package/src/globals/workerCogSource.js +1 -0
  41. package/src/gpu/mountRenderer.js +4 -11
  42. package/src/gpu/releaseRenderer.js +1 -0
  43. package/src/index.js +6 -12
  44. package/src/materials/createProgramUniforms.js +1 -0
  45. package/src/models/loadModel.js +6 -10
  46. package/src/models/loadModelResources.js +2 -8
  47. package/src/models/modelNode.js +3 -7
  48. package/src/models/prepareModel.js +19 -0
  49. package/src/models/prepareModelGeometry.js +25 -0
  50. package/src/models/prepareModelPrimitive.js +17 -0
  51. package/src/mvt/addMvtCrossings.js +17 -0
  52. package/src/mvt/appendMvtBandTriangles.js +31 -0
  53. package/src/mvt/appendMvtCoordinates.js +11 -0
  54. package/src/mvt/appendMvtPolygonTriangles.js +19 -0
  55. package/src/mvt/beginMvtPath.js +9 -0
  56. package/src/mvt/closeMvtPath.js +7 -0
  57. package/src/mvt/collectMvtEdges.js +19 -0
  58. package/src/mvt/createMvtReader.js +7 -0
  59. package/src/mvt/decodeVectorTile.js +32 -0
  60. package/src/mvt/expectMvtWire.js +3 -0
  61. package/src/mvt/finishMvtPath.js +5 -0
  62. package/src/mvt/finiteMvtCoordinate.js +7 -0
  63. package/src/mvt/groupMvtPolygons.js +25 -0
  64. package/src/mvt/isMvtFallbackError.js +6 -0
  65. package/src/mvt/mergeMvtActiveEdges.js +9 -0
  66. package/src/mvt/mvtEdgeX.js +4 -0
  67. package/src/mvt/mvtPathsVertices.js +8 -0
  68. package/src/mvt/mvtPolygonPaths.js +12 -0
  69. package/src/mvt/numericMvtValue.js +4 -0
  70. package/src/mvt/readMvtFeature.js +34 -0
  71. package/src/mvt/readMvtField.js +8 -0
  72. package/src/mvt/readMvtGeometry.js +29 -0
  73. package/src/mvt/readMvtInteger.js +12 -0
  74. package/src/mvt/readMvtKnownValue.js +21 -0
  75. package/src/mvt/readMvtLayer.js +31 -0
  76. package/src/mvt/readMvtMessage.js +10 -0
  77. package/src/mvt/readMvtNumber.js +9 -0
  78. package/src/mvt/readMvtNumbers.js +11 -0
  79. package/src/mvt/readMvtString.js +6 -0
  80. package/src/mvt/readMvtValue.js +19 -0
  81. package/src/mvt/skipMvtField.js +14 -0
  82. package/src/mvt/sortMvtActiveEdges.js +15 -0
  83. package/src/mvt/sortedMvtLevels.js +22 -0
  84. package/src/mvt/takeMvtBytes.js +8 -0
  85. package/src/mvt/tessellateVectorRings.js +19 -0
  86. package/src/mvt/triangulateVectorRings.js +19 -0
  87. package/src/native/beforeNativeRender.js +6 -0
  88. package/src/native/canScaleNativeStyle.js +17 -0
  89. package/src/native/createNativeMesh.js +31 -0
  90. package/src/native/disposeNativeLayer.js +1 -1
  91. package/src/native/getGridTerrainTile.js +34 -0
  92. package/src/native/gridTerrainElevation.js +30 -0
  93. package/src/native/loadGridTerrain.js +26 -0
  94. package/src/native/nativeLayer.js +2 -2
  95. package/src/native/nativeLayerMethod.js +5 -14
  96. package/src/native/nativeProgram.js +20 -0
  97. package/src/native/nativeVectorGeometry.js +23 -0
  98. package/src/native/orderNativeGridLayer.js +14 -0
  99. package/src/native/putNativeMesh.js +15 -21
  100. package/src/native/refreshNativeEvent.js +13 -2
  101. package/src/native/refreshNativeLayer.js +1 -0
  102. package/src/native/syncGridLayer.js +48 -3
  103. package/src/native/syncNativeStrokeAnchors.js +12 -0
  104. package/src/native/syncNativeStrokeZoom.js +29 -0
  105. package/src/native/syncVectorLayer.js +15 -13
  106. package/src/native/terrainGridMesh.js +34 -0
  107. package/src/native/updateNativeStrokeRadius.js +9 -0
  108. package/src/projections/displayContainerPoint.js +23 -3
  109. package/src/projections/groundBounds.js +2 -2
  110. package/src/projections/localPixel.js +7 -2
  111. package/src/projections/localPixelForGeometry.js +4 -2
  112. package/src/projections/projectCameraPoint.js +6 -5
  113. package/src/rendering/collectVisibleMesh.js +5 -2
  114. package/src/rendering/drawSceneMeshes.js +3 -1
  115. package/src/rendering/nativeStrokeExpansion.js +4 -0
  116. package/src/rendering/prepareMeshUniforms.js +2 -0
  117. package/src/rendering/resizeRenderer.js +9 -0
  118. package/src/scene/initializerFor.js +3 -5
  119. package/src/scene/layerInitialize.js +14 -12
  120. package/src/scene/resolveNextInitialization.js +1 -1
  121. package/src/shaders/materialShaders.js +1 -0
  122. package/src/shaders/materialVertexShader.js +7 -2
  123. package/src/shaders/nativeStrokeShader.js +6 -0
  124. package/src/sources/attachAreaMesh.js +5 -6
  125. package/src/sources/buildArea.js +4 -5
  126. package/src/sources/buildAreaFeature.js +3 -19
  127. package/src/sources/initVectorTiles.js +15 -0
  128. package/src/sources/isVectorTileSource.js +4 -0
  129. package/src/sources/readyVectorTiles.js +10 -0
  130. package/src/sources/sourceAreaContext.js +1 -6
  131. package/src/sunlight/createSun.js +0 -1
  132. package/src/terrain/initTerrain.js +7 -1
  133. package/src/terrain/loadTerrain.js +4 -1
  134. package/src/terrain/mapElevationOf.js +5 -1
  135. package/src/terrain/onTerrainAdd.js +11 -1
  136. package/src/terrain/onTerrainRemove.js +10 -1
  137. package/src/utils/yieldTask.js +5 -0
  138. package/src/vector-style/appendQuotedStyleCharacter.js +22 -0
  139. package/src/vector-style/arrayContainsRange.js +8 -0
  140. package/src/vector-style/evaluateBoolean.js +18 -0
  141. package/src/vector-style/evaluateCoalesceOrCase.js +21 -0
  142. package/src/vector-style/evaluateComparison.js +16 -0
  143. package/src/vector-style/evaluateIExpression.js +8 -0
  144. package/src/vector-style/evaluateInput.js +6 -0
  145. package/src/vector-style/evaluateInterpolate.js +27 -0
  146. package/src/vector-style/evaluateMatch.js +12 -0
  147. package/src/vector-style/evaluateMath.js +14 -0
  148. package/src/vector-style/evaluateMembership.js +18 -0
  149. package/src/vector-style/evaluateNegation.js +13 -0
  150. package/src/vector-style/evaluatePrimitive.js +9 -0
  151. package/src/vector-style/evaluateStep.js +11 -0
  152. package/src/vector-style/evaluateStyle.js +33 -0
  153. package/src/vector-style/evaluateToExpression.js +14 -0
  154. package/src/vector-style/fillVectorPaint.js +17 -0
  155. package/src/vector-style/lineVectorPaint.js +21 -0
  156. package/src/vector-style/parseFunctionalColor.js +14 -0
  157. package/src/vector-style/parseHexColor.js +13 -0
  158. package/src/vector-style/parseVectorStyle.js +13 -0
  159. package/src/vector-style/readPaintValue.js +6 -0
  160. package/src/vector-style/removeTrailingCommas.js +12 -0
  161. package/src/vector-style/scaleDashArray.js +13 -0
  162. package/src/vector-style/skipStyleComment.js +9 -0
  163. package/src/vector-style/stripStyleComments.js +21 -0
  164. package/src/vector-style/styleColor.js +11 -0
  165. package/src/vector-style/validateVectorLayers.js +10 -0
  166. package/src/vector-style/vectorPaint.js +8 -0
  167. package/src/vector-style/visibleStyle.js +7 -0
  168. package/src/vector-tiles/appendVectorBatch.js +22 -0
  169. package/src/vector-tiles/attachVectorTileBatch.js +17 -0
  170. package/src/vector-tiles/attachVectorTileBatches.js +15 -0
  171. package/src/vector-tiles/compareVectorLabelPriority.js +3 -0
  172. package/src/vector-tiles/compareVectorTileDistance.js +3 -0
  173. package/src/vector-tiles/configureVectorTileLayer.js +28 -0
  174. package/src/vector-tiles/forwardVectorTileError.js +5 -0
  175. package/src/vector-tiles/loadVectorSprite.js +5 -0
  176. package/src/vector-tiles/loadVectorTile.js +36 -0
  177. package/src/vector-tiles/onVectorTileAdd.js +39 -0
  178. package/src/vector-tiles/onVectorTileMessage.js +10 -0
  179. package/src/vector-tiles/onVectorTileRemove.js +20 -0
  180. package/src/vector-tiles/onVectorTileWorkerError.js +11 -0
  181. package/src/vector-tiles/paintVectorTileBatch.js +12 -0
  182. package/src/vector-tiles/prepareVectorLabel.js +43 -0
  183. package/src/vector-tiles/prepareVectorStyleLayer.js +30 -0
  184. package/src/vector-tiles/prepareVectorTile.js +16 -0
  185. package/src/vector-tiles/projectVectorPaths.js +15 -0
  186. package/src/vector-tiles/projectVectorPoint.js +6 -0
  187. package/src/vector-tiles/projectVectorTriangles.js +18 -0
  188. package/src/vector-tiles/pruneVectorTiles.js +11 -0
  189. package/src/vector-tiles/pumpVectorTiles.js +18 -0
  190. package/src/vector-tiles/readTileJSON.js +17 -0
  191. package/src/vector-tiles/readVectorStyle.js +17 -0
  192. package/src/vector-tiles/refreshVectorTiles.js +5 -0
  193. package/src/vector-tiles/reserveVectorLabelCells.js +6 -0
  194. package/src/vector-tiles/retireVectorTileGroup.js +13 -0
  195. package/src/vector-tiles/revokeVectorWorkerUrl.js +9 -0
  196. package/src/vector-tiles/rotateVectorLabel.js +12 -0
  197. package/src/vector-tiles/rotateVectorLabels.js +6 -0
  198. package/src/vector-tiles/simplifyVectorPath.js +21 -0
  199. package/src/vector-tiles/updateVectorLabelMarker.js +27 -0
  200. package/src/vector-tiles/updateVectorTileLabels.js +28 -0
  201. package/src/vector-tiles/updateVectorTilePaint.js +20 -0
  202. package/src/vector-tiles/updateVectorTiles.js +29 -0
  203. package/src/vector-tiles/validateVectorTileZooms.js +6 -0
  204. package/src/vector-tiles/vectorFeaturePaint.js +15 -0
  205. package/src/vector-tiles/vectorFeaturePaths.js +16 -0
  206. package/src/vector-tiles/vectorFeatureZoom.js +8 -0
  207. package/src/vector-tiles/vectorLabelAnchors.js +24 -0
  208. package/src/vector-tiles/vectorLabelCandidates.js +11 -0
  209. package/src/vector-tiles/vectorLabelCells.js +26 -0
  210. package/src/vector-tiles/vectorLabelIcon.js +30 -0
  211. package/src/vector-tiles/vectorLabelProperty.js +3 -0
  212. package/src/vector-tiles/vectorSpriteIcon.js +11 -0
  213. package/src/vector-tiles/vectorStraightRun.js +14 -0
  214. package/src/vector-tiles/vectorStyleDependencies.js +15 -0
  215. package/src/vector-tiles/vectorStyleValue.js +5 -0
  216. package/src/vector-tiles/vectorStyleZoom.js +6 -0
  217. package/src/vector-tiles/vectorTileAwaited.js +9 -0
  218. package/src/vector-tiles/vectorTileOverlaps.js +4 -0
  219. package/src/vector-tiles/vectorTilePaint.js +10 -0
  220. package/src/vector-tiles/vectorTileSettings.js +17 -0
  221. package/src/vector-tiles/vectorTilesIdle.js +3 -0
  222. package/src/vector-tiles/vectorTolerance.js +4 -0
  223. package/src/vector-tiles/wrapVectorLabel.js +11 -0
  224. package/src/weakmaps/nativeProgramsByRenderer.js +1 -0
  225. package/src/weakmaps/streamTerrainByLayer.js +1 -0
  226. package/src/weakmaps/streamTerrainByMap.js +1 -0
  227. package/src/weakmaps/vectorTileOptionsByLayer.js +1 -0
  228. package/src/weakmaps/vectorWorkerByLayer.js +1 -0
  229. package/src/weakmaps/workerMapByLayer.js +1 -0
  230. package/src/workers/buildAreaInWorker.js +3 -27
  231. package/src/workers/cogWorker.js +21 -0
  232. package/src/workers/createGeometryWorker.js +1 -0
  233. package/src/workers/geometryWorker.js +15 -0
  234. package/src/workers/getCogInWorker.js +7 -0
  235. package/src/workers/modelWorker.js +10 -0
  236. package/src/workers/openCogInWorker.js +14 -0
  237. package/src/workers/runSourceWorker.js +32 -0
  238. package/src/workers/settleGeometryWorker.js +1 -1
  239. package/src/workers/vectorTileWorker.js +10 -0
  240. package/src/geometry/buildExtrudedPolygon.js +0 -10
  241. package/src/sources/buildAreaPoint.js +0 -7
@@ -0,0 +1,43 @@
1
+ import { evaluateStyle } from '../vector-style/evaluateStyle.js';
2
+ import { projectVectorPoint } from './projectVectorPoint.js';
3
+ import { vectorLabelProperty } from './vectorLabelProperty.js';
4
+ import { vectorStyleValue } from './vectorStyleValue.js';
5
+ import { vectorLabelAnchors } from './vectorLabelAnchors.js';
6
+
7
+ export function prepareVectorLabel(job, layer, entry, feature, order) {
8
+ let text = entry.layout?.['text-field'];
9
+ const { properties } = feature, { zoom } = job;
10
+ const icon = entry.layout?.['symbol-placement'] === 'line' ? null
11
+ : evaluateStyle(entry.layout?.['icon-image'], properties, zoom);
12
+ if (Array.isArray(text)) text = evaluateStyle(text, properties, zoom);
13
+ if (typeof text !== 'string') text = '';
14
+ text = text.replace(/\{([^}]+)\}/g, vectorLabelProperty.bind(null, properties));
15
+ if (!text.trim() && typeof icon !== 'string') return;
16
+ if (entry.layout?.['text-transform'] === 'uppercase') text = text.toUpperCase();
17
+ const size = vectorStyleValue(entry.layout, 'text-size', 12, properties, zoom), line = feature.type === 2 && text.trim();
18
+ const spacing = layer.extent / 16, anchors = /* alloc */ [];
19
+ let path, anchor;
20
+ for (path of line ? feature.geometry : feature.geometry.slice(0, 1)) {
21
+ if (!path?.length) continue;
22
+ if (!line) anchors.push(/* alloc */ { point: path[Math.floor(path.length / 2)], a: null });
23
+ else for (anchor of vectorLabelAnchors(path, spacing)) anchors.push(anchor);
24
+ }
25
+ for (anchor of anchors) {
26
+ if (anchor.point[0] < 0 || anchor.point[0] >= layer.extent || anchor.point[1] < 0 || anchor.point[1] >= layer.extent) continue;
27
+ job.labels.push(/* alloc */ { text, latlng: projectVectorPoint(anchor.point, job.coords, layer.extent),
28
+ order, entry, properties, size, pixelBase: anchor.length * 256 / layer.extent / 2 ** job.coords.z,
29
+ along: anchor.a ? /* alloc */ [
30
+ projectVectorPoint(anchor.a, job.coords, layer.extent),
31
+ projectVectorPoint(anchor.b, job.coords, layer.extent),
32
+ ] : null,
33
+ icon: text.trim() ? null : icon,
34
+ iconOffset: evaluateStyle(entry.layout?.['icon-offset'], properties, zoom) || /* alloc */ [0, 0],
35
+ allowOverlap: entry.layout?.['icon-allow-overlap'] === true,
36
+ color: vectorStyleValue(entry.paint, 'text-color', '#000', properties, zoom),
37
+ halo: vectorStyleValue(entry.paint, 'text-halo-color', '#fff', properties, zoom),
38
+ haloWidth: vectorStyleValue(entry.paint, 'text-halo-width', 0, properties, zoom),
39
+ priority: /* alloc */ ['place_labels', 'place'].includes(entry['source-layer']) ? 0
40
+ : /* alloc */ ['street_labels', 'transportation_name'].includes(entry['source-layer']) ? 1 : 2,
41
+ });
42
+ }
43
+ }
@@ -0,0 +1,30 @@
1
+ import { vectorStyleDependencies } from './vectorStyleDependencies.js';
2
+ import { vectorFeatureZoom } from './vectorFeatureZoom.js';
3
+ import { prepareVectorLabel } from './prepareVectorLabel.js';
4
+ import { vectorFeaturePaint } from './vectorFeaturePaint.js';
5
+ import { vectorPaint } from '../vector-style/vectorPaint.js';
6
+ import { appendVectorBatch } from './appendVectorBatch.js';
7
+
8
+ export function prepareVectorStyleLayer(job, layer, entry, order) {
9
+ const batches = /* alloc */ new Map(), dependencies = vectorStyleDependencies(entry);
10
+ const outlineColor = entry.type === 'fill' ? entry.paint?.['fill-outline-color'] : null;
11
+ const outline = outlineColor ? /* alloc */ { ...entry, type: 'line',
12
+ paint: /* alloc */ { 'line-color': outlineColor, 'line-width': 1 } } : null;
13
+ let feature, sampleZoom, paint, batch;
14
+ for (feature of layer.features) {
15
+ sampleZoom = vectorFeatureZoom(entry, feature.properties, job.zoom, job.maxZoom);
16
+ if (sampleZoom < 0) continue;
17
+ if (entry.type === 'symbol') {
18
+ prepareVectorLabel(job, layer, entry, feature, order);
19
+ continue;
20
+ }
21
+ paint = vectorFeaturePaint(entry, feature, sampleZoom, job.maxZoom);
22
+ if (!paint) continue;
23
+ appendVectorBatch(job, layer, entry, feature, order, batches, dependencies, paint);
24
+ if (outline && feature.type === 3) {
25
+ appendVectorBatch(job, layer, outline, feature, order, batches, dependencies,
26
+ vectorPaint(outline, feature.properties, sampleZoom));
27
+ }
28
+ }
29
+ for (batch of batches.values()) if (batch.paths.length) job.output.push(batch);
30
+ }
@@ -0,0 +1,16 @@
1
+ import { decodeVectorTile } from '../mvt/decodeVectorTile.js';
2
+ import { prepareVectorStyleLayer } from './prepareVectorStyleLayer.js';
3
+
4
+ export function prepareVectorTile(buffer, coords, style, zoom, source, maxZoom = 19, mapZoom = zoom) {
5
+ const layers = decodeVectorTile(buffer), byName = /* alloc */ new Map();
6
+ const job = /* alloc */ { coords, zoom, mapZoom, maxZoom, output: /* alloc */ [], labels: /* alloc */ [],
7
+ triangles: /* alloc */ new WeakMap(), projected: /* alloc */ new WeakMap() };
8
+ let layer, order, entry;
9
+ for (layer of layers) byName.set(layer.name, layer);
10
+ for ([order, entry] of style.entries()) {
11
+ layer = byName.get(entry['source-layer']);
12
+ if (!layer || source !== undefined && entry.source !== source) continue;
13
+ prepareVectorStyleLayer(job, layer, entry, order);
14
+ }
15
+ return /* alloc */ { batches: job.output, labels: job.labels };
16
+ }
@@ -0,0 +1,15 @@
1
+ import { projectVectorPoint } from './projectVectorPoint.js';
2
+ import { simplifyVectorPath } from './simplifyVectorPath.js';
3
+
4
+ export function projectVectorPaths(geometry, coords, extent, tolerance) {
5
+ const paths = /* alloc */ [];
6
+ let path, simplified, projected, point;
7
+ for (path of geometry) {
8
+ simplified = simplifyVectorPath(path, tolerance);
9
+ if (simplified.length < 3 && Math.hypot(simplified.at(-1)[0] - simplified[0][0], simplified.at(-1)[1] - simplified[0][1]) < tolerance * 2) continue;
10
+ projected = /* alloc */ [];
11
+ for (point of simplified) projected.push(projectVectorPoint(point, coords, extent));
12
+ paths.push(projected);
13
+ }
14
+ return paths;
15
+ }
@@ -0,0 +1,6 @@
1
+ export function projectVectorPoint(point, coords, extent) {
2
+ const size = 2 ** coords.z;
3
+ const x = (coords.x + point[0] / extent) / size;
4
+ const y = (coords.y + point[1] / extent) / size;
5
+ return /* alloc */ [Math.atan(Math.sinh(Math.PI * (1 - 2 * y))) * 180 / Math.PI, x * 360 - 180];
6
+ }
@@ -0,0 +1,18 @@
1
+ import { triangulateVectorRings } from '../mvt/triangulateVectorRings.js';
2
+ import { projectVectorPoint } from './projectVectorPoint.js';
3
+ import { simplifyVectorPath } from './simplifyVectorPath.js';
4
+
5
+ export function projectVectorTriangles(geometry, coords, extent, tolerance) {
6
+ const paths = /* alloc */ [], rings = /* alloc */ [];
7
+ let triangle, projected, point, ring;
8
+ for (ring of geometry) {
9
+ ring = simplifyVectorPath(ring, tolerance);
10
+ if (ring.length >= 4) rings.push(ring);
11
+ }
12
+ for (triangle of triangulateVectorRings(rings)) {
13
+ projected = /* alloc */ [];
14
+ for (point of triangle) projected.push(projectVectorPoint(point, coords, extent));
15
+ paths.push(/* alloc */ [projected]);
16
+ }
17
+ return paths;
18
+ }
@@ -0,0 +1,11 @@
1
+ import { reportError } from '../scene/reportLayerError.js';
2
+ import { vectorTileAwaited } from './vectorTileAwaited.js';
3
+
4
+ export function pruneVectorTiles() {
5
+ let tile, key;
6
+ for ([key, tile] of this.tiles) {
7
+ if (tile.needed || tile.group && vectorTileAwaited(this, tile)) continue;
8
+ tile.controller.abort(); this.tiles.delete(key);
9
+ if (tile.group) this.retire(tile.group).catch(reportError.bind(null, this));
10
+ }
11
+ }
@@ -0,0 +1,18 @@
1
+ import { compareVectorTileDistance } from './compareVectorTileDistance.js';
2
+
3
+ export function pumpVectorTiles() {
4
+ if (!this.session) return;
5
+ const center = this._map.getCenter(), pending = /* alloc */ [];
6
+ let tile, point;
7
+ for (tile of this.tiles.values()) {
8
+ if (!tile.needed || tile.started) continue;
9
+ point = this._map.project(center, tile.coords.z).divideBy(256);
10
+ tile.distance = (tile.coords.x - point.x) ** 2 + (tile.coords.y - point.y) ** 2;
11
+ pending.push(tile);
12
+ }
13
+ pending.sort(compareVectorTileDistance);
14
+ for (tile of pending) {
15
+ if (this.inflight >= 4) break;
16
+ tile.started = true; this.inflight++; this.load(tile);
17
+ }
18
+ }
@@ -0,0 +1,17 @@
1
+ export async function readTileJSON(options) {
2
+ const url = /* alloc */ new URL(options.tileJSON, document.baseURI).href;
3
+ const response = await fetch(url);
4
+ if (!response.ok) throw /* alloc */ new Error(`TileJSON: HTTP ${response.status}`);
5
+ const metadata = await response.json();
6
+ if (!metadata || !Array.isArray(metadata.tiles) || !metadata.tiles.length ||
7
+ typeof metadata.tiles[0] !== 'string') {
8
+ throw /* alloc */ new Error('TileJSON requires a tile URL template');
9
+ }
10
+ return /* alloc */ {
11
+ ...options,
12
+ url: /* alloc */ new URL(metadata.tiles[0], url).href,
13
+ minNativeZoom: options.minNativeZoom ?? metadata.minzoom,
14
+ maxNativeZoom: options.maxNativeZoom ?? metadata.maxzoom,
15
+ attribution: options.attribution ?? metadata.attribution,
16
+ };
17
+ }
@@ -0,0 +1,17 @@
1
+ import { parseVectorStyle } from '../vector-style/parseVectorStyle.js';
2
+
3
+ export async function readVectorStyle(style) {
4
+ if (typeof style === 'string') {
5
+ const response = await fetch(style);
6
+ if (!response.ok) throw /* alloc */ new Error(`Vector style: HTTP ${response.status}`);
7
+ style = parseVectorStyle(await response.text());
8
+ } else style = style?.layers ?? style;
9
+ if (!Array.isArray(style)) throw /* alloc */ new Error('Invalid vector style layers');
10
+ let entry;
11
+ for (entry of style) {
12
+ if (!entry || typeof entry.id !== 'string' || typeof entry.type !== 'string') {
13
+ throw /* alloc */ new Error('Invalid vector style layers');
14
+ }
15
+ }
16
+ return style;
17
+ }
@@ -0,0 +1,5 @@
1
+ export function refreshVectorTiles() {
2
+ clearTimeout(this.timer);
3
+ this.changedAt = performance.now();
4
+ this.timer = setTimeout(this.update.bind(this), 180);
5
+ }
@@ -0,0 +1,6 @@
1
+ export function reserveVectorLabelCells(cells, occupied) {
2
+ let cell;
3
+ for (cell of cells) if (occupied.has(cell)) return false;
4
+ for (cell of cells) occupied.add(cell);
5
+ return true;
6
+ }
@@ -0,0 +1,13 @@
1
+ import { yieldTask } from '../utils/yieldTask.js';
2
+
3
+ export async function retireVectorTileGroup(group) {
4
+ const session = this.session;
5
+ this.retiring.add(group);
6
+ let removed = 0, layer;
7
+ for (layer of group.getLayers()) {
8
+ if (this.session !== session) return;
9
+ group.removeLayer(layer);
10
+ if (++removed % 8 === 0) await yieldTask();
11
+ }
12
+ group.remove(); this.retiring.delete(group);
13
+ }
@@ -0,0 +1,9 @@
1
+ import { vectorWorkerByLayer } from '../weakmaps/vectorWorkerByLayer.js';
2
+
3
+ export function revokeVectorWorkerUrl(layer) {
4
+ const entry = vectorWorkerByLayer.get(layer);
5
+ if (entry?.blobUrl) {
6
+ URL.revokeObjectURL(entry.blobUrl);
7
+ entry.blobUrl = null;
8
+ }
9
+ }
@@ -0,0 +1,12 @@
1
+ import { radians } from '../globals/radians.js';
2
+ import { markerSetRotation } from '../core/markerSetRotation.js';
3
+
4
+ export function rotateVectorLabel(map, marker, label) {
5
+ if (!label.along) return;
6
+ const a = map.latLngToContainerPoint(label.along[0]), b = map.latLngToContainerPoint(label.along[1]);
7
+ let angle = Math.atan2(b.y - a.y, b.x - a.x) / radians;
8
+ if (angle > 90) angle -= 180;
9
+ else if (angle < -90) angle += 180;
10
+ if (marker.options.rotation === angle * radians) return;
11
+ markerSetRotation(marker, angle * radians);
12
+ }
@@ -0,0 +1,6 @@
1
+ import { rotateVectorLabel } from './rotateVectorLabel.js';
2
+
3
+ export function rotateVectorLabels() {
4
+ let marker;
5
+ for (marker of this.labels.values()) if (marker._mvtLabel) rotateVectorLabel(this._map, marker, marker._mvtLabel);
6
+ }
@@ -0,0 +1,21 @@
1
+ export function simplifyVectorPath(path, tolerance) {
2
+ if (path.length < 3) return path;
3
+ const keep = /* alloc */ new Uint8Array(path.length);
4
+ const stack = /* alloc */ [/* alloc */ [0, path.length - 1]], output = /* alloc */ [];
5
+ keep[0] = keep[path.length - 1] = 1;
6
+ let start, end, a, b, dx, dy, length, index, distance, i, p, t, squared;
7
+ while (stack.length) {
8
+ [start, end] = stack.pop(); a = path[start]; b = path[end];
9
+ dx = b[0] - a[0]; dy = b[1] - a[1]; length = dx * dx + dy * dy;
10
+ index = -1; distance = tolerance * tolerance;
11
+ for (i = start + 1; i < end; i++) {
12
+ p = path[i];
13
+ t = length ? Math.max(0, Math.min(1, ((p[0] - a[0]) * dx + (p[1] - a[1]) * dy) / length)) : 0;
14
+ squared = (p[0] - a[0] - t * dx) ** 2 + (p[1] - a[1] - t * dy) ** 2;
15
+ if (squared > distance) { distance = squared; index = i; }
16
+ }
17
+ if (index >= 0) { keep[index] = 1; stack.push(/* alloc */ [start, index], /* alloc */ [index, end]); }
18
+ }
19
+ for (i = 0; i < path.length; i++) if (keep[i]) output.push(path[i]);
20
+ return output;
21
+ }
@@ -0,0 +1,27 @@
1
+ import { L } from '../globals/L.js';
2
+ import { vectorTileOptionsByLayer } from '../weakmaps/vectorTileOptionsByLayer.js';
3
+ import { vectorLabelIcon } from './vectorLabelIcon.js';
4
+ import { rotateVectorLabel } from './rotateVectorLabel.js';
5
+ import { forwardVectorTileError } from './forwardVectorTileError.js';
6
+
7
+ export function updateVectorLabelMarker(owner, label, key) {
8
+ const appearance = JSON.stringify(/* alloc */ [label.size, label.color, label.halo, label.haloWidth, label.icon]);
9
+ const sheet = vectorTileOptionsByLayer.get(owner).spriteSheet;
10
+ let marker = owner.labels.get(key);
11
+ if (marker) {
12
+ marker._mvtLabel = label;
13
+ if (marker._mvtLabelStyle === appearance) { rotateVectorLabel(owner._map, marker, label); return false; }
14
+ marker.setIcon(vectorLabelIcon(label, sheet));
15
+ } else {
16
+ const { pane } = vectorTileOptionsByLayer.get(owner);
17
+ marker = /* alloc */ new L.Marker(label.latlng, /* alloc */ {
18
+ icon: vectorLabelIcon(label, sheet), pane: `${pane}-${label.order}`, title: label.text,
19
+ alt: label.text, interactive: false, keyboard: false, rotateWithView: false,
20
+ }).on('error', forwardVectorTileError, owner).addTo(owner._map);
21
+ owner.labels.set(key, marker);
22
+ }
23
+ marker._mvtLabelStyle = appearance;
24
+ marker._mvtLabel = label;
25
+ rotateVectorLabel(owner._map, marker, label);
26
+ return true;
27
+ }
@@ -0,0 +1,28 @@
1
+ import { vectorLabelCandidates } from './vectorLabelCandidates.js';
2
+ import { vectorLabelCells } from './vectorLabelCells.js';
3
+ import { reserveVectorLabelCells } from './reserveVectorLabelCells.js';
4
+ import { updateVectorLabelMarker } from './updateVectorLabelMarker.js';
5
+ import { vectorTilesIdle } from './vectorTilesIdle.js';
6
+ import { yieldTask } from '../utils/yieldTask.js';
7
+
8
+ export async function updateVectorTileLabels() {
9
+ const session = this.session, revision = this.labelRevision = (this.labelRevision || 0) + 1;
10
+ this.labelsReady = false;
11
+ const candidates = vectorLabelCandidates(this), size = this._map.getSize();
12
+ const occupied = /* alloc */ new Set(), retained = /* alloc */ new Set();
13
+ let visited = 0, label, key, cells, marker;
14
+ for (label of candidates) {
15
+ if (++visited % 128 === 0) await yieldTask();
16
+ if (!vectorTilesIdle(this, session) || this.labelRevision !== revision) return;
17
+ cells = vectorLabelCells(this, label, size);
18
+ if (!cells || !label.allowOverlap && !reserveVectorLabelCells(cells, occupied)) continue;
19
+ key = `${label.text}${label.icon || ''}:${label.latlng.join(':')}`;
20
+ retained.add(key);
21
+ if (updateVectorLabelMarker(this, label, key)) await yieldTask();
22
+ }
23
+ for ([key, marker] of this.labels) {
24
+ if (!vectorTilesIdle(this, session) || this.labelRevision !== revision) return;
25
+ if (!retained.has(key)) { marker.remove(); this.labels.delete(key); await yieldTask(); }
26
+ }
27
+ this.labelsReady = true;
28
+ }
@@ -0,0 +1,20 @@
1
+ import { paintVectorTileBatch } from './paintVectorTileBatch.js';
2
+ import { vectorStyleZoom } from './vectorStyleZoom.js';
3
+ import { vectorTilesIdle } from './vectorTilesIdle.js';
4
+ import { yieldTask } from '../utils/yieldTask.js';
5
+
6
+ export async function updateVectorTilePaint() {
7
+ const zoom = vectorStyleZoom(this), session = this.session;
8
+ if (this.paintZoom === zoom) return;
9
+ const revision = this.paintRevision = (this.paintRevision || 0) + 1;
10
+ let updated = 0, tile, batch;
11
+ for (tile of this.tiles.values()) {
12
+ if (!tile.rendered) continue;
13
+ for (batch of tile.rendered) {
14
+ if (!vectorTilesIdle(this, session) || this.paintRevision !== revision || vectorStyleZoom(this) !== zoom) return;
15
+ paintVectorTileBatch(batch, zoom);
16
+ if (++updated % 32 === 0) await yieldTask();
17
+ }
18
+ }
19
+ this.paintZoom = zoom;
20
+ }
@@ -0,0 +1,29 @@
1
+ import { vectorTileOptionsByLayer } from '../weakmaps/vectorTileOptionsByLayer.js';
2
+ import { vectorStyleZoom } from './vectorStyleZoom.js';
3
+ import { reportError } from '../scene/reportLayerError.js';
4
+
5
+ export function updateVectorTiles() {
6
+ if (!this.session) return;
7
+ const { minNativeZoom, maxNativeZoom } = vectorTileOptionsByLayer.get(this);
8
+ const z = Math.max(minNativeZoom, Math.min(maxNativeZoom, Math.floor(vectorStyleZoom(this))));
9
+ const bounds = this._map.getBounds(), count = 2 ** z;
10
+ const nw = this._map.project(bounds.getNorthWest(), z).divideBy(256);
11
+ const se = this._map.project(bounds.getSouthEast(), z).divideBy(256);
12
+ let tile, x, y, key;
13
+ for (tile of this.tiles.values()) tile.needed = false;
14
+ for (x = Math.floor(nw.x); x <= Math.floor(se.x); x++) {
15
+ for (y = Math.max(0, Math.floor(nw.y)); y <= Math.min(count - 1, Math.floor(se.y)); y++) {
16
+ key = `${z}/${x}/${y}`;
17
+ tile = this.tiles.get(key);
18
+ if (!tile) {
19
+ tile = /* alloc */ { key, coords: /* alloc */ { z, x, y }, controller: /* alloc */ new AbortController() };
20
+ this.tiles.set(key, tile);
21
+ }
22
+ tile.needed = true;
23
+ }
24
+ }
25
+ this.prune();
26
+ this.pump();
27
+ this.updatePaint().catch(reportError.bind(null, this));
28
+ this.updateLabels().catch(reportError.bind(null, this));
29
+ }
@@ -0,0 +1,6 @@
1
+ export function validateVectorTileZooms(minNativeZoom, maxNativeZoom, maxZoom) {
2
+ if (!Number.isInteger(minNativeZoom) || !Number.isInteger(maxNativeZoom) || !Number.isInteger(maxZoom) ||
3
+ minNativeZoom < 0 || maxNativeZoom < minNativeZoom || maxZoom < maxNativeZoom || maxZoom > 24) {
4
+ throw /* alloc */ new Error('Invalid vector tile zoom range');
5
+ }
6
+ }
@@ -0,0 +1,15 @@
1
+ import { vectorPaint } from '../vector-style/vectorPaint.js';
2
+ import { visibleStyle } from '../vector-style/visibleStyle.js';
3
+
4
+ export function vectorFeaturePaint(entry, feature, sampleZoom, maxZoom) {
5
+ if (entry.type === 'fill') return feature.type === 3 ? vectorPaint(entry, feature.properties, sampleZoom) : null;
6
+ if (entry.type !== 'line' || feature.type !== 2) return null;
7
+ let paint = vectorPaint(entry, feature.properties, sampleZoom), candidate;
8
+ if (paint.weight > 0 && paint.opacity > 0) return paint;
9
+ for (candidate = maxZoom; candidate >= 0; candidate--) {
10
+ if (!visibleStyle(entry, feature.properties, candidate)) continue;
11
+ paint = vectorPaint(entry, feature.properties, candidate);
12
+ if (paint.weight > 0 && paint.opacity > 0) return paint;
13
+ }
14
+ return null;
15
+ }
@@ -0,0 +1,16 @@
1
+ import { projectVectorTriangles } from './projectVectorTriangles.js';
2
+ import { projectVectorPaths } from './projectVectorPaths.js';
3
+ import { vectorTolerance } from './vectorTolerance.js';
4
+
5
+ export function vectorFeaturePaths(job, layer, entry, feature) {
6
+ const cache = entry.type === 'fill' ? job.triangles : job.projected;
7
+ let paths = cache.get(feature);
8
+ if (!paths) {
9
+ const tolerance = vectorTolerance(job, layer);
10
+ paths = entry.type === 'fill'
11
+ ? projectVectorTriangles(feature.geometry, job.coords, layer.extent, tolerance)
12
+ : projectVectorPaths(feature.geometry, job.coords, layer.extent, tolerance);
13
+ cache.set(feature, paths);
14
+ }
15
+ return paths;
16
+ }
@@ -0,0 +1,8 @@
1
+ import { visibleStyle } from '../vector-style/visibleStyle.js';
2
+
3
+ export function vectorFeatureZoom(entry, properties, zoom, maxZoom) {
4
+ if (visibleStyle(entry, properties, zoom)) return zoom;
5
+ zoom = maxZoom;
6
+ while (zoom >= 0 && !visibleStyle(entry, properties, zoom)) zoom--;
7
+ return zoom;
8
+ }
@@ -0,0 +1,24 @@
1
+ import { vectorStraightRun } from './vectorStraightRun.js';
2
+
3
+ /** Anchors evenly spread along a path: each is a point on a segment plus that segment's ends. */
4
+ export function vectorLabelAnchors(path, spacing) {
5
+ const anchors = /* alloc */ [];
6
+ let length = 0, i, walked, target, count, k, segment, t, point;
7
+ for (i = 1; i < path.length; i++) length += Math.hypot(path[i][0] - path[i - 1][0], path[i][1] - path[i - 1][1]);
8
+ count = Math.max(1, Math.floor(length / spacing));
9
+ i = 1; walked = 0;
10
+ for (k = 0; k < count; k++) {
11
+ target = (k + 0.5) * length / count;
12
+ while (i < path.length - 1 && walked + Math.hypot(path[i][0] - path[i - 1][0], path[i][1] - path[i - 1][1]) < target) {
13
+ walked += Math.hypot(path[i][0] - path[i - 1][0], path[i][1] - path[i - 1][1]); i++;
14
+ }
15
+ segment = Math.hypot(path[i][0] - path[i - 1][0], path[i][1] - path[i - 1][1]);
16
+ t = segment ? Math.min(1, Math.max(0, (target - walked) / segment)) : 0;
17
+ point = /* alloc */ [
18
+ path[i - 1][0] + (path[i][0] - path[i - 1][0]) * t, path[i - 1][1] + (path[i][1] - path[i - 1][1]) * t,
19
+ ];
20
+ anchors.push(/* alloc */ { point, a: path[i - 1], b: path[i],
21
+ length: vectorStraightRun(path, i, point, 1) + vectorStraightRun(path, i, point, -1) });
22
+ }
23
+ return anchors;
24
+ }
@@ -0,0 +1,11 @@
1
+ import { compareVectorLabelPriority } from './compareVectorLabelPriority.js';
2
+
3
+ export function vectorLabelCandidates(layer) {
4
+ const candidates = /* alloc */ [];
5
+ let tile, label;
6
+ for (tile of layer.tiles.values()) {
7
+ if (!tile.needed || !tile.labelCandidates) continue;
8
+ for (label of tile.labelCandidates) candidates.push(label);
9
+ }
10
+ return candidates.sort(compareVectorLabelPriority);
11
+ }
@@ -0,0 +1,26 @@
1
+ import { evaluateStyle } from '../vector-style/evaluateStyle.js';
2
+ import { vectorStyleZoom } from './vectorStyleZoom.js';
3
+ import { vectorTileOptionsByLayer } from '../weakmaps/vectorTileOptionsByLayer.js';
4
+ import { visibleStyle } from '../vector-style/visibleStyle.js';
5
+
6
+ export function vectorLabelCells(layer, label, size) {
7
+ const map = layer._map, zoom = vectorStyleZoom(layer);
8
+ if (!visibleStyle(label.entry, label.properties, zoom)) return null;
9
+ label.size = evaluateStyle(label.entry.layout?.['text-size'] ?? 12, label.properties, zoom);
10
+ if (!(label.size > 0)) return null;
11
+ if (label.icon && !vectorTileOptionsByLayer.get(layer).spriteSheet?.index[label.icon]) return null;
12
+ label.color = evaluateStyle(label.entry.paint?.['text-color'] ?? '#000', label.properties, zoom);
13
+ label.halo = evaluateStyle(label.entry.paint?.['text-halo-color'] ?? '#fff', label.properties, zoom);
14
+ label.haloWidth = evaluateStyle(label.entry.paint?.['text-halo-width'] ?? 0, label.properties, zoom);
15
+ if (label.along && label.pixelBase * 2 ** map.getZoom() < label.text.length * label.size * 0.6) return null;
16
+ const point = map.latLngToContainerPoint(label.latlng);
17
+ if (point.x < 0 || point.y < 0 || point.x > size.x || point.y > size.y) return null;
18
+ const width = label.text.length * label.size * 0.65 + 16, cells = /* alloc */ [];
19
+ let x, y;
20
+ for (x = Math.floor((point.x - width / 2) / 32); x <= Math.floor((point.x + width / 2) / 32); x++) {
21
+ for (y = Math.floor((point.y - label.size) / 24); y <= Math.floor((point.y + label.size) / 24); y++) {
22
+ cells.push(`${x}:${y}`);
23
+ }
24
+ }
25
+ return cells;
26
+ }
@@ -0,0 +1,30 @@
1
+ import { L } from '../globals/L.js';
2
+ import { vectorSpriteIcon } from './vectorSpriteIcon.js';
3
+ import { wrapVectorLabel } from './wrapVectorLabel.js';
4
+
5
+ export function vectorLabelIcon(label, sheet) {
6
+ if (label.icon) return vectorSpriteIcon(label, sheet);
7
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
8
+ const lines = label.along ? [label.text] : wrapVectorLabel(label.text);
9
+ let longest = 0, line, key, text, index;
10
+ for (line of lines) longest = Math.max(longest, Array.from(line).length);
11
+ const width = Math.max(40, longest * label.size * 0.65 + 12);
12
+ const lineHeight = label.size * 1.2, height = lines.length * lineHeight + 12;
13
+ svg.setAttribute('width', width); svg.setAttribute('height', height);
14
+ const attributes = /* alloc */ {
15
+ x: width / 2, 'text-anchor': 'middle',
16
+ 'font-family': 'sans-serif', 'font-size': label.size,
17
+ fill: label.color, stroke: label.halo, 'stroke-width': label.haloWidth * 2, 'paint-order': 'stroke',
18
+ };
19
+ for (index = 0; index < lines.length; index++) {
20
+ text = document.createElementNS(svg.namespaceURI, 'text');
21
+ for (key of Object.keys(attributes)) text.setAttribute(key, attributes[key]);
22
+ text.setAttribute('y', height / 2 + (index - (lines.length - 1) / 2) * lineHeight + label.size * 0.35);
23
+ text.textContent = lines[index];
24
+ svg.append(text);
25
+ }
26
+ return /* alloc */ new L.Icon(/* alloc */ {
27
+ iconUrl: `data:image/svg+xml;charset=utf-8,${encodeURIComponent((/* alloc */ new XMLSerializer()).serializeToString(svg))}`,
28
+ iconSize: /* alloc */ [width, height], iconAnchor: /* alloc */ [width / 2, height / 2],
29
+ });
30
+ }
@@ -0,0 +1,3 @@
1
+ export function vectorLabelProperty(properties, match, key) {
2
+ return properties[key] ?? '';
3
+ }
@@ -0,0 +1,11 @@
1
+ import { L } from '../globals/L.js';
2
+
3
+ export function vectorSpriteIcon(label, sheet) {
4
+ const { x, y, width, height } = sheet.index[label.icon], [dx, dy] = label.iconOffset;
5
+ return /* alloc */ new L.DivIcon(/* alloc */ {
6
+ className: '',
7
+ html: `<div style="width:${width}px;height:${height}px;background:url(${sheet.url}) -${x}px -${y}px"></div>`,
8
+ iconSize: /* alloc */ [width, height],
9
+ iconAnchor: /* alloc */ [width / 2 - dx, height / 2 - dy],
10
+ });
11
+ }
@@ -0,0 +1,14 @@
1
+ /** Distance from a point on segment (i-1, i) along the path until it turns more than ~45 degrees from that segment. */
2
+ export function vectorStraightRun(path, i, point, step) {
3
+ const base = Math.atan2(path[i][1] - path[i - 1][1], path[i][0] - path[i - 1][0]);
4
+ let j = step > 0 ? i : i - 1, previous = point, run = 0, next;
5
+ while (j >= 0 && j < path.length) {
6
+ run += Math.hypot(path[j][0] - previous[0], path[j][1] - previous[1]);
7
+ previous = path[j];
8
+ next = j + step;
9
+ if (next < 0 || next >= path.length) break;
10
+ if (Math.cos(Math.atan2(path[next][1] - path[j][1], path[next][0] - path[j][0]) - base + (step < 0 ? Math.PI : 0)) < 0.7) break;
11
+ j = next;
12
+ }
13
+ return run;
14
+ }
@@ -0,0 +1,15 @@
1
+ export function vectorStyleDependencies(entry) {
2
+ const dependencies = /* alloc */ new Set();
3
+ const expressions = /* alloc */ [entry.paint, entry.filter];
4
+ let value, child;
5
+ while (expressions.length) {
6
+ value = expressions.pop();
7
+ if (!value || typeof value !== 'object') continue;
8
+ if (Array.isArray(value) && typeof value[1] === 'string' &&
9
+ /* alloc */ ['get', 'has', '==', '!=', '<', '>', '<=', '>=', 'in', '!in'].includes(value[0])) {
10
+ dependencies.add(value[1]);
11
+ }
12
+ for (child of Object.values(value)) expressions.push(child);
13
+ }
14
+ return dependencies;
15
+ }
@@ -0,0 +1,5 @@
1
+ import { evaluateStyle } from '../vector-style/evaluateStyle.js';
2
+
3
+ export function vectorStyleValue(object, key, fallback, properties, zoom) {
4
+ return object?.[key] === undefined ? fallback : evaluateStyle(object[key], properties, zoom);
5
+ }
@@ -0,0 +1,6 @@
1
+ import { vectorTileOptionsByLayer } from '../weakmaps/vectorTileOptionsByLayer.js';
2
+
3
+ // Style zooms are authored for 512px tiles (MapLibre): `styleZoomOffset: -1` maps Leaflet's 256px zoom onto them.
4
+ export function vectorStyleZoom(layer) {
5
+ return layer._map.getZoom() + (vectorTileOptionsByLayer.get(layer).styleZoomOffset ?? 0);
6
+ }
@@ -0,0 +1,9 @@
1
+ import { vectorTileOverlaps } from './vectorTileOverlaps.js';
2
+
3
+ export function vectorTileAwaited(layer, stale) {
4
+ let tile;
5
+ for (tile of layer.tiles.values()) {
6
+ if (tile.needed && !tile.group && vectorTileOverlaps(tile.coords, stale.coords)) return true;
7
+ }
8
+ return false;
9
+ }
@@ -0,0 +1,4 @@
1
+ export function vectorTileOverlaps(a, b) {
2
+ const shift = a.z - b.z;
3
+ return shift >= 0 ? a.x >> shift === b.x && a.y >> shift === b.y : b.x >> -shift === a.x && b.y >> -shift === a.y;
4
+ }