@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
|
@@ -0,0 +1,370 @@
|
|
|
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
|
+
* Coordinate reprojection utilities.
|
|
7
|
+
*
|
|
8
|
+
* Converts projected coordinates (e.g. UTM eastings/northings) from an
|
|
9
|
+
* IfcMapConversion + IfcProjectedCRS pair into WGS84 longitude/latitude
|
|
10
|
+
* so they can be displayed on a web map.
|
|
11
|
+
*
|
|
12
|
+
* proj4 definitions are resolved from:
|
|
13
|
+
* 1. The bundled EPSG index (@ifc-lite/data) — covers all 7000+ codes
|
|
14
|
+
* 2. Programmatically constructed (UTM zones, well-known codes)
|
|
15
|
+
* 3. Fetched from epsg.io at runtime as last resort
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import proj4 from 'proj4';
|
|
19
|
+
import type { MapConversion, ProjectedCRS } from '@ifc-lite/parser';
|
|
20
|
+
import type { CoordinateInfo } from '@ifc-lite/geometry';
|
|
21
|
+
import { lookupProj4 } from '@ifc-lite/data';
|
|
22
|
+
|
|
23
|
+
export interface LatLon {
|
|
24
|
+
lat: number;
|
|
25
|
+
lon: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Cache resolved projection definitions (from any source).
|
|
29
|
+
const projDefCache = new Map<string, string | null>();
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Extract EPSG numeric code from a CRS name like "EPSG:32632" or "EPSG 2056".
|
|
33
|
+
*/
|
|
34
|
+
function extractEpsgCode(crs: ProjectedCRS): string | null {
|
|
35
|
+
const match = crs.name?.match(/EPSG[:\s]*(\d+)/i);
|
|
36
|
+
return match ? match[1] : null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Build a proj4 definition string for a UTM zone.
|
|
41
|
+
*/
|
|
42
|
+
function utmProj4String(zone: string): string | null {
|
|
43
|
+
const match = zone.match(/^(\d{1,2})([NS])$/i);
|
|
44
|
+
if (!match) return null;
|
|
45
|
+
const zoneNum = parseInt(match[1], 10);
|
|
46
|
+
const isNorth = match[2].toUpperCase() === 'N';
|
|
47
|
+
if (zoneNum < 1 || zoneNum > 60) return null;
|
|
48
|
+
return `+proj=utm +zone=${zoneNum}${isNorth ? '' : ' +south'} +datum=WGS84 +units=m +no_defs`;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Well-known +towgs84 approximations for datums that normally use grid files.
|
|
53
|
+
* These are accurate to ~1-5m, which is sufficient for map display.
|
|
54
|
+
* Grid files (like OSTN15_NTv2_OSGBtoETRS.gsb) cannot run in the browser.
|
|
55
|
+
*/
|
|
56
|
+
const DATUM_TOWGS84: Record<string, string> = {
|
|
57
|
+
'airy': '+towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489', // OSGB36 (UK)
|
|
58
|
+
'clrk66': '+towgs84=-8,160,176,0,0,0,0', // NAD27 (approx)
|
|
59
|
+
'GRS80': '+towgs84=0,0,0,0,0,0,0', // GRS80-based (NAD83≈WGS84)
|
|
60
|
+
'bessel': '+towgs84=598.1,73.7,418.2,0.202,0.045,-2.455,6.7', // DHDN (Germany)
|
|
61
|
+
'intl': '+towgs84=-87,-98,-121,0,0,0,0', // NZGD49 (NZ)
|
|
62
|
+
'aust_SA': '+towgs84=-134,-48,149,0,0,0,0', // AGD84 (Australia)
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Strip +nadgrids=... from a proj4 string and add a +towgs84 approximation
|
|
67
|
+
* based on the ellipsoid. Grid files cannot be loaded in the browser.
|
|
68
|
+
*/
|
|
69
|
+
function sanitizeProj4(def: string): string {
|
|
70
|
+
if (!def.includes('+nadgrids') || def.includes('+nadgrids=@null')) return def;
|
|
71
|
+
|
|
72
|
+
// Extract the ellipsoid to find the right towgs84 approximation
|
|
73
|
+
const ellpsMatch = def.match(/\+ellps=(\S+)/);
|
|
74
|
+
const ellps = ellpsMatch?.[1] ?? '';
|
|
75
|
+
const towgs84 = DATUM_TOWGS84[ellps] ?? '+towgs84=0,0,0,0,0,0,0';
|
|
76
|
+
|
|
77
|
+
// Remove +nadgrids=... and add +towgs84
|
|
78
|
+
return def.replace(/\+nadgrids=\S+/g, '').replace(/\s+/g, ' ').trim() + ' ' + towgs84;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Fetch a proj4 definition string from epsg.io (last-resort fallback).
|
|
83
|
+
*/
|
|
84
|
+
async function fetchProj4Def(epsgCode: string): Promise<string | null> {
|
|
85
|
+
try {
|
|
86
|
+
const resp = await fetch(`https://epsg.io/${epsgCode}.proj4`);
|
|
87
|
+
if (!resp.ok) return null;
|
|
88
|
+
const text = (await resp.text()).trim();
|
|
89
|
+
if (!text || text.startsWith('<') || text.startsWith('{') || !text.includes('+')) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return text;
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Resolve a proj4 definition for the given ProjectedCRS.
|
|
100
|
+
*
|
|
101
|
+
* Resolution order:
|
|
102
|
+
* 1. Cache hit
|
|
103
|
+
* 2. Bundled EPSG index (7000+ codes with proj4 strings)
|
|
104
|
+
* 3. UTM zone heuristic (from CRS metadata)
|
|
105
|
+
* 4. Fetch from epsg.io (network fallback)
|
|
106
|
+
*/
|
|
107
|
+
export async function resolveProjection(crs: ProjectedCRS): Promise<string | null> {
|
|
108
|
+
const code = extractEpsgCode(crs);
|
|
109
|
+
|
|
110
|
+
// 1. Check cache
|
|
111
|
+
if (code && projDefCache.has(code)) {
|
|
112
|
+
return projDefCache.get(code) ?? null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 2. Bundled EPSG index (primary source — all 7000+ codes)
|
|
116
|
+
if (code) {
|
|
117
|
+
try {
|
|
118
|
+
const bundled = await lookupProj4(code);
|
|
119
|
+
if (bundled) {
|
|
120
|
+
const sanitized = sanitizeProj4(bundled);
|
|
121
|
+
projDefCache.set(code, sanitized);
|
|
122
|
+
return sanitized;
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
// EPSG index not loaded yet, continue to fallbacks
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// 3. UTM zone heuristic
|
|
130
|
+
if (crs.mapZone) {
|
|
131
|
+
const def = utmProj4String(crs.mapZone);
|
|
132
|
+
if (def) {
|
|
133
|
+
if (code) projDefCache.set(code, def);
|
|
134
|
+
return def;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const name = crs.name?.toUpperCase() ?? '';
|
|
138
|
+
const utmMatch = name.match(/UTM\s+ZONE\s+(\d{1,2}[NS])/i)
|
|
139
|
+
?? crs.description?.match(/UTM\s+zone\s+(\d{1,2}[NS])/i);
|
|
140
|
+
if (utmMatch) {
|
|
141
|
+
const def = utmProj4String(utmMatch[1]);
|
|
142
|
+
if (def) {
|
|
143
|
+
if (code) projDefCache.set(code, def);
|
|
144
|
+
return def;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// 4. Network fallback — fetch from epsg.io
|
|
149
|
+
if (code) {
|
|
150
|
+
const raw = await fetchProj4Def(code);
|
|
151
|
+
const fetched = raw ? sanitizeProj4(raw) : null;
|
|
152
|
+
projDefCache.set(code, fetched);
|
|
153
|
+
return fetched;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Compute the model center in the projected CRS (easting, northing).
|
|
161
|
+
*
|
|
162
|
+
* The coordinate pipeline is:
|
|
163
|
+
* 1. WASM extracts IFC positions (Z-up) and may apply RTC offset (wasmRtcOffset, Z-up)
|
|
164
|
+
* 2. Mesh collector converts Z-up → Y-up: viewerX = ifcX, viewerY = ifcZ, viewerZ = -ifcY
|
|
165
|
+
* 3. CoordinateHandler may apply originShift (Y-up)
|
|
166
|
+
*
|
|
167
|
+
* To recover IFC world coordinates (Z-up) from the viewer bounds:
|
|
168
|
+
* world_yup = bounds_center + originShift + wasmRtcOffset_as_yup
|
|
169
|
+
* ifc_x = world_yup.x, ifc_y = -world_yup.z, ifc_z = world_yup.y
|
|
170
|
+
*
|
|
171
|
+
* Then the projected CRS coordinates are:
|
|
172
|
+
* easting = mapConversion.eastings + scale * (cos*ifc_x - sin*ifc_y)
|
|
173
|
+
* northing = mapConversion.northings + scale * (sin*ifc_x + cos*ifc_y)
|
|
174
|
+
*/
|
|
175
|
+
function computeProjectedCenter(
|
|
176
|
+
conversion: MapConversion,
|
|
177
|
+
coordinateInfo?: CoordinateInfo,
|
|
178
|
+
): { easting: number; northing: number } {
|
|
179
|
+
const { ifcX, ifcY } = computeLocalIfcCenter(coordinateInfo);
|
|
180
|
+
|
|
181
|
+
// Apply MapConversion rotation + scale + offset
|
|
182
|
+
const scale = conversion.scale ?? 1.0;
|
|
183
|
+
const abscissa = conversion.xAxisAbscissa ?? 1.0;
|
|
184
|
+
const ordinate = conversion.xAxisOrdinate ?? 0.0;
|
|
185
|
+
|
|
186
|
+
const easting = conversion.eastings + scale * (abscissa * ifcX - ordinate * ifcY);
|
|
187
|
+
const northing = conversion.northings + scale * (ordinate * ifcX + abscissa * ifcY);
|
|
188
|
+
|
|
189
|
+
return { easting, northing };
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Reproject the model center from the projected CRS to WGS84 lat/lon.
|
|
194
|
+
*
|
|
195
|
+
* Uses the model's actual geometry bounds + RTC offset to determine where
|
|
196
|
+
* the model sits in the projected coordinate system, then reprojects to WGS84.
|
|
197
|
+
*
|
|
198
|
+
* @param conversion IfcMapConversion (offset, rotation, scale)
|
|
199
|
+
* @param crs IfcProjectedCRS (EPSG code)
|
|
200
|
+
* @param coordinateInfo Geometry coordinate info with bounds and RTC offset
|
|
201
|
+
*/
|
|
202
|
+
export async function reprojectToLatLon(
|
|
203
|
+
conversion: MapConversion,
|
|
204
|
+
crs: ProjectedCRS,
|
|
205
|
+
coordinateInfo?: CoordinateInfo,
|
|
206
|
+
): Promise<LatLon | null> {
|
|
207
|
+
const projDef = await resolveProjection(crs);
|
|
208
|
+
if (!projDef) return null;
|
|
209
|
+
|
|
210
|
+
const { easting, northing } = computeProjectedCenter(conversion, coordinateInfo);
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
const [lon, lat] = proj4(projDef, 'WGS84', [easting, northing]);
|
|
214
|
+
if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
|
|
215
|
+
if (lat < -90 || lat > 90 || lon < -180 || lon > 180) return null;
|
|
216
|
+
return { lat, lon };
|
|
217
|
+
} catch {
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Compute the model's local IFC center offset (ifcX, ifcY) from coordinate info.
|
|
224
|
+
* This is the geometry center in IFC Z-up coordinates, before MapConversion is applied.
|
|
225
|
+
*/
|
|
226
|
+
function computeLocalIfcCenter(coordinateInfo?: CoordinateInfo): { ifcX: number; ifcY: number } {
|
|
227
|
+
if (!coordinateInfo) return { ifcX: 0, ifcY: 0 };
|
|
228
|
+
|
|
229
|
+
const bounds = coordinateInfo.originalBounds;
|
|
230
|
+
const shift = coordinateInfo.originShift;
|
|
231
|
+
const rtc = coordinateInfo.wasmRtcOffset;
|
|
232
|
+
|
|
233
|
+
const rtcYup = rtc
|
|
234
|
+
? { x: rtc.x, y: rtc.z, z: -rtc.y }
|
|
235
|
+
: { x: 0, y: 0, z: 0 };
|
|
236
|
+
|
|
237
|
+
const cx = (bounds.min.x + bounds.max.x) / 2;
|
|
238
|
+
const cz = (bounds.min.z + bounds.max.z) / 2;
|
|
239
|
+
|
|
240
|
+
const worldYupX = cx + shift.x + rtcYup.x;
|
|
241
|
+
const worldYupZ = cz + shift.z + rtcYup.z;
|
|
242
|
+
|
|
243
|
+
return { ifcX: worldYupX, ifcY: -worldYupZ };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Reverse-project a WGS84 lat/lon into the IfcMapConversion eastings/northings
|
|
248
|
+
* values that would place the model center at the given location.
|
|
249
|
+
*
|
|
250
|
+
* This accounts for the model's local geometry offset, rotation, and scale:
|
|
251
|
+
* projected = eastings + scale * (cos*ifcX - sin*ifcY)
|
|
252
|
+
* ⟹ eastings = projected - scale * (cos*ifcX - sin*ifcY)
|
|
253
|
+
*/
|
|
254
|
+
export async function reprojectFromLatLon(
|
|
255
|
+
latLon: LatLon,
|
|
256
|
+
crs: ProjectedCRS,
|
|
257
|
+
conversion?: MapConversion,
|
|
258
|
+
coordinateInfo?: CoordinateInfo,
|
|
259
|
+
): Promise<{ easting: number; northing: number } | null> {
|
|
260
|
+
const projDef = await resolveProjection(crs);
|
|
261
|
+
if (!projDef) return null;
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
const [projE, projN] = proj4('WGS84', projDef, [latLon.lon, latLon.lat]);
|
|
265
|
+
if (!Number.isFinite(projE) || !Number.isFinite(projN)) return null;
|
|
266
|
+
|
|
267
|
+
// Subtract the rotated/scaled local geometry offset so that
|
|
268
|
+
// the resulting eastings/northings place the model center at this position
|
|
269
|
+
const { ifcX, ifcY } = computeLocalIfcCenter(coordinateInfo);
|
|
270
|
+
const scale = conversion?.scale ?? 1.0;
|
|
271
|
+
const abscissa = conversion?.xAxisAbscissa ?? 1.0;
|
|
272
|
+
const ordinate = conversion?.xAxisOrdinate ?? 0.0;
|
|
273
|
+
|
|
274
|
+
const easting = projE - scale * (abscissa * ifcX - ordinate * ifcY);
|
|
275
|
+
const northing = projN - scale * (ordinate * ifcX + abscissa * ifcY);
|
|
276
|
+
|
|
277
|
+
return { easting, northing };
|
|
278
|
+
} catch {
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Compute a building footprint rectangle from the model's bounding box and
|
|
285
|
+
* reproject each corner to WGS84 for display as a GeoJSON polygon on a web map.
|
|
286
|
+
*
|
|
287
|
+
* Uses the shiftedBounds (scene-local after RTC) from CoordinateInfo, transforms
|
|
288
|
+
* each corner through the MapConversion pipeline (rotation + scale + offset),
|
|
289
|
+
* then reprojects to lat/lon. The result is a rotated rectangle matching the
|
|
290
|
+
* model's XZ extent on the map.
|
|
291
|
+
*
|
|
292
|
+
* @returns A single GeoJSON-compatible polygon: closed ring of [lon, lat] pairs
|
|
293
|
+
*/
|
|
294
|
+
export async function computeFootprintGeoJSON(
|
|
295
|
+
conversion: MapConversion,
|
|
296
|
+
crs: ProjectedCRS,
|
|
297
|
+
coordinateInfo: CoordinateInfo,
|
|
298
|
+
): Promise<[number, number][] | null> {
|
|
299
|
+
const projDef = await resolveProjection(crs);
|
|
300
|
+
if (!projDef) {
|
|
301
|
+
console.warn('[footprint] failed to resolve projection for CRS:', crs.name);
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const scale = conversion.scale ?? 1.0;
|
|
306
|
+
const abscissa = conversion.xAxisAbscissa ?? 1.0;
|
|
307
|
+
const ordinate = conversion.xAxisOrdinate ?? 0.0;
|
|
308
|
+
|
|
309
|
+
const shift = coordinateInfo.originShift;
|
|
310
|
+
const rtc = coordinateInfo.wasmRtcOffset;
|
|
311
|
+
const rtcYup = rtc
|
|
312
|
+
? { x: rtc.x, z: -rtc.y }
|
|
313
|
+
: { x: 0, z: 0 };
|
|
314
|
+
|
|
315
|
+
const bounds = coordinateInfo.shiftedBounds;
|
|
316
|
+
|
|
317
|
+
// Four corners of the bounding box on the XZ plane (viewer Y-up)
|
|
318
|
+
const corners = [
|
|
319
|
+
{ x: bounds.min.x, z: bounds.min.z },
|
|
320
|
+
{ x: bounds.max.x, z: bounds.min.z },
|
|
321
|
+
{ x: bounds.max.x, z: bounds.max.z },
|
|
322
|
+
{ x: bounds.min.x, z: bounds.max.z },
|
|
323
|
+
];
|
|
324
|
+
|
|
325
|
+
const ring: [number, number][] = [];
|
|
326
|
+
|
|
327
|
+
for (const c of corners) {
|
|
328
|
+
// Scene-local → world Y-up
|
|
329
|
+
const worldX = c.x + shift.x + rtcYup.x;
|
|
330
|
+
const worldZ = c.z + shift.z + rtcYup.z;
|
|
331
|
+
|
|
332
|
+
// Y-up → IFC Z-up: ifcX = worldX, ifcY = -worldZ
|
|
333
|
+
const ifcX = worldX;
|
|
334
|
+
const ifcY = -worldZ;
|
|
335
|
+
|
|
336
|
+
// MapConversion: local IFC → projected CRS
|
|
337
|
+
const easting = conversion.eastings + scale * (abscissa * ifcX - ordinate * ifcY);
|
|
338
|
+
const northing = conversion.northings + scale * (ordinate * ifcX + abscissa * ifcY);
|
|
339
|
+
|
|
340
|
+
// Projected CRS → WGS84
|
|
341
|
+
try {
|
|
342
|
+
const [lon, lat] = proj4(projDef, 'WGS84', [easting, northing]);
|
|
343
|
+
if (!Number.isFinite(lat) || !Number.isFinite(lon)) return null;
|
|
344
|
+
ring.push([lon, lat]);
|
|
345
|
+
} catch {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Close the ring (GeoJSON requirement)
|
|
351
|
+
ring.push(ring[0]);
|
|
352
|
+
return ring;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Query terrain elevation at a given lat/lon using the Open-Meteo elevation API.
|
|
357
|
+
* Returns height in metres above sea level, or null on failure.
|
|
358
|
+
*/
|
|
359
|
+
export async function queryTerrainElevation(latLon: LatLon): Promise<number | null> {
|
|
360
|
+
try {
|
|
361
|
+
const url = `https://api.open-meteo.com/v1/elevation?latitude=${latLon.lat}&longitude=${latLon.lon}`;
|
|
362
|
+
const resp = await fetch(url);
|
|
363
|
+
if (!resp.ok) return null;
|
|
364
|
+
const data = await resp.json();
|
|
365
|
+
const elev = data?.elevation?.[0];
|
|
366
|
+
return typeof elev === 'number' && Number.isFinite(elev) ? elev : null;
|
|
367
|
+
} catch {
|
|
368
|
+
return null;
|
|
369
|
+
}
|
|
370
|
+
}
|
package/src/lib/lens/adapter.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
extractClassificationsOnDemand,
|
|
19
19
|
extractMaterialsOnDemand,
|
|
20
20
|
} from '@ifc-lite/parser';
|
|
21
|
+
import { toGlobalIdFromModels } from '@/store/globalId';
|
|
21
22
|
import type { FederatedModel } from '@/store/types';
|
|
22
23
|
|
|
23
24
|
interface ModelEntry {
|
|
@@ -80,12 +81,13 @@ export function createLensDataProvider(
|
|
|
80
81
|
},
|
|
81
82
|
|
|
82
83
|
forEachEntity(callback: (globalId: number, modelId: string) => void): void {
|
|
84
|
+
const models = new Map(entries.map((entry) => [entry.id, { idOffset: entry.idOffset }]));
|
|
83
85
|
for (const entry of entries) {
|
|
84
86
|
const entities = entry.ifcDataStore.entities;
|
|
85
87
|
if (!entities) continue;
|
|
86
88
|
for (let i = 0; i < entities.count; i++) {
|
|
87
89
|
const expressId = entities.expressId[i];
|
|
88
|
-
callback(
|
|
90
|
+
callback(toGlobalIdFromModels(models, entry.id, expressId), entry.id);
|
|
89
91
|
}
|
|
90
92
|
}
|
|
91
93
|
},
|
package/src/lib/recent-files.ts
CHANGED
|
@@ -103,7 +103,8 @@ export async function cacheFileBlobs(files: File[]): Promise<void> {
|
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/** Retrieve a cached file blob and reconstruct a File object. */
|
|
106
|
-
export async function getCachedFile(
|
|
106
|
+
export async function getCachedFile(target: string | RecentFileEntry): Promise<File | null> {
|
|
107
|
+
const name = typeof target === 'string' ? target : target.name;
|
|
107
108
|
try {
|
|
108
109
|
const db = await openDB();
|
|
109
110
|
const tx = db.transaction(STORE_NAME, 'readonly');
|
package/src/main.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import ReactDOM from 'react-dom/client';
|
|
|
11
11
|
import { ClerkProvider } from '@clerk/clerk-react';
|
|
12
12
|
import { App } from './App';
|
|
13
13
|
import './index.css';
|
|
14
|
+
import 'maplibre-gl/dist/maplibre-gl.css';
|
|
14
15
|
|
|
15
16
|
const clerkPublishableKey = (import.meta.env.VITE_CLERK_PUBLISHABLE_KEY as string | undefined)?.trim();
|
|
16
17
|
|
|
@@ -119,6 +119,13 @@ function escapeCsv(value: string, sep: string): string {
|
|
|
119
119
|
* on the same LocalBackend, providing full export support for both
|
|
120
120
|
* direct dispatch calls and SDK namespace usage.
|
|
121
121
|
*/
|
|
122
|
+
function toBlobPart(content: string | Uint8Array): BlobPart {
|
|
123
|
+
if (typeof content === 'string') return content;
|
|
124
|
+
const bytes = new Uint8Array(content.byteLength);
|
|
125
|
+
bytes.set(content);
|
|
126
|
+
return bytes;
|
|
127
|
+
}
|
|
128
|
+
|
|
122
129
|
export function createExportAdapter(store: StoreApi): ExportBackendMethods {
|
|
123
130
|
/** Resolve entity data via the query subsystem */
|
|
124
131
|
function getEntityData(ref: EntityRef): EntityData | null {
|
|
@@ -354,6 +361,11 @@ export function createExportAdapter(store: StoreApi): ExportBackendMethods {
|
|
|
354
361
|
model.ifcDataStore,
|
|
355
362
|
options.includeMutations === false ? undefined : getMutationViewForModel(store, modelId) ?? undefined,
|
|
356
363
|
);
|
|
364
|
+
// Include georeferencing mutations if present
|
|
365
|
+
const georefMutations = options.includeMutations !== false
|
|
366
|
+
? state.georefMutations?.get(modelId) ?? undefined
|
|
367
|
+
: undefined;
|
|
368
|
+
|
|
357
369
|
const exportOptions: StepExportOptions = {
|
|
358
370
|
schema: options.schema ?? model.ifcDataStore.schemaVersion,
|
|
359
371
|
includeGeometry: true,
|
|
@@ -364,6 +376,7 @@ export function createExportAdapter(store: StoreApi): ExportBackendMethods {
|
|
|
364
376
|
visibleOnly,
|
|
365
377
|
hiddenEntityIds,
|
|
366
378
|
isolatedEntityIds,
|
|
379
|
+
georefMutations,
|
|
367
380
|
};
|
|
368
381
|
|
|
369
382
|
return exporter.export(exportOptions).content;
|
|
@@ -381,7 +394,7 @@ function triggerDownload(content: string | Uint8Array, filename: string, mimeTyp
|
|
|
381
394
|
if (typeof document === 'undefined') {
|
|
382
395
|
throw new Error('download() requires a browser environment (document is unavailable)');
|
|
383
396
|
}
|
|
384
|
-
const blob = new Blob([content], { type: mimeType });
|
|
397
|
+
const blob = new Blob([toBlobPart(content)], { type: mimeType });
|
|
385
398
|
const url = URL.createObjectURL(blob);
|
|
386
399
|
const a = document.createElement('a');
|
|
387
400
|
a.href = url;
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { EntityRef, SectionPlane, CameraState, ViewerBackendMethods } from '@ifc-lite/sdk';
|
|
6
6
|
import type { StoreApi } from './types.js';
|
|
7
7
|
import { getModelForRef } from './model-compat.js';
|
|
8
|
+
import { toGlobalIdForRef } from '../../store/globalId.js';
|
|
8
9
|
|
|
9
10
|
const AXIS_TO_STORE: Record<string, 'down' | 'front' | 'side'> = {
|
|
10
11
|
x: 'side',
|
|
@@ -25,11 +26,8 @@ export function createViewerAdapter(store: StoreApi): ViewerBackendMethods {
|
|
|
25
26
|
const existing = state.pendingColorUpdates;
|
|
26
27
|
const colorMap = existing ? new Map(existing) : new Map<number, [number, number, number, number]>();
|
|
27
28
|
for (const ref of refs) {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const globalId = ref.expressId + model.idOffset;
|
|
31
|
-
colorMap.set(globalId, color);
|
|
32
|
-
}
|
|
29
|
+
if (!getModelForRef(state, ref.modelId)) continue;
|
|
30
|
+
colorMap.set(toGlobalIdForRef(state.models, ref), color);
|
|
33
31
|
}
|
|
34
32
|
state.setPendingColorUpdates(colorMap);
|
|
35
33
|
return undefined;
|
|
@@ -41,10 +39,8 @@ export function createViewerAdapter(store: StoreApi): ViewerBackendMethods {
|
|
|
41
39
|
const batchMap = new Map<number, [number, number, number, number]>();
|
|
42
40
|
for (const batch of batches) {
|
|
43
41
|
for (const ref of batch.refs) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
batchMap.set(ref.expressId + model.idOffset, batch.color);
|
|
47
|
-
}
|
|
42
|
+
if (!getModelForRef(state, ref.modelId)) continue;
|
|
43
|
+
batchMap.set(toGlobalIdForRef(state.models, ref), batch.color);
|
|
48
44
|
}
|
|
49
45
|
}
|
|
50
46
|
state.setPendingColorUpdates(batchMap);
|
|
@@ -6,6 +6,7 @@ import type { EntityRef, VisibilityBackendMethods } from '@ifc-lite/sdk';
|
|
|
6
6
|
import type { StoreApi } from './types.js';
|
|
7
7
|
import { getModelForRef, type ModelLike } from './model-compat.js';
|
|
8
8
|
import { collectSpatialSubtreeElementsWithIfcSpace } from '../../store/basketVisibleSet.js';
|
|
9
|
+
import { toGlobalIdForRef, toGlobalIdFromModels } from '../../store/globalId.js';
|
|
9
10
|
import { isSpaceLikeSpatialTypeName, isSpatialStructureTypeName, type SpatialNode } from '@ifc-lite/data';
|
|
10
11
|
|
|
11
12
|
function findDescendantNode(root: SpatialNode, expressId: number): SpatialNode | null {
|
|
@@ -49,10 +50,8 @@ export function createVisibilityAdapter(store: StoreApi): VisibilityBackendMetho
|
|
|
49
50
|
// hiddenEntities set (global IDs), not hiddenEntitiesByModel.
|
|
50
51
|
const globalIds: number[] = [];
|
|
51
52
|
for (const ref of refs) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
globalIds.push(ref.expressId + model.idOffset);
|
|
55
|
-
}
|
|
53
|
+
if (!getModelForRef(state, ref.modelId)) continue;
|
|
54
|
+
globalIds.push(toGlobalIdForRef(state.models, ref));
|
|
56
55
|
}
|
|
57
56
|
if (globalIds.length > 0) {
|
|
58
57
|
state.hideEntities(globalIds);
|
|
@@ -63,10 +62,8 @@ export function createVisibilityAdapter(store: StoreApi): VisibilityBackendMetho
|
|
|
63
62
|
const state = store.getState();
|
|
64
63
|
const globalIds: number[] = [];
|
|
65
64
|
for (const ref of refs) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
globalIds.push(ref.expressId + model.idOffset);
|
|
69
|
-
}
|
|
65
|
+
if (!getModelForRef(state, ref.modelId)) continue;
|
|
66
|
+
globalIds.push(toGlobalIdForRef(state.models, ref));
|
|
70
67
|
}
|
|
71
68
|
if (globalIds.length > 0) {
|
|
72
69
|
state.showEntities(globalIds);
|
|
@@ -81,7 +78,7 @@ export function createVisibilityAdapter(store: StoreApi): VisibilityBackendMetho
|
|
|
81
78
|
if (model) {
|
|
82
79
|
const expanded = expandSpatialRef(ref, model);
|
|
83
80
|
for (const id of expanded) {
|
|
84
|
-
globalIds.push(
|
|
81
|
+
globalIds.push(toGlobalIdFromModels(state.models, ref.modelId, id));
|
|
85
82
|
}
|
|
86
83
|
}
|
|
87
84
|
}
|
|
@@ -0,0 +1,125 @@
|
|
|
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
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
export type AnalysisExtensionPlacement = 'right' | 'bottom';
|
|
8
|
+
|
|
9
|
+
export interface AnalysisExtensionRenderProps {
|
|
10
|
+
onClose: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface AnalysisExtensionDefinition {
|
|
14
|
+
id: string;
|
|
15
|
+
label: string;
|
|
16
|
+
description?: string;
|
|
17
|
+
placement?: AnalysisExtensionPlacement;
|
|
18
|
+
icon: ComponentType<{ className?: string }>;
|
|
19
|
+
renderPanel: (props: AnalysisExtensionRenderProps) => ReactNode;
|
|
20
|
+
onBeforeOpen?: () => boolean | void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface AnalysisExtensionsSnapshot {
|
|
24
|
+
activeId: string | null;
|
|
25
|
+
extensions: AnalysisExtensionDefinition[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const listeners = new Set<() => void>();
|
|
29
|
+
const extensions = new Map<string, AnalysisExtensionDefinition>();
|
|
30
|
+
|
|
31
|
+
let activeId: string | null = null;
|
|
32
|
+
let snapshot: AnalysisExtensionsSnapshot = {
|
|
33
|
+
activeId,
|
|
34
|
+
extensions: [],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function rebuildSnapshot(): void {
|
|
38
|
+
snapshot = {
|
|
39
|
+
activeId,
|
|
40
|
+
extensions: Array.from(extensions.values()),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function emit(): void {
|
|
45
|
+
rebuildSnapshot();
|
|
46
|
+
listeners.forEach((listener) => listener());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function setActiveId(nextActiveId: string | null): void {
|
|
50
|
+
if (activeId === nextActiveId) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
activeId = nextActiveId;
|
|
54
|
+
emit();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function canOpen(definition: AnalysisExtensionDefinition): boolean {
|
|
58
|
+
return definition.onBeforeOpen?.() !== false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function subscribeAnalysisExtensions(listener: () => void): () => void {
|
|
62
|
+
listeners.add(listener);
|
|
63
|
+
return () => {
|
|
64
|
+
listeners.delete(listener);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function getAnalysisExtensionsSnapshot(): AnalysisExtensionsSnapshot {
|
|
69
|
+
return snapshot;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function getAnalysisExtensionById(id: string | null | undefined): AnalysisExtensionDefinition | null {
|
|
73
|
+
if (!id) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
return extensions.get(id) ?? null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function closeActiveAnalysisExtension(): void {
|
|
80
|
+
setActiveId(null);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function openAnalysisExtension(id: string): boolean {
|
|
84
|
+
const definition = extensions.get(id);
|
|
85
|
+
if (!definition) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
if (!canOpen(definition)) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
setActiveId(id);
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function toggleAnalysisExtension(id: string): boolean {
|
|
96
|
+
if (activeId === id) {
|
|
97
|
+
closeActiveAnalysisExtension();
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
return openAnalysisExtension(id);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function registerAnalysisExtensions(definitions: AnalysisExtensionDefinition[]): () => void {
|
|
104
|
+
const nextEntries = definitions.map((definition) => [definition.id, definition] as const);
|
|
105
|
+
nextEntries.forEach(([id, definition]) => {
|
|
106
|
+
extensions.set(id, definition);
|
|
107
|
+
});
|
|
108
|
+
emit();
|
|
109
|
+
|
|
110
|
+
return () => {
|
|
111
|
+
let shouldEmit = false;
|
|
112
|
+
for (const [id] of nextEntries) {
|
|
113
|
+
if (extensions.delete(id)) {
|
|
114
|
+
shouldEmit = true;
|
|
115
|
+
}
|
|
116
|
+
if (activeId === id) {
|
|
117
|
+
activeId = null;
|
|
118
|
+
shouldEmit = true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (shouldEmit) {
|
|
122
|
+
emit();
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
export function navigateToPath(path: string, options: { replace?: boolean } = {}): void {
|
|
6
|
+
const { replace = false } = options;
|
|
7
|
+
if (replace) {
|
|
8
|
+
window.history.replaceState({}, '', path);
|
|
9
|
+
} else {
|
|
10
|
+
window.history.pushState({}, '', path);
|
|
11
|
+
}
|
|
12
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
13
|
+
}
|