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
@@ -1,256 +1,2 @@
1
- /**
2
- * HSL inputs are linear-space to preserve the original building styling.
3
- * Numeric/CSS/RGB inputs are already sRGB; CSS alpha is not used for extrusion.
4
- * @param {number|string|Object} value 0xRRGGBB, CSS color, {r,g,b}, or {h,s,l} in 0..1.
5
- * @returns {Object} sRGB {r,g,b} components in 0..1.
6
- */
7
- export function parseColor(value) {
8
- if (value && typeof value === 'object' && 'h' in value) {
9
- const { h, s, l } = value;
10
- const a = s * Math.min(l, 1 - l);
11
- const channel = n => {
12
- const k = (n + h * 12) % 12;
13
- return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1));
14
- };
15
- const toSRGB = value => value <= 0.0031308 ? value * 12.92 : 1.055 * value ** (1 / 2.4) - 0.055;
16
- return { r: toSRGB(channel(0)), g: toSRGB(channel(8)), b: toSRGB(channel(4)) };
17
- }
18
- if (value && typeof value === 'object' && 'r' in value) return value;
19
- if (typeof value === 'number') return {
20
- r: (value >> 16 & 255) / 255, g: (value >> 8 & 255) / 255, b: (value & 255) / 255,
21
- };
22
- if (typeof value !== 'string' || !CSS.supports('color', value)) throw new Error('Invalid 3D color');
23
- const context = document.createElement('canvas').getContext('2d');
24
- context.fillStyle = value;
25
- context.fillRect(0, 0, 1, 1);
26
- const [r, g, b] = context.getImageData(0, 0, 1, 1).data;
27
- return { r: r / 255, g: g / 255, b: b / 255 };
28
- }
29
1
 
30
- /**
31
- * Paints the vertices `[start, end)` of a mesh and marks its color buffer dirty.
32
- * @param {Object} mesh Layer-created mesh with a color attribute.
33
- * @param {number} start Inclusive vertex index, not an offset into the RGB array.
34
- * @param {number} end Exclusive vertex index.
35
- * @param {Object} color sRGB {r,g,b}, typically from parseColor().
36
- */
37
- export function setVertexColor(mesh, start, end, color) {
38
- for (let i = start; i < end; i++) {
39
- mesh.geometry.attributes.color.data.set([color.r, color.g, color.b], i * 3);
40
- }
41
- mesh.geometry.attributes.color.needsUpdate = true;
42
- }
43
2
 
44
- /**
45
- * Triangulates a polygon given as `{x, y}` points.
46
- * Rings omit the repeated closing point; winding is normalized internally.
47
- * Vertex indices remain relative to the original inputs after duplicate/collinear
48
- * cleanup. Hole bridges duplicate endpoints, not source vertices.
49
- * @param {Object[]} contour Outer boundary.
50
- * @param {Object[][]} [holes] Interior boundaries.
51
- *
52
- * @returns {number[][]} Triangles as indices in `[...contour, ...holes.flat()]`.
53
- */
54
- export function triangulate(contour, holes = []) {
55
- const points = [contour, ...holes].flat();
56
- if (points.some(p => !Number.isFinite(p.x) || !Number.isFinite(p.y))) throw new Error('Invalid polygon coordinates');
57
- // Translate near the origin to avoid cancellation with geographic coordinates.
58
- const vertices = points.map((p, index) => ({ x: p.x - contour[0].x, y: p.y - contour[0].y, index }));
59
- const cross = (a, b, c) => (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
60
- const equal = (a, b) => a.x === b.x && a.y === b.y;
61
- // Remove zero-area corners before connecting holes; keep original vertex indices.
62
- const clean = ring => {
63
- let changed = true;
64
- while (changed && ring.length > 3) {
65
- changed = false;
66
- for (let i = 0; i < ring.length; i++) {
67
- const a = ring[(i + ring.length - 1) % ring.length], b = ring[i], c = ring[(i + 1) % ring.length];
68
- if (equal(a, b) || Math.abs(cross(a, b, c)) < 1e-10) {
69
- ring.splice(i, 1); changed = true; break;
70
- }
71
- }
72
- }
73
- if (ring.length < 3) throw new Error('Degenerate polygon ring');
74
- return ring;
75
- };
76
- let offset = 0;
77
- const rings = [contour, ...holes].map((path, index) => {
78
- const ring = clean(vertices.slice(offset, offset += path.length));
79
- if (isClockWise(ring) !== Boolean(index)) ring.reverse();
80
- return ring;
81
- });
82
- const inside = (point, ring) => {
83
- let result = false;
84
- for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
85
- const a = ring[i], b = ring[j];
86
- if ((a.y > point.y) !== (b.y > point.y) &&
87
- point.x < (b.x - a.x) * (point.y - a.y) / (b.y - a.y) + a.x) result = !result;
88
- }
89
- return result;
90
- };
91
- const intersects = (a, b, c, d) => {
92
- if (equal(a, c) || equal(a, d) || equal(b, c) || equal(b, d)) return false;
93
- const abC = cross(a, b, c), abD = cross(a, b, d), cdA = cross(c, d, a), cdB = cross(c, d, b);
94
- const on = (p, q, r) => Math.min(p.x, q.x) <= r.x && r.x <= Math.max(p.x, q.x) &&
95
- Math.min(p.y, q.y) <= r.y && r.y <= Math.max(p.y, q.y);
96
- return abC * abD < 0 && cdA * cdB < 0 ||
97
- abC === 0 && on(a, b, c) || abD === 0 && on(a, b, d) ||
98
- cdA === 0 && on(c, d, a) || cdB === 0 && on(c, d, b);
99
- };
100
- let polygon = rings[0].slice();
101
- // A bridge must stay inside the outer boundary, outside every hole, and cross no edge.
102
- // ponytail: quadratic ear clipping for building footprints; use spatial indexing for large rings.
103
- for (const hole of rings.slice(1).sort((a, b) => Math.min(...a.map(p => p.x)) - Math.min(...b.map(p => p.x)))) {
104
- let bridge, distance = Infinity;
105
- for (let h = 0; h < hole.length; h++) for (let p = 0; p < polygon.length; p++) {
106
- const a = hole[h], b = polygon[p], d = (a.x - b.x) ** 2 + (a.y - b.y) ** 2;
107
- if (d >= distance) continue;
108
- const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
109
- if (!inside(mid, rings[0]) || rings.slice(1).some(r => inside(mid, r))) continue;
110
- if ([polygon, ...rings.slice(1)].some(r => r.some((c, i) => intersects(a, b, c, r[(i + 1) % r.length])))) continue;
111
- bridge = [h, p]; distance = d;
112
- }
113
- if (!bridge) throw new Error('Unable to connect polygon hole');
114
- const [h, p] = bridge;
115
- polygon = [...polygon.slice(0, p + 1), ...hole.slice(h), ...hole.slice(0, h + 1),
116
- polygon[p], ...polygon.slice(p + 1)];
117
- }
118
- // Clip a convex corner only when no other vertex is inside/on its triangle.
119
- const result = [];
120
- while (polygon.length > 3) {
121
- let clipped = false;
122
- for (let i = 0; i < polygon.length; i++) {
123
- const a = polygon[(i + polygon.length - 1) % polygon.length], b = polygon[i], c = polygon[(i + 1) % polygon.length];
124
- if (cross(a, b, c) <= 1e-10) continue;
125
- if (polygon.some(p => !equal(p, a) && !equal(p, b) && !equal(p, c) &&
126
- cross(a, b, p) >= 0 && cross(b, c, p) >= 0 && cross(c, a, p) >= 0)) continue;
127
- result.push([a.index, b.index, c.index]); polygon.splice(i, 1); clipped = true; break;
128
- }
129
- if (!clipped) throw new Error('Unable to triangulate polygon: invalid or self-intersecting rings');
130
- }
131
- if (cross(...polygon) > 1e-10) result.push(polygon.map(p => p.index));
132
- const area = ring => Math.abs(ring.reduce((sum, p, i) => {
133
- const q = ring[(i + 1) % ring.length]; return sum + p.x * q.y - q.x * p.y;
134
- }, 0)) / 2;
135
- // Reject incomplete coverage instead of silently emitting a partial roof.
136
- const expected = area(rings[0]) - rings.slice(1).reduce((sum, ring) => sum + area(ring), 0);
137
- const actual = result.reduce((sum, triangle) => sum + cross(...triangle.map(i => vertices[i])) / 2, 0);
138
- if (expected <= 0 || Math.abs(actual - expected) > Math.max(1e-7, expected * 1e-8)) throw new Error('Polygon triangulation area mismatch');
139
- return result;
140
- }
141
-
142
- /**
143
- * @returns {boolean} Whether the `{x, y}` points are in clockwise order.
144
- */
145
- export function isClockWise(points) {
146
- let area = 0;
147
- for (let i = 0; i < points.length; i++) {
148
- const a = points[i], b = points[(i + 1) % points.length];
149
- area += a.x * b.y - b.x * a.y;
150
- }
151
- return area < 0;
152
- }
153
-
154
- /** Low-poly tree, sharing the source block's buffers, picking and terrain offset. */
155
- export function treeGeometry(point, style, addTriangle) {
156
- const { top, bottom = 0, trunkRadius, crownRadius, crownBottom, crownShape = 'round' } = style;
157
- if (![trunkRadius, crownRadius, crownBottom].every(Number.isFinite) ||
158
- trunkRadius <= 0 || crownRadius < trunkRadius || crownBottom <= bottom || crownBottom >= top ||
159
- !['round', 'cone'].includes(crownShape)) {
160
- throw new Error('Invalid tree dimensions or crown shape');
161
- }
162
- const trunk = parseColor(style.trunkColor ?? 0x72513a);
163
- const crown = parseColor(style.color ?? 0x4f823b);
164
- const ring = radius => Array.from({ length: 8 }, (_, i) => ({
165
- x: point.x + Math.cos(i * Math.PI / 4) * radius,
166
- y: point.y + Math.sin(i * Math.PI / 4) * radius,
167
- ground: point.ground,
168
- }));
169
- const surface = (lowRadius, low, highRadius, high, color) => {
170
- const lower = ring(lowRadius), upper = ring(highRadius);
171
- for (let i = 0; i < 8; i++) {
172
- const next = (i + 1) % 8;
173
- const angle = (i + 0.5) * Math.PI / 4;
174
- const slope = (lowRadius - highRadius) / (high - low);
175
- const length = Math.hypot(1, slope);
176
- const nx = Math.cos(angle) / length, ny = slope / length, nz = -Math.sin(angle) / length;
177
- if (lowRadius) addTriangle(lower[i], low, lower[next], low, upper[next], high, nx, ny, nz, color);
178
- if (highRadius) addTriangle(lower[i], low, upper[next], high, upper[i], high, nx, ny, nz, color);
179
- }
180
- };
181
- surface(trunkRadius, bottom, trunkRadius, crownBottom + (top - crownBottom) * 0.25, trunk);
182
- if (crownShape === 'cone') {
183
- const base = ring(crownRadius);
184
- for (let i = 0; i < 8; i++) addTriangle(point, crownBottom, base[i], crownBottom,
185
- base[(i + 1) % 8], crownBottom, 0, -1, 0, crown);
186
- surface(crownRadius, crownBottom, 0, top, crown);
187
- } else {
188
- const profile = [[0, 0], [0.35, 0.8], [0.6, 1], [0.85, 0.7], [1, 0]];
189
- for (let i = 1; i < profile.length; i++) {
190
- const [low, lr] = profile[i - 1], [high, hr] = profile[i];
191
- surface(lr * crownRadius, crownBottom + low * (top - crownBottom),
192
- hr * crownRadius, crownBottom + high * (top - crownBottom), crown);
193
- }
194
- }
195
- }
196
-
197
- /** Three crossed emitter discs; illumination itself is evaluated on receiving surfaces. */
198
- export function lightGeometry(point, style, addTriangle) {
199
- if (!Number.isFinite(style.lightRadius) || style.lightRadius <= 0) throw new Error('Invalid light radius');
200
- const color = parseColor(style.color);
201
- const quad = (a, b, c, d, height, normal) => {
202
- addTriangle(a, height, b, height, c, height, ...normal, color);
203
- addTriangle(a, height, c, height, d, height, ...normal, color);
204
- };
205
- const r = 0.65;
206
- const emitter = (u, v, axis) => ({
207
- x: point.x + (axis === 2 ? 0 : u * r),
208
- y: point.y + (axis === 1 ? 0 : axis === 2 ? u * r : v * r),
209
- ground: point.ground + (axis === 0 ? 0 : v * r), uv: [u, v],
210
- });
211
- for (let axis = 0; axis < 3; axis++) {
212
- quad(emitter(-1, -1, axis), emitter(1, -1, axis), emitter(1, 1, axis), emitter(-1, 1, axis),
213
- style.top, axis === 0 ? [0, 1, 0] : axis === 1 ? [0, 0, 1] : [1, 0, 0]);
214
- }
215
- }
216
-
217
- /** Schematic support and lamp head; wall-mounted fixtures do not get an invented pole. */
218
- export function lampPostGeometry(point, style, addTriangle) {
219
- const color = parseColor(0x50565a), radius = style.poleRadius;
220
- if (!Number.isFinite(radius) || radius <= 0) throw new Error('Invalid lamp pole radius');
221
- const ring = r => Array.from({ length: 6 }, (_, i) => ({
222
- x: point.x + Math.cos(i * Math.PI / 3) * r,
223
- y: point.y + Math.sin(i * Math.PI / 3) * r, ground: point.ground, uv: [3, 3],
224
- }));
225
- const center = { ...point, uv: [3, 3] };
226
- for (const [r, low, high] of [[radius, 0, style.top], [radius * 2.5, style.top - 0.25, style.top + 0.15]]) {
227
- const points = ring(r);
228
- for (let i = 0; i < 6; i++) {
229
- const a = points[i], b = points[(i + 1) % 6], angle = (i + 0.5) * Math.PI / 3;
230
- const nx = Math.cos(angle), nz = -Math.sin(angle);
231
- addTriangle(a, low, b, low, b, high, nx, 0, nz, color);
232
- addTriangle(a, low, b, high, a, high, nx, 0, nz, color);
233
- addTriangle(center, high, a, high, b, high, 0, 1, 0, color);
234
- addTriangle(center, low, b, low, a, low, 0, -1, 0, color);
235
- }
236
- }
237
- }
238
-
239
- /** Cache local AABB and center for ray picking and transparent mesh sorting. */
240
- export function computeBounds(geometry) {
241
- const min = [Infinity, Infinity, Infinity],
242
- max = [-Infinity, -Infinity, -Infinity],
243
- data = geometry.attributes.position.data;
244
- for (let i = 0; i < data.length; i++) {
245
- min[i % 3] = Math.min(min[i % 3], data[i]);
246
- max[i % 3] = Math.max(max[i % 3], data[i]);
247
- }
248
- const center = min.map((v, i) => (v + max[i]) / 2);
249
- let radius = 0;
250
- for (let i = 0; i < data.length; i += 3) {
251
- radius = Math.max(radius, Math.hypot(
252
- data[i] - center[0], data[i + 1] - center[1], data[i + 2] - center[2]
253
- ));
254
- }
255
- geometry.bounds = { min, max, center, radius };
256
- }
@@ -0,0 +1,10 @@
1
+ import { bridgeElevation } from './bridgeElevation.js';
2
+ import { terrainElevation } from './terrainElevation.js';
3
+
4
+ /** @param {L.LatLng|L.Point} location LatLng, or a pixel point at the terrain zoom. */
5
+
6
+ export function getElevation(backend, location) {
7
+ if (!backend._map || !backend._terrainReady) return null;
8
+ const point = location instanceof L.Point ? location : backend._map.project(location, backend._terrainZoom);
9
+ return bridgeElevation(point, backend._bridges) ?? terrainElevation(point, backend._terrainTiles);
10
+ }
@@ -0,0 +1,9 @@
1
+ import { decodeHeader } from './decodeHeader.js';
2
+ import { read } from './read.js';
3
+
4
+ /** Cache header initialization; failures remain visible to all callers. */
5
+
6
+ export function getHeader(backend) {
7
+ if (backend.options.archive && backend.options.archive !== backend) return backend.options.archive.getHeader();
8
+ return backend._header ||= read(backend, 0, 127).then(decodeHeader);
9
+ }
@@ -0,0 +1,76 @@
1
+ import { decodeDirectory } from './decodeDirectory.js';
2
+ import { decompress } from './decompress.js';
3
+ import { tileId } from './tileId.js';
4
+ import { read } from './read.js';
5
+ import { getHeader } from './getHeader.js';
6
+
7
+ /** Nearest directory entry at/before the Hilbert ID, then follow leaf pointers. */
8
+
9
+ export async function getZxy(backend, z, x, y, signal) {
10
+ if (backend.options.archive && backend.options.archive !== backend && backend.options.archive.getZxy) {
11
+ return backend.options.archive.getZxy(z, x, y, signal);
12
+ }
13
+ const id = tileId(z, x, y);
14
+ signal?.throwIfAborted();
15
+ const header = await getHeader(backend);
16
+ signal?.throwIfAborted();
17
+ if (z < header.minZoom || z > header.maxZoom) {
18
+ return;
19
+ }
20
+ let offset = header.rootDirectoryOffset, length = header.rootDirectoryLength;
21
+ const visited = new Set();
22
+ for (let depth = 0; depth < 4; depth++) {
23
+ if (visited.has(offset)) {
24
+ throw new Error('Cyclic PMTiles directory');
25
+ }
26
+ visited.add(offset);
27
+ const key = `${offset}:${length}`;
28
+ if (!backend._directories.has(key)) {
29
+ if (backend._directories.size >= 32) {
30
+ backend._directories.delete(backend._directories.keys().next().value);
31
+ }
32
+ const pending = read(backend, offset, length)
33
+ .then(data => decompress(data, header.internalCompression))
34
+ .then(decodeDirectory)
35
+ .catch(error => {
36
+ if (backend._directories.get(key) === pending) {
37
+ backend._directories.delete(key);
38
+ }
39
+ throw error;
40
+ });
41
+ backend._directories.set(key, pending);
42
+ }
43
+ const entries = await backend._directories.get(key);
44
+ signal?.throwIfAborted();
45
+ let low = 0, high = entries.length - 1;
46
+ while (low <= high) {
47
+ const mid = (low + high) >> 1;
48
+ if (entries[mid].tileId <= id) {
49
+ low = mid + 1;
50
+ } else {
51
+ high = mid - 1;
52
+ }
53
+ }
54
+ const entry = entries[high];
55
+ if (!entry) {
56
+ return;
57
+ }
58
+ if (entry.runLength) {
59
+ if (id - entry.tileId >= entry.runLength) {
60
+ return;
61
+ }
62
+ if (entry.offset + entry.length > header.tileDataLength) {
63
+ throw new Error('PMTiles tile outside data section');
64
+ }
65
+ const data = await decompress(await read(backend, header.tileDataOffset + entry.offset, entry.length, signal), header.tileCompression);
66
+ signal?.throwIfAborted();
67
+ return { data };
68
+ }
69
+ if (entry.offset + entry.length > header.leafDirectoryLength) {
70
+ throw new Error('PMTiles directory outside leaf section');
71
+ }
72
+ offset = header.leafDirectoryOffset + entry.offset;
73
+ length = entry.length;
74
+ }
75
+ throw new Error('PMTiles directory depth exceeds four levels');
76
+ }
@@ -0,0 +1 @@
1
+ export const glass = [0.12, 0.15, 0.18], tyre = [0.05, 0.05, 0.05];
@@ -0,0 +1 @@
1
+ export const headlight = [1.9, 1.85, 1.7];
@@ -0,0 +1,41 @@
1
+ import { CELL } from './CELL.js';
2
+ import { collider } from './collider.js';
3
+ import { computeBounds } from './computeBounds.js';
4
+ import { horizontalRay } from './horizontalRay.js';
5
+ import { traverse } from './traverse.js';
6
+ import { updateWorldMatrix } from './updateWorldMatrix.js';
7
+
8
+ // Horizontal normal of the nearest wall faced within `reach` metres of the feet at world (x, y, z), walking along
9
+ // the unit (dx, dz); knee and chest rays, so arches and tree crowns above the head let the walker through.
10
+ // ponytail: traffic vehicles and boats move on the GPU and are not obstacles.
11
+
12
+ export function hit(layer, x, y, z, dx, dz, reach) {
13
+ const skip = other => other === layer || ['terrain', 'traffic'].includes(other._type);
14
+ updateWorldMatrix(layer.scene);
15
+ let best = reach, found = null;
16
+ for (const other of layer._shared._layers) {
17
+ if (skip(other)) continue;
18
+ traverse(other.root, mesh => {
19
+ if (!mesh.visible) return true;
20
+ if (!mesh.geometry?.attributes?.position?.data || mesh.program?.depthTest === false) return;
21
+ if (!mesh.geometry.bounds) computeBounds(mesh.geometry);
22
+ const m = mesh.worldMatrix, { center: k, radius } = mesh.geometry.bounds;
23
+ 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) >
24
+ radius * Math.hypot(m[0], m[1], m[2]) + reach) return;
25
+ 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];
26
+ const seen = new Set();
27
+ for (let ix = Math.floor(Math.min(ox, ox + dx * reach) / CELL); ix <= Math.floor(Math.max(ox, ox + dx * reach) / CELL); ix++)
28
+ for (let iz = Math.floor(Math.min(oz, oz + dz * reach) / CELL); iz <= Math.floor(Math.max(oz, oz + dz * reach) / CELL); iz++)
29
+ for (const t of c.cells.get(ix + ',' + iz) || []) {
30
+ // Walls are one-way: walking out of a building (e.g. starting inside one) is allowed.
31
+ if (seen.has(t) || dx * c.nrm[t * 2] + dz * c.nrm[t * 2 + 1] >= 0) continue;
32
+ seen.add(t);
33
+ for (const height of [0.4, 1.5]) {
34
+ const d = horizontalRay(c.tri, t, ox, oy + height, oz, dx, dz);
35
+ if (d >= 0 && d < best) { best = d; found = [c.nrm[t * 2], c.nrm[t * 2 + 1]]; }
36
+ }
37
+ }
38
+ });
39
+ }
40
+ return found;
41
+ }
@@ -0,0 +1,16 @@
1
+
2
+ export function horizontalPosition(d, lat, lng, ascension, declination) {
3
+ const rad = Math.PI / 180;
4
+ const hourAngle = (280.16 + 360.9856235 * d + lng) * rad - ascension;
5
+ const latitude = lat * rad;
6
+ const altitude = Math.asin(Math.sin(latitude) * Math.sin(declination) +
7
+ Math.cos(latitude) * Math.cos(declination) * Math.cos(hourAngle));
8
+ const southAzimuth = Math.atan2(Math.sin(hourAngle),
9
+ Math.cos(hourAngle) * Math.sin(latitude) - Math.tan(declination) * Math.cos(latitude));
10
+ const azimuth = (southAzimuth / rad + 180 + 360) % 360;
11
+ return {
12
+ altitude: altitude / rad, azimuth,
13
+ direction: [Math.sin(azimuth * rad) * Math.cos(altitude), Math.sin(altitude),
14
+ -Math.cos(azimuth * rad) * Math.cos(altitude)]
15
+ };
16
+ }
@@ -0,0 +1,12 @@
1
+ // Möller-Trumbore for the horizontal ray (ox, oy, oz) + d·(dx, 0, dz) against triangle t; returns d or -1.
2
+ export function horizontalRay(v, t, ox, oy, oz, dx, dz) {
3
+ const i = t * 9, ex = v[i + 3] - v[i], ey = v[i + 4] - v[i + 1], ez = v[i + 5] - v[i + 2];
4
+ const fx = v[i + 6] - v[i], fy = v[i + 7] - v[i + 1], fz = v[i + 8] - v[i + 2];
5
+ const px = -dz * fy, py = dz * fx - dx * fz, pz = dx * fy, det = ex * px + ey * py + ez * pz;
6
+ if (Math.abs(det) < 1e-9) return -1;
7
+ const tx = ox - v[i], ty = oy - v[i + 1], tz = oz - v[i + 2], u = (tx * px + ty * py + tz * pz) / det;
8
+ if (u < 0 || u > 1) return -1;
9
+ const qx = ty * ez - tz * ey, qy = tz * ex - tx * ez, qz = tx * ey - ty * ex, w = (dx * qx + dz * qz) / det;
10
+ if (w < 0 || u + w > 1) return -1;
11
+ return (fx * qx + fy * qy + fz * qz) / det;
12
+ }
@@ -0,0 +1 @@
1
+ export const hull = [[-5.5, 30], [5.5, 30], [5.5, -20], [4, -26], [1.5, -30], [-1.5, -30], [-4, -26], [-5.5, -20]];
@@ -0,0 +1,9 @@
1
+ import { onAddSun } from './onAddSun.js';
2
+ import { onRemoveSun } from './onRemoveSun.js';
3
+
4
+ // Sun/moon clock control and sky colours; the control is created on first add (`layer.control`).
5
+ export function initSunlight(layer, options) {
6
+ L.Util.setOptions(layer, options);
7
+ layer.onAdd = map => onAddSun(layer, map);
8
+ layer.onRemove = () => onRemoveSun(layer);
9
+ }
@@ -0,0 +1,19 @@
1
+ import { onTerrainRemove } from './onTerrainRemove.js';
2
+ import { onTerrainAdd } from './onTerrainAdd.js';
3
+
4
+ /**
5
+ * Renders IGN Float32 DEM tiles and PMTiles raster basemaps in the shared WebGPU scene.
6
+ * Source options: `url` (single-zoom Float32 PMTiles DEM); `bridges` (optional GeoJSON deck polygons with Z, see _addBridges).
7
+ */
8
+ export function initTerrain(layer, options) {
9
+ const terrainSource = options.url;
10
+ const layerOptions = { ...options };
11
+ delete layerOptions.url;
12
+ layer._init3D(layerOptions);
13
+ layer.terrainSource = terrainSource;
14
+ layer._terrainTiles = new Map();
15
+ layer._rasterTiles = new Map();
16
+ layer._terrainReady = false;
17
+ layer.onAdd = map => onTerrainAdd(layer, map);
18
+ layer.onRemove = map => onTerrainRemove(layer, map);
19
+ }
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Vehicles moving along GeoJSON lanes; a compute pass places them on the GPU every frame.
3
+ * Source options:
4
+ * - `url`: GeoJSON (Multi)LineStrings, or a JS module whose default export `(time, layer, signal)` returns them (time-dependent data);
5
+ * - `vehicle`: 'car' (default) or 'boat'; `side`: offset right of the lane centreline in metres (vehicle default);
6
+ * - `speed`: m/s of `flow` lanes; `outline`: draw the lanes.
7
+ * Lane properties: `flow` (vehicles/h) or `timetable` (see scheduledTrips.js), optional fixed `elevation`
8
+ * 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.
9
+ * The 'sunlight' layer on the same map drives the time; without one, vehicles run live.
10
+ */
11
+ import { build } from './build.js';
12
+ import { tooltip } from './tooltip.js';
13
+ import { speed } from './speed.js';
14
+ import { vehicles } from './vehicles.js';
15
+ import {
16
+ addTraffic,
17
+ placeTraffic,
18
+ removeTraffic,
19
+ readyTraffic,
20
+ tickTraffic,
21
+ updateTraffic,
22
+ updateTrafficTerrain,
23
+ } from './traffic.js';
24
+
25
+ export function initTraffic(layer, { url, vehicle = 'car', side, outline, speed: velocity = speed, ...options } = {}) {
26
+ const { model, lights, side: defaultSide } = vehicles[vehicle];
27
+ side ??= defaultSide;
28
+ layer._init3D({
29
+ tooltip,
30
+ nightLight: Boolean(lights),
31
+ ...options,
32
+ });
33
+ const status = L.DomUtil.create('small', 'traffic-status');
34
+ status.style.cssText = 'display:block;max-width:200px;margin:0 0 4px 20px;color:#555;';
35
+ const template = build(model(0)), stride = template.position.length, vertices = stride / 3;
36
+ const params = new ArrayBuffer(16), paramFloats = new Float32Array(params), paramInts = new Uint32Array(params);
37
+ const state = {
38
+ layer, url, model, lights, side, outline, velocity, status, template, stride, vertices,
39
+ params, paramFloats, paramInts,
40
+ ready: false, frame: undefined, request: undefined, lanes: [], tripsKey: undefined,
41
+ mesh: undefined, route: undefined, litAt: -Infinity,
42
+ trips: [], rebasedAt: 0, nextCheck: -Infinity, elapsed: 0, gpu: null,
43
+ lanesDirty: true, stale: false, loaded: undefined, file: undefined,
44
+ };
45
+ // Lane points are [x, z, ground, cumulative length]. Mirrors along() and place().
46
+ const shader = `
47
+ struct Params { seconds: f32, side: f32, vertices: u32, total: u32 }
48
+ struct Vehicle { start: u32, count: u32, base: f32, speed: f32 }
49
+ @group(0) @binding(0) var<uniform> params: Params;
50
+ @group(0) @binding(1) var<storage, read> model: array<f32>;
51
+ @group(0) @binding(2) var<storage, read> points: array<vec4f>;
52
+ @group(0) @binding(3) var<storage, read> vehicles: array<Vehicle>;
53
+ @group(0) @binding(4) var<storage, read_write> position: array<f32>;
54
+ @group(0) @binding(5) var<storage, read_write> normal: array<f32>;
55
+ @compute @workgroup_size(64)
56
+ fn main(@builtin(global_invocation_id) id: vec3u) {
57
+ let v = id.x;
58
+ if (v >= params.total) { return; }
59
+ let vehicle = vehicles[v / params.vertices];
60
+ let last = vehicle.start + vehicle.count - 1u;
61
+ let length = points[last].w;
62
+ var s = vehicle.base + params.seconds * vehicle.speed;
63
+ s -= length * floor(s / length);
64
+ var i = vehicle.start + 1u;
65
+ while (i < last && points[i].w < s) { i++; }
66
+ let a = points[i - 1u];
67
+ let b = points[i];
68
+ let d = select(b.w - a.w, 1.0, b.w == a.w);
69
+ let t = (s - a.w) / d;
70
+ let dx = (b.x - a.x) / d;
71
+ let dz = (b.y - a.y) / d;
72
+ let cx = a.x + (b.x - a.x) * t - dz * params.side;
73
+ let cz = a.y + (b.y - a.y) * t + dx * params.side;
74
+ let y = a.z + (b.z - a.z) * t;
75
+ let k = (v % params.vertices) * 3u;
76
+ let n = params.vertices * 3u + k;
77
+ let o = v * 3u;
78
+ position[o] = cx - model[k] * dz - model[k + 2u] * dx;
79
+ position[o + 1u] = y + model[k + 1u];
80
+ position[o + 2u] = cz + model[k] * dx - model[k + 2u] * dz;
81
+ normal[o] = -model[n] * dz - model[n + 2u] * dx;
82
+ normal[o + 1u] = model[n + 1u];
83
+ normal[o + 2u] = model[n] * dx - model[n + 2u] * dz;
84
+ }`;
85
+ state.shader = shader;
86
+ state.tick = tickTraffic.bind(null, state);
87
+ state.update = updateTraffic.bind(null, state);
88
+ state.terrain = updateTrafficTerrain.bind(null, state);
89
+ layer._beforeRaycast = placeTraffic.bind(null, state);
90
+ layer.on('ready', readyTraffic.bind(null, state));
91
+ layer.on('add', addTraffic.bind(null, state));
92
+ layer.on('remove', removeTraffic.bind(null, state));
93
+ }
@@ -0,0 +1,72 @@
1
+ import {
2
+ controlOnAdd, onBlur, onKey, onLayerAdd, onLayerRemove, onPointer, onReady, onTerrain, start, step, stop, toggle
3
+ } from './walk.js';
4
+
5
+ /**
6
+ * Third-person walk mode, toggled by a map button (and Esc): a pedestrian at the map centre runs with W/S (or ↑/↓) and
7
+ * turns with A/D (or ←/→); the camera swings back behind it while it moves. Dragging the map only turns the camera
8
+ * (bearing, pitch); the wheel changes the camera distance.
9
+ * The walker follows the terrain, bridges included, and `layer.walker` exposes `{ latlng, heading, phase }`.
10
+ * Source options: `speed` (m/s, default 6), `distance` (camera distance in metres, default 20), `position` (button corner, default 'topleft').
11
+ * Visible meshes of the other 3D layers (buildings, trees, models, streetlights) are solid; terrain and traffic are not.
12
+ */
13
+ export function initWalk(layer, {
14
+ speed = 70,
15
+ distance = 20,
16
+ position = 'bottomright',
17
+ ...options
18
+ } = {}) {
19
+ layer._init3D(options);
20
+ const keys = new Set();
21
+ const control = new L.Control({ position });
22
+ const container = L.DomUtil.create('div', 'leaflet-bar leaflet-control');
23
+ container.style.cssText = 'display:flex;align-items:center;background:#fff;';
24
+ const button = L.DomUtil.create('button', '', container);
25
+ button.type = 'button';
26
+ button.title = 'Walk';
27
+ button.setAttribute('aria-label', 'Walk');
28
+ button.setAttribute('aria-pressed', 'false');
29
+ button.textContent = '🚶';
30
+ button.style.cssText = 'width:30px;height:30px;padding:0;border:0;border-radius:4px;background:#fff;font-size:18px;line-height:30px;cursor:pointer;';
31
+ const hint = L.DomUtil.create('small', '', container);
32
+ hint.style.cssText = 'display:none;padding:0 8px;color:#333;white-space:nowrap;';
33
+ hint.textContent = 'W/S: run · A/D: turn · drag: look around · Esc: exit';
34
+ L.DomEvent.disableClickPropagation(container);
35
+
36
+ const context = {
37
+ layer,
38
+ speed,
39
+ distance,
40
+ keys,
41
+ control,
42
+ container,
43
+ button,
44
+ hint,
45
+ meshes: null,
46
+ frame: null,
47
+ last: undefined,
48
+ swing: 0,
49
+ saved: null,
50
+ drag: null,
51
+ ready: false,
52
+ state: layer.walker = { latlng: null, heading: 0, phase: 0 }
53
+ }
54
+ context.step = step.bind(context);
55
+ context.onKey = onKey.bind(context);
56
+ context.onBlur = onBlur.bind(context);
57
+ context.onPointer = onPointer.bind(context);
58
+ context.onTerrain = onTerrain.bind(context);
59
+ context.start = start.bind(context);
60
+ context.stop = stop.bind(context);
61
+ context.toggle = toggle.bind(context);
62
+ context.controlOnAdd = controlOnAdd.bind(context);
63
+ context.onReady = onReady.bind(context);
64
+ context.onLayerAdd = onLayerAdd.bind(context);
65
+ context.onLayerRemove = onLayerRemove.bind(context);
66
+
67
+ control.onAdd = context.controlOnAdd;
68
+ L.DomEvent.on(button, 'click', context.toggle);
69
+ layer.on('ready', context.onReady);
70
+ layer.on('add', context.onLayerAdd);
71
+ layer.on('remove', context.onLayerRemove);
72
+ };