@ifc-lite/viewer 1.17.3 → 1.17.4

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 (495) hide show
  1. package/.turbo/turbo-build.log +39 -30
  2. package/.turbo/turbo-typecheck.log +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/DESKTOP_CONTRACT_VERSION +1 -0
  5. package/dist/assets/arrow-CZ5kQ26f.js +20 -0
  6. package/dist/assets/basketViewActivator-BmnNtVfZ.js +1 -0
  7. package/dist/assets/{bcf-D5-QWGO9.js → bcf-DOG9_WPX.js} +1 -1
  8. package/dist/assets/{browser-CKs-FY1P.js → browser-C5TFR7sH.js} +1 -1
  9. package/dist/assets/cesium-ADbP7waU.css +1 -0
  10. package/dist/assets/cesium-DUOzBlqv.js +17817 -0
  11. package/dist/assets/{exporters-C_6J153K.js → exporters-ChAtBmlj.js} +2225 -1754
  12. package/dist/assets/geometry.worker-BQ0rzNo-.js +1 -0
  13. package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
  14. package/dist/assets/{index-jhBr1wbn.js → index-Co8E2-FE.js} +28959 -24612
  15. package/dist/assets/index-DckuDqlv.css +1 -0
  16. package/dist/assets/{maplibre-gl-BpvwNKKy.js → maplibre-gl-CGLcoNXc.js} +1 -1
  17. package/dist/assets/native-bridge-BRvbckFQ.js +429 -0
  18. package/dist/assets/{sandbox-B79eavQ3.js → sandbox-DZiNLNMk.js} +5 -5
  19. package/dist/assets/{server-client-D3bUPJJc.js → server-client-BV8zHZ7Y.js} +4 -4
  20. package/dist/assets/tauri-core-stub-D8Fa-u43.js +1 -0
  21. package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +1 -0
  22. package/dist/assets/tauri-fs-stub-BdeRC7aK.js +1 -0
  23. package/dist/assets/wasm-bridge-g01g7T9b.js +1 -0
  24. package/dist/assets/{zip-B-jFFAGa.js → zip-DBEtpeu6.js} +3 -3
  25. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json +1 -0
  26. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json +1 -0
  27. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json +1 -0
  28. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json +1 -0
  29. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json +1 -0
  30. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json +1 -0
  31. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json +1 -0
  32. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json +1 -0
  33. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json +1 -0
  34. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json +1 -0
  35. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json +1 -0
  36. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json +1 -0
  37. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json +1 -0
  38. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json +1 -0
  39. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json +1 -0
  40. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json +1 -0
  41. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json +1 -0
  42. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json +1 -0
  43. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json +1 -0
  44. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json +1 -0
  45. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json +1 -0
  46. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json +1 -0
  47. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json +1 -0
  48. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json +1 -0
  49. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json +1 -0
  50. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json +1 -0
  51. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json +1 -0
  52. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json +1 -0
  53. package/dist/cesium/Assets/Images/bing_maps_credit.png +0 -0
  54. package/dist/cesium/Assets/Images/cesium_credit.png +0 -0
  55. package/dist/cesium/Assets/Images/google_earth_credit.png +0 -0
  56. package/dist/cesium/Assets/Images/ion-credit.png +0 -0
  57. package/dist/cesium/Assets/Textures/LensFlare/DirtMask.jpg +0 -0
  58. package/dist/cesium/Assets/Textures/LensFlare/StarBurst.jpg +0 -0
  59. package/dist/cesium/Assets/Textures/NaturalEarthII/0/0/0.jpg +0 -0
  60. package/dist/cesium/Assets/Textures/NaturalEarthII/0/1/0.jpg +0 -0
  61. package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/0.jpg +0 -0
  62. package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/1.jpg +0 -0
  63. package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/0.jpg +0 -0
  64. package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/1.jpg +0 -0
  65. package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/0.jpg +0 -0
  66. package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/1.jpg +0 -0
  67. package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/0.jpg +0 -0
  68. package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/1.jpg +0 -0
  69. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/0.jpg +0 -0
  70. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/1.jpg +0 -0
  71. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/2.jpg +0 -0
  72. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/3.jpg +0 -0
  73. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/0.jpg +0 -0
  74. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/1.jpg +0 -0
  75. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/2.jpg +0 -0
  76. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/3.jpg +0 -0
  77. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/0.jpg +0 -0
  78. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/1.jpg +0 -0
  79. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/2.jpg +0 -0
  80. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/3.jpg +0 -0
  81. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/0.jpg +0 -0
  82. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/1.jpg +0 -0
  83. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/2.jpg +0 -0
  84. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/3.jpg +0 -0
  85. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/0.jpg +0 -0
  86. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/1.jpg +0 -0
  87. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/2.jpg +0 -0
  88. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/3.jpg +0 -0
  89. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/0.jpg +0 -0
  90. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/1.jpg +0 -0
  91. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/2.jpg +0 -0
  92. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/3.jpg +0 -0
  93. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/0.jpg +0 -0
  94. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/1.jpg +0 -0
  95. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/2.jpg +0 -0
  96. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/3.jpg +0 -0
  97. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/0.jpg +0 -0
  98. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/1.jpg +0 -0
  99. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/2.jpg +0 -0
  100. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/3.jpg +0 -0
  101. package/dist/cesium/Assets/Textures/NaturalEarthII/tilemapresource.xml +14 -0
  102. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg +0 -0
  103. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg +0 -0
  104. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg +0 -0
  105. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg +0 -0
  106. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg +0 -0
  107. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg +0 -0
  108. package/dist/cesium/Assets/Textures/maki/airfield.png +0 -0
  109. package/dist/cesium/Assets/Textures/maki/airport.png +0 -0
  110. package/dist/cesium/Assets/Textures/maki/alcohol-shop.png +0 -0
  111. package/dist/cesium/Assets/Textures/maki/america-football.png +0 -0
  112. package/dist/cesium/Assets/Textures/maki/art-gallery.png +0 -0
  113. package/dist/cesium/Assets/Textures/maki/bakery.png +0 -0
  114. package/dist/cesium/Assets/Textures/maki/bank.png +0 -0
  115. package/dist/cesium/Assets/Textures/maki/bar.png +0 -0
  116. package/dist/cesium/Assets/Textures/maki/baseball.png +0 -0
  117. package/dist/cesium/Assets/Textures/maki/basketball.png +0 -0
  118. package/dist/cesium/Assets/Textures/maki/beer.png +0 -0
  119. package/dist/cesium/Assets/Textures/maki/bicycle.png +0 -0
  120. package/dist/cesium/Assets/Textures/maki/building.png +0 -0
  121. package/dist/cesium/Assets/Textures/maki/bus.png +0 -0
  122. package/dist/cesium/Assets/Textures/maki/cafe.png +0 -0
  123. package/dist/cesium/Assets/Textures/maki/camera.png +0 -0
  124. package/dist/cesium/Assets/Textures/maki/campsite.png +0 -0
  125. package/dist/cesium/Assets/Textures/maki/car.png +0 -0
  126. package/dist/cesium/Assets/Textures/maki/cemetery.png +0 -0
  127. package/dist/cesium/Assets/Textures/maki/cesium.png +0 -0
  128. package/dist/cesium/Assets/Textures/maki/chemist.png +0 -0
  129. package/dist/cesium/Assets/Textures/maki/cinema.png +0 -0
  130. package/dist/cesium/Assets/Textures/maki/circle-stroked.png +0 -0
  131. package/dist/cesium/Assets/Textures/maki/circle.png +0 -0
  132. package/dist/cesium/Assets/Textures/maki/city.png +0 -0
  133. package/dist/cesium/Assets/Textures/maki/clothing-store.png +0 -0
  134. package/dist/cesium/Assets/Textures/maki/college.png +0 -0
  135. package/dist/cesium/Assets/Textures/maki/commercial.png +0 -0
  136. package/dist/cesium/Assets/Textures/maki/cricket.png +0 -0
  137. package/dist/cesium/Assets/Textures/maki/cross.png +0 -0
  138. package/dist/cesium/Assets/Textures/maki/dam.png +0 -0
  139. package/dist/cesium/Assets/Textures/maki/danger.png +0 -0
  140. package/dist/cesium/Assets/Textures/maki/disability.png +0 -0
  141. package/dist/cesium/Assets/Textures/maki/dog-park.png +0 -0
  142. package/dist/cesium/Assets/Textures/maki/embassy.png +0 -0
  143. package/dist/cesium/Assets/Textures/maki/emergency-telephone.png +0 -0
  144. package/dist/cesium/Assets/Textures/maki/entrance.png +0 -0
  145. package/dist/cesium/Assets/Textures/maki/farm.png +0 -0
  146. package/dist/cesium/Assets/Textures/maki/fast-food.png +0 -0
  147. package/dist/cesium/Assets/Textures/maki/ferry.png +0 -0
  148. package/dist/cesium/Assets/Textures/maki/fire-station.png +0 -0
  149. package/dist/cesium/Assets/Textures/maki/fuel.png +0 -0
  150. package/dist/cesium/Assets/Textures/maki/garden.png +0 -0
  151. package/dist/cesium/Assets/Textures/maki/gift.png +0 -0
  152. package/dist/cesium/Assets/Textures/maki/golf.png +0 -0
  153. package/dist/cesium/Assets/Textures/maki/grocery.png +0 -0
  154. package/dist/cesium/Assets/Textures/maki/hairdresser.png +0 -0
  155. package/dist/cesium/Assets/Textures/maki/harbor.png +0 -0
  156. package/dist/cesium/Assets/Textures/maki/heart.png +0 -0
  157. package/dist/cesium/Assets/Textures/maki/heliport.png +0 -0
  158. package/dist/cesium/Assets/Textures/maki/hospital.png +0 -0
  159. package/dist/cesium/Assets/Textures/maki/ice-cream.png +0 -0
  160. package/dist/cesium/Assets/Textures/maki/industrial.png +0 -0
  161. package/dist/cesium/Assets/Textures/maki/land-use.png +0 -0
  162. package/dist/cesium/Assets/Textures/maki/laundry.png +0 -0
  163. package/dist/cesium/Assets/Textures/maki/library.png +0 -0
  164. package/dist/cesium/Assets/Textures/maki/lighthouse.png +0 -0
  165. package/dist/cesium/Assets/Textures/maki/lodging.png +0 -0
  166. package/dist/cesium/Assets/Textures/maki/logging.png +0 -0
  167. package/dist/cesium/Assets/Textures/maki/london-underground.png +0 -0
  168. package/dist/cesium/Assets/Textures/maki/marker-stroked.png +0 -0
  169. package/dist/cesium/Assets/Textures/maki/marker.png +0 -0
  170. package/dist/cesium/Assets/Textures/maki/minefield.png +0 -0
  171. package/dist/cesium/Assets/Textures/maki/mobilephone.png +0 -0
  172. package/dist/cesium/Assets/Textures/maki/monument.png +0 -0
  173. package/dist/cesium/Assets/Textures/maki/museum.png +0 -0
  174. package/dist/cesium/Assets/Textures/maki/music.png +0 -0
  175. package/dist/cesium/Assets/Textures/maki/oil-well.png +0 -0
  176. package/dist/cesium/Assets/Textures/maki/park.png +0 -0
  177. package/dist/cesium/Assets/Textures/maki/park2.png +0 -0
  178. package/dist/cesium/Assets/Textures/maki/parking-garage.png +0 -0
  179. package/dist/cesium/Assets/Textures/maki/parking.png +0 -0
  180. package/dist/cesium/Assets/Textures/maki/pharmacy.png +0 -0
  181. package/dist/cesium/Assets/Textures/maki/pitch.png +0 -0
  182. package/dist/cesium/Assets/Textures/maki/place-of-worship.png +0 -0
  183. package/dist/cesium/Assets/Textures/maki/playground.png +0 -0
  184. package/dist/cesium/Assets/Textures/maki/police.png +0 -0
  185. package/dist/cesium/Assets/Textures/maki/polling-place.png +0 -0
  186. package/dist/cesium/Assets/Textures/maki/post.png +0 -0
  187. package/dist/cesium/Assets/Textures/maki/prison.png +0 -0
  188. package/dist/cesium/Assets/Textures/maki/rail-above.png +0 -0
  189. package/dist/cesium/Assets/Textures/maki/rail-light.png +0 -0
  190. package/dist/cesium/Assets/Textures/maki/rail-metro.png +0 -0
  191. package/dist/cesium/Assets/Textures/maki/rail-underground.png +0 -0
  192. package/dist/cesium/Assets/Textures/maki/rail.png +0 -0
  193. package/dist/cesium/Assets/Textures/maki/religious-christian.png +0 -0
  194. package/dist/cesium/Assets/Textures/maki/religious-jewish.png +0 -0
  195. package/dist/cesium/Assets/Textures/maki/religious-muslim.png +0 -0
  196. package/dist/cesium/Assets/Textures/maki/restaurant.png +0 -0
  197. package/dist/cesium/Assets/Textures/maki/roadblock.png +0 -0
  198. package/dist/cesium/Assets/Textures/maki/rocket.png +0 -0
  199. package/dist/cesium/Assets/Textures/maki/school.png +0 -0
  200. package/dist/cesium/Assets/Textures/maki/scooter.png +0 -0
  201. package/dist/cesium/Assets/Textures/maki/shop.png +0 -0
  202. package/dist/cesium/Assets/Textures/maki/skiing.png +0 -0
  203. package/dist/cesium/Assets/Textures/maki/slaughterhouse.png +0 -0
  204. package/dist/cesium/Assets/Textures/maki/soccer.png +0 -0
  205. package/dist/cesium/Assets/Textures/maki/square-stroked.png +0 -0
  206. package/dist/cesium/Assets/Textures/maki/square.png +0 -0
  207. package/dist/cesium/Assets/Textures/maki/star-stroked.png +0 -0
  208. package/dist/cesium/Assets/Textures/maki/star.png +0 -0
  209. package/dist/cesium/Assets/Textures/maki/suitcase.png +0 -0
  210. package/dist/cesium/Assets/Textures/maki/swimming.png +0 -0
  211. package/dist/cesium/Assets/Textures/maki/telephone.png +0 -0
  212. package/dist/cesium/Assets/Textures/maki/tennis.png +0 -0
  213. package/dist/cesium/Assets/Textures/maki/theatre.png +0 -0
  214. package/dist/cesium/Assets/Textures/maki/toilets.png +0 -0
  215. package/dist/cesium/Assets/Textures/maki/town-hall.png +0 -0
  216. package/dist/cesium/Assets/Textures/maki/town.png +0 -0
  217. package/dist/cesium/Assets/Textures/maki/triangle-stroked.png +0 -0
  218. package/dist/cesium/Assets/Textures/maki/triangle.png +0 -0
  219. package/dist/cesium/Assets/Textures/maki/village.png +0 -0
  220. package/dist/cesium/Assets/Textures/maki/warehouse.png +0 -0
  221. package/dist/cesium/Assets/Textures/maki/waste-basket.png +0 -0
  222. package/dist/cesium/Assets/Textures/maki/water.png +0 -0
  223. package/dist/cesium/Assets/Textures/maki/wetland.png +0 -0
  224. package/dist/cesium/Assets/Textures/maki/zoo.png +0 -0
  225. package/dist/cesium/Assets/Textures/moonSmall.jpg +0 -0
  226. package/dist/cesium/Assets/Textures/pin.svg +1 -0
  227. package/dist/cesium/Assets/Textures/waterNormals.jpg +0 -0
  228. package/dist/cesium/Assets/Textures/waterNormalsSmall.jpg +0 -0
  229. package/dist/cesium/Assets/approximateTerrainHeights.json +1 -0
  230. package/dist/cesium/ThirdParty/Workers/package.json +1 -0
  231. package/dist/cesium/ThirdParty/Workers/zip-web-worker.js +1 -0
  232. package/dist/cesium/ThirdParty/basis_transcoder.wasm +0 -0
  233. package/dist/cesium/ThirdParty/draco_decoder.wasm +0 -0
  234. package/dist/cesium/ThirdParty/google-earth-dbroot-parser.js +1 -0
  235. package/dist/cesium/ThirdParty/wasm_splats_bg.wasm +0 -0
  236. package/dist/cesium/ThirdParty/zip-module.wasm +0 -0
  237. package/dist/cesium/Widgets/Animation/Animation.css +127 -0
  238. package/dist/cesium/Widgets/Animation/lighter.css +70 -0
  239. package/dist/cesium/Widgets/BaseLayerPicker/BaseLayerPicker.css +108 -0
  240. package/dist/cesium/Widgets/BaseLayerPicker/lighter.css +22 -0
  241. package/dist/cesium/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.css +102 -0
  242. package/dist/cesium/Widgets/CesiumInspector/CesiumInspector.css +113 -0
  243. package/dist/cesium/Widgets/CesiumWidget/CesiumWidget.css +119 -0
  244. package/dist/cesium/Widgets/CesiumWidget/lighter.css +14 -0
  245. package/dist/cesium/Widgets/FullscreenButton/FullscreenButton.css +8 -0
  246. package/dist/cesium/Widgets/Geocoder/Geocoder.css +70 -0
  247. package/dist/cesium/Widgets/Geocoder/lighter.css +17 -0
  248. package/dist/cesium/Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorer.css +27 -0
  249. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldHillshade.png +0 -0
  250. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldImagery.png +0 -0
  251. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldOcean.png +0 -0
  252. package/dist/cesium/Widgets/Images/ImageryProviders/azureAerial.png +0 -0
  253. package/dist/cesium/Widgets/Images/ImageryProviders/azureRoads.png +0 -0
  254. package/dist/cesium/Widgets/Images/ImageryProviders/bingAerial.png +0 -0
  255. package/dist/cesium/Widgets/Images/ImageryProviders/bingAerialLabels.png +0 -0
  256. package/dist/cesium/Widgets/Images/ImageryProviders/bingRoads.png +0 -0
  257. package/dist/cesium/Widgets/Images/ImageryProviders/blueMarble.png +0 -0
  258. package/dist/cesium/Widgets/Images/ImageryProviders/earthAtNight.png +0 -0
  259. package/dist/cesium/Widgets/Images/ImageryProviders/googleContour.png +0 -0
  260. package/dist/cesium/Widgets/Images/ImageryProviders/googleRoadmap.png +0 -0
  261. package/dist/cesium/Widgets/Images/ImageryProviders/googleSatellite.png +0 -0
  262. package/dist/cesium/Widgets/Images/ImageryProviders/googleSatelliteLabels.png +0 -0
  263. package/dist/cesium/Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png +0 -0
  264. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxSatellite.png +0 -0
  265. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxStreets.png +0 -0
  266. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxTerrain.png +0 -0
  267. package/dist/cesium/Widgets/Images/ImageryProviders/naturalEarthII.png +0 -0
  268. package/dist/cesium/Widgets/Images/ImageryProviders/openStreetMap.png +0 -0
  269. package/dist/cesium/Widgets/Images/ImageryProviders/sentinel-2.png +0 -0
  270. package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmooth.png +0 -0
  271. package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmoothDark.png +0 -0
  272. package/dist/cesium/Widgets/Images/ImageryProviders/stamenToner.png +0 -0
  273. package/dist/cesium/Widgets/Images/ImageryProviders/stamenWatercolor.png +0 -0
  274. package/dist/cesium/Widgets/Images/NavigationHelp/Mouse.svg +84 -0
  275. package/dist/cesium/Widgets/Images/NavigationHelp/MouseLeft.svg +76 -0
  276. package/dist/cesium/Widgets/Images/NavigationHelp/MouseMiddle.svg +76 -0
  277. package/dist/cesium/Widgets/Images/NavigationHelp/MouseRight.svg +76 -0
  278. package/dist/cesium/Widgets/Images/NavigationHelp/Touch.svg +120 -0
  279. package/dist/cesium/Widgets/Images/NavigationHelp/TouchDrag.svg +129 -0
  280. package/dist/cesium/Widgets/Images/NavigationHelp/TouchRotate.svg +76 -0
  281. package/dist/cesium/Widgets/Images/NavigationHelp/TouchTilt.svg +135 -0
  282. package/dist/cesium/Widgets/Images/NavigationHelp/TouchZoom.svg +74 -0
  283. package/dist/cesium/Widgets/Images/TerrainProviders/CesiumWorldTerrain.png +0 -0
  284. package/dist/cesium/Widgets/Images/TerrainProviders/Ellipsoid.png +0 -0
  285. package/dist/cesium/Widgets/Images/TimelineIcons.png +0 -0
  286. package/dist/cesium/Widgets/Images/info-loading.gif +0 -0
  287. package/dist/cesium/Widgets/InfoBox/InfoBox.css +92 -0
  288. package/dist/cesium/Widgets/InfoBox/InfoBoxDescription.css +178 -0
  289. package/dist/cesium/Widgets/NavigationHelpButton/NavigationHelpButton.css +93 -0
  290. package/dist/cesium/Widgets/NavigationHelpButton/lighter.css +38 -0
  291. package/dist/cesium/Widgets/PerformanceWatchdog/PerformanceWatchdog.css +15 -0
  292. package/dist/cesium/Widgets/ProjectionPicker/ProjectionPicker.css +38 -0
  293. package/dist/cesium/Widgets/SceneModePicker/SceneModePicker.css +56 -0
  294. package/dist/cesium/Widgets/SelectionIndicator/SelectionIndicator.css +20 -0
  295. package/dist/cesium/Widgets/Timeline/Timeline.css +103 -0
  296. package/dist/cesium/Widgets/Timeline/lighter.css +23 -0
  297. package/dist/cesium/Widgets/VRButton/VRButton.css +8 -0
  298. package/dist/cesium/Widgets/Viewer/Viewer.css +107 -0
  299. package/dist/cesium/Widgets/VoxelInspector/VoxelInspector.css +16 -0
  300. package/dist/cesium/Widgets/lighter.css +237 -0
  301. package/dist/cesium/Widgets/lighterShared.css +46 -0
  302. package/dist/cesium/Widgets/shared.css +103 -0
  303. package/dist/cesium/Widgets/widgets.css +1342 -0
  304. package/dist/cesium/Workers/chunk-23ZQ2IVV.js +29 -0
  305. package/dist/cesium/Workers/chunk-2EQO3Q56.js +26 -0
  306. package/dist/cesium/Workers/chunk-2MJIIVP4.js +26 -0
  307. package/dist/cesium/Workers/chunk-2TE5NTVD.js +26 -0
  308. package/dist/cesium/Workers/chunk-2ZBHLJST.js +26 -0
  309. package/dist/cesium/Workers/chunk-5TJMAQVL.js +26 -0
  310. package/dist/cesium/Workers/chunk-6BD4U3VO.js +26 -0
  311. package/dist/cesium/Workers/chunk-7TVGLKQF.js +26 -0
  312. package/dist/cesium/Workers/chunk-BTSYJ5XU.js +26 -0
  313. package/dist/cesium/Workers/chunk-BXMEEOCS.js +63 -0
  314. package/dist/cesium/Workers/chunk-BYLCY7GP.js +29 -0
  315. package/dist/cesium/Workers/chunk-CTHM3W6I.js +26 -0
  316. package/dist/cesium/Workers/chunk-CUUSNIVQ.js +26 -0
  317. package/dist/cesium/Workers/chunk-E3JOOS3S.js +26 -0
  318. package/dist/cesium/Workers/chunk-E7KYDCM5.js +26 -0
  319. package/dist/cesium/Workers/chunk-EDVBB7SS.js +27 -0
  320. package/dist/cesium/Workers/chunk-EFBN7QNX.js +26 -0
  321. package/dist/cesium/Workers/chunk-EQ4YRVWL.js +26 -0
  322. package/dist/cesium/Workers/chunk-F6PRE7D6.js +26 -0
  323. package/dist/cesium/Workers/chunk-FC4ZZ65J.js +26 -0
  324. package/dist/cesium/Workers/chunk-FFBVWF2L.js +26 -0
  325. package/dist/cesium/Workers/chunk-GBAA6GVX.js +26 -0
  326. package/dist/cesium/Workers/chunk-ICALLYLG.js +26 -0
  327. package/dist/cesium/Workers/chunk-ILRYTWTP.js +26 -0
  328. package/dist/cesium/Workers/chunk-IRNLBSEJ.js +26 -0
  329. package/dist/cesium/Workers/chunk-IX4VMHEV.js +26 -0
  330. package/dist/cesium/Workers/chunk-L6QHHACZ.js +26 -0
  331. package/dist/cesium/Workers/chunk-LI2ZSORM.js +26 -0
  332. package/dist/cesium/Workers/chunk-LSLE2RL4.js +26 -0
  333. package/dist/cesium/Workers/chunk-M4HLDBCG.js +26 -0
  334. package/dist/cesium/Workers/chunk-MJHHSGEH.js +26 -0
  335. package/dist/cesium/Workers/chunk-NMVKML6W.js +26 -0
  336. package/dist/cesium/Workers/chunk-OCWJRAXS.js +26 -0
  337. package/dist/cesium/Workers/chunk-OIRKANTH.js +26 -0
  338. package/dist/cesium/Workers/chunk-OIT7J4IC.js +26 -0
  339. package/dist/cesium/Workers/chunk-OLZ3FYUM.js +26 -0
  340. package/dist/cesium/Workers/chunk-Q5BPHJQF.js +26 -0
  341. package/dist/cesium/Workers/chunk-QFM5DCMQ.js +26 -0
  342. package/dist/cesium/Workers/chunk-QKUIYMGC.js +28 -0
  343. package/dist/cesium/Workers/chunk-S44JILQT.js +26 -0
  344. package/dist/cesium/Workers/chunk-SLT4J352.js +26 -0
  345. package/dist/cesium/Workers/chunk-SQMIIXB7.js +26 -0
  346. package/dist/cesium/Workers/chunk-TJ4XLGBQ.js +26 -0
  347. package/dist/cesium/Workers/chunk-TNSUQXWK.js +27 -0
  348. package/dist/cesium/Workers/chunk-UBOGZS7F.js +26 -0
  349. package/dist/cesium/Workers/chunk-V3OSTMM6.js +26 -0
  350. package/dist/cesium/Workers/chunk-V7QEYVP3.js +26 -0
  351. package/dist/cesium/Workers/chunk-VUKYSU4H.js +26 -0
  352. package/dist/cesium/Workers/chunk-W37FE5GR.js +26 -0
  353. package/dist/cesium/Workers/chunk-WBOV35NL.js +26 -0
  354. package/dist/cesium/Workers/chunk-WPMZLB3Y.js +26 -0
  355. package/dist/cesium/Workers/chunk-WWWZVEEH.js +26 -0
  356. package/dist/cesium/Workers/chunk-XFIQ5DEQ.js +28 -0
  357. package/dist/cesium/Workers/chunk-XQHLGIO7.js +26 -0
  358. package/dist/cesium/Workers/chunk-XUSCFAVF.js +26 -0
  359. package/dist/cesium/Workers/chunk-YP7I5QBZ.js +26 -0
  360. package/dist/cesium/Workers/chunk-Z3QF2EHT.js +26 -0
  361. package/dist/cesium/Workers/combineGeometry.js +26 -0
  362. package/dist/cesium/Workers/createBoxGeometry.js +26 -0
  363. package/dist/cesium/Workers/createBoxOutlineGeometry.js +26 -0
  364. package/dist/cesium/Workers/createCircleGeometry.js +26 -0
  365. package/dist/cesium/Workers/createCircleOutlineGeometry.js +26 -0
  366. package/dist/cesium/Workers/createCoplanarPolygonGeometry.js +26 -0
  367. package/dist/cesium/Workers/createCoplanarPolygonOutlineGeometry.js +26 -0
  368. package/dist/cesium/Workers/createCorridorGeometry.js +26 -0
  369. package/dist/cesium/Workers/createCorridorOutlineGeometry.js +26 -0
  370. package/dist/cesium/Workers/createCylinderGeometry.js +26 -0
  371. package/dist/cesium/Workers/createCylinderOutlineGeometry.js +26 -0
  372. package/dist/cesium/Workers/createEllipseGeometry.js +26 -0
  373. package/dist/cesium/Workers/createEllipseOutlineGeometry.js +26 -0
  374. package/dist/cesium/Workers/createEllipsoidGeometry.js +26 -0
  375. package/dist/cesium/Workers/createEllipsoidOutlineGeometry.js +26 -0
  376. package/dist/cesium/Workers/createFrustumGeometry.js +26 -0
  377. package/dist/cesium/Workers/createFrustumOutlineGeometry.js +26 -0
  378. package/dist/cesium/Workers/createGeometry.js +26 -0
  379. package/dist/cesium/Workers/createGroundPolylineGeometry.js +26 -0
  380. package/dist/cesium/Workers/createPlaneGeometry.js +26 -0
  381. package/dist/cesium/Workers/createPlaneOutlineGeometry.js +26 -0
  382. package/dist/cesium/Workers/createPolygonGeometry.js +26 -0
  383. package/dist/cesium/Workers/createPolygonOutlineGeometry.js +26 -0
  384. package/dist/cesium/Workers/createPolylineGeometry.js +26 -0
  385. package/dist/cesium/Workers/createPolylineVolumeGeometry.js +26 -0
  386. package/dist/cesium/Workers/createPolylineVolumeOutlineGeometry.js +26 -0
  387. package/dist/cesium/Workers/createRectangleGeometry.js +26 -0
  388. package/dist/cesium/Workers/createRectangleOutlineGeometry.js +26 -0
  389. package/dist/cesium/Workers/createSimplePolylineGeometry.js +26 -0
  390. package/dist/cesium/Workers/createSphereGeometry.js +26 -0
  391. package/dist/cesium/Workers/createSphereOutlineGeometry.js +26 -0
  392. package/dist/cesium/Workers/createTaskProcessorWorker.js +26 -0
  393. package/dist/cesium/Workers/createVectorTileClampedPolylines.js +26 -0
  394. package/dist/cesium/Workers/createVectorTileGeometries.js +26 -0
  395. package/dist/cesium/Workers/createVectorTilePoints.js +26 -0
  396. package/dist/cesium/Workers/createVectorTilePolygons.js +26 -0
  397. package/dist/cesium/Workers/createVectorTilePolylines.js +26 -0
  398. package/dist/cesium/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -0
  399. package/dist/cesium/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -0
  400. package/dist/cesium/Workers/createVerticesFromHeightmap.js +26 -0
  401. package/dist/cesium/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -0
  402. package/dist/cesium/Workers/createWallGeometry.js +26 -0
  403. package/dist/cesium/Workers/createWallOutlineGeometry.js +26 -0
  404. package/dist/cesium/Workers/decodeDraco.js +26 -0
  405. package/dist/cesium/Workers/decodeGoogleEarthEnterprisePacket.js +26 -0
  406. package/dist/cesium/Workers/decodeI3S.js +26 -0
  407. package/dist/cesium/Workers/gaussianSplatSorter.js +26 -0
  408. package/dist/cesium/Workers/gaussianSplatTextureGenerator.js +26 -0
  409. package/dist/cesium/Workers/incrementallyBuildTerrainPicker.js +26 -0
  410. package/dist/cesium/Workers/transcodeKTX2.js +56 -0
  411. package/dist/cesium/Workers/transferTypedArrayTest.js +26 -0
  412. package/dist/cesium/Workers/upsampleQuantizedTerrainMesh.js +26 -0
  413. package/dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -0
  414. package/dist/index.html +10 -8
  415. package/package.json +15 -12
  416. package/src/App.tsx +1 -17
  417. package/src/components/viewer/BCFPanel.tsx +46 -4
  418. package/src/components/viewer/CesiumOverlay.tsx +672 -0
  419. package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
  420. package/src/components/viewer/ChatPanel.tsx +54 -16
  421. package/src/components/viewer/CommandPalette.tsx +6 -1
  422. package/src/components/viewer/DesktopEntitlementBanner.tsx +74 -0
  423. package/src/components/viewer/ExportChangesButton.tsx +6 -1
  424. package/src/components/viewer/ExportDialog.tsx +22 -6
  425. package/src/components/viewer/HierarchyPanel.tsx +196 -0
  426. package/src/components/viewer/IDSPanel.tsx +52 -3
  427. package/src/components/viewer/KeyboardShortcutsDialog.tsx +1 -1
  428. package/src/components/viewer/MainToolbar.tsx +353 -27
  429. package/src/components/viewer/PropertiesPanel.tsx +218 -79
  430. package/src/components/viewer/ScriptPanel.tsx +34 -8
  431. package/src/components/viewer/SettingsPage.tsx +430 -0
  432. package/src/components/viewer/StatusBar.tsx +17 -1
  433. package/src/components/viewer/UpgradePage.tsx +6 -4
  434. package/src/components/viewer/ViewerLayout.tsx +47 -6
  435. package/src/components/viewer/Viewport.tsx +49 -8
  436. package/src/components/viewer/ViewportContainer.tsx +280 -28
  437. package/src/components/viewer/ViewportOverlays.tsx +129 -27
  438. package/src/components/viewer/properties/GeoreferencingPanel.tsx +117 -5
  439. package/src/components/viewer/properties/LocationMap.tsx +458 -17
  440. package/src/components/viewer/selectionHandlers.ts +4 -3
  441. package/src/components/viewer/useAnimationLoop.ts +4 -0
  442. package/src/components/viewer/useGeometryStreaming.ts +127 -40
  443. package/src/components/viewer/useMouseControls.ts +4 -1
  444. package/src/hooks/ingest/viewerModelIngest.ts +275 -0
  445. package/src/hooks/useIDS.ts +1 -1
  446. package/src/hooks/useIfc.ts +7 -1
  447. package/src/hooks/useIfcCache.ts +28 -15
  448. package/src/hooks/useIfcFederation.ts +57 -225
  449. package/src/hooks/useIfcLoader.ts +1656 -130
  450. package/src/hooks/useIfcServer.ts +0 -69
  451. package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +175 -0
  452. package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
  453. package/src/lib/desktop-entitlement.ts +45 -0
  454. package/src/lib/desktop-product.ts +124 -0
  455. package/src/lib/geo/cesium-bridge.ts +310 -0
  456. package/src/lib/geo/reproject.ts +151 -25
  457. package/src/lib/recent-files.ts +2 -1
  458. package/src/services/analysis-extensions.ts +125 -0
  459. package/src/services/app-navigation.ts +13 -0
  460. package/src/services/bsdd.ts +53 -4
  461. package/src/services/cacheService.ts +1 -1
  462. package/src/services/desktop-cache.ts +43 -0
  463. package/src/services/desktop-export.ts +77 -0
  464. package/src/services/desktop-harness.ts +196 -0
  465. package/src/services/desktop-logger.ts +20 -0
  466. package/src/services/desktop-native-metadata.ts +207 -0
  467. package/src/services/desktop-panel-actions.ts +43 -0
  468. package/src/services/desktop-preferences.ts +44 -0
  469. package/src/services/file-dialog.ts +147 -0
  470. package/src/services/tauri-core-stub.ts +7 -0
  471. package/src/services/tauri-dialog-stub.ts +7 -0
  472. package/src/services/tauri-fs-stub.ts +7 -0
  473. package/src/store/index.ts +40 -2
  474. package/src/store/slices/cesiumSlice.ts +122 -0
  475. package/src/store/slices/chatSlice.ts +5 -1
  476. package/src/store/slices/dataSlice.ts +139 -28
  477. package/src/store/slices/desktopEntitlementSlice.ts +86 -0
  478. package/src/store/slices/loadingSlice.ts +14 -2
  479. package/src/store/slices/modelSlice.ts +58 -3
  480. package/src/store/types.ts +96 -2
  481. package/src/store.ts +1 -1
  482. package/src/utils/desktopModelSnapshot.ts +358 -0
  483. package/src/utils/ifcConfig.ts +6 -1
  484. package/src/utils/nativeSpatialDataStore.ts +250 -0
  485. package/src/utils/serverDataModel.ts +4 -0
  486. package/src/utils/spatialHierarchy.ts +10 -11
  487. package/vite.config.ts +24 -0
  488. package/dist/assets/arrow-DJf2ErbF.js +0 -20
  489. package/dist/assets/basketViewActivator-aojwdomq.js +0 -1
  490. package/dist/assets/desktop-cache-oPzaWXYE.js +0 -1
  491. package/dist/assets/geometry.worker-Nz9_YIqh.js +0 -1
  492. package/dist/assets/ifc-lite_bg-eSkBTizQ.wasm +0 -0
  493. package/dist/assets/index-pbE7itQS.css +0 -1
  494. package/dist/assets/native-bridge-DSIyEYXG.js +0 -113
  495. package/dist/assets/wasm-bridge-B0J07fZZ.js +0 -1
@@ -0,0 +1,672 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+
5
+ /**
6
+ * CesiumOverlay — renders a CesiumJS globe behind the WebGPU canvas,
7
+ * providing real-world 3D context (terrain, buildings, imagery) for
8
+ * georeferenced IFC models.
9
+ *
10
+ * Architecture:
11
+ * - A separate <div> behind the WebGPU <canvas> (z-index layering)
12
+ * - WebGPU canvas uses transparent clear color so Cesium shows through
13
+ * - Camera is synchronized every frame from the IFC viewer camera
14
+ * - CesiumJS is lazy-loaded on first activation to avoid bundle bloat
15
+ * - User controls remain on the WebGPU canvas; Cesium's are disabled
16
+ *
17
+ * Live edit support:
18
+ * - When georef props change (e.g. user edits EPSG, eastings, rotation),
19
+ * the coordinate bridge is rebuilt and the globe flies to the new location
20
+ * - The Cesium viewer itself is NOT recreated — only the bridge is updated
21
+ */
22
+
23
+ import { useEffect, useRef, useState } from 'react';
24
+ import { useViewerStore } from '@/store';
25
+ import type { MapConversion, ProjectedCRS } from '@ifc-lite/parser';
26
+ import type { CoordinateInfo, GeometryResult } from '@ifc-lite/geometry';
27
+ import { getGlobalRenderer } from '@/hooks/useBCF';
28
+ import { createCesiumBridge, type CesiumBridge } from '@/lib/geo/cesium-bridge';
29
+
30
+ // Lazy-loaded Cesium module and CSS
31
+ let cesiumPromise: Promise<typeof import('cesium')> | null = null;
32
+ let cesiumModule: typeof import('cesium') | null = null;
33
+ function loadCesium() {
34
+ if (!cesiumPromise) {
35
+ cesiumPromise = Promise.all([
36
+ import('cesium'),
37
+ import('cesium/Build/Cesium/Widgets/widgets.css'),
38
+ ]).then(([cesium]) => {
39
+ cesiumModule = cesium;
40
+ return cesium;
41
+ });
42
+ }
43
+ return cesiumPromise;
44
+ }
45
+
46
+ /**
47
+ * Build a minimal GLB with all geometry merged into a SINGLE mesh.
48
+ * This is MUCH faster than GLTFExporter (which creates one glTF node per IFC mesh).
49
+ * For a 42K mesh model: GLTFExporter takes seconds, this takes ~100ms.
50
+ */
51
+ function buildMergedGLB(meshes: import('@ifc-lite/geometry').MeshData[]): Uint8Array {
52
+ // Pass 1: calculate total sizes
53
+ let totalVerts = 0;
54
+ let totalIdxs = 0;
55
+ for (const m of meshes) {
56
+ if (!m.positions?.length || !m.indices?.length) continue;
57
+ totalVerts += m.positions.length / 3;
58
+ totalIdxs += m.indices.length;
59
+ }
60
+
61
+ // Allocate merged buffers
62
+ const positions = new Float32Array(totalVerts * 3);
63
+ const colors = new Uint8Array(totalVerts * 4);
64
+ const indices = new Uint32Array(totalIdxs);
65
+
66
+ // Pass 2: merge
67
+ let vertOff = 0;
68
+ let idxOff = 0;
69
+ for (const m of meshes) {
70
+ if (!m.positions?.length || !m.indices?.length) continue;
71
+ const nv = m.positions.length / 3;
72
+ positions.set(m.positions, vertOff * 3);
73
+ // Vertex colors from mesh color
74
+ const r = Math.round((m.color?.[0] ?? 0.7) * 255);
75
+ const g = Math.round((m.color?.[1] ?? 0.7) * 255);
76
+ const b = Math.round((m.color?.[2] ?? 0.7) * 255);
77
+ const a = Math.round((m.color?.[3] ?? 1.0) * 255);
78
+ for (let i = 0; i < nv; i++) {
79
+ const ci = (vertOff + i) * 4;
80
+ colors[ci] = r; colors[ci + 1] = g; colors[ci + 2] = b; colors[ci + 3] = a;
81
+ }
82
+ for (let i = 0; i < m.indices.length; i++) {
83
+ indices[idxOff + i] = m.indices[i] + vertOff;
84
+ }
85
+ vertOff += nv;
86
+ idxOff += m.indices.length;
87
+ }
88
+
89
+ // Compute bounds
90
+ let minX = Infinity, minY = Infinity, minZ = Infinity;
91
+ let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
92
+ for (let i = 0; i < positions.length; i += 3) {
93
+ const x = positions[i], y = positions[i + 1], z = positions[i + 2];
94
+ if (x < minX) minX = x; if (x > maxX) maxX = x;
95
+ if (y < minY) minY = y; if (y > maxY) maxY = y;
96
+ if (z < minZ) minZ = z; if (z > maxZ) maxZ = z;
97
+ }
98
+
99
+ // Build minimal glTF JSON
100
+ const posByteLen = positions.byteLength;
101
+ const colByteLen = colors.byteLength;
102
+ const idxByteLen = indices.byteLength;
103
+ const totalBinLen = posByteLen + colByteLen + idxByteLen;
104
+
105
+ const gltf = {
106
+ asset: { version: '2.0', generator: 'IFC-Lite-Cesium' },
107
+ scene: 0,
108
+ scenes: [{ nodes: [0] }],
109
+ nodes: [{ mesh: 0 }],
110
+ meshes: [{ primitives: [{ attributes: { POSITION: 0, COLOR_0: 1 }, indices: 2 }] }],
111
+ accessors: [
112
+ { bufferView: 0, componentType: 5126, count: totalVerts, type: 'VEC3', min: [minX, minY, minZ], max: [maxX, maxY, maxZ] },
113
+ { bufferView: 1, componentType: 5121, count: totalVerts, type: 'VEC4', normalized: true },
114
+ { bufferView: 2, componentType: 5125, count: totalIdxs, type: 'SCALAR' },
115
+ ],
116
+ bufferViews: [
117
+ { buffer: 0, byteOffset: 0, byteLength: posByteLen, target: 34962 },
118
+ { buffer: 0, byteOffset: posByteLen, byteLength: colByteLen, target: 34962 },
119
+ { buffer: 0, byteOffset: posByteLen + colByteLen, byteLength: idxByteLen, target: 34963 },
120
+ ],
121
+ buffers: [{ byteLength: totalBinLen }],
122
+ extensionsUsed: ['KHR_materials_unlit'],
123
+ };
124
+
125
+ const jsonStr = JSON.stringify(gltf);
126
+ const jsonBuf = new TextEncoder().encode(jsonStr);
127
+ // Pad JSON to 4-byte alignment
128
+ const jsonPad = (4 - (jsonBuf.length % 4)) % 4;
129
+ const jsonChunkLen = jsonBuf.length + jsonPad;
130
+ // Pad binary to 4-byte alignment
131
+ const binPad = (4 - (totalBinLen % 4)) % 4;
132
+ const binChunkLen = totalBinLen + binPad;
133
+
134
+ // GLB: 12-byte header + 8-byte JSON chunk header + JSON + 8-byte BIN chunk header + BIN
135
+ const glbLen = 12 + 8 + jsonChunkLen + 8 + binChunkLen;
136
+ const glb = new ArrayBuffer(glbLen);
137
+ const view = new DataView(glb);
138
+ let off = 0;
139
+
140
+ // GLB header
141
+ view.setUint32(off, 0x46546C67, true); off += 4; // magic "glTF"
142
+ view.setUint32(off, 2, true); off += 4; // version
143
+ view.setUint32(off, glbLen, true); off += 4; // total length
144
+
145
+ // JSON chunk
146
+ view.setUint32(off, jsonChunkLen, true); off += 4;
147
+ view.setUint32(off, 0x4E4F534A, true); off += 4; // "JSON"
148
+ new Uint8Array(glb, off, jsonBuf.length).set(jsonBuf); off += jsonBuf.length;
149
+ for (let i = 0; i < jsonPad; i++) view.setUint8(off++, 0x20); // space padding
150
+
151
+ // BIN chunk
152
+ view.setUint32(off, binChunkLen, true); off += 4;
153
+ view.setUint32(off, 0x004E4942, true); off += 4; // "BIN\0"
154
+ new Uint8Array(glb, off, posByteLen).set(new Uint8Array(positions.buffer)); off += posByteLen;
155
+ new Uint8Array(glb, off, colByteLen).set(colors); off += colByteLen;
156
+ new Uint8Array(glb, off, idxByteLen).set(new Uint8Array(indices.buffer)); off += idxByteLen;
157
+
158
+ return new Uint8Array(glb);
159
+ }
160
+
161
+ /**
162
+ * Build a Cesium model matrix for placing the IFC model in ECEF.
163
+ * Extracted as a pure function so it can be called from both
164
+ * the GLB load effect (initial) and the matrix update effect (instant).
165
+ */
166
+ function buildModelMatrix(
167
+ Cesium: typeof import('cesium'),
168
+ bridge: CesiumBridge,
169
+ mapConversion: MapConversion | undefined,
170
+ coordinateInfo: CoordinateInfo | undefined,
171
+ clamp: boolean,
172
+ terrainH: number | null,
173
+ ) {
174
+ const hScale = mapConversion?.scale ?? 1.0;
175
+ const absc = mapConversion?.xAxisAbscissa ?? 1.0;
176
+ const ordi = mapConversion?.xAxisOrdinate ?? 0.0;
177
+ const bounds = coordinateInfo?.originalBounds;
178
+ const mvx = bounds ? (bounds.min.x + bounds.max.x) / 2 : 0;
179
+ const mvy = bounds ? (bounds.min.y + bounds.max.y) / 2 : 0;
180
+ const mvz = bounds ? (bounds.min.z + bounds.max.z) / 2 : 0;
181
+
182
+ let placementHeight = bridge.modelOrigin.height;
183
+ if (clamp && terrainH !== null) {
184
+ const minY = bounds?.min.y ?? 0;
185
+ const bottomOffset = mvy - minY;
186
+ placementHeight = terrainH + bottomOffset;
187
+ }
188
+
189
+ const origin = Cesium.Cartesian3.fromDegrees(
190
+ bridge.modelOrigin.longitude, bridge.modelOrigin.latitude, placementHeight,
191
+ );
192
+ const enuToEcef = Cesium.Transforms.eastNorthUpToFixedFrame(origin);
193
+ const sa = hScale * absc, so = hScale * ordi;
194
+ const ifcToEnu = new Cesium.Matrix4(
195
+ sa, -so, 0, -(sa * mvx + so * mvz),
196
+ so, sa, 0, -(so * mvx - sa * mvz),
197
+ 0, 0, 1, -mvy,
198
+ 0, 0, 0, 1,
199
+ );
200
+ return Cesium.Matrix4.multiply(enuToEcef, ifcToEnu, new Cesium.Matrix4());
201
+ }
202
+
203
+ export interface CesiumOverlayProps {
204
+ mapConversion?: MapConversion;
205
+ projectedCRS?: ProjectedCRS;
206
+ coordinateInfo?: CoordinateInfo;
207
+ geometryResult?: GeometryResult | null;
208
+ }
209
+
210
+ export function CesiumOverlay({
211
+ mapConversion,
212
+ projectedCRS,
213
+ coordinateInfo,
214
+ geometryResult,
215
+ }: CesiumOverlayProps) {
216
+ const containerRef = useRef<HTMLDivElement>(null);
217
+ const viewerRef = useRef<InstanceType<typeof import('cesium').Viewer> | null>(null);
218
+ const bridgeRef = useRef<CesiumBridge | null>(null);
219
+ const rafRef = useRef<number | null>(null);
220
+ const [status, setStatus] = useState<'idle' | 'loading' | 'ready' | 'error'>('idle');
221
+ const [error, setError] = useState<string | null>(null);
222
+ // Tracks bridge readiness as state (not just a ref) so terrain query effect re-runs
223
+ const [bridgeVersion, setBridgeVersion] = useState(0);
224
+
225
+ const cesiumEnabled = useViewerStore((s) => s.cesiumEnabled);
226
+ const dataSource = useViewerStore((s) => s.cesiumDataSource);
227
+ const ionToken = useViewerStore((s) => s.cesiumIonToken);
228
+ const terrainEnabled = useViewerStore((s) => s.cesiumTerrainEnabled);
229
+ const terrainClamp = useViewerStore((s) => s.cesiumTerrainClamp);
230
+ const terrainHeight = useViewerStore((s) => s.cesiumTerrainHeight);
231
+ const setCesiumTerrainHeight = useViewerStore((s) => s.setCesiumTerrainHeight);
232
+ const setCesiumTerrainClipY = useViewerStore((s) => s.setCesiumTerrainClipY);
233
+ const setCesiumGlbLoaded = useViewerStore((s) => s.setCesiumGlbLoaded);
234
+
235
+ // Use refs so the camera sync loop always reads the latest values
236
+ const terrainClampRef = useRef(terrainClamp);
237
+ const terrainHeightRef = useRef(terrainHeight);
238
+ terrainClampRef.current = terrainClamp;
239
+ terrainHeightRef.current = terrainHeight;
240
+
241
+ // Track the Cesium model (IFC geometry loaded as glTF for correct world positioning)
242
+ const cesiumModelRef = useRef<{ modelMatrix: any; destroy?: () => void } | null>(null);
243
+ const glbCacheRef = useRef<{ meshCount: number; glb: Uint8Array } | null>(null);
244
+
245
+ // ─── Effect 1: Create/destroy the Cesium viewer (heavy, rare) ───────────
246
+ // Only depends on cesiumEnabled, ionToken, terrainEnabled, dataSource.
247
+ // NOT on mapConversion/projectedCRS — those are handled by Effect 2.
248
+ useEffect(() => {
249
+ if (!cesiumEnabled || !containerRef.current) return;
250
+
251
+ let cancelled = false;
252
+ setStatus('loading');
253
+ setError(null);
254
+
255
+ (async () => {
256
+ try {
257
+ const Cesium = await loadCesium();
258
+ if (cancelled || !containerRef.current) return;
259
+
260
+ // Configure Cesium ion token if provided
261
+ if (ionToken) {
262
+ Cesium.Ion.defaultAccessToken = ionToken;
263
+ }
264
+
265
+ const viewer = new Cesium.Viewer(containerRef.current, {
266
+ animation: false,
267
+ baseLayerPicker: false,
268
+ fullscreenButton: false,
269
+ geocoder: false,
270
+ homeButton: false,
271
+ infoBox: false,
272
+ sceneModePicker: false,
273
+ selectionIndicator: false,
274
+ timeline: false,
275
+ navigationHelpButton: false,
276
+ navigationInstructionsInitiallyVisible: false,
277
+ // Cesium ion ToS requires visible attribution — use a small container
278
+ // at bottom of the overlay rather than hiding credits entirely.
279
+ msaaSamples: 1,
280
+ requestRenderMode: true,
281
+ maximumRenderTimeChange: Infinity,
282
+ baseLayer: false,
283
+ });
284
+
285
+ if (cancelled) { viewer.destroy(); return; }
286
+
287
+ // Disable Cesium's user input — the IFC viewer controls the camera.
288
+ // Keep collision detection off since we set the camera programmatically.
289
+ const scene = viewer.scene;
290
+ const sscc = scene.screenSpaceCameraController;
291
+ sscc.enableRotate = false;
292
+ sscc.enableTranslate = false;
293
+ sscc.enableZoom = false;
294
+ sscc.enableTilt = false;
295
+ sscc.enableLook = false;
296
+ sscc.enableCollisionDetection = false;
297
+ sscc.minimumZoomDistance = 0;
298
+ sscc.maximumZoomDistance = Infinity;
299
+ // Enable depth testing so the model (and other objects) get clipped
300
+ // by terrain — prevents seeing underground portions.
301
+ scene.globe.depthTestAgainstTerrain = true;
302
+
303
+ // Move credit/logo from bottom-left to top-left to avoid overlap
304
+ // with other UI elements.
305
+ const bottomContainer = viewer.bottomContainer as HTMLElement;
306
+ if (bottomContainer) {
307
+ bottomContainer.style.top = '0';
308
+ bottomContainer.style.bottom = 'auto';
309
+ bottomContainer.style.left = '0';
310
+ bottomContainer.style.right = 'auto';
311
+ }
312
+
313
+ // Disable skybox/atmosphere/fog for transparent compositing
314
+ if (scene.skyBox) (scene.skyBox as any).show = false;
315
+ if (scene.sun) scene.sun.show = false;
316
+ if (scene.moon) scene.moon.show = false;
317
+ if (scene.skyAtmosphere) scene.skyAtmosphere.show = false;
318
+ scene.fog.enabled = false;
319
+ scene.globe.showGroundAtmosphere = false;
320
+ scene.backgroundColor = Cesium.Color.TRANSPARENT;
321
+ scene.globe.baseColor = Cesium.Color.TRANSPARENT;
322
+
323
+ // Add imagery
324
+ try {
325
+ const imageryProvider = await Cesium.IonImageryProvider.fromAssetId(2);
326
+ viewer.imageryLayers.addImageryProvider(imageryProvider);
327
+ } catch {
328
+ viewer.imageryLayers.addImageryProvider(
329
+ new Cesium.OpenStreetMapImageryProvider({
330
+ url: 'https://a.tile.openstreetmap.org/',
331
+ })
332
+ );
333
+ }
334
+
335
+ // Add terrain
336
+ if (terrainEnabled && ionToken) {
337
+ try {
338
+ const terrainProvider = await Cesium.CesiumTerrainProvider.fromIonAssetId(1);
339
+ viewer.terrainProvider = terrainProvider;
340
+ } catch { /* terrain unavailable */ }
341
+ }
342
+
343
+ // Add data source layer
344
+ await addDataSourceLayer(Cesium, viewer, dataSource, ionToken);
345
+
346
+ if (cancelled) { viewer.destroy(); return; }
347
+
348
+ viewerRef.current = viewer;
349
+ setStatus('ready');
350
+ } catch (err) {
351
+ if (!cancelled) {
352
+ console.error('[CesiumOverlay] Init failed:', err);
353
+ setError(err instanceof Error ? err.message : 'Cesium initialization failed');
354
+ setStatus('error');
355
+ }
356
+ }
357
+ })();
358
+
359
+ return () => {
360
+ cancelled = true;
361
+ if (rafRef.current !== null) {
362
+ cancelAnimationFrame(rafRef.current);
363
+ rafRef.current = null;
364
+ }
365
+ if (viewerRef.current) {
366
+ viewerRef.current.destroy();
367
+ viewerRef.current = null;
368
+ }
369
+ // Invalidate model ref — the destroyed viewer took the primitive with it,
370
+ // so Effect 2c must re-load the GLB into the next viewer instance.
371
+ cesiumModelRef.current = null;
372
+ bridgeRef.current = null;
373
+ setStatus('idle');
374
+ };
375
+ }, [cesiumEnabled, ionToken, terrainEnabled, dataSource]);
376
+
377
+ // ─── Effect 2: Rebuild coordinate bridge when georef changes (fast) ─────
378
+ // This is the live-edit handler. When the user changes EPSG, eastings,
379
+ // northings, rotation, etc., we rebuild the bridge and fly to the new spot.
380
+ useEffect(() => {
381
+ if (status !== 'ready' || !mapConversion || !projectedCRS) {
382
+ bridgeRef.current = null;
383
+ return;
384
+ }
385
+
386
+ let cancelled = false;
387
+
388
+ (async () => {
389
+ const bridge = await createCesiumBridge(mapConversion, projectedCRS, coordinateInfo);
390
+ if (cancelled) return;
391
+
392
+ if (!bridge) {
393
+ bridgeRef.current = null;
394
+ return;
395
+ }
396
+
397
+ const prevBridge = bridgeRef.current;
398
+ bridgeRef.current = bridge;
399
+ // Bump version so terrain query effect re-runs now that bridge is ready
400
+ setBridgeVersion((v) => v + 1);
401
+
402
+ // Fly to the new model location (smooth animation)
403
+ const viewer = viewerRef.current;
404
+ const Cesium = cesiumModule;
405
+ if (viewer && Cesium) {
406
+ const { modelOrigin } = bridge;
407
+
408
+ const isFirstPosition = !prevBridge;
409
+ const target = Cesium.Cartesian3.fromDegrees(
410
+ modelOrigin.longitude, modelOrigin.latitude, modelOrigin.height,
411
+ );
412
+
413
+ if (isFirstPosition) {
414
+ // First time: instant jump to isometric view
415
+ const hpr = new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-45), 300);
416
+ viewer.camera.lookAt(target, hpr);
417
+ viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
418
+ viewer.scene.requestRender();
419
+ } else if (prevBridge) {
420
+ // Georef edit: just re-render, the camera sync loop will pick
421
+ // up the new bridge on the next frame. No dramatic fly animation.
422
+ viewer.scene.requestRender();
423
+ }
424
+ }
425
+ })();
426
+
427
+ return () => { cancelled = true; };
428
+ }, [status, mapConversion, projectedCRS, coordinateInfo]);
429
+
430
+ // ─── Effect 2b: Query terrain height when bridge is ready ───────────────
431
+ // Also re-queries when terrainClamp is toggled on (in case first query failed)
432
+ useEffect(() => {
433
+ if (status !== 'ready') return;
434
+ const bridge = bridgeRef.current;
435
+ const viewer = viewerRef.current;
436
+ const Cesium = cesiumModule;
437
+ if (!bridge || !viewer || !Cesium) return;
438
+
439
+ let cancelled = false;
440
+
441
+ // Query immediately, then retry after a delay if terrain tiles weren't loaded yet
442
+ // Compute model center Y in viewer space for terrain clip offset
443
+ const bounds = coordinateInfo?.originalBounds;
444
+ const modelVY = bounds ? (bounds.min.y + bounds.max.y) / 2 : 0;
445
+ const modelMinY = bounds ? bounds.min.y : 0;
446
+
447
+ const doQuery = () => {
448
+ bridge.queryTerrainHeight(Cesium, viewer).then((h) => {
449
+ if (!cancelled && h !== null) {
450
+ setCesiumTerrainHeight(h);
451
+ // Compute terrain clip Y in viewer space:
452
+ // terrain is at height h (meters). Model origin is at bridge.modelOrigin.height.
453
+ // In viewer Y-up, the bottom of the model is at modelMinY.
454
+ // Terrain clip Y = modelMinY + (terrainHeight - modelOriginHeight)
455
+ // This places the clip plane at the terrain surface relative to model geometry.
456
+ const terrainClipY = modelMinY + (h - bridge.modelOrigin.height);
457
+ setCesiumTerrainClipY(terrainClipY);
458
+ }
459
+ });
460
+ };
461
+
462
+ // First attempt
463
+ doQuery();
464
+ // Retry after 5s in case terrain tiles were still loading
465
+ const retryTimer = setTimeout(doQuery, 5000);
466
+
467
+ return () => { cancelled = true; clearTimeout(retryTimer); };
468
+ }, [status, terrainEnabled, terrainClamp, bridgeVersion]);
469
+
470
+ // ─── Effect 2c: Load GLB into Cesium (only when geometry changes) ───────
471
+ // This is the heavy operation — only re-runs when geometry actually changes.
472
+ useEffect(() => {
473
+ if (status !== 'ready' || !geometryResult?.meshes?.length) return;
474
+ const viewer = viewerRef.current;
475
+ const bridge = bridgeRef.current;
476
+ const Cesium = cesiumModule;
477
+ if (!viewer || !bridge || !Cesium) return;
478
+
479
+ let cancelled = false;
480
+
481
+ const startExport = async () => {
482
+ if (cancelled) return;
483
+ try {
484
+ // Export GLB (cached by mesh count — skip if already loaded)
485
+ const meshCount = geometryResult.meshes.length;
486
+ if (cesiumModelRef.current && glbCacheRef.current?.meshCount === meshCount) {
487
+ // Model already loaded with same geometry — just update matrix
488
+ return;
489
+ }
490
+
491
+ // Remove previous model
492
+ if (cesiumModelRef.current) {
493
+ viewer.scene.primitives.remove(cesiumModelRef.current);
494
+ cesiumModelRef.current = null;
495
+ }
496
+
497
+ let glbBytes: Uint8Array;
498
+ if (glbCacheRef.current?.meshCount === meshCount) {
499
+ glbBytes = glbCacheRef.current.glb;
500
+ } else {
501
+ await new Promise(r => setTimeout(r, 50));
502
+ if (cancelled) return;
503
+ glbBytes = buildMergedGLB(geometryResult.meshes);
504
+ glbCacheRef.current = { meshCount, glb: glbBytes };
505
+ }
506
+ if (cancelled) return;
507
+
508
+ await new Promise(r => setTimeout(r, 0));
509
+ if (cancelled) return;
510
+
511
+ // Build initial model matrix
512
+ const modelMatrix = buildModelMatrix(Cesium, bridge, mapConversion, coordinateInfo, terrainClampRef.current, terrainHeightRef.current);
513
+
514
+ const blob = new Blob([glbBytes as BlobPart], { type: 'model/gltf-binary' });
515
+ const glbUrl = URL.createObjectURL(blob);
516
+ let model: { modelMatrix: any; destroy?: () => void } | null = null;
517
+ try {
518
+ model = await Cesium.Model.fromGltfAsync({
519
+ url: glbUrl, modelMatrix, shadows: Cesium.ShadowMode.DISABLED,
520
+ });
521
+ } finally {
522
+ URL.revokeObjectURL(glbUrl);
523
+ }
524
+ if (cancelled) {
525
+ model?.destroy?.();
526
+ return;
527
+ }
528
+
529
+ viewer.scene.primitives.add(model);
530
+ cesiumModelRef.current = model;
531
+ setCesiumGlbLoaded(true);
532
+ viewer.scene.requestRender();
533
+ } catch (err) {
534
+ console.warn('[CesiumOverlay] Failed to load IFC model into Cesium:', err);
535
+ }
536
+ };
537
+
538
+ const deferTimer = setTimeout(startExport, 1000);
539
+
540
+ return () => {
541
+ cancelled = true;
542
+ clearTimeout(deferTimer);
543
+ if (cesiumModelRef.current && viewerRef.current) {
544
+ viewerRef.current.scene.primitives.remove(cesiumModelRef.current);
545
+ cesiumModelRef.current = null;
546
+ }
547
+ setCesiumGlbLoaded(false);
548
+ };
549
+ }, [status, bridgeVersion, geometryResult]);
550
+
551
+ // ─── Effect 2d: Update model matrix (instant, no reload) ────────────────
552
+ // When terrain clamp, terrain height, or georef changes, just update the
553
+ // existing model's matrix — no GLB re-export, no flicker.
554
+ useEffect(() => {
555
+ const model = cesiumModelRef.current;
556
+ const bridge = bridgeRef.current;
557
+ const viewer = viewerRef.current;
558
+ const Cesium = cesiumModule;
559
+ if (!model || !bridge || !viewer || !Cesium) return;
560
+
561
+ const newMatrix = buildModelMatrix(Cesium, bridge, mapConversion, coordinateInfo, terrainClamp, terrainHeight);
562
+ model.modelMatrix = newMatrix;
563
+ viewer.scene.requestRender();
564
+ }, [terrainClamp, terrainHeight, mapConversion, coordinateInfo]);
565
+
566
+ // ─── Effect 3: Camera sync loop ─────────────────────────────────────────
567
+ useEffect(() => {
568
+ if (status !== 'ready') return;
569
+
570
+ const viewer = viewerRef.current;
571
+ if (!viewer) return;
572
+
573
+ let cancelled = false;
574
+
575
+ function syncCamera() {
576
+ if (cancelled) return;
577
+
578
+ const bridge = bridgeRef.current;
579
+ const renderer = getGlobalRenderer();
580
+ const Cesium = cesiumModule;
581
+ if (!viewer || !bridge || !renderer || !Cesium) {
582
+ rafRef.current = requestAnimationFrame(syncCamera);
583
+ return;
584
+ }
585
+
586
+ const camera = renderer.getCamera();
587
+ const camPos = camera.getPosition();
588
+ const camTarget = camera.getTarget();
589
+ const camUp = camera.getUp();
590
+ const fov = camera.getFOV();
591
+
592
+ // Sync Cesium camera (no terrain offset — model matrix handles clamping)
593
+ bridge.syncCamera(Cesium, viewer, camPos, camTarget, camUp, fov);
594
+
595
+ rafRef.current = requestAnimationFrame(syncCamera);
596
+ }
597
+
598
+ rafRef.current = requestAnimationFrame(syncCamera);
599
+
600
+ return () => {
601
+ cancelled = true;
602
+ if (rafRef.current !== null) {
603
+ cancelAnimationFrame(rafRef.current);
604
+ rafRef.current = null;
605
+ }
606
+ };
607
+ }, [status]);
608
+
609
+ if (!cesiumEnabled || !mapConversion || !projectedCRS) {
610
+ return null;
611
+ }
612
+
613
+ return (
614
+ <>
615
+ <div
616
+ ref={containerRef}
617
+ className="absolute inset-0 z-0"
618
+ style={{ pointerEvents: 'none' }}
619
+ />
620
+ {status === 'loading' && (
621
+ <div className="absolute top-2 left-1/2 -translate-x-1/2 z-10 flex items-center gap-2 px-3 py-1.5 bg-black/60 backdrop-blur-sm rounded text-xs text-white font-mono">
622
+ <div className="h-3 w-3 border-2 border-white/30 border-t-white rounded-full animate-spin" />
623
+ Loading 3D context...
624
+ </div>
625
+ )}
626
+ {status === 'error' && error && (
627
+ <div className="absolute top-2 left-1/2 -translate-x-1/2 z-10 px-3 py-1.5 bg-red-900/80 backdrop-blur-sm rounded text-xs text-red-200 font-mono">
628
+ {error}
629
+ </div>
630
+ )}
631
+ </>
632
+ );
633
+ }
634
+
635
+ /**
636
+ * Add the selected 3D data source layer to the Cesium viewer.
637
+ */
638
+ async function addDataSourceLayer(
639
+ Cesium: typeof import('cesium'),
640
+ viewer: InstanceType<typeof import('cesium').Viewer>,
641
+ dataSource: string,
642
+ ionToken: string,
643
+ ) {
644
+ try {
645
+ switch (dataSource) {
646
+ case 'osm-buildings': {
647
+ if (!ionToken) return;
648
+ const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(96188);
649
+ viewer.scene.primitives.add(tileset);
650
+ break;
651
+ }
652
+ case 'google-photorealistic': {
653
+ try {
654
+ const tileset = await Cesium.createGooglePhotorealistic3DTileset();
655
+ viewer.scene.primitives.add(tileset);
656
+ } catch {
657
+ if (ionToken) {
658
+ const tileset = await Cesium.Cesium3DTileset.fromIonAssetId(2275207);
659
+ viewer.scene.primitives.add(tileset);
660
+ }
661
+ }
662
+ break;
663
+ }
664
+ case 'bing-aerial':
665
+ default:
666
+ // No 3D tileset for Bing — imagery is added separately via imageryLayers
667
+ break;
668
+ }
669
+ } catch (err) {
670
+ console.warn('[CesiumOverlay] Failed to add data source:', dataSource, err);
671
+ }
672
+ }