@ifc-lite/viewer 1.17.2 → 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.
- package/.turbo/turbo-build.log +34 -24
- package/.turbo/turbo-typecheck.log +1 -42
- package/CHANGELOG.md +24 -0
- package/DESKTOP_CONTRACT_VERSION +1 -0
- package/dist/assets/arrow-CZ5kQ26f.js +20 -0
- package/dist/assets/basketViewActivator-BmnNtVfZ.js +1 -0
- package/dist/assets/bcf-DOG9_WPX.js +281 -0
- package/dist/assets/{browser-BDShTXzi.js → browser-C5TFR7sH.js} +1 -1
- package/dist/assets/cesium-ADbP7waU.css +1 -0
- package/dist/assets/cesium-DUOzBlqv.js +17817 -0
- package/dist/assets/drawing-2d-gWfpdfYe.js +257 -0
- package/dist/assets/epsg-index.generated-BjJrt_0S.js +1 -0
- package/dist/assets/exporters-ChAtBmlj.js +80367 -0
- package/dist/assets/geometry.worker-BQ0rzNo-.js +1 -0
- package/dist/assets/ids-B4jTqB1O.js +1 -0
- package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
- package/dist/assets/index-Co8E2-FE.js +106013 -0
- package/dist/assets/index-DckuDqlv.css +1 -0
- package/dist/assets/lens-CSASnhAL.js +1 -0
- package/dist/assets/maplibre-gl-CGLcoNXc.js +811 -0
- package/dist/assets/native-bridge-BRvbckFQ.js +429 -0
- package/dist/assets/{arrow2-bb-jcVEo.js → parquet-CEXmQNRO.js} +2 -2
- package/dist/assets/sandbox-DZiNLNMk.js +5933 -0
- package/dist/assets/server-client-BV8zHZ7Y.js +626 -0
- package/dist/assets/tauri-core-stub-D8Fa-u43.js +1 -0
- package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +1 -0
- package/dist/assets/tauri-fs-stub-BdeRC7aK.js +1 -0
- package/dist/assets/wasm-bridge-g01g7T9b.js +1 -0
- package/dist/assets/zip-DBEtpeu6.js +12 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json +1 -0
- package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json +1 -0
- package/dist/cesium/Assets/Images/bing_maps_credit.png +0 -0
- package/dist/cesium/Assets/Images/cesium_credit.png +0 -0
- package/dist/cesium/Assets/Images/google_earth_credit.png +0 -0
- package/dist/cesium/Assets/Images/ion-credit.png +0 -0
- package/dist/cesium/Assets/Textures/LensFlare/DirtMask.jpg +0 -0
- package/dist/cesium/Assets/Textures/LensFlare/StarBurst.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/0/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/0/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/0.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/1.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/2.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/3.jpg +0 -0
- package/dist/cesium/Assets/Textures/NaturalEarthII/tilemapresource.xml +14 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg +0 -0
- package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg +0 -0
- package/dist/cesium/Assets/Textures/maki/airfield.png +0 -0
- package/dist/cesium/Assets/Textures/maki/airport.png +0 -0
- package/dist/cesium/Assets/Textures/maki/alcohol-shop.png +0 -0
- package/dist/cesium/Assets/Textures/maki/america-football.png +0 -0
- package/dist/cesium/Assets/Textures/maki/art-gallery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bakery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bank.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bar.png +0 -0
- package/dist/cesium/Assets/Textures/maki/baseball.png +0 -0
- package/dist/cesium/Assets/Textures/maki/basketball.png +0 -0
- package/dist/cesium/Assets/Textures/maki/beer.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bicycle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/building.png +0 -0
- package/dist/cesium/Assets/Textures/maki/bus.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cafe.png +0 -0
- package/dist/cesium/Assets/Textures/maki/camera.png +0 -0
- package/dist/cesium/Assets/Textures/maki/campsite.png +0 -0
- package/dist/cesium/Assets/Textures/maki/car.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cemetery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cesium.png +0 -0
- package/dist/cesium/Assets/Textures/maki/chemist.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cinema.png +0 -0
- package/dist/cesium/Assets/Textures/maki/circle-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/circle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/city.png +0 -0
- package/dist/cesium/Assets/Textures/maki/clothing-store.png +0 -0
- package/dist/cesium/Assets/Textures/maki/college.png +0 -0
- package/dist/cesium/Assets/Textures/maki/commercial.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cricket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/cross.png +0 -0
- package/dist/cesium/Assets/Textures/maki/dam.png +0 -0
- package/dist/cesium/Assets/Textures/maki/danger.png +0 -0
- package/dist/cesium/Assets/Textures/maki/disability.png +0 -0
- package/dist/cesium/Assets/Textures/maki/dog-park.png +0 -0
- package/dist/cesium/Assets/Textures/maki/embassy.png +0 -0
- package/dist/cesium/Assets/Textures/maki/emergency-telephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/entrance.png +0 -0
- package/dist/cesium/Assets/Textures/maki/farm.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fast-food.png +0 -0
- package/dist/cesium/Assets/Textures/maki/ferry.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fire-station.png +0 -0
- package/dist/cesium/Assets/Textures/maki/fuel.png +0 -0
- package/dist/cesium/Assets/Textures/maki/garden.png +0 -0
- package/dist/cesium/Assets/Textures/maki/gift.png +0 -0
- package/dist/cesium/Assets/Textures/maki/golf.png +0 -0
- package/dist/cesium/Assets/Textures/maki/grocery.png +0 -0
- package/dist/cesium/Assets/Textures/maki/hairdresser.png +0 -0
- package/dist/cesium/Assets/Textures/maki/harbor.png +0 -0
- package/dist/cesium/Assets/Textures/maki/heart.png +0 -0
- package/dist/cesium/Assets/Textures/maki/heliport.png +0 -0
- package/dist/cesium/Assets/Textures/maki/hospital.png +0 -0
- package/dist/cesium/Assets/Textures/maki/ice-cream.png +0 -0
- package/dist/cesium/Assets/Textures/maki/industrial.png +0 -0
- package/dist/cesium/Assets/Textures/maki/land-use.png +0 -0
- package/dist/cesium/Assets/Textures/maki/laundry.png +0 -0
- package/dist/cesium/Assets/Textures/maki/library.png +0 -0
- package/dist/cesium/Assets/Textures/maki/lighthouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/lodging.png +0 -0
- package/dist/cesium/Assets/Textures/maki/logging.png +0 -0
- package/dist/cesium/Assets/Textures/maki/london-underground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/marker-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/marker.png +0 -0
- package/dist/cesium/Assets/Textures/maki/minefield.png +0 -0
- package/dist/cesium/Assets/Textures/maki/mobilephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/monument.png +0 -0
- package/dist/cesium/Assets/Textures/maki/museum.png +0 -0
- package/dist/cesium/Assets/Textures/maki/music.png +0 -0
- package/dist/cesium/Assets/Textures/maki/oil-well.png +0 -0
- package/dist/cesium/Assets/Textures/maki/park.png +0 -0
- package/dist/cesium/Assets/Textures/maki/park2.png +0 -0
- package/dist/cesium/Assets/Textures/maki/parking-garage.png +0 -0
- package/dist/cesium/Assets/Textures/maki/parking.png +0 -0
- package/dist/cesium/Assets/Textures/maki/pharmacy.png +0 -0
- package/dist/cesium/Assets/Textures/maki/pitch.png +0 -0
- package/dist/cesium/Assets/Textures/maki/place-of-worship.png +0 -0
- package/dist/cesium/Assets/Textures/maki/playground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/police.png +0 -0
- package/dist/cesium/Assets/Textures/maki/polling-place.png +0 -0
- package/dist/cesium/Assets/Textures/maki/post.png +0 -0
- package/dist/cesium/Assets/Textures/maki/prison.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-above.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-light.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-metro.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail-underground.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rail.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-christian.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-jewish.png +0 -0
- package/dist/cesium/Assets/Textures/maki/religious-muslim.png +0 -0
- package/dist/cesium/Assets/Textures/maki/restaurant.png +0 -0
- package/dist/cesium/Assets/Textures/maki/roadblock.png +0 -0
- package/dist/cesium/Assets/Textures/maki/rocket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/school.png +0 -0
- package/dist/cesium/Assets/Textures/maki/scooter.png +0 -0
- package/dist/cesium/Assets/Textures/maki/shop.png +0 -0
- package/dist/cesium/Assets/Textures/maki/skiing.png +0 -0
- package/dist/cesium/Assets/Textures/maki/slaughterhouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/soccer.png +0 -0
- package/dist/cesium/Assets/Textures/maki/square-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/square.png +0 -0
- package/dist/cesium/Assets/Textures/maki/star-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/star.png +0 -0
- package/dist/cesium/Assets/Textures/maki/suitcase.png +0 -0
- package/dist/cesium/Assets/Textures/maki/swimming.png +0 -0
- package/dist/cesium/Assets/Textures/maki/telephone.png +0 -0
- package/dist/cesium/Assets/Textures/maki/tennis.png +0 -0
- package/dist/cesium/Assets/Textures/maki/theatre.png +0 -0
- package/dist/cesium/Assets/Textures/maki/toilets.png +0 -0
- package/dist/cesium/Assets/Textures/maki/town-hall.png +0 -0
- package/dist/cesium/Assets/Textures/maki/town.png +0 -0
- package/dist/cesium/Assets/Textures/maki/triangle-stroked.png +0 -0
- package/dist/cesium/Assets/Textures/maki/triangle.png +0 -0
- package/dist/cesium/Assets/Textures/maki/village.png +0 -0
- package/dist/cesium/Assets/Textures/maki/warehouse.png +0 -0
- package/dist/cesium/Assets/Textures/maki/waste-basket.png +0 -0
- package/dist/cesium/Assets/Textures/maki/water.png +0 -0
- package/dist/cesium/Assets/Textures/maki/wetland.png +0 -0
- package/dist/cesium/Assets/Textures/maki/zoo.png +0 -0
- package/dist/cesium/Assets/Textures/moonSmall.jpg +0 -0
- package/dist/cesium/Assets/Textures/pin.svg +1 -0
- package/dist/cesium/Assets/Textures/waterNormals.jpg +0 -0
- package/dist/cesium/Assets/Textures/waterNormalsSmall.jpg +0 -0
- package/dist/cesium/Assets/approximateTerrainHeights.json +1 -0
- package/dist/cesium/ThirdParty/Workers/package.json +1 -0
- package/dist/cesium/ThirdParty/Workers/zip-web-worker.js +1 -0
- package/dist/cesium/ThirdParty/basis_transcoder.wasm +0 -0
- package/dist/cesium/ThirdParty/draco_decoder.wasm +0 -0
- package/dist/cesium/ThirdParty/google-earth-dbroot-parser.js +1 -0
- package/dist/cesium/ThirdParty/wasm_splats_bg.wasm +0 -0
- package/dist/cesium/ThirdParty/zip-module.wasm +0 -0
- package/dist/cesium/Widgets/Animation/Animation.css +127 -0
- package/dist/cesium/Widgets/Animation/lighter.css +70 -0
- package/dist/cesium/Widgets/BaseLayerPicker/BaseLayerPicker.css +108 -0
- package/dist/cesium/Widgets/BaseLayerPicker/lighter.css +22 -0
- package/dist/cesium/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.css +102 -0
- package/dist/cesium/Widgets/CesiumInspector/CesiumInspector.css +113 -0
- package/dist/cesium/Widgets/CesiumWidget/CesiumWidget.css +119 -0
- package/dist/cesium/Widgets/CesiumWidget/lighter.css +14 -0
- package/dist/cesium/Widgets/FullscreenButton/FullscreenButton.css +8 -0
- package/dist/cesium/Widgets/Geocoder/Geocoder.css +70 -0
- package/dist/cesium/Widgets/Geocoder/lighter.css +17 -0
- package/dist/cesium/Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorer.css +27 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldHillshade.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldImagery.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldOcean.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/azureAerial.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/azureRoads.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingAerial.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingAerialLabels.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/bingRoads.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/blueMarble.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/earthAtNight.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleContour.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleRoadmap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleSatellite.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/googleSatelliteLabels.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxSatellite.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxStreets.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/mapboxTerrain.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/naturalEarthII.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/openStreetMap.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/sentinel-2.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmooth.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmoothDark.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stamenToner.png +0 -0
- package/dist/cesium/Widgets/Images/ImageryProviders/stamenWatercolor.png +0 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/Mouse.svg +84 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseLeft.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseMiddle.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/MouseRight.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/Touch.svg +120 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchDrag.svg +129 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchRotate.svg +76 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchTilt.svg +135 -0
- package/dist/cesium/Widgets/Images/NavigationHelp/TouchZoom.svg +74 -0
- package/dist/cesium/Widgets/Images/TerrainProviders/CesiumWorldTerrain.png +0 -0
- package/dist/cesium/Widgets/Images/TerrainProviders/Ellipsoid.png +0 -0
- package/dist/cesium/Widgets/Images/TimelineIcons.png +0 -0
- package/dist/cesium/Widgets/Images/info-loading.gif +0 -0
- package/dist/cesium/Widgets/InfoBox/InfoBox.css +92 -0
- package/dist/cesium/Widgets/InfoBox/InfoBoxDescription.css +178 -0
- package/dist/cesium/Widgets/NavigationHelpButton/NavigationHelpButton.css +93 -0
- package/dist/cesium/Widgets/NavigationHelpButton/lighter.css +38 -0
- package/dist/cesium/Widgets/PerformanceWatchdog/PerformanceWatchdog.css +15 -0
- package/dist/cesium/Widgets/ProjectionPicker/ProjectionPicker.css +38 -0
- package/dist/cesium/Widgets/SceneModePicker/SceneModePicker.css +56 -0
- package/dist/cesium/Widgets/SelectionIndicator/SelectionIndicator.css +20 -0
- package/dist/cesium/Widgets/Timeline/Timeline.css +103 -0
- package/dist/cesium/Widgets/Timeline/lighter.css +23 -0
- package/dist/cesium/Widgets/VRButton/VRButton.css +8 -0
- package/dist/cesium/Widgets/Viewer/Viewer.css +107 -0
- package/dist/cesium/Widgets/VoxelInspector/VoxelInspector.css +16 -0
- package/dist/cesium/Widgets/lighter.css +237 -0
- package/dist/cesium/Widgets/lighterShared.css +46 -0
- package/dist/cesium/Widgets/shared.css +103 -0
- package/dist/cesium/Widgets/widgets.css +1342 -0
- package/dist/cesium/Workers/chunk-23ZQ2IVV.js +29 -0
- package/dist/cesium/Workers/chunk-2EQO3Q56.js +26 -0
- package/dist/cesium/Workers/chunk-2MJIIVP4.js +26 -0
- package/dist/cesium/Workers/chunk-2TE5NTVD.js +26 -0
- package/dist/cesium/Workers/chunk-2ZBHLJST.js +26 -0
- package/dist/cesium/Workers/chunk-5TJMAQVL.js +26 -0
- package/dist/cesium/Workers/chunk-6BD4U3VO.js +26 -0
- package/dist/cesium/Workers/chunk-7TVGLKQF.js +26 -0
- package/dist/cesium/Workers/chunk-BTSYJ5XU.js +26 -0
- package/dist/cesium/Workers/chunk-BXMEEOCS.js +63 -0
- package/dist/cesium/Workers/chunk-BYLCY7GP.js +29 -0
- package/dist/cesium/Workers/chunk-CTHM3W6I.js +26 -0
- package/dist/cesium/Workers/chunk-CUUSNIVQ.js +26 -0
- package/dist/cesium/Workers/chunk-E3JOOS3S.js +26 -0
- package/dist/cesium/Workers/chunk-E7KYDCM5.js +26 -0
- package/dist/cesium/Workers/chunk-EDVBB7SS.js +27 -0
- package/dist/cesium/Workers/chunk-EFBN7QNX.js +26 -0
- package/dist/cesium/Workers/chunk-EQ4YRVWL.js +26 -0
- package/dist/cesium/Workers/chunk-F6PRE7D6.js +26 -0
- package/dist/cesium/Workers/chunk-FC4ZZ65J.js +26 -0
- package/dist/cesium/Workers/chunk-FFBVWF2L.js +26 -0
- package/dist/cesium/Workers/chunk-GBAA6GVX.js +26 -0
- package/dist/cesium/Workers/chunk-ICALLYLG.js +26 -0
- package/dist/cesium/Workers/chunk-ILRYTWTP.js +26 -0
- package/dist/cesium/Workers/chunk-IRNLBSEJ.js +26 -0
- package/dist/cesium/Workers/chunk-IX4VMHEV.js +26 -0
- package/dist/cesium/Workers/chunk-L6QHHACZ.js +26 -0
- package/dist/cesium/Workers/chunk-LI2ZSORM.js +26 -0
- package/dist/cesium/Workers/chunk-LSLE2RL4.js +26 -0
- package/dist/cesium/Workers/chunk-M4HLDBCG.js +26 -0
- package/dist/cesium/Workers/chunk-MJHHSGEH.js +26 -0
- package/dist/cesium/Workers/chunk-NMVKML6W.js +26 -0
- package/dist/cesium/Workers/chunk-OCWJRAXS.js +26 -0
- package/dist/cesium/Workers/chunk-OIRKANTH.js +26 -0
- package/dist/cesium/Workers/chunk-OIT7J4IC.js +26 -0
- package/dist/cesium/Workers/chunk-OLZ3FYUM.js +26 -0
- package/dist/cesium/Workers/chunk-Q5BPHJQF.js +26 -0
- package/dist/cesium/Workers/chunk-QFM5DCMQ.js +26 -0
- package/dist/cesium/Workers/chunk-QKUIYMGC.js +28 -0
- package/dist/cesium/Workers/chunk-S44JILQT.js +26 -0
- package/dist/cesium/Workers/chunk-SLT4J352.js +26 -0
- package/dist/cesium/Workers/chunk-SQMIIXB7.js +26 -0
- package/dist/cesium/Workers/chunk-TJ4XLGBQ.js +26 -0
- package/dist/cesium/Workers/chunk-TNSUQXWK.js +27 -0
- package/dist/cesium/Workers/chunk-UBOGZS7F.js +26 -0
- package/dist/cesium/Workers/chunk-V3OSTMM6.js +26 -0
- package/dist/cesium/Workers/chunk-V7QEYVP3.js +26 -0
- package/dist/cesium/Workers/chunk-VUKYSU4H.js +26 -0
- package/dist/cesium/Workers/chunk-W37FE5GR.js +26 -0
- package/dist/cesium/Workers/chunk-WBOV35NL.js +26 -0
- package/dist/cesium/Workers/chunk-WPMZLB3Y.js +26 -0
- package/dist/cesium/Workers/chunk-WWWZVEEH.js +26 -0
- package/dist/cesium/Workers/chunk-XFIQ5DEQ.js +28 -0
- package/dist/cesium/Workers/chunk-XQHLGIO7.js +26 -0
- package/dist/cesium/Workers/chunk-XUSCFAVF.js +26 -0
- package/dist/cesium/Workers/chunk-YP7I5QBZ.js +26 -0
- package/dist/cesium/Workers/chunk-Z3QF2EHT.js +26 -0
- package/dist/cesium/Workers/combineGeometry.js +26 -0
- package/dist/cesium/Workers/createBoxGeometry.js +26 -0
- package/dist/cesium/Workers/createBoxOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCircleGeometry.js +26 -0
- package/dist/cesium/Workers/createCircleOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCoplanarPolygonGeometry.js +26 -0
- package/dist/cesium/Workers/createCoplanarPolygonOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCorridorGeometry.js +26 -0
- package/dist/cesium/Workers/createCorridorOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createCylinderGeometry.js +26 -0
- package/dist/cesium/Workers/createCylinderOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipseGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipseOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipsoidGeometry.js +26 -0
- package/dist/cesium/Workers/createEllipsoidOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createFrustumGeometry.js +26 -0
- package/dist/cesium/Workers/createFrustumOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createGeometry.js +26 -0
- package/dist/cesium/Workers/createGroundPolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createPlaneGeometry.js +26 -0
- package/dist/cesium/Workers/createPlaneOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolygonGeometry.js +26 -0
- package/dist/cesium/Workers/createPolygonOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineVolumeGeometry.js +26 -0
- package/dist/cesium/Workers/createPolylineVolumeOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createRectangleGeometry.js +26 -0
- package/dist/cesium/Workers/createRectangleOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createSimplePolylineGeometry.js +26 -0
- package/dist/cesium/Workers/createSphereGeometry.js +26 -0
- package/dist/cesium/Workers/createSphereOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/createTaskProcessorWorker.js +26 -0
- package/dist/cesium/Workers/createVectorTileClampedPolylines.js +26 -0
- package/dist/cesium/Workers/createVectorTileGeometries.js +26 -0
- package/dist/cesium/Workers/createVectorTilePoints.js +26 -0
- package/dist/cesium/Workers/createVectorTilePolygons.js +26 -0
- package/dist/cesium/Workers/createVectorTilePolylines.js +26 -0
- package/dist/cesium/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -0
- package/dist/cesium/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -0
- package/dist/cesium/Workers/createVerticesFromHeightmap.js +26 -0
- package/dist/cesium/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -0
- package/dist/cesium/Workers/createWallGeometry.js +26 -0
- package/dist/cesium/Workers/createWallOutlineGeometry.js +26 -0
- package/dist/cesium/Workers/decodeDraco.js +26 -0
- package/dist/cesium/Workers/decodeGoogleEarthEnterprisePacket.js +26 -0
- package/dist/cesium/Workers/decodeI3S.js +26 -0
- package/dist/cesium/Workers/gaussianSplatSorter.js +26 -0
- package/dist/cesium/Workers/gaussianSplatTextureGenerator.js +26 -0
- package/dist/cesium/Workers/incrementallyBuildTerrainPicker.js +26 -0
- package/dist/cesium/Workers/transcodeKTX2.js +56 -0
- package/dist/cesium/Workers/transferTypedArrayTest.js +26 -0
- package/dist/cesium/Workers/upsampleQuantizedTerrainMesh.js +26 -0
- package/dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -0
- package/dist/index.html +13 -2
- package/package.json +27 -19
- package/src/App.tsx +1 -17
- package/src/components/viewer/BCFPanel.tsx +46 -4
- package/src/components/viewer/CesiumOverlay.tsx +672 -0
- package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
- package/src/components/viewer/ChatPanel.tsx +54 -16
- package/src/components/viewer/CommandPalette.tsx +6 -1
- package/src/components/viewer/DesktopEntitlementBanner.tsx +74 -0
- package/src/components/viewer/ExportChangesButton.tsx +24 -4
- package/src/components/viewer/ExportDialog.tsx +38 -9
- package/src/components/viewer/HierarchyPanel.tsx +202 -6
- package/src/components/viewer/IDSPanel.tsx +52 -3
- package/src/components/viewer/KeyboardShortcutsDialog.tsx +1 -1
- package/src/components/viewer/MainToolbar.tsx +353 -27
- package/src/components/viewer/PropertiesPanel.tsx +306 -131
- package/src/components/viewer/ScriptPanel.tsx +34 -8
- package/src/components/viewer/Section2DPanel.tsx +3 -2
- package/src/components/viewer/SettingsPage.tsx +430 -0
- package/src/components/viewer/StatusBar.tsx +17 -1
- package/src/components/viewer/UpgradePage.tsx +6 -4
- package/src/components/viewer/ViewerLayout.tsx +47 -6
- package/src/components/viewer/Viewport.tsx +49 -8
- package/src/components/viewer/ViewportContainer.tsx +285 -32
- package/src/components/viewer/ViewportOverlays.tsx +129 -27
- package/src/components/viewer/hierarchy/treeDataBuilder.ts +2 -1
- package/src/components/viewer/properties/EpsgLookupDialog.tsx +418 -0
- package/src/components/viewer/properties/GeoreferencingPanel.tsx +703 -0
- package/src/components/viewer/properties/LocationMap.tsx +730 -0
- package/src/components/viewer/properties/ModelMetadataPanel.tsx +3 -70
- package/src/components/viewer/selectionHandlers.ts +4 -3
- package/src/components/viewer/useAnimationLoop.ts +4 -0
- package/src/components/viewer/useGeometryStreaming.ts +127 -40
- package/src/components/viewer/useMouseControls.ts +4 -1
- package/src/hooks/bcfIdLookup.ts +13 -11
- package/src/hooks/ids/idsColorSystem.ts +3 -8
- package/src/hooks/ingest/viewerModelIngest.ts +275 -0
- package/src/hooks/useIDS.ts +32 -17
- package/src/hooks/useIfc.ts +7 -1
- package/src/hooks/useIfcCache.ts +28 -15
- package/src/hooks/useIfcFederation.ts +59 -227
- package/src/hooks/useIfcLoader.ts +1656 -130
- package/src/hooks/useIfcServer.ts +0 -69
- package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +175 -0
- package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
- package/src/lib/desktop-entitlement.ts +45 -0
- package/src/lib/desktop-product.ts +124 -0
- package/src/lib/geo/cesium-bridge.ts +310 -0
- package/src/lib/geo/kmz-exporter.ts +112 -0
- package/src/lib/geo/reproject.ts +370 -0
- package/src/lib/lens/adapter.ts +3 -1
- package/src/lib/recent-files.ts +2 -1
- package/src/main.tsx +1 -0
- package/src/sdk/adapters/export-adapter.ts +14 -1
- package/src/sdk/adapters/viewer-adapter.ts +5 -9
- package/src/sdk/adapters/visibility-adapter.ts +6 -9
- package/src/services/analysis-extensions.ts +125 -0
- package/src/services/app-navigation.ts +13 -0
- package/src/services/bsdd.ts +53 -4
- package/src/services/cacheService.ts +1 -1
- package/src/services/desktop-cache.ts +43 -0
- package/src/services/desktop-export.ts +77 -0
- package/src/services/desktop-harness.ts +196 -0
- package/src/services/desktop-logger.ts +20 -0
- package/src/services/desktop-native-metadata.ts +207 -0
- package/src/services/desktop-panel-actions.ts +43 -0
- package/src/services/desktop-preferences.ts +44 -0
- package/src/services/file-dialog.ts +147 -0
- package/src/services/tauri-core-stub.ts +7 -0
- package/src/services/tauri-dialog-stub.ts +7 -0
- package/src/services/tauri-fs-stub.ts +7 -0
- package/src/store/basketVisibleSet.ts +3 -4
- package/src/store/globalId.ts +79 -0
- package/src/store/index.ts +41 -2
- package/src/store/slices/cesiumSlice.ts +122 -0
- package/src/store/slices/chatSlice.ts +5 -1
- package/src/store/slices/dataSlice.ts +139 -28
- package/src/store/slices/desktopEntitlementSlice.ts +86 -0
- package/src/store/slices/loadingSlice.ts +14 -2
- package/src/store/slices/modelSlice.ts +58 -3
- package/src/store/slices/mutationSlice.ts +178 -0
- package/src/store/slices/pinboardSlice.ts +4 -8
- package/src/store/types.ts +96 -2
- package/src/store.ts +1 -1
- package/src/utils/desktopModelSnapshot.ts +358 -0
- package/src/utils/ifcConfig.ts +6 -1
- package/src/utils/nativeSpatialDataStore.ts +250 -0
- package/src/utils/serverDataModel.ts +4 -0
- package/src/utils/spatialHierarchy.ts +10 -11
- package/vite.config.ts +41 -0
- package/dist/assets/Arrow.dom-BhOg9lpn.js +0 -20
- package/dist/assets/arrow2_bg-BlXl-cSQ.js +0 -1
- package/dist/assets/basketViewActivator-BRG5DBmM.js +0 -1
- package/dist/assets/desktop-cache-oPzaWXYE.js +0 -1
- package/dist/assets/geometry.worker-kgiT_Qhh.js +0 -1
- package/dist/assets/ifc-lite_bg-FNRmpSvM.wasm +0 -0
- package/dist/assets/index-B1Ecw4AU.js +0 -189756
- package/dist/assets/index-Ba4eoTe7.css +0 -1
- package/dist/assets/index-CrgYBjTn.js +0 -229
- package/dist/assets/module-6F3E5H7Y-tx0BadV3.js +0 -6
- package/dist/assets/native-bridge-Crsb7TKz.js +0 -111
- package/dist/assets/wasm-bridge-mJUhb7uk.js +0 -1
|
@@ -2,19 +2,26 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
|
|
5
|
-
import { useMemo, useRef, useState, useCallback } from 'react';
|
|
5
|
+
import { useMemo, useRef, useState, useCallback, useEffect, useSyncExternalStore } from 'react';
|
|
6
6
|
import { Viewport } from './Viewport';
|
|
7
7
|
import { ViewportOverlays } from './ViewportOverlays';
|
|
8
8
|
import { ToolOverlays } from './ToolOverlays';
|
|
9
9
|
import { Section2DPanel } from './Section2DPanel';
|
|
10
10
|
import { BasketPresentationDock } from './BasketPresentationDock';
|
|
11
11
|
import { BCFOverlay } from './bcf/BCFOverlay';
|
|
12
|
-
import {
|
|
12
|
+
import { CesiumOverlay } from './CesiumOverlay';
|
|
13
|
+
import { getViewerStoreApi, useViewerStore } from '@/store';
|
|
14
|
+
import { toGlobalIdFromModels } from '@/store/globalId';
|
|
13
15
|
import { collectIfcBuildingStoreyElementsWithIfcSpace } from '@/store/basketVisibleSet';
|
|
14
16
|
import { useIfc } from '@/hooks/useIfc';
|
|
15
17
|
import { useWebGPU } from '@/hooks/useWebGPU';
|
|
16
|
-
import {
|
|
18
|
+
import { openIfcFileDialog } from '@/services/file-dialog';
|
|
19
|
+
import { logToDesktopTerminal } from '@/services/desktop-logger';
|
|
20
|
+
import { cacheFileBlobs, formatFileSize, getCachedFile, getRecentFiles, recordRecentFiles, type RecentFileEntry } from '@/lib/recent-files';
|
|
21
|
+
import { isTauri } from '@/utils/ifcConfig';
|
|
22
|
+
import { Upload, MousePointer, Layers, Info, Command, AlertTriangle, ChevronDown, ExternalLink, Plus, Clock3 } from 'lucide-react';
|
|
17
23
|
import type { MeshData, CoordinateInfo, GeometryResult } from '@ifc-lite/geometry';
|
|
24
|
+
import { extractGeoreferencingOnDemand, type IfcDataStore, type MapConversion, type ProjectedCRS } from '@ifc-lite/parser';
|
|
18
25
|
|
|
19
26
|
const ZERO_VEC3 = { x: 0, y: 0, z: 0 };
|
|
20
27
|
const DEFAULT_COORDINATE_INFO: CoordinateInfo = {
|
|
@@ -25,20 +32,41 @@ const DEFAULT_COORDINATE_INFO: CoordinateInfo = {
|
|
|
25
32
|
};
|
|
26
33
|
|
|
27
34
|
export function ViewportContainer() {
|
|
28
|
-
const {
|
|
35
|
+
const { loadFile, loading, clearAllModels, loadFilesSequentially } = useIfc();
|
|
36
|
+
const releaseGeometryMemory = useViewerStore((s) => s.releaseGeometryMemory);
|
|
29
37
|
const selectedStoreys = useViewerStore((s) => s.selectedStoreys);
|
|
30
38
|
const typeVisibility = useViewerStore((s) => s.typeVisibility);
|
|
31
39
|
const isolatedEntities = useViewerStore((s) => s.isolatedEntities);
|
|
32
40
|
const classFilter = useViewerStore((s) => s.classFilter);
|
|
33
|
-
// Multi-model support: get all loaded models from store (for merged geometry)
|
|
34
|
-
const storeModels = useViewerStore((s) => s.models);
|
|
35
41
|
const resetViewerState = useViewerStore((s) => s.resetViewerState);
|
|
36
42
|
const bcfOverlayVisible = useViewerStore((s) => s.bcfOverlayVisible);
|
|
43
|
+
const cesiumEnabled = useViewerStore((s) => s.cesiumEnabled);
|
|
44
|
+
const georefMutations = useViewerStore((s) => s.georefMutations);
|
|
45
|
+
const setCesiumSourceModelId = useViewerStore((s) => s.setCesiumSourceModelId);
|
|
46
|
+
// Subscribe to mutationVersion so Cesium reacts to georef edits
|
|
47
|
+
const mutationVersion = useViewerStore((s) => s.mutationVersion);
|
|
37
48
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
38
49
|
const [isDragging, setIsDragging] = useState(false);
|
|
39
50
|
const [showTroubleshooting, setShowTroubleshooting] = useState(false);
|
|
51
|
+
const [recentFiles, setRecentFiles] = useState<RecentFileEntry[]>([]);
|
|
40
52
|
const webgpu = useWebGPU();
|
|
41
53
|
|
|
54
|
+
const viewerStoreApi = getViewerStoreApi();
|
|
55
|
+
const viewportStoreState = useSyncExternalStore(
|
|
56
|
+
viewerStoreApi.subscribe,
|
|
57
|
+
viewerStoreApi.getState,
|
|
58
|
+
viewerStoreApi.getState,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
const {
|
|
62
|
+
geometryResult,
|
|
63
|
+
ifcDataStore,
|
|
64
|
+
models,
|
|
65
|
+
boundedGeometryMode,
|
|
66
|
+
geometryUpdateTick,
|
|
67
|
+
} = viewportStoreState;
|
|
68
|
+
const storeModels = models;
|
|
69
|
+
|
|
42
70
|
// Check if we have models loaded (for determining add vs replace behavior)
|
|
43
71
|
const hasModelsLoaded = models.size > 0 || (geometryResult?.meshes && geometryResult.meshes.length > 0);
|
|
44
72
|
|
|
@@ -52,39 +80,87 @@ export function ViewportContainer() {
|
|
|
52
80
|
return map;
|
|
53
81
|
}, [storeModels]);
|
|
54
82
|
|
|
83
|
+
const mergedCacheRef = useRef<MeshData[]>([]);
|
|
84
|
+
const mergedLengthsRef = useRef<Map<string, number>>(new Map());
|
|
85
|
+
const mergedVisibilityRef = useRef<Map<string, boolean>>(new Map());
|
|
86
|
+
|
|
55
87
|
// Multi-model: merge geometries from all visible models
|
|
56
88
|
const mergedGeometryResult = useMemo(() => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
89
|
+
if (storeModels.size === 1) {
|
|
90
|
+
const firstModel = storeModels.values().next().value;
|
|
91
|
+
if (!firstModel?.visible) {
|
|
92
|
+
return {
|
|
93
|
+
meshes: [],
|
|
94
|
+
totalVertices: 0,
|
|
95
|
+
totalTriangles: 0,
|
|
96
|
+
coordinateInfo: DEFAULT_COORDINATE_INFO,
|
|
97
|
+
} satisfies GeometryResult;
|
|
98
|
+
}
|
|
99
|
+
return firstModel.geometryResult ?? geometryResult;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (storeModels.size > 1) {
|
|
60
103
|
let totalVertices = 0;
|
|
61
104
|
let totalTriangles = 0;
|
|
62
105
|
let mergedCoordinateInfo: CoordinateInfo | undefined;
|
|
106
|
+
let shouldRebuild = false;
|
|
63
107
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
108
|
+
if (mergedLengthsRef.current.size !== storeModels.size) {
|
|
109
|
+
shouldRebuild = true;
|
|
110
|
+
}
|
|
67
111
|
|
|
112
|
+
for (const [modelId, model] of storeModels) {
|
|
68
113
|
const modelGeometry = model.geometryResult;
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
114
|
+
const meshCount = model.visible ? (modelGeometry?.meshes.length ?? 0) : 0;
|
|
115
|
+
totalVertices += model.visible ? (modelGeometry?.totalVertices ?? 0) : 0;
|
|
116
|
+
totalTriangles += model.visible ? (modelGeometry?.totalTriangles ?? 0) : 0;
|
|
117
|
+
if (!mergedCoordinateInfo && model.visible && modelGeometry?.coordinateInfo) {
|
|
118
|
+
mergedCoordinateInfo = modelGeometry.coordinateInfo;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (
|
|
122
|
+
mergedVisibilityRef.current.get(modelId) !== model.visible ||
|
|
123
|
+
(mergedLengthsRef.current.get(modelId) ?? 0) > meshCount
|
|
124
|
+
) {
|
|
125
|
+
shouldRebuild = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (shouldRebuild) {
|
|
130
|
+
const rebuilt: MeshData[] = [];
|
|
131
|
+
mergedLengthsRef.current = new Map();
|
|
132
|
+
mergedVisibilityRef.current = new Map();
|
|
133
|
+
for (const [modelId, model] of storeModels) {
|
|
134
|
+
const modelGeometry = model.geometryResult;
|
|
135
|
+
mergedVisibilityRef.current.set(modelId, model.visible);
|
|
136
|
+
const modelIndex = modelIdToIndex.get(modelId) ?? 0;
|
|
137
|
+
if (!model.visible || !modelGeometry?.meshes) {
|
|
138
|
+
mergedLengthsRef.current.set(modelId, 0);
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
72
141
|
for (const mesh of modelGeometry.meshes) {
|
|
73
|
-
|
|
142
|
+
rebuilt.push({ ...mesh, modelIndex });
|
|
74
143
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
144
|
+
mergedLengthsRef.current.set(modelId, modelGeometry.meshes.length);
|
|
145
|
+
}
|
|
146
|
+
mergedCacheRef.current = rebuilt;
|
|
147
|
+
} else {
|
|
148
|
+
for (const [modelId, model] of storeModels) {
|
|
149
|
+
const modelGeometry = model.geometryResult;
|
|
150
|
+
const modelIndex = modelIdToIndex.get(modelId) ?? 0;
|
|
151
|
+
const previousLength = mergedLengthsRef.current.get(modelId) ?? 0;
|
|
152
|
+
const nextMeshes = model.visible ? (modelGeometry?.meshes ?? []) : [];
|
|
153
|
+
for (let i = previousLength; i < nextMeshes.length; i++) {
|
|
154
|
+
const mesh = nextMeshes[i];
|
|
155
|
+
mergedCacheRef.current.push({ ...mesh, modelIndex });
|
|
81
156
|
}
|
|
157
|
+
mergedLengthsRef.current.set(modelId, nextMeshes.length);
|
|
158
|
+
mergedVisibilityRef.current.set(modelId, model.visible);
|
|
82
159
|
}
|
|
83
160
|
}
|
|
84
161
|
|
|
85
|
-
// Return merged result (may be empty if all models hidden)
|
|
86
162
|
return {
|
|
87
|
-
meshes:
|
|
163
|
+
meshes: mergedCacheRef.current,
|
|
88
164
|
totalVertices,
|
|
89
165
|
totalTriangles,
|
|
90
166
|
coordinateInfo: mergedCoordinateInfo ?? DEFAULT_COORDINATE_INFO,
|
|
@@ -95,6 +171,106 @@ export function ViewportContainer() {
|
|
|
95
171
|
return geometryResult;
|
|
96
172
|
}, [storeModels, geometryResult, modelIdToIndex]);
|
|
97
173
|
|
|
174
|
+
// Extract georeferencing info merged with any live mutations (for Cesium overlay).
|
|
175
|
+
// Reacts to: model load, Cesium toggle, and every georef field edit.
|
|
176
|
+
const georef = useMemo(() => {
|
|
177
|
+
if (!cesiumEnabled) return null;
|
|
178
|
+
|
|
179
|
+
// Helper: merge original georef with mutations for a model
|
|
180
|
+
function mergeGeoref(
|
|
181
|
+
originalCRS: ProjectedCRS | undefined,
|
|
182
|
+
originalConv: MapConversion | undefined,
|
|
183
|
+
modelId: string,
|
|
184
|
+
): { mapConversion: MapConversion; projectedCRS: ProjectedCRS } | null {
|
|
185
|
+
const muts = georefMutations.get(modelId);
|
|
186
|
+
const mutCRS = muts?.projectedCRS;
|
|
187
|
+
const mutConv = muts?.mapConversion;
|
|
188
|
+
|
|
189
|
+
// Build merged ProjectedCRS — mutation fields override originals
|
|
190
|
+
const hasCRS = originalCRS || mutCRS;
|
|
191
|
+
if (!hasCRS) return null;
|
|
192
|
+
const projectedCRS: ProjectedCRS = {
|
|
193
|
+
id: originalCRS?.id ?? 0,
|
|
194
|
+
name: (mutCRS?.name ?? originalCRS?.name ?? '') as string,
|
|
195
|
+
description: mutCRS?.description ?? originalCRS?.description,
|
|
196
|
+
geodeticDatum: mutCRS?.geodeticDatum ?? originalCRS?.geodeticDatum,
|
|
197
|
+
verticalDatum: mutCRS?.verticalDatum ?? originalCRS?.verticalDatum,
|
|
198
|
+
mapProjection: mutCRS?.mapProjection ?? originalCRS?.mapProjection,
|
|
199
|
+
mapZone: mutCRS?.mapZone ?? originalCRS?.mapZone,
|
|
200
|
+
mapUnit: mutCRS?.mapUnit ?? originalCRS?.mapUnit,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
// Need at least an EPSG name to resolve projection
|
|
204
|
+
if (!projectedCRS.name) return null;
|
|
205
|
+
|
|
206
|
+
// Build merged MapConversion
|
|
207
|
+
const mapConversion: MapConversion = {
|
|
208
|
+
id: originalConv?.id ?? 0,
|
|
209
|
+
sourceCRS: originalConv?.sourceCRS ?? 0,
|
|
210
|
+
targetCRS: originalConv?.targetCRS ?? 0,
|
|
211
|
+
eastings: (mutConv?.eastings ?? originalConv?.eastings ?? 0) as number,
|
|
212
|
+
northings: (mutConv?.northings ?? originalConv?.northings ?? 0) as number,
|
|
213
|
+
orthogonalHeight: (mutConv?.orthogonalHeight ?? originalConv?.orthogonalHeight ?? 0) as number,
|
|
214
|
+
xAxisAbscissa: mutConv?.xAxisAbscissa ?? originalConv?.xAxisAbscissa,
|
|
215
|
+
xAxisOrdinate: mutConv?.xAxisOrdinate ?? originalConv?.xAxisOrdinate,
|
|
216
|
+
scale: mutConv?.scale ?? originalConv?.scale,
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
return { mapConversion, projectedCRS };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check federated models first
|
|
223
|
+
for (const [modelId, model] of storeModels) {
|
|
224
|
+
const ds = model.ifcDataStore;
|
|
225
|
+
if (!ds) continue;
|
|
226
|
+
const original = extractGeoreferencingOnDemand(ds as IfcDataStore);
|
|
227
|
+
const merged = mergeGeoref(
|
|
228
|
+
original?.projectedCRS,
|
|
229
|
+
original?.mapConversion,
|
|
230
|
+
modelId,
|
|
231
|
+
);
|
|
232
|
+
if (merged) {
|
|
233
|
+
// Return coordinateInfo from the SAME model to avoid mismatched transforms
|
|
234
|
+
const coordInfo = model.geometryResult?.coordinateInfo;
|
|
235
|
+
return { hasGeoreference: true, ...merged, sourceModelId: modelId, coordinateInfo: coordInfo };
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Fallback to legacy single-model
|
|
240
|
+
if (ifcDataStore) {
|
|
241
|
+
const original = extractGeoreferencingOnDemand(ifcDataStore as IfcDataStore);
|
|
242
|
+
const merged = mergeGeoref(
|
|
243
|
+
original?.projectedCRS,
|
|
244
|
+
original?.mapConversion,
|
|
245
|
+
'__legacy__',
|
|
246
|
+
);
|
|
247
|
+
if (merged) {
|
|
248
|
+
return { hasGeoreference: true, ...merged, sourceModelId: '__legacy__', coordinateInfo: mergedGeometryResult?.coordinateInfo };
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return null;
|
|
253
|
+
}, [cesiumEnabled, storeModels, ifcDataStore, georefMutations, mutationVersion, mergedGeometryResult]);
|
|
254
|
+
|
|
255
|
+
// Sync the active Cesium source model ID so terrain actions are scoped correctly
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
setCesiumSourceModelId(georef?.sourceModelId ?? null);
|
|
258
|
+
}, [georef?.sourceModelId, setCesiumSourceModelId]);
|
|
259
|
+
|
|
260
|
+
useEffect(() => {
|
|
261
|
+
// Recent files are a desktop-only feature — the web viewer should not
|
|
262
|
+
// show previously opened files in the landing page empty state.
|
|
263
|
+
if (!isTauri()) return;
|
|
264
|
+
|
|
265
|
+
const refreshRecentFiles = () => {
|
|
266
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
refreshRecentFiles();
|
|
270
|
+
window.addEventListener('focus', refreshRecentFiles);
|
|
271
|
+
return () => window.removeEventListener('focus', refreshRecentFiles);
|
|
272
|
+
}, []);
|
|
273
|
+
|
|
98
274
|
const handleDragOver = useCallback((e: React.DragEvent) => {
|
|
99
275
|
e.preventDefault();
|
|
100
276
|
e.stopPropagation();
|
|
@@ -127,6 +303,10 @@ export function ViewportContainer() {
|
|
|
127
303
|
|
|
128
304
|
if (supportedFiles.length === 0) return;
|
|
129
305
|
|
|
306
|
+
recordRecentFiles(supportedFiles.map((file) => ({ name: file.name, size: file.size })));
|
|
307
|
+
void cacheFileBlobs(supportedFiles);
|
|
308
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
309
|
+
|
|
130
310
|
if (hasModelsLoaded) {
|
|
131
311
|
// Models already loaded - add new files sequentially
|
|
132
312
|
loadFilesSequentially(supportedFiles);
|
|
@@ -157,6 +337,10 @@ export function ViewportContainer() {
|
|
|
157
337
|
|
|
158
338
|
if (supportedFiles.length === 0) return;
|
|
159
339
|
|
|
340
|
+
recordRecentFiles(supportedFiles.map((file) => ({ name: file.name, size: file.size })));
|
|
341
|
+
void cacheFileBlobs(supportedFiles);
|
|
342
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
343
|
+
|
|
160
344
|
if (supportedFiles.length === 1) {
|
|
161
345
|
// Single file - use loadFile (simpler single-model path)
|
|
162
346
|
loadFile(supportedFiles[0]);
|
|
@@ -183,6 +367,7 @@ export function ViewportContainer() {
|
|
|
183
367
|
// A version counter triggers downstream re-renders via the Viewport prop.
|
|
184
368
|
const filteredCacheRef = useRef<MeshData[]>([]);
|
|
185
369
|
const filteredSourceLenRef = useRef(0);
|
|
370
|
+
const filteredSourceRef = useRef<MeshData[] | null>(null);
|
|
186
371
|
const filteredTypeVisRef = useRef(typeVisibility);
|
|
187
372
|
const filteredVersionRef = useRef(0);
|
|
188
373
|
|
|
@@ -190,6 +375,7 @@ export function ViewportContainer() {
|
|
|
190
375
|
if (!mergedGeometryResult?.meshes) {
|
|
191
376
|
filteredCacheRef.current = [];
|
|
192
377
|
filteredSourceLenRef.current = 0;
|
|
378
|
+
filteredSourceRef.current = null;
|
|
193
379
|
filteredVersionRef.current = 0;
|
|
194
380
|
return null;
|
|
195
381
|
}
|
|
@@ -203,9 +389,11 @@ export function ViewportContainer() {
|
|
|
203
389
|
prevVis.spaces !== typeVisibility.spaces ||
|
|
204
390
|
prevVis.openings !== typeVisibility.openings ||
|
|
205
391
|
prevVis.site !== typeVisibility.site;
|
|
206
|
-
|
|
392
|
+
const sourceChanged = filteredSourceRef.current !== allMeshes;
|
|
393
|
+
if (typeVisChanged || sourceChanged || allMeshes.length < filteredSourceLenRef.current) {
|
|
207
394
|
cache.length = 0;
|
|
208
395
|
filteredSourceLenRef.current = 0;
|
|
396
|
+
filteredSourceRef.current = allMeshes;
|
|
209
397
|
filteredTypeVisRef.current = typeVisibility;
|
|
210
398
|
}
|
|
211
399
|
|
|
@@ -237,7 +425,7 @@ export function ViewportContainer() {
|
|
|
237
425
|
|
|
238
426
|
// Only bump version when cache content actually changed — avoids
|
|
239
427
|
// unnecessary downstream re-renders when memo runs with same data.
|
|
240
|
-
if (cache.length !== prevCacheLen || typeVisChanged) {
|
|
428
|
+
if (cache.length !== prevCacheLen || typeVisChanged || sourceChanged) {
|
|
241
429
|
filteredVersionRef.current++;
|
|
242
430
|
}
|
|
243
431
|
|
|
@@ -265,14 +453,14 @@ export function ViewportContainer() {
|
|
|
265
453
|
const hierarchy = model.ifcDataStore?.spatialHierarchy;
|
|
266
454
|
if (!hierarchy) continue;
|
|
267
455
|
|
|
268
|
-
const offset = model.idOffset ?? 0;
|
|
269
|
-
|
|
270
456
|
for (const storeyId of selectedStoreys) {
|
|
271
|
-
const localStoreyId = hierarchy.byStorey.has(storeyId)
|
|
457
|
+
const localStoreyId = hierarchy.byStorey.has(storeyId)
|
|
458
|
+
? storeyId
|
|
459
|
+
: storeyId - (model.idOffset ?? 0);
|
|
272
460
|
const storeyElementIds = collectIfcBuildingStoreyElementsWithIfcSpace(hierarchy, localStoreyId);
|
|
273
461
|
if (storeyElementIds) {
|
|
274
462
|
for (const originalExpressId of storeyElementIds) {
|
|
275
|
-
combinedGlobalIds.add(
|
|
463
|
+
combinedGlobalIds.add(toGlobalIdFromModels(storeModels, model.id, originalExpressId));
|
|
276
464
|
}
|
|
277
465
|
}
|
|
278
466
|
}
|
|
@@ -530,7 +718,29 @@ export function ViewportContainer() {
|
|
|
530
718
|
|
|
531
719
|
{/* Action */}
|
|
532
720
|
<button
|
|
533
|
-
onClick={() =>
|
|
721
|
+
onClick={async () => {
|
|
722
|
+
if (!webgpu.supported) {
|
|
723
|
+
return;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
void logToDesktopTerminal('info', '[ViewportContainer] Empty-state open button clicked');
|
|
727
|
+
const file = await openIfcFileDialog();
|
|
728
|
+
if (file) {
|
|
729
|
+
void logToDesktopTerminal('info', `[ViewportContainer] Native dialog selected ${file.path}`);
|
|
730
|
+
recordRecentFiles([{
|
|
731
|
+
name: file.name,
|
|
732
|
+
size: file.size,
|
|
733
|
+
path: file.path,
|
|
734
|
+
modifiedMs: file.modifiedMs ?? null,
|
|
735
|
+
}]);
|
|
736
|
+
setRecentFiles(getRecentFiles().slice(0, 3));
|
|
737
|
+
loadFile(file);
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
void logToDesktopTerminal('info', '[ViewportContainer] Falling back to browser file input');
|
|
742
|
+
fileInputRef.current?.click();
|
|
743
|
+
}}
|
|
534
744
|
disabled={!webgpu.supported || webgpu.checking}
|
|
535
745
|
className={`group w-full flex items-center justify-center gap-3 px-6 py-3 font-mono text-sm border transition-all ${
|
|
536
746
|
!webgpu.supported || webgpu.checking
|
|
@@ -545,6 +755,37 @@ export function ViewportContainer() {
|
|
|
545
755
|
<p className="mt-3 text-xs font-mono text-zinc-400 dark:text-[#565f89]">
|
|
546
756
|
{webgpu.supported ? 'or drag & drop anywhere' : 'file upload disabled'}
|
|
547
757
|
</p>
|
|
758
|
+
|
|
759
|
+
{recentFiles.length > 0 && (
|
|
760
|
+
<div className="mt-6 w-full border-t border-zinc-200 dark:border-[#3b4261] pt-4">
|
|
761
|
+
<div className="mb-3 flex items-center gap-2 text-xs font-mono uppercase tracking-[0.2em] text-zinc-400 dark:text-[#565f89]">
|
|
762
|
+
<Clock3 className="h-3.5 w-3.5" />
|
|
763
|
+
<span>Recent Files</span>
|
|
764
|
+
</div>
|
|
765
|
+
<div className="flex flex-col gap-2">
|
|
766
|
+
{recentFiles.map((file) => (
|
|
767
|
+
<button
|
|
768
|
+
key={`${file.name}-${file.timestamp}`}
|
|
769
|
+
type="button"
|
|
770
|
+
onClick={async () => {
|
|
771
|
+
const cached = await getCachedFile(file);
|
|
772
|
+
if (cached) {
|
|
773
|
+
await loadFile(cached);
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
fileInputRef.current?.click();
|
|
777
|
+
}}
|
|
778
|
+
className="flex items-center justify-between gap-3 border border-zinc-200 bg-zinc-50 px-3 py-2 text-left transition-colors hover:border-primary hover:text-primary dark:border-[#3b4261] dark:bg-[#1f2335] dark:hover:border-primary"
|
|
779
|
+
>
|
|
780
|
+
<span className="min-w-0 truncate font-mono text-xs">{file.name}</span>
|
|
781
|
+
<span className="shrink-0 font-mono text-[10px] uppercase tracking-wide text-zinc-400 dark:text-[#565f89]">
|
|
782
|
+
{formatFileSize(file.size)}
|
|
783
|
+
</span>
|
|
784
|
+
</button>
|
|
785
|
+
))}
|
|
786
|
+
</div>
|
|
787
|
+
</div>
|
|
788
|
+
)}
|
|
548
789
|
</div>
|
|
549
790
|
|
|
550
791
|
{/* Feature Grid */}
|
|
@@ -606,18 +847,30 @@ export function ViewportContainer() {
|
|
|
606
847
|
</div>
|
|
607
848
|
)}
|
|
608
849
|
|
|
850
|
+
{/* Cesium 3D world context overlay — rendered behind the WebGPU canvas */}
|
|
851
|
+
{cesiumEnabled && georef && (
|
|
852
|
+
<CesiumOverlay
|
|
853
|
+
mapConversion={georef.mapConversion}
|
|
854
|
+
projectedCRS={georef.projectedCRS}
|
|
855
|
+
coordinateInfo={georef.coordinateInfo}
|
|
856
|
+
geometryResult={mergedGeometryResult}
|
|
857
|
+
/>
|
|
858
|
+
)}
|
|
609
859
|
<Viewport
|
|
610
860
|
geometry={filteredGeometry}
|
|
611
861
|
geometryVersion={geometryVersion}
|
|
612
862
|
coordinateInfo={mergedGeometryResult?.coordinateInfo}
|
|
613
863
|
computedIsolatedIds={computedIsolatedIds}
|
|
614
864
|
modelIdToIndex={modelIdToIndex}
|
|
865
|
+
cesiumActive={cesiumEnabled && georef !== null}
|
|
866
|
+
releaseGeometryAfterStream={false}
|
|
867
|
+
onGeometryReleased={releaseGeometryMemory}
|
|
615
868
|
/>
|
|
616
869
|
{bcfOverlayVisible && <BCFOverlay />}
|
|
617
870
|
<ViewportOverlays />
|
|
618
871
|
<ToolOverlays />
|
|
619
872
|
<BasketPresentationDock />
|
|
620
|
-
<Section2DPanel
|
|
873
|
+
<Section2DPanel
|
|
621
874
|
mergedGeometry={mergedGeometryResult}
|
|
622
875
|
computedIsolatedIds={computedIsolatedIds}
|
|
623
876
|
modelIdToIndex={modelIdToIndex}
|
|
@@ -8,10 +8,16 @@ import {
|
|
|
8
8
|
ZoomIn,
|
|
9
9
|
ZoomOut,
|
|
10
10
|
Layers,
|
|
11
|
+
Globe2,
|
|
12
|
+
Mountain,
|
|
13
|
+
Building2,
|
|
14
|
+
Satellite,
|
|
15
|
+
X,
|
|
11
16
|
} from 'lucide-react';
|
|
12
17
|
import { Button } from '@/components/ui/button';
|
|
13
18
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
|
|
14
19
|
import { useViewerStore } from '@/store';
|
|
20
|
+
import type { CesiumDataSource } from '@/store/slices/cesiumSlice';
|
|
15
21
|
import { goHomeFromStore } from '@/store/homeView';
|
|
16
22
|
import { useIfc } from '@/hooks/useIfc';
|
|
17
23
|
import { cn } from '@/lib/utils';
|
|
@@ -28,6 +34,14 @@ export function ViewportOverlays({ hideViewCube = false }: { hideViewCube?: bool
|
|
|
28
34
|
const setOnScaleChange = useViewerStore((s) => s.setOnScaleChange);
|
|
29
35
|
const { ifcDataStore, geometryResult } = useIfc();
|
|
30
36
|
|
|
37
|
+
// Cesium state
|
|
38
|
+
const cesiumEnabled = useViewerStore((s) => s.cesiumEnabled);
|
|
39
|
+
const cesiumDataSource = useViewerStore((s) => s.cesiumDataSource);
|
|
40
|
+
const setCesiumDataSource = useViewerStore((s) => s.setCesiumDataSource);
|
|
41
|
+
const cesiumTerrainEnabled = useViewerStore((s) => s.cesiumTerrainEnabled);
|
|
42
|
+
const setCesiumTerrainEnabled = useViewerStore((s) => s.setCesiumTerrainEnabled);
|
|
43
|
+
const toggleCesium = useViewerStore((s) => s.toggleCesium);
|
|
44
|
+
|
|
31
45
|
// Use refs for rotation to avoid re-renders - ViewCube updates itself directly
|
|
32
46
|
const cameraRotationRef = useRef({ azimuth: 45, elevation: 25 });
|
|
33
47
|
const viewCubeRef = useRef<ViewCubeRef | null>(null);
|
|
@@ -132,35 +146,45 @@ export function ViewportOverlays({ hideViewCube = false }: { hideViewCube?: bool
|
|
|
132
146
|
|
|
133
147
|
return (
|
|
134
148
|
<>
|
|
135
|
-
{/* Navigation
|
|
136
|
-
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
{/* Bottom-right: Cesium settings overlay OR Navigation controls */}
|
|
150
|
+
{cesiumEnabled ? (
|
|
151
|
+
<CesiumSettingsOverlay
|
|
152
|
+
dataSource={cesiumDataSource}
|
|
153
|
+
onDataSourceChange={setCesiumDataSource}
|
|
154
|
+
terrainEnabled={cesiumTerrainEnabled}
|
|
155
|
+
onTerrainChange={setCesiumTerrainEnabled}
|
|
156
|
+
onClose={toggleCesium}
|
|
157
|
+
/>
|
|
158
|
+
) : (
|
|
159
|
+
<div className="absolute bottom-4 right-4 flex flex-col gap-1 bg-background/80 backdrop-blur-sm rounded-lg border shadow-sm p-1">
|
|
160
|
+
<Tooltip>
|
|
161
|
+
<TooltipTrigger asChild>
|
|
162
|
+
<Button variant="ghost" size="icon-sm" onClick={handleHome}>
|
|
163
|
+
<Home className="h-4 w-4" />
|
|
164
|
+
</Button>
|
|
165
|
+
</TooltipTrigger>
|
|
166
|
+
<TooltipContent side="left">Home (H)</TooltipContent>
|
|
167
|
+
</Tooltip>
|
|
145
168
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
169
|
+
<Tooltip>
|
|
170
|
+
<TooltipTrigger asChild>
|
|
171
|
+
<Button variant="ghost" size="icon-sm" onClick={handleZoomIn}>
|
|
172
|
+
<ZoomIn className="h-4 w-4" />
|
|
173
|
+
</Button>
|
|
174
|
+
</TooltipTrigger>
|
|
175
|
+
<TooltipContent side="left">Zoom In (+)</TooltipContent>
|
|
176
|
+
</Tooltip>
|
|
154
177
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
178
|
+
<Tooltip>
|
|
179
|
+
<TooltipTrigger asChild>
|
|
180
|
+
<Button variant="ghost" size="icon-sm" onClick={handleZoomOut}>
|
|
181
|
+
<ZoomOut className="h-4 w-4" />
|
|
182
|
+
</Button>
|
|
183
|
+
</TooltipTrigger>
|
|
184
|
+
<TooltipContent side="left">Zoom Out (-)</TooltipContent>
|
|
185
|
+
</Tooltip>
|
|
186
|
+
</div>
|
|
187
|
+
)}
|
|
164
188
|
|
|
165
189
|
{/* Context Info (bottom-center) - Storey names */}
|
|
166
190
|
{storeyNames && storeyNames.length > 0 && (
|
|
@@ -209,3 +233,81 @@ export function ViewportOverlays({ hideViewCube = false }: { hideViewCube?: bool
|
|
|
209
233
|
</>
|
|
210
234
|
);
|
|
211
235
|
}
|
|
236
|
+
|
|
237
|
+
/* ------------------------------------------------------------------ */
|
|
238
|
+
/* Cesium Settings Overlay — replaces nav controls when Cesium is on */
|
|
239
|
+
/* ------------------------------------------------------------------ */
|
|
240
|
+
|
|
241
|
+
const DATA_SOURCES: { value: CesiumDataSource; label: string; icon: typeof Globe2 }[] = [
|
|
242
|
+
{ value: 'google-photorealistic', label: 'Google 3D', icon: Globe2 },
|
|
243
|
+
{ value: 'osm-buildings', label: 'OSM', icon: Building2 },
|
|
244
|
+
{ value: 'bing-aerial', label: 'Aerial', icon: Satellite },
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
function CesiumSettingsOverlay({
|
|
248
|
+
dataSource,
|
|
249
|
+
onDataSourceChange,
|
|
250
|
+
terrainEnabled,
|
|
251
|
+
onTerrainChange,
|
|
252
|
+
onClose,
|
|
253
|
+
}: {
|
|
254
|
+
dataSource: CesiumDataSource;
|
|
255
|
+
onDataSourceChange: (ds: CesiumDataSource) => void;
|
|
256
|
+
terrainEnabled: boolean;
|
|
257
|
+
onTerrainChange: (enabled: boolean) => void;
|
|
258
|
+
onClose: () => void;
|
|
259
|
+
}) {
|
|
260
|
+
return (
|
|
261
|
+
<div className="absolute bottom-4 right-4 z-10 pointer-events-auto bg-background/90 backdrop-blur-sm rounded-lg border shadow-lg p-2 flex flex-col gap-2 min-w-[160px]">
|
|
262
|
+
{/* Header */}
|
|
263
|
+
<div className="flex items-center justify-between gap-2">
|
|
264
|
+
<span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
|
|
265
|
+
3D World
|
|
266
|
+
</span>
|
|
267
|
+
<Tooltip>
|
|
268
|
+
<TooltipTrigger asChild>
|
|
269
|
+
<Button variant="ghost" size="icon-sm" className="h-5 w-5" onClick={onClose}>
|
|
270
|
+
<X className="h-3 w-3" />
|
|
271
|
+
</Button>
|
|
272
|
+
</TooltipTrigger>
|
|
273
|
+
<TooltipContent side="left">Disable Cesium overlay</TooltipContent>
|
|
274
|
+
</Tooltip>
|
|
275
|
+
</div>
|
|
276
|
+
|
|
277
|
+
{/* Data Source Buttons */}
|
|
278
|
+
<div className="flex flex-col gap-0.5">
|
|
279
|
+
{DATA_SOURCES.map((ds) => {
|
|
280
|
+
const Icon = ds.icon;
|
|
281
|
+
const active = dataSource === ds.value;
|
|
282
|
+
return (
|
|
283
|
+
<button
|
|
284
|
+
key={ds.value}
|
|
285
|
+
onClick={() => onDataSourceChange(ds.value)}
|
|
286
|
+
className={cn(
|
|
287
|
+
'flex items-center gap-2 px-2 py-1.5 rounded text-xs transition-colors text-left',
|
|
288
|
+
active
|
|
289
|
+
? 'bg-teal-600 text-white'
|
|
290
|
+
: 'hover:bg-muted text-foreground/80',
|
|
291
|
+
)}
|
|
292
|
+
>
|
|
293
|
+
<Icon className="h-3.5 w-3.5 shrink-0" />
|
|
294
|
+
{ds.label}
|
|
295
|
+
</button>
|
|
296
|
+
);
|
|
297
|
+
})}
|
|
298
|
+
</div>
|
|
299
|
+
|
|
300
|
+
{/* Terrain Toggle */}
|
|
301
|
+
<label className="flex items-center gap-2 px-2 py-1 cursor-pointer border-t border-border pt-2">
|
|
302
|
+
<Mountain className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
|
|
303
|
+
<span className="text-xs text-foreground/80">Terrain</span>
|
|
304
|
+
<input
|
|
305
|
+
type="checkbox"
|
|
306
|
+
checked={terrainEnabled}
|
|
307
|
+
onChange={(e) => onTerrainChange(e.target.checked)}
|
|
308
|
+
className="ml-auto accent-teal-500"
|
|
309
|
+
/>
|
|
310
|
+
</label>
|
|
311
|
+
</div>
|
|
312
|
+
);
|
|
313
|
+
}
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from '@ifc-lite/data';
|
|
14
14
|
import type { IfcDataStore } from '@ifc-lite/parser';
|
|
15
15
|
import { useViewerStore, type FederatedModel } from '@/store';
|
|
16
|
+
import { toGlobalIdFromModels } from '@/store/globalId';
|
|
16
17
|
import type { TreeNode, NodeType, StoreyData, UnifiedStorey } from './types';
|
|
17
18
|
|
|
18
19
|
/** Helper to create elevation key (with 0.5m tolerance for matching) */
|
|
@@ -300,7 +301,7 @@ export function buildTreeData(
|
|
|
300
301
|
nodes.push({
|
|
301
302
|
id: storeyNodeId,
|
|
302
303
|
expressIds: allStoreyIds,
|
|
303
|
-
globalIds: unified.storeys.map((s) =>
|
|
304
|
+
globalIds: unified.storeys.map((s) => toGlobalIdFromModels(models, s.modelId, s.storeyId)),
|
|
304
305
|
modelIds: unified.storeys.map(s => s.modelId),
|
|
305
306
|
name: unified.name,
|
|
306
307
|
type: 'unified-storey',
|