leaflet-city-mapper 0.0.1 → 0.0.3

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 (629) hide show
  1. package/README.md +61 -13
  2. package/cucumber.mjs +4 -0
  3. package/dist/leaflet-city-mapper.js +3 -1
  4. package/dist/leaflet-city-mapper.js.map +4 -4
  5. package/package.json +3 -4
  6. package/src/archives/decodeDirectory.js +32 -0
  7. package/src/archives/decodeHeader.js +19 -0
  8. package/src/archives/decompress.js +5 -0
  9. package/src/archives/getHeader.js +9 -0
  10. package/src/archives/getZxy.js +75 -0
  11. package/src/archives/loadDirectory.js +7 -0
  12. package/src/archives/loadSource.js +17 -0
  13. package/src/archives/read.js +29 -0
  14. package/src/archives/tileId.js +19 -0
  15. package/src/archives/varint.js +15 -0
  16. package/src/camera/angles.js +6 -0
  17. package/src/camera/animationPoint.js +8 -0
  18. package/src/camera/cameraMapReady.js +8 -0
  19. package/src/camera/cancelCameraAnimation.js +11 -0
  20. package/src/camera/cleanupCameraMap.js +11 -0
  21. package/src/camera/constrainCameraToBounds.js +3 -0
  22. package/src/camera/displayPoint.js +3 -0
  23. package/src/camera/fitCameraBounds.js +48 -0
  24. package/src/camera/groundBounds.js +11 -0
  25. package/src/camera/initializeCameraMap.js +25 -0
  26. package/src/camera/mapAnimateCamera.js +17 -0
  27. package/src/camera/mapCamera.js +123 -0
  28. package/src/camera/mapContainerPointToLayerPoint.js +7 -0
  29. package/src/camera/mapGetBearing.js +1 -0
  30. package/src/camera/mapGetBounds.js +14 -0
  31. package/src/camera/mapGetBoundsCenterZoom.js +7 -0
  32. package/src/camera/mapGetBoundsZoom.js +14 -0
  33. package/src/camera/mapGetCenterLayerPoint.js +5 -0
  34. package/src/camera/mapGetPitch.js +1 -0
  35. package/src/camera/mapLayerPointToContainerPoint.js +7 -0
  36. package/src/camera/mapLimitCenter.js +12 -0
  37. package/src/camera/mapLimitOffset.js +10 -0
  38. package/src/camera/mapPanBy.js +9 -0
  39. package/src/camera/mapPanInside.js +14 -0
  40. package/src/camera/mapResetNorth.js +1 -0
  41. package/src/camera/mapResetNorthPitch.js +1 -0
  42. package/src/camera/mapSetBearing.js +1 -0
  43. package/src/camera/mapSetPitch.js +1 -0
  44. package/src/camera/mapSetPitchAndBearing.js +14 -0
  45. package/src/camera/mapSetZoomAround.js +11 -0
  46. package/src/camera/mapStopPitchBearingAnimation.js +6 -0
  47. package/src/camera/mapTryAnimatedPan.js +9 -0
  48. package/src/camera/mapUpdateCameraOverlays.js +7 -0
  49. package/src/camera/pointOf.js +3 -0
  50. package/src/camera/project.js +20 -0
  51. package/src/camera/runCameraAnimations.js +28 -0
  52. package/src/camera/scheduleCameraAnimation.js +8 -0
  53. package/src/camera/updateSky.js +16 -0
  54. package/src/camera/verticalGroundY.js +4 -0
  55. package/src/collision/collectMeshes.js +5 -0
  56. package/src/collision/collider.js +63 -0
  57. package/src/collision/horizontalRay.js +12 -0
  58. package/src/collision/intersectMeshes.js +133 -0
  59. package/src/collision/sortHits.js +23 -0
  60. package/src/constants/CELL.js +4 -0
  61. package/src/constants/Compass.js +7 -0
  62. package/src/constants/ContainerResize.js +7 -0
  63. package/src/constants/HEIGHT.js +1 -0
  64. package/src/constants/PitchDrag.js +7 -0
  65. package/src/constants/ShiftRotate.js +7 -0
  66. package/src/constants/TILE_RADIUS.js +1 -0
  67. package/src/constants/TILE_SIZE.js +1 -0
  68. package/src/constants/TouchMode.js +6 -0
  69. package/src/constants/accessorSizes.js +1 -0
  70. package/src/constants/accessorTypes.js +8 -0
  71. package/src/constants/attachState.js +1 -0
  72. package/src/constants/cameraControlsState.js +1 -0
  73. package/src/constants/cityMapper.js +6 -0
  74. package/src/constants/colliders.js +2 -0
  75. package/src/constants/dark.js +1 -0
  76. package/src/constants/elevationWGSL.js +27 -0
  77. package/src/constants/glass.js +1 -0
  78. package/src/constants/headlight.js +1 -0
  79. package/src/constants/hull.js +1 -0
  80. package/src/constants/indexState.js +1 -0
  81. package/src/constants/limbs.js +9 -0
  82. package/src/constants/mapCameraState.js +1 -0
  83. package/src/constants/moves.js +11 -0
  84. package/src/constants/nativeEventMaps.js +1 -0
  85. package/src/constants/nativeLayerState.js +1 -0
  86. package/src/constants/nativeMethodHandlers.js +31 -0
  87. package/src/constants/onMapChangeState.js +1 -0
  88. package/src/constants/onZoomAnimState.js +1 -0
  89. package/src/constants/paints.js +10 -0
  90. package/src/constants/parts.js +19 -0
  91. package/src/constants/pendingUpdates.js +1 -0
  92. package/src/constants/pumpState.js +1 -0
  93. package/src/constants/renderers.js +2 -0
  94. package/src/constants/ringDirections.js +10 -0
  95. package/src/constants/roundProfile.js +1 -0
  96. package/src/constants/shirt.js +1 -0
  97. package/src/constants/skin.js +2 -0
  98. package/src/constants/speed.js +3 -0
  99. package/src/constants/taillight.js +1 -0
  100. package/src/constants/trafficShader.js +49 -0
  101. package/src/constants/trousers.js +1 -0
  102. package/src/constants/tyre.js +1 -0
  103. package/src/constants/underEntryState.js +1 -0
  104. package/src/constants/vehicles.js +40 -0
  105. package/src/constants/white.js +1 -0
  106. package/src/controls/acceptPitchDrag.js +4 -0
  107. package/src/controls/acceptRotateDrag.js +3 -0
  108. package/src/controls/adjustCameraDrag.js +10 -0
  109. package/src/controls/cameraControls.js +60 -0
  110. package/src/controls/cameraDragClick.js +9 -0
  111. package/src/controls/cameraDragContextMenu.js +8 -0
  112. package/src/controls/cameraDragDown.js +20 -0
  113. package/src/controls/cameraDragEnd.js +6 -0
  114. package/src/controls/cameraDragMove.js +23 -0
  115. package/src/controls/changeCameraTouch.js +14 -0
  116. package/src/controls/cleanupCameraTouch.js +24 -0
  117. package/src/controls/compassAddHooks.js +15 -0
  118. package/src/controls/compassOrientation.js +6 -0
  119. package/src/controls/compassRemoveHooks.js +5 -0
  120. package/src/controls/containerResizeAddHooks.js +8 -0
  121. package/src/controls/containerResizeRemoveHooks.js +5 -0
  122. package/src/controls/dragCamera.js +22 -0
  123. package/src/controls/editable.js +3 -0
  124. package/src/controls/endAllCameraDrags.js +7 -0
  125. package/src/controls/endAllCameraTouches.js +7 -0
  126. package/src/controls/endCameraTouch.js +11 -0
  127. package/src/controls/endCameraTouchEvent.js +5 -0
  128. package/src/controls/finishCameraDrag.js +9 -0
  129. package/src/controls/finishCompassPermission.js +16 -0
  130. package/src/controls/loadCameraControls.js +9 -0
  131. package/src/controls/moveCameraTouch.js +22 -0
  132. package/src/controls/notifyCameraTouchChange.js +1 -0
  133. package/src/controls/pitchDragAddHooks.js +6 -0
  134. package/src/controls/pitchDragRemoveHooks.js +5 -0
  135. package/src/controls/refreshRotateControl.js +7 -0
  136. package/src/controls/refreshRotateFocus.js +5 -0
  137. package/src/controls/removeCameraDrag.js +23 -0
  138. package/src/controls/resizeMap.js +3 -0
  139. package/src/controls/rotateButtonClick.js +7 -0
  140. package/src/controls/rotateButtonKeydown.js +11 -0
  141. package/src/controls/rotateControl.js +3 -0
  142. package/src/controls/rotateOnAdd.js +38 -0
  143. package/src/controls/rotateOnRemove.js +6 -0
  144. package/src/controls/shiftRotateAddHooks.js +8 -0
  145. package/src/controls/shiftRotateRemoveHooks.js +5 -0
  146. package/src/controls/shiftRotateWheel.js +9 -0
  147. package/src/controls/startCameraTouch.js +23 -0
  148. package/src/core/addImageState.js +7 -0
  149. package/src/core/addRasterImage.js +10 -0
  150. package/src/core/adjustCameraMarkerPan.js +22 -0
  151. package/src/core/beforeNativeRender.js +10 -0
  152. package/src/core/boundsQuad.js +11 -0
  153. package/src/core/bringNativeLayerToBack.js +3 -0
  154. package/src/core/bringNativeLayerToFront.js +3 -0
  155. package/src/core/cameraCircleBounds.js +6 -0
  156. package/src/core/cameraMarkerDrag.js +18 -0
  157. package/src/core/cameraMarkerOnDrag.js +8 -0
  158. package/src/core/cancelGridFade.js +10 -0
  159. package/src/core/closestCameraLayerPoint.js +7 -0
  160. package/src/core/compareNativeHits.js +3 -0
  161. package/src/core/current.js +3 -0
  162. package/src/core/disposeNativeLayer.js +35 -0
  163. package/src/core/fireRasterLoad.js +5 -0
  164. package/src/core/forwardNativeError.js +3 -0
  165. package/src/core/gridlayerGetEvents.js +7 -0
  166. package/src/core/gridlayerGetTiledPixelBounds.js +8 -0
  167. package/src/core/handleNativeMapEvent.js +47 -0
  168. package/src/core/hideTargets.js +16 -0
  169. package/src/core/initNativeGPU.js +21 -0
  170. package/src/core/initializeGridContainer.js +6 -0
  171. package/src/core/initializeNativeLayer.js +42 -0
  172. package/src/core/localPixel.js +5 -0
  173. package/src/core/localPixelForGeometry.js +6 -0
  174. package/src/core/localPosition.js +6 -0
  175. package/src/core/markerCameraIconPoint.js +9 -0
  176. package/src/core/markerGetEvents.js +5 -0
  177. package/src/core/markerInitInteraction.js +8 -0
  178. package/src/core/markerQuadCorners.js +31 -0
  179. package/src/core/markerSetIcon.js +9 -0
  180. package/src/core/markerSetPos.js +14 -0
  181. package/src/core/markerSetRotation.js +7 -0
  182. package/src/core/markerUpdateZIndex.js +8 -0
  183. package/src/core/nativeAddLatLng.js +3 -0
  184. package/src/core/nativeBringToBack.js +3 -0
  185. package/src/core/nativeBringToFront.js +3 -0
  186. package/src/core/nativeEvents.js +26 -0
  187. package/src/core/nativeImageError.js +8 -0
  188. package/src/core/nativeImageRefresh.js +7 -0
  189. package/src/core/nativeLayer.js +97 -0
  190. package/src/core/nativeLayerMethod.js +21 -0
  191. package/src/core/nativeRedraw.js +3 -0
  192. package/src/core/nativeSetBounds.js +3 -0
  193. package/src/core/nativeSetIcon.js +3 -0
  194. package/src/core/nativeSetLatLng.js +3 -0
  195. package/src/core/nativeSetLatLngs.js +3 -0
  196. package/src/core/nativeSetOpacity.js +3 -0
  197. package/src/core/nativeSetRadius.js +3 -0
  198. package/src/core/nativeSetStyle.js +3 -0
  199. package/src/core/nativeSetUrl.js +3 -0
  200. package/src/core/nativeSetZIndex.js +3 -0
  201. package/src/core/nativeSetZIndexOffset.js +3 -0
  202. package/src/core/popupAdjustPan.js +23 -0
  203. package/src/core/popupGetEvents.js +5 -0
  204. package/src/core/popupUpdatePosition.js +14 -0
  205. package/src/core/putNativeMesh.js +33 -0
  206. package/src/core/quadNativeMesh.js +15 -0
  207. package/src/core/readyNativeGPU.js +6 -0
  208. package/src/core/refreshNativeEvent.js +5 -0
  209. package/src/core/refreshNativeLayer.js +29 -0
  210. package/src/core/refreshNativeLayerContract.js +3 -0
  211. package/src/core/rejectNativeReady.js +3 -0
  212. package/src/core/removeImageState.js +8 -0
  213. package/src/core/removeNativeEvents.js +16 -0
  214. package/src/core/removeTargets.js +8 -0
  215. package/src/core/reorderNativeLayer.js +6 -0
  216. package/src/core/resolveNativeReady.js +3 -0
  217. package/src/core/restoreNativeEvents.js +6 -0
  218. package/src/core/runGridFades.js +14 -0
  219. package/src/core/runMarkerPanFrame.js +12 -0
  220. package/src/core/scheduleGridFade.js +9 -0
  221. package/src/core/scheduleMarkerPan.js +8 -0
  222. package/src/core/styleNativeMesh.js +10 -0
  223. package/src/core/syncGridLayer.js +22 -0
  224. package/src/core/syncImageOverlay.js +9 -0
  225. package/src/core/syncMarker.js +12 -0
  226. package/src/core/syncVectorLayer.js +26 -0
  227. package/src/core/synchronizeNativeLayer.js +35 -0
  228. package/src/core/textureFor.js +48 -0
  229. package/src/core/tooltipGetEvents.js +5 -0
  230. package/src/core/tooltipSetPosition.js +8 -0
  231. package/src/core/updateGridOpacity.js +23 -0
  232. package/src/core/updateNativeLayerView.js +6 -0
  233. package/src/core/uploadCanvasTexture.js +19 -0
  234. package/src/geometry/addBridges.js +88 -0
  235. package/src/geometry/below.js +3 -0
  236. package/src/geometry/box.js +3 -0
  237. package/src/geometry/bridgeElevation.js +19 -0
  238. package/src/geometry/bridgeLocal.js +4 -0
  239. package/src/geometry/build.js +19 -0
  240. package/src/geometry/circleAt.js +5 -0
  241. package/src/geometry/clipLine.js +23 -0
  242. package/src/geometry/clipSegment.js +19 -0
  243. package/src/geometry/computeBounds.js +33 -0
  244. package/src/geometry/conformModelToTerrain.js +67 -0
  245. package/src/geometry/cross.js +3 -0
  246. package/src/geometry/disk.js +11 -0
  247. package/src/geometry/diskAt.js +4 -0
  248. package/src/geometry/dot.js +6 -0
  249. package/src/geometry/emitter.js +8 -0
  250. package/src/geometry/lampPostGeometry.js +24 -0
  251. package/src/geometry/lampRing.js +11 -0
  252. package/src/geometry/lightGeometry.js +15 -0
  253. package/src/geometry/line.js +54 -0
  254. package/src/geometry/nativeGeometry.js +55 -0
  255. package/src/geometry/nativeTriangle.js +3 -0
  256. package/src/geometry/polygon.js +22 -0
  257. package/src/geometry/push.js +3 -0
  258. package/src/geometry/quad.js +4 -0
  259. package/src/geometry/roofCoverage.js +52 -0
  260. package/src/geometry/samePoint.js +3 -0
  261. package/src/geometry/segment.js +21 -0
  262. package/src/geometry/setVertexColor.js +15 -0
  263. package/src/geometry/sub.js +6 -0
  264. package/src/geometry/surface.js +17 -0
  265. package/src/geometry/treeGeometry.js +31 -0
  266. package/src/geometry/treeRing.js +14 -0
  267. package/src/geometry/triangle.js +12 -0
  268. package/src/geometry/vertexNormals.js +32 -0
  269. package/src/geometry/visit.js +9 -0
  270. package/src/index.js +98 -65
  271. package/src/lighting/cacheLightGrid.js +23 -0
  272. package/src/lighting/collectLightMeshes.js +6 -0
  273. package/src/lighting/lightGrid.js +42 -0
  274. package/src/lighting/updatePointLights.js +34 -0
  275. package/src/lighting/visitCells.js +15 -0
  276. package/src/lighting/worldLights.js +27 -0
  277. package/src/models/decodeModel.js +45 -0
  278. package/src/models/hasUnsupportedPrimitives.js +10 -0
  279. package/src/models/loadBuffer.js +6 -0
  280. package/src/models/loadImage.js +15 -0
  281. package/src/models/loadModel.js +69 -0
  282. package/src/models/materialFor.js +21 -0
  283. package/src/models/modelNode.js +93 -0
  284. package/src/models/nodeMatrix.js +22 -0
  285. package/src/models/readAccessor.js +53 -0
  286. package/src/models/readAccessorValues.js +16 -0
  287. package/src/models/textureFor.js +35 -0
  288. package/src/models/textureSampler.js +10 -0
  289. package/src/picking/collectVisibleMesh.js +4 -0
  290. package/src/picking/findFeature.js +49 -0
  291. package/src/picking/hit.js +23 -0
  292. package/src/picking/hitMesh.js +30 -0
  293. package/src/picking/onClick.js +13 -0
  294. package/src/picking/onPointerLeave.js +11 -0
  295. package/src/picking/onPointerMove.js +15 -0
  296. package/src/picking/pointerClick.js +5 -0
  297. package/src/picking/pointerLeave.js +5 -0
  298. package/src/picking/pointerMove.js +5 -0
  299. package/src/picking/raycast.js +59 -0
  300. package/src/picking/setHighlight.js +13 -0
  301. package/src/picking/shouldSkipOther.js +3 -0
  302. package/src/picking/showFeature.js +34 -0
  303. package/src/raster/addRasterTile.js +114 -0
  304. package/src/raster/comparePendingTiles.js +5 -0
  305. package/src/raster/createGeometry.js +22 -0
  306. package/src/raster/createRasterMesh.js +47 -0
  307. package/src/raster/finishAttachment.js +11 -0
  308. package/src/raster/finishRasterTile.js +47 -0
  309. package/src/raster/getRasterEvents.js +6 -0
  310. package/src/raster/getRasterTileSize.js +5 -0
  311. package/src/raster/initRaster.js +38 -0
  312. package/src/raster/isLoading.js +5 -0
  313. package/src/raster/loadRasterTile.js +10 -0
  314. package/src/raster/onPMTileAdd.js +10 -0
  315. package/src/raster/onPMTileRemove.js +8 -0
  316. package/src/raster/pruneRasterTiles.js +37 -0
  317. package/src/raster/pumpRasterTiles.js +22 -0
  318. package/src/raster/readyRaster.js +13 -0
  319. package/src/raster/registerTerrainTile.js +12 -0
  320. package/src/raster/releaseRasterTile.js +18 -0
  321. package/src/raster/releaseRasterTiles.js +15 -0
  322. package/src/raster/removeRasterTile.js +13 -0
  323. package/src/raster/reportError.js +6 -0
  324. package/src/raster/setPMTileOpacity.js +7 -0
  325. package/src/raster/setPMTileZIndex.js +7 -0
  326. package/src/raster/setRasterOpacity.js +11 -0
  327. package/src/raster/setRasterTerrain.js +21 -0
  328. package/src/raster/setRasterZIndex.js +11 -0
  329. package/src/raster/updateAttachedTiles.js +10 -0
  330. package/src/raster/updateRasterTiles.js +59 -0
  331. package/src/rendering/collectFrameMeshes.js +31 -0
  332. package/src/rendering/collectMeshes.js +36 -0
  333. package/src/rendering/compareMeshes.js +10 -0
  334. package/src/rendering/compareRoofTiles.js +4 -0
  335. package/src/rendering/composeRoofAtlas.js +52 -0
  336. package/src/rendering/createMesh.js +33 -0
  337. package/src/rendering/createProgram.js +92 -0
  338. package/src/rendering/destroyAfterSubmission.js +8 -0
  339. package/src/rendering/destroyTexture.js +6 -0
  340. package/src/rendering/disposeMesh.js +14 -0
  341. package/src/rendering/drawGeometry.js +129 -0
  342. package/src/rendering/drawSceneMeshes.js +51 -0
  343. package/src/rendering/ensureRoofBlit.js +40 -0
  344. package/src/rendering/prepareFrameMeshes.js +42 -0
  345. package/src/rendering/prepareFrameUniforms.js +49 -0
  346. package/src/rendering/rebuildRoofAtlas.js +67 -0
  347. package/src/rendering/render.js +57 -0
  348. package/src/rendering/reportCompilation.js +17 -0
  349. package/src/rendering/resizeRenderer.js +19 -0
  350. package/src/rendering/sortMeshes.js +6 -0
  351. package/src/rendering/synchronizeZoomView.js +34 -0
  352. package/src/rendering/textureBinding.js +7 -0
  353. package/src/rendering/updateMapCamera.js +32 -0
  354. package/src/rendering/updateRoofRaster.js +32 -0
  355. package/src/scene/attach.js +161 -0
  356. package/src/scene/attachLayer.js +10 -0
  357. package/src/scene/cancelUpdate.js +10 -0
  358. package/src/scene/emptyEvents.js +3 -0
  359. package/src/scene/emptyNode.js +11 -0
  360. package/src/scene/endZoom.js +16 -0
  361. package/src/scene/failAttachment.js +9 -0
  362. package/src/scene/get3DEvents.js +13 -0
  363. package/src/scene/init3D.js +30 -0
  364. package/src/scene/initializeLayer.js +16 -0
  365. package/src/scene/initializerFor.js +14 -0
  366. package/src/scene/layerInitialize.js +38 -0
  367. package/src/scene/layerLayerAdd.js +21 -0
  368. package/src/scene/onAdd3DLayer.js +35 -0
  369. package/src/scene/onMapChange.js +16 -0
  370. package/src/scene/onRemove3DLayer.js +69 -0
  371. package/src/scene/onZoomAnim.js +16 -0
  372. package/src/scene/placeEntry.js +11 -0
  373. package/src/scene/placeUnderEntry.js +8 -0
  374. package/src/scene/ready3D.js +25 -0
  375. package/src/scene/releaseRenderer.js +14 -0
  376. package/src/scene/removeEntry.js +6 -0
  377. package/src/scene/renderPendingMapChange.js +11 -0
  378. package/src/scene/renderPendingUpdates.js +19 -0
  379. package/src/scene/renderPendingZoomAnimation.js +7 -0
  380. package/src/scene/rendererDeviceError.js +10 -0
  381. package/src/scene/rendererDeviceLost.js +11 -0
  382. package/src/scene/replaceEntry.js +7 -0
  383. package/src/scene/reportError.js +3 -0
  384. package/src/scene/requestAdapter.js +12 -0
  385. package/src/scene/requestDevice.js +9 -0
  386. package/src/scene/resolveNextInitialization.js +12 -0
  387. package/src/scene/restoreObject.js +71 -0
  388. package/src/scene/runPlacements.js +7 -0
  389. package/src/scene/setParent.js +7 -0
  390. package/src/scene/showWebGPUWarning.js +16 -0
  391. package/src/scene/startZoom.js +5 -0
  392. package/src/scene/traverse.js +7 -0
  393. package/src/scene/underEntry.js +17 -0
  394. package/src/scene/update.js +19 -0
  395. package/src/scene/updateCamera.js +34 -0
  396. package/src/scene/updateWorldMatrix.js +48 -0
  397. package/src/{utils/shaders.js → shaders/materialShaders.js} +246 -237
  398. package/src/shadows/bindSunlight.js +12 -0
  399. package/src/shadows/drawShadowMeshes.js +48 -0
  400. package/src/shadows/ensureShadowPipeline.js +53 -0
  401. package/src/shadows/renderSunlight.js +46 -0
  402. package/src/shadows/resizeSunlight.js +15 -0
  403. package/src/shadows/shadowBounds.js +32 -0
  404. package/src/shadows/shadowCacheMatches.js +23 -0
  405. package/src/shadows/shadowMatrix.js +39 -0
  406. package/src/sources/addGeneratedTriangle.js +6 -0
  407. package/src/sources/addTriangle.js +17 -0
  408. package/src/sources/attachAreaMesh.js +58 -0
  409. package/src/sources/buildArea.js +42 -0
  410. package/src/sources/buildAreaFeature.js +41 -0
  411. package/src/sources/buildAreaPoint.js +25 -0
  412. package/src/sources/buildAreaPolygon.js +29 -0
  413. package/src/sources/compareAreaDistance.js +4 -0
  414. package/src/sources/generateTreeGeometry.js +11 -0
  415. package/src/sources/groundOffset.js +3 -0
  416. package/src/sources/initializeGeoJSON.js +8 -0
  417. package/src/sources/instanceAreaGeometry.js +29 -0
  418. package/src/sources/projectRing.js +20 -0
  419. package/src/sources/projectedTree.js +13 -0
  420. package/src/sources/pump.js +54 -0
  421. package/src/sources/releaseArea.js +22 -0
  422. package/src/sources/setGeoJSONData.js +12 -0
  423. package/src/sources/setGeoJSONLayerData.js +5 -0
  424. package/src/sources/sourceAreaContext.js +9 -0
  425. package/src/sources/updateArea.js +45 -0
  426. package/src/sources/updateStatus.js +12 -0
  427. package/src/sunlight/addTimeLayer.js +3 -0
  428. package/src/sunlight/addTo.js +10 -0
  429. package/src/sunlight/atmosphere.js +28 -0
  430. package/src/sunlight/horizontalPosition.js +16 -0
  431. package/src/sunlight/initSunlight.js +14 -0
  432. package/src/sunlight/initialize.js +11 -0
  433. package/src/sunlight/mix.js +6 -0
  434. package/src/sunlight/moonPosition.js +17 -0
  435. package/src/sunlight/onAdd.js +5 -0
  436. package/src/sunlight/onAddSun.js +66 -0
  437. package/src/sunlight/projectCelestialBody.js +13 -0
  438. package/src/sunlight/remove.js +7 -0
  439. package/src/sunlight/removeSun.js +15 -0
  440. package/src/sunlight/removeTimeLayer.js +3 -0
  441. package/src/sunlight/render.js +7 -0
  442. package/src/sunlight/rgb.js +6 -0
  443. package/src/sunlight/solarPosition.js +17 -0
  444. package/src/sunlight/styleTimeControl.js +7 -0
  445. package/src/sunlight/tickSun.js +5 -0
  446. package/src/sunlight/updateSky.js +20 -0
  447. package/src/sunlight/updateSun.js +34 -0
  448. package/src/sunlight/useLiveTime.js +6 -0
  449. package/src/sunlight/useSelectedTime.js +20 -0
  450. package/src/terrain/clearLayerTerrain.js +5 -0
  451. package/src/terrain/getElevation.js +10 -0
  452. package/src/terrain/initTerrain.js +20 -0
  453. package/src/terrain/loadReadyTerrain.js +5 -0
  454. package/src/terrain/loadTerrain.js +63 -0
  455. package/src/terrain/loadTerrainTiles.js +13 -0
  456. package/src/terrain/onTerrainAdd.js +21 -0
  457. package/src/terrain/onTerrainChange.js +14 -0
  458. package/src/terrain/onTerrainRemove.js +41 -0
  459. package/src/terrain/readBridges.js +4 -0
  460. package/src/terrain/sample.js +7 -0
  461. package/src/terrain/setLayerTerrain.js +5 -0
  462. package/src/terrain/setTerrainHeight.js +10 -0
  463. package/src/terrain/terrainAtlas.js +23 -0
  464. package/src/terrain/terrainElevation.js +20 -0
  465. package/src/terrain/terrainGrid.js +24 -0
  466. package/src/traffic/addTraffic.js +7 -0
  467. package/src/traffic/along.js +14 -0
  468. package/src/traffic/clockMinutes.js +6 -0
  469. package/src/traffic/compareDepartures.js +5 -0
  470. package/src/traffic/createTrafficMesh.js +7 -0
  471. package/src/traffic/destroyTrafficGpu.js +5 -0
  472. package/src/traffic/disposeTrafficObject.js +13 -0
  473. package/src/traffic/drawTrafficRoute.js +6 -0
  474. package/src/traffic/failTraffic.js +6 -0
  475. package/src/traffic/failedTrafficLoad.js +5 -0
  476. package/src/traffic/fetchTrafficLanes.js +10 -0
  477. package/src/traffic/groundTraffic.js +15 -0
  478. package/src/traffic/initTraffic.js +54 -0
  479. package/src/traffic/loadTraffic.js +15 -0
  480. package/src/traffic/loadedTrafficLanes.js +16 -0
  481. package/src/traffic/locateTraffic.js +9 -0
  482. package/src/traffic/moveTraffic.js +15 -0
  483. package/src/traffic/placeTraffic.js +21 -0
  484. package/src/traffic/prepareTraffic.js +25 -0
  485. package/src/traffic/readyTraffic.js +6 -0
  486. package/src/traffic/rebaseTraffic.js +58 -0
  487. package/src/traffic/rebuildTrafficMesh.js +28 -0
  488. package/src/traffic/removeTraffic.js +17 -0
  489. package/src/traffic/routeColor.js +6 -0
  490. package/src/traffic/routeGeometry.js +31 -0
  491. package/src/traffic/scheduledTrips.js +40 -0
  492. package/src/traffic/startTraffic.js +8 -0
  493. package/src/traffic/tickTraffic.js +57 -0
  494. package/src/traffic/toLanes.js +16 -0
  495. package/src/traffic/tooltip.js +11 -0
  496. package/src/traffic/trafficBounds.js +17 -0
  497. package/src/traffic/trafficNow.js +4 -0
  498. package/src/traffic/trafficStorage.js +5 -0
  499. package/src/traffic/tripsAt.js +27 -0
  500. package/src/traffic/updateTraffic.js +8 -0
  501. package/src/traffic/updateTrafficTerrain.js +12 -0
  502. package/src/traffic/vehicleOffsets.js +11 -0
  503. package/src/triangulation/area.js +9 -0
  504. package/src/triangulation/clean.js +18 -0
  505. package/src/triangulation/containsVertex.js +11 -0
  506. package/src/triangulation/cross.js +3 -0
  507. package/src/triangulation/crossesBoundary.js +8 -0
  508. package/src/triangulation/crossesRing.js +9 -0
  509. package/src/triangulation/equal.js +3 -0
  510. package/src/triangulation/inside.js +10 -0
  511. package/src/triangulation/insideHole.js +7 -0
  512. package/src/triangulation/intersects.js +11 -0
  513. package/src/triangulation/isClockWise.js +13 -0
  514. package/src/triangulation/minimumX.js +6 -0
  515. package/src/triangulation/on.js +4 -0
  516. package/src/triangulation/sortHoles.js +26 -0
  517. package/src/triangulation/triangulate.js +86 -0
  518. package/src/utils/channel.js +4 -0
  519. package/src/utils/compareDistance.js +3 -0
  520. package/src/utils/noOperation.js +1 -0
  521. package/src/utils/parseColor.js +42 -0
  522. package/src/utils/toSRGB.js +3 -0
  523. package/src/utils/wrap.js +3 -0
  524. package/src/vehicles/bicycleModel.js +23 -0
  525. package/src/vehicles/boatBenches.js +8 -0
  526. package/src/vehicles/boatModel.js +27 -0
  527. package/src/vehicles/busModel.js +6 -0
  528. package/src/vehicles/carModel.js +22 -0
  529. package/src/vehicles/carriage.js +19 -0
  530. package/src/vehicles/metroModel.js +9 -0
  531. package/src/vehicles/mirror.js +8 -0
  532. package/src/vehicles/pedestrianModel.js +17 -0
  533. package/src/vehicles/tramModel.js +9 -0
  534. package/src/walk/blocked.js +6 -0
  535. package/src/walk/createWalk.js +60 -0
  536. package/src/walk/initWalk.js +18 -0
  537. package/src/walk/initialize.js +6 -0
  538. package/src/walk/local.js +10 -0
  539. package/src/walk/onAdd.js +4 -0
  540. package/src/walk/onBlur.js +3 -0
  541. package/src/walk/onKey.js +12 -0
  542. package/src/walk/onPointer.js +13 -0
  543. package/src/walk/onRemove.js +4 -0
  544. package/src/walk/onTerrain.js +5 -0
  545. package/src/walk/place.js +18 -0
  546. package/src/walk/start.js +37 -0
  547. package/src/walk/step.js +53 -0
  548. package/src/walk/stop.js +27 -0
  549. package/src/walk/toggle.js +6 -0
  550. package/dist/scene/gpu.js +0 -3
  551. package/dist/scene/gpu.js.map +0 -7
  552. package/dist/scene/lighting.js +0 -9
  553. package/dist/scene/lighting.js.map +0 -7
  554. package/dist/scene/model.js +0 -2
  555. package/dist/scene/model.js.map +0 -7
  556. package/dist/scene/picking.js +0 -2
  557. package/dist/scene/picking.js.map +0 -7
  558. package/dist/scene/pmtiles.js +0 -2
  559. package/dist/scene/pmtiles.js.map +0 -7
  560. package/dist/scene/render.js +0 -15
  561. package/dist/scene/render.js.map +0 -7
  562. package/dist/scene/sources.js +0 -2
  563. package/dist/scene/sources.js.map +0 -7
  564. package/dist/types/3d.js +0 -2
  565. package/dist/types/3d.js.map +0 -7
  566. package/dist/types/geojson.js +0 -2
  567. package/dist/types/geojson.js.map +0 -7
  568. package/dist/types/pmtiles.js +0 -2
  569. package/dist/types/pmtiles.js.map +0 -7
  570. package/dist/types/sunlight.js +0 -2
  571. package/dist/types/sunlight.js.map +0 -7
  572. package/dist/types/terrain.js +0 -24
  573. package/dist/types/terrain.js.map +0 -7
  574. package/dist/types/traffic.js +0 -41
  575. package/dist/types/traffic.js.map +0 -7
  576. package/dist/types/walk.js +0 -2
  577. package/dist/types/walk.js.map +0 -7
  578. package/dist/utils/control.js +0 -2
  579. package/dist/utils/control.js.map +0 -7
  580. package/dist/utils/geometry.js +0 -2
  581. package/dist/utils/geometry.js.map +0 -7
  582. package/dist/utils/lighting.js +0 -2
  583. package/dist/utils/lighting.js.map +0 -7
  584. package/dist/utils/model.js +0 -2
  585. package/dist/utils/model.js.map +0 -7
  586. package/dist/utils/picking.js +0 -2
  587. package/dist/utils/picking.js.map +0 -7
  588. package/dist/utils/pmtiles.js +0 -2
  589. package/dist/utils/pmtiles.js.map +0 -7
  590. package/dist/utils/scene.js +0 -2
  591. package/dist/utils/scene.js.map +0 -7
  592. package/dist/utils/shaders.js +0 -203
  593. package/dist/utils/shaders.js.map +0 -7
  594. package/dist/utils/sun.js +0 -2
  595. package/dist/utils/sun.js.map +0 -7
  596. package/dist/utils/terrain.js +0 -2
  597. package/dist/utils/terrain.js.map +0 -7
  598. package/dist/utils/traffic.js +0 -2
  599. package/dist/utils/traffic.js.map +0 -7
  600. package/dist/utils/vehicles.js +0 -2
  601. package/dist/utils/vehicles.js.map +0 -7
  602. package/dist/utils/walk.js +0 -2
  603. package/dist/utils/walk.js.map +0 -7
  604. package/src/scene/gpu.js +0 -438
  605. package/src/scene/lighting.js +0 -193
  606. package/src/scene/model.js +0 -204
  607. package/src/scene/picking.js +0 -150
  608. package/src/scene/pmtiles.js +0 -94
  609. package/src/scene/render.js +0 -467
  610. package/src/scene/sources.js +0 -265
  611. package/src/types/3d.js +0 -337
  612. package/src/types/geojson.js +0 -42
  613. package/src/types/pmtiles.js +0 -143
  614. package/src/types/sunlight.js +0 -142
  615. package/src/types/terrain.js +0 -331
  616. package/src/types/traffic.js +0 -356
  617. package/src/types/walk.js +0 -219
  618. package/src/utils/control.js +0 -18
  619. package/src/utils/geometry.js +0 -256
  620. package/src/utils/lighting.js +0 -51
  621. package/src/utils/model.js +0 -178
  622. package/src/utils/picking.js +0 -119
  623. package/src/utils/pmtiles.js +0 -79
  624. package/src/utils/scene.js +0 -102
  625. package/src/utils/sun.js +0 -71
  626. package/src/utils/terrain.js +0 -78
  627. package/src/utils/traffic.js +0 -90
  628. package/src/utils/vehicles.js +0 -69
  629. package/src/utils/walk.js +0 -72
@@ -1,265 +0,0 @@
1
- import { parseColor, triangulate, isClockWise, treeGeometry, lightGeometry, lampPostGeometry } from '../utils/geometry.js';
2
- import { emptyNode } from '../utils/scene.js';
3
-
4
- /** GeoJSON source areas: loading, building and releasing. */
5
- export function onTerrainChange(backend) {
6
- if (!backend._map) return;
7
- for (const area of backend._areas.values()) backend._releaseArea(area);
8
- backend._areas.clear();
9
- backend._updateArea();
10
- }
11
-
12
- /** Cover the visible ground bounds and one bordering block, clipped to the archive. */
13
- export function updateArea(backend) {
14
- if (!backend._map || !backend.header) return;
15
- const z = backend.header.minZoom;
16
- const center = backend._map.project(backend._map.getCenter(), z).divideBy(256).floor();
17
- const bounds = backend._map.getBounds();
18
- const nw = backend._map.project(bounds.getNorthWest(), z).divideBy(256).floor();
19
- const se = backend._map.project(bounds.getSouthEast(), z).divideBy(256).floor();
20
- const archiveNW = backend._map.project([backend.header.maxLat, backend.header.minLon], z).divideBy(256).floor();
21
- const archiveSE = backend._map.project([backend.header.minLat, backend.header.maxLon], z).divideBy(256).floor();
22
- const wanted = new Map();
23
- for (let x = Math.max(0, nw.x - 1, archiveNW.x); x <= Math.min(2 ** z - 1, se.x + 1, archiveSE.x); x++) {
24
- for (let y = Math.max(0, nw.y - 1, archiveNW.y); y <= Math.min(2 ** z - 1, se.y + 1, archiveSE.y); y++) {
25
- wanted.set(`${x}/${y}`, { z, x, y });
26
- }
27
- }
28
- for (const [key, area] of backend._areas) {
29
- if (!wanted.has(key)) {
30
- backend._releaseArea(area);
31
- backend._areas.delete(key);
32
- }
33
- }
34
- // Load the nearest new blocks first without rebuilding retained geometry.
35
- for (const [key, coords] of [...wanted].sort(([, a], [, b]) =>
36
- Math.hypot(a.x - center.x, a.y - center.y) - Math.hypot(b.x - center.x, b.y - center.y))) {
37
- if (!backend._areas.has(key)) backend._areas.set(key, { coords, request: new AbortController() });
38
- }
39
- backend._pump();
40
- }
41
-
42
- export async function loadSource(backend, area) {
43
- const { z, x, y } = area.coords;
44
- const result = await backend.getZxy(z, x, y, area.request.signal);
45
- return result ? JSON.parse(new TextDecoder().decode(result.data))
46
- : { type: 'FeatureCollection', features: [] };
47
- }
48
-
49
- /** Start at most two load/build tasks; cancelled tasks still free their slot in finally. */
50
- export function pump(backend) {
51
- // Meshes need the shared renderer; _attach() re-runs _updateArea() once it exists.
52
- if (!backend._map || !backend._shared) return;
53
- for (const area of backend._areas.values()) {
54
- if (backend._inflight >= 2) break;
55
- if (area.started) continue;
56
- area.started = true;
57
- backend._inflight++;
58
- (async () => {
59
- try {
60
- const coords = area.coords;
61
- const data = await backend._loadSource(area);
62
- if (area.request.signal.aborted) return;
63
- if (data?.type !== 'FeatureCollection' || !Array.isArray(data.features)) {
64
- throw new Error('Invalid GeoJSON response');
65
- }
66
- const features = data.features;
67
- const positions = [], normals = [], colors = [], uvs = [], featureFaces = [], lights = [];
68
- const supports = new Set();
69
- let skipped = 0;
70
- const map = backend._map;
71
- const crs = map.options.crs;
72
- const origin = crs.project(backend.location);
73
- const metres = Math.cos(backend.location.lat * Math.PI / 180);
74
- const groundOffset = point => point.ground || 0;
75
- const addTriangle = (a, ah, b, bh, c, ch, nx, ny, nz, color) => {
76
- const ux = b.x - a.x, uy = bh - ah, uz = a.y - b.y;
77
- const vx = c.x - a.x, vy = ch - ah, vz = a.y - c.y;
78
- // Orient the triangle to its intended outward normal after flipping north to -z.
79
- if ((uy * vz - uz * vy) * nx + (uz * vx - ux * vz) * ny + (ux * vy - uy * vx) * nz < 0) {
80
- const point = b, height = bh;
81
- b = c; bh = ch; c = point; ch = height;
82
- }
83
- positions.push(a.x, ah + groundOffset(a), -a.y,
84
- b.x, bh + groundOffset(b), -b.y,
85
- c.x, ch + groundOffset(c), -c.y);
86
- normals.push(nx, ny, nz, nx, ny, nz, nx, ny, nz);
87
- colors.push(color.r, color.g, color.b, color.r, color.g, color.b, color.r, color.g, color.b);
88
- if (backend.options.nightLight) uvs.push(...a.uv, ...b.uv, ...c.uv);
89
- };
90
- let deadline = performance.now() + 8;
91
- for (const feature of features) {
92
- if (area.request.signal.aborted) return;
93
- if (performance.now() >= deadline) {
94
- await new Promise(requestAnimationFrame);
95
- if (area.request.signal.aborted) return;
96
- deadline = performance.now() + 8;
97
- }
98
- const geometry = feature?.geometry;
99
- const isTree = geometry?.type === 'Point';
100
- if (backend.options.nightLight && !isTree) throw new Error('Night lights require Point geometry');
101
- const polygons = geometry?.type === 'Polygon' ? [geometry.coordinates] : geometry?.type === 'MultiPolygon' ? geometry.coordinates : null;
102
- if (!polygons && !isTree) throw new Error('Unsupported GeoJSON geometry');
103
- const [lon, lat] = (isTree ? geometry.coordinates : polygons[0]?.[0]?.[0]) ?? [];
104
- if (!Number.isFinite(lon) || !Number.isFinite(lat)) throw new Error('Invalid GeoJSON coordinates');
105
- if (coords) {
106
- const anchor = map.project(new L.LatLng(lat, lon), coords.z);
107
- // Overlapping archive blocks may contain the same polygon; its first vertex owns it.
108
- if (Math.floor(anchor.x / 256) !== coords.x || Math.floor(anchor.y / 256) !== coords.y) continue;
109
- }
110
- const style = backend.options.featureStyle(feature);
111
- if (style === null) {
112
- skipped++;
113
- continue;
114
- }
115
- if (!style || typeof style !== 'object') throw new Error('featureStyle must return an extrusion style or null');
116
- const { top, bottom = 0, color = 0xd9b38c } = style;
117
- if (!Number.isFinite(top) || !Number.isFinite(bottom) || bottom < 0 || top <= bottom) {
118
- throw new Error('Invalid extrusion heights: expected top > bottom >= 0');
119
- }
120
- const baseColor = parseColor(color);
121
- const vertexStart = positions.length / 3;
122
- if (isTree) {
123
- const point = crs.project(new L.LatLng(lat, lon));
124
- const elevation = map._terrain3D?._getElevation([lat, lon]);
125
- const projected = {
126
- x: (point.x - origin.x) * metres, y: (point.y - origin.y) * metres,
127
- ground: Number.isFinite(elevation) && Number.isFinite(backend.root.position[1])
128
- ? elevation - backend.root.position[1] : 0,
129
- };
130
- if (backend.options.nightLight) {
131
- if (!Number.isFinite(style.lightFlux) || style.lightFlux <= 0) throw new Error('Invalid light flux');
132
- const support = feature.properties?.cod_ouvrag || `${lon},${lat}`;
133
- if (style.poleRadius > 0 && !supports.has(support)) {
134
- lampPostGeometry(projected, style, addTriangle);
135
- supports.add(support);
136
- }
137
- lightGeometry(projected, style, addTriangle);
138
- lights.push({
139
- position: [projected.x, projected.ground + top, -projected.y],
140
- radius: Math.hypot(top, style.lightRadius), color: [baseColor.r, baseColor.g, baseColor.b],
141
- flux: style.lightFlux,
142
- });
143
- } else treeGeometry(projected, style, addTriangle);
144
- }
145
- for (const rings of polygons || []) {
146
- if (!rings.length) throw new Error('Empty GeoJSON polygon');
147
- const paths = rings.map(ring => {
148
- if (ring.length < 4) throw new Error('Invalid GeoJSON polygon ring');
149
- return ring.slice(0, -1).map(([lng, lat]) => {
150
- if (!Number.isFinite(lng) || !Number.isFinite(lat)) throw new Error('Invalid GeoJSON coordinates');
151
- const point = crs.project(new L.LatLng(lat, lng));
152
- const elevation = backend._map._terrain3D?._getElevation([lat, lng]);
153
- return {
154
- x: (point.x - origin.x) * metres,
155
- y: (point.y - origin.y) * metres,
156
- ground: Number.isFinite(elevation) && Number.isFinite(backend.root.position[1])
157
- ? elevation - backend.root.position[1] : 0,
158
- };
159
- });
160
- });
161
- const points = paths.flat();
162
- for (const [a, b, c] of triangulate(paths[0], paths.slice(1))) {
163
- addTriangle(points[a], top, points[b], top, points[c], top, 0, 1, 0, baseColor);
164
- if (bottom > 0) addTriangle(points[a], bottom, points[b], bottom, points[c], bottom, 0, -1, 0, baseColor);
165
- }
166
- paths.forEach((path, index) => {
167
- // Interior walls face into the courtyard; exterior walls face away from the building.
168
- const sign = isClockWise(path) === (index === 0) ? -1 : 1;
169
- for (let i = 0; i < path.length; i++) {
170
- const a = path[i], b = path[(i + 1) % path.length];
171
- const length = Math.hypot(b.x - a.x, b.y - a.y);
172
- if (!length) continue;
173
- const nx = sign * (b.y - a.y) / length, nz = sign * (b.x - a.x) / length;
174
- addTriangle(a, bottom, b, bottom, b, top, nx, 0, nz, baseColor);
175
- addTriangle(a, bottom, b, top, a, top, nx, 0, nz, baseColor);
176
- }
177
- });
178
- }
179
- const vertexEnd = positions.length / 3;
180
- featureFaces.push({
181
- id: feature.id ?? feature.properties?.objectid ?? JSON.stringify(geometry),
182
- properties: feature.properties, baseColor,
183
- faceStart: vertexStart / 3, faceEnd: vertexEnd / 3, vertexStart, vertexEnd,
184
- });
185
- }
186
- if (!positions.length) {
187
- Object.assign(area, { mesh: null, buildings: 0, skipped, done: true });
188
- return;
189
- }
190
- const device = backend.renderer.device;
191
- const attributes = {
192
- position: { size: 3, data: new Float32Array(positions) },
193
- normal: { size: 3, data: new Float32Array(normals) },
194
- color: { size: 3, data: new Float32Array(colors) },
195
- };
196
- if (backend.options.nightLight) attributes.uv = { size: 2, data: new Float32Array(uvs) };
197
- for (const [name, attribute] of Object.entries(attributes)) {
198
- attribute.count = attribute.data.length / attribute.size;
199
- attribute.buffer = device.createBuffer({
200
- size: Math.max(4, attribute.data.byteLength),
201
- usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
202
- });
203
- device.queue.writeBuffer(attribute.buffer, 0, attribute.data);
204
- }
205
- const meshGeometry = {
206
- device,
207
- attributes,
208
- drawRange: { start: 0, count: attributes.position.count },
209
- };
210
- Object.assign(area, {
211
- mesh: {
212
- ...emptyNode(),
213
- device,
214
- geometry: meshGeometry,
215
- program: backend._createProgram({ vertexColors: true, roofTexture: Boolean(backend.options.roofTexture),
216
- ...(backend.options.nightLight ? { nightLight: true, alphaMode: 'BLEND', doubleSided: true } : {}) }),
217
- id: L.Layer.types['3d']._nextId++,
218
- renderOrder: 0,
219
- extras: { featureFaces, lights },
220
- },
221
- buildings: featureFaces.length,
222
- skipped,
223
- done: true
224
- });
225
- backend.add(area.mesh);
226
- } catch (error) {
227
- if (area.request.signal.aborted) return;
228
- area.error = error.message;
229
- backend.fire('error', { error });
230
- }
231
- })().finally(() => {
232
- backend._inflight--;
233
- backend._pump();
234
- });
235
- }
236
- backend._updateStatus();
237
- }
238
-
239
- /** Cancel pending work and dispose this block's GPU data, including any hover highlight. */
240
- export function releaseArea(backend, area) {
241
- area.request.abort();
242
- if (area.mesh) {
243
- if (backend.highlightedFeature?.mesh === area.mesh) {
244
- backend._setHighlight(null);
245
- backend.hoveredFeature = null;
246
- backend._showFeature(null);
247
- }
248
- backend.remove(area.mesh);
249
- const geometry = area.mesh.geometry;
250
- for (const attribute of Object.values(geometry.attributes)) attribute.buffer.destroy();
251
- backend._removeProgram(area.mesh.program);
252
- }
253
- }
254
-
255
- /** Emit a snapshot for consumers; ready does not wait for all neighborhood tasks. */
256
- export function updateStatus(backend, enabled = true) {
257
- const progress = { enabled, loaded: 0, skipped: 0, pending: 0, errors: [] };
258
- for (const area of backend._areas.values()) {
259
- if (area.error) progress.errors.push(area.error);
260
- else if (!area.done) progress.pending++;
261
- progress.loaded += area.buildings ?? 0;
262
- progress.skipped += area.skipped ?? 0;
263
- }
264
- backend.fire('progress', progress);
265
- }
package/src/types/3d.js DELETED
@@ -1,337 +0,0 @@
1
- /**
2
- * The '3d' layer type, loaded on demand by src/index.js.
3
- *
4
- * A native WebGPU scene drawn above the map tiles and kept in sync with the map camera
5
- * (center, zoom, bearing, pitch and zoom animations).
6
- *
7
- * No rendering dependencies. Use the `ready` event before using the helpers.
8
- * All instances on one map share a canvas, scene and camera, with one group per layer.
9
- *
10
- * World coordinates are metres relative to `location`: x east, y up, z south.
11
- * The shared scene instead uses the first attached layer's origin. `root` converts
12
- * each layer's local metres into that shared space, including latitude scaling.
13
- *
14
- * Lifecycle: initialize CPU state -> attach shared GPU device -> load configured
15
- * data/model -> ready. Removal cancels source work and detaches this layer only;
16
- * the last removal destroys the context. Model CPU arrays/images survive for re-add.
17
- *
18
- * This file holds the Leaflet lifecycle and explicit delegates to scene/ operations.
19
- * Stateless computations live in utils/; scene/ owns loading, GPU resources and interaction.
20
- * PMTiles v3 reading is implemented directly by this layer. Models are static triangles, without
21
- * animation, skinning, morph targets, normal maps or required extensions.
22
- *
23
- * Events: ready; error {error}; progress {enabled, loaded, skipped, pending, errors};
24
- * featurehover/featureclick {feature, originalEvent}. A feature may be null on a miss.
25
- * Picking tests geometry, not texture alpha: a transparent texel can still be hit.
26
- *
27
- * @example
28
- * new L.Layer({ source: { url: 'tower.glb', center: [48.8582601, 2.29449985] } }).addTo(map);
29
- * new L.Layer({ source: { type: '3d', url: 'buildings.pmtiles', featureStyle }, attribution }).addTo(map);
30
- * new L.Layer({ source: { type: 'terrain', url: 'terrain.pmtiles' } }).addTo(map);
31
- * new L.Layer({ source: { url: 'orthophotos.pmtiles', maxZoom: 24 } }).addTo(map);
32
- *
33
- * @typedef {Object} Layer3DOptions The `source` object; `pane`/`attribution` stay standard L.Layer options.
34
- * @property {string} [type] 'pmtiles' (raster tiles), '3d' (WebGPU scene) or 'terrain'; see L.Layer.types.
35
- * @property {number[]} [center] Local origin [lat,lng]; defaults to the first map center.
36
- * @property {number[]} [rotation] Model Euler rotation [x,y,z] in radians, YXZ order.
37
- * @property {number[]} [scale] Model scale [x,y,z]; independent of geographic scaling.
38
- * @property {string} [url] GLB/glTF model URL (loaded before ready), or PMTiles URL containing
39
- * Polygon/MultiPolygon or tree/light Point GeoJSON ('3d'), raster tiles ('pmtiles') or Float32 DEM ('terrain').
40
- * @property {function(Object): (ExtrusionStyle|null)} [featureStyle] Source styling; null skips.
41
- * @property {function(PickedFeature): (Node|string)} [tooltipContent] No HTML string evaluation.
42
- * @property {string} [ariaLabel='3D scene'] Shared canvas accessible name.
43
- * @property {boolean} [nightLight=false] Point sources: emissive bulbs and local illumination.
44
- * @property {boolean} [nightSparkle=false] Model: sparse luminous points at night.
45
- *
46
- * @typedef {Object} ExtrusionStyle
47
- * @property {number} top Roof height in metres; must exceed bottom.
48
- * @property {number} [bottom=0] Nonnegative base height; positive values create an underside.
49
- * @property {number|string|Object} [color=0xd9b38c] RGB/CSS color, or linear-space {h,s,l}.
50
- * @property {number} [trunkRadius] Point trees: trunk radius in metres.
51
- * @property {number} [crownRadius] Point trees: maximum crown radius in metres.
52
- * @property {number} [crownBottom] Point trees: crown base in metres, between bottom and top.
53
- * @property {string} [crownShape='round'] Point trees: 'round' or 'cone' schematic crown.
54
- * @property {number|string|Object} [trunkColor=0x72513a] Point trees: bark color.
55
- * @property {number} [lightRadius] Point lights: estimated ground reach in metres; top is emitter height.
56
- * @property {number} [lightFlux] Point lights: luminous flux in lumens.
57
- *
58
- * @typedef {Object} PickedFeature
59
- * @property {string|number} id Source feature id or configured model URL.
60
- * @property {Object} properties GeoJSON properties or model-level glTF extras.
61
- * @property {Object} mesh Intersected mesh.
62
- * @property {number[]} point Intersection [x,y,z] in shared scene metres, not layer-local metres.
63
- * @property {Object} [model] Configured model root; absent for source polygons.
64
- * @property {number} [vertexStart] First polygon vertex in the batched mesh.
65
- * @property {number} [vertexEnd] Exclusive end of the polygon's vertex range.
66
- *
67
- * @typedef {Object} SourceArea
68
- * @property {Object} coords Archive block {z,x,y}; z is header.minZoom, not display zoom.
69
- * @property {AbortController} request Cancellation also prevents attaching obsolete results.
70
- * @property {boolean} [started] Enqueued work has consumed a concurrency slot.
71
- * @property {boolean} [done] Geometry built successfully, including empty blocks.
72
- * @property {Object|null} [mesh] One batched GPU mesh per non-empty block.
73
- * @property {number} [buildings] Emitted feature count, not number of triangles.
74
- * @property {number} [skipped] Features intentionally skipped by featureStyle.
75
- * @property {string} [error] Failed load/build message; reported through error and progress.
76
- *
77
- * @since leaflet-rotate (v0.6.0)
78
- */
79
-
80
- import * as shapes from '../utils/geometry.js';
81
- import * as gpu from '../scene/gpu.js';
82
- import * as lighting from '../scene/lighting.js';
83
- import * as model from '../scene/model.js';
84
- import * as picking from '../scene/picking.js';
85
- import * as pmtiles from '../scene/pmtiles.js';
86
- import * as archive from '../utils/pmtiles.js';
87
- import * as render from '../scene/render.js';
88
- import * as graph from '../utils/scene.js';
89
- import * as sources from '../scene/sources.js';
90
-
91
- L.Layer.types['3d'] = L.Layer.extend({
92
- color(value) { return shapes.parseColor(value); },
93
- _setVertexColor(mesh, start, end, color) { shapes.setVertexColor(mesh, start, end, color); return this.update(); },
94
- _triangulate(contour, holes) { return shapes.triangulate(contour, holes); },
95
- _isClockWise(points) { return shapes.isClockWise(points); },
96
- _treeGeometry(point, style, addTriangle) { return shapes.treeGeometry(point, style, addTriangle); },
97
- _lightGeometry(point, style, addTriangle) { return shapes.lightGeometry(point, style, addTriangle); },
98
- _lampPostGeometry(point, style, addTriangle) { return shapes.lampPostGeometry(point, style, addTriangle); },
99
- _attach(map) { return gpu.attach(this, map); },
100
- _destroyTexture(texture) { return gpu.destroyTexture(this, texture); },
101
- _createProgram(material) { return gpu.createProgram(this, material); },
102
- _removeProgram(program) { return gpu.removeProgram(program); },
103
- _createMesh(data, material, usage) { return gpu.createMesh(this, data, material, usage); },
104
- _disposeMesh(mesh) { return gpu.disposeMesh(this, mesh); },
105
- _computeBounds(geometry) { return shapes.computeBounds(geometry); },
106
- _drawGeometry(mesh, pass, cullMode, frontFace) { return gpu.drawGeometry(this, mesh, pass, cullMode, frontFace); },
107
- _initSunlight() { return lighting.initSunlight(this); },
108
- _resizeSunlight(size) { return lighting.resizeSunlight(this, size); },
109
- _bindSunlight() { return lighting.bindSunlight(this); },
110
- _updatePointLights() { return lighting.updatePointLights(this); },
111
- _renderSunlight(encoder, meshes, sunlight) { return lighting.renderSunlight(this, encoder, meshes, sunlight); },
112
- _loadModel() { return model.loadModel(this); },
113
- raycast(event, objects, recursive) { return picking.raycast(this, event, objects, recursive); },
114
- _findFeature(event) { return picking.findFeature(this, event); },
115
- _setHighlight(feature) { return picking.setHighlight(this, feature); },
116
- _showFeature(feature, event) { return picking.showFeature(this, feature, event); },
117
- _onPointerMove(event) { return picking.onPointerMove(this, event); },
118
- _onClick(event) { return picking.onClick(this, event); },
119
- _onPointerLeave() { return picking.onPointerLeave(this); },
120
- _read(offset, length, signal) { return pmtiles.read(this, offset, length, signal); },
121
- _decompress(data, compression) { return archive.decompress(data, compression); },
122
- getHeader() { return pmtiles.getHeader(this); },
123
- getZxy(z, x, y, signal) { return pmtiles.getZxy(this, z, x, y, signal); },
124
- update() { return render.update(this); },
125
- _onMapChange() { return render.onMapChange(this); },
126
- _getTileLevel() { return render.getTileLevel(this); },
127
- _startZoom() { return render.startZoom(this); },
128
- _endZoom() { return render.endZoom(this); },
129
- _render() { return render.render(this); },
130
- setParent(node, parent) { return graph.setParent(node, parent); },
131
- traverse(node, callback) { return graph.traverse(node, callback); },
132
- _updateWorldMatrix(node) { return graph.updateWorldMatrix(node); },
133
- _updateCamera(camera) { return graph.updateCamera(camera); },
134
- _onTerrainChange() { return sources.onTerrainChange(this); },
135
- _updateArea() { return sources.updateArea(this); },
136
- _pump() { return sources.pump(this); },
137
- _loadSource(area) { return sources.loadSource(this, area); },
138
- _releaseArea(area) { return sources.releaseArea(this, area); },
139
- _updateStatus(enabled) { return sources.updateStatus(this, enabled); },
140
-
141
- statics: {
142
- /** Rendering owner per map; entries are removed on the last layer removal. */
143
- _renderers: new WeakMap(),
144
- },
145
-
146
- options: {
147
- // Accessible description of the canvas.
148
- ariaLabel: '3D scene',
149
- },
150
-
151
- /**
152
- * @param {Layer3DOptions} [options] World origin comes from center or the first map centre.
153
- * Public state: `location` is fixed after first addition; `root` is this layer's
154
- * transform; `group` aliases root only for sources; `model` is the configured
155
- * model wrapper. `_shared` references the rendering owner (a '3d' layer);
156
- * `scene`, `camera` and `renderer` alias its resources while attached.
157
- *
158
- */
159
- initialize(options) {
160
- L.Util.setOptions(this, options);
161
- // ponytail: models are recognised by extension; extensionless model URLs need a .glb/.gltf suffix or query.
162
- const model = !this._geojson && /\.(glb|gltf)(?:[?#]|$)/i.test(this.options.url);
163
- this.modelUrl = model ? this.options.url : null;
164
- this.url = this.options.url && !model && !this._geojson ? new URL(this.options.url, document.baseURI).href : null;
165
- this._directories = new Map();
166
- if (this.options.center) {
167
- this.location = new L.LatLng(this.options.center[0], this.options.center[1]);
168
- }
169
- /** @type {Map<string, SourceArea>} Keys are archive x/y, not screen tiles. */
170
- this._areas = new Map();
171
- // Counts pending archive/build tasks, including ones cancelled after a pan.
172
- this._inflight = 0;
173
- // Gate GPU work on attachment; replaced on removal to support delayed loads.
174
- this._added = Promise.withResolvers();
175
- // Defer initialization so callers can subscribe to ready/error after construction.
176
- queueMicrotask(async () => {
177
- try {
178
- this.root = graph.emptyNode();
179
- this.raycaster = {
180
- origin: [0, 0, 0],
181
- direction: [0, 0, 0]
182
- };
183
- if (this.url || this._geojson) {
184
- this.group = this.root;
185
- if (this.url) this.header = await this.getHeader();
186
- }
187
- if (this._map) {
188
- await this._attach(this._map);
189
- this._added.resolve();
190
- }
191
- if (this.modelUrl) await this._loadModel();
192
- if (this._shared) this.update();
193
- this.fire('ready');
194
- } catch (error) {
195
- this.fire('error', { error });
196
- }
197
- });
198
- },
199
-
200
- /** Attach interaction immediately; initialization may finish before or after onAdd. */
201
- onAdd(map) {
202
- if (!this.location) {
203
- const center = map.getCenter();
204
- this.location = new L.LatLng(center.lat, center.lng);
205
- }
206
- if (this.url || this._geojson || this.options.tooltipContent || this.modelUrl) {
207
- this.container = map.getContainer();
208
- if (this.options.tooltipContent) {
209
- this._tooltip = L.DomUtil.create('div', 'leaflet-3d-tooltip', this.container);
210
- this._tooltip.hidden = true;
211
- this._tooltip.setAttribute('role', 'tooltip');
212
- this._tooltip.setAttribute('aria-live', 'polite');
213
- this._tooltip.style.cssText = 'position:absolute;z-index:600;max-width:220px;padding:10px 12px;border:1px solid #6b5140;border-radius:6px;background:#fffaf0;box-shadow:0 3px 12px #0005;color:#30251d;font:13px/1.45 sans-serif;pointer-events:none';
214
- }
215
- L.DomEvent.on(this.container, {
216
- mousemove: this._onPointerMove,
217
- click: this._onClick,
218
- mouseleave: this._onPointerLeave,
219
- }, this);
220
- }
221
- if (this.root) {
222
- this._attach(map).then(() => this._added.resolve(), error => this.fire('error', { error }));
223
- }
224
- },
225
-
226
- /** Reconcile source coverage when the visible ground footprint changes. */
227
- getEvents() {
228
- return this.url ? {
229
- moveend: this._updateArea,
230
- zoomend: this._updateArea,
231
- rotate: this._updateArea,
232
- pitch: this._updateArea,
233
- resize: this._updateArea,
234
- terrainchange: this._onTerrainChange,
235
- } : {};
236
- },
237
-
238
- /** Release source meshes/UI; retain manually added objects and model CPU data. */
239
- onRemove(map) {
240
- this._added = Promise.withResolvers();
241
- if (this.container) {
242
- this._onPointerLeave();
243
- L.DomEvent.off(this.container, {
244
- mousemove: this._onPointerMove,
245
- click: this._onClick,
246
- mouseleave: this._onPointerLeave,
247
- }, this);
248
- this.container = null;
249
- }
250
- for (const area of this._areas.values()) this._releaseArea(area);
251
- this._areas.clear();
252
- this._tooltip?.remove();
253
- this._tooltip = null;
254
- if (this.url || this._geojson) this._updateStatus(false);
255
- const shared = this._shared;
256
- if (!shared) return;
257
- this.setParent(this.root, null);
258
- shared._layers.delete(this);
259
- if (shared === this) {
260
- map.off('move zoom rotate pitch resize viewreset layeradd layerremove', this._onMapChange, this);
261
- map.off('zoomstart', this._startZoom, this);
262
- map.off('zoomanim', this.update, this);
263
- map.off('zoomend', this._endZoom, this);
264
- cancelAnimationFrame(this._frame);
265
- this._frame = null;
266
- this._queued = false;
267
- if (this._layers.size) {
268
- // Keep the original scene origin and GPU resources when ownership changes.
269
- const next = this._layers.values().next().value;
270
- for (const key of ['_layers', '_sceneOrigin', '_size', '_zoomLevel', '_zoomTransitions', '_cursor', '_roofRaster', '_roofTiles']) {
271
- next[key] = this[key];
272
- delete this[key];
273
- }
274
- for (const layer of next._layers) layer._shared = next;
275
- L.Layer.types['3d']._renderers.set(map, next);
276
- map.on('move zoom rotate pitch resize viewreset layeradd layerremove', next._onMapChange, next);
277
- map.on('zoomstart', next._startZoom, next);
278
- map.on('zoomanim', next.update, next);
279
- map.on('zoomend', next._endZoom, next);
280
- next.update();
281
- } else {
282
- if (this._roofRaster) this._destroyTexture(this._roofRaster.texture.texture);
283
- this._roofRaster = null;
284
- for (const source of this._roofTiles?.values() || []) this._destroyTexture(source.texture);
285
- this._roofTiles = null;
286
- for (const animation of this._zoomTransitions?.keys() || []) animation.play();
287
- this._zoomTransitions = null;
288
- this.renderer.canvas.remove();
289
- const renderer = this.renderer;
290
- const resources = [renderer.depthTexture, renderer.roofFallbackTexture.texture, renderer.uniformBuffer,
291
- renderer.sunlight?.texture, renderer.sunlight?.buffer, renderer.sunlight?.lights].filter(Boolean);
292
- renderer.device.queue.onSubmittedWorkDone().then(() => {
293
- for (const resource of resources) resource.destroy();
294
- renderer.device.destroy();
295
- }, error => {
296
- this.fire('error', { error });
297
- renderer.device.destroy();
298
- });
299
- L.Layer.types['3d']._renderers.delete(map);
300
- for (const key of ['_layers', '_sceneOrigin', '_size', '_zoomLevel', '_cursor']) delete this[key];
301
- }
302
- } else shared.update();
303
- this._shared = null;
304
- this.renderer = this.scene = this.camera = null;
305
- },
306
-
307
- /**
308
- * Adds a scene node or mesh in layer-local coordinates and schedules a redraw.
309
- * Requires initialization and a compatible scene node.
310
- * @param {Object} object
311
- * @returns {L.Layer} This layer.
312
- */
313
- add(object) {
314
- this.setParent(object, this.root);
315
- return this.update();
316
- },
317
-
318
- _setTerrainHeight() {
319
- if (!this.root || !this.location) return;
320
- this._terrainBaseY ??= this.root.position[1];
321
- this.root.position[1] = this._terrainBaseY + (this._map?._terrain3D?._getElevation(this.location) ?? 0);
322
- },
323
-
324
- /**
325
- * Without an argument, removes this Leaflet layer. With an object, only detaches it:
326
- * geometry/program resources are not disposed, so it can be added again.
327
- * @param {Object} [object]
328
- * @returns {L.Layer}
329
- */
330
- remove(object) {
331
- if (object === undefined) return L.Layer.prototype.remove.call(this);
332
- this.setParent(object, null);
333
- return this.update();
334
- },
335
- });
336
-
337
- L.Layer.types['3d']._nextId = 0;
@@ -1,42 +0,0 @@
1
- import './3d.js';
2
-
3
- /** One GeoJSON batch, independent of the viewport, using the existing extrusion pipeline. */
4
- L.Layer.types.geojson = L.Layer.types['3d'].extend({
5
- _geojson: true,
6
-
7
- async _loadSource(area) {
8
- const { data, url } = this.options;
9
- if (typeof this.options.featureStyle !== 'function') {
10
- throw new Error('featureStyle must be a function');
11
- }
12
- if ((data !== undefined) === (url !== undefined)) {
13
- throw new Error('GeoJSON source requires either data or url');
14
- }
15
- if (data !== undefined) return data;
16
- if (typeof url !== 'string' || !url.trim()) throw new Error('Invalid GeoJSON URL');
17
- const response = await fetch(new URL(url, document.baseURI), { signal: area.request.signal });
18
- if (!response.ok) throw new Error(`Unable to load GeoJSON: HTTP ${response.status}`);
19
- return response.json();
20
- },
21
-
22
- _updateArea() {
23
- if (!this._map || !this._shared) return;
24
- if (!this._areas.has('geojson')) {
25
- this._areas.set('geojson', { request: new AbortController() });
26
- }
27
- this._pump();
28
- },
29
-
30
- getEvents() {
31
- return { terrainchange: this._onTerrainChange };
32
- },
33
-
34
- setData(data) {
35
- this.options.data = data;
36
- delete this.options.url;
37
- for (const area of this._areas.values()) this._releaseArea(area);
38
- this._areas.clear();
39
- this._updateArea();
40
- return this;
41
- },
42
- });