leaflet-city-mapper 0.0.1 → 0.0.2

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 (472) hide show
  1. package/README.md +15 -13
  2. package/cucumber.mjs +4 -0
  3. package/dist/leaflet-city-mapper.js +1 -1
  4. package/dist/leaflet-city-mapper.js.map +4 -4
  5. package/dist/utils/CELL.js +2 -0
  6. package/dist/utils/CELL.js.map +7 -0
  7. package/dist/utils/addBridges.js +2 -0
  8. package/dist/utils/addBridges.js.map +7 -0
  9. package/dist/utils/addRasterTile.js +2 -0
  10. package/dist/utils/addRasterTile.js.map +7 -0
  11. package/dist/utils/along.js +2 -0
  12. package/dist/utils/along.js.map +7 -0
  13. package/dist/utils/atmosphere.js +2 -0
  14. package/dist/utils/atmosphere.js.map +7 -0
  15. package/dist/utils/attach.js +2 -0
  16. package/dist/utils/attach.js.map +7 -0
  17. package/dist/utils/bindSunlight.js +2 -0
  18. package/dist/utils/bindSunlight.js.map +7 -0
  19. package/dist/utils/box.js +2 -0
  20. package/dist/utils/box.js.map +7 -0
  21. package/dist/utils/bridgeElevation.js +2 -0
  22. package/dist/utils/bridgeElevation.js.map +7 -0
  23. package/dist/utils/build.js +2 -0
  24. package/dist/utils/build.js.map +7 -0
  25. package/dist/utils/cameraControls.js +2 -0
  26. package/dist/utils/cameraControls.js.map +7 -0
  27. package/dist/utils/channel.js +2 -0
  28. package/dist/utils/channel.js.map +7 -0
  29. package/dist/utils/collider.js +2 -0
  30. package/dist/utils/collider.js.map +7 -0
  31. package/dist/utils/colliders.js +2 -0
  32. package/dist/utils/colliders.js.map +7 -0
  33. package/dist/utils/computeBounds.js +2 -0
  34. package/dist/utils/computeBounds.js.map +7 -0
  35. package/dist/utils/conformModelToTerrain.js +2 -0
  36. package/dist/utils/conformModelToTerrain.js.map +7 -0
  37. package/dist/utils/createMesh.js +2 -0
  38. package/dist/utils/createMesh.js.map +7 -0
  39. package/dist/utils/createProgram.js +3 -0
  40. package/dist/utils/createProgram.js.map +7 -0
  41. package/dist/utils/decodeDirectory.js +2 -0
  42. package/dist/utils/decodeDirectory.js.map +7 -0
  43. package/dist/utils/decodeHeader.js +2 -0
  44. package/dist/utils/decodeHeader.js.map +7 -0
  45. package/dist/utils/decodeModel.js +2 -0
  46. package/dist/utils/decodeModel.js.map +7 -0
  47. package/dist/utils/decompress.js +2 -0
  48. package/dist/utils/decompress.js.map +7 -0
  49. package/dist/utils/destroyTexture.js +2 -0
  50. package/dist/utils/destroyTexture.js.map +7 -0
  51. package/dist/utils/disposeMesh.js +2 -0
  52. package/dist/utils/disposeMesh.js.map +7 -0
  53. package/dist/utils/drawGeometry.js +2 -0
  54. package/dist/utils/drawGeometry.js.map +7 -0
  55. package/dist/utils/elevationWGSL.js +24 -0
  56. package/dist/utils/elevationWGSL.js.map +7 -0
  57. package/dist/utils/emptyNode.js +2 -0
  58. package/dist/utils/emptyNode.js.map +7 -0
  59. package/dist/utils/endZoom.js +2 -0
  60. package/dist/utils/endZoom.js.map +7 -0
  61. package/dist/utils/findFeature.js +2 -0
  62. package/dist/utils/findFeature.js.map +7 -0
  63. package/dist/utils/geometry.js +0 -1
  64. package/dist/utils/geometry.js.map +4 -4
  65. package/dist/utils/getElevation.js +2 -0
  66. package/dist/utils/getElevation.js.map +7 -0
  67. package/dist/utils/getHeader.js +2 -0
  68. package/dist/utils/getHeader.js.map +7 -0
  69. package/dist/utils/getZxy.js +2 -0
  70. package/dist/utils/getZxy.js.map +7 -0
  71. package/dist/utils/glass.js +2 -0
  72. package/dist/utils/glass.js.map +7 -0
  73. package/dist/utils/headlight.js +2 -0
  74. package/dist/utils/headlight.js.map +7 -0
  75. package/dist/utils/hit.js +2 -0
  76. package/dist/utils/hit.js.map +7 -0
  77. package/dist/utils/horizontalPosition.js +2 -0
  78. package/dist/utils/horizontalPosition.js.map +7 -0
  79. package/dist/utils/horizontalRay.js +2 -0
  80. package/dist/utils/horizontalRay.js.map +7 -0
  81. package/dist/utils/hull.js +2 -0
  82. package/dist/utils/hull.js.map +7 -0
  83. package/dist/utils/initSunlight.js +2 -0
  84. package/dist/utils/initSunlight.js.map +7 -0
  85. package/dist/utils/initTerrain.js +2 -0
  86. package/dist/utils/initTerrain.js.map +7 -0
  87. package/dist/utils/initTraffic.js +40 -0
  88. package/dist/utils/initTraffic.js.map +7 -0
  89. package/dist/utils/initWalk.js +2 -0
  90. package/dist/utils/initWalk.js.map +7 -0
  91. package/dist/utils/intersectMeshes.js +2 -0
  92. package/dist/utils/intersectMeshes.js.map +7 -0
  93. package/dist/utils/isClockWise.js +2 -0
  94. package/dist/utils/isClockWise.js.map +7 -0
  95. package/dist/utils/lampPostGeometry.js +2 -0
  96. package/dist/utils/lampPostGeometry.js.map +7 -0
  97. package/dist/utils/lightGeometry.js +2 -0
  98. package/dist/utils/lightGeometry.js.map +7 -0
  99. package/dist/utils/lightGrid.js +2 -0
  100. package/dist/utils/lightGrid.js.map +7 -0
  101. package/dist/utils/limbs.js +2 -0
  102. package/dist/utils/limbs.js.map +7 -0
  103. package/dist/utils/loadModel.js +2 -0
  104. package/dist/utils/loadModel.js.map +7 -0
  105. package/dist/utils/loadSource.js +2 -0
  106. package/dist/utils/loadSource.js.map +7 -0
  107. package/dist/utils/loadTerrain.js +2 -0
  108. package/dist/utils/loadTerrain.js.map +7 -0
  109. package/dist/utils/mapCamera.js +2 -0
  110. package/dist/utils/mapCamera.js.map +7 -0
  111. package/dist/utils/{shaders.js → materialShaders.js} +16 -8
  112. package/dist/utils/materialShaders.js.map +7 -0
  113. package/dist/utils/mirror.js +2 -0
  114. package/dist/utils/mirror.js.map +7 -0
  115. package/dist/utils/moonPosition.js +2 -0
  116. package/dist/utils/moonPosition.js.map +7 -0
  117. package/dist/utils/moves.js +2 -0
  118. package/dist/utils/moves.js.map +7 -0
  119. package/dist/utils/nativeEvents.js +2 -0
  120. package/dist/utils/nativeEvents.js.map +7 -0
  121. package/dist/utils/nativeGeometry.js +2 -0
  122. package/dist/utils/nativeGeometry.js.map +7 -0
  123. package/dist/utils/nativeLayer.js +2 -0
  124. package/dist/utils/nativeLayer.js.map +7 -0
  125. package/dist/utils/nodeMatrix.js +2 -0
  126. package/dist/utils/nodeMatrix.js.map +7 -0
  127. package/dist/utils/onAdd3DLayer.js +2 -0
  128. package/dist/utils/onAdd3DLayer.js.map +7 -0
  129. package/dist/utils/onAddSun.js +2 -0
  130. package/dist/utils/onAddSun.js.map +7 -0
  131. package/dist/utils/onClick.js +2 -0
  132. package/dist/utils/onClick.js.map +7 -0
  133. package/dist/utils/onMapChange.js +2 -0
  134. package/dist/utils/onMapChange.js.map +7 -0
  135. package/dist/utils/onPMTileAdd.js +2 -0
  136. package/dist/utils/onPMTileAdd.js.map +7 -0
  137. package/dist/utils/onPMTileRemove.js +2 -0
  138. package/dist/utils/onPMTileRemove.js.map +7 -0
  139. package/dist/utils/onPointerLeave.js +2 -0
  140. package/dist/utils/onPointerLeave.js.map +7 -0
  141. package/dist/utils/onPointerMove.js +2 -0
  142. package/dist/utils/onPointerMove.js.map +7 -0
  143. package/dist/utils/onRemove3DLayer.js +2 -0
  144. package/dist/utils/onRemove3DLayer.js.map +7 -0
  145. package/dist/utils/onRemoveSun.js +2 -0
  146. package/dist/utils/onRemoveSun.js.map +7 -0
  147. package/dist/utils/onTerrainAdd.js +2 -0
  148. package/dist/utils/onTerrainAdd.js.map +7 -0
  149. package/dist/utils/onTerrainChange.js +2 -0
  150. package/dist/utils/onTerrainChange.js.map +7 -0
  151. package/dist/utils/onTerrainRemove.js +2 -0
  152. package/dist/utils/onTerrainRemove.js.map +7 -0
  153. package/dist/utils/onZoomAnim.js +2 -0
  154. package/dist/utils/onZoomAnim.js.map +7 -0
  155. package/dist/utils/paints.js +2 -0
  156. package/dist/utils/paints.js.map +7 -0
  157. package/dist/utils/parseColor.js +2 -0
  158. package/dist/utils/parseColor.js.map +7 -0
  159. package/dist/utils/parts.js +2 -0
  160. package/dist/utils/parts.js.map +7 -0
  161. package/dist/utils/projectCelestialBody.js +2 -0
  162. package/dist/utils/projectCelestialBody.js.map +7 -0
  163. package/dist/utils/pump.js +2 -0
  164. package/dist/utils/pump.js.map +7 -0
  165. package/dist/utils/rasterTiles.js +2 -0
  166. package/dist/utils/rasterTiles.js.map +7 -0
  167. package/dist/utils/raycast.js +2 -0
  168. package/dist/utils/raycast.js.map +7 -0
  169. package/dist/utils/read.js +2 -0
  170. package/dist/utils/read.js.map +7 -0
  171. package/dist/utils/readAccessor.js +2 -0
  172. package/dist/utils/readAccessor.js.map +7 -0
  173. package/dist/utils/releaseArea.js +2 -0
  174. package/dist/utils/releaseArea.js.map +7 -0
  175. package/dist/utils/removeRasterTile.js +2 -0
  176. package/dist/utils/removeRasterTile.js.map +7 -0
  177. package/dist/utils/render.js +15 -0
  178. package/dist/utils/render.js.map +7 -0
  179. package/dist/utils/renderSunlight.js +13 -0
  180. package/dist/utils/renderSunlight.js.map +7 -0
  181. package/dist/utils/renderers.js +2 -0
  182. package/dist/utils/renderers.js.map +7 -0
  183. package/dist/utils/resizeSunlight.js +2 -0
  184. package/dist/utils/resizeSunlight.js.map +7 -0
  185. package/dist/utils/roofCoverage.js +2 -0
  186. package/dist/utils/roofCoverage.js.map +7 -0
  187. package/dist/utils/routeGeometry.js +2 -0
  188. package/dist/utils/routeGeometry.js.map +7 -0
  189. package/dist/utils/scheduledTrips.js +2 -0
  190. package/dist/utils/scheduledTrips.js.map +7 -0
  191. package/dist/utils/setGeoJSONData.js +2 -0
  192. package/dist/utils/setGeoJSONData.js.map +7 -0
  193. package/dist/utils/setHighlight.js +2 -0
  194. package/dist/utils/setHighlight.js.map +7 -0
  195. package/dist/utils/setPMTileOpacity.js +2 -0
  196. package/dist/utils/setPMTileOpacity.js.map +7 -0
  197. package/dist/utils/setPMTileZIndex.js +2 -0
  198. package/dist/utils/setPMTileZIndex.js.map +7 -0
  199. package/dist/utils/setParent.js +2 -0
  200. package/dist/utils/setParent.js.map +7 -0
  201. package/dist/utils/setTerrainHeight.js +2 -0
  202. package/dist/utils/setTerrainHeight.js.map +7 -0
  203. package/dist/utils/setVertexColor.js +2 -0
  204. package/dist/utils/setVertexColor.js.map +7 -0
  205. package/dist/utils/showFeature.js +2 -0
  206. package/dist/utils/showFeature.js.map +7 -0
  207. package/dist/utils/sizes.js +2 -0
  208. package/dist/utils/sizes.js.map +7 -0
  209. package/dist/utils/skin.js +2 -0
  210. package/dist/utils/skin.js.map +7 -0
  211. package/dist/utils/solarPosition.js +2 -0
  212. package/dist/utils/solarPosition.js.map +7 -0
  213. package/dist/utils/sortMeshes.js +2 -0
  214. package/dist/utils/sortMeshes.js.map +7 -0
  215. package/dist/utils/speed.js +2 -0
  216. package/dist/utils/speed.js.map +7 -0
  217. package/dist/utils/startZoom.js +2 -0
  218. package/dist/utils/startZoom.js.map +7 -0
  219. package/dist/utils/taillight.js +2 -0
  220. package/dist/utils/taillight.js.map +7 -0
  221. package/dist/utils/terrainAtlas.js +2 -0
  222. package/dist/utils/terrainAtlas.js.map +7 -0
  223. package/dist/utils/terrainElevation.js +2 -0
  224. package/dist/utils/terrainElevation.js.map +7 -0
  225. package/dist/utils/terrainGrid.js +2 -0
  226. package/dist/utils/terrainGrid.js.map +7 -0
  227. package/dist/utils/textureSampler.js +2 -0
  228. package/dist/utils/textureSampler.js.map +7 -0
  229. package/dist/utils/tileId.js +2 -0
  230. package/dist/utils/tileId.js.map +7 -0
  231. package/dist/utils/toLanes.js +2 -0
  232. package/dist/utils/toLanes.js.map +7 -0
  233. package/dist/utils/toSRGB.js +2 -0
  234. package/dist/utils/toSRGB.js.map +7 -0
  235. package/dist/utils/tooltip.js +3 -0
  236. package/dist/utils/tooltip.js.map +7 -0
  237. package/dist/utils/traffic.js +1 -1
  238. package/dist/utils/traffic.js.map +3 -3
  239. package/dist/utils/traverse.js +2 -0
  240. package/dist/utils/traverse.js.map +7 -0
  241. package/dist/utils/treeGeometry.js +2 -0
  242. package/dist/utils/treeGeometry.js.map +7 -0
  243. package/dist/utils/triangulate.js +2 -0
  244. package/dist/utils/triangulate.js.map +7 -0
  245. package/dist/utils/tripsAt.js +2 -0
  246. package/dist/utils/tripsAt.js.map +7 -0
  247. package/dist/utils/types.js +2 -0
  248. package/dist/utils/types.js.map +7 -0
  249. package/dist/utils/underEntry.js +2 -0
  250. package/dist/utils/underEntry.js.map +7 -0
  251. package/dist/utils/update.js +2 -0
  252. package/dist/utils/update.js.map +7 -0
  253. package/dist/utils/updateArea.js +2 -0
  254. package/dist/utils/updateArea.js.map +7 -0
  255. package/dist/utils/updateCamera.js +2 -0
  256. package/dist/utils/updateCamera.js.map +7 -0
  257. package/dist/utils/updatePointLights.js +2 -0
  258. package/dist/utils/updatePointLights.js.map +7 -0
  259. package/dist/utils/updateWorldMatrix.js +2 -0
  260. package/dist/utils/updateWorldMatrix.js.map +7 -0
  261. package/dist/utils/vehicleOffsets.js +2 -0
  262. package/dist/utils/vehicleOffsets.js.map +7 -0
  263. package/dist/utils/vehicles.js +1 -1
  264. package/dist/utils/vehicles.js.map +3 -3
  265. package/dist/utils/vertexNormals.js +2 -0
  266. package/dist/utils/vertexNormals.js.map +7 -0
  267. package/dist/utils/walk.js +1 -1
  268. package/dist/utils/walk.js.map +3 -3
  269. package/dist/utils/white.js +2 -0
  270. package/dist/utils/white.js.map +7 -0
  271. package/dist/utils/worldLights.js +2 -0
  272. package/dist/utils/worldLights.js.map +7 -0
  273. package/dist/utils/wrap.js +2 -0
  274. package/dist/utils/wrap.js.map +7 -0
  275. package/package.json +2 -4
  276. package/src/index.js +365 -50
  277. package/src/utils/CELL.js +4 -0
  278. package/src/utils/addBridges.js +66 -0
  279. package/src/utils/addRasterTile.js +112 -0
  280. package/src/utils/along.js +9 -0
  281. package/src/utils/atmosphere.js +20 -0
  282. package/src/utils/attach.js +255 -0
  283. package/src/utils/bindSunlight.js +12 -0
  284. package/src/utils/box.js +1 -0
  285. package/src/utils/bridgeElevation.js +18 -0
  286. package/src/utils/build.js +20 -0
  287. package/src/utils/cameraControls.js +287 -0
  288. package/src/utils/channel.js +4 -0
  289. package/src/utils/collider.js +62 -0
  290. package/src/utils/colliders.js +2 -0
  291. package/src/utils/computeBounds.js +17 -0
  292. package/src/utils/conformModelToTerrain.js +69 -0
  293. package/src/utils/createMesh.js +31 -0
  294. package/src/utils/createProgram.js +92 -0
  295. package/src/utils/decodeDirectory.js +40 -0
  296. package/src/utils/decodeHeader.js +15 -0
  297. package/src/utils/decodeModel.js +43 -0
  298. package/src/utils/decompress.js +5 -0
  299. package/src/utils/destroyTexture.js +7 -0
  300. package/src/utils/disposeMesh.js +13 -0
  301. package/src/utils/drawGeometry.js +122 -0
  302. package/src/utils/elevationWGSL.js +27 -0
  303. package/src/utils/emptyNode.js +9 -0
  304. package/src/utils/endZoom.js +15 -0
  305. package/src/utils/findFeature.js +49 -0
  306. package/src/utils/geometry.js +0 -254
  307. package/src/utils/getElevation.js +10 -0
  308. package/src/utils/getHeader.js +9 -0
  309. package/src/utils/getZxy.js +76 -0
  310. package/src/utils/glass.js +1 -0
  311. package/src/utils/headlight.js +1 -0
  312. package/src/utils/hit.js +41 -0
  313. package/src/utils/horizontalPosition.js +16 -0
  314. package/src/utils/horizontalRay.js +12 -0
  315. package/src/utils/hull.js +1 -0
  316. package/src/utils/initSunlight.js +9 -0
  317. package/src/utils/initTerrain.js +19 -0
  318. package/src/utils/initTraffic.js +93 -0
  319. package/src/utils/initWalk.js +72 -0
  320. package/src/utils/{picking.js → intersectMeshes.js} +121 -119
  321. package/src/utils/isClockWise.js +12 -0
  322. package/src/utils/lampPostGeometry.js +26 -0
  323. package/src/utils/lightGeometry.js +22 -0
  324. package/src/utils/{lighting.js → lightGrid.js} +50 -51
  325. package/src/utils/limbs.js +9 -0
  326. package/src/{scene/model.js → utils/loadModel.js} +37 -24
  327. package/src/utils/loadSource.js +17 -0
  328. package/src/utils/loadTerrain.js +65 -0
  329. package/src/utils/mapCamera.js +432 -0
  330. package/src/utils/{shaders.js → materialShaders.js} +243 -237
  331. package/src/utils/mirror.js +6 -0
  332. package/src/utils/moonPosition.js +17 -0
  333. package/src/utils/moves.js +11 -0
  334. package/src/utils/nativeEvents.js +77 -0
  335. package/src/utils/nativeGeometry.js +131 -0
  336. package/src/utils/nativeLayer.js +317 -0
  337. package/src/utils/nodeMatrix.js +22 -0
  338. package/src/utils/onAdd3DLayer.js +31 -0
  339. package/src/utils/onAddSun.js +147 -0
  340. package/src/utils/onClick.js +13 -0
  341. package/src/utils/onMapChange.js +16 -0
  342. package/src/utils/onPMTileAdd.js +15 -0
  343. package/src/utils/onPMTileRemove.js +8 -0
  344. package/src/utils/onPointerLeave.js +11 -0
  345. package/src/utils/onPointerMove.js +15 -0
  346. package/src/utils/onRemove3DLayer.js +78 -0
  347. package/src/utils/onRemoveSun.js +3 -0
  348. package/src/utils/onTerrainAdd.js +18 -0
  349. package/src/utils/onTerrainChange.js +13 -0
  350. package/src/utils/onTerrainRemove.js +40 -0
  351. package/src/utils/onZoomAnim.js +14 -0
  352. package/src/utils/paints.js +10 -0
  353. package/src/utils/parseColor.js +42 -0
  354. package/src/utils/parts.js +16 -0
  355. package/src/utils/projectCelestialBody.js +13 -0
  356. package/src/{scene/sources.js → utils/pump.js} +59 -98
  357. package/src/utils/rasterTiles.js +285 -0
  358. package/src/utils/raycast.js +60 -0
  359. package/src/utils/read.js +29 -0
  360. package/src/utils/readAccessor.js +68 -0
  361. package/src/utils/releaseArea.js +34 -0
  362. package/src/utils/removeRasterTile.js +13 -0
  363. package/src/{scene → utils}/render.js +112 -173
  364. package/src/utils/renderSunlight.js +170 -0
  365. package/src/utils/renderers.js +2 -0
  366. package/src/utils/resizeSunlight.js +15 -0
  367. package/src/utils/roofCoverage.js +47 -0
  368. package/src/utils/routeGeometry.js +22 -0
  369. package/src/utils/scheduledTrips.js +29 -0
  370. package/src/utils/setGeoJSONData.js +11 -0
  371. package/src/utils/setHighlight.js +13 -0
  372. package/src/utils/setPMTileOpacity.js +7 -0
  373. package/src/utils/setPMTileZIndex.js +7 -0
  374. package/src/utils/setParent.js +7 -0
  375. package/src/utils/setTerrainHeight.js +10 -0
  376. package/src/utils/setVertexColor.js +14 -0
  377. package/src/utils/showFeature.js +27 -0
  378. package/src/utils/sizes.js +1 -0
  379. package/src/utils/skin.js +2 -0
  380. package/src/utils/solarPosition.js +17 -0
  381. package/src/utils/sortMeshes.js +12 -0
  382. package/src/utils/speed.js +3 -0
  383. package/src/utils/startZoom.js +5 -0
  384. package/src/utils/taillight.js +1 -0
  385. package/src/utils/terrainAtlas.js +21 -0
  386. package/src/utils/terrainElevation.js +20 -0
  387. package/src/utils/terrainGrid.js +23 -0
  388. package/src/utils/textureSampler.js +10 -0
  389. package/src/utils/tileId.js +18 -0
  390. package/src/utils/toLanes.js +7 -0
  391. package/src/utils/toSRGB.js +1 -0
  392. package/src/utils/tooltip.js +6 -0
  393. package/src/utils/traffic.js +310 -85
  394. package/src/utils/traverse.js +6 -0
  395. package/src/utils/treeGeometry.js +45 -0
  396. package/src/utils/triangulate.js +100 -0
  397. package/src/utils/tripsAt.js +16 -0
  398. package/src/utils/types.js +8 -0
  399. package/src/utils/{control.js → underEntry.js} +1 -2
  400. package/src/utils/update.js +18 -0
  401. package/src/utils/updateArea.js +40 -0
  402. package/src/utils/updateCamera.js +32 -0
  403. package/src/utils/updatePointLights.js +38 -0
  404. package/src/utils/updateWorldMatrix.js +47 -0
  405. package/src/utils/vehicleOffsets.js +8 -0
  406. package/src/utils/vehicles.js +65 -69
  407. package/src/utils/vertexNormals.js +30 -0
  408. package/src/utils/walk.js +181 -66
  409. package/src/utils/white.js +1 -0
  410. package/src/utils/worldLights.js +25 -0
  411. package/src/utils/wrap.js +1 -0
  412. package/dist/scene/gpu.js +0 -3
  413. package/dist/scene/gpu.js.map +0 -7
  414. package/dist/scene/lighting.js +0 -9
  415. package/dist/scene/lighting.js.map +0 -7
  416. package/dist/scene/model.js +0 -2
  417. package/dist/scene/model.js.map +0 -7
  418. package/dist/scene/picking.js +0 -2
  419. package/dist/scene/picking.js.map +0 -7
  420. package/dist/scene/pmtiles.js +0 -2
  421. package/dist/scene/pmtiles.js.map +0 -7
  422. package/dist/scene/render.js +0 -15
  423. package/dist/scene/render.js.map +0 -7
  424. package/dist/scene/sources.js +0 -2
  425. package/dist/scene/sources.js.map +0 -7
  426. package/dist/types/3d.js +0 -2
  427. package/dist/types/3d.js.map +0 -7
  428. package/dist/types/geojson.js +0 -2
  429. package/dist/types/geojson.js.map +0 -7
  430. package/dist/types/pmtiles.js +0 -2
  431. package/dist/types/pmtiles.js.map +0 -7
  432. package/dist/types/sunlight.js +0 -2
  433. package/dist/types/sunlight.js.map +0 -7
  434. package/dist/types/terrain.js +0 -24
  435. package/dist/types/terrain.js.map +0 -7
  436. package/dist/types/traffic.js +0 -41
  437. package/dist/types/traffic.js.map +0 -7
  438. package/dist/types/walk.js +0 -2
  439. package/dist/types/walk.js.map +0 -7
  440. package/dist/utils/control.js +0 -2
  441. package/dist/utils/control.js.map +0 -7
  442. package/dist/utils/lighting.js +0 -2
  443. package/dist/utils/lighting.js.map +0 -7
  444. package/dist/utils/model.js +0 -2
  445. package/dist/utils/model.js.map +0 -7
  446. package/dist/utils/picking.js +0 -2
  447. package/dist/utils/picking.js.map +0 -7
  448. package/dist/utils/pmtiles.js +0 -2
  449. package/dist/utils/pmtiles.js.map +0 -7
  450. package/dist/utils/scene.js +0 -2
  451. package/dist/utils/scene.js.map +0 -7
  452. package/dist/utils/shaders.js.map +0 -7
  453. package/dist/utils/sun.js +0 -2
  454. package/dist/utils/sun.js.map +0 -7
  455. package/dist/utils/terrain.js +0 -2
  456. package/dist/utils/terrain.js.map +0 -7
  457. package/src/scene/gpu.js +0 -438
  458. package/src/scene/lighting.js +0 -193
  459. package/src/scene/picking.js +0 -150
  460. package/src/scene/pmtiles.js +0 -94
  461. package/src/types/3d.js +0 -337
  462. package/src/types/geojson.js +0 -42
  463. package/src/types/pmtiles.js +0 -143
  464. package/src/types/sunlight.js +0 -142
  465. package/src/types/terrain.js +0 -331
  466. package/src/types/traffic.js +0 -356
  467. package/src/types/walk.js +0 -219
  468. package/src/utils/model.js +0 -178
  469. package/src/utils/pmtiles.js +0 -79
  470. package/src/utils/scene.js +0 -102
  471. package/src/utils/sun.js +0 -71
  472. package/src/utils/terrain.js +0 -78
package/dist/types/3d.js DELETED
@@ -1,2 +0,0 @@
1
- import*as s from"../utils/geometry.js";import*as n from"../scene/gpu.js";import*as l from"../scene/lighting.js";import*as p from"../scene/model.js";import*as a from"../scene/picking.js";import*as _ from"../scene/pmtiles.js";import*as m from"../utils/pmtiles.js";import*as h from"../scene/render.js";import*as d from"../utils/scene.js";import*as u from"../scene/sources.js";L.Layer.types["3d"]=L.Layer.extend({color(e){return s.parseColor(e)},_setVertexColor(e,r,t,i){return s.setVertexColor(e,r,t,i),this.update()},_triangulate(e,r){return s.triangulate(e,r)},_isClockWise(e){return s.isClockWise(e)},_treeGeometry(e,r,t){return s.treeGeometry(e,r,t)},_lightGeometry(e,r,t){return s.lightGeometry(e,r,t)},_lampPostGeometry(e,r,t){return s.lampPostGeometry(e,r,t)},_attach(e){return n.attach(this,e)},_destroyTexture(e){return n.destroyTexture(this,e)},_createProgram(e){return n.createProgram(this,e)},_removeProgram(e){return n.removeProgram(e)},_createMesh(e,r,t){return n.createMesh(this,e,r,t)},_disposeMesh(e){return n.disposeMesh(this,e)},_computeBounds(e){return s.computeBounds(e)},_drawGeometry(e,r,t,i){return n.drawGeometry(this,e,r,t,i)},_initSunlight(){return l.initSunlight(this)},_resizeSunlight(e){return l.resizeSunlight(this,e)},_bindSunlight(){return l.bindSunlight(this)},_updatePointLights(){return l.updatePointLights(this)},_renderSunlight(e,r,t){return l.renderSunlight(this,e,r,t)},_loadModel(){return p.loadModel(this)},raycast(e,r,t){return a.raycast(this,e,r,t)},_findFeature(e){return a.findFeature(this,e)},_setHighlight(e){return a.setHighlight(this,e)},_showFeature(e,r){return a.showFeature(this,e,r)},_onPointerMove(e){return a.onPointerMove(this,e)},_onClick(e){return a.onClick(this,e)},_onPointerLeave(){return a.onPointerLeave(this)},_read(e,r,t){return _.read(this,e,r,t)},_decompress(e,r){return m.decompress(e,r)},getHeader(){return _.getHeader(this)},getZxy(e,r,t,i){return _.getZxy(this,e,r,t,i)},update(){return h.update(this)},_onMapChange(){return h.onMapChange(this)},_getTileLevel(){return h.getTileLevel(this)},_startZoom(){return h.startZoom(this)},_endZoom(){return h.endZoom(this)},_render(){return h.render(this)},setParent(e,r){return d.setParent(e,r)},traverse(e,r){return d.traverse(e,r)},_updateWorldMatrix(e){return d.updateWorldMatrix(e)},_updateCamera(e){return d.updateCamera(e)},_onTerrainChange(){return u.onTerrainChange(this)},_updateArea(){return u.updateArea(this)},_pump(){return u.pump(this)},_loadSource(e){return u.loadSource(this,e)},_releaseArea(e){return u.releaseArea(this,e)},_updateStatus(e){return u.updateStatus(this,e)},statics:{_renderers:new WeakMap},options:{ariaLabel:"3D scene"},initialize(e){L.Util.setOptions(this,e);const r=!this._geojson&&/\.(glb|gltf)(?:[?#]|$)/i.test(this.options.url);this.modelUrl=r?this.options.url:null,this.url=this.options.url&&!r&&!this._geojson?new URL(this.options.url,document.baseURI).href:null,this._directories=new Map,this.options.center&&(this.location=new L.LatLng(this.options.center[0],this.options.center[1])),this._areas=new Map,this._inflight=0,this._added=Promise.withResolvers(),queueMicrotask(async()=>{try{this.root=d.emptyNode(),this.raycaster={origin:[0,0,0],direction:[0,0,0]},(this.url||this._geojson)&&(this.group=this.root,this.url&&(this.header=await this.getHeader())),this._map&&(await this._attach(this._map),this._added.resolve()),this.modelUrl&&await this._loadModel(),this._shared&&this.update(),this.fire("ready")}catch(t){this.fire("error",{error:t})}})},onAdd(e){if(!this.location){const r=e.getCenter();this.location=new L.LatLng(r.lat,r.lng)}(this.url||this._geojson||this.options.tooltipContent||this.modelUrl)&&(this.container=e.getContainer(),this.options.tooltipContent&&(this._tooltip=L.DomUtil.create("div","leaflet-3d-tooltip",this.container),this._tooltip.hidden=!0,this._tooltip.setAttribute("role","tooltip"),this._tooltip.setAttribute("aria-live","polite"),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"),L.DomEvent.on(this.container,{mousemove:this._onPointerMove,click:this._onClick,mouseleave:this._onPointerLeave},this)),this.root&&this._attach(e).then(()=>this._added.resolve(),r=>this.fire("error",{error:r}))},getEvents(){return this.url?{moveend:this._updateArea,zoomend:this._updateArea,rotate:this._updateArea,pitch:this._updateArea,resize:this._updateArea,terrainchange:this._onTerrainChange}:{}},onRemove(e){this._added=Promise.withResolvers(),this.container&&(this._onPointerLeave(),L.DomEvent.off(this.container,{mousemove:this._onPointerMove,click:this._onClick,mouseleave:this._onPointerLeave},this),this.container=null);for(const t of this._areas.values())this._releaseArea(t);this._areas.clear(),this._tooltip?.remove(),this._tooltip=null,(this.url||this._geojson)&&this._updateStatus(!1);const r=this._shared;if(r){if(this.setParent(this.root,null),r._layers.delete(this),r===this)if(e.off("move zoom rotate pitch resize viewreset layeradd layerremove",this._onMapChange,this),e.off("zoomstart",this._startZoom,this),e.off("zoomanim",this.update,this),e.off("zoomend",this._endZoom,this),cancelAnimationFrame(this._frame),this._frame=null,this._queued=!1,this._layers.size){const t=this._layers.values().next().value;for(const i of["_layers","_sceneOrigin","_size","_zoomLevel","_zoomTransitions","_cursor","_roofRaster","_roofTiles"])t[i]=this[i],delete this[i];for(const i of t._layers)i._shared=t;L.Layer.types["3d"]._renderers.set(e,t),e.on("move zoom rotate pitch resize viewreset layeradd layerremove",t._onMapChange,t),e.on("zoomstart",t._startZoom,t),e.on("zoomanim",t.update,t),e.on("zoomend",t._endZoom,t),t.update()}else{this._roofRaster&&this._destroyTexture(this._roofRaster.texture.texture),this._roofRaster=null;for(const o of this._roofTiles?.values()||[])this._destroyTexture(o.texture);this._roofTiles=null;for(const o of this._zoomTransitions?.keys()||[])o.play();this._zoomTransitions=null,this.renderer.canvas.remove();const t=this.renderer,i=[t.depthTexture,t.roofFallbackTexture.texture,t.uniformBuffer,t.sunlight?.texture,t.sunlight?.buffer,t.sunlight?.lights].filter(Boolean);t.device.queue.onSubmittedWorkDone().then(()=>{for(const o of i)o.destroy();t.device.destroy()},o=>{this.fire("error",{error:o}),t.device.destroy()}),L.Layer.types["3d"]._renderers.delete(e);for(const o of["_layers","_sceneOrigin","_size","_zoomLevel","_cursor"])delete this[o]}else r.update();this._shared=null,this.renderer=this.scene=this.camera=null}},add(e){return this.setParent(e,this.root),this.update()},_setTerrainHeight(){!this.root||!this.location||(this._terrainBaseY??=this.root.position[1],this.root.position[1]=this._terrainBaseY+(this._map?._terrain3D?._getElevation(this.location)??0))},remove(e){return e===void 0?L.Layer.prototype.remove.call(this):(this.setParent(e,null),this.update())}}),L.Layer.types["3d"]._nextId=0;
2
- //# sourceMappingURL=3d.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/3d.js"],
4
- "sourcesContent": ["/**\n * The '3d' layer type, loaded on demand by src/index.js.\n *\n * A native WebGPU scene drawn above the map tiles and kept in sync with the map camera\n * (center, zoom, bearing, pitch and zoom animations).\n *\n * No rendering dependencies. Use the `ready` event before using the helpers.\n * All instances on one map share a canvas, scene and camera, with one group per layer.\n *\n * World coordinates are metres relative to `location`: x east, y up, z south.\n * The shared scene instead uses the first attached layer's origin. `root` converts\n * each layer's local metres into that shared space, including latitude scaling.\n *\n * Lifecycle: initialize CPU state -> attach shared GPU device -> load configured\n * data/model -> ready. Removal cancels source work and detaches this layer only;\n * the last removal destroys the context. Model CPU arrays/images survive for re-add.\n *\n * This file holds the Leaflet lifecycle and explicit delegates to scene/ operations.\n * Stateless computations live in utils/; scene/ owns loading, GPU resources and interaction.\n * PMTiles v3 reading is implemented directly by this layer. Models are static triangles, without\n * animation, skinning, morph targets, normal maps or required extensions.\n *\n * Events: ready; error {error}; progress {enabled, loaded, skipped, pending, errors};\n * featurehover/featureclick {feature, originalEvent}. A feature may be null on a miss.\n * Picking tests geometry, not texture alpha: a transparent texel can still be hit.\n *\n * @example\n * new L.Layer({ source: { url: 'tower.glb', center: [48.8582601, 2.29449985] } }).addTo(map);\n * new L.Layer({ source: { type: '3d', url: 'buildings.pmtiles', featureStyle }, attribution }).addTo(map);\n * new L.Layer({ source: { type: 'terrain', url: 'terrain.pmtiles' } }).addTo(map);\n * new L.Layer({ source: { url: 'orthophotos.pmtiles', maxZoom: 24 } }).addTo(map);\n *\n * @typedef {Object} Layer3DOptions The `source` object; `pane`/`attribution` stay standard L.Layer options.\n * @property {string} [type] 'pmtiles' (raster tiles), '3d' (WebGPU scene) or 'terrain'; see L.Layer.types.\n * @property {number[]} [center] Local origin [lat,lng]; defaults to the first map center.\n * @property {number[]} [rotation] Model Euler rotation [x,y,z] in radians, YXZ order.\n * @property {number[]} [scale] Model scale [x,y,z]; independent of geographic scaling.\n * @property {string} [url] GLB/glTF model URL (loaded before ready), or PMTiles URL containing\n * Polygon/MultiPolygon or tree/light Point GeoJSON ('3d'), raster tiles ('pmtiles') or Float32 DEM ('terrain').\n * @property {function(Object): (ExtrusionStyle|null)} [featureStyle] Source styling; null skips.\n * @property {function(PickedFeature): (Node|string)} [tooltipContent] No HTML string evaluation.\n * @property {string} [ariaLabel='3D scene'] Shared canvas accessible name.\n * @property {boolean} [nightLight=false] Point sources: emissive bulbs and local illumination.\n * @property {boolean} [nightSparkle=false] Model: sparse luminous points at night.\n *\n * @typedef {Object} ExtrusionStyle\n * @property {number} top Roof height in metres; must exceed bottom.\n * @property {number} [bottom=0] Nonnegative base height; positive values create an underside.\n * @property {number|string|Object} [color=0xd9b38c] RGB/CSS color, or linear-space {h,s,l}.\n * @property {number} [trunkRadius] Point trees: trunk radius in metres.\n * @property {number} [crownRadius] Point trees: maximum crown radius in metres.\n * @property {number} [crownBottom] Point trees: crown base in metres, between bottom and top.\n * @property {string} [crownShape='round'] Point trees: 'round' or 'cone' schematic crown.\n * @property {number|string|Object} [trunkColor=0x72513a] Point trees: bark color.\n * @property {number} [lightRadius] Point lights: estimated ground reach in metres; top is emitter height.\n * @property {number} [lightFlux] Point lights: luminous flux in lumens.\n *\n * @typedef {Object} PickedFeature\n * @property {string|number} id Source feature id or configured model URL.\n * @property {Object} properties GeoJSON properties or model-level glTF extras.\n * @property {Object} mesh Intersected mesh.\n * @property {number[]} point Intersection [x,y,z] in shared scene metres, not layer-local metres.\n * @property {Object} [model] Configured model root; absent for source polygons.\n * @property {number} [vertexStart] First polygon vertex in the batched mesh.\n * @property {number} [vertexEnd] Exclusive end of the polygon's vertex range.\n *\n * @typedef {Object} SourceArea\n * @property {Object} coords Archive block {z,x,y}; z is header.minZoom, not display zoom.\n * @property {AbortController} request Cancellation also prevents attaching obsolete results.\n * @property {boolean} [started] Enqueued work has consumed a concurrency slot.\n * @property {boolean} [done] Geometry built successfully, including empty blocks.\n * @property {Object|null} [mesh] One batched GPU mesh per non-empty block.\n * @property {number} [buildings] Emitted feature count, not number of triangles.\n * @property {number} [skipped] Features intentionally skipped by featureStyle.\n * @property {string} [error] Failed load/build message; reported through error and progress.\n *\n * @since leaflet-rotate (v0.6.0)\n */\n\nimport * as shapes from '../utils/geometry.js';\nimport * as gpu from '../scene/gpu.js';\nimport * as lighting from '../scene/lighting.js';\nimport * as model from '../scene/model.js';\nimport * as picking from '../scene/picking.js';\nimport * as pmtiles from '../scene/pmtiles.js';\nimport * as archive from '../utils/pmtiles.js';\nimport * as render from '../scene/render.js';\nimport * as graph from '../utils/scene.js';\nimport * as sources from '../scene/sources.js';\n\nL.Layer.types['3d'] = L.Layer.extend({\n color(value) { return shapes.parseColor(value); },\n _setVertexColor(mesh, start, end, color) { shapes.setVertexColor(mesh, start, end, color); return this.update(); },\n _triangulate(contour, holes) { return shapes.triangulate(contour, holes); },\n _isClockWise(points) { return shapes.isClockWise(points); },\n _treeGeometry(point, style, addTriangle) { return shapes.treeGeometry(point, style, addTriangle); },\n _lightGeometry(point, style, addTriangle) { return shapes.lightGeometry(point, style, addTriangle); },\n _lampPostGeometry(point, style, addTriangle) { return shapes.lampPostGeometry(point, style, addTriangle); },\n _attach(map) { return gpu.attach(this, map); },\n _destroyTexture(texture) { return gpu.destroyTexture(this, texture); },\n _createProgram(material) { return gpu.createProgram(this, material); },\n _removeProgram(program) { return gpu.removeProgram(program); },\n _createMesh(data, material, usage) { return gpu.createMesh(this, data, material, usage); },\n _disposeMesh(mesh) { return gpu.disposeMesh(this, mesh); },\n _computeBounds(geometry) { return shapes.computeBounds(geometry); },\n _drawGeometry(mesh, pass, cullMode, frontFace) { return gpu.drawGeometry(this, mesh, pass, cullMode, frontFace); },\n _initSunlight() { return lighting.initSunlight(this); },\n _resizeSunlight(size) { return lighting.resizeSunlight(this, size); },\n _bindSunlight() { return lighting.bindSunlight(this); },\n _updatePointLights() { return lighting.updatePointLights(this); },\n _renderSunlight(encoder, meshes, sunlight) { return lighting.renderSunlight(this, encoder, meshes, sunlight); },\n _loadModel() { return model.loadModel(this); },\n raycast(event, objects, recursive) { return picking.raycast(this, event, objects, recursive); },\n _findFeature(event) { return picking.findFeature(this, event); },\n _setHighlight(feature) { return picking.setHighlight(this, feature); },\n _showFeature(feature, event) { return picking.showFeature(this, feature, event); },\n _onPointerMove(event) { return picking.onPointerMove(this, event); },\n _onClick(event) { return picking.onClick(this, event); },\n _onPointerLeave() { return picking.onPointerLeave(this); },\n _read(offset, length, signal) { return pmtiles.read(this, offset, length, signal); },\n _decompress(data, compression) { return archive.decompress(data, compression); },\n getHeader() { return pmtiles.getHeader(this); },\n getZxy(z, x, y, signal) { return pmtiles.getZxy(this, z, x, y, signal); },\n update() { return render.update(this); },\n _onMapChange() { return render.onMapChange(this); },\n _getTileLevel() { return render.getTileLevel(this); },\n _startZoom() { return render.startZoom(this); },\n _endZoom() { return render.endZoom(this); },\n _render() { return render.render(this); },\n setParent(node, parent) { return graph.setParent(node, parent); },\n traverse(node, callback) { return graph.traverse(node, callback); },\n _updateWorldMatrix(node) { return graph.updateWorldMatrix(node); },\n _updateCamera(camera) { return graph.updateCamera(camera); },\n _onTerrainChange() { return sources.onTerrainChange(this); },\n _updateArea() { return sources.updateArea(this); },\n _pump() { return sources.pump(this); },\n _loadSource(area) { return sources.loadSource(this, area); },\n _releaseArea(area) { return sources.releaseArea(this, area); },\n _updateStatus(enabled) { return sources.updateStatus(this, enabled); },\n\n statics: {\n /** Rendering owner per map; entries are removed on the last layer removal. */\n _renderers: new WeakMap(),\n },\n\n options: {\n // Accessible description of the canvas.\n ariaLabel: '3D scene',\n },\n\n /**\n * @param {Layer3DOptions} [options] World origin comes from center or the first map centre.\n * Public state: `location` is fixed after first addition; `root` is this layer's\n * transform; `group` aliases root only for sources; `model` is the configured\n * model wrapper. `_shared` references the rendering owner (a '3d' layer);\n * `scene`, `camera` and `renderer` alias its resources while attached.\n *\n */\n initialize(options) {\n L.Util.setOptions(this, options);\n // ponytail: models are recognised by extension; extensionless model URLs need a .glb/.gltf suffix or query.\n const model = !this._geojson && /\\.(glb|gltf)(?:[?#]|$)/i.test(this.options.url);\n this.modelUrl = model ? this.options.url : null;\n this.url = this.options.url && !model && !this._geojson ? new URL(this.options.url, document.baseURI).href : null;\n this._directories = new Map();\n if (this.options.center) {\n this.location = new L.LatLng(this.options.center[0], this.options.center[1]);\n }\n /** @type {Map<string, SourceArea>} Keys are archive x/y, not screen tiles. */\n this._areas = new Map();\n // Counts pending archive/build tasks, including ones cancelled after a pan.\n this._inflight = 0;\n // Gate GPU work on attachment; replaced on removal to support delayed loads.\n this._added = Promise.withResolvers();\n // Defer initialization so callers can subscribe to ready/error after construction.\n queueMicrotask(async () => {\n try {\n this.root = graph.emptyNode();\n this.raycaster = {\n origin: [0, 0, 0],\n direction: [0, 0, 0]\n };\n if (this.url || this._geojson) {\n this.group = this.root;\n if (this.url) this.header = await this.getHeader();\n }\n if (this._map) {\n await this._attach(this._map);\n this._added.resolve();\n }\n if (this.modelUrl) await this._loadModel();\n if (this._shared) this.update();\n this.fire('ready');\n } catch (error) {\n this.fire('error', { error });\n }\n });\n },\n\n /** Attach interaction immediately; initialization may finish before or after onAdd. */\n onAdd(map) {\n if (!this.location) {\n const center = map.getCenter();\n this.location = new L.LatLng(center.lat, center.lng);\n }\n if (this.url || this._geojson || this.options.tooltipContent || this.modelUrl) {\n this.container = map.getContainer();\n if (this.options.tooltipContent) {\n this._tooltip = L.DomUtil.create('div', 'leaflet-3d-tooltip', this.container);\n this._tooltip.hidden = true;\n this._tooltip.setAttribute('role', 'tooltip');\n this._tooltip.setAttribute('aria-live', 'polite');\n 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';\n }\n L.DomEvent.on(this.container, {\n mousemove: this._onPointerMove,\n click: this._onClick,\n mouseleave: this._onPointerLeave,\n }, this);\n }\n if (this.root) {\n this._attach(map).then(() => this._added.resolve(), error => this.fire('error', { error }));\n }\n },\n\n /** Reconcile source coverage when the visible ground footprint changes. */\n getEvents() {\n return this.url ? {\n moveend: this._updateArea,\n zoomend: this._updateArea,\n rotate: this._updateArea,\n pitch: this._updateArea,\n resize: this._updateArea,\n terrainchange: this._onTerrainChange,\n } : {};\n },\n\n /** Release source meshes/UI; retain manually added objects and model CPU data. */\n onRemove(map) {\n this._added = Promise.withResolvers();\n if (this.container) {\n this._onPointerLeave();\n L.DomEvent.off(this.container, {\n mousemove: this._onPointerMove,\n click: this._onClick,\n mouseleave: this._onPointerLeave,\n }, this);\n this.container = null;\n }\n for (const area of this._areas.values()) this._releaseArea(area);\n this._areas.clear();\n this._tooltip?.remove();\n this._tooltip = null;\n if (this.url || this._geojson) this._updateStatus(false);\n const shared = this._shared;\n if (!shared) return;\n this.setParent(this.root, null);\n shared._layers.delete(this);\n if (shared === this) {\n map.off('move zoom rotate pitch resize viewreset layeradd layerremove', this._onMapChange, this);\n map.off('zoomstart', this._startZoom, this);\n map.off('zoomanim', this.update, this);\n map.off('zoomend', this._endZoom, this);\n cancelAnimationFrame(this._frame);\n this._frame = null;\n this._queued = false;\n if (this._layers.size) {\n // Keep the original scene origin and GPU resources when ownership changes.\n const next = this._layers.values().next().value;\n for (const key of ['_layers', '_sceneOrigin', '_size', '_zoomLevel', '_zoomTransitions', '_cursor', '_roofRaster', '_roofTiles']) {\n next[key] = this[key];\n delete this[key];\n }\n for (const layer of next._layers) layer._shared = next;\n L.Layer.types['3d']._renderers.set(map, next);\n map.on('move zoom rotate pitch resize viewreset layeradd layerremove', next._onMapChange, next);\n map.on('zoomstart', next._startZoom, next);\n map.on('zoomanim', next.update, next);\n map.on('zoomend', next._endZoom, next);\n next.update();\n } else {\n if (this._roofRaster) this._destroyTexture(this._roofRaster.texture.texture);\n this._roofRaster = null;\n for (const source of this._roofTiles?.values() || []) this._destroyTexture(source.texture);\n this._roofTiles = null;\n for (const animation of this._zoomTransitions?.keys() || []) animation.play();\n this._zoomTransitions = null;\n this.renderer.canvas.remove();\n const renderer = this.renderer;\n const resources = [renderer.depthTexture, renderer.roofFallbackTexture.texture, renderer.uniformBuffer,\n renderer.sunlight?.texture, renderer.sunlight?.buffer, renderer.sunlight?.lights].filter(Boolean);\n renderer.device.queue.onSubmittedWorkDone().then(() => {\n for (const resource of resources) resource.destroy();\n renderer.device.destroy();\n }, error => {\n this.fire('error', { error });\n renderer.device.destroy();\n });\n L.Layer.types['3d']._renderers.delete(map);\n for (const key of ['_layers', '_sceneOrigin', '_size', '_zoomLevel', '_cursor']) delete this[key];\n }\n } else shared.update();\n this._shared = null;\n this.renderer = this.scene = this.camera = null;\n },\n\n /**\n * Adds a scene node or mesh in layer-local coordinates and schedules a redraw.\n * Requires initialization and a compatible scene node.\n * @param {Object} object\n * @returns {L.Layer} This layer.\n */\n add(object) {\n this.setParent(object, this.root);\n return this.update();\n },\n\n _setTerrainHeight() {\n if (!this.root || !this.location) return;\n this._terrainBaseY ??= this.root.position[1];\n this.root.position[1] = this._terrainBaseY + (this._map?._terrain3D?._getElevation(this.location) ?? 0);\n },\n\n /**\n * Without an argument, removes this Leaflet layer. With an object, only detaches it:\n * geometry/program resources are not disposed, so it can be added again.\n * @param {Object} [object]\n * @returns {L.Layer}\n */\n remove(object) {\n if (object === undefined) return L.Layer.prototype.remove.call(this);\n this.setParent(object, null);\n return this.update();\n },\n});\n\nL.Layer.types['3d']._nextId = 0;\n"],
5
- "mappings": "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",
6
- "names": ["shapes", "gpu", "lighting", "model", "picking", "pmtiles", "archive", "render", "graph", "sources", "value", "mesh", "start", "end", "color", "contour", "holes", "points", "point", "style", "addTriangle", "map", "texture", "material", "program", "data", "usage", "geometry", "pass", "cullMode", "frontFace", "size", "encoder", "meshes", "sunlight", "event", "objects", "recursive", "feature", "offset", "length", "signal", "compression", "z", "x", "y", "node", "parent", "callback", "camera", "area", "enabled", "options", "error", "center", "shared", "next", "key", "layer", "source", "animation", "renderer", "resources", "resource", "object"]
7
- }
@@ -1,2 +0,0 @@
1
- import"./3d.js";L.Layer.types.geojson=L.Layer.types["3d"].extend({_geojson:!0,async _loadSource(r){const{data:e,url:t}=this.options;if(typeof this.options.featureStyle!="function")throw new Error("featureStyle must be a function");if(e!==void 0==(t!==void 0))throw new Error("GeoJSON source requires either data or url");if(e!==void 0)return e;if(typeof t!="string"||!t.trim())throw new Error("Invalid GeoJSON URL");const s=await fetch(new URL(t,document.baseURI),{signal:r.request.signal});if(!s.ok)throw new Error(`Unable to load GeoJSON: HTTP ${s.status}`);return s.json()},_updateArea(){!this._map||!this._shared||(this._areas.has("geojson")||this._areas.set("geojson",{request:new AbortController}),this._pump())},getEvents(){return{terrainchange:this._onTerrainChange}},setData(r){this.options.data=r,delete this.options.url;for(const e of this._areas.values())this._releaseArea(e);return this._areas.clear(),this._updateArea(),this}});
2
- //# sourceMappingURL=geojson.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/geojson.js"],
4
- "sourcesContent": ["import './3d.js';\r\n\r\n/** One GeoJSON batch, independent of the viewport, using the existing extrusion pipeline. */\r\nL.Layer.types.geojson = L.Layer.types['3d'].extend({\r\n _geojson: true,\r\n\r\n async _loadSource(area) {\r\n const { data, url } = this.options;\r\n if (typeof this.options.featureStyle !== 'function') {\r\n throw new Error('featureStyle must be a function');\r\n }\r\n if ((data !== undefined) === (url !== undefined)) {\r\n throw new Error('GeoJSON source requires either data or url');\r\n }\r\n if (data !== undefined) return data;\r\n if (typeof url !== 'string' || !url.trim()) throw new Error('Invalid GeoJSON URL');\r\n const response = await fetch(new URL(url, document.baseURI), { signal: area.request.signal });\r\n if (!response.ok) throw new Error(`Unable to load GeoJSON: HTTP ${response.status}`);\r\n return response.json();\r\n },\r\n\r\n _updateArea() {\r\n if (!this._map || !this._shared) return;\r\n if (!this._areas.has('geojson')) {\r\n this._areas.set('geojson', { request: new AbortController() });\r\n }\r\n this._pump();\r\n },\r\n\r\n getEvents() {\r\n return { terrainchange: this._onTerrainChange };\r\n },\r\n\r\n setData(data) {\r\n this.options.data = data;\r\n delete this.options.url;\r\n for (const area of this._areas.values()) this._releaseArea(area);\r\n this._areas.clear();\r\n this._updateArea();\r\n return this;\r\n },\r\n});\r\n"],
5
- "mappings": "AAAA,MAAO,UAGP,EAAE,MAAM,MAAM,QAAU,EAAE,MAAM,MAAM,IAAI,EAAE,OAAO,CACjD,SAAU,GAEV,MAAM,YAAYA,EAAM,CACtB,KAAM,CAAE,KAAAC,EAAM,IAAAC,CAAI,EAAI,KAAK,QAC3B,GAAI,OAAO,KAAK,QAAQ,cAAiB,WACvC,MAAM,IAAI,MAAM,iCAAiC,EAEnD,GAAKD,IAAS,SAAgBC,IAAQ,QACpC,MAAM,IAAI,MAAM,4CAA4C,EAE9D,GAAID,IAAS,OAAW,OAAOA,EAC/B,GAAI,OAAOC,GAAQ,UAAY,CAACA,EAAI,KAAK,EAAG,MAAM,IAAI,MAAM,qBAAqB,EACjF,MAAMC,EAAW,MAAM,MAAM,IAAI,IAAID,EAAK,SAAS,OAAO,EAAG,CAAE,OAAQF,EAAK,QAAQ,MAAO,CAAC,EAC5F,GAAI,CAACG,EAAS,GAAI,MAAM,IAAI,MAAM,gCAAgCA,EAAS,MAAM,EAAE,EACnF,OAAOA,EAAS,KAAK,CACvB,EAEA,aAAc,CACR,CAAC,KAAK,MAAQ,CAAC,KAAK,UACnB,KAAK,OAAO,IAAI,SAAS,GAC5B,KAAK,OAAO,IAAI,UAAW,CAAE,QAAS,IAAI,eAAkB,CAAC,EAE/D,KAAK,MAAM,EACb,EAEA,WAAY,CACV,MAAO,CAAE,cAAe,KAAK,gBAAiB,CAChD,EAEA,QAAQF,EAAM,CACZ,KAAK,QAAQ,KAAOA,EACpB,OAAO,KAAK,QAAQ,IACpB,UAAWD,KAAQ,KAAK,OAAO,OAAO,EAAG,KAAK,aAAaA,CAAI,EAC/D,YAAK,OAAO,MAAM,EAClB,KAAK,YAAY,EACV,IACT,CACF,CAAC",
6
- "names": ["area", "data", "url", "response"]
7
- }
@@ -1,2 +0,0 @@
1
- import"./3d.js";import{read as h,getHeader as c,getZxy as d}from"../scene/pmtiles.js";import{decompress as u}from"../utils/pmtiles.js";L.Layer.types.pmtiles=L.TileLayer.extend({_read(e,r,t){return h(this,e,r,t)},_decompress(e,r){return u(e,r)},getHeader(){return c(this)},getZxy(e,r,t,i){return d(this,e,r,t,i)},initialize(e){L.TileLayer.prototype.initialize.call(this,e.url,e),this.url=new URL(e.url,document.baseURI).href,this._directories=new Map,this.on("tileunload",this._releaseTile,this),this.on("load tileunload",()=>L.Layer.types["3d"]._renderers.get(this._map)?.update()),this.ready=Promise.resolve(this.options.archive||this).then(async r=>{const t=await r.getHeader();return this.options.archive=r,this.header=t,this.options.maxNativeZoom===void 0&&(this.options.maxNativeZoom=t.maxZoom),this.fire("ready"),this}).catch(r=>{throw this.fire("error",{error:r}),r})},onAdd(e){this.header?(L.TileLayer.prototype.onAdd.call(this,e),this._setTerrain3D(e._terrain3D)):this.ready=this.ready.then(r=>(this._map===e&&e.hasLayer(this)&&!this._container&&(L.TileLayer.prototype.onAdd.call(this,e),this._setTerrain3D(e._terrain3D)),r))},onRemove(e){this._setTerrain3D(null),this._container&&L.TileLayer.prototype.onRemove.call(this,e)},setOpacity(e){return L.TileLayer.prototype.setOpacity.call(this,e),L.Layer.types["3d"]._renderers.get(this._map)?.update(),this},setZIndex(e){return L.TileLayer.prototype.setZIndex.call(this,e),L.Layer.types["3d"]._renderers.get(this._map)?.update(),this},createTile(e,r){const t=document.createElement("img");return t.alt="",(this.options.crossOrigin||this.options.crossOrigin==="")&&(t.crossOrigin=this.options.crossOrigin===!0?"":this.options.crossOrigin),typeof this.options.referrerPolicy=="string"&&(t.referrerPolicy=this.options.referrerPolicy),t.request=new AbortController,this.ready.then(()=>{if(!t.request.signal.aborted)return this.options.archive.getZxy(e.z,e.x,e.y,t.request.signal)}).then(async i=>{if(!t.request.signal.aborted){if(!i)throw new Error(`Tile ${e.z}/${e.x}/${e.y} is not in the offline archive`);await new Promise((o,l)=>{const s=a=>{t.request.signal.removeEventListener("abort",n),t.onload=t.onerror=null,this._releaseURL(t),a?l(a):o()},n=()=>s();t.request.signal.addEventListener("abort",n,{once:!0}),t.objectURL=URL.createObjectURL(new Blob([i.data])),t.onload=()=>s(),t.onerror=()=>s(new Error(`Unable to decode tile ${e.z}/${e.x}/${e.y}`)),t.src=t.objectURL}),!t.request.signal.aborted&&(t.done=!0,this._registerTerrainTile(e,t),r(null,t))}}).catch(i=>{t.request.signal.aborted||(t.error=i.message,this._tileOnError(r,t,i))}),t},_abortLoading(){for(const{coords:e,el:r}of Object.values(this._tiles))e.z!==this._tileZoom&&this._releaseTile({tile:r});L.TileLayer.prototype._abortLoading.call(this)},_setTerrain3D(e){if(this._terrain3D!==e){for(const{el:r}of Object.values(this._tiles||{}))this._terrain3D?.removeRasterTile(r);if(this._terrain3D=e||null,this._terrain3D)for(const{coords:r,el:t}of Object.values(this._tiles||{}))t.done&&this._registerTerrainTile(r,t)}},_registerTerrainTile(e,r){if(!this._terrain3D)return;const t=this._terrain3D;t.addRasterTile(this,e,r).catch(i=>{this._terrain3D===t&&r.isConnected&&this.fire("tileerror",{tile:r,coords:e,error:i})})},_releaseURL(e){e.objectURL&&(URL.revokeObjectURL(e.objectURL),e.objectURL=null)},_releaseTile({tile:e}){this._terrain3D?.removeRasterTile(e),e.request.abort(),this._releaseURL(e)}});
2
- //# sourceMappingURL=pmtiles.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/pmtiles.js"],
4
- "sourcesContent": ["import './3d.js';\nimport { read, getHeader, getZxy } from '../scene/pmtiles.js';\nimport { decompress } from '../utils/pmtiles.js';\n\n/** A raster TileLayer backed by the shared PMTiles reader. */\nL.Layer.types.pmtiles = L.TileLayer.extend({\n _read(offset, length, signal) { return read(this, offset, length, signal); },\n _decompress(data, compression) { return decompress(data, compression); },\n getHeader() { return getHeader(this); },\n getZxy(z, x, y, signal) { return getZxy(this, z, x, y, signal); },\n\n initialize(options) {\n L.TileLayer.prototype.initialize.call(this, options.url, options);\n this.url = new URL(options.url, document.baseURI).href;\n this._directories = new Map();\n this.on('tileunload', this._releaseTile, this);\n this.on('load tileunload', () => L.Layer.types['3d']._renderers.get(this._map)?.update());\n this.ready = Promise.resolve(this.options.archive || this).then(async archive => {\n const header = await archive.getHeader();\n this.options.archive = archive;\n this.header = header;\n if (this.options.maxNativeZoom === undefined) this.options.maxNativeZoom = header.maxZoom;\n this.fire('ready');\n return this;\n }).catch(error => {\n this.fire('error', { error });\n throw error;\n });\n },\n\n onAdd(map) {\n if (this.header) {\n L.TileLayer.prototype.onAdd.call(this, map);\n this._setTerrain3D(map._terrain3D);\n } else {\n this.ready = this.ready.then(layer => {\n if (this._map === map && map.hasLayer(this) && !this._container) {\n L.TileLayer.prototype.onAdd.call(this, map);\n this._setTerrain3D(map._terrain3D);\n }\n return layer;\n });\n }\n },\n\n onRemove(map) {\n this._setTerrain3D(null);\n if (this._container) L.TileLayer.prototype.onRemove.call(this, map);\n },\n\n setOpacity(opacity) {\n L.TileLayer.prototype.setOpacity.call(this, opacity);\n L.Layer.types['3d']._renderers.get(this._map)?.update();\n return this;\n },\n\n setZIndex(zIndex) {\n L.TileLayer.prototype.setZIndex.call(this, zIndex);\n L.Layer.types['3d']._renderers.get(this._map)?.update();\n return this;\n },\n\n createTile(coords, done) {\n const tile = document.createElement('img');\n tile.alt = '';\n if (this.options.crossOrigin || this.options.crossOrigin === '') {\n tile.crossOrigin = this.options.crossOrigin === true ? '' : this.options.crossOrigin;\n }\n if (typeof this.options.referrerPolicy === 'string') tile.referrerPolicy = this.options.referrerPolicy;\n tile.request = new AbortController();\n this.ready.then(() => {\n if (tile.request.signal.aborted) return;\n return this.options.archive.getZxy(coords.z, coords.x, coords.y, tile.request.signal);\n }).then(async result => {\n if (tile.request.signal.aborted) return;\n if (!result) throw new Error(`Tile ${coords.z}/${coords.x}/${coords.y} is not in the offline archive`);\n await new Promise((resolve, reject) => {\n const finish = error => {\n tile.request.signal.removeEventListener('abort', abort);\n tile.onload = tile.onerror = null;\n this._releaseURL(tile);\n if (error) reject(error);\n else resolve();\n };\n const abort = () => finish();\n tile.request.signal.addEventListener('abort', abort, { once: true });\n tile.objectURL = URL.createObjectURL(new Blob([result.data]));\n tile.onload = () => finish();\n tile.onerror = () => finish(new Error(`Unable to decode tile ${coords.z}/${coords.x}/${coords.y}`));\n tile.src = tile.objectURL;\n });\n if (tile.request.signal.aborted) return;\n tile.done = true;\n this._registerTerrainTile(coords, tile);\n done(null, tile);\n }).catch(error => {\n if (tile.request.signal.aborted) return;\n tile.error = error.message;\n this._tileOnError(done, tile, error);\n });\n return tile;\n },\n\n _abortLoading() {\n // Requests can still be pending while an image with no src reports complete.\n for (const { coords, el } of Object.values(this._tiles)) {\n if (coords.z !== this._tileZoom) this._releaseTile({ tile: el });\n }\n L.TileLayer.prototype._abortLoading.call(this);\n },\n\n _setTerrain3D(terrain) {\n if (this._terrain3D === terrain) return;\n for (const { el } of Object.values(this._tiles || {})) this._terrain3D?.removeRasterTile(el);\n this._terrain3D = terrain || null;\n if (this._terrain3D) {\n for (const { coords, el } of Object.values(this._tiles || {})) {\n if (el.done) this._registerTerrainTile(coords, el);\n }\n }\n },\n\n _registerTerrainTile(coords, tile) {\n if (!this._terrain3D) return;\n const terrain = this._terrain3D;\n terrain.addRasterTile(this, coords, tile).catch(error => {\n if (this._terrain3D === terrain && tile.isConnected) this.fire('tileerror', { tile, coords, error });\n });\n },\n\n _releaseURL(tile) {\n if (tile.objectURL) {\n URL.revokeObjectURL(tile.objectURL);\n tile.objectURL = null;\n }\n },\n\n _releaseTile({ tile }) {\n this._terrain3D?.removeRasterTile(tile);\n tile.request.abort();\n this._releaseURL(tile);\n },\n});\n"],
5
- "mappings": "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",
6
- "names": ["read", "getHeader", "getZxy", "decompress", "offset", "length", "signal", "data", "compression", "z", "x", "y", "options", "archive", "header", "error", "map", "layer", "opacity", "zIndex", "coords", "done", "tile", "result", "resolve", "reject", "finish", "abort", "el", "terrain"]
7
- }
@@ -1,2 +0,0 @@
1
- import{atmosphere as E,moonPosition as D,solarPosition as P,projectCelestialBody as A}from"../utils/sun.js";import{underEntry as U}from"../utils/control.js";function N(t){const s=globalThis.L,e=new s.Control({position:"bottomright"});e.live=!0;let r,l,g,a,v;const C=t.getContainer().style.getPropertyValue("--leaflet-sky-background"),w="position:absolute;width:18px;height:18px;border-radius:50%;transform:translate(-50%,-50%);pointer-events:none;",m=s.DomUtil.create("div","sunlight-sun"),f=s.DomUtil.create("div","sunlight-moon");m.style.cssText=w+"background:#fff3bd;box-shadow:0 0 18px 7px #ffd27699;",f.style.cssText=w+"background:#dce5f2;box-shadow:0 0 10px 2px #cbdcff55;",m.setAttribute("role","img"),m.setAttribute("aria-label","Sun"),f.setAttribute("role","img"),f.setAttribute("aria-label","Moon");const c=()=>{const n=t._sunlight,o=t._pitchSky;n?t.getContainer().style.setProperty("--leaflet-sky-background",n.background):C?t.getContainer().style.setProperty("--leaflet-sky-background",C):t.getContainer().style.removeProperty("--leaflet-sky-background");const i=t.getSize(),h=t.getPitch()*Math.PI/180,S=t.getBearing()*Math.PI/180;for(const[d,y]of[[m,n],[f,n?.moon]]){if(d.hidden=!0,!o||!y||y.altitude<=0||!n)continue;d.parentNode!==o&&o.append(d);const T=A(y.direction,i,h,S);if(!T)continue;const{left:p,top:x}=T;d.hidden=p<0||p>i.x||x<0||x>o.clientHeight||o.style.display==="none",d.style.left=`${p}px`,d.style.top=`${x}px`}},b=()=>s.Layer.types["3d"]?._renderers.get(t)?.update(),u=()=>{try{e.live&&(e.time=new Date);const n=e.time.toISOString();r.value=n.slice(0,10),l.value=String(e.time.getUTCHours()*60+e.time.getUTCMinutes()),g.textContent=`${n.slice(11,16)} UTC${e.live?" \xB7 now":""}`;const o=t.getCenter(),i=t._sunlight=P(e.time,o.lat,o.lng);Object.assign(i,E(i.altitude)),i.moon=D(e.time,o.lat,o.lng),a.textContent=i.altitude<=0?"Night \xB7 no direct sunlight":i.altitude<3?"Low sun \xB7 shadows paused":`Sun altitude ${i.altitude.toFixed(1)}\xB0`,t.fire("simulationtimechange",{time:new Date(e.time),live:e.live}),c(),b()}catch(n){delete t._sunlight,c(),b(),a.textContent=`Error: ${n.message}`,console.error("Solar simulation",n)}},k=()=>{if(e.live=!1,!r.value||!r.validity.valid){e.time=new Date(NaN),t.fire("simulationtimechange",{time:null,live:!1}),delete t._sunlight,c(),b(),a.textContent="Error: choose a valid solar date";return}e.time=new Date(`${r.value}T00:00:00Z`),e.time.setUTCMinutes(Number(l.value)),u()};return e.onAdd=()=>{const n=s.DomUtil.create("div","sunlight-control");n.style.cssText="color:#222;width:min(200px,calc(100vw - 60px));font:12px/1.4 sans-serif;",r=document.createElement("input"),r.type="date",r.style.cssText="width:100%;box-sizing:border-box;",r.setAttribute("aria-label","Solar date (UTC)"),l=document.createElement("input"),l.type="range",l.style.cssText="width:100%;box-sizing:border-box;margin:10px 0 4px;cursor:pointer;",l.min="0",l.max="1439",l.step="1",l.setAttribute("aria-label","Time of day (UTC)"),g=document.createElement("output"),g.style.cssText="font-weight:bold;font-variant-numeric:tabular-nums;",g.setAttribute("aria-live","off");const o=document.createElement("button");o.type="button",o.textContent="Now",o.onclick=()=>{e.live=!0,u()};const i=document.createElement("div");i.className="sunlight-time",i.style.cssText="display:flex;justify-content:space-between;align-items:center;",i.append(g,o),a=document.createElement("div"),a.className="sunlight-status",a.style.marginTop="5px",a.setAttribute("role","status");const h=document.createElement("small");return h.style.color="#555",h.textContent="Indicative \xB7 loaded geometry only. Streetlight illumination is estimated, not measured lux.",n.append(r,l,i,a,h),l.oninput=k,r.onchange=k,s.DomEvent.disableClickPropagation(n),s.DomEvent.disableScrollPropagation(n),u(),v=setInterval(()=>{e.live&&u()},6e4),t.on("moveend",u),t.on("move rotate pitch resize",c),n},e.onRemove=()=>{clearInterval(v),t.fire("simulationtimechange",{time:null,live:!1}),t.off("moveend",u),t.off("move rotate pitch resize",c),delete t._sunlight,c(),m.remove(),f.remove(),b()},e}L.Layer.types.sunlight=L.Layer.extend({onAdd(t){this.control=this.control||N(t),this.control._map||this.control.addTo(t);const s=this.control.getContainer(),e=U(this,s);s.classList.toggle("leaflet-control",!e),s.classList.toggle("leaflet-bar",!e),Object.assign(s.style,e?{background:"",padding:"2px 0 6px 20px",margin:"0"}:{background:"#fff",padding:"8px",margin:""})},onRemove(){this.control.remove()}});
2
- //# sourceMappingURL=sunlight.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/sunlight.js"],
4
- "sourcesContent": ["import { atmosphere, moonPosition, solarPosition, projectCelestialBody } from '../utils/sun.js';\nimport { underEntry } from '../utils/control.js';\n\nfunction installSunlight(map) {\n const L = globalThis.L;\n const control = new L.Control({ position: 'bottomright' });\n control.live = true;\n let date, slider, output, status, timer;\n const originalSky = map.getContainer().style.getPropertyValue('--leaflet-sky-background');\n const disc = 'position:absolute;width:18px;height:18px;border-radius:50%;transform:translate(-50%,-50%);pointer-events:none;';\n const sunDisc = L.DomUtil.create('div', 'sunlight-sun');\n const moonDisc = L.DomUtil.create('div', 'sunlight-moon');\n sunDisc.style.cssText = disc + 'background:#fff3bd;box-shadow:0 0 18px 7px #ffd27699;';\n moonDisc.style.cssText = disc + 'background:#dce5f2;box-shadow:0 0 10px 2px #cbdcff55;';\n sunDisc.setAttribute('role', 'img'); sunDisc.setAttribute('aria-label', 'Sun');\n moonDisc.setAttribute('role', 'img'); moonDisc.setAttribute('aria-label', 'Moon');\n const updateSky = () => {\n const sun = map._sunlight, sky = map._pitchSky;\n if (sun) map.getContainer().style.setProperty('--leaflet-sky-background', sun.background);\n else if (originalSky) map.getContainer().style.setProperty('--leaflet-sky-background', originalSky);\n else map.getContainer().style.removeProperty('--leaflet-sky-background');\n const size = map.getSize(), pitch = map.getPitch() * Math.PI / 180, bearing = map.getBearing() * Math.PI / 180;\n for (const [disc, body] of [[sunDisc, sun], [moonDisc, sun?.moon]]) {\n disc.hidden = true;\n if (!sky || !body || body.altitude <= 0 || !sun) continue;\n if (disc.parentNode !== sky) sky.append(disc);\n const point = projectCelestialBody(body.direction, size, pitch, bearing);\n if (!point) continue;\n const { left, top } = point;\n disc.hidden = left < 0 || left > size.x || top < 0 || top > sky.clientHeight || sky.style.display === 'none';\n disc.style.left = `${left}px`; disc.style.top = `${top}px`;\n }\n };\n const render = () => L.Layer.types['3d']?._renderers.get(map)?.update();\n const update = () => {\n try {\n if (control.live) control.time = new Date();\n const time = control.time.toISOString();\n date.value = time.slice(0, 10);\n slider.value = String(control.time.getUTCHours() * 60 + control.time.getUTCMinutes());\n output.textContent = `${time.slice(11, 16)} UTC${control.live ? ' \u00B7 now' : ''}`;\n const center = map.getCenter();\n const sun = map._sunlight = solarPosition(control.time, center.lat, center.lng);\n Object.assign(sun, atmosphere(sun.altitude));\n sun.moon = moonPosition(control.time, center.lat, center.lng);\n status.textContent = sun.altitude <= 0 ? 'Night \u00B7 no direct sunlight' :\n sun.altitude < 3 ? 'Low sun \u00B7 shadows paused' : `Sun altitude ${sun.altitude.toFixed(1)}\u00B0`;\n map.fire('simulationtimechange', { time: new Date(control.time), live: control.live });\n updateSky(); render();\n } catch (error) {\n delete map._sunlight;\n updateSky();\n render();\n status.textContent = `Error: ${error.message}`;\n console.error('Solar simulation', error);\n }\n };\n const selectTime = () => {\n control.live = false;\n if (!date.value || !date.validity.valid) {\n control.time = new Date(NaN);\n map.fire('simulationtimechange', { time: null, live: false });\n delete map._sunlight;\n updateSky();\n render();\n status.textContent = 'Error: choose a valid solar date';\n return;\n }\n control.time = new Date(`${date.value}T00:00:00Z`);\n control.time.setUTCMinutes(Number(slider.value));\n update();\n };\n control.onAdd = () => {\n const container = L.DomUtil.create('div', 'sunlight-control');\n container.style.cssText = 'color:#222;width:min(200px,calc(100vw - 60px));font:12px/1.4 sans-serif;';\n date = document.createElement('input');\n date.type = 'date';\n date.style.cssText = 'width:100%;box-sizing:border-box;';\n date.setAttribute('aria-label', 'Solar date (UTC)');\n slider = document.createElement('input');\n slider.type = 'range';\n slider.style.cssText = 'width:100%;box-sizing:border-box;margin:10px 0 4px;cursor:pointer;';\n slider.min = '0'; slider.max = '1439'; slider.step = '1';\n slider.setAttribute('aria-label', 'Time of day (UTC)');\n output = document.createElement('output');\n output.style.cssText = 'font-weight:bold;font-variant-numeric:tabular-nums;';\n output.setAttribute('aria-live', 'off');\n const now = document.createElement('button');\n now.type = 'button'; now.textContent = 'Now';\n now.onclick = () => { control.live = true; update(); };\n const timeRow = document.createElement('div');\n timeRow.className = 'sunlight-time';\n timeRow.style.cssText = 'display:flex;justify-content:space-between;align-items:center;';\n timeRow.append(output, now);\n status = document.createElement('div');\n status.className = 'sunlight-status';\n status.style.marginTop = '5px';\n status.setAttribute('role', 'status');\n const note = document.createElement('small');\n note.style.color = '#555';\n note.textContent = 'Indicative \u00B7 loaded geometry only. Streetlight illumination is estimated, not measured lux.';\n container.append(date, slider, timeRow, status, note);\n slider.oninput = selectTime;\n date.onchange = selectTime;\n L.DomEvent.disableClickPropagation(container);\n L.DomEvent.disableScrollPropagation(container);\n update();\n timer = setInterval(() => { if (control.live) update(); }, 60000);\n map.on('moveend', update);\n map.on('move rotate pitch resize', updateSky);\n return container;\n };\n control.onRemove = () => {\n clearInterval(timer);\n map.fire('simulationtimechange', { time: null, live: false });\n map.off('moveend', update);\n map.off('move rotate pitch resize', updateSky);\n delete map._sunlight;\n updateSky();\n sunDisc.remove(); moonDisc.remove();\n render();\n };\n return control;\n}\n\n// Sun/moon clock control and sky colours; the control is created on first add (`layer.control`).\nL.Layer.types.sunlight = L.Layer.extend({\n onAdd(map) {\n this.control = this.control || installSunlight(map);\n if (!this.control._map) this.control.addTo(map);\n // Shown under this layer's entry in the layers control; a standalone control without one.\n const container = this.control.getContainer(), nested = underEntry(this, container);\n container.classList.toggle('leaflet-control', !nested);\n container.classList.toggle('leaflet-bar', !nested);\n Object.assign(container.style, nested\n ? { background: '', padding: '2px 0 6px 20px', margin: '0' }\n : { background: '#fff', padding: '8px', margin: '' });\n },\n onRemove() {\n this.control.remove();\n },\n});\n"],
5
- "mappings": "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",
6
- "names": ["atmosphere", "moonPosition", "solarPosition", "projectCelestialBody", "underEntry", "installSunlight", "map", "L", "control", "date", "slider", "output", "status", "timer", "originalSky", "disc", "sunDisc", "moonDisc", "updateSky", "sun", "sky", "size", "pitch", "bearing", "body", "point", "left", "top", "render", "update", "time", "center", "error", "selectTime", "container", "now", "timeRow", "note", "nested"]
7
- }
@@ -1,24 +0,0 @@
1
- import{bridgeElevation as G,terrainElevation as R,terrainGrid as z,terrainAtlas as O}from"../utils/terrain.js";import{triangulate as S}from"../utils/geometry.js";import"./3d.js";import"./pmtiles.js";L.Layer.types.terrain=L.Layer.types["3d"].extend({initialize(t={}){const e=t.url,s={...t};delete s.url,L.Layer.types["3d"].prototype.initialize.call(this,s),this.terrainSource=e,this._terrainTiles=new Map,this._rasterTiles=new Map,this._terrainReady=!1},onAdd(t){if(t._terrain3D&&t._terrain3D!==this)throw new Error("Only one terrain layer can be active per map");t._terrain3D=this,L.Layer.types["3d"].prototype.onAdd.call(this,t),this._terrainPromise=this.root?this._loadTerrain():new Promise(e=>this.once("ready",()=>this._loadTerrain().then(e),this)),t.eachLayer(e=>e._setTerrain3D?.(this)),t.fire("terrainchange")},onRemove(t){this._terrainController?.abort(),this._terrainLoading=!1,this._terrainReady=!1,t.eachLayer(e=>e._setTerrain3D?.(null));for(const e of this._rasterTiles.keys())this.removeRasterTile(e);t._terrain3D===this&&delete t._terrain3D;for(const e of Object.values(t._layers))e._setTerrainHeight?.();t.fire("terrainchange"),this._terrainTiles.clear(),this._terrainOriginElevation=0,this._terrainPromise=null,this._rasterProgram&&this._removeProgram(this._rasterProgram),this._rasterProgram=null,this._dem&&this._destroyTexture(this._dem.texture),this._dem=null;for(const e of this._terrainGrids?.values()||[])for(const s of Object.values(e))this._destroyTexture(s.buffer);this._terrainGrids=null,this._bridges=null,this._disposeMesh(this._bridgeMesh),this._bridgeMesh=null,L.Layer.types["3d"].prototype.onRemove.call(this,t)},async _loadTerrain(){if(this._terrainLoading||!this._map)return;this._terrainLoading=!0,this._terrainReady=!1;const t=this._terrainController=new AbortController;try{if(!this.terrainSource)throw new Error("Terrain layer requires a PMTiles elevation archive");const e=this._terrainArchive=new L.Layer({source:{type:"pmtiles",url:this.terrainSource}});await e.ready;const s=e.header;if(s.tileType!==0||s.minZoom!==s.maxZoom)throw new Error("Expected a single-zoom Float32 PMTiles terrain archive");this._terrainZoom=s.maxZoom;const x=this._map,p=x.project([s.maxLat,s.minLon],this._terrainZoom).divideBy(256).floor(),y=x.project([s.minLat,s.maxLon],this._terrainZoom).divideBy(256).floor();this._terrainBounds=new L.Bounds(p,y);const T=[];for(let n=p.x;n<=y.x;n++)for(let _=p.y;_<=y.y;_++)T.push({z:this._terrainZoom,x:n,y:_});let g=0;await Promise.all(Array.from({length:Math.min(4,T.length)},async()=>{for(;g<T.length;){t.signal.throwIfAborted();const n=T[g++],_=await e.getZxy(n.z,n.x,n.y,t.signal);if(!_||_.data.byteLength!==256*256*4)throw new Error(`Missing or invalid Float32 terrain tile ${n.z}/${n.x}/${n.y}`);this._terrainTiles.set(`${n.x}/${n.y}`,new Float32Array(_.data))}}));const w=this.options.bridges&&await fetch(this.options.bridges,{signal:t.signal}).then(n=>{if(!n.ok)throw new Error(`Bridges: HTTP ${n.status}`);return n.json()});if(t.signal.aborted||this._map!==x)return;this._terrainReady=!0,this._terrainOriginElevation=this._getElevation(this.location)??0;for(const n of Object.values(x._layers))n._setTerrainHeight?.();return w&&this._addBridges(w),x.fire("terrainchange"),this.update(),this.fire("terrainready"),!0}catch(e){return t.signal.aborted||this.fire("error",{error:e}),!1}finally{this._terrainLoading=!1}},_getElevation(t){if(!this._map||!this._terrainReady)return null;const e=t instanceof L.Point?t:this._map.project(t,this._terrainZoom);return G(e,this._bridges)??R(e,this._terrainTiles)},_addBridges(t){const e=this._map,s=e.options.crs,x=this._terrainZoom,p=s.project(this.location),y=Math.cos(this.location.lat*Math.PI/180),T=this.root.position[1],g=[],w=[],n=[],_=([m,M,h])=>{const l=s.project(new L.LatLng(M,m));return[(l.x-p.x)*y,h-T,-(l.y-p.y)*y]},E=(m,M)=>{g.push(...m),w.push(...M),n.push(.6,.58,.54)};this._bridges=new Map;for(const{geometry:m}of t.features){const M=m.type==="Polygon"?[m.coordinates]:m.type==="MultiPolygon"?m.coordinates:[];for(const h of M){const l=h.map(r=>r.slice(0,-1)).filter(r=>r.length>=3);if(!l.length)continue;const c=l.flat().map(([r,o,a])=>{const i=e.project([o,r],x);return[i.x,i.y,a]}),d=l.flat().map(_);let U;try{const r=l.map((i,u)=>l.slice(0,u).reduce((b,f)=>b+f.length,0)),[o,...a]=l.map((i,u)=>i.map((b,f)=>({x:c[r[u]+f][0],y:c[r[u]+f][1]})));U=S(o,a)}catch{continue}const v={triangles:U.map(r=>r.map(o=>c[o])),min:[Math.min(...c.map(r=>r[0])),Math.min(...c.map(r=>r[1]))],max:[Math.max(...c.map(r=>r[0])),Math.max(...c.map(r=>r[1]))]};for(let r=Math.floor(v.min[0]/64);r<=Math.floor(v.max[0]/64);r++)for(let o=Math.floor(v.min[1]/64);o<=Math.floor(v.max[1]/64);o++){const a=`${r}/${o}`;this._bridges.set(a,[...this._bridges.get(a)||[],v])}const P=r=>[r[0],r[1]-1.2,r[2]];for(let[r,o,a]of U){const[i,u,b]=[d[r],d[o],d[a]];(u[2]-i[2])*(b[0]-i[0])-(u[0]-i[0])*(b[2]-i[2])<0&&([o,a]=[a,o]);for(const f of[r,o,a])E(d[f],[0,1,0]);for(const f of[r,a,o])E(P(d[f]),[0,-1,0])}let B=0;for(const r of l){for(let o=0;o<r.length;o++){const a=d[B+o],i=d[B+(o+1)%r.length],u=Math.hypot(i[0]-a[0],i[2]-a[2])||1,b=[(i[2]-a[2])/u,0,-(i[0]-a[0])/u];for(const f of[a,i,P(i),a,P(i),P(a)])E(f,b)}B+=r.length}}}g.length&&(this._bridgeMesh=this._createMesh({position:g,normal:w,color:n}))},async addRasterTile(t,e,s){const[x,p]=await Promise.all([this._terrainPromise,createImageBitmap(s)]);if(!x||!this._map||this._map._terrain3D!==this||t._terrain3D!==this||s.request.signal.aborted||!s.isConnected||this._rasterTiles.has(s)){p.close();return}const y=Math.max(1,Math.min(64,256/2**(e.z-this._terrainZoom))),T=this._map,g=T.options.crs,w=g.project(this.location),n=Math.cos(this.location.lat*Math.PI/180),_=g.scale(e.z),E=2**(this._terrainZoom-e.z),m=g.transformation.untransform(new L.Point(e.x*256,e.y*256),_),M=g.transformation.untransform(new L.Point((e.x+1)*256,(e.y+1)*256),_),h=this.renderer.device,l={device:h,texture:h.createTexture({size:[s.width,s.height],format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST|GPUTextureUsage.RENDER_ATTACHMENT}),sampler:h.createSampler({addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"}),samplerOptions:{addressModeU:"clamp-to-edge",addressModeV:"clamp-to-edge"},image:s,format:"rgba8unorm",srgb:!1,flipY:!1,uploaded:s};if(h.queue.copyExternalImageToTexture({source:p},{texture:l.texture},[s.width,s.height]),p.close(),!this._rasterProgram||this._rasterProgram.device!==h){const a=this._terrainBounds,i=a.max.x-a.min.x+1,u=a.max.y-a.min.y+1,{elevations:b,low:f,high:D}=O(this._terrainTiles,a);this._dem&&this._destroyTexture(this._dem.texture),this._dem={texture:h.createTexture({size:[i*256,u*256],format:"r32float",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST}),low:Number.isFinite(f)?f:this._terrainOriginElevation,high:Number.isFinite(D)?D:this._terrainOriginElevation},h.queue.writeTexture({texture:this._dem.texture},b,{bytesPerRow:i*1024},[i*256,u*256]),this._terrainGrids=new Map,this._rasterProgram=this._createProgram({baseTexture:l,unlit:!0,alphaMode:"BLEND",terrain:this._dem})}let c=this._terrainGrids.get(y);if(!c){c=z(y);for(const[a,i]of Object.entries(c))i.size||=1,i.count=i.data.length/i.size,i.indexFormat="uint16",i.buffer=h.createBuffer({size:Math.max(4,i.data.byteLength),usage:a==="index"?GPUBufferUsage.INDEX|GPUBufferUsage.COPY_DST:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST}),h.queue.writeBuffer(i.buffer,0,i.data);this._terrainGrids.set(y,c)}const d=this._terrainOriginElevation,U=Math.min(this._dem.low,d)-d,v=Math.max(this._dem.high,d)-d,P=(M.x-m.x)*n,B=-(M.y-m.y)*n,r={device:h,attributes:c,drawRange:{start:0,count:c.index.count},bounds:{min:[0,U,0],max:[1,v,1],center:[.5,(U+v)/2,.5],radius:Math.hypot(P,v-U,B)/2/Math.max(P,1,B)}},o={position:[(m.x-w.x)*n,0,-(m.y-w.y)*n],rotation:[0,0,0],scale:[P,1,B],worldMatrix:[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],children:[],visible:!0,device:h,geometry:r,program:this._rasterProgram,texture:l,terrain:[e.x*256*E-this._terrainBounds.min.x*256,e.y*256*E-this._terrainBounds.min.y*256,256*E,d],tile:s,opacity:t.options.opacity??1,id:L.Layer.types["3d"]._nextId++,renderOrder:-1};this.add(o),this._rasterTiles.set(s,o),s._terrainVisibility=s.style.visibility},removeRasterTile(t){t._terrainRequest?.abort();const e=this._rasterTiles.get(t);e&&(this.remove(e),this._destroyTexture(e.texture.texture),this._rasterTiles.delete(t),t.style.visibility=t._terrainVisibility,delete t._terrainVisibility)}}),L.Layer.types.terrain.elevationWGSL=`
2
- fn demSample(pixel: vec2<i32>) -> f32 {
3
- if (any(pixel < vec2<i32>(0)) || any(pixel >= vec2<i32>(textureDimensions(dem)))) { return -1e9; }
4
- return textureLoad(dem, pixel, 0).r;
5
- }
6
- fn elevation(pixel: vec2<f32>, base: f32) -> f32 {
7
- let p = pixel - vec2<f32>(0.5);
8
- let f = fract(p);
9
- let i = vec2<i32>(floor(p));
10
- let v00 = demSample(i);
11
- let v10 = demSample(i + vec2<i32>(1, 0));
12
- let v01 = demSample(i + vec2<i32>(0, 1));
13
- let v11 = demSample(i + vec2<i32>(1, 1));
14
- if (v00 > -1000.0 && v10 > -1000.0 && v01 > -1000.0 && v11 > -1000.0) {
15
- return mix(mix(v00, v10, f.x), mix(v01, v11, f.x), f.y);
16
- }
17
- if (v00 > -1000.0) { return v00; }
18
- if (v10 > -1000.0) { return v10; }
19
- if (v01 > -1000.0) { return v01; }
20
- if (v11 > -1000.0) { return v11; }
21
- return base;
22
- }
23
- `;
24
- //# sourceMappingURL=terrain.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/terrain.js"],
4
- "sourcesContent": ["import { bridgeElevation, terrainElevation, terrainGrid, terrainAtlas } from '../utils/terrain.js';\nimport { triangulate } from '../utils/geometry.js';\nimport './3d.js';\nimport './pmtiles.js';\n\n/**\n * Renders IGN Float32 DEM tiles and PMTiles raster basemaps in the shared WebGPU scene.\n * Source options: `url` (single-zoom Float32 PMTiles DEM); `bridges` (optional GeoJSON deck polygons with Z, see _addBridges).\n */\nL.Layer.types.terrain = L.Layer.types['3d'].extend({\n initialize(options = {}) {\n const terrainSource = options.url;\n const layerOptions = { ...options };\n delete layerOptions.url;\n L.Layer.types['3d'].prototype.initialize.call(this, layerOptions);\n this.terrainSource = terrainSource;\n this._terrainTiles = new Map();\n this._rasterTiles = new Map();\n this._terrainReady = false;\n },\n\n onAdd(map) {\n if (map._terrain3D && map._terrain3D !== this) throw new Error('Only one terrain layer can be active per map');\n map._terrain3D = this;\n L.Layer.types['3d'].prototype.onAdd.call(this, map);\n this._terrainPromise = this.root\n ? this._loadTerrain()\n : new Promise(resolve => this.once('ready', () => this._loadTerrain().then(resolve), this));\n map.eachLayer(layer => layer._setTerrain3D?.(this));\n map.fire('terrainchange');\n },\n\n onRemove(map) {\n this._terrainController?.abort();\n this._terrainLoading = false;\n this._terrainReady = false;\n map.eachLayer(layer => layer._setTerrain3D?.(null));\n for (const tile of this._rasterTiles.keys()) this.removeRasterTile(tile);\n if (map._terrain3D === this) delete map._terrain3D;\n for (const layer of Object.values(map._layers)) layer._setTerrainHeight?.();\n map.fire('terrainchange');\n this._terrainTiles.clear();\n this._terrainOriginElevation = 0;\n this._terrainPromise = null;\n if (this._rasterProgram) this._removeProgram(this._rasterProgram);\n this._rasterProgram = null;\n if (this._dem) this._destroyTexture(this._dem.texture);\n this._dem = null;\n for (const grid of this._terrainGrids?.values() || []) {\n for (const attribute of Object.values(grid)) this._destroyTexture(attribute.buffer);\n }\n this._terrainGrids = null;\n this._bridges = null;\n this._disposeMesh(this._bridgeMesh);\n this._bridgeMesh = null;\n L.Layer.types['3d'].prototype.onRemove.call(this, map);\n },\n\n async _loadTerrain() {\n if (this._terrainLoading || !this._map) return;\n this._terrainLoading = true;\n this._terrainReady = false;\n const controller = this._terrainController = new AbortController();\n try {\n if (!this.terrainSource) throw new Error('Terrain layer requires a PMTiles elevation archive');\n const archive = this._terrainArchive = new L.Layer({ source: { type: 'pmtiles', url: this.terrainSource } });\n await archive.ready;\n const header = archive.header;\n if (header.tileType !== 0 || header.minZoom !== header.maxZoom) {\n throw new Error('Expected a single-zoom Float32 PMTiles terrain archive');\n }\n this._terrainZoom = header.maxZoom;\n const map = this._map;\n const northwest = map.project([header.maxLat, header.minLon], this._terrainZoom).divideBy(256).floor();\n const southeast = map.project([header.minLat, header.maxLon], this._terrainZoom).divideBy(256).floor();\n this._terrainBounds = new L.Bounds(northwest, southeast);\n const tiles = [];\n for (let x = northwest.x; x <= southeast.x; x++) {\n for (let y = northwest.y; y <= southeast.y; y++) tiles.push({ z: this._terrainZoom, x, y });\n }\n let next = 0;\n await Promise.all(Array.from({ length: Math.min(4, tiles.length) }, async () => {\n while (next < tiles.length) {\n controller.signal.throwIfAborted();\n const coords = tiles[next++];\n const result = await archive.getZxy(coords.z, coords.x, coords.y, controller.signal);\n if (!result || result.data.byteLength !== 256 * 256 * 4) {\n throw new Error(`Missing or invalid Float32 terrain tile ${coords.z}/${coords.x}/${coords.y}`);\n }\n this._terrainTiles.set(`${coords.x}/${coords.y}`, new Float32Array(result.data));\n }\n }));\n const bridges = this.options.bridges && await fetch(this.options.bridges, { signal: controller.signal })\n .then(response => { if (!response.ok) throw new Error(`Bridges: HTTP ${response.status}`); return response.json(); });\n if (controller.signal.aborted || this._map !== map) return;\n this._terrainReady = true;\n this._terrainOriginElevation = this._getElevation(this.location) ?? 0;\n for (const layer of Object.values(map._layers)) layer._setTerrainHeight?.();\n if (bridges) this._addBridges(bridges);\n map.fire('terrainchange');\n this.update();\n this.fire('terrainready');\n return true;\n } catch (error) {\n if (!controller.signal.aborted) this.fire('error', { error });\n return false;\n } finally {\n this._terrainLoading = false;\n }\n },\n\n /** @param {L.LatLng|L.Point} location LatLng, or a pixel point at the terrain zoom. */\n _getElevation(location) {\n if (!this._map || !this._terrainReady) return null;\n const point = location instanceof L.Point ? location : this._map.project(location, this._terrainZoom);\n return bridgeElevation(point, this._bridges) ?? terrainElevation(point, this._terrainTiles);\n },\n\n /**\n * Bare-earth DEMs drop bridges: `_getElevation` returns the deck height inside these polygons (GeoJSON\n * Polygon/MultiPolygon with Z, e.g. IGN BD TOPO), and one mesh draws the 1.2 m thick decks.\n * ponytail: anything under a deck (quays, boats asking `_getElevation`) also gets the deck height.\n */\n _addBridges(geojson) {\n const map = this._map, crs = map.options.crs, zoom = this._terrainZoom;\n const origin = crs.project(this.location), metres = Math.cos(this.location.lat * Math.PI / 180);\n const base = this.root.position[1], position = [], normal = [], color = [];\n const local = ([lng, lat, z]) => {\n const p = crs.project(new L.LatLng(lat, lng));\n return [(p.x - origin.x) * metres, z - base, -(p.y - origin.y) * metres];\n };\n const push = (p, n) => { position.push(...p); normal.push(...n); color.push(0.6, 0.58, 0.54); };\n this._bridges = new Map();\n for (const { geometry } of geojson.features) {\n const polygons = geometry.type === 'Polygon' ? [geometry.coordinates] : geometry.type === 'MultiPolygon' ? geometry.coordinates : [];\n for (const polygon of polygons) {\n const rings = polygon.map(ring => ring.slice(0, -1)).filter(ring => ring.length >= 3);\n if (!rings.length) continue;\n const pixels = rings.flat().map(([lng, lat, z]) => { const p = map.project([lat, lng], zoom); return [p.x, p.y, z]; });\n const points = rings.flat().map(local);\n let triangles;\n try {\n const starts = rings.map((ring, r) => rings.slice(0, r).reduce((sum, previous) => sum + previous.length, 0));\n const [contour, ...holes] = rings.map((ring, r) => ring.map((c, i) => ({ x: pixels[starts[r] + i][0], y: pixels[starts[r] + i][1] })));\n triangles = triangulate(contour, holes);\n } catch { continue; }\n const bridge = {\n triangles: triangles.map(t => t.map(i => pixels[i])),\n min: [Math.min(...pixels.map(p => p[0])), Math.min(...pixels.map(p => p[1]))],\n max: [Math.max(...pixels.map(p => p[0])), Math.max(...pixels.map(p => p[1]))],\n };\n for (let x = Math.floor(bridge.min[0] / 64); x <= Math.floor(bridge.max[0] / 64); x++) {\n for (let y = Math.floor(bridge.min[1] / 64); y <= Math.floor(bridge.max[1] / 64); y++) {\n const key = `${x}/${y}`;\n this._bridges.set(key, [...this._bridges.get(key) || [], bridge]);\n }\n }\n const below = p => [p[0], p[1] - 1.2, p[2]];\n for (let [a, b, c] of triangles) {\n // Counter-clockwise seen from above, so double-sided shading keeps the top lit.\n const [pa, pb, pc] = [points[a], points[b], points[c]];\n if ((pb[2] - pa[2]) * (pc[0] - pa[0]) - (pb[0] - pa[0]) * (pc[2] - pa[2]) < 0) [b, c] = [c, b];\n for (const i of [a, b, c]) push(points[i], [0, 1, 0]);\n for (const i of [a, c, b]) push(below(points[i]), [0, -1, 0]);\n }\n let start = 0;\n for (const ring of rings) {\n for (let i = 0; i < ring.length; i++) {\n const p = points[start + i], q = points[start + (i + 1) % ring.length];\n const length = Math.hypot(q[0] - p[0], q[2] - p[2]) || 1, n = [(q[2] - p[2]) / length, 0, -(q[0] - p[0]) / length];\n for (const corner of [p, q, below(q), p, below(q), below(p)]) push(corner, n);\n }\n start += ring.length;\n }\n }\n }\n if (position.length) this._bridgeMesh = this._createMesh({ position, normal, color });\n },\n\n async addRasterTile(layer, coords, tile) {\n const [ready, bitmap] = await Promise.all([this._terrainPromise, createImageBitmap(tile)]);\n if (!ready || !this._map || this._map._terrain3D !== this || layer._terrain3D !== this ||\n tile.request.signal.aborted || !tile.isConnected || this._rasterTiles.has(tile)) {\n bitmap.close();\n return;\n }\n // Match DEM pixel spacing, capped at 64 subdivisions per tile.\n const divisions = Math.max(1, Math.min(64, 256 / 2 ** (coords.z - this._terrainZoom)));\n const map = this._map, crs = map.options.crs;\n const origin = crs.project(this.location), metres = Math.cos(this.location.lat * Math.PI / 180);\n // Tile pixels map linearly to projected metres: one scaled unit grid per tile, elevation in the vertex shader.\n const scale = crs.scale(coords.z), terrainScale = 2 ** (this._terrainZoom - coords.z);\n const corner = crs.transformation.untransform(new L.Point(coords.x * 256, coords.y * 256), scale);\n const opposite = crs.transformation.untransform(new L.Point((coords.x + 1) * 256, (coords.y + 1) * 256), scale);\n const device = this.renderer.device;\n const texture = {\n device,\n texture: device.createTexture({\n size: [tile.width, tile.height],\n format: 'rgba8unorm',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT,\n }),\n sampler: device.createSampler({ addressModeU: 'clamp-to-edge', addressModeV: 'clamp-to-edge' }),\n samplerOptions: { addressModeU: 'clamp-to-edge', addressModeV: 'clamp-to-edge' },\n image: tile, format: 'rgba8unorm', srgb: false, flipY: false, uploaded: tile,\n };\n device.queue.copyExternalImageToTexture({ source: bitmap }, { texture: texture.texture }, [tile.width, tile.height]);\n bitmap.close();\n if (!this._rasterProgram || this._rasterProgram.device !== device) {\n // DEM atlas over the archive's tile grid; invalid or missing samples become -1e9 (the shader's no-data).\n // ponytail: one texture, capped by maxTextureDimension2D (32\u00D732 DEM tiles at 8192 px); split it for larger archives.\n const bounds = this._terrainBounds, columns = bounds.max.x - bounds.min.x + 1, rows = bounds.max.y - bounds.min.y + 1;\n const { elevations, low, high } = terrainAtlas(this._terrainTiles, bounds);\n if (this._dem) this._destroyTexture(this._dem.texture);\n this._dem = {\n texture: device.createTexture({\n size: [columns * 256, rows * 256],\n format: 'r32float',\n usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST,\n }),\n low: Number.isFinite(low) ? low : this._terrainOriginElevation,\n high: Number.isFinite(high) ? high : this._terrainOriginElevation,\n };\n device.queue.writeTexture({ texture: this._dem.texture }, elevations,\n { bytesPerRow: columns * 1024 }, [columns * 256, rows * 256]);\n this._terrainGrids = new Map();\n this._rasterProgram = this._createProgram({\n baseTexture: texture,\n unlit: true,\n alphaMode: 'BLEND',\n terrain: this._dem,\n });\n }\n let attributes = this._terrainGrids.get(divisions);\n if (!attributes) {\n attributes = terrainGrid(divisions);\n for (const [name, attribute] of Object.entries(attributes)) {\n attribute.size ||= 1;\n attribute.count = attribute.data.length / attribute.size;\n attribute.indexFormat = 'uint16';\n attribute.buffer = device.createBuffer({\n size: Math.max(4, attribute.data.byteLength),\n usage: name === 'index'\n ? GPUBufferUsage.INDEX | GPUBufferUsage.COPY_DST\n : GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,\n });\n device.queue.writeBuffer(attribute.buffer, 0, attribute.data);\n }\n this._terrainGrids.set(divisions, attributes);\n }\n const base = this._terrainOriginElevation;\n const bottom = Math.min(this._dem.low, base) - base, top = Math.max(this._dem.high, base) - base;\n const sizeX = (opposite.x - corner.x) * metres, sizeZ = -(opposite.y - corner.y) * metres;\n // ponytail: ray picking sees the flat unit grid; read the DEM back if terrain must be pickable.\n const geometry = {\n device,\n attributes,\n drawRange: { start: 0, count: attributes.index.count },\n // Local bounds whose radius, scaled by the largest axis, still covers the displaced tile.\n bounds: {\n min: [0, bottom, 0], max: [1, top, 1], center: [0.5, (bottom + top) / 2, 0.5],\n radius: Math.hypot(sizeX, top - bottom, sizeZ) / 2 / Math.max(sizeX, 1, sizeZ),\n },\n };\n const mesh = {\n position: [(corner.x - origin.x) * metres, 0, -(corner.y - origin.y) * metres],\n rotation: [0, 0, 0],\n scale: [sizeX, 1, sizeZ],\n worldMatrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1],\n children: [],\n visible: true,\n device,\n geometry,\n program: this._rasterProgram,\n texture,\n // DEM pixel of the tile's corner, DEM pixels per tile, and the elevation at the layer origin.\n terrain: [\n coords.x * 256 * terrainScale - this._terrainBounds.min.x * 256,\n coords.y * 256 * terrainScale - this._terrainBounds.min.y * 256,\n 256 * terrainScale,\n base,\n ],\n tile,\n opacity: layer.options.opacity ?? 1,\n id: L.Layer.types['3d']._nextId++,\n renderOrder: -1,\n };\n this.add(mesh);\n this._rasterTiles.set(tile, mesh);\n tile._terrainVisibility = tile.style.visibility;\n },\n\n removeRasterTile(tile) {\n tile._terrainRequest?.abort();\n const mesh = this._rasterTiles.get(tile);\n if (!mesh) return;\n this.remove(mesh);\n this._destroyTexture(mesh.texture.texture);\n this._rasterTiles.delete(tile);\n tile.style.visibility = tile._terrainVisibility;\n delete tile._terrainVisibility;\n },\n});\n\n/**\n * WGSL twin of _getElevation for the vertex shader: bilinear DEM pixels, or the first valid\n * neighbour near no-data (stored as -1e9), else `base`. Expects `dem: texture_2d<f32>`.\n */\nL.Layer.types.terrain.elevationWGSL = `\n fn demSample(pixel: vec2<i32>) -> f32 {\n if (any(pixel < vec2<i32>(0)) || any(pixel >= vec2<i32>(textureDimensions(dem)))) { return -1e9; }\n return textureLoad(dem, pixel, 0).r;\n }\n fn elevation(pixel: vec2<f32>, base: f32) -> f32 {\n let p = pixel - vec2<f32>(0.5);\n let f = fract(p);\n let i = vec2<i32>(floor(p));\n let v00 = demSample(i);\n let v10 = demSample(i + vec2<i32>(1, 0));\n let v01 = demSample(i + vec2<i32>(0, 1));\n let v11 = demSample(i + vec2<i32>(1, 1));\n if (v00 > -1000.0 && v10 > -1000.0 && v01 > -1000.0 && v11 > -1000.0) {\n return mix(mix(v00, v10, f.x), mix(v01, v11, f.x), f.y);\n }\n if (v00 > -1000.0) { return v00; }\n if (v10 > -1000.0) { return v10; }\n if (v01 > -1000.0) { return v01; }\n if (v11 > -1000.0) { return v11; }\n return base;\n }\n`;\n"],
5
- "mappings": "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",
6
- "names": ["bridgeElevation", "terrainElevation", "terrainGrid", "terrainAtlas", "triangulate", "options", "terrainSource", "layerOptions", "map", "resolve", "layer", "tile", "grid", "attribute", "controller", "archive", "header", "northwest", "southeast", "tiles", "x", "y", "next", "coords", "result", "bridges", "response", "error", "location", "point", "geojson", "crs", "zoom", "origin", "metres", "base", "position", "normal", "color", "local", "lng", "lat", "z", "p", "push", "n", "geometry", "polygons", "polygon", "rings", "ring", "pixels", "points", "triangles", "starts", "r", "sum", "previous", "contour", "holes", "c", "i", "bridge", "t", "key", "below", "a", "b", "pa", "pb", "pc", "start", "q", "length", "corner", "ready", "bitmap", "divisions", "scale", "terrainScale", "opposite", "device", "texture", "bounds", "columns", "rows", "elevations", "low", "high", "attributes", "name", "bottom", "top", "sizeX", "sizeZ", "mesh"]
7
- }
@@ -1,41 +0,0 @@
1
- import"./3d.js";import{computeBounds as xe}from"../utils/geometry.js";import{along as ye,speed as we,toLanes as _e,tripsAt as ze,routeGeometry as Ae}from"../utils/traffic.js";import{build as se,vehicles as $}from"../utils/vehicles.js";import{underEntry as Ue}from"../utils/control.js";const Be=({properties:r})=>{const m=document.createElement("div");return m.style.whiteSpace="pre-line",m.textContent=[r.name,r.departure&&`Departure ${r.departure} ${r.timetable.timeZone}`,r.description].filter(Boolean).join(`
2
- `),m};function Le(r,{url:m,model:P,lights:G,side:A,outline:k,velocity:le}){const W=globalThis.L,Z=()=>{let e={live:!0};return r._map?.eachLayer(o=>{o.control?.time&&(e=o.control)}),{live:e.live,time:e.live?new Date:e.time}},y=W.DomUtil.create("small","traffic-status");y.style.cssText="display:block;max-width:200px;margin:0 0 4px 20px;color:#555;";const b=se(P(0)),D=b.position.length,w=D/3;let I=!1,x,O,h=[],_,c,g,J=-1/0,d=[],q=0,M=-1/0,Q=0,l=null,C=!0,N=!1;const j=new ArrayBuffer(16),X=new Float32Array(j),Y=new Uint32Array(j),ee=(e,o,n,t=0)=>{const a=r._createMesh(e,n,t);return a.extras.featureFaces=o,a},U=e=>{e&&(r.highlightedFeature?.mesh===e&&(r._setHighlight(null),r.hoveredFeature=null,r._showFeature(null)),r._disposeMesh(e))},te=e=>{y.textContent=`Error: ${e.message}`,y.setAttribute("role","alert"),console.error("Traffic layer",e)},ne=()=>{const e=r._map._terrain3D?._terrainReady&&r._map._terrain3D,o=r.root.position[1];for(const n of h)n.points.forEach((t,a)=>{const i=e&&(n.elevation??e._getElevation(n.latlngs[a]));t[2]=Number.isFinite(i)&&Number.isFinite(o)?i-o:0});C=!0,M=-1/0},ce=()=>{const e=r._map.options.crs,o=e.project(r.location),n=Math.cos(r.location.lat*Math.PI/180);for(const t of h){t.points=t.latlngs.map(([a,i])=>{const s=e.project(new W.LatLng(a,i));return[(s.x-o.x)*n,-(s.y-o.y)*n,0]}),t.lengths=[0];for(let a=1;a<t.points.length;a++)t.lengths.push(t.lengths[a-1]+Math.hypot(t.points[a][0]-t.points[a-1][0],t.points[a][1]-t.points[a-1][1]));t.length=t.lengths.at(-1)}ne(),U(g),g=null,_=null},ue=()=>{g=ee(Ae(h),[],{emissive:[.03,.25,.3],alphaMode:"BLEND"}),g.renderOrder=1e3},fe=()=>{if(U(c),c=null,!d.length)return;const e=d.flatMap((n,t)=>se(P(t)).color),o=e.length/3;c=ee({position:e.map(()=>0),normal:e.map(()=>0),color:e},d.map((n,t)=>({id:n.id,properties:n.properties,faceStart:t*w/3,faceEnd:(t+1)*w/3,vertexStart:t*w,vertexEnd:(t+1)*w})),{},GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC),c.geometry.drawRange.count=o,oe()},oe=()=>{const e={attributes:{position:{data:h.flatMap(o=>o.points.flatMap(([n,t,a])=>[n-20,a,t-20,n+20,a+5,t+20]))}}};xe(e),c.geometry.bounds=e.bounds},re=()=>{for(const e of[l?.params,l?.template,l?.points,l?.vehicles])e?.destroy();l=null},H=(e,o)=>{const n=e.createBuffer({size:Math.max(16,o.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});return e.queue.writeBuffer(n,0,o),n},pe=`
3
- struct Params { seconds: f32, side: f32, vertices: u32, total: u32 }
4
- struct Vehicle { start: u32, count: u32, base: f32, speed: f32 }
5
- @group(0) @binding(0) var<uniform> params: Params;
6
- @group(0) @binding(1) var<storage, read> model: array<f32>;
7
- @group(0) @binding(2) var<storage, read> points: array<vec4f>;
8
- @group(0) @binding(3) var<storage, read> vehicles: array<Vehicle>;
9
- @group(0) @binding(4) var<storage, read_write> position: array<f32>;
10
- @group(0) @binding(5) var<storage, read_write> normal: array<f32>;
11
- @compute @workgroup_size(64)
12
- fn main(@builtin(global_invocation_id) id: vec3u) {
13
- let v = id.x;
14
- if (v >= params.total) { return; }
15
- let vehicle = vehicles[v / params.vertices];
16
- let last = vehicle.start + vehicle.count - 1u;
17
- let length = points[last].w;
18
- var s = vehicle.base + params.seconds * vehicle.speed;
19
- s -= length * floor(s / length);
20
- var i = vehicle.start + 1u;
21
- while (i < last && points[i].w < s) { i++; }
22
- let a = points[i - 1u];
23
- let b = points[i];
24
- let d = select(b.w - a.w, 1.0, b.w == a.w);
25
- let t = (s - a.w) / d;
26
- let dx = (b.x - a.x) / d;
27
- let dz = (b.y - a.y) / d;
28
- let cx = a.x + (b.x - a.x) * t - dz * params.side;
29
- let cz = a.y + (b.y - a.y) * t + dx * params.side;
30
- let y = a.z + (b.z - a.z) * t;
31
- let k = (v % params.vertices) * 3u;
32
- let n = params.vertices * 3u + k;
33
- let o = v * 3u;
34
- position[o] = cx - model[k] * dz - model[k + 2u] * dx;
35
- position[o + 1u] = y + model[k + 1u];
36
- position[o + 2u] = cz + model[k] * dx - model[k + 2u] * dz;
37
- normal[o] = -model[n] * dz - model[n + 2u] * dx;
38
- normal[o + 1u] = model[n + 1u];
39
- normal[o + 2u] = model[n] * dx - model[n + 2u] * dz;
40
- }`,de=()=>{const{device:e}=r.renderer;if(l?.device!==e&&(re(),l={device:e,pipeline:e.createComputePipeline({layout:"auto",compute:{module:e.createShaderModule({code:pe}),entryPoint:"main"}}),params:e.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),template:H(e,new Float32Array([...b.position,...b.normal]))},C=!0),C){const i=new Float32Array(h.reduce((u,p)=>u+p.points.length,0)*4);let s=0;for(const u of h)u.start=s/4,u.points.forEach((p,f)=>{i.set([p[0],p[1],p[2],u.lengths[f]],s),s+=4});l.points?.destroy(),l.points=H(e,i),C=!1}const o=new Float32Array(d.length*4),n=new Uint32Array(o.buffer);d.forEach((i,s)=>{n[s*4]=i.lane.start,n[s*4+1]=i.lane.points.length,o[s*4+2]=i.distance,o[s*4+3]=i.speed,c.extras.featureFaces[s].properties=i.properties}),l.vehicles?.size>=o.byteLength?e.queue.writeBuffer(l.vehicles,0,o):(l.vehicles?.destroy(),l.vehicles=H(e,o));const{position:t,normal:a}=c.geometry.attributes;l.bindGroup=e.createBindGroup({layout:l.pipeline.getBindGroupLayout(0),entries:[l.params,l.template,l.points,l.vehicles,t.buffer,a.buffer].map((i,s)=>({binding:s,resource:{buffer:i}}))})},me=e=>{const{device:o}=l;X[0]=Q=e,X[1]=A,Y[2]=w,Y[3]=d.length*w,o.queue.writeBuffer(l.params,0,j);const n=o.createCommandEncoder(),t=n.beginComputePass();t.setPipeline(l.pipeline),t.setBindGroup(0,l.bindGroup),t.dispatchWorkgroups(Math.ceil(Y[3]/64)),t.end(),o.queue.submit([n.finish()]),N=!0},ae=e=>{const{points:o,lengths:n,length:t}=e.lane;let a=e.distance+Q*e.speed;a-=t*Math.floor(a/t);const{x:i,y:s,z:u,dx:p,dz:f}=ye(o,n,a);return{x:i-f*A,y:s,z:u+p*A,dx:p,dz:f}},he=()=>{if(!c||!N)return;N=!1;const{position:e,normal:o}=c.geometry.attributes;d.forEach((n,t)=>{const{x:a,y:i,z:s,dx:u,dz:p}=ae(n);for(let f=0,v=t*D;f<D;f+=3,v+=3){const E=b.position[f],S=b.position[f+2],F=b.normal[f],R=b.normal[f+2];e.data[v]=a-E*p-S*u,e.data[v+1]=i+b.position[f+1],e.data[v+2]=s+E*u-S*p,o.data[v]=-F*p-R*u,o.data[v+1]=b.normal[f+1],o.data[v+2]=F*u-R*p}})},ge=r.raycast;r.raycast=function(...e){return he(),ge.apply(this,e)};const B=()=>{if(x=void 0,!I||!r._map)return;if(!r.renderer){x=requestAnimationFrame(B);return}c&&!(c.geometry.attributes.position.buffer.usage&GPUBufferUsage.STORAGE)&&(_=null,M=-1/0);const{live:e,time:o}=Z(),n=o?.getTime(),t=Number.isFinite(n);let a=!1;if(!e||!t||!(n>=q&&n<M)){let i;try{d=t?ze(o,h,le):[],i=t?z?`${d.length} vehicle${d.length===1?"":"s"}${z.note?` \xB7 ${z.note}`:""}`:"Loading\u2026":"Select a valid simulation date"}catch(u){return te(u)}q=n,M=n+1e3;const s=d.map(u=>u.id).join();a=s!==_||k&&!g&&h.length,k&&!g&&h.length&&ue(),s!==_&&(fe(),_=s),c&&de(),y.textContent!==i&&(y.textContent=i),y.removeAttribute("role")}c&&me((n-q)/1e3),c&&G&&(!e||!(performance.now()-J<100))&&(J=performance.now(),c.extras.lights=d.flatMap(i=>{const{x:s,y:u,z:p,dx:f,dz:v}=ae(i);return G.map(({position:[E,S,F],...R})=>({...R,position:[s-E*v-F*f,u+S,p+E*f-F*v]}))})),(c||a)&&r.update(),e&&t&&(x=requestAnimationFrame(B))};let z,V;const ve=async(e,o)=>{const n=new URL(m,document.baseURI).href;if(/\.m?js(?:[?#]|$)/i.test(m))return(await import(n)).default(e,r,o);if(!V){const t=await fetch(n,{signal:o});if(!t.ok)throw new Error(`HTTP ${t.status}`);V=await t.json()}return V},be=()=>{const{time:e}=Z();if(!Number.isFinite(e?.getTime()))return;O?.abort();const{signal:o}=O=new AbortController;ve(e,o).then(n=>{o.aborted||!r._map||n===z||(z=n,h=_e(n),ce(),x||B())},n=>{n.name!=="AbortError"&&te(n)})},T=e=>{e?.layer!==r&&(cancelAnimationFrame(x),be(),B())},K=()=>{h.length&&(ne(),U(g),g=null,c&&oe(),x||B())},ie=()=>{r._map.off("simulationtimechange layerremove",T).on("simulationtimechange layerremove",T),r._map.off("terrainchange",K).on("terrainchange",K),Ue(r,y),T()};r.on("ready",()=>{I=!0,r._map&&ie()}),r.on("add",()=>{I&&ie()}),r.on("remove",()=>{O?.abort(),cancelAnimationFrame(x),x=void 0,r._map.off("simulationtimechange layerremove",T).off("terrainchange",K),U(c),U(g),c=g=null,re(),h=[],d=[],_=z=null})}L.Layer.types.traffic=L.Layer.types["3d"].extend({initialize({url:r,vehicle:m="car",side:P,outline:G=!1,speed:A=we,...k}={}){if(!r)throw new Error("Traffic needs a source url");if(!$[m])throw new Error(`Unknown vehicle: ${m}`);L.Layer.types["3d"].prototype.initialize.call(this,{tooltipContent:Be,nightLight:!!$[m].lights,...k}),Le(this,{url:r,...$[m],side:P??$[m].side,outline:G,velocity:A})}});
41
- //# sourceMappingURL=traffic.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/traffic.js"],
4
- "sourcesContent": ["import './3d.js';\nimport { computeBounds } from '../utils/geometry.js';\nimport { along, speed, toLanes, tripsAt, routeGeometry } from '../utils/traffic.js';\nimport { build, vehicles } from '../utils/vehicles.js';\nimport { underEntry } from '../utils/control.js';\n\nconst tooltip = ({ properties: p }) => {\n const content = document.createElement('div');\n content.style.whiteSpace = 'pre-line';\n content.textContent = [p.name, p.departure && `Departure ${p.departure} ${p.timetable.timeZone}`, p.description].filter(Boolean).join('\\n');\n return content;\n};\n\nfunction installTraffic(layer, { url, model, lights, side, outline, velocity }) {\n const L = globalThis.L;\n // The 'sunlight' layer on the same map drives the simulation time; without one, vehicles run live.\n const now = () => {\n let control = { live: true };\n layer._map?.eachLayer(other => { if (other.control?.time) control = other.control; });\n return { live: control.live, time: control.live ? new Date() : control.time };\n };\n const status = L.DomUtil.create('small', 'traffic-status');\n status.style.cssText = 'display:block;max-width:200px;margin:0 0 4px 20px;color:#555;';\n const template = build(model(0)), stride = template.position.length, vertices = stride / 3;\n let ready = false, frame, request, lanes = [], tripsKey, mesh, route, litAt = -Infinity;\n // Vehicles move on the GPU: `trips` are rebased at most once per second, a compute pass places them every frame.\n let trips = [], rebasedAt = 0, nextCheck = -Infinity, elapsed = 0, gpu = null, lanesDirty = true, stale = false;\n const params = new ArrayBuffer(16), paramFloats = new Float32Array(params), paramInts = new Uint32Array(params);\n\n const createMesh = (data, featureFaces, material, usage = 0) => {\n const result = layer._createMesh(data, material, usage);\n result.extras.featureFaces = featureFaces;\n return result;\n };\n const dispose = object => {\n if (!object) return;\n if (layer.highlightedFeature?.mesh === object) {\n layer._setHighlight(null);\n layer.hoveredFeature = null;\n layer._showFeature(null);\n }\n layer._disposeMesh(object);\n };\n const fail = error => {\n status.textContent = `Error: ${error.message}`;\n status.setAttribute('role', 'alert');\n console.error('Traffic layer', error);\n };\n\n const ground = () => {\n const terrain = layer._map._terrain3D?._terrainReady && layer._map._terrain3D, base = layer.root.position[1];\n for (const lane of lanes) lane.points.forEach((point, i) => {\n const elevation = terrain && (lane.elevation ?? terrain._getElevation(lane.latlngs[i]));\n point[2] = Number.isFinite(elevation) && Number.isFinite(base) ? elevation - base : 0;\n });\n lanesDirty = true;\n nextCheck = -Infinity;\n };\n const prepare = () => {\n const crs = layer._map.options.crs, origin = crs.project(layer.location);\n const metres = Math.cos(layer.location.lat * Math.PI / 180);\n for (const lane of lanes) {\n lane.points = lane.latlngs.map(([lat, lng]) => {\n const point = crs.project(new L.LatLng(lat, lng));\n return [(point.x - origin.x) * metres, -(point.y - origin.y) * metres, 0];\n });\n lane.lengths = [0];\n for (let i = 1; i < lane.points.length; i++) {\n lane.lengths.push(lane.lengths[i - 1] + Math.hypot(lane.points[i][0] - lane.points[i - 1][0], lane.points[i][1] - lane.points[i - 1][1]));\n }\n lane.length = lane.lengths.at(-1);\n }\n ground();\n dispose(route); route = null;\n tripsKey = null;\n };\n\n // Dashed lane outline, just above the lanes.\n const drawRoute = () => {\n\n route = createMesh(routeGeometry(lanes), [], { emissive: [0.03, 0.25, 0.3], alphaMode: 'BLEND' });\n route.renderOrder = 1000;\n };\n // One batched mesh, `vertices` per vehicle; the compute pass writes its position/normal buffers (STORAGE).\n const rebuild = () => {\n dispose(mesh); mesh = null;\n if (!trips.length) return;\n const color = trips.flatMap((trip, i) => build(model(i)).color), count = color.length / 3;\n mesh = createMesh({ position: color.map(() => 0), normal: color.map(() => 0), color },\n trips.map((trip, i) => ({ id: trip.id, properties: trip.properties, faceStart: i * vertices / 3, faceEnd: (i + 1) * vertices / 3,\n vertexStart: i * vertices, vertexEnd: (i + 1) * vertices })), {}, GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC);\n mesh.geometry.drawRange.count = count;\n bounds();\n };\n // Vehicles never leave their lanes: cull and pick against the lanes' extent.\n const bounds = () => {\n const extent = { attributes: { position: { data: lanes.flatMap(lane => lane.points.flatMap(([x, z, y]) => [x - 20, y, z - 20, x + 20, y + 5, z + 20])) } } };\n computeBounds(extent);\n mesh.geometry.bounds = extent.bounds;\n };\n\n const destroyGpu = () => {\n for (const buffer of [gpu?.params, gpu?.template, gpu?.points, gpu?.vehicles]) buffer?.destroy();\n gpu = null;\n };\n const storage = (device, data) => {\n const buffer = device.createBuffer({ size: Math.max(16, data.byteLength), usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST });\n device.queue.writeBuffer(buffer, 0, data);\n return buffer;\n };\n // Lane points are [x, z, ground, cumulative length]. Mirrors along() and place().\n const shader = `\n struct Params { seconds: f32, side: f32, vertices: u32, total: u32 }\n struct Vehicle { start: u32, count: u32, base: f32, speed: f32 }\n @group(0) @binding(0) var<uniform> params: Params;\n @group(0) @binding(1) var<storage, read> model: array<f32>;\n @group(0) @binding(2) var<storage, read> points: array<vec4f>;\n @group(0) @binding(3) var<storage, read> vehicles: array<Vehicle>;\n @group(0) @binding(4) var<storage, read_write> position: array<f32>;\n @group(0) @binding(5) var<storage, read_write> normal: array<f32>;\n @compute @workgroup_size(64)\n fn main(@builtin(global_invocation_id) id: vec3u) {\n let v = id.x;\n if (v >= params.total) { return; }\n let vehicle = vehicles[v / params.vertices];\n let last = vehicle.start + vehicle.count - 1u;\n let length = points[last].w;\n var s = vehicle.base + params.seconds * vehicle.speed;\n s -= length * floor(s / length);\n var i = vehicle.start + 1u;\n while (i < last && points[i].w < s) { i++; }\n let a = points[i - 1u];\n let b = points[i];\n let d = select(b.w - a.w, 1.0, b.w == a.w);\n let t = (s - a.w) / d;\n let dx = (b.x - a.x) / d;\n let dz = (b.y - a.y) / d;\n let cx = a.x + (b.x - a.x) * t - dz * params.side;\n let cz = a.y + (b.y - a.y) * t + dx * params.side;\n let y = a.z + (b.z - a.z) * t;\n let k = (v % params.vertices) * 3u;\n let n = params.vertices * 3u + k;\n let o = v * 3u;\n position[o] = cx - model[k] * dz - model[k + 2u] * dx;\n position[o + 1u] = y + model[k + 1u];\n position[o + 2u] = cz + model[k] * dx - model[k + 2u] * dz;\n normal[o] = -model[n] * dz - model[n + 2u] * dx;\n normal[o + 1u] = model[n + 1u];\n normal[o + 2u] = model[n] * dx - model[n + 2u] * dz;\n }`;\n // Upload lanes and the rebased trips; the CPU copy is refreshed only for picking (place()).\n const rebase = () => {\n const { device } = layer.renderer;\n if (gpu?.device !== device) {\n destroyGpu();\n gpu = {\n device,\n pipeline: device.createComputePipeline({ layout: 'auto', compute: { module: device.createShaderModule({ code: shader }), entryPoint: 'main' } }),\n params: device.createBuffer({ size: 16, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST }),\n template: storage(device, new Float32Array([...template.position, ...template.normal])),\n };\n lanesDirty = true;\n }\n if (lanesDirty) {\n const data = new Float32Array(lanes.reduce((count, lane) => count + lane.points.length, 0) * 4);\n let offset = 0;\n for (const lane of lanes) {\n lane.start = offset / 4;\n lane.points.forEach((point, i) => { data.set([point[0], point[1], point[2], lane.lengths[i]], offset); offset += 4; });\n }\n gpu.points?.destroy();\n gpu.points = storage(device, data);\n lanesDirty = false;\n }\n const data = new Float32Array(trips.length * 4), index = new Uint32Array(data.buffer);\n trips.forEach((trip, i) => {\n index[i * 4] = trip.lane.start;\n index[i * 4 + 1] = trip.lane.points.length;\n data[i * 4 + 2] = trip.distance;\n data[i * 4 + 3] = trip.speed;\n mesh.extras.featureFaces[i].properties = trip.properties;\n });\n if (gpu.vehicles?.size >= data.byteLength) device.queue.writeBuffer(gpu.vehicles, 0, data);\n else {\n gpu.vehicles?.destroy();\n gpu.vehicles = storage(device, data);\n }\n const { position, normal } = mesh.geometry.attributes;\n gpu.bindGroup = device.createBindGroup({\n layout: gpu.pipeline.getBindGroupLayout(0),\n entries: [gpu.params, gpu.template, gpu.points, gpu.vehicles, position.buffer, normal.buffer]\n .map((buffer, binding) => ({ binding, resource: { buffer } })),\n });\n };\n const move = seconds => {\n const { device } = gpu;\n paramFloats[0] = elapsed = seconds;\n paramFloats[1] = side;\n paramInts[2] = vertices;\n paramInts[3] = trips.length * vertices;\n device.queue.writeBuffer(gpu.params, 0, params);\n const encoder = device.createCommandEncoder(), pass = encoder.beginComputePass();\n pass.setPipeline(gpu.pipeline);\n pass.setBindGroup(0, gpu.bindGroup);\n pass.dispatchWorkgroups(Math.ceil(paramInts[3] / 64));\n pass.end();\n device.queue.submit([encoder.finish()]);\n stale = true;\n };\n // CPU twin of the compute pass: the centre of `trip` and its heading.\n const locate = trip => {\n const { points, lengths, length } = trip.lane;\n let distance = trip.distance + elapsed * trip.speed;\n distance -= length * Math.floor(distance / length);\n const { x, y, z, dx, dz } = along(points, lengths, distance);\n return { x: x - dz * side, y, z: z + dx * side, dx, dz };\n };\n // Run lazily before picking.\n const place = () => {\n if (!mesh || !stale) return;\n stale = false;\n const { position, normal } = mesh.geometry.attributes;\n trips.forEach((trip, i) => {\n const { x: cx, y, z: cz, dx, dz } = locate(trip);\n for (let k = 0, o = i * stride; k < stride; k += 3, o += 3) {\n const lx = template.position[k], lz = template.position[k + 2], nx = template.normal[k], nz = template.normal[k + 2];\n position.data[o] = cx - lx * dz - lz * dx;\n position.data[o + 1] = y + template.position[k + 1];\n position.data[o + 2] = cz + lx * dx - lz * dz;\n normal.data[o] = -nx * dz - nz * dx;\n normal.data[o + 1] = template.normal[k + 1];\n normal.data[o + 2] = nx * dx - nz * dz;\n }\n });\n };\n const raycast = layer.raycast;\n layer.raycast = function (...args) {\n place();\n return raycast.apply(this, args);\n };\n\n const tick = () => {\n frame = undefined;\n if (!ready || !layer._map) return;\n // Re-adding after the last GPU owner was removed can attach asynchronously.\n if (!layer.renderer) { frame = requestAnimationFrame(tick); return; }\n // A renderer change re-creates vertex buffers without STORAGE: rebuild the mesh.\n if (mesh && !(mesh.geometry.attributes.position.buffer.usage & GPUBufferUsage.STORAGE)) { tripsKey = null; nextCheck = -Infinity; }\n const { live, time } = now(), ms = time?.getTime(), valid = Number.isFinite(ms);\n let changed = false;\n // Trips only change at timetable/hour boundaries: re-check once per second while live.\n if (!live || !valid || !(ms >= rebasedAt && ms < nextCheck)) {\n let text;\n try {\n trips = valid ? tripsAt(time, lanes, velocity) : [];\n text = !valid ? 'Select a valid simulation date' : !loaded ? 'Loading\u2026' :\n `${trips.length} vehicle${trips.length === 1 ? '' : 's'}${loaded.note ? ` \u00B7 ${loaded.note}` : ''}`;\n } catch (error) { return fail(error); }\n rebasedAt = ms;\n nextCheck = ms + 1000;\n const key = trips.map(trip => trip.id).join();\n changed = key !== tripsKey || (outline && !route && lanes.length);\n if (outline && !route && lanes.length) drawRoute();\n if (key !== tripsKey) { rebuild(); tripsKey = key; }\n if (mesh) rebase();\n if (status.textContent !== text) status.textContent = text;\n status.removeAttribute('role');\n }\n if (mesh) move((ms - rebasedAt) / 1000);\n // ponytail: night point lights follow the vehicles at 10 Hz via the shared CPU light grid (~5 ms with thousands of lamps);\n // bin the lights in a compute pass if it shows up in profiles.\n if (mesh && lights && (!live || !(performance.now() - litAt < 100))) {\n litAt = performance.now();\n mesh.extras.lights = trips.flatMap(trip => {\n const { x, y, z, dx, dz } = locate(trip);\n return lights.map(({ position: [lx, ly, lz], ...light }) => ({ ...light, position: [x - lx * dz - lz * dx, y + ly, z + lx * dx - lz * dz] }));\n });\n }\n if (mesh || changed) layer.update();\n if (live && valid) frame = requestAnimationFrame(tick);\n };\n let loaded, file;\n // A JS module serves time-dependent lanes; anything else is a static GeoJSON file, fetched once.\n const fetchLanes = async (time, signal) => {\n const href = new URL(url, document.baseURI).href;\n if (/\\.m?js(?:[?#]|$)/i.test(url)) return (await import(href)).default(time, layer, signal);\n if (!file) {\n const response = await fetch(href, { signal });\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n file = await response.json();\n }\n return file;\n };\n const load = () => {\n const { time } = now();\n if (!Number.isFinite(time?.getTime())) return;\n request?.abort();\n const { signal } = request = new AbortController();\n fetchLanes(time, signal).then(data => {\n if (signal.aborted || !layer._map || data === loaded) return;\n loaded = data;\n lanes = toLanes(data);\n prepare();\n if (!frame) tick();\n }, error => { if (error.name !== 'AbortError') fail(error); });\n };\n // 'layerremove' fires once the clock layer has really left the map.\n const update = event => {\n if (event?.layer === layer) return;\n cancelAnimationFrame(frame);\n load();\n tick();\n };\n const terrain = () => {\n if (!lanes.length) return;\n ground();\n dispose(route); route = null;\n if (mesh) bounds();\n if (!frame) tick();\n };\n const start = () => {\n layer._map.off('simulationtimechange layerremove', update).on('simulationtimechange layerremove', update);\n layer._map.off('terrainchange', terrain).on('terrainchange', terrain);\n underEntry(layer, status);\n update();\n };\n layer.on('ready', () => { ready = true; if (layer._map) start(); });\n layer.on('add', () => { if (ready) start(); });\n layer.on('remove', () => {\n request?.abort();\n cancelAnimationFrame(frame); frame = undefined;\n layer._map.off('simulationtimechange layerremove', update).off('terrainchange', terrain);\n dispose(mesh); dispose(route); mesh = route = null;\n destroyGpu();\n lanes = []; trips = []; tripsKey = loaded = null;\n });\n}\n\n/**\n * Vehicles moving along GeoJSON lanes; a compute pass places them on the GPU every frame.\n * Source options:\n * - `url`: GeoJSON (Multi)LineStrings, or a JS module whose default export `(time, layer, signal)` returns them (time-dependent data);\n * - `vehicle`: 'car' (default) or 'boat'; `side`: offset right of the lane centreline in metres (vehicle default);\n * - `speed`: m/s of `flow` lanes; `outline`: draw the lanes.\n * Lane properties: `flow` (vehicles/h) or `timetable` (see scheduledTrips in utils/traffic.js), optional fixed `elevation`\n * in metres, `name`/`description` for the default tooltip. The status line (vehicle count, then the FeatureCollection `note`) sits under the layer's entry in the layers control.\n * The 'sunlight' layer on the same map drives the time; without one, vehicles run live.\n */\nL.Layer.types.traffic = L.Layer.types['3d'].extend({\n initialize({ url, vehicle = 'car', side, outline = false, speed: velocity = speed, ...options } = {}) {\n if (!url) throw new Error('Traffic needs a source url');\n if (!vehicles[vehicle]) throw new Error(`Unknown vehicle: ${vehicle}`);\n L.Layer.types['3d'].prototype.initialize.call(this, { tooltipContent: tooltip, nightLight: Boolean(vehicles[vehicle].lights), ...options });\n installTraffic(this, { url, ...vehicles[vehicle], side: side ?? vehicles[vehicle].side, outline, velocity });\n },\n});\n"],
5
- "mappings": "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",
6
- "names": ["computeBounds", "along", "speed", "toLanes", "tripsAt", "routeGeometry", "build", "vehicles", "underEntry", "tooltip", "p", "content", "installTraffic", "layer", "url", "model", "lights", "side", "outline", "velocity", "L", "now", "control", "other", "status", "template", "stride", "vertices", "ready", "frame", "request", "lanes", "tripsKey", "mesh", "route", "litAt", "trips", "rebasedAt", "nextCheck", "elapsed", "gpu", "lanesDirty", "stale", "params", "paramFloats", "paramInts", "createMesh", "data", "featureFaces", "material", "usage", "result", "dispose", "object", "fail", "error", "ground", "terrain", "base", "lane", "point", "i", "elevation", "prepare", "crs", "origin", "metres", "lat", "lng", "drawRoute", "rebuild", "color", "trip", "count", "bounds", "extent", "x", "z", "y", "destroyGpu", "buffer", "storage", "device", "shader", "rebase", "offset", "index", "position", "normal", "binding", "move", "seconds", "encoder", "pass", "locate", "points", "lengths", "length", "distance", "dx", "dz", "place", "cx", "cz", "k", "o", "lx", "lz", "nx", "nz", "raycast", "args", "tick", "live", "time", "ms", "valid", "changed", "text", "loaded", "key", "ly", "light", "file", "fetchLanes", "signal", "href", "response", "load", "update", "event", "start", "vehicle", "options"]
7
- }
@@ -1,2 +0,0 @@
1
- import{CELL as R,collider as O,horizontalRay as Q,parts as $,limbs as H}from"../utils/walk.js";import"./3d.js";import{computeBounds as tt}from"../utils/geometry.js";import{traverse as ot,updateWorldMatrix as et}from"../utils/scene.js";import{build as nt}from"../utils/vehicles.js";const j={KeyW:[1,0],ArrowUp:[1,0],KeyS:[-1,0],ArrowDown:[-1,0],KeyD:[0,1],ArrowRight:[0,1],KeyA:[0,-1],ArrowLeft:[0,-1]},J=o=>Math.atan2(Math.sin(o),Math.cos(o));function it(o,T,B,I,a,g,f){const x=globalThis.L.Layer.types,c=y=>y===o||["terrain","traffic"].some(l=>x[l]&&y instanceof x[l]);et(o.scene);let _=f,M=null;for(const y of o._shared._layers)c(y)||ot(y.root,l=>{if(!l.visible)return!0;if(!l.geometry?.attributes?.position?.data||l.program?.depthTest===!1)return;l.geometry.bounds||tt(l.geometry);const i=l.worldMatrix,{center:r,radius:b}=l.geometry.bounds;if(Math.hypot(i[0]*r[0]+i[4]*r[1]+i[8]*r[2]+i[12]-T,i[2]*r[0]+i[6]*r[1]+i[10]*r[2]+i[14]-I)>b*Math.hypot(i[0],i[1],i[2])+f)return;const e=O(l),k=T-i[12]+e.origin[0],F=B-i[13]+e.origin[1],P=I-i[14]+e.origin[2],S=new Set;for(let K=Math.floor(Math.min(k,k+a*f)/R);K<=Math.floor(Math.max(k,k+a*f)/R);K++)for(let z=Math.floor(Math.min(P,P+g*f)/R);z<=Math.floor(Math.max(P,P+g*f)/R);z++)for(const u of e.cells.get(K+","+z)||[])if(!(S.has(u)||a*e.nrm[u*2]+g*e.nrm[u*2+1]>=0)){S.add(u);for(const V of[.4,1.5]){const D=Q(e.tri,u,k,F+V,P,a,g);D>=0&&D<_&&(_=D,M=[e.nrm[u*2],e.nrm[u*2+1]])}}});return M}function at(o,{speed:T,distance:B,position:I}){const a=globalThis.L,g=new Set,f=new a.Control({position:I}),x=a.DomUtil.create("div","leaflet-bar leaflet-control");x.style.cssText="display:flex;align-items:center;background:#fff;";const c=a.DomUtil.create("button","",x);c.type="button",c.title="Walk",c.setAttribute("aria-label","Walk"),c.setAttribute("aria-pressed","false"),c.textContent="\u{1F6B6}",c.style.cssText="width:30px;height:30px;padding:0;border:0;border-radius:4px;background:#fff;font-size:18px;line-height:30px;cursor:pointer;";const _=a.DomUtil.create("small","",x);_.style.cssText="display:none;padding:0 8px;color:#333;white-space:nowrap;",_.textContent="W/S: run \xB7 A/D: turn \xB7 drag: look around \xB7 Esc: exit",a.DomEvent.disableClickPropagation(x),f.onAdd=()=>x;let M,y,l,i=0,r,b;const e=o.walker={latlng:null,heading:0,phase:0},k=()=>{const t=o._map,n=t.options.crs,h=n.project(o.location),s=Math.cos(o.location.lat*Math.PI/180),p=n.project(e.latlng),m=t._terrain3D?._terrainReady&&t._terrain3D,A=m&&m._getElevation(e.latlng)||0;return[(p.x-h.x)*s,A-o.root.position[1],-(p.y-h.y)*s]},F=()=>{const[t,n,h]=k(),s=-e.heading,p=Math.cos(s),m=Math.sin(s);H.forEach(([,A,d,E],X)=>{const W=M[X];W.position[0]=t+A*p,W.position[1]=n+d,W.position[2]=h-A*m,W.rotation[0]=E*i*Math.sin(e.phase),W.rotation[1]=s}),o.update()},P=t=>{y=requestAnimationFrame(P);const n=o._map,h=Math.min(.1,(t-(l??t))/1e3);if(l=t,!o.renderer)return;let s=!1;M||(M=H.map(([d])=>o._createMesh(nt($[d]))),s=!0);let p=0,m=0;for(const d of g)p+=j[d]?.[0]||0,m+=j[d]?.[1]||0;if(p=Math.sign(p),m=Math.sign(m),m&&(e.heading=J(e.heading+m*2.5*h),s=!0),p){const d=p*T*h,{lat:E,lng:X}=e.latlng,{position:W,scale:N}=o.root;let C=Math.sin(e.heading)*d,Z=Math.cos(e.heading)*d;const Y=k().map((w,G)=>W[G]+N[G]*w),v=()=>{const w=Math.hypot(C,Z);return w>1e-6&&it(o,Y[0],Y[1],Y[2],C/w,-Z/w,w+.3)},U=v();if(U){const w=C*U[0]-Z*U[1];C-=w*U[0],Z+=w*U[1],v()&&(C=Z=0)}e.latlng=new a.LatLng(E+Z/111320,X+C/(111320*Math.cos(E*Math.PI/180))),e.phase+=Math.hypot(C,Z)/1.6*Math.PI,s=!0}if(p||m){const d=n.getBearing()*Math.PI/180,E=J(-e.heading-d);Math.abs(E)>.001&&n._setPitchAndBearing(n.getPitch(),(d+E*Math.min(1,h*4))*180/Math.PI),n.setView(e.latlng,n.getZoom(),{animate:!1})}const A=p?.9:0;Math.abs(i-A)>.001&&(i+=(A-i)*Math.min(1,h*10),s=!0),s&&F()},S=t=>{if(!(t.target.closest?.("input:not([type=checkbox], [type=radio]), select, textarea, [contenteditable]")||t.ctrlKey||t.altKey||t.metaKey)){if(t.type==="keydown"&&t.code==="Escape"){D();return}j[t.code]&&(t.preventDefault(),t.type==="keydown"?g.add(t.code):g.delete(t.code))}},K=()=>g.clear(),z=t=>{const n=o._map;if(t.type==="pointerdown"){if(t.button!==0||t.target.closest(".leaflet-control"))return;b={x:t.clientX,y:t.clientY},n.getContainer().setPointerCapture(t.pointerId)}else b&&t.type==="pointermove"?(n._setPitchAndBearing(Math.max(20,Math.min(85,n.getPitch()-(t.clientY-b.y)*.2)),n.getBearing()-(t.clientX-b.x)*.25),b={x:t.clientX,y:t.clientY}):b=null},u=()=>{M&&F()},V=()=>{const t=o._map;if(r||!t)return;e.latlng=t.getCenter();const n=t.getSize().y*1.5/B,h=Math.min(t.getMaxZoom(),Math.log2(n*4007501668557849e-8*Math.cos(e.latlng.lat*Math.PI/180)/256));r={zoom:t.getZoom(),pitch:t.getPitch(),scrollWheelZoom:t.options.scrollWheelZoom,handlers:["dragging","keyboard","doubleClickZoom","boxZoom"].filter(s=>t[s]?.enabled())};for(const s of r.handlers)t[s].disable();t.options.scrollWheelZoom=r.scrollWheelZoom&&"center",e.heading=-t.getBearing()*Math.PI/180,t.setView(e.latlng,h,{animate:!1}),t.setPitch(75),a.DomEvent.on(document,"keydown keyup",S),a.DomEvent.on(window,"blur",K),a.DomEvent.on(t.getContainer(),"pointerdown pointermove pointerup pointercancel",z),t.on("terrainchange",u),c.setAttribute("aria-pressed","true"),c.style.background="#e4e4e4",_.style.display="",l=void 0,y=requestAnimationFrame(P)},D=()=>{const t=o._map;cancelAnimationFrame(y),g.clear(),b=null,a.DomEvent.off(document,"keydown keyup",S),a.DomEvent.off(window,"blur",K);for(const n of M||[])o._disposeMesh(n);if(M=null,c.setAttribute("aria-pressed","false"),c.style.background="#fff",_.style.display="none",!(!t||!r)){a.DomEvent.off(t.getContainer(),"pointerdown pointermove pointerup pointercancel",z),t.off("terrainchange",u),t.options.scrollWheelZoom=r.scrollWheelZoom;for(const n of r.handlers)t[n].enable();t.setView(e.latlng,r.zoom,{animate:!1}),t.setPitch(r.pitch),r=null}};a.DomEvent.on(c,"click",()=>r?D():V());let q=!1;o.on("ready",()=>{q=!0,o._map&&f.addTo(o._map)}),o.on("add",()=>{q&&f.addTo(o._map)}),o.on("remove",()=>{D(),f.remove()})}L.Layer.types.walk=L.Layer.types["3d"].extend({initialize({speed:o=70,distance:T=20,position:B="bottomright",...I}={}){L.Layer.types["3d"].prototype.initialize.call(this,I),at(this,{speed:o,distance:T,position:B})}});
2
- //# sourceMappingURL=walk.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/types/walk.js"],
4
- "sourcesContent": ["import { CELL, collider, horizontalRay, parts, limbs } from '../utils/walk.js';\nimport './3d.js';\nimport { computeBounds } from '../utils/geometry.js';\nimport { traverse, updateWorldMatrix } from '../utils/scene.js';\nimport { build } from '../utils/vehicles.js';\n\n// W/S (\u2191/\u2193) run forward/back along the heading, A/D (\u2190/\u2192) turn: [forward, turn].\nconst moves = { KeyW: [1, 0], ArrowUp: [1, 0], KeyS: [-1, 0], ArrowDown: [-1, 0], KeyD: [0, 1], ArrowRight: [0, 1], KeyA: [0, -1], ArrowLeft: [0, -1] };\nconst wrap = angle => Math.atan2(Math.sin(angle), Math.cos(angle));\n\n// Horizontal normal of the nearest wall faced within `reach` metres of the feet at world (x, y, z), walking along\n// the unit (dx, dz); knee and chest rays, so arches and tree crowns above the head let the walker through.\n// ponytail: traffic vehicles and boats move on the GPU and are not obstacles.\nfunction hit(layer, x, y, z, dx, dz, reach) {\n const types = globalThis.L.Layer.types, skip = other => other === layer ||\n ['terrain', 'traffic'].some(name => types[name] && other instanceof types[name]);\n updateWorldMatrix(layer.scene);\n let best = reach, found = null;\n for (const other of layer._shared._layers) {\n if (skip(other)) continue;\n traverse(other.root, mesh => {\n if (!mesh.visible) return true;\n if (!mesh.geometry?.attributes?.position?.data || mesh.program?.depthTest === false) return;\n if (!mesh.geometry.bounds) computeBounds(mesh.geometry);\n const m = mesh.worldMatrix, { center: k, radius } = mesh.geometry.bounds;\n if (Math.hypot(m[0] * k[0] + m[4] * k[1] + m[8] * k[2] + m[12] - x, m[2] * k[0] + m[6] * k[1] + m[10] * k[2] + m[14] - z) >\n radius * Math.hypot(m[0], m[1], m[2]) + reach) return;\n const c = collider(mesh), ox = x - m[12] + c.origin[0], oy = y - m[13] + c.origin[1], oz = z - m[14] + c.origin[2];\n const seen = new Set();\n for (let ix = Math.floor(Math.min(ox, ox + dx * reach) / CELL); ix <= Math.floor(Math.max(ox, ox + dx * reach) / CELL); ix++)\n for (let iz = Math.floor(Math.min(oz, oz + dz * reach) / CELL); iz <= Math.floor(Math.max(oz, oz + dz * reach) / CELL); iz++)\n for (const t of c.cells.get(ix + ',' + iz) || []) {\n // Walls are one-way: walking out of a building (e.g. starting inside one) is allowed.\n if (seen.has(t) || dx * c.nrm[t * 2] + dz * c.nrm[t * 2 + 1] >= 0) continue;\n seen.add(t);\n for (const height of [0.4, 1.5]) {\n const d = horizontalRay(c.tri, t, ox, oy + height, oz, dx, dz);\n if (d >= 0 && d < best) { best = d; found = [c.nrm[t * 2], c.nrm[t * 2 + 1]]; }\n }\n }\n });\n }\n return found;\n}\n\nfunction installWalk(layer, { speed, distance, position }) {\n const L = globalThis.L, keys = new Set();\n // Map button (leaflet-bar look) toggling the walk; the key hint shows beside it while walking.\n const control = new L.Control({ position });\n const container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');\n container.style.cssText = 'display:flex;align-items:center;background:#fff;';\n const button = L.DomUtil.create('button', '', container);\n button.type = 'button';\n button.title = 'Walk';\n button.setAttribute('aria-label', 'Walk');\n button.setAttribute('aria-pressed', 'false');\n button.textContent = '\uD83D\uDEB6';\n button.style.cssText = 'width:30px;height:30px;padding:0;border:0;border-radius:4px;background:#fff;font-size:18px;line-height:30px;cursor:pointer;';\n const hint = L.DomUtil.create('small', '', container);\n hint.style.cssText = 'display:none;padding:0 8px;color:#333;white-space:nowrap;';\n hint.textContent = 'W/S: run \u00B7 A/D: turn \u00B7 drag: look around \u00B7 Esc: exit';\n L.DomEvent.disableClickPropagation(container);\n control.onAdd = () => container;\n let meshes, frame, last, swing = 0, saved, drag;\n // Walker state: position, compass heading (radians, clockwise from north) and stride phase.\n const state = layer.walker = { latlng: null, heading: 0, phase: 0 };\n\n // Feet position in this layer's root space.\n const local = () => {\n const map = layer._map, crs = map.options.crs, origin = crs.project(layer.location), metres = Math.cos(layer.location.lat * Math.PI / 180);\n const p = crs.project(state.latlng), terrain = map._terrain3D?._terrainReady && map._terrain3D;\n const ground = (terrain && terrain._getElevation(state.latlng)) || 0;\n return [(p.x - origin.x) * metres, ground - layer.root.position[1], -(p.y - origin.y) * metres];\n };\n const place = () => {\n const [x, y, z] = local();\n // Model forward is -z; a yaw of -heading turns it to the compass heading (x east, -z north).\n const yaw = -state.heading, cos = Math.cos(yaw), sin = Math.sin(yaw);\n limbs.forEach(([, px, py, sign], i) => {\n const mesh = meshes[i];\n mesh.position[0] = x + px * cos; mesh.position[1] = y + py; mesh.position[2] = z - px * sin;\n mesh.rotation[0] = sign * swing * Math.sin(state.phase);\n mesh.rotation[1] = yaw;\n });\n layer.update();\n };\n\n const step = now => {\n frame = requestAnimationFrame(step);\n const map = layer._map, dt = Math.min(0.1, (now - (last ?? now)) / 1000);\n last = now;\n if (!layer.renderer) return;\n let changed = false;\n if (!meshes) { meshes = limbs.map(([part]) => layer._createMesh(build(parts[part]))); changed = true; }\n let forward = 0, turn = 0;\n for (const key of keys) { forward += moves[key]?.[0] || 0; turn += moves[key]?.[1] || 0; }\n forward = Math.sign(forward); turn = Math.sign(turn);\n if (turn) { state.heading = wrap(state.heading + turn * 2.5 * dt); changed = true; }\n if (forward) {\n const metres = forward * speed * dt, { lat, lng } = state.latlng, { position, scale } = layer.root;\n let east = Math.sin(state.heading) * metres, north = Math.cos(state.heading) * metres;\n const feet = local().map((value, i) => position[i] + scale[i] * value);\n // World x is east, z south; keep 0.3 m from walls and slide along the one in the way.\n const blocked = () => {\n const length = Math.hypot(east, north);\n return length > 1e-6 && hit(layer, feet[0], feet[1], feet[2], east / length, -north / length, length + 0.3);\n };\n const wall = blocked();\n if (wall) {\n const into = east * wall[0] - north * wall[1];\n east -= into * wall[0]; north += into * wall[1];\n if (blocked()) east = north = 0;\n }\n state.latlng = new L.LatLng(lat + north / 111320, lng + east / (111320 * Math.cos(lat * Math.PI / 180)));\n state.phase += Math.hypot(east, north) / 1.6 * Math.PI;\n changed = true;\n }\n if (forward || turn) {\n // The camera (looking along -bearing) swings back behind the walker.\n const bearing = map.getBearing() * Math.PI / 180, behind = wrap(-state.heading - bearing);\n if (Math.abs(behind) > 1e-3) map._setPitchAndBearing(map.getPitch(), (bearing + behind * Math.min(1, dt * 4)) * 180 / Math.PI);\n map.setView(state.latlng, map.getZoom(), { animate: false });\n }\n const target = forward ? 0.9 : 0;\n if (Math.abs(swing - target) > 1e-3) { swing += (target - swing) * Math.min(1, dt * 10); changed = true; }\n if (changed) place();\n };\n\n const onKey = event => {\n // Text fields and sliders keep their keys; buttons and checkboxes (e.g. the Walk button, focused once clicked) don't.\n if (event.target.closest?.('input:not([type=checkbox], [type=radio]), select, textarea, [contenteditable]') ||\n event.ctrlKey || event.altKey || event.metaKey) return;\n if (event.type === 'keydown' && event.code === 'Escape') { stop(); return; }\n if (!moves[event.code]) return;\n event.preventDefault();\n if (event.type === 'keydown') keys.add(event.code); else keys.delete(event.code);\n };\n const onBlur = () => keys.clear();\n // Dragging only turns the camera around the walker: horizontal = bearing, vertical = pitch.\n const onPointer = event => {\n const map = layer._map;\n if (event.type === 'pointerdown') {\n if (event.button !== 0 || event.target.closest('.leaflet-control')) return;\n drag = { x: event.clientX, y: event.clientY };\n map.getContainer().setPointerCapture(event.pointerId);\n } else if (drag && event.type === 'pointermove') {\n map._setPitchAndBearing(Math.max(20, Math.min(85, map.getPitch() - (event.clientY - drag.y) * 0.2)),\n map.getBearing() - (event.clientX - drag.x) * 0.25);\n drag = { x: event.clientX, y: event.clientY };\n } else drag = null;\n };\n const onTerrain = () => { if (meshes) place(); };\n\n const start = () => {\n const map = layer._map;\n if (saved || !map) return;\n state.latlng = map.getCenter();\n // Zoom whose camera distance (1.5 viewport heights, as in scene/render.js) is about `distance` metres behind the walker.\n const pixelsPerMetre = map.getSize().y * 1.5 / distance;\n const zoom = Math.min(map.getMaxZoom(), Math.log2(pixelsPerMetre * 40075016.68557849 * Math.cos(state.latlng.lat * Math.PI / 180) / 256));\n saved = { zoom: map.getZoom(), pitch: map.getPitch(), scrollWheelZoom: map.options.scrollWheelZoom,\n handlers: ['dragging', 'keyboard', 'doubleClickZoom', 'boxZoom'].filter(name => map[name]?.enabled()) };\n for (const name of saved.handlers) map[name].disable();\n // Wheel zoom moves the camera closer or farther, keeping the walker centred.\n map.options.scrollWheelZoom = saved.scrollWheelZoom && 'center';\n state.heading = -map.getBearing() * Math.PI / 180;\n map.setView(state.latlng, zoom, { animate: false });\n map.setPitch(75);\n L.DomEvent.on(document, 'keydown keyup', onKey);\n L.DomEvent.on(window, 'blur', onBlur);\n L.DomEvent.on(map.getContainer(), 'pointerdown pointermove pointerup pointercancel', onPointer);\n map.on('terrainchange', onTerrain);\n button.setAttribute('aria-pressed', 'true');\n button.style.background = '#e4e4e4';\n hint.style.display = '';\n last = undefined;\n frame = requestAnimationFrame(step);\n };\n const stop = () => {\n const map = layer._map;\n cancelAnimationFrame(frame);\n keys.clear(); drag = null;\n L.DomEvent.off(document, 'keydown keyup', onKey);\n L.DomEvent.off(window, 'blur', onBlur);\n for (const mesh of meshes || []) layer._disposeMesh(mesh);\n meshes = null;\n button.setAttribute('aria-pressed', 'false');\n button.style.background = '#fff';\n hint.style.display = 'none';\n if (!map || !saved) return;\n L.DomEvent.off(map.getContainer(), 'pointerdown pointermove pointerup pointercancel', onPointer);\n map.off('terrainchange', onTerrain);\n map.options.scrollWheelZoom = saved.scrollWheelZoom;\n for (const name of saved.handlers) map[name].enable();\n map.setView(state.latlng, saved.zoom, { animate: false });\n map.setPitch(saved.pitch);\n saved = null;\n };\n L.DomEvent.on(button, 'click', () => (saved ? stop() : start()));\n let ready = false;\n layer.on('ready', () => { ready = true; if (layer._map) control.addTo(layer._map); });\n layer.on('add', () => { if (ready) control.addTo(layer._map); });\n layer.on('remove', () => { stop(); control.remove(); });\n}\n\n/**\n * Third-person walk mode, toggled by a map button (and Esc): a pedestrian at the map centre runs with W/S (or \u2191/\u2193) and\n * turns with A/D (or \u2190/\u2192); the camera swings back behind it while it moves. Dragging the map only turns the camera\n * (bearing, pitch); the wheel changes the camera distance.\n * The walker follows the terrain, bridges included, and `layer.walker` exposes `{ latlng, heading, phase }`.\n * Source options: `speed` (m/s, default 6), `distance` (camera distance in metres, default 20), `position` (button corner, default 'topleft').\n * Visible meshes of the other 3D layers (buildings, trees, models, streetlights) are solid; terrain and traffic are not.\n */\nL.Layer.types.walk = L.Layer.types['3d'].extend({\n initialize({ speed = 70, distance = 20, position = 'bottomright', ...options } = {}) {\n L.Layer.types['3d'].prototype.initialize.call(this, options);\n installWalk(this, { speed, distance, position });\n },\n});\n"],
5
- "mappings": "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",
6
- "names": ["CELL", "collider", "horizontalRay", "parts", "limbs", "computeBounds", "traverse", "updateWorldMatrix", "build", "moves", "wrap", "angle", "hit", "layer", "x", "y", "z", "dx", "dz", "reach", "types", "skip", "other", "name", "best", "found", "mesh", "m", "k", "radius", "c", "ox", "oy", "oz", "seen", "ix", "iz", "t", "height", "d", "installWalk", "speed", "distance", "position", "L", "keys", "control", "container", "button", "hint", "meshes", "frame", "last", "swing", "saved", "drag", "state", "local", "map", "crs", "origin", "metres", "terrain", "ground", "place", "yaw", "cos", "sin", "px", "py", "sign", "i", "step", "now", "dt", "changed", "part", "forward", "turn", "key", "lat", "lng", "scale", "east", "north", "feet", "value", "blocked", "length", "wall", "into", "bearing", "behind", "target", "onKey", "event", "stop", "onBlur", "onPointer", "onTerrain", "start", "pixelsPerMetre", "zoom", "ready", "options"]
7
- }
@@ -1,2 +0,0 @@
1
- function c(e,r){const o=e._map,t=()=>{const l=[...o.getContainer().querySelectorAll(".leaflet-control-layers-selector")].find(n=>n.layerId===globalThis.L.Util.stamp(e));return l?.closest("label").after(r),!!l},a=()=>queueMicrotask(()=>o.hasLayer(e)&&t());return o.on("layeradd layerremove",a),e.once("remove",()=>{o.off("layeradd layerremove",a),r.remove()}),t()}export{c as underEntry};
2
- //# sourceMappingURL=control.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/utils/control.js"],
4
- "sourcesContent": ["/**\n * Keeps `element` right under `layer`'s entry in the map's layers control while the layer is on the map.\n * Returns false when no layers control lists the layer.\n */\nexport function underEntry(layer, element) {\n const map = layer._map;\n const place = () => {\n const input = [...map.getContainer().querySelectorAll('.leaflet-control-layers-selector')]\n .find(input => input.layerId === globalThis.L.Util.stamp(layer));\n input?.closest('label').after(element);\n return Boolean(input);\n };\n // Leaflet rebuilds the list after 'layeradd'/'layerremove' (on the layer's own 'add'/'remove'): re-place afterwards.\n const replace = () => queueMicrotask(() => map.hasLayer(layer) && place());\n map.on('layeradd layerremove', replace);\n layer.once('remove', () => { map.off('layeradd layerremove', replace); element.remove(); });\n return place();\n}\n"],
5
- "mappings": "AAIO,SAASA,EAAWC,EAAOC,EAAS,CACzC,MAAMC,EAAMF,EAAM,KACZG,EAAQ,IAAM,CAClB,MAAMC,EAAQ,CAAC,GAAGF,EAAI,aAAa,EAAE,iBAAiB,kCAAkC,CAAC,EACtF,KAAKE,GAASA,EAAM,UAAY,WAAW,EAAE,KAAK,MAAMJ,CAAK,CAAC,EACjE,OAAAI,GAAO,QAAQ,OAAO,EAAE,MAAMH,CAAO,EAC9B,EAAQG,CACjB,EAEMC,EAAU,IAAM,eAAe,IAAMH,EAAI,SAASF,CAAK,GAAKG,EAAM,CAAC,EACzE,OAAAD,EAAI,GAAG,uBAAwBG,CAAO,EACtCL,EAAM,KAAK,SAAU,IAAM,CAAEE,EAAI,IAAI,uBAAwBG,CAAO,EAAGJ,EAAQ,OAAO,CAAG,CAAC,EACnFE,EAAM,CACf",
6
- "names": ["underEntry", "layer", "element", "map", "place", "input", "replace"]
7
- }
@@ -1,2 +0,0 @@
1
- function G(h,o){const u=h.reduce((r,l)=>r+l.length/8,0),e=32;let i=new Float32Array(8);if(u){let r=1/0,l=1/0,g=-1/0,w=-1/0;for(const t of h)for(let n=0;n<t.length;n+=8)r=Math.min(r,t[n]-t[n+3]),g=Math.max(g,t[n]+t[n+3]),l=Math.min(l,t[n+2]-t[n+3]),w=Math.max(w,t[n+2]+t[n+3]);const s=Math.ceil((g-r)/e)+1,a=Math.ceil((w-l)/e)+1,I=t=>{for(const n of h)for(let c=0;c<n.length;c+=8){const f=n[c+3],y=n[c]-r,U=n[c+2]-l;for(let x=Math.floor((U-f)/e);x<=Math.floor((U+f)/e);x++)for(let A=Math.floor((y-f)/e);A<=Math.floor((y+f)/e);A++)t(x*s+A,n,c)}},M=new Uint32Array(s*a),d=new Uint32Array(s*a);I(t=>M[t]++);const E=M.reduce((t,n)=>t+n,0),v=(2+s*a+E*2)*4;if(v*4>o)throw new Error("Streetlight grid exceeds GPU storage limit");i=new Float32Array(v),i.set([r,l,e,s,a,u,0,0]);let F=2+s*a;for(let t=0;t<M.length;t++)M[t]&&(i[(2+t)*4]=d[t]=F,i[(2+t)*4+1]=M[t],F+=M[t]*2);I((t,n,c)=>{for(let f=0,y=d[t]*4;f<8;f++)i[y+f]=n[c+f];d[t]+=2})}return{data:i,count:u}}function P(h,o){const u=new Float32Array(h.length*8);return h.forEach(({position:[e,i,r],radius:l,color:g,flux:w},s)=>{const a=o[3]*e+o[7]*i+o[11]*r+o[15];u.set([(o[0]*e+o[4]*i+o[8]*r+o[12])/a,(o[1]*e+o[5]*i+o[9]*r+o[13])/a,(o[2]*e+o[6]*i+o[10]*r+o[14])/a,l,...g,w/(4*Math.PI)*.03],s*8)}),u}export{G as lightGrid,P as worldLights};
2
- //# sourceMappingURL=lighting.js.map