{"version":3,"sources":["hooks/use-dialog.tsx","hooks/use-task-queue.ts","hooks/use-viewer.ts","hooks/use-active-tool.ts","hooks/use-project-watcher.ts","hooks/use-popover.tsx","hooks/use-auth.ts","hooks/use-context-menu.ts","hooks/use-global-settings.ts","hooks/use-websockets.ts","hooks/use-bookmarks.ts","../node_modules/web-ifc sync","projections/projections.tsx","projections/manager.tsx","projections/detector.tsx","engine-viewer.tsx","index.tsx","redux/store.ts","viewer/file-system-loader.ts","hooks/use-table-state.ts","redux/assets-slice.ts","redux/bookmarks-slice.ts","viewer/projections.ts","classifications.ts","api/index.ts","api/folders.ts","api/tags.ts","api/bookmarks.ts","utilities/misc.ts","events.ts","viewer/utilities/change-detection.ts","viewer/utilities/unit-converter.ts","viewer/utilities/misc-utils.ts","viewer/utilities/polygon.ts","viewer/utilities/parse.ts","viewer/utilities/mesh-utils.ts","viewer/utilities/image-utils.ts","types/controls.ts","redux/custom-links-slice.ts","viewer/worker-pool.ts","types/project.ts","theme/colors.ts","theme/index.ts","types/measurements.ts","file-extensions.ts","redux/settings-slice.ts","utilities/dates.ts","viewer/textures/colormaps/classifications.png","hooks/use-branding.ts","components/buttons.tsx","components/dense-icon.tsx","components/dialogs.tsx","components/draggable-list.tsx","components/enhanced-table.tsx","components/menu-items.tsx","components/tooltips.tsx","components/inputs.tsx","components/progress.tsx","components/tabs.tsx","components/toolbar.tsx","components/memos.tsx","electron-menu.ts","components/language-switch/language-popover.tsx","components/language-switch/index.tsx","components/account-button/account-popover.tsx","components/account-button/index.tsx","components/toaster.tsx","components/links.tsx","components/color-picker.tsx","urls.ts","redux/camera-slice.ts","localization/i18n.ts","localization/index.ts","point-profile/point-profile.tsx","executable.ts","move-settings.ts","electron-modules.ts","export/utils/misc.ts","redux/project-slice.ts","redux/folders-slice.ts","redux/projections-slice.ts","providers/auth-provider.tsx","providers/tools-provider.tsx","providers/viewer-provider.tsx","providers/task-queue-provider.tsx","providers/global-settings-provider.tsx","providers/websocket-provider.tsx","providers/bookmarks-provider.tsx","viewer/textures/misc/mosaic-logo.png","providers/branding-provider.tsx","viewer/measurements/land-xml-calculation.ts","viewer/textures/tag-icons/basic-pins/index.ts","viewer/textures/tag-icons/basic-pins/basic-pin-large-0.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-1.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-2.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-3.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-4.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-5.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-6.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-7.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-8.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-9.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-10.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-11.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-12.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-13.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-14.png","viewer/textures/tag-icons/basic-pins/basic-pin-large-15.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-0.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-1.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-2.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-3.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-4.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-5.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-6.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-7.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-8.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-9.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-10.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-11.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-12.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-13.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-14.png","viewer/textures/tag-icons/basic-pins/basic-pin-small-15.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-0.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-1.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-2.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-3.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-4.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-5.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-6.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-7.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-8.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-9.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-10.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-11.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-12.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-13.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-14.png","viewer/textures/tag-icons/basic-pins/basic-push-pin-15.png","viewer/textures/tag-icons/traffic-signs/index.ts","viewer/textures/tag-icons/traffic-signs/001-ahead only.png","viewer/textures/tag-icons/traffic-signs/002-crossroads.png","viewer/textures/tag-icons/traffic-signs/003-falling rocks.png","viewer/textures/tag-icons/traffic-signs/004-give way.png","viewer/textures/tag-icons/traffic-signs/005-hump.png","viewer/textures/tag-icons/traffic-signs/006-left turn.png","viewer/textures/tag-icons/traffic-signs/007-parking.png","viewer/textures/tag-icons/traffic-signs/008-level crossing.png","viewer/textures/tag-icons/traffic-signs/009-speed limit.png","viewer/textures/tag-icons/traffic-signs/010-narrow bridge.png","viewer/textures/tag-icons/traffic-signs/011-no bike.png","viewer/textures/tag-icons/traffic-signs/012-no trucks.png","viewer/textures/tag-icons/traffic-signs/013-no alarm.png","viewer/textures/tag-icons/traffic-signs/014-no turn left.png","viewer/textures/tag-icons/traffic-signs/015-no motorcycles.png","viewer/textures/tag-icons/traffic-signs/016-speed limit.png","viewer/textures/tag-icons/traffic-signs/017-no overtaking.png","viewer/textures/tag-icons/traffic-signs/018-pedestrian.png","viewer/textures/tag-icons/traffic-signs/019-no entry.png","viewer/textures/tag-icons/traffic-signs/020-u turn.png","viewer/textures/tag-icons/traffic-signs/021-Two way.png","viewer/textures/tag-icons/traffic-signs/022-pedestrian crossing.png","viewer/textures/tag-icons/traffic-signs/023-right turn.png","viewer/textures/tag-icons/traffic-signs/024-road work.png","viewer/textures/tag-icons/traffic-signs/025-roundabout.png","viewer/textures/tag-icons/traffic-signs/026-pedestrian crossing.png","viewer/textures/tag-icons/traffic-signs/027-Slippery road.png","viewer/textures/tag-icons/traffic-signs/028-traffic lights.png","viewer/textures/tag-icons/traffic-signs/029-turn left.png","viewer/textures/tag-icons/traffic-signs/030-turn right.png","viewer/textures/tag-icons/traffic-signs/031-uneven.png","viewer/textures/tag-icons/traffic-signs/032-maximum.png","viewer/textures/tag-icons/traffic-signs/033-wild animals.png","viewer/textures/tag-icons/uk-road-signs/index.ts","viewer/textures/tag-icons/uk-road-signs/001-narrow.png","viewer/textures/tag-icons/uk-road-signs/002-merge.png","viewer/textures/tag-icons/uk-road-signs/003-curve.png","viewer/textures/tag-icons/uk-road-signs/004-curve.png","viewer/textures/tag-icons/uk-road-signs/005-Junction.png","viewer/textures/tag-icons/uk-road-signs/006-curve.png","viewer/textures/tag-icons/uk-road-signs/007-crossroads.png","viewer/textures/tag-icons/uk-road-signs/008-hump.png","viewer/textures/tag-icons/uk-road-signs/009-uneven.png","viewer/textures/tag-icons/uk-road-signs/010-roundabout.png","viewer/textures/tag-icons/uk-road-signs/011-Two way.png","viewer/textures/tag-icons/uk-road-signs/012-Junction.png","viewer/textures/tag-icons/uk-road-signs/013-Junction.png","viewer/textures/tag-icons/uk-road-signs/014-Two way.png","viewer/textures/tag-icons/uk-road-signs/015-level.png","viewer/textures/tag-icons/uk-road-signs/016-warning.png","viewer/textures/tag-icons/uk-road-signs/017-hump.png","viewer/textures/tag-icons/uk-road-signs/018-dock.png","viewer/textures/tag-icons/uk-road-signs/019-merge.png","viewer/textures/tag-icons/uk-road-signs/020-falling rocks.png","viewer/textures/tag-icons/uk-road-signs/021-speed limit.png","viewer/textures/tag-icons/uk-road-signs/022-speed limit.png","viewer/textures/tag-icons/uk-road-signs/023-speed limit.png","viewer/textures/tag-icons/uk-road-signs/024-speed limit.png","viewer/textures/tag-icons/uk-road-signs/025-speed limit.png","viewer/textures/tag-icons/uk-road-signs/026-speed limit.png","viewer/textures/tag-icons/uk-road-signs/027-speed limit.png","viewer/textures/tag-icons/uk-road-signs/028-priority.png","viewer/textures/tag-icons/uk-road-signs/029-no overtaking.png","viewer/textures/tag-icons/uk-road-signs/030-no turn right.png","viewer/textures/tag-icons/uk-road-signs/031-u turn.png","viewer/textures/tag-icons/uk-road-signs/032-no stopping.png","viewer/textures/tag-icons/uk-road-signs/033-no waiting.png","viewer/textures/tag-icons/uk-road-signs/034-ahead.png","viewer/textures/tag-icons/uk-road-signs/035-turn left.png","viewer/textures/tag-icons/uk-road-signs/036-keep left.png","viewer/textures/tag-icons/uk-road-signs/037-direction.png","viewer/textures/tag-icons/uk-road-signs/038-turn left.png","viewer/textures/tag-icons/uk-road-signs/039-roundabout.png","viewer/textures/tag-icons/uk-road-signs/040-no entry.png","viewer/textures/tag-icons/uk-road-signs/041-parking.png","viewer/textures/tag-icons/uk-road-signs/042-priority.png","viewer/textures/tag-icons/uk-road-signs/043-cul de sac.png","viewer/textures/tag-icons/uk-road-signs/044-countdown.png","viewer/textures/tag-icons/uk-road-signs/045-countdown.png","viewer/textures/tag-icons/uk-road-signs/046-countdown.png","viewer/textures/tag-icons/uk-road-signs/047-hospital.png","viewer/textures/tag-icons/uk-road-signs/048-information.png","viewer/textures/tag-icons/uk-road-signs/049-speed camera.png","viewer/textures/tag-icons/uk-road-signs/050-lane.png","viewer/textures/tag-icons/uk-road-signs/051-end motorway.png","viewer/textures/tag-icons/uk-road-signs/052-motorway.png","viewer/textures/tag-icons/uk-road-signs/053-one way.png","viewer/textures/tag-icons/uk-road-signs/054-direction.png","viewer/textures/tag-icons/uk-road-signs/055-stop.png","viewer/textures/tag-icons/uk-road-signs/056-road.png","viewer/textures/tag-icons/uk-road-signs/057-emergency diversion.png","viewer/textures/tag-icons/uk-road-signs/058-emergency diversion.png","viewer/textures/tag-icons/uk-road-signs/059-emergency diversion.png","viewer/textures/tag-icons/uk-road-signs/060-emergency diversion.png","viewer/textures/tag-icons/package_objects/index.ts","viewer/textures/tag-icons/package_objects/construction--barrier--temporary.png","viewer/textures/tag-icons/package_objects/construction--flat--crosswalk-plain.png","viewer/textures/tag-icons/package_objects/construction--flat--driveway.png","viewer/textures/tag-icons/package_objects/construction--flat--flat-driveway.png","viewer/textures/tag-icons/package_objects/marking--discrete--arrow--left.png","viewer/textures/tag-icons/package_objects/marking--discrete--arrow--right.png","viewer/textures/tag-icons/package_objects/marking--discrete--arrow--split-left-or-straight.png","viewer/textures/tag-icons/package_objects/marking--discrete--arrow--split-right-or-straight.png","viewer/textures/tag-icons/package_objects/marking--discrete--arrow--straight.png","viewer/textures/tag-icons/package_objects/marking--discrete--crosswalk-zebra.png","viewer/textures/tag-icons/package_objects/marking--discrete--give-way-row.png","viewer/textures/tag-icons/package_objects/marking--discrete--give-way-single.png","viewer/textures/tag-icons/package_objects/marking--discrete--other-marking.png","viewer/textures/tag-icons/package_objects/marking--discrete--stop-line.png","viewer/textures/tag-icons/package_objects/marking--discrete--symbol--bicycle.png","viewer/textures/tag-icons/package_objects/marking--discrete--text.png","viewer/textures/tag-icons/package_objects/object--banner.png","viewer/textures/tag-icons/package_objects/object--bench.png","viewer/textures/tag-icons/package_objects/object--bike-rack.png","viewer/textures/tag-icons/package_objects/object--catch-basin.png","viewer/textures/tag-icons/package_objects/object--cctv-camera.png","viewer/textures/tag-icons/package_objects/object--fire-hydrant.png","viewer/textures/tag-icons/package_objects/object--junction-box.png","viewer/textures/tag-icons/package_objects/object--mailbox.png","viewer/textures/tag-icons/package_objects/object--manhole.png","viewer/textures/tag-icons/package_objects/object--parking-meter.png","viewer/textures/tag-icons/package_objects/object--phone-booth.png","viewer/textures/tag-icons/package_objects/object--sign--advertisement.png","viewer/textures/tag-icons/package_objects/object--sign--information.png","viewer/textures/tag-icons/package_objects/object--sign--store.png","viewer/textures/tag-icons/package_objects/object--street-light.png","viewer/textures/tag-icons/package_objects/object--support--pole.png","viewer/textures/tag-icons/package_objects/object--support--traffic-sign-frame.png","viewer/textures/tag-icons/package_objects/object--support--utility-pole.png","viewer/textures/tag-icons/package_objects/object--traffic-cone.png","viewer/textures/tag-icons/package_objects/object--traffic-light.png","viewer/textures/tag-icons/package_objects/object--trash-can.png","viewer/textures/tag-icons/package_objects/object--water-valve.png","viewer/textures/tag-icons/package_signs/complementary--accident-area--g1.png","viewer/textures/tag-icons/package_signs/complementary--accident-area--g2.png","viewer/textures/tag-icons/package_signs/complementary--accident-area--g3.png","viewer/textures/tag-icons/package_signs/complementary--accident-area--g4.png","viewer/textures/tag-icons/package_signs/complementary--advisory-exit-or-ramp-speed--g1.png","viewer/textures/tag-icons/package_signs/complementary--bicycles--g1.png","viewer/textures/tag-icons/package_signs/complementary--bicycles-and-pedestrians-detour--g1.png","viewer/textures/tag-icons/package_signs/complementary--bicycles-or-pedestrians-detour--g1.png","viewer/textures/tag-icons/package_signs/complementary--bicycles-turn-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--bike-route--g1.png","viewer/textures/tag-icons/package_signs/complementary--bike-route--g3.png","viewer/textures/tag-icons/package_signs/complementary--both-directions--g1.png","viewer/textures/tag-icons/package_signs/complementary--both-directions--g2.png","viewer/textures/tag-icons/package_signs/complementary--buses--g1.png","viewer/textures/tag-icons/package_signs/complementary--buses-and-trucks--g1.png","viewer/textures/tag-icons/package_signs/complementary--camera--g1.png","viewer/textures/tag-icons/package_signs/complementary--camera--g2.png","viewer/textures/tag-icons/package_signs/complementary--camera--g3.png","viewer/textures/tag-icons/package_signs/complementary--camera--g4.png","viewer/textures/tag-icons/package_signs/complementary--camera--g5.png","viewer/textures/tag-icons/package_signs/complementary--caravan-trailers--g2.png","viewer/textures/tag-icons/package_signs/complementary--caravan-trailers--g3.png","viewer/textures/tag-icons/package_signs/complementary--caravans--g2.png","viewer/textures/tag-icons/package_signs/complementary--carts--g1.png","viewer/textures/tag-icons/package_signs/complementary--chevron-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--chevron-left--g2.png","viewer/textures/tag-icons/package_signs/complementary--chevron-left--g3.png","viewer/textures/tag-icons/package_signs/complementary--chevron-left--g4.png","viewer/textures/tag-icons/package_signs/complementary--chevron-left--g5.png","viewer/textures/tag-icons/package_signs/complementary--chevron-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--chevron-right--g2.png","viewer/textures/tag-icons/package_signs/complementary--chevron-right--g3.png","viewer/textures/tag-icons/package_signs/complementary--chevron-right--g4.png","viewer/textures/tag-icons/package_signs/complementary--chevron-right--g5.png","viewer/textures/tag-icons/package_signs/complementary--dangerous-or-pollutant-good--g1.png","viewer/textures/tag-icons/package_signs/complementary--dead-end--g1.png","viewer/textures/tag-icons/package_signs/complementary--detour--g1.png","viewer/textures/tag-icons/package_signs/complementary--disabled-persons--g1.png","viewer/textures/tag-icons/package_signs/complementary--distance--g1.png","viewer/textures/tag-icons/package_signs/complementary--distance--g2.png","viewer/textures/tag-icons/package_signs/complementary--distance--g3.png","viewer/textures/tag-icons/package_signs/complementary--end-of-road-works--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-bicycles--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-bicycles--g2.png","viewer/textures/tag-icons/package_signs/complementary--except-buses--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-carts--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-motorcycles--g2.png","viewer/textures/tag-icons/package_signs/complementary--except-polluting-level-green--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-polluting-level-green-yellow--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-polluting-level-green-yellow-red--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-tractors--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-tractors--g2.png","viewer/textures/tag-icons/package_signs/complementary--except-trailers--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-trailers--g2.png","viewer/textures/tag-icons/package_signs/complementary--except-trains--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-trams--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-trucks--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-vehicles--g1.png","viewer/textures/tag-icons/package_signs/complementary--except-vehicles--g2.png","viewer/textures/tag-icons/package_signs/complementary--go-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--go-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--go-straight-or-turn-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--go-straight-or-turn-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--height-limit--g1.png","viewer/textures/tag-icons/package_signs/complementary--height-limit--g2.png","viewer/textures/tag-icons/package_signs/complementary--including-bicycles-and-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/complementary--including-buses-vehicles--g1.png","viewer/textures/tag-icons/package_signs/complementary--keep-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--keep-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--lane-control--g1.png","viewer/textures/tag-icons/package_signs/complementary--lane-control--g2.png","viewer/textures/tag-icons/package_signs/complementary--lane-control--g3.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-10--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-15--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-20--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-25--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-30--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-35--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-40--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-45--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-50--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-55--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-60--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-65--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-70--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-75--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-80--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-85--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-90--g1.png","viewer/textures/tag-icons/package_signs/complementary--maximum-speed-limit-95--g1.png","viewer/textures/tag-icons/package_signs/complementary--motorcycles--g1.png","viewer/textures/tag-icons/package_signs/complementary--motorcycles--g2.png","viewer/textures/tag-icons/package_signs/complementary--motorcycles--g3.png","viewer/textures/tag-icons/package_signs/complementary--motorcycles--g4.png","viewer/textures/tag-icons/package_signs/complementary--obstacle-delineator--g1.png","viewer/textures/tag-icons/package_signs/complementary--obstacle-delineator--g2.png","viewer/textures/tag-icons/package_signs/complementary--obstacle-delineator--g3.png","viewer/textures/tag-icons/package_signs/complementary--one-direction-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--one-direction-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--pass-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--pass-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--pedestrians-and-bicycles--g1.png","viewer/textures/tag-icons/package_signs/complementary--pedestrians-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--pedestrians-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--photo-enforced--g1.png","viewer/textures/tag-icons/package_signs/complementary--playground--g1.png","viewer/textures/tag-icons/package_signs/complementary--priority-route-at-intersection--g1.png","viewer/textures/tag-icons/package_signs/complementary--priority-route-at-intersection--g2.png","viewer/textures/tag-icons/package_signs/complementary--priority-route-at-intersection--g3.png","viewer/textures/tag-icons/package_signs/complementary--priority-route-at-intersection--g4.png","viewer/textures/tag-icons/package_signs/complementary--priority-route-at-intersection--g5.png","viewer/textures/tag-icons/package_signs/complementary--priority-route-at-intersection--g6.png","viewer/textures/tag-icons/package_signs/complementary--railroad--g1.png","viewer/textures/tag-icons/package_signs/complementary--railroad--g2.png","viewer/textures/tag-icons/package_signs/complementary--railroad--g3.png","viewer/textures/tag-icons/package_signs/complementary--restriction-in-both-directions--g1.png","viewer/textures/tag-icons/package_signs/complementary--roundabout-go-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--roundabout-go-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--roundabout-go-straight--g1.png","viewer/textures/tag-icons/package_signs/complementary--slippery-for-caravan-trailers--g1.png","viewer/textures/tag-icons/package_signs/complementary--snow--g2.png","viewer/textures/tag-icons/package_signs/complementary--snow--g4.png","viewer/textures/tag-icons/package_signs/complementary--snow--g5.png","viewer/textures/tag-icons/package_signs/complementary--snowmobiles--g1.png","viewer/textures/tag-icons/package_signs/complementary--soft-shoulder--g1.png","viewer/textures/tag-icons/package_signs/complementary--soft-shoulder--g2.png","viewer/textures/tag-icons/package_signs/complementary--steep-ascent--g1.png","viewer/textures/tag-icons/package_signs/complementary--steep-descent--g1.png","viewer/textures/tag-icons/package_signs/complementary--time-restrictions--g1.png","viewer/textures/tag-icons/package_signs/complementary--time-restrictions--g3.png","viewer/textures/tag-icons/package_signs/complementary--tow-away-zone--g1.png","viewer/textures/tag-icons/package_signs/complementary--tow-away-zone--g3.png","viewer/textures/tag-icons/package_signs/complementary--tractors--g1.png","viewer/textures/tag-icons/package_signs/complementary--traffic-queues--g1.png","viewer/textures/tag-icons/package_signs/complementary--trailers--g1.png","viewer/textures/tag-icons/package_signs/complementary--trailers--g2.png","viewer/textures/tag-icons/package_signs/complementary--trailers--g3.png","viewer/textures/tag-icons/package_signs/complementary--trailers--g4.png","viewer/textures/tag-icons/package_signs/complementary--trains--g1.png","viewer/textures/tag-icons/package_signs/complementary--trams--g1.png","viewer/textures/tag-icons/package_signs/complementary--trees--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks--g2.png","viewer/textures/tag-icons/package_signs/complementary--trucks--g3.png","viewer/textures/tag-icons/package_signs/complementary--trucks-and-trailers--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-buses-trailers--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-go-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-go-left-ahead--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-go-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-go-right-ahead--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-go-straight--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-turn-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--trucks-turn-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--turn-left--g1.png","viewer/textures/tag-icons/package_signs/complementary--turn-left--g2.png","viewer/textures/tag-icons/package_signs/complementary--turn-right--g1.png","viewer/textures/tag-icons/package_signs/complementary--turn-right--g2.png","viewer/textures/tag-icons/package_signs/complementary--two-way-traffic--g1.png","viewer/textures/tag-icons/package_signs/complementary--two-way-traffic--g2.png","viewer/textures/tag-icons/package_signs/complementary--two-way-traffic--g3.png","viewer/textures/tag-icons/package_signs/complementary--two-way-traffic--g4.png","viewer/textures/tag-icons/package_signs/complementary--two-way-traffic--g5.png","viewer/textures/tag-icons/package_signs/complementary--vehicles--g1.png","viewer/textures/tag-icons/package_signs/complementary--vehicles--g2.png","viewer/textures/tag-icons/package_signs/complementary--vehicles-or-buses--g1.png","viewer/textures/tag-icons/package_signs/complementary--weekends-or-holidays--g1.png","viewer/textures/tag-icons/package_signs/complementary--weight-limit--g1.png","viewer/textures/tag-icons/package_signs/complementary--when-foggy--g1.png","viewer/textures/tag-icons/package_signs/complementary--when-rainy--g1.png","viewer/textures/tag-icons/package_signs/complementary--when-rainy--g2.png","viewer/textures/tag-icons/package_signs/complementary--when-rainy--g3.png","viewer/textures/tag-icons/package_signs/complementary--when-snowy--g1.png","viewer/textures/tag-icons/package_signs/complementary--when-snowy--g2.png","viewer/textures/tag-icons/package_signs/complementary--when-snowy-or-rainy--g1.png","viewer/textures/tag-icons/package_signs/complementary--when-snowy-or-rainy--g2.png","viewer/textures/tag-icons/package_signs/complementary--when-wet--g1.png","viewer/textures/tag-icons/package_signs/complementary--width-limit--g1.png","viewer/textures/tag-icons/package_signs/complementary--working-days--g1.png","viewer/textures/tag-icons/package_signs/information--airport--g1.png","viewer/textures/tag-icons/package_signs/information--airport--g2.png","viewer/textures/tag-icons/package_signs/information--bicycle-lane--g1.png","viewer/textures/tag-icons/package_signs/information--bicycles-both-ways--g1.png","viewer/textures/tag-icons/package_signs/information--bicycles-crossing--g1.png","viewer/textures/tag-icons/package_signs/information--bicycles-crossing--g2.png","viewer/textures/tag-icons/package_signs/information--bicycles-crossing--g3.png","viewer/textures/tag-icons/package_signs/information--bike-route--g1.png","viewer/textures/tag-icons/package_signs/information--bike-route--g2.png","viewer/textures/tag-icons/package_signs/information--built-up-area--g1.png","viewer/textures/tag-icons/package_signs/information--built-up-area--g2.png","viewer/textures/tag-icons/package_signs/information--bus-lane-straight--g1.png","viewer/textures/tag-icons/package_signs/information--bus-stop--g1.png","viewer/textures/tag-icons/package_signs/information--bus-stop--g2.png","viewer/textures/tag-icons/package_signs/information--camera--g1.png","viewer/textures/tag-icons/package_signs/information--camera--g2.png","viewer/textures/tag-icons/package_signs/information--camera--g3.png","viewer/textures/tag-icons/package_signs/information--camp--g1.png","viewer/textures/tag-icons/package_signs/information--camp--g2.png","viewer/textures/tag-icons/package_signs/information--car-pool-lane--g1.png","viewer/textures/tag-icons/package_signs/information--caravan-parking--g1.png","viewer/textures/tag-icons/package_signs/information--caravan-trailer-parking--g1.png","viewer/textures/tag-icons/package_signs/information--cargo-loading-zone--g1.png","viewer/textures/tag-icons/package_signs/information--central-lane--g1.png","viewer/textures/tag-icons/package_signs/information--charging-station--g1.png","viewer/textures/tag-icons/package_signs/information--children--g1.png","viewer/textures/tag-icons/package_signs/information--children--g2.png","viewer/textures/tag-icons/package_signs/information--children-crossing--g5.png","viewer/textures/tag-icons/package_signs/information--cycling-two-abreast-permitted--g1.png","viewer/textures/tag-icons/package_signs/information--dead-end--g1.png","viewer/textures/tag-icons/package_signs/information--dead-end--g2.png","viewer/textures/tag-icons/package_signs/information--dead-end--g3.png","viewer/textures/tag-icons/package_signs/information--dead-end--g4.png","viewer/textures/tag-icons/package_signs/information--dead-end-except-bicycles--g1.png","viewer/textures/tag-icons/package_signs/information--dead-end-except-bicycles-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/information--dead-end-except-bicycles-and-pedestrians--g2.png","viewer/textures/tag-icons/package_signs/information--dead-end-left--g1.png","viewer/textures/tag-icons/package_signs/information--dead-end-left--g2.png","viewer/textures/tag-icons/package_signs/information--dead-end-right--g1.png","viewer/textures/tag-icons/package_signs/information--dead-end-right--g2.png","viewer/textures/tag-icons/package_signs/information--dead-end-right--g3.png","viewer/textures/tag-icons/package_signs/information--directions--g1.png","viewer/textures/tag-icons/package_signs/information--disabled-persons--g1.png","viewer/textures/tag-icons/package_signs/information--disabled-persons--g2.png","viewer/textures/tag-icons/package_signs/information--disabled-persons--g3.png","viewer/textures/tag-icons/package_signs/information--emergency-facility--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-advisory-maximum-speed-limit-20--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-advisory-maximum-speed-limit-40--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-advisory-maximum-speed-limit-60--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-advisory-maximum-speed-limit-70--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-advisory-maximum-speed-limit-80--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-advisory-maximum-speed-limit-90--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-bicycle-lane--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-built-up-area--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-built-up-area--g2.png","viewer/textures/tag-icons/package_signs/information--end-of-built-up-area--g3.png","viewer/textures/tag-icons/package_signs/information--end-of-built-up-area--g4.png","viewer/textures/tag-icons/package_signs/information--end-of-car-pool-lane--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-limited-access-road--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-living-street--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-living-street--g2.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-10--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-20--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-25--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-30--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-35--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-40--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-50--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-60--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-70--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-75--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-80--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-90--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-100--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-110--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-120--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-minimum-speed-130--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-motorway--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-overtaking-permitted-heavy-good-vehicles--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-road-works--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-tunnel--g1.png","viewer/textures/tag-icons/package_signs/information--end-of-tunnel--g2.png","viewer/textures/tag-icons/package_signs/information--end-of-two-way-traffic--g1.png","viewer/textures/tag-icons/package_signs/information--equestrians-permitted--g1.png","viewer/textures/tag-icons/package_signs/information--exit-ahead--g1.png","viewer/textures/tag-icons/package_signs/information--exit-ahead--g2.png","viewer/textures/tag-icons/package_signs/information--exit-ahead--g3.png","viewer/textures/tag-icons/package_signs/information--flight-port--g1.png","viewer/textures/tag-icons/package_signs/information--food--g1.png","viewer/textures/tag-icons/package_signs/information--food--g2.png","viewer/textures/tag-icons/package_signs/information--gas-station--g1.png","viewer/textures/tag-icons/package_signs/information--gas-station--g2.png","viewer/textures/tag-icons/package_signs/information--gas-station--g3.png","viewer/textures/tag-icons/package_signs/information--general-speed-limit-at-city-border--g1.png","viewer/textures/tag-icons/package_signs/information--go-left--g1.png","viewer/textures/tag-icons/package_signs/information--go-right--g1.png","viewer/textures/tag-icons/package_signs/information--go-straight--g1.png","viewer/textures/tag-icons/package_signs/information--go-straight-or-left--g1.png","viewer/textures/tag-icons/package_signs/information--go-straight-or-right--g1.png","viewer/textures/tag-icons/package_signs/information--go-straight-or-turn-left--g1.png","viewer/textures/tag-icons/package_signs/information--go-straight-or-turn-right--g1.png","viewer/textures/tag-icons/package_signs/information--hazardous-goods-vehicles-lane--g1.png","viewer/textures/tag-icons/package_signs/information--height-limit--g1.png","viewer/textures/tag-icons/package_signs/information--height-limit--g2.png","viewer/textures/tag-icons/package_signs/information--highway-directions--g1.png","viewer/textures/tag-icons/package_signs/information--highway-exit--g1.png","viewer/textures/tag-icons/package_signs/information--highway-interchange--g1.png","viewer/textures/tag-icons/package_signs/information--highway-interstate-route--g1.png","viewer/textures/tag-icons/package_signs/information--highway-interstate-route--g2.png","viewer/textures/tag-icons/package_signs/information--highway-preferential-lane--g1.png","viewer/textures/tag-icons/package_signs/information--highway-preferential-lane--g2.png","viewer/textures/tag-icons/package_signs/information--highway-reference-location--g1.png","viewer/textures/tag-icons/package_signs/information--highway-reference-location--g2.png","viewer/textures/tag-icons/package_signs/information--hiking--g1.png","viewer/textures/tag-icons/package_signs/information--hospital--g1.png","viewer/textures/tag-icons/package_signs/information--hurricane-evacuation-route--g1.png","viewer/textures/tag-icons/package_signs/information--interstate-route--g1.png","viewer/textures/tag-icons/package_signs/information--lane-control-intersections--g1.png","viewer/textures/tag-icons/package_signs/information--lane-control-left-turn--g1.png","viewer/textures/tag-icons/package_signs/information--lane-control-multiple-lanes--g1.png","viewer/textures/tag-icons/package_signs/information--lane-control-multiple-lanes--g2.png","viewer/textures/tag-icons/package_signs/information--lane-control-right-turn--g1.png","viewer/textures/tag-icons/package_signs/information--limited-access-road--g1.png","viewer/textures/tag-icons/package_signs/information--litter-container--g1.png","viewer/textures/tag-icons/package_signs/information--living-street--g1.png","viewer/textures/tag-icons/package_signs/information--living-street--g2.png","viewer/textures/tag-icons/package_signs/information--living-street--g3.png","viewer/textures/tag-icons/package_signs/information--lodging--g1.png","viewer/textures/tag-icons/package_signs/information--lodging--g2.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-10--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-20--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-25--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-30--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-35--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-40--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-50--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-60--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-70--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-75--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-80--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-90--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-100--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-110--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-120--g1.png","viewer/textures/tag-icons/package_signs/information--minimum-speed-130--g1.png","viewer/textures/tag-icons/package_signs/information--motorway--g1.png","viewer/textures/tag-icons/package_signs/information--motorway-exit-ahead--g1.png","viewer/textures/tag-icons/package_signs/information--motorway-exit-ahead--g2.png","viewer/textures/tag-icons/package_signs/information--motorway-exit-ahead--g3.png","viewer/textures/tag-icons/package_signs/information--overtaking-allowed-heavy-good-vehicles--g1.png","viewer/textures/tag-icons/package_signs/information--parallel-parking--g1.png","viewer/textures/tag-icons/package_signs/information--park-and-ride--g1.png","viewer/textures/tag-icons/package_signs/information--park-and-ride--g2.png","viewer/textures/tag-icons/package_signs/information--parking--g1.png","viewer/textures/tag-icons/package_signs/information--parking--g2.png","viewer/textures/tag-icons/package_signs/information--parking--g3.png","viewer/textures/tag-icons/package_signs/information--parking--g4.png","viewer/textures/tag-icons/package_signs/information--parking--g5.png","viewer/textures/tag-icons/package_signs/information--parking--g6.png","viewer/textures/tag-icons/package_signs/information--parking-area--g1.png","viewer/textures/tag-icons/package_signs/information--parking-with-restrictions--g1.png","viewer/textures/tag-icons/package_signs/information--pass-on-either-side--g1.png","viewer/textures/tag-icons/package_signs/information--passenger-loading-zone--g1.png","viewer/textures/tag-icons/package_signs/information--pedestrians-crossing--g1.png","viewer/textures/tag-icons/package_signs/information--pedestrians-crossing--g2.png","viewer/textures/tag-icons/package_signs/information--pedestrians-crossing--g3.png","viewer/textures/tag-icons/package_signs/information--pedestrians-only--g4.png","viewer/textures/tag-icons/package_signs/information--pedestrians-permitted--g1.png","viewer/textures/tag-icons/package_signs/information--perpendicular-parking--g1.png","viewer/textures/tag-icons/package_signs/information--picnic-site--g1.png","viewer/textures/tag-icons/package_signs/information--playground--g1.png","viewer/textures/tag-icons/package_signs/information--recreational-vehicle-sanitary-station--g1.png","viewer/textures/tag-icons/package_signs/information--recycle-collection-center--g1.png","viewer/textures/tag-icons/package_signs/information--rest-area--g1.png","viewer/textures/tag-icons/package_signs/information--road-bump--g1.png","viewer/textures/tag-icons/package_signs/information--road-skating--g1.png","viewer/textures/tag-icons/package_signs/information--safety-zone--g1.png","viewer/textures/tag-icons/package_signs/information--safety-zone--g2.png","viewer/textures/tag-icons/package_signs/information--safety-zone--g3.png","viewer/textures/tag-icons/package_signs/information--shared-path-vehicles-and-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/information--stairs--g1.png","viewer/textures/tag-icons/package_signs/information--stairs--g2.png","viewer/textures/tag-icons/package_signs/information--stairs--g3.png","viewer/textures/tag-icons/package_signs/information--stairs--g4.png","viewer/textures/tag-icons/package_signs/information--stop-line--g1.png","viewer/textures/tag-icons/package_signs/information--stop-permitted--g1.png","viewer/textures/tag-icons/package_signs/information--street-name-one-line--g1.png","viewer/textures/tag-icons/package_signs/information--street-name-three-lines--g1.png","viewer/textures/tag-icons/package_signs/information--street-name-two-lines--g1.png","viewer/textures/tag-icons/package_signs/information--subway--g1.png","viewer/textures/tag-icons/package_signs/information--telephone--g1.png","viewer/textures/tag-icons/package_signs/information--telephone--g2.png","viewer/textures/tag-icons/package_signs/information--telephone-device-for-the-deaf--g1.png","viewer/textures/tag-icons/package_signs/information--toll-station--g1.png","viewer/textures/tag-icons/package_signs/information--tourism-information--g1.png","viewer/textures/tag-icons/package_signs/information--tourist-attraction--g1.png","viewer/textures/tag-icons/package_signs/information--traffic-merges-left--g1.png","viewer/textures/tag-icons/package_signs/information--traffic-merges-right--g1.png","viewer/textures/tag-icons/package_signs/information--trail-crossing--g1.png","viewer/textures/tag-icons/package_signs/information--trail-crossing--g2.png","viewer/textures/tag-icons/package_signs/information--trail-crossing--g3.png","viewer/textures/tag-icons/package_signs/information--trailer-camping--g1.png","viewer/textures/tag-icons/package_signs/information--train-or-light-rail-station--g1.png","viewer/textures/tag-icons/package_signs/information--tram-bus-stop--g1.png","viewer/textures/tag-icons/package_signs/information--tram-bus-stop--g2.png","viewer/textures/tag-icons/package_signs/information--trams-crossing--g1.png","viewer/textures/tag-icons/package_signs/information--truck-lane-left--g1.png","viewer/textures/tag-icons/package_signs/information--truck-parking--g1.png","viewer/textures/tag-icons/package_signs/information--truck-trailer-lane-right--g1.png","viewer/textures/tag-icons/package_signs/information--truck-trailer-lane-straight--g1.png","viewer/textures/tag-icons/package_signs/information--trucks-both-ways--g1.png","viewer/textures/tag-icons/package_signs/information--trucks-only--g1.png","viewer/textures/tag-icons/package_signs/information--tsunami-evacuation_route--g1.png","viewer/textures/tag-icons/package_signs/information--tunnel--g1.png","viewer/textures/tag-icons/package_signs/information--tunnel--g2.png","viewer/textures/tag-icons/package_signs/information--tunnel--g3.png","viewer/textures/tag-icons/package_signs/information--tunnel-ahead--g1.png","viewer/textures/tag-icons/package_signs/information--turn-left--g1.png","viewer/textures/tag-icons/package_signs/information--turn-left-ahead--g1.png","viewer/textures/tag-icons/package_signs/information--turn-right--g1.png","viewer/textures/tag-icons/package_signs/information--turn-right-ahead--g1.png","viewer/textures/tag-icons/package_signs/information--urban-area--g1.png","viewer/textures/tag-icons/package_signs/information--vehicles-on-rails--g1.png","viewer/textures/tag-icons/package_signs/information--water-protection-zone--g1.png","viewer/textures/tag-icons/package_signs/information--weight-and-height-limit--g1.png","viewer/textures/tag-icons/package_signs/information--weight-limit--g1.png","viewer/textures/tag-icons/package_signs/information--wireless-internet--g1.png","viewer/textures/tag-icons/package_signs/regulatory--advisory-maximum-speed-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--all-directions-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--all-way--g1.png","viewer/textures/tag-icons/package_signs/regulatory--atvs-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--axle-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--axle-limit--g2.png","viewer/textures/tag-icons/package_signs/regulatory--bicycle-lane-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycle-parking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-and-buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-only--g3.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-only--g4.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-push-button--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-push-button--g2.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-stop-on-red--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-wrong-way--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bicycles-yield-or-use-signal--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bike-route--g1.png","viewer/textures/tag-icons/package_signs/regulatory--building-direction--g1.png","viewer/textures/tag-icons/package_signs/regulatory--bus-priority-lane--g1.png","viewer/textures/tag-icons/package_signs/regulatory--buses-and-taxi-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--buses-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--circular-intersection--g1.png","viewer/textures/tag-icons/package_signs/regulatory--circular-intersection--g2.png","viewer/textures/tag-icons/package_signs/regulatory--circular-intersection--g3.png","viewer/textures/tag-icons/package_signs/regulatory--circular-intersection--g4.png","viewer/textures/tag-icons/package_signs/regulatory--cross-only-on-green--g1.png","viewer/textures/tag-icons/package_signs/regulatory--cross-only-on-pedestrian-signal--g1.png","viewer/textures/tag-icons/package_signs/regulatory--crosswalk-stop-on-red--g1.png","viewer/textures/tag-icons/package_signs/regulatory--cycling-restriction--g1.png","viewer/textures/tag-icons/package_signs/regulatory--cyclists-dismount-and-walk--g1.png","viewer/textures/tag-icons/package_signs/regulatory--detour-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--detour-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--divided-highway-crossing--g1.png","viewer/textures/tag-icons/package_signs/regulatory--divided-highway-ends--g1.png","viewer/textures/tag-icons/package_signs/regulatory--divided-highway-starts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--do-not-block-intersection--g1.png","viewer/textures/tag-icons/package_signs/regulatory--do-not-pass--g1.png","viewer/textures/tag-icons/package_signs/regulatory--do-not-stop-on-tracks--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-all-directions-on-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-all-directions-on-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-bicyclists-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-go-left-or-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-go-straight-on-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-go-straight-on-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-turn-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-turn-left-no-u-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-turn-left-or-straight--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-lanes-turn-right-or-straight--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-bicycles-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-bicycles-and-pedestrians--g2.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-bicycles-and-pedestrians--g3.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-equestrians-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-equestrians-and-pedestrians-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-pedestrians-and-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-pedestrians-and-bicycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-pedestrians-and-equestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-path-pedestrians-bicycles-and-equestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-speed-limits--g1.png","viewer/textures/tag-icons/package_signs/regulatory--dual-speed-limits--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-bicycles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-bicycles-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-bus-and-taxi-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-buses-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-cycling-restriction--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-dual-path-bicycles-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-dual-path-pedestrians-and-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-equestrians-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-low-beam-headlights--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-10--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-10--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-20--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-20--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-25--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-25--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-30--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-30--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-35--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-35--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-40--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-40--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-50--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-50--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-60--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-60--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-65--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-65--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-70--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-70--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-75--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-75--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-80--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-80--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-90--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-90--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-100--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-100--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-110--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-110--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-120--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-120--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-130--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit-130--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-maximum-speed-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-mopeds-and-bicycles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-heavy-goods-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-horn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking--g3.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking--g4.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking--g5.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-overtaking-by-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-parking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-parking--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-no-parking-or-stopping--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-one-way-straight--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-parking-zone--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-parking-zone--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-pedestrians-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-pedestrians-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-pedestrians-only--g3.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-pedestrians-only--g4.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-priority-road--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-prohibition--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-school-zone--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-shared-path-bicycles-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-shared-path-pedestrians-and-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-snow-chains--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-snow-chains--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-snowmobiles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-speed-limit-zone--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-speed-limit-zone--g2.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-speed-limit-zone--g3.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-tractors-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-trams-and-buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-trams-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-trucks-and-buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-trucks-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--end-of-trucks-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--equestrians-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--except-railroad-crossing--g1.png","viewer/textures/tag-icons/package_signs/regulatory--fine-for-littering--g1.png","viewer/textures/tag-icons/package_signs/regulatory--give-way-to-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--give-way-to-oncoming-traffic--g1.png","viewer/textures/tag-icons/package_signs/regulatory--give-way-to-oncoming-traffic--g2.png","viewer/textures/tag-icons/package_signs/regulatory--go-left-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--go-right-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight--g1.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight--g3.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-or-turn-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-or-turn-left--g2.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-or-turn-left--g3.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-or-turn-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-or-turn-right--g2.png","viewer/textures/tag-icons/package_signs/regulatory--go-straight-or-turn-right--g3.png","viewer/textures/tag-icons/package_signs/regulatory--heavy-goods-vehicles-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--height-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--high-beam-headlights--g1.png","viewer/textures/tag-icons/package_signs/regulatory--horn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--in-street-pedestrian-crossing--g1.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g2.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g3.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g4.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g5.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g6.png","viewer/textures/tag-icons/package_signs/regulatory--keep-left--g7.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g2.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g3.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g4.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g5.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g6.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g7.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g8.png","viewer/textures/tag-icons/package_signs/regulatory--keep-right--g9.png","viewer/textures/tag-icons/package_signs/regulatory--lane-control--g1.png","viewer/textures/tag-icons/package_signs/regulatory--left-turn-yield-on-green--g1.png","viewer/textures/tag-icons/package_signs/regulatory--length-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--length-limit--g2.png","viewer/textures/tag-icons/package_signs/regulatory--light-rail-divided-highway--g1.png","viewer/textures/tag-icons/package_signs/regulatory--light-rail-do-not-pass--g1.png","viewer/textures/tag-icons/package_signs/regulatory--light-rail-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--look--g1.png","viewer/textures/tag-icons/package_signs/regulatory--low-beam-headlights--g1.png","viewer/textures/tag-icons/package_signs/regulatory--low-beam-headlights--g2.png","viewer/textures/tag-icons/package_signs/regulatory--low-beam-headlights--g3.png","viewer/textures/tag-icons/package_signs/regulatory--low-speed-vehicle-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-5--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-5--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-10--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-10--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-15--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-15--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-20--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-20--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-25--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-25--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-30--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-30--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-35--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-35--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-40--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-40--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-45--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-45--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-50--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-50--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-55--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-60--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-60--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-65--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-65--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-70--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-70--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-75--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-80--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-80--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-85--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-90--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-90--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-100--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-100--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-110--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-110--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-120--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-120--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-130--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-130--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-5--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-5--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-10--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-10--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-10--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-15--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-15--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-20--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-20--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-20--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-25--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-25--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-25--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-30--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-30--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-30--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-35--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-35--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-35--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-40--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-40--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-40--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-45--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-45--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-50--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-50--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-50--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-55--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-55--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-60--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-60--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-60--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-65--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-65--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-70--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-70--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-70--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-75--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-75--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-75--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-80--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-80--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-80--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-85--g2.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-85--g3.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-90--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-100--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-110--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-120--g1.png","viewer/textures/tag-icons/package_signs/regulatory--maximum-speed-limit-led-130--g1.png","viewer/textures/tag-icons/package_signs/regulatory--minimum-safe-distance--g1.png","viewer/textures/tag-icons/package_signs/regulatory--minimum-safe-distance--g2.png","viewer/textures/tag-icons/package_signs/regulatory--mopeds-and-bicycles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--motorcycles-and-bicycles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--motorcycles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--motorcycles-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-5--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-10--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-15--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-20--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-25--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-30--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-35--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-40--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-45--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-50--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-55--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-60--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-65--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-70--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-75--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-80--g1.png","viewer/textures/tag-icons/package_signs/regulatory--night-speed-limit-85--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-abnormal-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-atvs--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles-carts-or-hand-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles-mopeds-or-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles-mopeds-or-motorcycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles-or-hand-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles-or-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-bicycles-tractors-or-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-buses--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-buses--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-buses--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-caravan-trailers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-caravans--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-caravans-or-caravan-trailers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-cargo-loading--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-carts--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-carts--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-carts-or-tractors--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-construction-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-entry--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-equestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-go-straight-or-turn-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-go-straight-or-turn-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-good-trailers--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-goods-vehicle-trailers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-hand-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-hand-carts--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-hand-carts-or-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-hawkers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles-or-buses--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles-or-tractors--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-heavy-goods-vehicles-or-trailers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-horizontal-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-horn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-horn--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-lane-change-to-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-lane-change-to-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-learner-drivers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-left-or-u-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-left-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-left-turn--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-left-turn--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-left-turn--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-left-turn--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-low-speed-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-mopeds-or-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicle-trailers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles--g6.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles--g7.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles-except-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles-except-motorcycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles-except-motorcycles--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles-or-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles-or-buses--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motor-vehicles-or-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-motorcycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking--g6.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking--g7.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking-atvs--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-overtaking-by-heavy-goods-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g6.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g7.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g8.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking--g9.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-bicycles-or-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-bus-stop--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-or-no-stopping--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-or-no-stopping--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-or-no-stopping--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-or-no-stopping--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-parking-or-no-stopping--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-passenger-loading--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians--g6.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians-bicycles-animals-or-hand-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians-or-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians-or-bicycles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-pedestrians-or-bicycles--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-rickshaws--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-rickshaws--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-rickshaws--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-right-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-right-turn--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-right-turn--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-right-turn-on-red--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-skiing--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-snowmobiles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-snowmobiles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-snowmobiles-or-atvs--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping--g5.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping--g6.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping--g7.png","viewer/textures/tag-icons/package_signs/regulatory--no-stopping-on-pavement--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-straight-through--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-straight-through--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-studded-snow-chains--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-through-trucks--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-tour-buses--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-tractors--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-tractors-mopeds-or-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-tractors-or-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-trailers--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-tricycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-tricycles-or-hand-carts--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-turn-on-red--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-turn-on-red--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-turn-on-red--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-turns--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-turns--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-two-stage-right-turn-for-mopeds--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-u-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-u-turn--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-u-turn--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-dangerous-goods--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-dangerous-goods--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-dangerous-goods--g3.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-dangerous-goods--g4.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-dangerous-water-pollutants--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-dangerous-water-pollutants--g2.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-explosives--g1.png","viewer/textures/tag-icons/package_signs/regulatory--no-vehicles-carrying-explosives-or-dangerous-water-pollutants--g1.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-left--g2.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-left--g3.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-right--g2.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-right--g3.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-straight--g1.png","viewer/textures/tag-icons/package_signs/regulatory--one-way-straight--g3.png","viewer/textures/tag-icons/package_signs/regulatory--parking-fee-station--g1.png","viewer/textures/tag-icons/package_signs/regulatory--parking-restrictions--g1.png","viewer/textures/tag-icons/package_signs/regulatory--parking-restrictions--g2.png","viewer/textures/tag-icons/package_signs/regulatory--parking-restrictions--g3.png","viewer/textures/tag-icons/package_signs/regulatory--pass-on-either-side--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pass-on-either-side--g2.png","viewer/textures/tag-icons/package_signs/regulatory--pass-on-either-side--g3.png","viewer/textures/tag-icons/package_signs/regulatory--pass-with-care--g1.png","viewer/textures/tag-icons/package_signs/regulatory--passing-lane-ahead--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-bicycles-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-keep-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-only--g2.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-only--g3.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-priority-zone--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-push-button--g1.png","viewer/textures/tag-icons/package_signs/regulatory--pedestrians-push-button--g2.png","viewer/textures/tag-icons/package_signs/regulatory--priority-over-oncoming-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--priority-over-oncoming-vehicles--g2.png","viewer/textures/tag-icons/package_signs/regulatory--priority-road--g1.png","viewer/textures/tag-icons/package_signs/regulatory--priority-road--g2.png","viewer/textures/tag-icons/package_signs/regulatory--radar-enforced--g1.png","viewer/textures/tag-icons/package_signs/regulatory--reserved-parking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--reversible-lanes--g1.png","viewer/textures/tag-icons/package_signs/regulatory--reversible-lanes--g2.png","viewer/textures/tag-icons/package_signs/regulatory--road-closed--g1.png","viewer/textures/tag-icons/package_signs/regulatory--road-closed--g2.png","viewer/textures/tag-icons/package_signs/regulatory--road-closed-to-vehicles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--road-closed-to-vehicles--g3.png","viewer/textures/tag-icons/package_signs/regulatory--roundabout--g1.png","viewer/textures/tag-icons/package_signs/regulatory--roundabout--g2.png","viewer/textures/tag-icons/package_signs/regulatory--roundabout--g3.png","viewer/textures/tag-icons/package_signs/regulatory--shared-path-bicycles-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--shared-path-pedestrians-and-bicycles--g1.png","viewer/textures/tag-icons/package_signs/regulatory--sidewalk-closed--g1.png","viewer/textures/tag-icons/package_signs/regulatory--slanted-parking--g1.png","viewer/textures/tag-icons/package_signs/regulatory--snow-chains--g1.png","viewer/textures/tag-icons/package_signs/regulatory--snow-chains--g2.png","viewer/textures/tag-icons/package_signs/regulatory--snow-chains--g3.png","viewer/textures/tag-icons/package_signs/regulatory--snowmobiles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--snowmobiles-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--speed-limit-zone--g1.png","viewer/textures/tag-icons/package_signs/regulatory--speeding-fines-increased--g1.png","viewer/textures/tag-icons/package_signs/regulatory--state-route--g1.png","viewer/textures/tag-icons/package_signs/regulatory--stay-in-lane--g1.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g1.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g2.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g3.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g4.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g5.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g6.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g7.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g8.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g9.png","viewer/textures/tag-icons/package_signs/regulatory--stop--g10.png","viewer/textures/tag-icons/package_signs/regulatory--stop-here-on-red-or-flashing-light--g1.png","viewer/textures/tag-icons/package_signs/regulatory--stop-here-on-red-or-flashing-light--g2.png","viewer/textures/tag-icons/package_signs/regulatory--stop-signals--g1.png","viewer/textures/tag-icons/package_signs/regulatory--stop-signals--g2.png","viewer/textures/tag-icons/package_signs/regulatory--tanks-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--taxi-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--text--g1.png","viewer/textures/tag-icons/package_signs/regulatory--text--g2.png","viewer/textures/tag-icons/package_signs/regulatory--toll-pass-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--tractors-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--traffic-signal-photo-enforced--g1.png","viewer/textures/tag-icons/package_signs/regulatory--trams-and-buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--trams-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--triple-lanes--g1.png","viewer/textures/tag-icons/package_signs/regulatory--triple-lanes-go-straight-center-lane--g1.png","viewer/textures/tag-icons/package_signs/regulatory--triple-lanes-turn-left-center-lane--g1.png","viewer/textures/tag-icons/package_signs/regulatory--triple-lanes-turn-right-center-lane--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-route--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-5--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-10--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-15--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-20--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-25--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-30--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-35--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-40--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-45--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-50--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-55--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-60--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-65--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-70--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-75--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-80--g1.png","viewer/textures/tag-icons/package_signs/regulatory--truck-speed-limit-85--g1.png","viewer/textures/tag-icons/package_signs/regulatory--trucks-and-buses-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--trucks-on-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--trucks-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left--g2.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left--g3.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left-ahead--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left-ahead--g2.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left-or-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left-or-right--g2.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left-or-right--g3.png","viewer/textures/tag-icons/package_signs/regulatory--turn-left-or-u-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-right--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-right--g2.png","viewer/textures/tag-icons/package_signs/regulatory--turn-right--g3.png","viewer/textures/tag-icons/package_signs/regulatory--turn-right-ahead--g1.png","viewer/textures/tag-icons/package_signs/regulatory--turn-right-ahead--g2.png","viewer/textures/tag-icons/package_signs/regulatory--turning-vehicles-yield-to-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--two-stage-right-turn-for-mopeds--g1.png","viewer/textures/tag-icons/package_signs/regulatory--two-way--g1.png","viewer/textures/tag-icons/package_signs/regulatory--u-turn--g1.png","viewer/textures/tag-icons/package_signs/regulatory--u-turn--g2.png","viewer/textures/tag-icons/package_signs/regulatory--u-turn--g3.png","viewer/textures/tag-icons/package_signs/regulatory--use-crosswalk--g1.png","viewer/textures/tag-icons/package_signs/regulatory--vehicles-carrying-dangerous-goods-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--vehicles-carrying-dangerous-goods-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--vehicles-carrying-explosives-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--vehicles-carrying-hazardous-goods-permitted--g1.png","viewer/textures/tag-icons/package_signs/regulatory--vehicles-only--g1.png","viewer/textures/tag-icons/package_signs/regulatory--wear-seat-belt--g1.png","viewer/textures/tag-icons/package_signs/regulatory--wear-seat-belt--g2.png","viewer/textures/tag-icons/package_signs/regulatory--wear-seat-belt--g3.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g2.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g3.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g4.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g5.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g6.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit--g7.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit-per-axle--g1.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit-per-tandem-axle--g1.png","viewer/textures/tag-icons/package_signs/regulatory--weight-limit-with-trucks--g1.png","viewer/textures/tag-icons/package_signs/regulatory--width-limit--g1.png","viewer/textures/tag-icons/package_signs/regulatory--wrong-way--g1.png","viewer/textures/tag-icons/package_signs/regulatory--yield--g1.png","viewer/textures/tag-icons/package_signs/regulatory--yield-or-stop-for-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/regulatory--your-speed--g1.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g1.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g2.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g3.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g4.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g5.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g6.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g7.png","viewer/textures/tag-icons/package_signs/warning--accident-area--g8.png","viewer/textures/tag-icons/package_signs/warning--added-lane-from-entering-roadway--g1.png","viewer/textures/tag-icons/package_signs/warning--added-lane-from-entering-roadway--g2.png","viewer/textures/tag-icons/package_signs/warning--added-lane-left--g1.png","viewer/textures/tag-icons/package_signs/warning--added-lane-right--g1.png","viewer/textures/tag-icons/package_signs/warning--animal-drawn-vehicles--g1.png","viewer/textures/tag-icons/package_signs/warning--arch-bridge--g1.png","viewer/textures/tag-icons/package_signs/warning--atv-and-snowmobiles--g1.png","viewer/textures/tag-icons/package_signs/warning--atv-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--atv-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--axle-restriction--g1.png","viewer/textures/tag-icons/package_signs/warning--bear-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--bear-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--bicycles-and-others--g1.png","viewer/textures/tag-icons/package_signs/warning--bicycles-caution-on-rail-tracks--g1.png","viewer/textures/tag-icons/package_signs/warning--bicycles-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--bicycles-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--bicycles-crossing--g3.png","viewer/textures/tag-icons/package_signs/warning--bicycles-crossing--g4.png","viewer/textures/tag-icons/package_signs/warning--bollard--g1.png","viewer/textures/tag-icons/package_signs/warning--bridge--g1.png","viewer/textures/tag-icons/package_signs/warning--bridge--g2.png","viewer/textures/tag-icons/package_signs/warning--bus-stop-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--bus-stop-ahead--g2.png","viewer/textures/tag-icons/package_signs/warning--bus-stop-ahead--g3.png","viewer/textures/tag-icons/package_signs/warning--camel-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--camel-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--camera--g1.png","viewer/textures/tag-icons/package_signs/warning--camera--g2.png","viewer/textures/tag-icons/package_signs/warning--carts--g1.png","viewer/textures/tag-icons/package_signs/warning--carts--g2.png","viewer/textures/tag-icons/package_signs/warning--checkpoint--g1.png","viewer/textures/tag-icons/package_signs/warning--children--g1.png","viewer/textures/tag-icons/package_signs/warning--children--g2.png","viewer/textures/tag-icons/package_signs/warning--children--g3.png","viewer/textures/tag-icons/package_signs/warning--children--g4.png","viewer/textures/tag-icons/package_signs/warning--children--g6.png","viewer/textures/tag-icons/package_signs/warning--cliff--g1.png","viewer/textures/tag-icons/package_signs/warning--cliff--g2.png","viewer/textures/tag-icons/package_signs/warning--closed-lane-in-triple-lanes--g1.png","viewer/textures/tag-icons/package_signs/warning--closed-lane-in-triple-lanes--g2.png","viewer/textures/tag-icons/package_signs/warning--construction-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--crossroads--g1.png","viewer/textures/tag-icons/package_signs/warning--crossroads--g2.png","viewer/textures/tag-icons/package_signs/warning--crossroads--g3.png","viewer/textures/tag-icons/package_signs/warning--crossroads--g4.png","viewer/textures/tag-icons/package_signs/warning--crossroads--g5.png","viewer/textures/tag-icons/package_signs/warning--crossroads--g6.png","viewer/textures/tag-icons/package_signs/warning--crossroads-with-priority-to-the-right--g1.png","viewer/textures/tag-icons/package_signs/warning--curve-left--g1.png","viewer/textures/tag-icons/package_signs/warning--curve-left--g2.png","viewer/textures/tag-icons/package_signs/warning--curve-left--g3.png","viewer/textures/tag-icons/package_signs/warning--curve-left-with-junction--g1.png","viewer/textures/tag-icons/package_signs/warning--curve-out-intersection-left--g1.png","viewer/textures/tag-icons/package_signs/warning--curve-out-intersection-right--g1.png","viewer/textures/tag-icons/package_signs/warning--curve-right--g1.png","viewer/textures/tag-icons/package_signs/warning--curve-right--g2.png","viewer/textures/tag-icons/package_signs/warning--curve-right--g3.png","viewer/textures/tag-icons/package_signs/warning--curve-right-with-junction--g1.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-left--g1.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-left--g2.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-left--g4.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-right--g1.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-right--g2.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-right--g3.png","viewer/textures/tag-icons/package_signs/warning--dangerous-crosswinds-right--g4.png","viewer/textures/tag-icons/package_signs/warning--dead-end--g1.png","viewer/textures/tag-icons/package_signs/warning--dead-end--g2.png","viewer/textures/tag-icons/package_signs/warning--dead-end--g3.png","viewer/textures/tag-icons/package_signs/warning--dead-end-go-left--g1.png","viewer/textures/tag-icons/package_signs/warning--dead-end-go-right--g1.png","viewer/textures/tag-icons/package_signs/warning--descent-or-climbing-lanes-in-triple-lanes--g1.png","viewer/textures/tag-icons/package_signs/warning--detour-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--detour-or-construction-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--dip--g1.png","viewer/textures/tag-icons/package_signs/warning--dip--g2.png","viewer/textures/tag-icons/package_signs/warning--disabled-persons-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--disabled-persons-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g1.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g2.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g3.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g4.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g5.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g6.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g7.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g8.png","viewer/textures/tag-icons/package_signs/warning--divided-highway--g9.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-ends--g1.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-ends--g2.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-ends--g3.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-ends--g4.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-on-left--g1.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-on-left--g2.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-on-right--g1.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-on-right--g2.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-to-left--g1.png","viewer/textures/tag-icons/package_signs/warning--divided-highway-to-right--g1.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g1.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g2.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g3.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g4.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g5.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g6.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g7.png","viewer/textures/tag-icons/package_signs/warning--domestic-animals--g8.png","viewer/textures/tag-icons/package_signs/warning--double-curve-first-left--g1.png","viewer/textures/tag-icons/package_signs/warning--double-curve-first-left--g2.png","viewer/textures/tag-icons/package_signs/warning--double-curve-first-right--g1.png","viewer/textures/tag-icons/package_signs/warning--double-curve-first-right--g2.png","viewer/textures/tag-icons/package_signs/warning--double-descent--g1.png","viewer/textures/tag-icons/package_signs/warning--double-reverse-curve-left--g1.png","viewer/textures/tag-icons/package_signs/warning--double-reverse-curve-left--g2.png","viewer/textures/tag-icons/package_signs/warning--double-reverse-curve-right--g1.png","viewer/textures/tag-icons/package_signs/warning--double-reverse-curve-right--g2.png","viewer/textures/tag-icons/package_signs/warning--double-side-roads-left--g1.png","viewer/textures/tag-icons/package_signs/warning--double-side-roads-left--g3.png","viewer/textures/tag-icons/package_signs/warning--double-side-roads-right--g1.png","viewer/textures/tag-icons/package_signs/warning--double-side-roads-right--g3.png","viewer/textures/tag-icons/package_signs/warning--double-turn-first-left--g1.png","viewer/textures/tag-icons/package_signs/warning--double-turn-first-right--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-all-directions-on-left--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-all-directions-on-right--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-go-straight-or-turn-left--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-go-straight-or-turn-right--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-left-turn--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-left-turn-or-go-straight--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-right-turn--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-right-turn-or-go-straight--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-turn-left--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-turn-left-or-right--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-turn-left-or-right--g2.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-turn-left-or-right--g3.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-turn-left-or-right--g4.png","viewer/textures/tag-icons/package_signs/warning--dual-lanes-turn-right--g1.png","viewer/textures/tag-icons/package_signs/warning--dual-path-cyclists-and-pedestrians--g1.png","viewer/textures/tag-icons/package_signs/warning--electricity--g1.png","viewer/textures/tag-icons/package_signs/warning--electricity--g2.png","viewer/textures/tag-icons/package_signs/warning--elephant-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--emergency-vehicles--g1.png","viewer/textures/tag-icons/package_signs/warning--emu-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--emu-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--entering-roadway-merge--g1.png","viewer/textures/tag-icons/package_signs/warning--entering-roadway-merge--g2.png","viewer/textures/tag-icons/package_signs/warning--equestrians-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--equestrians-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--expressway--g1.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-left--g1.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-left--g2.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-left--g3.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-left--g4.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-right--g1.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-right--g2.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-right--g3.png","viewer/textures/tag-icons/package_signs/warning--falling-rocks-or-debris-right--g4.png","viewer/textures/tag-icons/package_signs/warning--ferry--g1.png","viewer/textures/tag-icons/package_signs/warning--flaggers-in-road--g1.png","viewer/textures/tag-icons/package_signs/warning--flaggers-in-road--g2.png","viewer/textures/tag-icons/package_signs/warning--foggy-road--g1.png","viewer/textures/tag-icons/package_signs/warning--foggy-road--g2.png","viewer/textures/tag-icons/package_signs/warning--ford--g1.png","viewer/textures/tag-icons/package_signs/warning--forest--g1.png","viewer/textures/tag-icons/package_signs/warning--fresh-oil--g1.png","viewer/textures/tag-icons/package_signs/warning--frog-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--gate--g1.png","viewer/textures/tag-icons/package_signs/warning--gate--g2.png","viewer/textures/tag-icons/package_signs/warning--gate-left--g1.png","viewer/textures/tag-icons/package_signs/warning--gate-right--g1.png","viewer/textures/tag-icons/package_signs/warning--go-left--g1.png","viewer/textures/tag-icons/package_signs/warning--go-right--g1.png","viewer/textures/tag-icons/package_signs/warning--golf-carts-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--gravel-road-surface--g1.png","viewer/textures/tag-icons/package_signs/warning--hairpin-curve-left--g1.png","viewer/textures/tag-icons/package_signs/warning--hairpin-curve-left--g2.png","viewer/textures/tag-icons/package_signs/warning--hairpin-curve-left--g3.png","viewer/textures/tag-icons/package_signs/warning--hairpin-curve-right--g1.png","viewer/textures/tag-icons/package_signs/warning--hairpin-curve-right--g3.png","viewer/textures/tag-icons/package_signs/warning--height-restriction--g2.png","viewer/textures/tag-icons/package_signs/warning--height-restriction--g3.png","viewer/textures/tag-icons/package_signs/warning--height-restriction--g4.png","viewer/textures/tag-icons/package_signs/warning--height-restriction--g5.png","viewer/textures/tag-icons/package_signs/warning--horizontal-alignment-left--g1.png","viewer/textures/tag-icons/package_signs/warning--horizontal-alignment-left--g3.png","viewer/textures/tag-icons/package_signs/warning--horizontal-alignment-right--g1.png","viewer/textures/tag-icons/package_signs/warning--horizontal-alignment-right--g3.png","viewer/textures/tag-icons/package_signs/warning--horse-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--icy-road--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-acute-left--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-acute-left--g2.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-acute-right--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-acute-right--g2.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-left--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-left--g2.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-left--g3.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-left--g4.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-right--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-right--g2.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-right--g3.png","viewer/textures/tag-icons/package_signs/warning--junction-with-a-side-road-perpendicular-right--g4.png","viewer/textures/tag-icons/package_signs/warning--junction-with-merge-from-left--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-merge-from-right--g1.png","viewer/textures/tag-icons/package_signs/warning--junction-with-side-roads--g1.png","viewer/textures/tag-icons/package_signs/warning--kangaloo-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--keep-distance--g1.png","viewer/textures/tag-icons/package_signs/warning--keep-left--g1.png","viewer/textures/tag-icons/package_signs/warning--keep-right--g1.png","viewer/textures/tag-icons/package_signs/warning--kiwi-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--kiwi-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--koala-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--koala-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--koala-crossing--g3.png","viewer/textures/tag-icons/package_signs/warning--koala-crossing--g4.png","viewer/textures/tag-icons/package_signs/warning--lane-closed-in-dual-lanes-left--g1.png","viewer/textures/tag-icons/package_signs/warning--lane-closed-in-dual-lanes-left--g2.png","viewer/textures/tag-icons/package_signs/warning--lane-closed-in-dual-lanes-right--g1.png","viewer/textures/tag-icons/package_signs/warning--lane-closed-in-dual-lanes-right--g2.png","viewer/textures/tag-icons/package_signs/warning--length-restriction--g1.png","viewer/textures/tag-icons/package_signs/warning--length-restriction--g2.png","viewer/textures/tag-icons/package_signs/warning--light-rail-transit-vehicles--g1.png","viewer/textures/tag-icons/package_signs/warning--limited-lighting-under-trees--g1.png","viewer/textures/tag-icons/package_signs/warning--logging-vehicles--g1.png","viewer/textures/tag-icons/package_signs/warning--loop-270-degree--g1.png","viewer/textures/tag-icons/package_signs/warning--loop-pretzel--g1.png","viewer/textures/tag-icons/package_signs/warning--loose-road-surface--g1.png","viewer/textures/tag-icons/package_signs/warning--loose-road-surface--g2.png","viewer/textures/tag-icons/package_signs/warning--loose-road-surface--g3.png","viewer/textures/tag-icons/package_signs/warning--loose-road-surface--g4.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g1.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g2.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g3.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g4.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g5.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g6.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g7.png","viewer/textures/tag-icons/package_signs/warning--low-flying-aircraft--g8.png","viewer/textures/tag-icons/package_signs/warning--low-ground-clearance--g1.png","viewer/textures/tag-icons/package_signs/warning--low-ground-clearance--g2.png","viewer/textures/tag-icons/package_signs/warning--low-ground-clearance--g3.png","viewer/textures/tag-icons/package_signs/warning--monkey-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--motorcycles-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--narrow-bridge--g1.png","viewer/textures/tag-icons/package_signs/warning--narrow-bridge--g2.png","viewer/textures/tag-icons/package_signs/warning--narrow-bridge--g3.png","viewer/textures/tag-icons/package_signs/warning--no-passing-zone--g1.png","viewer/textures/tag-icons/package_signs/warning--no-passing-zone--g2.png","viewer/textures/tag-icons/package_signs/warning--occupied-lanes--g1.png","viewer/textures/tag-icons/package_signs/warning--offset-roads--g1.png","viewer/textures/tag-icons/package_signs/warning--offset-roads--g2.png","viewer/textures/tag-icons/package_signs/warning--offset-roads--g3.png","viewer/textures/tag-icons/package_signs/warning--offset-roads--g4.png","viewer/textures/tag-icons/package_signs/warning--opening-or-swing-bridge--g1.png","viewer/textures/tag-icons/package_signs/warning--opening-or-swing-bridge--g2.png","viewer/textures/tag-icons/package_signs/warning--other-danger--g1.png","viewer/textures/tag-icons/package_signs/warning--other-danger--g2.png","viewer/textures/tag-icons/package_signs/warning--other-danger--g3.png","viewer/textures/tag-icons/package_signs/warning--panda-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--pass-left-or-right--g1.png","viewer/textures/tag-icons/package_signs/warning--pass-left-or-right--g2.png","viewer/textures/tag-icons/package_signs/warning--pass-left-or-right--g3.png","viewer/textures/tag-icons/package_signs/warning--pavement-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--pavement-ends--g1.png","viewer/textures/tag-icons/package_signs/warning--pavement-ends--g2.png","viewer/textures/tag-icons/package_signs/warning--pavement-ends--g3.png","viewer/textures/tag-icons/package_signs/warning--pavement-ends--g4.png","viewer/textures/tag-icons/package_signs/warning--pavement-ends--g5.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g4.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g5.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g6.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g7.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g8.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g9.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g10.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g11.png","viewer/textures/tag-icons/package_signs/warning--pedestrians-crossing--g12.png","viewer/textures/tag-icons/package_signs/warning--playground--g1.png","viewer/textures/tag-icons/package_signs/warning--playground--g3.png","viewer/textures/tag-icons/package_signs/warning--polar-bear-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--quay-or-river-bank--g1.png","viewer/textures/tag-icons/package_signs/warning--quay-or-river-bank--g2.png","viewer/textures/tag-icons/package_signs/warning--quay-or-river-bank--g3.png","viewer/textures/tag-icons/package_signs/warning--quay-or-river-bank--g4.png","viewer/textures/tag-icons/package_signs/warning--rabbit-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--raccoon-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing--g3.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing--g4.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g1.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g2.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g3.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g4.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g5.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g6.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-with-barriers--g7.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-without-barriers--g1.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-without-barriers--g2.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-without-barriers--g3.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-without-barriers--g4.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-without-barriers--g5.png","viewer/textures/tag-icons/package_signs/warning--railroad-crossing-without-barriers--g6.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g1.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g2.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g3.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g4.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g5.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g6.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g7.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g8.png","viewer/textures/tag-icons/package_signs/warning--railroad-intersection--g9.png","viewer/textures/tag-icons/package_signs/warning--ramp-closed--g1.png","viewer/textures/tag-icons/package_signs/warning--reduced-maximum-speed-limit--g1.png","viewer/textures/tag-icons/package_signs/warning--reserved-lane--g1.png","viewer/textures/tag-icons/package_signs/warning--restricted-zone--g1.png","viewer/textures/tag-icons/package_signs/warning--reversible-lanes--g1.png","viewer/textures/tag-icons/package_signs/warning--reversible-lanes--g2.png","viewer/textures/tag-icons/package_signs/warning--rickshaws-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--road-blocks--g1.png","viewer/textures/tag-icons/package_signs/warning--road-bump--g1.png","viewer/textures/tag-icons/package_signs/warning--road-bump--g2.png","viewer/textures/tag-icons/package_signs/warning--road-bump--g3.png","viewer/textures/tag-icons/package_signs/warning--road-bump-with-speed-limit--g1.png","viewer/textures/tag-icons/package_signs/warning--road-closed--g3.png","viewer/textures/tag-icons/package_signs/warning--road-narrows--g1.png","viewer/textures/tag-icons/index.ts","viewer/textures/tag-icons/package_signs/index.ts","viewer/textures/tag-icons/package_signs/warning--road-narrows--g2.png","viewer/textures/tag-icons/package_signs/warning--road-narrows-left--g1.png","viewer/textures/tag-icons/package_signs/warning--road-narrows-left--g2.png","viewer/textures/tag-icons/package_signs/warning--road-narrows-left-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--road-narrows-right--g1.png","viewer/textures/tag-icons/package_signs/warning--road-narrows-right--g2.png","viewer/textures/tag-icons/package_signs/warning--road-narrows-right-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--road-toll-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--road-widens--g1.png","viewer/textures/tag-icons/package_signs/warning--road-widens-left--g1.png","viewer/textures/tag-icons/package_signs/warning--road-widens-right--g1.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g1.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g2.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g3.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g5.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g6.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g8.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g9.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g10.png","viewer/textures/tag-icons/package_signs/warning--roadworks--g11.png","viewer/textures/tag-icons/package_signs/warning--roadworks-go-left-or-straight--g1.png","viewer/textures/tag-icons/package_signs/warning--roadworks-go-right-or-straight--g1.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g1.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g2.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g3.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g4.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g5.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g6.png","viewer/textures/tag-icons/package_signs/warning--roundabout--g7.png","viewer/textures/tag-icons/package_signs/warning--ruts--g1.png","viewer/textures/tag-icons/package_signs/warning--sand--g1.png","viewer/textures/tag-icons/package_signs/warning--sand-drift--g1.png","viewer/textures/tag-icons/package_signs/warning--school-zone--g2.png","viewer/textures/tag-icons/package_signs/warning--severe-weather--g1.png","viewer/textures/tag-icons/package_signs/warning--shared-lane-motorcycles-bicycles--g1.png","viewer/textures/tag-icons/package_signs/warning--sharp-turn--g1.png","viewer/textures/tag-icons/package_signs/warning--single-reverse-curve--g1.png","viewer/textures/tag-icons/package_signs/warning--skewed-t-roads-left--g1.png","viewer/textures/tag-icons/package_signs/warning--skewed-t-roads-left--g2.png","viewer/textures/tag-icons/package_signs/warning--skewed-t-roads-left--g3.png","viewer/textures/tag-icons/package_signs/warning--skewed-t-roads-right--g1.png","viewer/textures/tag-icons/package_signs/warning--skewed-t-roads-right--g2.png","viewer/textures/tag-icons/package_signs/warning--skewed-t-roads-right--g3.png","viewer/textures/tag-icons/package_signs/warning--skiers--g1.png","viewer/textures/tag-icons/package_signs/warning--skiers--g2.png","viewer/textures/tag-icons/package_signs/warning--skiers--g3.png","viewer/textures/tag-icons/package_signs/warning--slippery-bicycles--g1.png","viewer/textures/tag-icons/package_signs/warning--slippery-motorcycles--g1.png","viewer/textures/tag-icons/package_signs/warning--slippery-motorcycles--g2.png","viewer/textures/tag-icons/package_signs/warning--slippery-road-surface--g1.png","viewer/textures/tag-icons/package_signs/warning--slippery-road-surface--g2.png","viewer/textures/tag-icons/package_signs/warning--slow--g1.png","viewer/textures/tag-icons/package_signs/warning--snow-tractors--g1.png","viewer/textures/tag-icons/package_signs/warning--snowmobiles--g1.png","viewer/textures/tag-icons/package_signs/warning--snowmobiles--g2.png","viewer/textures/tag-icons/package_signs/warning--snowmobiles--g3.png","viewer/textures/tag-icons/package_signs/warning--snowmobiles-and-others--g1.png","viewer/textures/tag-icons/package_signs/warning--soft-road-surface--g1.png","viewer/textures/tag-icons/package_signs/warning--soft-road-surface--g2.png","viewer/textures/tag-icons/package_signs/warning--soft-shoulder--g1.png","viewer/textures/tag-icons/package_signs/warning--soft-shoulder--g2.png","viewer/textures/tag-icons/package_signs/warning--soft-shoulder--g3.png","viewer/textures/tag-icons/package_signs/warning--soft-shoulder--g4.png","viewer/textures/tag-icons/package_signs/warning--speed-camera--g1.png","viewer/textures/tag-icons/package_signs/warning--steep-ascent--g1.png","viewer/textures/tag-icons/package_signs/warning--steep-ascent--g2.png","viewer/textures/tag-icons/package_signs/warning--steep-ascent--g3.png","viewer/textures/tag-icons/package_signs/warning--steep-ascent--g4.png","viewer/textures/tag-icons/package_signs/warning--steep-ascent-and-descent--g1.png","viewer/textures/tag-icons/package_signs/warning--steep-descent--g1.png","viewer/textures/tag-icons/package_signs/warning--steep-descent--g2.png","viewer/textures/tag-icons/package_signs/warning--steep-descent--g3.png","viewer/textures/tag-icons/package_signs/warning--steep-descent--g4.png","viewer/textures/tag-icons/package_signs/warning--steep-descent--g5.png","viewer/textures/tag-icons/package_signs/warning--steep-descent--g6.png","viewer/textures/tag-icons/package_signs/warning--stop-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--stop-ahead--g3.png","viewer/textures/tag-icons/package_signs/warning--stop-ahead--g4.png","viewer/textures/tag-icons/package_signs/warning--stop-ahead--g5.png","viewer/textures/tag-icons/package_signs/warning--stop-ahead--g6.png","viewer/textures/tag-icons/package_signs/warning--t-roads--g1.png","viewer/textures/tag-icons/package_signs/warning--t-roads--g2.png","viewer/textures/tag-icons/package_signs/warning--tanks-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--tanks-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--texts--g1.png","viewer/textures/tag-icons/package_signs/warning--texts--g2.png","viewer/textures/tag-icons/package_signs/warning--texts--g3.png","viewer/textures/tag-icons/package_signs/warning--towing--g1.png","viewer/textures/tag-icons/package_signs/warning--tractors--g1.png","viewer/textures/tag-icons/package_signs/warning--tractors--g2.png","viewer/textures/tag-icons/package_signs/warning--tractors--g3.png","viewer/textures/tag-icons/package_signs/warning--tractors--g4.png","viewer/textures/tag-icons/package_signs/warning--tractors--g5.png","viewer/textures/tag-icons/package_signs/warning--tractors--g6.png","viewer/textures/tag-icons/package_signs/warning--tractors--g7.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-at-signalized-intersections--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-left--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-left--g2.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-left--g3.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-left--g4.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-left-and-right--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-left-buses--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-right--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-right--g2.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-right--g3.png","viewer/textures/tag-icons/package_signs/warning--traffic-merges-right-buses--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-queues-likely--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-queues-likely--g2.png","viewer/textures/tag-icons/package_signs/warning--traffic-queues-likely--g3.png","viewer/textures/tag-icons/package_signs/warning--traffic-queues-likely--g4.png","viewer/textures/tag-icons/package_signs/warning--traffic-queues-likely--g5.png","viewer/textures/tag-icons/package_signs/warning--traffic-signals--g1.png","viewer/textures/tag-icons/package_signs/warning--traffic-signals--g2.png","viewer/textures/tag-icons/package_signs/warning--traffic-signals--g3.png","viewer/textures/tag-icons/package_signs/warning--traffic-signals--g4.png","viewer/textures/tag-icons/package_signs/warning--traffic-signals--g5.png","viewer/textures/tag-icons/package_signs/warning--traffic-signals--g6.png","viewer/textures/tag-icons/package_signs/warning--traffic-slow--g1.png","viewer/textures/tag-icons/package_signs/warning--trail-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--trail-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--trail-crossing--g3.png","viewer/textures/tag-icons/package_signs/warning--trail-crossing--g4.png","viewer/textures/tag-icons/package_signs/warning--trail-crossing--g5.png","viewer/textures/tag-icons/package_signs/warning--trail-crossing--g6.png","viewer/textures/tag-icons/package_signs/warning--trams-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--trams-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--triple-curve-left--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-curve-right--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-lanes-left-turn--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-lanes-left-turn-or-go-straight--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-lanes-right-turn--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-lanes-right-turn-or-go-straight--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-lanes-with-directions--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-reverse-curve-left--g1.png","viewer/textures/tag-icons/package_signs/warning--triple-reverse-curve-right--g1.png","viewer/textures/tag-icons/package_signs/warning--trucks-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--trucks-crossing--g2.png","viewer/textures/tag-icons/package_signs/warning--trucks-rollover--g1.png","viewer/textures/tag-icons/package_signs/warning--trucks-rollover--g2.png","viewer/textures/tag-icons/package_signs/warning--trucks-rollover--g3.png","viewer/textures/tag-icons/package_signs/warning--trucks-rollover--g4.png","viewer/textures/tag-icons/package_signs/warning--trucks-rollover--g5.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g1.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g2.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g3.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g4.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g5.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g6.png","viewer/textures/tag-icons/package_signs/warning--tunnel--g7.png","viewer/textures/tag-icons/package_signs/warning--turn-left--g1.png","viewer/textures/tag-icons/package_signs/warning--turn-left--g2.png","viewer/textures/tag-icons/package_signs/warning--turn-left--g3.png","viewer/textures/tag-icons/package_signs/warning--turn-left-or-right--g1.png","viewer/textures/tag-icons/package_signs/warning--turn-right--g1.png","viewer/textures/tag-icons/package_signs/warning--turn-right--g2.png","viewer/textures/tag-icons/package_signs/warning--turn-right--g3.png","viewer/textures/tag-icons/package_signs/warning--two-way-traffic--g1.png","viewer/textures/tag-icons/package_signs/warning--two-way-traffic--g2.png","viewer/textures/tag-icons/package_signs/warning--two-way-traffic--g3.png","viewer/textures/tag-icons/package_signs/warning--two-way-traffic--g4.png","viewer/textures/tag-icons/package_signs/warning--two-way-traffic--g5.png","viewer/textures/tag-icons/package_signs/warning--two-way-traffic--g6.png","viewer/textures/tag-icons/package_signs/warning--u-turn--g1.png","viewer/textures/tag-icons/package_signs/warning--u-turn--g2.png","viewer/textures/tag-icons/package_signs/warning--uneven-road--g1.png","viewer/textures/tag-icons/package_signs/warning--uneven-road--g2.png","viewer/textures/tag-icons/package_signs/warning--uneven-roads-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--vehicles-and-others--g1.png","viewer/textures/tag-icons/package_signs/warning--vehicles-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--village--g1.png","viewer/textures/tag-icons/package_signs/warning--weight-limit--g5.png","viewer/textures/tag-icons/package_signs/warning--weight-limit-per-tandem-axle--g1.png","viewer/textures/tag-icons/package_signs/warning--width-restriction--g1.png","viewer/textures/tag-icons/package_signs/warning--width-restriction--g2.png","viewer/textures/tag-icons/package_signs/warning--width-restriction--g3.png","viewer/textures/tag-icons/package_signs/warning--width-restriction--g4.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g1.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g2.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g3.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g4.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g5.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g6.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g7.png","viewer/textures/tag-icons/package_signs/warning--wild-animals--g8.png","viewer/textures/tag-icons/package_signs/warning--wind--g1.png","viewer/textures/tag-icons/package_signs/warning--winding-road--g1.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-left--g1.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-left--g2.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-left--g3.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-right--g1.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-right--g2.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-right--g3.png","viewer/textures/tag-icons/package_signs/warning--winding-road-first-right--g4.png","viewer/textures/tag-icons/package_signs/warning--winding-road-to-left--g1.png","viewer/textures/tag-icons/package_signs/warning--winding-road-to-right--g1.png","viewer/textures/tag-icons/package_signs/warning--wombat-crossing--g1.png","viewer/textures/tag-icons/package_signs/warning--y-roads--g1.png","viewer/textures/tag-icons/package_signs/warning--y-roads--g2.png","viewer/textures/tag-icons/package_signs/warning--yield-ahead--g1.png","viewer/textures/tag-icons/package_signs/warning--yield-ahead--g3.png","viewer/textures/tag-icons/allterra/index.ts","viewer/textures/tag-icons/allterra/beginn schiessuebungsraum.png","viewer/textures/tag-icons/allterra/beginn schiessuebungsstrecke.png","viewer/textures/tag-icons/allterra/doppelrhombus.png","viewer/textures/tag-icons/allterra/doppelwinkel.png","viewer/textures/tag-icons/allterra/ende schiessuebungsraum.png","viewer/textures/tag-icons/allterra/ende schiessuebungsstrecke.png","viewer/textures/tag-icons/allterra/rhombus.png","viewer/textures/tag-icons/allterra/stellung feuerhalt.png","viewer/textures/tag-icons/allterra/winkel.png","types/tags.ts","utilities/assets.ts","utilities/camera.ts","redux/config-upgrade.ts","utilities/project.ts","functions/definitions/blur_vehicles_people.tsx","functions/definitions/classify_export.tsx","functions/definitions/convert_units.tsx","functions/definitions/las_to_orthomosaic.tsx","functions/definitions/las_to_solv3d_streamable.tsx","functions/definitions/sampling.tsx","functions/definitions/thin_las.tsx","functions/definitions/interpolate_dxf.tsx","functions/definitions/interpolate_shp.tsx","functions/functions.tsx","types/web-sources.ts","folder/asset.tsx","folder/tags.tsx","folder/folder.tsx","folder/web-sources.tsx","folder/folder-list.tsx","folder/models.tsx","bookmarks/bookmark-list.tsx","bookmarks/bookmark.tsx","asset-drawer.tsx","app-bar.tsx","settings/sliders.tsx","settings/global-settings/components.tsx","settings/global-settings/global-settings.tsx","viewer/textures/colormaps/awesome-green.png","viewer/textures/colormaps/black-orange.png","viewer/textures/colormaps/blue-hue.png","viewer/textures/colormaps/blue-orange.png","viewer/textures/colormaps/blue-red.png","viewer/textures/colormaps/grayscale.png","viewer/textures/colormaps/heat-map.png","viewer/textures/colormaps/jet.png","viewer/textures/colormaps/pastel-shades.png","viewer/textures/colormaps/index.ts","viewer/textures/map-preview/index.ts","viewer/textures/map-preview/open-street-maps.png","viewer/textures/map-preview/arcgis-world.png","viewer/textures/map-preview/arcgis-street.png","viewer/textures/map-preview/no-basemap.png","types/basemaps.ts","settings/project-settings/components.tsx","settings/project-settings/settings-drawer.tsx","viewer/classifications.ts","viewer/shaders/render_basic.frag","viewer/shaders/render_common.vert","viewer/shaders/index.ts","viewer/shaders/ifc.vert","viewer/shaders/ifc.frag","viewer/shaders/pointcloud.vert","viewer/shaders/pointcloud.frag","viewer/shaders/panoramic.vert","viewer/shaders/panoramic.frag","viewer/shaders/planar.vert","viewer/shaders/planar.frag","viewer/shaders/linework_basic.vert","viewer/shaders/linework_basic.frag","viewer/shaders/linework_sprite.vert","viewer/shaders/linework_sprite.frag","viewer/shaders/render_edl.frag","viewer/shaders/render_output.frag","viewer/shaders/markers.vert","viewer/shaders/markers.frag","viewer/shaders/utilities.glsl","viewer/shaders/picker_basic.vert","viewer/shaders/picker_basic.frag","viewer/shaders/gpu_picker.vert","viewer/shaders/gpu_picker.frag","viewer/shaders/texture_pack.vert","viewer/shaders/tags.vert","viewer/shaders/tags.frag","viewer/rendering/render-materials.ts","viewer/rendering/render-targets.ts","viewer/rendering/render-utils.ts","viewer/pointcloud/point-cloud.ts","viewer/binary-heap.ts","viewer/pointcloud/point-loader.ts","viewer/pointcloud/generic-pointcloud.ts","viewer/pointcloud/streamable-pointcloud.ts","viewer/pointcloud/encompass-pointcloud.ts","viewer/pointcloud/point-attributes.ts","viewer/pointcloud/potree-pointcloud.ts","viewer/controls/orbit-controls.ts","viewer/labelling/categories.ts","viewer/cameras/texture-cache.ts","viewer/cameras/camera-list.ts","viewer/textures/misc/no-image-panoramic.png","viewer/cameras/panoramic.ts","viewer/textures/misc/no-image-planar.png","viewer/cameras/planar.ts","viewer/cameras/aerial-controller.ts","viewer/ray-caster.ts","viewer/cameras/scene-controller.ts","context-menu/context-menu.tsx","context-menu/custom-links.tsx","viewer/aerial/map.ts","viewer/aerial/orthos.ts","viewer/labelling/image-label.ts","viewer/labelling/ortho-label.ts","viewer/labelling/scene-label.ts","viewer/markup/clipping-box.ts","viewer/markup/point-markup.ts","viewer/controls/mobile-controls.ts","viewer/point-profile/point-profile.ts","viewer/controls/controls.ts","viewer/controls/compass.ts","viewer/controls/mouse-controls.ts","viewer/controls/multi-image.ts","viewer/measurements/measurement.ts","viewer/measurements/measurement-aerial-view.ts","viewer/measurements/measurement-constructor.ts","viewer/measurements/measurement-controller.ts","viewer/measurements/measurement-formatter.ts","viewer/measurements/measurement-group-exporter.ts","viewer/measurements/measurement-group.ts","viewer/measurements/measurement-scene-view.ts","viewer/gpu-picker.ts","stats.module.js","viewer/tags/tags-list.ts","viewer/tags/scene-controller.ts","viewer/tags/aerial-controller.ts","viewer/tags/annotations.ts","viewer/textures/sprites/point.png","viewer/linework/cad.ts","viewer/linework/ifc.ts","viewer/linework/shp.ts","viewer/linework/dxf.ts","viewer/web-sources/loader.ts","viewer/web-sources/web-sources.ts","viewer/main.ts","viewer/viewer.tsx","types/aligner.ts","viewer/data-aligner/image-aligner-advanced.ts","viewer/data-aligner/image-aligner-basic.ts","viewer/data-aligner/observations.ts","viewer/data-aligner/local-projection.ts","alignment/observations.tsx","alignment/image-aligner-advanced.tsx","alignment/image-aligner-basic.tsx","alignment/local-projection.tsx","labelling/image-labelling.tsx","navigation/quick-nav.tsx","export/static/utils.ts","export/static/state.ts","export/static/exporter.ts","export/common.tsx","export/static/static-export.tsx","export/cloud/exporter.ts","types/cloud-export.ts","export/cloud/cloud-export.tsx","markup/point-markup.tsx","measurements/measurements.tsx","measurements/multi-image.tsx","viewer/textures/misc/solv3d-logo.png","about.tsx","task-queue.tsx","hooks/use-item-search.ts","cloud-projects.tsx","app.tsx"],"names":["useDialog","state","setState","useState","open","data","handleOpen","useCallback","handleClose","useTaskQueue","useContext","TaskQueueContext","useViewer","ViewerContext","useActiveTool","ActiveToolContext","useUniqueProjectID","useSelector","selectSessionID","usePopover","anchorRef","useRef","setOpen","handleToggle","prevState","useAuth","AuthContext","useContextMenu","anchorPosition","undefined","event","preventDefault","left","clientX","top","clientY","useGlobalSettings","GlobalSettingsContext","useWebSockets","WebSocketContext","useBookmarks","BookmarksContext","webpackEmptyContext","req","e","Error","code","keys","resolve","module","exports","id","unknownProjectionMeters","type","default","name","string","unknownProjectionFeet","defaultProjection","defaultTransform","origin","Array","fill","translation","rotation","scale","uniqueProjectionID","text","replace","userProjections","constructor","file","this","load","getByName","find","projection","getByString","proj","filter","transform","withUniqueName","suffix","push","storage","setSync","isStaticSite","getSync","isArray","delete","index","map","x","indexOf","splice","update","save","useStyles","makeStyles","theme","createStyles","title","margin","padding","spacing","content","paddingTop","titleClose","color","marginTop","marginBottom","adornedEnd","paddingRight","utmParent","display","utmZone","flex","utmButton","marginLeft","button","dropdown","minWidth","formControl","width","buttonDiv","textAlign","tabsParent","tabsHeaders","UserProjectionPanel","props","loadProjectionToEdit","setActiveTab","tableState","t","useTranslation","deleteDialog","columns","label","searchable","rows","option","custom","disabled","LocalScene","isDataProjection","actions","icon","fontSize","onClick","row","deletePrompt","Fragment","length","Typography","variant","results","maxHeight","onCancel","onSubmit","toast","error","onDelete","prompt","EditPanel","customProjection","updateEditableValues","hasTransform","setHasTransform","newProjection","existingName","classes","projString","translate","nameTrim","trim","stringTrim","originXError","originYError","originZError","translateXError","translateYError","translateZError","rotationError","scaleError","canSubmit","updateString","value","updateOrigin","parseFloat","target","isNaN","updateTranslation","Grid","container","item","xs","onChange","options","placeholder","multiline","FormControlLabel","className","control","Checkbox","checked","TextField","InputLabelProps","shrink","fullWidth","Button","JSON","parse","stringify","nameChanged","duplicateName","isValidProjection","success","SearchPanel","setType","searchTerm","setSearchTerm","hemisphere","setHemisphere","searching","setSearching","searchResults","setSearchResults","handleString","getProjections","searchText","pageNumber","previousResults","maxPageNumber","fetch","then","response","json","parsed","forEach","result","proj4","combined","setTimeout","numeric","epsg","parseInt","InputLabel","Select","labelId","MenuItem","InputProps","startAdornment","InputAdornment","position","clsx","select","reset","StyledPanel","PanelProps","style","minHeight","children","ProjectionsManager","uniqueProjectID","projectionsDialog","userTableState","useTableState","defaultSort","searchTableState","setExistingName","setNewProjection","activeTab","setTabValue","setCustomProjection","clearProjectionValues","projectionData","dataCopy","hasOwnProperty","transformCopy","useEffect","registerEvent","Dialog","scroll","onClose","AppBar","Tabs","newactiveTab","Tab","TabProps","IconButton","aria-label","size","newValues","eventKey","ProjectionItem","fileName","useTheme","Paper","flexDirection","alignItems","gutterBottom","ProjectionsDetector","dialog","dispatch","useDispatch","items","setItems","saveProjection","setSaveProjection","neverAsk","setNeverAsk","needsCheck","setNeedsCheck","page","setPage","dataProjection","selectDataProjection","callback","async","assetPaths","detail","fileNames","path","basename","projections","exe","PythonExecutable","Promise","commands","run","saveLogs","onLine","jsonData","getProjection","i","document","addEventListener","removeEventListener","selected","hasMultiple","existingProjection","uniqueProjection","useExisting","createNew","buttonText","resetCameraState","resetAerialState","updateDataProjection","updateViewProjection","Stack","Pagination","count","sx","pt","checkLASProjections","sendCustomEvent","EngineViewer","useBranding","store","StyledEngineProvider","injectFirst","ThemeProvider","ThemedViewer","ReactDOM","render","getElementById","appReducer","combineReducers","project","projectReducer","camera","cameraReducer","folders","foldersReducer","projectionsReducer","settings","settingsReducer","assets","assetsReducer","bookmarks","bookmarksReducer","custom_links","customLinksReducer","middleware","MiddlewareArray","concat","thunk","configureStore","reducer","action","newProject","loadConfig","configInit","projectJSON","payload","parameters","setTagQueryString","tag","updateStateFromTag","bookmarkID","bookmark","aerialState","sceneState","asset","visible","visibleAssets","includes","updateStateFromBookmark","getModifiedSceneState","getModifiedAerialState","switched","toBoolean","expanded","updateStateFromParameters","nanoid","isMobile","useAppDispatch","readFileJSON","isCloudSite","isValidURL","readJsonFromURL","readJsonElectron","readFileText","readTextFromURL","readTextElectron","readFileBuffer","readBufferFromURL","readBufferElectron","headers","status","fse","readFile","byteRange","first","last","arrayBuffer","bytesRequested","byteLength","tmpBuffer","Buffer","alloc","buffer","bytesRead","read","close","pageSize","query","setQuery","sortDir","setSortDir","sortBy","setSortBy","setPageNumber","rowsPerPage","setRowsPerPage","descendingComparator","a","b","compA","compB","toLowerCase","getComparator","handleSearchChange","debounce","handlePageNumberChange","handleRowsPerPageChange","handleRequestSort","handleSearch","queryParts","split","searchableColumns","column","valid","parts","handleSort","comparator","sort","handlePages","slice","AssetType","pointCloudType","ext","lasFileFormat","LAS","encompassFileFormat","Encompass","e57FileFormat","E57Points","potreeFileFormat","Potree","Unknown","getByID","assetID","getAssetByTagID","tagID","Tag","getAssetPayload","date","Date","toISOString","folderID","saved","cloud","assetsSlice","createSlice","initialState","reducers","addAsset","addAssets","updateAsset","updates","key","deleteAsset","toggleFolderVisibility","setVisibleAssets","setVisibleFolder","setSavedState","updateModelLayer","layerID","DXF","SHP","getAssetByModelLayerID","layer","updateWebMapLayer","Webmap","layers","getAssetByWebMapLayerID","createTags","tags","createTagsHelper","api","create","deleteTag","deleteTagHelper","updateTag","annotations","newAssetID","newAsset","wsCreateAsset","wsUpdateAsset","wsDeleteAsset","createAsset","getState","assetData","texture","createCollection","deleteCollection","updateCollection","selectAllAssets","getVisibleAssets","getModelAssets","IFC","getTagAssets","getPointCloudAssets","getCameraFileAssets","Panoramic","Planar","getOrthoAssets","OrthoMosaic","getLandXMLAssets","LandXML","getWebMapAssets","bookmarksSlice","createBookmark","attributes","updateBookmark","deleteBookmark","modified","wsCreateBookmark","wsUpdateBookmark","wsDeleteBookmark","selectAllBookmarks","transformCache","unitsToValue","latitudeLongitude","webMercator","workerPool","AsyncWorkerPool","verifyProjection","verifyProjectionString","verifyTransformObject","estimateTransform","estimator","inputValues","outputValues","domain","y","range","console","errors","estimate","nudged","getScale","getRotation","getTranslation","transformed","point","transformMany","dX","dY","Math","sqrt","MathUtils","radToDeg","reprojectPoints","points","projectionFrom","projectionTo","reject","values","positions","postMessage","reprojectPoint","isVector3","toArray","rotateAxis","Vector3","angle","degToRad","sub","applyAxisAngle","divide","add","heightScale","transformKey","projToMeters1","projectionToMeters","getTransform","forward","multiply","closestUtmZone","lonlat","units","ceil","Coordinate","z","super","clone","copy","SceneCoordinate","toAerial","_sceneToAerial","toLonLat","_sceneToLonLat","toGeocentric","LonLatCoordinate","toDataProjection","_sceneToData","DataProjectionCoordinate","toViewProjection","GeocentricCoordinate","toProjection","viewProjection","ViewProjectionCoordinate","toScene","_dataToScene","pow","ep","p","th","atan2","lon","lat","sin","cos","N","alt","PI","abs","ProjectedCoordinate","distanceTo","isLonLat1","isLonLatProjection","isLonLat2","haversineDistance","vector","SphericalPosition","radius","_theta","_phi","limits","round","precision","divisor","fromVectors","pivot","orbit","offset","theta","dist2d","phi","max","min","fromValues","toVector3","getEulerInverse","euler","quaternion","Quaternion","setFromEuler","invert","Euler","setFromQuaternion","geometryToArray","geometry","polygon","coordinates","flatCoordinates","totalPoints","ecef","calculateEigenVectors","mean","vertex","divideScalar","array","eigen","executeWithoutLogging","PCA","getEigenVectors","eigenvalue","fromArray","calculatePointsPCA","flatten","matrix","Matrix4","makeBasis","transpose","adjusted","applyMatrix4","flatArray","projectionToUnits","Units","Meters","Feet","SurveyFeet","Proj","convert","P1","P2","diffLat","diffLng","arc","distance2d","height","distance","origin_east","origin_north","origin_elevation","translation_east","translation_north","translation_elevation","scale_factor_h","Object","assign","toUpperCase","join","_sceneShift","_sceneScale","_dataProjection","_viewProjection","dataToMeters","dataProjectionUnits","viewProjectionUnits","isLonLatProject","initialized","engineStyleProjection","proj4String","scale_factor_v","setDataProjection","resetSceneShift","setViewProjection","checkForOffset","dx","dy","offsetToScene","_dataToLonLat","_dataToAerial","lonLat","multiplyScalar","numberOfClassifications","classifications","alias","from","getClassificationColors","image","Image","onload","canvas","createElement","context","getContext","drawImage","imageData","getImageData","colors","red","green","hexColor","toString","padStart","src","classificationsShader","url","engineCloudURL","cloudProjectID","method","body","withOriginalID","folder","err","annotation","tagCollection","asyncTimeout","ms","isHTML","isHtml","CustomEvent","dispatchEvent","ChangeDetector","viewer","oldZoom","oldFov","oldLookatVector","oldCameraPosition","oldUpVector","oldCameraID","oldHeight","oldWidth","oldOrbitState","orbitChanged","cameraChanged","changed","fov","getAerialZoomLevel","lookatVector","upVector","getCurrentCameraName","orbitState","lookatChanged","angleTo","newLookatVector","upChanged","newUpVector","positionChanged","newCameraPosition","fovChanged","newFov","zoomChanged","newZoom","newCameraID","heightChanged","newHeight","widthChanged","newWidth","newOrbitState","UnitConverter","metresToSurveyFeetRatio","metresToFeetRatio","fromUnits","toUnits","fixedLength","allowedUnits","TypeError","convertedValue","ratio","toFixed","test","navigator","userAgent","isUrl","encodeURI","getProjFactor","screenHeight","projFactor","tan","getPointScale","mesh","meshPosition","getWorldPosition","window","innerHeight","toVector2","Vector2","toScreenPosition","uv","set","eventToPixel","offsetX","offsetY","layerX","layerY","randomHexColor","random","closestPowerOfTwo","power","log","roundDigit","num","digits","multiplyFactor","Number","EPSILON","logger","windowSafeDateISO","coordinatesToArray","numPoints","newPoints","interpolate1D","start","end","steps","linspace","mergeBoundingBoxes","boundingBoxes","bbox","Box3","getCoordinateBounds","Infinity","coordinate","allIndexOf","indices","withOpacity","opacity","colorWithOpacity","olColor","simplepolygon","require","pointInPolygon","vertices","numberOfVertices","insidePolygon","j","verti","vertj","dy1","dy2","cond1","cond2","planeFromVectors","directions","normal","setLength","Plane","checkValidPolygon","shifted","features","parseURLParams","hash","URL","substring","urlParams","URLSearchParams","fromEntries","params","warning","center","zoom","ox","oy","oz","px","py","pz","initialSceneState","lookat","cam","angles","mapBoundsStyle","Style","stroke","Stroke","boundsToMapLayer","boundingBox","polygonPoints","vectorsource","VectorSource","wrapX","Polygon","feature","Feature","addFeature","VectorLayer","zIndex","source","fetchImage","signal","blob","Blob","createImageBitmap","imageOrientation","colorSpaceConversion","resizeImage","resized","resizeWidth","resizeHeight","resizeQuality","warn","ControlType","ControlModes","0","ORBIT","MOUSE","LEFT","ZOOM","MIDDLE","PAN","RIGHT","1","2","customLinkSlice","createCustomLink","customURL","updateCustomLink","linkID","deleteCustomLink","selectAllCustomLinks","numWorkers","workers","queue","initWorkers","filePath","worker","Worker","message","transfer","processQueue","shift","onmessage","ProjectType","AccessType","themeSpacing","createTheme","brand","isMosaic","primaryColor","secondaryColor","createMuiTheme","components","MuiPopover","styleOverrides","root","MuiTooltip","defaultProps","disableInteractive","tooltip","backgroundColor","arrow","border","MuiDialogTitle","MuiDialogContent","MuiIconButton","MuiSelect","MuiTextField","MuiTabs","indicatorColor","textColor","MuiSwitch","MuiCheckbox","MuiRadio","palette","primary","main","light","lighten","dark","darken","secondary","mode","mixins","toolbar","VolumeType","SamplingRate","MeasureType","AerialMeasureType","MeasureExportType","LocalizedFileFilter","extensions","getCombinedExtension","filters","pngFilter","pointCloudFileFormats","pointCloudFilter","configFileType","configFilter","customURLFilter","imageOrthoFormat","imageOrthoFilter","imageCSVFilter","projFileFormat","imagePlanarFormat","imagePlanarFilter","csvExportFilter","cameraMatrixFilter","measureDataFormat","measureDataFilter","measureCSVFilter","tagCSVFilter","DXFFileFormat","SHPFileFormat","IFCFileFormat","xmlFileFormat","drawingFilter","DXFModelFilter","SHPModelFilter","ZIPFileFilter","modelFileFilter","labelFilter","modelFilter","xmlFileFilter","lasFileFilter","ColorType","MarkerNavType","defaultClassifications","classification","available","initialSettingsState","colorMap","colorType","Height","dynamicSize","circularPoints","arrowMarkers","Arrows","cloudMaxPoints","cloudDistance","cloudScale","cloudMinimum","tagDistance","modelDistance","drawerOpen","heightClip","intensityClip","saveSettingsDefaults","cloneDeep","applySavedSettings","settingsSlice","updateSettingsState","applySavedDefaults","defaults","changeDefaultSettings","changeOpacity","changeTagDistance","changeModelDistance","changeCloudDistance","changeCloudMaxPoints","changeCloudScale","changeCloudMinimum","changeHeightClip","changeIntensityClip","changeColorMap","changeColorType","changeDynamicSize","changeCircularPoints","changeAvailableClassifications","availableClassifications","Set","has","changeClassificationVisibility","changeAllClassificationVisibility","changeSwitched","changeSelectedTab","changeAssetDrawerState","changeArrowMarkers","selectOpacity","selectTagDistance","selectCloudDistance","selectCloudMaxPoints","selectCloudScale","selectCloudMinimum","selectHeightClip","selectIntensityClip","selectColorMap","selectColorType","selectDynamicSize","selectCircularPoints","selectViewerSwitched","selectSelectedTab","selectAssetDrawerState","selectArrowMarkers","selectClassifications","getAvailableClassifications","getClassificationVisibilities","selectModelDistance","getDateTimeFormat","memoizeFormatConstructor","Intl","DateTimeFormat","defaultOptions","timeStyle","dateStyle","toLocaleString","language","createdAt","format","BrandingContext","olButtonParent","background","borderRadius","olButtonTopLeft","olButtonBottomLeft","bottom","olButton","outline","olButtonRotate","transition","EnhancedIconButton","tooltipText","tooltipTitle","dangerouslySetInnerHTML","__html","ArrowTooltip","OpenLayersIcon","rotate","placement","DenseIcon","centered","other","ListItemIcon","draggableTitleClose","grey","marginRight","draggableContent","maxWidth","draggableMouseDown","modal","draggableContentParent","overflow","draggableTopDiv","draggableBackdropPaper","draggableBackdropRounded","draggableRoundCorner","draggableTitle","userSelect","cursor","draggableTitleDown","progressContent","progressNoTransition","simpleDialogMain","simpleDialogHeader","simpleDialogTitle","simpleDialogClose","PromptDialog","DialogTitle","DialogContent","DialogContentText","DialogActions","AlertDialog","TextDialog","clear","setText","setDisabled","handleSubmit","trimmedText","onKeyDown","autoFocus","DropDownDialog","defaultValue","setValue","SimpleDialog","canClose","DraggableDialog","resize","initialHeight","initialWidth","resizeElementID","useMemo","paperPropID","mouseDown","setMouseDown","dialogSize","setDialogSize","dialogPosition","setDialogPosition","headerHeight","interval","setInterval","element","dialogWidth","clientWidth","dialogHeight","clientHeight","parentWidth","innerWidth","parentHeight","dialogLeft","dialogBottom","dialogRight","newPosition","isEqual","checkOutOfBounds","clearInterval","handle","bounds","onDrag","fullScreen","disableEnforceFocus","aria-labelledby","paperFullScreen","scrollPaper","slotProps","backdrop","PaperProps","onMouseDown","onMouseUp","ProgressDialog","percent","animated","LinearProgress","bar","LabelCategoryDialog","getSelectedLabels","selectedLabelIDs","highlightedLabels","getCategoryDropdown","allCategories","getAllCategories","highlightedCategories","labelID","getCategoryByLabelID","choosableCategories","category","dropDownList","labelIDs","transferLabel","draggingListItem","staticListItem","borderBottom","flexGrow","DraggableListItem","setData","inputName","listLength","useStaticListItem","draggableId","provided","snapshot","ListItem","ref","innerRef","draggableProps","dragHandleProps","isDragging","NumberField","step","DraggableList","memo","onDragEnd","droppableId","droppableProps","header","fontWeight","whiteSpace","densePadding","denseFooter","hiddenSort","clip","noSelect","rowDisabled","rowIcon","buttonCell","buttonHeader","tableRow","paddingLeft","EnhancedTableCheckboxHead","numVisible","indeterminate","stopPropagation","EnhancedTableHead","onRequestSort","dense","hasActions","TableHead","TableRow","sortable","TableCell","align","sortDirection","TableSortLabel","active","hideSortIcon","direction","property","EnhancedTableBody","setSelectedRow","handleContextMenu","TableBody","hover","tabIndex","EnhancedTableCell","i18n","isString","condition","cellContent","wordBreak","forceOpacity","pointer","EnhancedTable","contextMenu","search","setSearch","selectedRow","tableRows","numberOfRows","Input","TableContainer","Table","stickyHeader","TablePagination","rowsPerPageOptions","component","labelRowsPerPage","labelDisplayedRows","to","getItemAriaLabel","onPageChange","onRowsPerPageChange","DenseMenu","subMenuRoot","justifyContent","subMenuLabel","NestedMenuItem","React","forwardRef","parentMenuOpen","rightIcon","tabIndexProp","ContainerProps","ContainerPropsProp","MenuItemProps","containerRefProp","menuItemRef","useImperativeHandle","current","containerRef","menuContainerRef","isSubMenuOpen","setIsSubMenuOpen","isSubmenuFocused","ownerDocument","activeElement","child","onFocus","onMouseEnter","onMouseLeave","focus","firstChild","Menu","pointerEvents","anchorEl","anchorOrigin","vertical","horizontal","transformOrigin","MenuListProps","keepMounted","disableAutoFocus","NestedMenu","MenuDivider","Divider","onEnter","enteringScreen","transitions","duration","transitionProps","timeout","enter","exit","anchorReference","TransitionComponent","Grow","TransitionProps","Tooltip","CursorTooltip","lines","disableToggle","disableZoom","hidden","setHidden","modifiedLines","hasLines","onHotkey","HTMLInputElement","which","followCursor","converter","flexibleHeight","dropdownWithLabel","paddingBottom","inputParent","inputLabel","buttonMargin","NumberFieldWithUnits","NumberFieldNoUnits","NumberFieldWithLabel","adornment","helperText","endAdornment","inputProps","hasError","floatValue","convertedMin","setConvertedMin","convertedMax","setConvertedMax","convertedData","setConvertedData","convertNearestStep","roundFunc","numSteps","floor","DropdownWithLabel","seperator","menuOptions","optionsToDropdown","DropdownWithLabelInline","FormControl","hasSeperator","isLastItem","FolderWithLabel","showOpenDialog","properties","canceled","folderPath","slash","filePaths","FileWithLabel","optional","saveFile","handleChange","showSaveDialog","Delete","Save","AttachFile","InputWithLabel","required","touched","setTouched","onInputChange","onBlur","TextWithLabel","renderAsHTML","typography","body1","TextFieldWithLabelInline","CheckboxWithLabel","onCheckboxChange","_","Switch","SwitchWithLabel","SwitchWithLabelInline","EditableTextField","permissions","editing","setEditing","newValue","setNewValue","edit","EditButtonGroup","EditableDropdown","currentOption","newOption","ColorPickerWithLabelInline","ColorPicker","NeverAskCheckbox","FormGroup","LinearProgressWithLabel","Box","mr","TabPanel","BoxProps","role","verticalDivider","icons","iconButton","iconSize","listIcon","DenseDivider","spacingDown","spacingUp","DividerWithText","Chip","IconToolBar","ToolBarDivider","FontAwesomeIcon","errorColor","Icon","colorPrimary","ToolBarButton","SlimScrollbar","scrollHeight","autoHide","autoHeight","autoHeightMin","autoHeightMax","autoHideTimeout","autoHideDuration","DynamicScrollbar","scrollPercent","setScroll","setMaxHeight","listElementID","checkScrollHeight","offsetHeight","percentHeight","getMaxHeight","memoWithOpen","areEqual","prevProps","nextProps","menuStateCache","fileMenu","submenu","click","WorkflowExecutable","sendToMainWindow","exitFromApp","helpMenu","isDevMode","accelerator","remote","getCurrentWindow","toggleDevTools","shell","openPath","logDirectoryPath","clearMlResources","openExternal","toolsMenu","enabled","debugMenu","clearTempFolder","reload","webContents","send","showMessageBox","noLink","setToolEnabled","toolName","getApplicationMenu","getMenuItemById","setMenuState","running","showStatus","license_check","buildElectronMenu","isStandardProject","template","menu","buildFromTemplate","setApplicationMenu","checkAllowedMenuItems","LanguageOptions","LanguagePopover","selectProjectType","Standard","changeLanguage","updateCompass","setLocalizedURL","clearTimeout","Popover","disableScrollLock","ListItemText","LanguageSwitch","popover","textTransform","divider","buttonParent","AccountPopover","linkAccount","signOut","loggedIn","user","accountType","ViewOnly","Admin","getAccountType","firstName","lastName","email","AccountButton","Toaster","toasts","useToasterStore","remove","toastOptions","backdropFilter","alpha","common","white","boxShadow","shadows","typographyLink","textDecoration","textDecorationColor","TypographyLink","openExternalLink","colorPicker","setColor","disableUnderline","input","engineCloudURLKey","tagQueryString","setEngineCloudURL","force","isElectronApp","currentEngineCloudURL","localStorage","getItem","setItem","location","redirectToLogin","searchParams","returnTo","href","setAttribute","appendChild","removeChild","initialAerialState","basemap","cameraStateSlice","adjustments","changeCameraTransform","changeCameraState","changeCameraHeight","changeBasicAdjustments","changeSavedAerialState","selectCameraHeight","selectActiveCamera","selectCameraState","selectOrbitMode","selectCameraTransform","selectBasicAdjustments","selectSavedAerialState","resources","en","de","fr","es","ja","ar","supportedLngs","use","initReactI18next","LanguageDetector","init","detection","cookieMinutes","fallbackLng","interpolation","escapeValue","getLocalizedURL","history","pushState","profileContainer","toolbarDropdown","profileChart","PointProfile","samplingType","setSamplingType","displayUnits","setDisplayUnits","savePointProfileImageBrowser","imageBase64","getPointProfileImage","projectName","savePointProfileImageElectron","defaultPath","imageBase64Data","imageBuffer","fs","writeFileSync","encoding","catch","setPointProfileSampling","setPointProfileUnits","resetPointProfile","refreshPointProfile","resetPointProfileView","initProfileContainer","devModeConfig","appPath","app","getAppPath","readFileSync","testing","getDevModeConfig","Executable","exePath","exeName","developerKey","spawnDetached","logText","basePath","executablePath","dirname","statusMessage","pid","parseCommandsList","copyableCommands","onLogs","commandList","cwd","spawn","env","process","PYTHONUNBUFFERED","NODEJS","detached","copyPasteCommands","on","commandIndex","commandName","saveLogFile","stderr","parseLines","stdout","line","messageType","messageData","destroy","execSync","onbeforeunload","write","stdin","manifest","workflowName","logPrefix","dateString","replaceAll","logPath","logs","writeFile","filenames","readdir","oldestFilePath","oldest","filename","stats","stat","birthtime","trackToolUsage","electron","ipcRenderer","pattern","pathname","getCloudProjectID","checkForCloudSite","isPackaged","tempDirectoryPath","getPath","getTemporaryFile","existsSync","numRemoved","eventName","removeAllListeners","mkdirSync","recursive","userSettings","storagePath","engineStoragePath","viewerStoragePath","productName","settingName","oldName","newName","copyFileSync","setDataPath","engineProjectionExist","viewerProjectionExist","dataPath","engineProjections","finalData","projectionsByName","changeDuplicateNames","setStoragePath","isModelFile","isStreamablePointsFile","isRawPointsFile","getModelLayers","originalId","getWebmapLayers","identifier","String","getBaseAsset","getTagsData","comment","roll","pitch","yaw","config","object","defaultProjectTitle","currentConfigVersion","minimumConfigVersion","projectSlice","uniqueSession","configVersion","updateProjectID","updateSessionID","updateProjectName","changePath","selectProjectID","selectProjectName","defaultFolderTitle","generateDefaultFolder","allowAnonViewers","foldersSlice","createFolder","updateFolder","newDefaultFolder","deleteFolder","wsCreateFolder","wsUpdateFolder","wsDeleteFolder","selectDefaultFolder","selectAllFolders","projectionsSlice","view","measureUnits","changeMeasureUnits","selectViewProjection","selectMeasureUnits","originalFetch","handler","locked","accessTokenKey","refreshTokenKey","clearTokens","removeItem","checkForKey","tokenKey","token","get","updateTokens","others","accessToken","refreshToken","initialUserState","apiKey","adminPermissions","access","emptyPermissions","createContext","getAppCode","checkVersion","AuthProvider","websockets","activate","appCode","access_code","useAppCode","retryAttempt","initialize","newState","getUser","connect","getPermissions","Provider","stSignOut","disconnect","serverConfigVersion","semver","eq","SuperTokens","appInfo","appName","apiDomain","apiBasePath","recipeList","Session","EmailPassword","customFetch","wait","initCustomFetch","activeToolOpen","setActiveToolOpen","ActiveToolProvider","setViewer","ViewerProvider","TaskStatus","taskQueue","addRunningTask","onFinish","stopRunningTask","task","clearTaskQueue","TaskQueueProvider","setTaskQueue","setRunning","runningTask","Running","updateTaskStatus","taskID","tasks","availableTasks","Waiting","runAvailableTask","Finished","newTask","orthoQuality","orthoOpacity","controlType","openQuickNav","aerialMeasureType","Spherical","volumeType","MultiPlane","volumeSampleRate","Medium","viewerBackground","aerialBackground","GlobalSettingsProvider","loadFromStorage","cache","now","configURL","getGlobalSettingsFromStorage","saveToStorage","EventType","ObjectType","joinRoom","roomID","WebSocketProvider","socket","setSocket","currentRoomID","setCurrentRoomID","onCreate","Assets","Folders","Bookmarks","onUpdate","objectID","register","CreateObject","UpdateObject","DeleteObject","extraHeaders","Authorization","io","addTrailingSlash","connected","emit","LeaveRoom","JoinRoom","loadBookmark","deleteBookmarks","BookmarksProvider","applySavedAerialState","visibleAssetIDs","bookmarkAssetIDs","assetIDs","getValidAssetIDs","applySavedSceneState","setInitialStateFlag","companyName","iconPath","BrandingProvider","hostname","mosaicLogo","spiralIntersect","spiral","stepDist","sigDigs","spiralParams","spiType","RL","constant","reverseCurve","partial","radiusEnd","radiusStart","cw","rot","delta","L","dirEnd","dirStart","xStart","yStart","xEnd","yEnd","segmentMin","segmentMax","Start","c","End","d","xCorr","yCorr","deltaCorr","ls","le","distMin","endPointError","chosenDelta","deltaTrial","l","xRotated","yRotated","xDiff","yDiff","dist","spiralParamaters","spiralCoord","distAlong","distAcross","xAtLength","yAtLength","lengthLocal","distAcrossNew","sideOfLine","lineDist","textures","tagTextures","basicPins","trafficSigns","UKRoadSigns","packageObjects","icon0","icon1","icon2","icon3","icon4","icon5","icon6","icon7","icon8","icon9","icon10","icon11","icon12","icon13","icon14","icon15","icon16","icon17","icon18","icon19","icon20","icon21","icon22","icon23","icon24","icon25","icon26","icon27","icon28","icon29","icon30","icon31","icon32","icon33","icon34","icon35","icon36","icon37","icon38","icon39","icon40","icon41","icon42","icon43","icon44","icon45","icon46","icon47","icon48","icon49","icon50","icon51","icon52","icon53","icon54","icon55","icon56","icon57","icon58","icon59","icon60","icon61","icon62","icon63","icon64","icon65","icon66","icon67","icon68","icon69","icon70","icon71","icon72","icon73","icon74","icon75","icon76","icon77","icon78","icon79","icon80","icon81","icon82","icon83","icon84","icon85","icon86","icon87","icon88","icon89","icon90","icon91","icon92","icon93","icon94","icon95","icon96","icon97","icon98","icon99","icon100","icon101","icon102","icon103","icon104","icon105","icon106","icon107","icon108","icon109","icon110","icon111","icon112","icon113","icon114","icon115","icon116","icon117","icon118","icon119","icon120","icon121","icon122","icon123","icon124","icon125","icon126","icon127","icon128","icon129","icon130","icon131","icon132","icon133","icon134","icon135","icon136","icon137","icon138","icon139","icon140","icon141","icon142","icon143","icon144","icon145","icon146","icon147","icon148","icon149","icon150","icon151","icon152","icon153","icon154","icon155","icon156","icon157","icon158","icon159","icon160","icon161","icon162","icon163","icon164","icon165","icon166","icon167","icon168","icon169","icon170","icon171","icon172","icon173","icon174","icon175","icon176","icon177","icon178","icon179","icon180","icon181","icon182","icon183","icon184","icon185","icon186","icon187","icon188","icon189","icon190","icon191","icon192","icon193","icon194","icon195","icon196","icon197","icon198","icon199","icon200","icon201","icon202","icon203","icon204","icon205","icon206","icon207","icon208","icon209","icon210","icon211","icon212","icon213","icon214","icon215","icon216","icon217","icon218","icon219","icon220","icon221","icon222","icon223","icon224","icon225","icon226","icon227","icon228","icon229","icon230","icon231","icon232","icon233","icon234","icon235","icon236","icon237","icon238","icon239","icon240","icon241","icon242","icon243","icon244","icon245","icon246","icon247","icon248","icon249","icon250","icon251","icon252","icon253","icon254","icon255","icon256","icon257","icon258","icon259","icon260","icon261","icon262","icon263","icon264","icon265","icon266","icon267","icon268","icon269","icon270","icon271","icon272","icon273","icon274","icon275","icon276","icon277","icon278","icon279","icon280","icon281","icon282","icon283","icon284","icon285","icon286","icon287","icon288","icon289","icon290","icon291","icon292","icon293","icon294","icon295","icon296","icon297","icon298","icon299","icon300","icon301","icon302","icon303","icon304","icon305","icon306","icon307","icon308","icon309","icon310","icon311","icon312","icon313","icon314","icon315","icon316","icon317","icon318","icon319","icon320","icon321","icon322","icon323","icon324","icon325","icon326","icon327","icon328","icon329","icon330","icon331","icon332","icon333","icon334","icon335","icon336","icon337","icon338","icon339","icon340","icon341","icon342","icon343","icon344","icon345","icon346","icon347","icon348","icon349","icon350","icon351","icon352","icon353","icon354","icon355","icon356","icon357","icon358","icon359","icon360","icon361","icon362","icon363","icon364","icon365","icon366","icon367","icon368","icon369","icon370","icon371","icon372","icon373","icon374","icon375","icon376","icon377","icon378","icon379","icon380","icon381","icon382","icon383","icon384","icon385","icon386","icon387","icon388","icon389","icon390","icon391","icon392","icon393","icon394","icon395","icon396","icon397","icon398","icon399","icon400","icon401","icon402","icon403","icon404","icon405","icon406","icon407","icon408","icon409","icon410","icon411","icon412","icon413","icon414","icon415","icon416","icon417","icon418","icon419","icon420","icon421","icon422","icon423","icon424","icon425","icon426","icon427","icon428","icon429","icon430","icon431","icon432","icon433","icon434","icon435","icon436","icon437","icon438","icon439","icon440","icon441","icon442","icon443","icon444","icon445","icon446","icon447","icon448","icon449","icon450","icon451","icon452","icon453","icon454","icon455","icon456","icon457","icon458","icon459","icon460","icon461","icon462","icon463","icon464","icon465","icon466","icon467","icon468","icon469","icon470","icon471","icon472","icon473","icon474","icon475","icon476","icon477","icon478","icon479","icon480","icon481","icon482","icon483","icon484","icon485","icon486","icon487","icon488","icon489","icon490","icon491","icon492","icon493","icon494","icon495","icon496","icon497","icon498","icon499","icon500","icon501","icon502","icon503","icon504","icon505","icon506","icon507","icon508","icon509","icon510","icon511","icon512","icon513","icon514","icon515","icon516","icon517","icon518","icon519","icon520","icon521","icon522","icon523","icon524","icon525","icon526","icon527","icon528","icon529","icon530","icon531","icon532","icon533","icon534","icon535","icon536","icon537","icon538","icon539","icon540","icon541","icon542","icon543","icon544","icon545","icon546","icon547","icon548","icon549","icon550","icon551","icon552","icon553","icon554","icon555","icon556","icon557","icon558","icon559","icon560","icon561","icon562","icon563","icon564","icon565","icon566","icon567","icon568","icon569","icon570","icon571","icon572","icon573","icon574","icon575","icon576","icon577","icon578","icon579","icon580","icon581","icon582","icon583","icon584","icon585","icon586","icon587","icon588","icon589","icon590","icon591","icon592","icon593","icon594","icon595","icon596","icon597","icon598","icon599","icon600","icon601","icon602","icon603","icon604","icon605","icon606","icon607","icon608","icon609","icon610","icon611","icon612","icon613","icon614","icon615","icon616","icon617","icon618","icon619","icon620","icon621","icon622","icon623","icon624","icon625","icon626","icon627","icon628","icon629","icon630","icon631","icon632","icon633","icon634","icon635","icon636","icon637","icon638","icon639","icon640","icon641","icon642","icon643","icon644","icon645","icon646","icon647","icon648","icon649","icon650","icon651","icon652","icon653","icon654","icon655","icon656","icon657","icon658","icon659","icon660","icon661","icon662","icon663","icon664","icon665","icon666","icon667","icon668","icon669","icon670","icon671","icon672","icon673","icon674","icon675","icon676","icon677","icon678","icon679","icon680","icon681","icon682","icon683","icon684","icon685","icon686","icon687","icon688","icon689","icon690","icon691","icon692","icon693","icon694","icon695","icon696","icon697","icon698","icon699","icon700","icon701","icon702","icon703","icon704","icon705","icon706","icon707","icon708","icon709","icon710","icon711","icon712","icon713","icon714","icon715","icon716","icon717","icon718","icon719","icon720","icon721","icon722","icon723","icon724","icon725","icon726","icon727","icon728","icon729","icon730","icon731","icon732","icon733","icon734","icon735","icon736","icon737","icon738","icon739","icon740","icon741","icon742","icon743","icon744","icon745","icon746","icon747","icon748","icon749","icon750","icon751","icon752","icon753","icon754","icon755","icon756","icon757","icon758","icon759","icon760","icon761","icon762","icon763","icon764","icon765","icon766","icon767","icon768","icon769","icon770","icon771","icon772","icon773","icon774","icon775","icon776","icon777","icon778","icon779","icon780","icon781","icon782","icon783","icon784","icon785","icon786","icon787","icon788","icon789","icon790","icon791","icon792","icon793","icon794","icon795","icon796","icon797","icon798","icon799","icon800","icon801","icon802","icon803","icon804","icon805","icon806","icon807","icon808","icon809","icon810","icon811","icon812","icon813","icon814","icon815","icon816","icon817","icon818","icon819","icon820","icon821","icon822","icon823","icon824","icon825","icon826","icon827","icon828","icon829","icon830","icon831","icon832","icon833","icon834","icon835","icon836","icon837","icon838","icon839","icon840","icon841","icon842","icon843","icon844","icon845","icon846","icon847","icon848","icon849","icon850","icon851","icon852","icon853","icon854","icon855","icon856","icon857","icon858","icon859","icon860","icon861","icon862","icon863","icon864","icon865","icon866","icon867","icon868","icon869","icon870","icon871","icon872","icon873","icon874","icon875","icon876","icon877","icon878","icon879","icon880","icon881","icon882","icon883","icon884","icon885","icon886","icon887","icon888","icon889","icon890","icon891","icon892","icon893","icon894","icon895","icon896","icon897","icon898","icon899","icon900","icon901","icon902","icon903","icon904","icon905","icon906","icon907","icon908","icon909","icon910","icon911","icon912","icon913","icon914","icon915","icon916","icon917","icon918","icon919","icon920","icon921","icon922","icon923","icon924","icon925","icon926","icon927","icon928","icon929","icon930","icon931","icon932","icon933","icon934","icon935","icon936","icon937","icon938","icon939","icon940","icon941","icon942","icon943","icon944","icon945","icon946","icon947","icon948","icon949","icon950","icon951","icon952","icon953","icon954","icon955","icon956","icon957","icon958","icon959","icon960","icon961","icon962","icon963","icon964","icon965","icon966","icon967","icon968","icon969","icon970","icon971","icon972","icon973","icon974","icon975","icon976","icon977","icon978","icon979","icon980","icon981","icon982","icon983","icon984","icon985","icon986","icon987","icon988","icon989","icon990","icon991","icon992","icon993","icon994","icon995","icon996","icon997","icon998","icon999","icon1000","icon1001","icon1002","icon1003","icon1004","icon1005","icon1006","icon1007","icon1008","icon1009","icon1010","icon1011","icon1012","icon1013","icon1014","icon1015","icon1016","icon1017","icon1018","icon1019","icon1020","icon1021","icon1022","icon1023","icon1024","icon1025","icon1026","icon1027","icon1028","icon1029","icon1030","icon1031","icon1032","icon1033","icon1034","icon1035","icon1036","icon1037","icon1038","icon1039","icon1040","icon1041","icon1042","icon1043","icon1044","icon1045","icon1046","icon1047","icon1048","icon1049","icon1050","icon1051","icon1052","icon1053","icon1054","icon1055","icon1056","icon1057","icon1058","icon1059","icon1060","icon1061","icon1062","icon1063","icon1064","icon1065","icon1066","icon1067","icon1068","icon1069","icon1070","icon1071","icon1072","icon1073","icon1074","icon1075","icon1076","icon1077","icon1078","icon1079","icon1080","icon1081","icon1082","icon1083","icon1084","icon1085","icon1086","icon1087","icon1088","icon1089","icon1090","icon1091","icon1092","icon1093","icon1094","icon1095","icon1096","icon1097","icon1098","icon1099","icon1100","icon1101","icon1102","icon1103","icon1104","icon1105","icon1106","icon1107","icon1108","icon1109","icon1110","icon1111","icon1112","icon1113","icon1114","icon1115","icon1116","icon1117","icon1118","icon1119","icon1120","icon1121","icon1122","icon1123","icon1124","icon1125","icon1126","icon1127","icon1128","icon1129","icon1130","icon1131","icon1132","icon1133","icon1134","icon1135","icon1136","icon1137","icon1138","icon1139","icon1140","icon1141","icon1142","icon1143","icon1144","icon1145","icon1146","icon1147","icon1148","icon1149","icon1150","icon1151","icon1152","icon1153","icon1154","icon1155","icon1156","icon1157","icon1158","icon1159","icon1160","icon1161","icon1162","icon1163","icon1164","icon1165","icon1166","icon1167","icon1168","icon1169","icon1170","icon1171","icon1172","icon1173","icon1174","icon1175","icon1176","icon1177","icon1178","icon1179","icon1180","icon1181","icon1182","icon1183","icon1184","icon1185","icon1186","icon1187","icon1188","icon1189","icon1190","icon1191","icon1192","icon1193","icon1194","icon1195","icon1196","icon1197","icon1198","icon1199","icon1200","icon1201","icon1202","icon1203","icon1204","icon1205","icon1206","icon1207","icon1208","icon1209","icon1210","icon1211","icon1212","icon1213","icon1214","icon1215","icon1216","icon1217","icon1218","icon1219","icon1220","icon1221","icon1222","icon1223","icon1224","icon1225","icon1226","icon1227","icon1228","icon1229","icon1230","icon1231","icon1232","icon1233","icon1234","icon1235","icon1236","icon1237","icon1238","icon1239","icon1240","icon1241","icon1242","icon1243","icon1244","icon1245","icon1246","icon1247","icon1248","icon1249","icon1250","icon1251","icon1252","icon1253","icon1254","icon1255","icon1256","icon1257","icon1258","icon1259","icon1260","icon1261","icon1262","icon1263","icon1264","icon1265","icon1266","icon1267","icon1268","icon1269","icon1270","icon1271","icon1272","icon1273","icon1274","icon1275","icon1276","icon1277","icon1278","icon1279","icon1280","icon1281","icon1282","icon1283","icon1284","icon1285","icon1286","icon1287","icon1288","icon1289","icon1290","icon1291","icon1292","icon1293","icon1294","icon1295","icon1296","icon1297","icon1298","icon1299","icon1300","icon1301","icon1302","icon1303","icon1304","icon1305","icon1306","icon1307","icon1308","icon1309","icon1310","icon1311","icon1312","icon1313","icon1314","icon1315","icon1316","icon1317","icon1318","icon1319","icon1320","icon1321","icon1322","icon1323","icon1324","icon1325","icon1326","icon1327","icon1328","icon1329","icon1330","icon1331","icon1332","icon1333","icon1334","icon1335","icon1336","icon1337","icon1338","icon1339","icon1340","icon1341","icon1342","defaultTagTexture","getTagTexturePath","TagSize","AnnotationSize","AnnotationDrawType","useAssetTools","addAssetPaths","totalAssetsAdded","tagPaths","isTagFile","tagPathsAdded","addTagCSVs","toRemove","planarPaths","isPlanarFile","addPlanarFiles","panoramicPaths","isPanoramicFile","addPanoramicFiles","pointCloudPaths","isPointCloudFile","addPointCloudFiles","orthoPaths","isOrthomosaicFile","addOrthoFiles","modelPaths","addModelFiles","xmlPaths","isXmlFile","addXMLFiles","ifcPaths","isIFCFile","shpPaths","isSHPFile","dxfPaths","isDXFFile","modelsAdded","addIFCFiles","addSHPFiles","addDXFFiles","assetsList","LASPaths","isLASFile","assetPath","extension","extname","showBackdrop","numAdded","addOrthoBatch","hideBackdrop","catchErrors","pathsAdded","numberOfTags","addTagCSV","numFilesAdded","numMissing","addPanoramicFile","pathError","addPlanarFile","addXMLFile","addFilePaths","configs","isConfigFile","isAssetFile","isProjectionFile","loadProjectFile","projectionPath","addWebSource","downloadFile","fileType","fileFilter","encodeURIComponent","savePath","getPathFromDialog","pathWithExtension","isCSVFile","isTXTFile","isRZMLFile","isODMFile","getDXFLayerNames","getSHPLayerNames","dbf","layerData","dbfPath","geotiff","file_path","corners","base64","base64_split","scale_x","scale_y","width_original","height_original","orthoData","imageBounds","imageDataSplit","imageSize","imageSizeOriginal","imagePath","scaleX","scaleY","cameras","numCameras","cameraData","rowData","parser","Parser","explicitChildren","preserveChildrenOrder","xmlJSON","parseStringPromise","xmlData","info","$","$$","alignments","enu","Alignments","Alignment","alignment","alignObject","staStart","about","desc","CoordGeom","geom","geometryElement","shapeType","dollarSignKeys","featureKeys","key$","aboutValue","fKey","splitCoordValue","tempValue","coordValue","coordValueCorrected","scv","overwriteLength","overwriteStaStart","calcAngle","acos","curveDist","getHeaderIndex","CSV","xIndex","yIndex","nameIndex","annotationIndex","commentIndex","hasHeight","easting","northing","definition","elevation","openDialogMulti","showErrorBox","openDialogFile","parseDirectory","entries","directoryPath","withFileTypes","files","entry","isFile","directories","isDirectory","directory","saveMatrixFile","cameraTransformPath","copyFile","readTransformFile","errorResponse","arr","cols","col","getMatrixValues","setFromMatrixPosition","setPosition","setFromRotationMatrix","upgradeVersion324","oldVersion","gt","getConfigVersion","upgradeVersion323","upgradeVersion322","upgradeVersion321","upgradeVersion320","upgradeVersion319","links","upgradeVersion318","mappedCamerasIDs","upgradeVersion317","overrideSettings","fromJSON","upgradeVersion316","upgradeVersion315","upgradeVersion314","isDefault","upgradeVersion313","upgradeVersion312","upgradeVersion311","cloudSize","upgradeVersion310","newVersion","upgradeVersion39","extent","resolution","log2","upgradeVersion38","upgradeVersion37","upgradeVersion36","upgradeVersion35","upgradeVersion34","getLocalizedProjectName","getLocalizedFolderName","saveProjectAs","nameWithoutExt","writeProject","saveProject","allowSaveAs","loadProjectJSON","version","clearWindowHash","lt","loadProject","buttons","exitWithChanges","Cloud","hasChanged","originalState","modifiedState","defaultId","DetectionType","mixedDataWarning","BlurVehiclesPeople","outputPath","setOutputPath","detectionType","setDetectionType","VehiclesAndPeople","blurStrength","setBlurStrength","accuracy","setAccuracy","checkEdges","setCheckEdges","importResult","setImportResult","getCamerasByCSV","getCameraFolders","pathOverlap","tempImagePath","imagesCSVPath","pathsJSON","getCameraRowsCSV","Vehicles","People","multipleSelectWithLabel","OperationTypes","ClassifyExport","operationType","setOperationType","Include","classValues","setClassValues","classList","pointclouds","uniqueClassifications","formatClassValue","classValue","Exclude","multiple","renderValue","renderedClasses","classVal","savedLocation","wordWrap","ConvertUnits","inputUnits","setInputUnits","outputUnits","setOutputUnits","nullUnits","sameUnits","pathNameNoExt","outputName","FormHelperText","ChannelType","ChannelSelector","Empty","Red","Green","Blue","Linearity","Planarity","Scattering","Normal","Intensity","NumReturns","ReturnNumber","Classification","LasToOrthomosaic","channelOne","setChannelOne","channelTwo","setChannelTwo","channelThree","setChannelThree","pixelSize","setPixelSize","emptyChannels","tifPath","LasToSolv3dStreamable","isSingleFile","setSingleFile","binPath","Sampling","defaultSamplingRateOptions","samplingRate","setSamplingRate","validSampling","decimalSamplingRate","ThinTechniques","ThinDimensions","invalidThinningError","ThinLas","defaultThinningOptions","thinTechnique","setThinTechnique","Lowest","thinDimension","setThinDimension","Two","thinning","setThinning","inValidThinningValue","Average","Highest","Three","InterpolateDXF","demPath","setDemPath","InterpolateSHP","generateFunctionData","FunctionsMenu","contextOpen","closeContextMenu","blurVehiclesPeopleDialog","lasToOrthomosaicDialog","lasToSolv3dStreamableDialog","thinLasDialog","samplingDialog","classifyExportDialog","convertUnitsDialog","interpolateSHPDialog","interpolateDXFDialog","LASFiles","cameraFiles","SHPFiles","DXFFiles","hasLASFiles","hasCameraFiles","hasSHPFiles","hasDXFFiles","handleBlurVehiclesPeople","handleLasToOrthomosaic","handleLasToSolv3dStreamable","handleThinLas","handleSampling","handleClassifyExport","handleConvertUnits","handleInterpolateSHP","handleInterpolateDXF","filtered","localeCompare","getMenuItems","ServerType","initialAssetState","assetPercent","assetError","assetIsLarge","floatRight","float","itemText","assetMargins","assetWarning","assetInfo","assetCheckbox","right","checkboxParent","percentLabel","fileInfoHeading","fileInfoText","tagAvatar","remoteAssetIcon","LasFileInfoDialog","hasVLRSData","vlrs_data","vlrsKeys","getLasFileInfo","x_min","x_max","y_min","y_max","z_min","z_max","record_id","has_time_stamp","has_rgb","has_intensity","AssetItem","setDraggingAsset","fileInfoDialog","detailsDialog","renameDialog","iconUpdateDialog","modelLayersDialog","webmapLayersDialog","landXMLDialog","assetState","setAssetState","isPanoramic","isPlanar","isEncompassCloud","isPotreeCloud","isE57File","isOrtho","isTag","isIFC","isSHP","isDXF","isLandXML","isWebMap","isCamera","isPointCloud","canEditLayers","ArcGISImageServer","TileServer","updateAssetState","newAssetState","getCloudStatus","getModelStatus","submitTagIcon","isLargeCloud","showPercent","assetCount","getAssetCount","tagTexture","tagSize","getTagAttributes","isRemoteAsset","canDeleteAsset","canEditAsset","ListItemButton","draggable","onContextMenu","onDragStart","snapToOrtho","snapToPointCloud","snapToImages","snapToModel","Avatar","secondaryTypographyProps","ListItemSecondaryAction","edge","handleImageCSVExport","getTagsByCSV","getTagRowsCSV","handleTagCSVExport","TagIconDialog","currentTexture","currentSize","WebSourceLayerDialog","ModelLayerDialog","TagItemsDialog","NEW_CSV_ID","NEW_FOLDER_ID","textField","selectDivider","asterisk","avatarParent","tagIconPagination","tagIconSearchParent","tagIconPageParent","tagIconParent","tagIconCheck","tagIconImage","setTagTexture","setTagSize","selectedPage","tagsPerPage","resetDefaults","searchTerms","matches","iconChanged","sizeChanged","tagIconsPerRow","numPages","texturesForPage","handleIconClick","XSmall","Small","Large","XLarge","formatter","getMeasurementFormatter","getViewProjection","getVectorPrecision","tagItems","zoomToTag","jumpToTag","copyPosition","copyTextToClipboard","copyURL","deleteRow","tagToDelete","isAerialTag","TagDeleteDialog","toDelete","numTagsToDelete","TagDetailsDialog","setTagID","tagFiles","getTagDetails","AnnotationsToolbar","TagDetailsContent","viewerSwitched","setSize","savedAnnotations","savedTagID","setTagAnnotationType","setTagAnnotationColor","setTagAnnotationSize","toggleTagAnnotations","loadTagAnnotations","setTagSelected","setTagAnnotationDrawing","typeOptions","PolygonFreeHand","LineString","LineStringFreeHand","Rectangle","Circle","Star","Eraser","sizeOptions","showToolbar","gap","getTagAnnotations","TagCreateDialog","setTitle","setComment","collectionID","setCollectionID","collectionName","setCollectionName","setFolderID","hasExistingFolders","hasExistingCSVs","createNewFile","createNewFolder","titleMissing","nameMissing","localizedFolderName","newTag","tagFolderID","tagCollectionID","tagCSV","Collapse","in","assetFolderClass","FolderDialog","setName","setAllowAnonViewers","AssetFolder","draggingAsset","editDialog","setExpanded","dragDropHover","setDragDropHover","numHidden","onDragOver","onDragLeave","onDrop","dataTransfer","addAssetsToFolder","newVisibility","List","disablePadding","AddAssetList","WebSourceDialog","serverURL","setServerURL","serverName","setServerName","serverType","setServerType","ArcGISMapServer","submitting","setSubmitting","getMapLayers","baseURL","getMapServerLayers","ok","getImageServerLayers","ArcGISFeatureServer","getFeatureServerLayers","OGCWMS","WMSCapabilities","Capability","Layer","Name","Title","getWMSLayers","OGCWFS","XMLParser","FeatureTypeList","FeatureType","getWFSLayers","OGCWMTS","WMTSCapabilities","Contents","Identifier","getWMTSLayers","getTileServerLayers","isSecureURL","protocol","mapType","pop","hasX","hasY","hasZ","ArcGISOnline","warnings","showEsriWarning","webmapData","public","WebSourceLayerCheckbox","onVisibilityChange","visible_sortable","visible_checkbox","getRows","webmapDialog","handleAddWebMap","FolderList","newFolderDialog","defaultFolder","ModelLayerCheckbox","ModelLayerColor","color_picker","addItem","footerDiv","footerCheckbox","getStoredState","BookmarkList","bookmarkDialog","BookmarkItem","getCameraPosition","updateDialog","assetDrawerWidth","inside","drawer","drawerPaper","tab","flexBasis","flexShrink","tabGrow","toggleDrawer","CompanyLogo","branding","AssetDrawer","assetDrawerState","projectActiveTab","setSelectedTab","labels","addSceneLabel","updateSceneLabels","removeSceneLabel","Drawer","anchor","transitionDuration","paper","menuButton","projectionText","slimButton","matrixValuesParent","matrixValues","matrixButtons","ProjectDetails","projectDialog","warnDialog","setHeight","setChanged","projectionID","setProjectionID","matchedProjection","setMatchedProjection","imported","setImported","setProjections","cameraTransform","setCameraTransform","projectHeight","basicAdjustments","unknownTextMeters","unknownTextFeet","onCorrectionRemove","onMatrixChange","localizedProjectName","importedProjection","userProjection","handleImported","sortedProjections","name1","name2","selectedProjection","toMeters","hasBasicAlignment","localizedProjectionName","getLocalizedProjectionName","roundedHeight","getTransformValues","hasUserProjections","emptyName","emptyHeight","emptyProjection","hasErrors","noWrap","newProjectionID","oldProjection","toMetersOld","toMetersNew","ListSubheader","disableSticky","conflict","resetBasicAlignerCamera","trimmedName","heightInMeters","projectionName","MainAppHeader","settingsDrawerState","setSettingsDrawerState","customURLDialogOpen","setCustomURLDialogOpen","measurementsDialogOpen","setMeasurementsDialogOpen","appBar","Toolbar","MainAppFooter","mouseCoords","setMouseCoords","setCoordinate","setCoordinates","coords","textShadow","listItem","inputPropParent","inputPropTitle","InputSlider","labelFunction","magnitude","isRangeType","labelFormat","openState","sliderValue","setSliderValue","roundToStep","changeCallback","throttle","finishCallback","scaledValue","out","toInput","saveValue","fromInput","Slider","valueLabelDisplay","valueLabelFormat","KeyboardArrowUp","KeyboardArrowDown","RangeInputProp","setValues","SingleInputProp","inputValue","setInputValue","inputError","setInputError","InputField","minValue","setMinValue","maxValue","setMaxValue","minError","setMinError","maxError","setMaxError","SingleSlider","RangeSlider","SectionTitle","ViewerBackground","AerialBackground","MouseControlType","Reverse","Autocad","QuickNavigationToggle","AerialTypeDropdown","VolumeCalculation","LowestPlane","VolumeSampling","High","Low","EngineCloudURL","OrthomosaicOpacity","OrthomosaicQuality","GlobalSettings","settingsDialog","globalSettings","setOpenQuickNav","setOrthoQuality","setOrthoOpacity","setControlType","setAerialMeasureType","setVolumeType","setVolumeSampleRate","setViewerBackground","setAerialBackground","globalEngineCloudURL","setGlobalEngineCloudURL","ColorMap","colorMaps","heatMap","awesomeGreen","pastelShades","blueOrange","blackOrange","blueHue","blueRed","jet","grayScale","getColorMap","emptyBasemapID","aerialBasemaps","colorPreview","colorMapImage","objectFit","SectionDescription","GPUPickerDebug","pickerDebug","setPickerDebug","togglePickerDebug","PointsRenderDebug","renderPaused","setRenderPaused","setPointsRenderPaused","BoudingBoxDebug","boundsVisible","setBoundsVisible","setPointBoundsVisible","ClassificationList","classificationColors","setClassificationColors","savedAvailableClassifications","savedClassificationVisibilities","updateColorsList","setVisibleClassifications","newClasses","oldClasses","hasClassifications","every","borderColor","borderStyle","borderWidth","ModelDistance","savedModelDistance","setModelDistance","TagDrawDistance","savedTagDistance","setTagDistance","PointCloudDistance","savedCloudDistance","setPointCloudDistance","PointCloudScale","savedCloudScale","setPointCloudScale","PointCloudSize","savedCloudMinimum","setPointCloudMinimum","AdaptivePointSize","savedDynamicSize","setPointCloudDynamicSize","PointCloudShape","savedCircularPoints","setPointCloudCircularPoints","IntensityRange","savedIntensityClip","savedColorType","setPointCloudIntensityClip","HeightRange","savedHeightClip","setPointCloudHeightClip","ColorMapPicker","savedColorMap","onRender","setPointCloudColorMap","img","PointCloudOpacity","savedOpacity","setPointCloudOpacity","PointCloudCount","savedMaxPoints","setPointCloudMaxPoints","PointCloudColor","setPointCloudColorType","NavigationType","savedArrowMarkers","setNavigationType","Markers","None","AerialBasemapPicker","savedBaseMap","setAerialBasemap","isEmpty","list","boldTitleTypography","SettingsDrawer","isOrbitMode","classificationTexture","TextureLoader","minFilter","NearestFilter","magFilter","shaders","ifc","vert","frag","pointcloud","panoramic","planar","linework_basic","linework_sprite","render_edl","commonRenderVertexShader","render_basic","render_transition","markers","utilities","basic_picker","gpu_picker","texture_packer","packedTextureScale","assignPackedData","valueInt","generateDataTexture","channels","Color","Uint8Array","r","g","RGBFormat","RGBAFormat","DataTexture","needsUpdate","BaseMaterial","ShaderMaterial","updateValues","initProperties","uniforms","defineProperty","PointCloudMaterial","gpuPicker","minSize","adaptiveSize","isOctreeCloud","drawDistance","screenwidth","octreeSpacing","octreeSize","octreeCorner","intensityRange","rgbMax","heightRange","classificationVisible","visibleClassTexture","crossSectionWidth","crossSectionStart","crossSectionEnd","clipBoxTexture","areaTriangleTexture","visibleNodesTexture","numClippingBoxes","numAreaTriangles","loader","colorMapTexture","updateVisibleClassifications","Uniform","depth","maxSize","heightClamp","intensityClamp","classificationData","visibleNodes","areaTriangleData","clipPolygonData","defines","NUMBER_OF_CLASSIFICATIONS","CLIP_TEXTURE_WIDTH","CLIP_TEXTURE_HEIGHT","AREA_TEXTURE_WIDTH","AREA_TEXTURE_HEIGHT","VISIBLE_NODES_WIDTH","PACKED_TEXTURE_SCALE","fragmentShader","vertexShader","vertexColors","transparent","depthWrite","updateNumClippingBoxes","NUM_CLIP_BOXES","updateNumAreaTriangles","NUM_AREA_TRIANGLES","OutputRenderMaterial","tCurrent","tPrevious","progress","screenWidth","zooming","zoomRadius","mousePosition","BasicRenderMaterial","tImage","tDepth","EDLRenderMaterial","near","far","pixelRatio","edlStrength","neighbours","Float32Array","neighbourCount","NEIGHBOUR_COUNT","TagMaterial","cameraRotation","timeStamp","windowHeight","texturePath","textureData","uniform","imageTexture","side","DoubleSide","PanoramicImageMaterial","PlanarImageMaterial","imageWidth","imageHeight","fx","fy","cx","cy","MarkerMaterial","cameraHeight","currentIndex","orbitMode","LineworkSpriteMaterial","LineworkBasicMaterial","IFCMaterial","MeshLambertMaterial","isShaderMaterial","onBeforeCompile","shader","userData","BasicRenderTarget","WebGLRenderTarget","LinearFilter","stencilBuffer","EDLRenderTarget","isWebGL2","generateMipmaps","depthBuffer","depthTexture","DepthTexture","FloatType","UnsignedIntType","RenderPass","screenScene","screenQuad","PlaneBufferGeometry","material","MeshBasicMaterial","depthTest","Scene","Mesh","Camera","renderer","setRenderTarget","RenderUtils","screenPass","targets","EDLEnabled","animationFrames","_zooming","mouseEvent","basicMaterial","basicRenderTarget","EDLMaterial","outputMaterial","outputRenderTarget","previousRenderTarget","previousNeedsUpdate","initTargets","capabilities","maxVaryings","floatFragmentTextures","EDLSupport","renderSize","getSize","pixels","insideRadius","addTarget","updateEDLValues","updateZoomValues","updateProgress","resizeTextures","renderTarget","setCamera","increment","updateTexture","w","h","dispose","updateMaterial","textureFromImage","Texture","setEDLState","onMouseMove","renderScene","scene","renderToTarget","renderMaterial","renderToPrevious","renderToScreen","PointCloudNode","parent","pointsScene","pointsPicker","boundingBoxMesh","_boundingBox","nodeSize","edgeSize","nodeCenter","density","loaded","loading","picker","addChildNode","node","clearChildNodes","removeChildNode","removeFromScene","disposeGeometry","setVisibility","setGeometry","BufferGeometry","BufferAttribute","intensity","gpu_index","addToScene","Points","materialScene","materialPicker","generateEdgeMesh","addCloudData","isVisible","frustum","intersectsBox","controls","cameraPosition","getCameraTarget","bounds2D","camera2D","PointCloud","rgbArray","maxColor","materials","_tightBoundingBox","materialDefaults","gpuPickers","updateMinimapExtent","setIdentifier","disposeNodes","getVisibleNodes","updateBoundingBox","updateIntensityRange","intensityMin","intensityMax","updateColorLimits","closestValue","arrMax","midpoint","updateClassificationFromHistogram","histogram","updateClassifications","boxGeometry","BoxGeometry","edgeGeometry","EdgesGeometry","boxMaterial","LineBasicMaterial","LineSegments","getClassificationHistogram","BinaryHeap","scoreFunction","bubbleUp","sinkDown","peek","n","score","parentN","elemScore","child2N","child1N","swap","child1","child1Score","child2","PointCloudManager","mapLayer","clouds","visiblePointsTarget","visiblePointsPerCloud","maxUnloadedNodes","numNodesLoading","unloadedNodes","maxUnloadedClouds","loadedToGPUThisFrame","streamableCacheSize","genericCacheSize","maxGenericFilesVisible","exeLaunchTimeout","lastExeLaunched","performance","numLoadedPoints","numVisiblePoints","numSceneNodesVisible","minStreamableNodeSize","transparency","rawJsonResponse","shouldUpdate","_drawDistance","initScene","cameraHandler","renderUtils","minimap","tightBoundingBox","GenericPointCloud","StreamablePointCloud","reconcile","pointCloudFiles","currentFiles","newFiles","assetsToLoad","filesToDelete","pointCloudsAdded","pointCloudsRemoved","deleteFile","addNewFile","pointCloud","toggleVisibility","AmbientLight","doesCloudExist","addPointCloud","updateMeasureList","cloudDetails","newPointCloud","EncompassPointCloud","PotreePointCloud","removeTempFiles","measurements","refreshMeasurementList","updateClamping","removeLayer","combinedBoundingBox","addLayer","updateUniforms","subScalar","updateCloudSampling","numToDraw","drawRange","setDrawRange","updateCrossSection","calculatePointsVisible","updateVisibilityTexture","nodes","nodeMap","Map","visibleNodeTextureOffsets","offsetsToChild","nodeIndex","parentName","parentOffset","parentOffsetToChild","lodOffset","offsetUint8","updateClipBoxTexture","pointMarkup","clippingBoxes","numClipBoxes","clippingBox","hidePoints","updateClassification","newClassification","ignoredClassification","inverse","updateAreaTriangleTexture","areaGeometry","getAreaGeometry","triangleIndex","volumeStatus","vertex1","vertex2","vertex3","pointsInRadius","getX","getY","getZ","pointsInPolygon","getSampledPoints","highest","keyfunc","samples","dtmPoints","sampled","manageStreamableCache","stack","unusedNodes","streamablePointClouds","numberOfNodes","numberToDelete","reverse","manageGenericCache","genericPointClouds","insideSphere","nodeScreenSize","weight","MAX_VALUE","loadGenericPointClouds","loadingClouds","unloadedClouds","loadFromExe","loadStreamablePointClouds","numLoading","loadMetadata","loadUnloadedGeometry","maxUnloaded","GenericPointCloudNode","updateGenericPointClouds","hideDescendants","calculateGenericVisibility","updateStreamablePointClouds","calculateStreamableVisibility","waitForCameras","priorityQueue","loadedPointClouds","isGeometryNode","isTreeNode","minNodeSize","totalPointsTarget","singleCloudLimit","totalPointsLoaded","cloudPointsLoaded","cloudID","childDistance","updateMaterials","getCameraFrustum","_shift","decodeMetadata","num_points","bytes_path","xyzMin","xyz_min","xyzMax","xyz_max","unique_classes","rgb_max","intensity_min","intensity_max","updateRootNode","getGeometry","getBinaryData","GenericPointCloudRootNode","updateSizeInfo","workerExe","cancelled","byteCutoffSize","pointsDataParsed","numSampledPoints","numSampledChunks","isLargeFile","dataPaths","sceneOffset","apply","mins","maxs","file_info","removeSync","updatePercent","onProgress","points_to_process","lasFilePath","minChunkSize","parseHeaderResponse","parsePointsResponse","checkForLargeFile","number_of_bytes","point_count","zoomToSceneExtent","estimatedBoundingBox","StreamablePointCloudNode","level","addScalar","getChildOffset","getChildNode","childName","childSize","childLevel","childCenter","NodeConstructor","structure","metadata","metadataPath","EncompassPointCloudNode","hierarchy","nodePath","getDataPath","minCorner","corner","readNodeHierarchy","EncompassPointCloudNodeV0","args","childIndex","EncompassPointCloudNodeV1","EncompassPointCloudNodeV2","folderDepth","hrcPath","updateHierarchy","isFolderRoot","loadHierarchy","dataDir","match","RegExp","hierarchy_step_size","point_offset","box","tight_bounding_box","hasHierarchyV1","checkLegacyHierarchy","hasHierarchyV2","contains_hierarchy","RootNodeConstructor","rootNode","availableNodes","node_structure","PointAttributeTypes","DATA_TYPE_DOUBLE","ordinal","DATA_TYPE_FLOAT","DATA_TYPE_INT8","DATA_TYPE_UINT8","DATA_TYPE_INT16","DATA_TYPE_UINT16","DATA_TYPE_INT32","DATA_TYPE_UINT32","DATA_TYPE_INT64","DATA_TYPE_UINT64","typenameTypeattributeMap","obj","PointAttribute","numElements","byteSize","description","initialRange","POSITION_CARTESIAN","RGBA_PACKED","COLOR_PACKED","RGB_PACKED","NORMAL_FLOATS","INTENSITY","CLASSIFICATION","NORMAL_SPHEREMAPPED","NORMAL_OCT16","NORMAL","RETURN_NUMBER","NUMBER_OF_RETURNS","SOURCE_ID","INDICES","SPACING","GPS_TIME","PointAttributes","pointAttributes","vectors","pointAttributeName","pointAttribute","addVector","hasNormals","DataView64","DataView","getUint64","littleEndian","getBigUint64","getInt64","getBigInt64","PotreePointCloudNode","nodeType","hierarchyByteOffset","hierarchyByteSize","byteOffset","attemptNumber","maxAttempts","hierarchyPath","parseHierarchy","bytesPerNode","numNodes","nodePos","getUint8","childMask","getUint32","ArrayBuffer","octreePath","xyzScale","xyzCenter","xyzOffset","attributeBuffers","hasClassHistogram","jsonAttributes","replacements","jsonAttribute","attribute","parseAttributes","bboxMin","bboxMax","firstChunkSize","CustomOrbitControls","domElement","clampDistance","scope","minDistance","maxDistance","keyPressed","walkMode","walkVelocity","walkRotation","maxWalkSpeed","walkIncrement","walkPercent","walkPercentMin","walkPercentMax","oldRadiusState","zoomToCursor","focused","minZoom","maxZoom","minPolarAngle","maxPolarAngle","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","enablePan","panSpeed","panningMode","keyPanSpeed","autoRotate","autoRotateSpeed","enableKeys","UP","BOTTOM","SPACE","PLUS","MINUS","NUMPAD_PLUS","NUMPAD_MINUS","WALK_FORWARD","WALK_BACK","WALK_RIGHT","WALK_LEFT","WALK_UP","WALK_DOWN","mouseButtons","target0","position0","zoom0","setControls","getPolarAngle","spherical","getAzimuthalAngle","clearSphericalDelta","sphericalDelta","clearPanOffset","panOffset","saveState","resetWalkValues","incrementWalkSpeed","static","decreaseWalkSpeed","setWalkMode","quat","setFromUnitVectors","up","applyQuaternion","setFromVector3","activePosition","activeTarget","applyWalkOffset","scaleFactor","updateProjectionMatrix","changeEvent","STATE","NONE","quatInverse","lastPosition","lastQuaternion","lastUpdated","changeDetected","rotateLeft","makeSafe","lookAt","setFromSpherical","prevRadius","newRadius","radiusDelta","addScaledVector","dollyDirection","updateMatrixWorld","transformDirection","distanceToSquared","EPS","dot","moveStopEvent","onMouseWheel","onTouchStart","onTouchEnd","onTouchMove","onMouseFocus","onKeyUp","startEvent","endEvent","ROTATE","DOLLY","TOUCH_ROTATE","TOUCH_DOLLY","TOUCH_PAN","rotateStart","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","mouse","getZoomScale","rotateUp","updateZoomParameters","rect","getBoundingClientRect","unproject","normalize","panLeft","v","objectMatrix","setFromMatrixColumn","panUp","crossVectors","pan","deltaX","deltaY","targetDistance","dollyIn","dollyScale","dollyOut","handleMouseWheel","switchTo","shiftKey","handleMouseDownRotate","handleMouseDownDolly","handleMouseDownPan","subVectors","handleMouseMoveRotate","handleMouseMoveDolly","handleMouseMovePan","keyCode","handleKeyDown","handleKeyUp","touches","pageX","pageY","handleTouchStartRotate","handleTouchStartDolly","handleTouchStartPan","handleTouchMoveRotate","handleTouchMoveDolly","handleTouchMovePan","setRotateRadius","dollyInZoom","zoomPercent","numIterations","ln","prototype","EventDispatcher","parseHex","getClassFromAlias","classNum","getNameFromClass","classicationCheck","getColorFromClassNum","hex","textToColor","rgbColor","textToColorArray","createHash","digest","s","TextureCache","maxCacheSize","isThumbnailCache","maxTextureSize","maxDeviceSize","setMaxTextureSize","textureSize","controller","manage","lastAccess","closeImages","images","ImageBitmap","HTMLCanvasElement","missing","imageInfo","getImageInfo","CanvasTexture","DOMException","ABORT_ERR","toKeep","originalWidth","originalHeight","maxEdgeLength","thumbnailCache","standardCache","ImagePosition","_scene","_aerial","_value","applyEuler","ImageRotation","_euler","setRotation","adjustment","rotationWithTransform","multiplyRotations","rotationWithAdjustment","CameraFeature","opts","CameraImage","cameraFile","missingTexture","setMatrix","setAdjustment","updateFeature","aerial","Point","pixelToDirection","pixel","directionToPixel","setCameraPosition","setCameraParameters","positionToCameraAngle","thumbnail","AbortController","textureCache","setObjectVisible","generateObject","loadThumbnail","loadFullImage","grabImageFromPath","applyTempRotation","angleEuler","tempRotation","abort","CameraFile","standardMaterial","standardMesh","pickingMaterial","pickingMesh","numVertices","uvs","getNewCamera","initSceneView","markerScene","aerialController","mapSource","cameraID","getByPickerID","pickerID","arrIndex","cameraIndex","camera_index","arrayLength","markerShape","Int32Array","cameraIndices","cameraShape","PlanarImage","numUvs","uvIndex","updateMatrix","updateCameras","updateAdjustments","updateAerialView","addFeatures","updateSceneView","numCorners","cornerIndex","setXYZ","updatePicker","setSelected","meshes","baseIndex","setVisible","cameraLoading","initialCameraLoading","markersVisible","removeFeatures","removedFeatures","removedFeature","removeFeatureInternal","CameraHandler","cameraScene","sceneViewController","aligned","newCameraLoading","cameraLoadedOnce","initScenes","SceneViewCameras","AerialCameras","renderInFront","PanoramicCameraFile","PlanarCameraFile","updateVisibility","camerasFiles","currentIDs","newAssetIDs","cameraFilesAdded","cameraFilesRemoved","flat","clearCurrentCamera","getFeatureForEvent","getNextIndex","loadImage","getPreviousIndex","setWaitForCameras","setNormalCamera","setOrbitValues","setOrbitCamera","setCameraHeight","setCurrentImage","cameraImage","getCameraByName","cameraName","getCameraByID","getCamerasByFolder","getRowsCSV","csvEncompassOut","degrees","centerOnImage","setCurrentCamera","cameraLoaded","updatePreviousTexture","clearImages","updateArrowNavigation","clearArrowNavigation","currentCamera","setMeshVisible","setCameraAdjustments","newAdjustments","setCameraMatrix","elements","newMatrix","equals","resetCameraMatrix","resetTextureCache","loadSavedCameraState","savedCameraState","savedcameraID","activeCamera","savedLookat","closestCameraID","closestCameraToPosition","cameraLoadOptions","maxViewAngle","bestCameraID","bestDistance","cameraPos","rotationA","rotationB","matrixA","makeRotationFromEuler","matrixB","multiplyMatrices","directionToCameraAngle","sphere","missingImagePath","PanoramicImage","u","imageDirection","directionsToPlanar","planarSize","plane","projectPoint","allX","allY","xMin","xMax","yMin","yMax","interpolatePixels","interpolated","xyz","xyzTemp","xyz1","nextIndex","xyz2","_x","_y","_z","interpTemp","xyzNoDups","previous","mouseControls","backgroundLayer","WebGLPointsLayer","foregroundLayer","minCameraRadius","maxCameraRadius","getFeaturesAtPixel","layerFilter","RayCaster","raycaster","ray","vectorFromEvent","defaultRaycaster","setPrecision","threshold","intersectPlane","intersectObject","intersectTriangle","triangle","intersectObjects","sortByRay","objects","distanceToRay","raycastDirection","Raycaster","arrowNavigation","markerNavigation","modifier","navigationType","MarkerNavigation","ArrowNavigation","initEvents","bind","removeEvents","mouseMoved","isLeftClick","updateNavigation","clearNavigation","isHidden","isArrowMode","isMarkerMode","setEnabled","sceneViewCameras","getPickerResults","markCameraSelected","nearbyCameras","cameraPlane","cameraObject","cursorObject","calculating","minCameraDistance","maxCameraDistance","createCameraObject","createCursorObject","setObjectsVisible","shape","Shape","moveTo","lineTo","ShapeGeometry","absarc","hole","Path","holes","intersect","getBestCamera","getCameraFromPlane","getCameraFromDirection","closestCamera","Line3","nextCamera","getNextCamera","previousCamera","getPreviousCamera","P0","closestPointToPointParameter","intersection","intersect2D","closestDistance","visibleCameras","spherePosition","Sphere","intersectsSphere","calculateClosestCameras","calculateNearbyCameras","calculateCameraPlane","tooClose","tooFar","minAngle","setFromNormalAndCoplanarPoint","ContextMenu","newTagDialog","changeCategoryDialog","customLinks","modelProperties","setModelProperties","tagCoordinate","setTagCoordinate","contextData","isAerial","labelData","selectedTags","modelData","sceneCoord","aerialCoord","multipleCategories","clearHighlightedLinework","listItemSeperator","menuEvent","numLabelsSelected","numLabelsHighlighted","profileActive","pointProfileActive","getCurrentCamera","labelSelected","labelPointSelected","pointID","hasLabelCoord","numTagsSelected","hasModelData","enableChangeCategory","hasSceneCoord","hasAerialCoord","noTagSelected","oneTagSelected","pointProfileActions","pointProfileStart","pointProfileEnd","pointProfileCancel","tagActions","isImageOnly","getMultiImageCoordinate","orbitModeActions","resetCamera","modelActions","labelActions","anyLabelSelected","deleteHighlighted","deleteLabelPoint","unHighlightAll","insertLabelPoint","editLabel","moveToLabel","customUserActions","showInAerial","showInScene","urlString","constructCustomURL","hasCustom","clearTooltipText","ModelProperties","showContextMenu","card","cardHeader","cardButtons","alignSelf","headerTitle","cardContent","EditLinkDialog","setUrl","setTarget","setShowInScene","setShowInAerial","addNewLink","CustomLink","Card","CardHeader","titleTypographyProps","subheader","subheaderTypographyProps","CardContent","CustomContextURL","newURLDialog","importURLData","CreateBasemapLayer","Tile","TagFeature","ViewTriangle","aerialMap","generateSource","Fill","rotateViewMarker","ring","generateMarkerCoordinates","getTargetElement","coneAngle","axis","coneLength","getView","getResolution","v0","v1","v2","changeDetector","AerialMap","containerElement","orthoList","viewTriangle","maxLayerZoom","maxMapZoomLevel","maxCameraZoomLevel","markerRadius","observer","currentCameraFeature","currentCameraLayer","selectedCameraFeature","selectedCameraLayer","mapSystem","initMap","initResize","addCurrentLayer","addSelectedLayer","OrthoMosaicList","arcGISBase","OSM","XYZ","attributions","scrollWidth","getLayers","getArray","basemapID","basemapLayers","getVisible","activeBasemap","getCenter","getZoom","orthoLabels","imageLabels","localAligner","tagsHandler","resetView","setCenter","setZoom","setVisibleBasemap","attribution","Attribution","collapsible","defaultLayers","defaultControls","extend","View","onresize","handleWindowResize","onMapClick","onDoubleClick","updateSavedState","un","CircleStyle","hovering","currentView","maxZoomReached","selectedTagID","showTagDetails","selectedCameraID","getCoordinates","boundingExtent","mapSize","fit","nearest","clearAerialTooltip","initialEvent","getCustomEvent","onMouseUpAerial","isRightClick","openContextMenu","onMouseMoveAerial","dragging","onFeatureHover","selectedCamera","setAerialState","anyToolEnabled","getEventPixel","tagIDs","mapCoordinate","getCoordinateFromPixel","updateSize","setDragState","getInteractions","interaction","DragPan","setActive","jumpToPosition","mapPosition","setMapExtent","hasPoints","cameraSelected","extentFromPoints","reproject","xPositions","yPositions","OrthoImageLayer","ImageLayer","orthosList","aerialBounds","splitData","cropBase64","cropCorners","calculateCroppedData","calculateExtent","calculateAerialPolygon","addMapLayer","dataProjectionName","x_scale","y_scale","x_offset","y_offset","x_skew","y_skew","originalSize","zoomToExtent","transformExtent","imagePixelsToAerial","cornerPixels","proj4Projection","index_start","index_end","width_start","width_end","height_start","height_end","extentWidth","extentHeight","subtileCorners","intersectAerialPoints","aerialPoints","turfIntersect","turfPolygon","aerialToPixels","aerialToImagePixels","coordinatesTransformed","coordTransformed","reverseTransform","allLayers","numSubtiles","imageURL","Static","imageExtent","interpolate","imageLoadFunction","imageChunk","orthomosaic","getImage","addImageChunk","LayerGroup","setOpacity","orthos","chunksLoading","chunksToLoad","orthoID","ortho","orthoFiles","loadable","toLoad","projected","ImageLabel","completed","drawable","highlighted","textScore","isThing","findText","duplicatePixelDistance","stateChanged","draw","unSelect","complete","setDrawable","setScore","setIsThing","setFindText","setHighlighted","highlight","insertPoint","createCoordData","coordArray","duplicatePoint","oldPoint","newPoint","screenPosNew","screenPosOld","dU","dV","LabelCategory","listIdx","invalidLabels","sorted","originalOrder","getLabelByID","visibility","addNewLabel","drawLabel","updateColor","idxCoord","minDistanceIdx","endIdx","createSegment","deleteLabel","deleteLabels","unHighlight","updateName","completeLabel","hasEnoughPoints","unSelectAll","selectLabel","sortLabels","scoreThreshold","allLabels","order","undoSort","unsortedLabels","moveToLabelInList","ImageLabelTools","sceneLabels","activeLabeler","categories","currentCategory","allowUpdate","setCategoryList","setTrainingArea","AerialLabelTools","SceneLabelTools","setCategories","trainingArea","polygonScene","standardScene","numHighlighted","numLabelsAll","getIdxInList","validCategory","setUpdateState","categoryID","getCategoryByID","activeLabel","deletePoint","addLabel","setActiveLabelType","deleteAllCategories","activeImagePaths","activeImages","loadedImagePaths","checkIfSelected","checkUniqueName","chosenCategory","getCategoryByName","sortCategory","sortType","categoryToSort","drawAll","addCategory","getNewCategory","addTrainingArea","getNewTrainingArea","deleteCategory","editCategoryName","toggleCategoryVisibility","deleteTrainingArea","addTrainingAreaLabel","unSelectLabels","coord","clearTooltips","newCategoryID","newCategory","oldCategory","newLabel","addPoint","deleteSpecificPoint","zoomToLabel","isTrainingArea","resetTemporaryPoint","simplifyPolygon","tolerance","highQuality","simplePolygon","turfSimplify","mergeTrainingLabels","labelsToMerge","mergedLabels","firstLabel","isPlanarImage","isPanoramicImage","mergeLabel","points1","points2","point1","index1","matchFound","point2","index2","union","polygonPoints1","polygonPoints2","turfUnion","duplicate","remainingLabels","simplifyPanoramicLabels","geometryWithBuffer","bufferSize","geomJSTS","GeoJSONReader","BufferOp","bufferOp","checkForImageOverlap","hasOverlap","visibleOrthos","polygonPointsOnly","importLabel","progressData","addedLabel","image_id","segmentation","minPoints","is_linestring","is_point","skippedLabels","lineGeom","turfLineString","buffer_size","pointGeom","turfPoint","linework_data","file_name","pointsToPixels","setKnownImageSize","labelTotal","labelIndex","mergeID","merge_id","checkLabelOverlap","checkOverlap","checkLabelInvalid","clearViewerTooltip","progressCallback","overwrite","hasTrainingArea","numLabelsTotal","trainingAreaCategory","addCategoryLabels","trainingAreas","mergeList","newLabels","category_id","categoryVisible","labelObject","supercategory","getLabelAnnotations","getTrainingAnnotations","jsonImageObj","sectionsFromIntersection","removeDuplicate","sections","intersectPoints","annotationFromPolygon","imageID","segment","iscrowd","area","areaFromPolygon","contour","ShapeUtils","shortestDistance","closestPoint","idx","closestPointToPoint","startPoint","endPoint","LabelPoint","LabelPolygon","OrthoLabel","minCoordinates","styleCache","featuresLayer","getSource","editingLayer","getLayerFromCache","clearStyleCache","setFeatureStyle","setStyle","featureStyle","editingStyle","checkDefaultStyle","defaultStyleParams","styleKey","getLayerStyle","updatePoint","removePoint","removeSpecificPoint","getPixelFromCoordinate","checkDuplicate","newCoord","drawPoints","temporaryPoint","completedSource","editingSource","drawPolygon","validPolygon","sources","hasFeature","removeFeature","OrthoCategory","aerialTools","addMapLayers","darkenedColor","pointColor","categoryColor","TrainingAreaCategory","lineDash","VectorImageLayer","updateWhileInteracting","updateWhileAnimating","imageLabelTools","TrainingAreaLabel","polygonsInsideImage","polygonHover","pointHover","calculatePolygonPixels","pixelPolygon","pixelPoint","trainingLabels","trainingLabel","trainingLabelIndex","moreTooltip","pointCount","getFeaturesInExtent","isValid","markLastPointDraggable","updateDraggablePoint","pointFeatures","lastPoint","setPointHover","cancelLabel","setToolTipText","setPointGrabTooltip","canDrag","setPolygonHover","drawActiveLabel","checkFeatureHover","setPolygonHoverTooltip","drawing","onRightClick","oneHighlighted","noneHighlighted","ctrlKey","highlightLabel","selectedPoint","getFeatureAtPixel","pointFeaturesForExtent","selectedPolygon","polygonFeaturesForExtent","mousePixel","mouseCoord","mouseBuffer","values_","pointExtent","getExtent","intersectsCoordinate","pointRadius","helpMsg","startTooltip","invalidTooltip","setAerialTooltip","dragTooltip","highlightTooltip","imageIndex","orthoName","boundsToCheck","boundsPolygon","labelPolygon","_direction","_position","SceneLabel","_imageWidth","_imageHeight","standardMeshes","polygonMeshes","sphereGeometry","SphereGeometry","sphereMaterial","lineGeometry","lineMaterial","lineDashedMaterial","polygonMaterial","polygonOpacity","minPoleAngle","standardColor","LineDashedMaterial","dashSize","gapSize","setPointScale","computeBoundingSphere","drawLines","setFromPoints","Line","computeLineDistances","drawPolygons","coordinates3d","oldState","coordinates2d","pixels2d","polygonAtPoles","coordinatesFlat","earcut","deviation","numTriangles","Triangle","getMidpoint","setIndex","pointsAtPole","maxAngle","polyPointRing","booleanContains","getCameraBestFit","averageDirection","fovRequired","SceneCategory","deleteUnfinishedLabel","numberOfLabels","visited","getClickedDirection","getImagePixel","mouseClick","labelPoints","targetPoly","polygons","setViewerTooltip","onMouseDrag","calculatePlanarSections","imageBorders","calculatePanoramicSections","horizontalShift","getHorizontalShift","imageBordersLeft","imageBordersRight","polygonLeft","polygonRight","intersectionLeft","intersectionRight","minSpread","widthCutoff","xValues","minX","maxX","shiftedMin","shiftedMax","spread","polygonInImage","getCameraSize","mergeIndex","polygonsInside","mergeable","ScaleHandle","PlaneGeometry","drag","minusPoint","lineStart","lineEnd","camOnLine","intersectOnLine","setScale","newScale","RotateHandle","ordering","zAxis","xAxis","newAxis","cross","PositionHandle","ClippingBox","Group","operationID","wireframe","positionHandle","scaleHandles","rotateHandles","wireframeMaterialStandard","wireframeMaterialHover","addWireframe","addScaleHandles","addRotateHandles","addPositionHandle","setFromObject","setHover","wireframeMaterial","edgeMesh","xAxisMaterial","xAxisGeometry","yAxisMaterial","yAxisGeometry","yAxis","zAxisMaterial","zAxisGeometry","raycast","intersects","parentScale","objectScale","highlightScale","OperationType","ClippingGroup","markupList","Classify","Split","isDelete","isClassify","setNewClassification","setIgnoredClassification","axisOffset","smooth","resetRotation","dz","removeByID","PointMarkupList","dragObject","clippingGroups","setMarkupGroups","activeGroup","clippingGroup","refreshMarkupList","group","addNewGroup","newGroup","enable","disable","removeClippingGroup","removeClippingBox","addNewBlock","cameraAngle","newBoxScale","setScalar","clearNewBlock","setDragObject","setMovementState","getDragObject","containsPoint","handleOverride","isPosition","isRotation","standardTooltip","isFirstTouch","numTouching","pinchStart","pinchEnd","Chart","zoomPlugin","line2D","line3D","lineWidth","hoverColor","markerSize","ProfileChart","initSphere","clearScene","hideSphere","selectStart","localPosition","selectEnd","setZ","updatePoints","resetZoom","selectCancel","linePoint","validWidth","distanceAlongLine","validDistance","show","drawSphere","distanceClamped","at","showSphere","updateUnits","updateSampling","getProfileImage","chartImageBase64","toBase64Image","pointProfile","sampleMinimum","sampleMaximum","chart","setPointProfileOpen","scales","ticks","plugins","caretPadding","displayColors","callbacks","dataIndex","raw","legend","wheel","pinch","datasets","pointHoverBackgroundColor","pointHoverBorderColor","onHover","maintainAspectRatio","animation","animationDuration","responsive","responsiveAnimationDuration","updateChart","hide","getSampledData","needsSampling","chartTitle","PanoControls","cameraAlignerAdv","cameraAlignerBasic","hammer","orbitControls","flyControls","oldCameraState","Hammer","OrbitController","FlyMoveControls","MouseControls","CameraAlignerAdv","CameraAlignerBasic","LocalAligner","cadHandler","compass","onMouseDoubleClick","touchHandler","touchEvent","changedPointers","MouseEvent","bubbles","cancelable","screenX","screenY","altKey","metaKey","onDoubleTap","down","resetSceneView","updateFarPlane","updatePickers","newOrbit","newPivot","smoothTransition","rotateLength","setPositionValues","updateCamera","getClosestCoordinate","combinedBounds","orbitFromBounds","boxSize","boxMean","boundSize","orbitWithAngle","onMouseMoveScene","movement","updateRotation","onZoomStart","onZoomFinish","measureGrabFinished","toggle","mouseClicked","onMouseUpScene","onMouseScroll","currentOrbit","saveLastPosition","loadLastPosition","orbitPosition","orbitTarget","getProperties","getCameraDistance","pivotLength","getPrecision","approxDistance","defaultFarPlane","changedTouches","eventType","pinchMove","sign","touchToMouse","move","panoControls","numberOfSteps","getAngleDiff","sphereStart","sphereFinish","dRadius","dPhi","dTheta","currentPivot","dPivot","pivotOffset","isPerspectiveCamera","getPositionValues","TextMaterial","MeshPhongMaterial","CompassControls","composer","antialias","sizeRatioLarge","sizeRatioSmall","alphaTest","lightPosition","cube","cubeSize","cubeColorStandard","cubeColorHover","cubeEdgeColor","cubeTextColor","cubeMaterials","donutSize","donutColor","donutTextColor","north","west","east","south","compassClassName","initAntiAliasing","addObjects","addLights","WebGLRenderer","setPixelRatio","PerspectiveCamera","cameraDistance","EffectComposer","ssaaRenderPass","SSAARenderPass","unbiased","sampleLevel","addPass","copyPass","ShaderPass","CopyShader","addRotationCube","addCompassRing","addCompassLetters","ambientLight","spotLight","SpotLight","castShadow","cubeGeometry","BoxBufferGeometry","getTextMaterial","donutGeometry","donutMaterial","getCircleMaterial","letters","letter","getDirectionMesh","canvasSize","maxLength","fontScale","cubeColor","fillStyle","fillRect","font","fillText","strokeStyle","strokeText","getLetterMaterial","beginPath","textHeight","geometryUpper","materialUpper","FrontSide","meshUpper","geometryLower","materialLower","BackSide","meshLower","getSelectedSide","togglePointer","offsetLeft","offsetTop","setFromCamera","setCubeMaterials","materialIndex","faceIndex","hoverIndex","rotateLetters","zenith","pointA","pointB","bearing","startLat","destLat","startLng","destLng","brng","updateOffset","setContainerCursor","calculateRotations","lookatLocal","lookatLonLat","yPosLocal","yPosLonLat","cameraLocal","cameraLatLon","groupYaw","groupPitch","cubeYaw","phiDelta","thetaDelta","wheelDelta","wheelTimeout","wheelDelay","endTimeout","endDelay","rotating","scrolling","moveInterval","_zoomEvent","moveStart","moveEnd","moveDelta","moveDistance","lastMovement","maxPixelDistance","updateCameraMatrix","vector0","angles0","vector1","angles1","newEvent","MultiImageWindow","objectScene","backgroundScene","tools","setMultiImageOpen","setMultiImageState","onComplete","onAddPoint","intersectResponse","canComplete","canAddMore","disablePreviousImage","disableNextImage","disableAddMore","disableComplete","initRenderer","MultipleCameraMeasurement","parentElement","offsetWidth","updateIntersect","calculate","updateBackground","loadNextImage","loadCamera","loadPreviousImage","resetSecondObservation","resetObservations","autoClear","addSecondObservation","getClickedPoint","resetFirstObservation","getCurrentCameraIndex","clickedPoint","nextPosition","addFirstObservation","aspect","renderSceneObjects","firstPoint","secondPoint","origin1","origin2","getEndpoint","getSphereMesh","rayA","rayB","sameCamera","getIntersection","setButtonDisabled","defaultResponse","distances","calculated","viewerScene","windowScene","updatePointScale","viewerCamera","windowCamera","Nv","Na","Nb","Da","Db","da","db","ptA","ptB","lineSegment","segmentLength","midPoint","d1n","d2n","a1","a2","Measurement","_header","_title","timeCreated","getTime","setController","setHeader","setTimestamp","isoTime","Measurement3D","maxVertexLength","minVertexRequired","Length","getLineDistance","lastIndex","NaN","atan","rise","distance2D","finished","addedPoint","added","getProjectedVertices","MeasurementArea","ignoreHeight","vertexA","vertexB","StationMeasurement","Station","stationStart","activeAlignment","getAlignmentByID","isBetween","curveIntersect","x1","x2","x3","y1","y2","y3","distEndsSquared","crossProduct","dotProduct","getClosestSegment","segments","minDist","chosenSegment","segmentTest","lineIntersect","checkOnly","intersectCoordinate","clickedCoordinate","startCoordinate","unshift","intersectCoordinate2D","clickedCoordinate2D","Center","pointVector","startVector","endVector","pointArc","distStartToArc","angleStart","angleEnd","angleLarge","angleSmall","angleSmallQuadrant","angleLargeQuadrant","angleQuadrant","angleReverse","spiralIntersection","getIntersect","clickPointInData","alignmentInfo","xmlAlignment","loadExistingStation","measurement","along","across","station","MeasurementLine","cancelMessage","MeasurementPoint","surfaceGenerator","Area","SurfaceGenerator","generateSurface","generate","MeasurementVolume","volumeHelper","Volume","calculatingVolume","sampleRate","setSampleRate","renderMeasurement","stopVolumeCalculation","stopCalculation","VolumeHelper","loadExistingVolume","setVolume","destroyWorker","HeightMeasurement","vertex0","SnapMeasurement","snapResult","snap","snapCoordinate","finalHeight","validHeights","pos","heights","SnapDownMeasurement","reduce","acc","curr","SnapUpMeasurement","AerialMeasurement","getAerialLength","loadFromCoordinates","AerialLengthMeasurement","AerialAreaMeasurement","getAerialArea","sigma","numNeighbours","initWebworker","rate","getCalculatedBounds","calculateVolume","zMin","zMax","terminate","drawMesh","triangles","getVolume","volume","tri","p1","p2","p3","signedTetrahedronVolume","generateTriangleArray","v3","final","removeInvalidTriangles","validTriangles","getDelaunayTriangles","reverseWinding","delaunay","Delaunator","denseBounds","getDensePolygon","removeOutliers","calculationFinished","webWorkerFinished","pointsArray","upperPoints","trianglesUpper","lowerPoints","trianglesCombined","changeRequired","renderInScene","removeMeshesFromScene","addMeshesToScene","generateMesh","calculateArea","getArea","optimize","triangleIndices","verticesModified","numIndices","triIndexA","triIndexB","triA","triB","vertSet","allVerts","sharedVerts","uniqueVerts","modTriA","modTriB","t1","t2","oldArea","t3","t4","newArea","triVertices","flatPoints","index0","getLength","densePolygonTemp","vectorLength","directionIncrement","densePolygon","old","MinimapMeasure","styleHover","styleDefault","drawStyle","measurementType","sketch","tempTooltips","addInteraction","mapElement","reloadInteraction","removeInteraction","tooltips","getTooltipsForGeometry","removeOverlay","removeAll","setMeasurementType","validMeasureType","getDistance","getAerialSegments","objectMessage","objectPosition","formatLength","addNewTooltip","innerHTML","getLastCoordinate","hasEnoughSegments","formatArea","getInteriorPoint","clearTempTooltips","cancelMeasurement","editable","listener","Draw","drawingType","originalEvent","unByKey","addAerialMeasurement","alternateColor","Overlay","positioning","addOverlay","MeasurementConstructor","measureType","isFinished","measureAssets","setBuilder","getEmptyMeasurement","SnapUp","SnapDown","getMeasurement","MeasurementController","measurementSceneView","measurementAerialView","measurementBuilder","measurementGroupExporter","measurementGroup","setMeasurements","MeasurementFormatter","MeasurementSceneView","MeasurementGroupExporter","MeasurementGroup","hoveredPoint","reconcileXMLs","xmlFiles","currentAssets","measurementAssets","newAssets","xml","assetToDelete","updateMeasureAssets","xmlFile","loadMeasureAsset","createNewMeasurementGroup","stopDrawingItems","closeMultiImageWindow","enableTimeout","removeIDs","deletable","setActiveAlignment","alignUnits","linearUnit","loadMeasurementData","loadMeasurements","returnCoordinate","getCoordinate","temporaryMeasurement","activeMeasurement","clickMultiImage","multiImage","multiImageWindow","isSinglePoint","onClickFinish","canFinish","clickStandard","addTemporaryPoint","updateMeasureText","addSceneMeasurement","measuring","resetDragObject","removeTemporaryObjects","measureEndpoints","MeasureEndpoint","measurementID","checkMorePoints","morepoints","setTooltipText","clearViews","export","exportCSV","exportDAT","exportLinework","setUnits","refreshVolume","emptyValue","metersCutoff","squareMetersCutoff","vectorPrecisionLonLat","vectorPrecisionStandard","isMetric","finalValue","roundFloat","metresToFeet","isSurveyFeet","feet","metresToMiles","metresToKiloMetres","formatVolume","cubicMetresToCubicYards","squareMetresToSquareMiles","squareMetresToSquareFeet","squareMetresToSquareKilometres","formatAngle","nullValue","formatGrade","isFinite","formatStation","distanceAlong","lengthUnits","alongFinal","stationFinal","isImperial","feetToMetres","stationTotal","stationNumber","stationAlong","formatOffset","distanceAcross","sideOfSegment","convertUnits","precisionX","precisionY","precisionZ","isSurveryFeet","metres","squareMetres","cubicMetres","metresToYards","getDataExport","temp3DMPath","pythonName","handleExport3D","handleExport2D","getExportRows2D","getExportRows3D","measurements2D","measurements3D","measurement_coordinates","vertextView","time_created","measureCsvOut","mapProjection","getHeaderValues2D","getHeaderValues3D","distance3D","grade","areaValue","volumeValue","invalidVolumeMessage","areaUnits","volumeUnits","measurementVertices","updateMeasurements","removeFromArray","measure3D","newMeasurement","measure2D","timestamp","getLineCoordinates","names","getPointCoordinates","areaMeasurements","measureGeometry","surfaceVertices","surfaceIndices","alternateLabelColor","measurementVertex","boundingSphere","matrixWorld","TemporaryEndpoint","sphereBuffer","sphereMaterialStandard","sphereMaterialHover","lineMaterialStandard","lineMaterialHeight","lineMaterialHover","temporaryEndpoints","temporaryLines","temporaryLabels","dragValid","checkEndpointSelected","addActiveEndpoint","updateMeasureEndpoint","vertexIndex","setRestrictedPointTooltip","restrictedTooltip","endTooltipCount","moreTooltipMulti","endTooltipMulti","endTooltip","startTooltipMulti","createTempEndpoint","removeObjects","removeLabels","drawLabels","createEndpoint","createLine","useAlternate","defaultMaterial","pointMaterial","posScene","firstPointHigher","line0","line1","totalLength","fromBufferAttribute","addVectors","isHeight","lastLines","hasEnoughLines","oldMeasurement","removeMeasurement","addGPUIndex","GPUPicker","debug","numSections","_needsUpdate","LinearEncoding","clearSections","tX","tY","sectionWidth","sectionHeight","sectionX","sectionY","sectionIndex","pixelIndex","timeStart","startX","startY","pixelBuffer","readRenderTargetPixels","time","mouseResult","updateBaseIDs","oldClearColor","newClearColor","oldRenderTarget","getRenderTarget","getClearColor","oldClearAlpha","getClearAlpha","setClearColor","setClearAlpha","currentBaseID","gpuIndex","getSelectedObject","getObjectPosition","minIndex","maxIndex","coordinateFromBuffer","coordinateFromMesh","coordinateFromLine","toCheck","planes","faces","face","P3","setFromCoplanarPoints","intersections","isFirstPoint","Stats","addPanel","panel","dom","showPanel","cssText","beginTime","prevTime","frames","fpsPanel","Panel","msPanel","self","memory","memPanel","REVISION","begin","usedJSHeapSize","jsHeapSizeLimit","setMode","fg","bg","PR","devicePixelRatio","WIDTH","HEIGHT","TEXT_X","TEXT_Y","GRAPH_X","GRAPH_Y","GRAPH_WIDTH","GRAPH_HEIGHT","textBaseline","globalAlpha","TagMesh","TagPosition","TagItem","csv","TagFile","boundingBoxForTags","visibleChanged","textureChanged","newTagIDs","currentTagIDs","tagsChanged","TagsHandler","tagState","updateTagData","SceneViewTags","AerialTags","TagAnnotations","getTooltipText","getTagByID","getTagByQuery","allTags","tagCsvOut","hasComments","hasAnnotations","updated","toggleAnnotations","loadAnnotations","getAnnotations","setAnnotationType","setAnnotationDrawing","setDrawing","setAnnotationColor","setAnnotationSize","timeoutSeconds","pickingMeshes","flashTimeout","sceneViewTags","gpuIndices","cornerNumber","tagIndex","tagMaterial","tagFromPickerIndex","arrayIndex","setHovering","Cluster","getClusterStyle","getFeatures","tagScale","texturePaths","mostFrequent","strokeColor","combinedStyles","anchorXUnits","anchorYUnits","Text","GeoJSON","hitTolerance","isShape","readFeature","getDrawTool","freehand","geometryFunction","createRegularPolygon","createBox","starGeometryFunction","onDrawEnd","annotationID","writeFeatureObject","setLineStringTool","setRectangleTool","dashed","dash","erasing","newCoordinates","fraction","tileSize","pointTexture","spritePath","tileProjection","olProjection","GeomType","LineworkText","Sprite","checkVisibility","cameraPosition2D","meshPosition2D","LineworkPoints","LineworkLine","LineworkPolygon","MapLayer","lineworkLayer","reprojected","startIndex","endIndex","numCoordinates","useVectorTile","useImageLayer","outProjection","reprojectFeatures","geojsonObject","generateVectorTileLayer","generateImageLayer","generateVectorLayer","tileIndex","geojsonvt","indexMaxZoom","indexMaxPoints","VectorTileSource","tileUrlFunction","tileCoord","tileLoadFunction","tile","getTile","geojson","replacer","readFeatures","getTileGrid","getTileCoordExtent","featureProjection","setFeatures","VectorTileLayer","updateStyle","PointsLayer","minRadius","maxRadius","pointSize","LineLayer","Lines","PolygonLayer","Polygons","maxVertices","getFeature","getOutline","geojsonFeatures","polygonFaces","isContinuous","mapFeature","isQuad","faceSlice","LineworkLayer","mapLayers","geomType","addSceneData","addAerialData","addTextData","textScale","generateTexture","SpriteMaterial","meshColor","addCoordinates","bufferGeometry","getLineIndices","getPolygonIndices","pointIndex","geomIndex","LineworkFile","updateProperties","validBounds","CADHandler","ifcFiles","IFCFile","selectedFile","clearHighlightedFiles","removeSubset","modelFiles","newFile","SHPFile","DXFFile","loadNextfile","numLines","textWidth","measureText","borderThickness","xScale","flipY","rawType","useWebWorkers","highlightMaterial","IFCLoader","ifcManager","manager","ifcAPI","initManager","parseFromBuffer","ifcWorker","handleResponse","modelID","coordinationMatrix","GetCoordinationMatrix","cloneMeshObject","replaceMaterials","workerPath","wasmPath","setWasmPath","applyWebIfcConfig","COORDINATE_TO_ORIGIN","USE_FAST_BOOLS","setOnProgress","total","ifcMesh","attributesToProperties","expressID","getExpressId","getItemProperties","subsetMesh","createSubset","ids","removePrevious","SHPLayer","addLayers","shp","shpPath","numInvalid","layerNames","layerName","addNewGeometry","newLayer","DXFLayer","parseFromText","WebSourceHandler","webSources","sourcesToLoad","webSource","deleteSource","addNewSource","getNewSource","newSource","WebSource","webmapHandler","clearable","removeOnClear","visibleIdentifier","setLayerVisible","newIdentifiers","clearLayers","generateLayers","identifiers","removeLayers","FeatureVectorSource","tileGrid","createXYZ","strategy","getExtents","prevResolution","onResolutionChange","getZForResolution","fromUserResolution","tileRange","getTileRangeForExtentAndZ","fromUserExtent","extents","minY","maxY","toUserExtent","updateFeatures","newFeatures","featureID","getId","oldFeature","getFeatureById","FeatureWebSource","controllers","cancelRequests","clearLoadedExtents","loadedExtentsRtree_","TileLayer","TileArcGISRest","crossOrigin","LAYERS","featureCount","advancedQueryCapabilities","supportsPagination","supportsQueryWithResultType","supportsQuantization","supportsCoordinatesQuantization","spatialReference","wkid","xmin","ymin","xmax","ymax","esriResponse","getCapabilities","getNumberOfFeatures","vectorSource","styleFunction","createStyleFunction","reconstructQuantizedGeometry","geometryType","rings","paths","resultOffset","srid","getCode","projectionToEsriSRID","isComplexLayer","extendBounds","quantizationParameters","originPosition","fetchError","EsriJSON","exceededTransferLimit","newResultOffset","TileWMS","geomExtent","serverResponse","optionsFromCapabilities","matrixSet","WMTS","newLabelStyle","Viewer","viewContainer","mapContainer","defaultNearPlane","updateMouseCoords","drawPickerScene","initialZoomApplied","initialStateApplied","timingDebug","estimateLocalTransform","getLocalProjection","clearLocalTransformErrors","resetErrorValues","getOrthoLabelPolygons","isAerialLabels","initGpuPickers","StatsPanel","addContainerElements","animate","numberOfFiles","hasCameras","removeContainerElements","setProjectName","clamp","colorMapKey","getDataProjection","setMeasurementUnits","setInitialZoomFlag","setCameraState","setOrbitState","hasModels","hasTags","setTagState","matrixWorldInverse","cameraViewProjectionMatrix","projectionMatrix","Frustum","setFromProjectionMatrix","isBehindCamera","customStyle","div","onclick","toggleLocalAligner","refreshLocalTransform","drawObservations","generateLocalAlignerRows","numRows","addNewObservations","setLocalAlignerActive","setActiveObservation","deleteLocalAlignment","pointMarkupActive","addPointMarkupOperation","updatePointMarkupName","setPointMarkupActive","pointMarkupToggle","clearPointMarkup","pointMarkupZoom","pointMarkupDeleteGroup","pointMarkupDeleteBox","pointMarkupNameExists","setPointMarkupNewClassification","setPointMarkupIgnoredClassification","resetPointMarkupRotation","setPointMarkupHover","initMultiImageContainer","toggleMultiImageWindow","multiImageNextImage","multiImagePreviousImage","multiImageOnComplete","multiImageOnAddPoint","multiImageOnClose","toggleMeasurements","updateVolumeType","updateVolumeSampleRate","updateMeasureHover","deleteMeasurement","renameMeasurement","exportMeasurements","activeImageLabelPaths","loadedImageLabelPaths","loadImageLabelData","numLabels","labelHotkey","setLabelText","setLabelFindText","currentCategoryName","getIndexInList","checkCategoryUniqueness","categoryName","headerFileInfo","snapToFolder","tagFile","tagBBOX","toggleCameraAligner","resetCameraAligner","generateAdvancedAlignerRows","setErrorsCameraAligner","setErrors","clearErrorsCameraAligner","clearErrors","deleteRowCameraAligner","setBasicAlignerState","getBasicAlignerValue","cameraAngles","flashObservations","setCurrentObservation","updateCompassOffset","getAllCameras","folderPaths","previousCSV","setEmptyProject","reconcileAssets","applySavedTagState","allCameras","numberOfCameras","numCamerasChanged","showDetails","redrawImageObsMarkers","resetInitialFlag","resetDefaultAerialCamera","resetDefaultControlState","removeInteractions","clearCoordinates","updateCoordinates","logarithmicDepthBuffer","powerPreference","renderPickerScene","updateSceneElements","withTiming","scenePos","showCompassElement","requestAnimationFrame","nodesVisible","pointsVisible","childCount","getElementsByClassName","drawExpandedState","indexToShow","timeElapsed","containerLarge","offsetLarge","containerSmall","offsetSmall","borderTop","compassElement","ViewSwitcher","SceneViewer","setLocalObservations","setAlignerObservations","viewerRef","aerialRef","savedAerialState","viewerTooltipLines","setViewerTooltipLines","aerialTooltipLines","setAerialTooltipLines","cameraState","handleSwitched","addAllAssets","assetList","viewerAssets","numAssets","handleHashUpdate","setWindowHash","onhashchange","modifiedSceneState","modifiedAerialState","tagQuery","handleHashChange","newURL","viewerProps","viewerObj","defs","oldViewerTooltipLines","newViewerTooltipLines","oldAerialTooltipLines","newAerialTooltipLines","newCameraState","oldAerialState","newAerialState","viewerClasses","mapClasses","classSmall","getClasses","ObservationType","LocalObservationType","observations","imageObsInterval","pointObsInterval","setObservations","imageSelected","pointSelected","observationType","refreshObservationList","observation","imageMesh","pointMesh","numObservations","imageObs","imageHidden","pointObs","pointHidden","imageIdentifier","pose","pointIdx","imageIdx","cancelAlignment","clickImage","currentRow","imageDir","addImageObservationMesh","clickScene","addPointObservationMesh","selecting","resetSelectedState","updateAllMeshes","pointObsColor","PointObservation","imageObsColor","ImageObservation","flashObservation","defaultColor","numberOfFlashes","setHex","flashColor","clearFlashIntervals","obs","rotations","meshPos","inputInverted","currentID","updateAlignment","aerialObsColor","activeObservation","Aerial","styleColor","filled","latlon","average","output","local","drawPointObservations","drawAerialObservations","isSceneObs","isAerialObs","clearActiveObservation","onSceneClick","sceneTooltip","aerialTooltip","aerialObservationSuccess","imageObservationSuccess","pointObservationSuccess","errorLow","errorMedium","errorHigh","PointObservationIcon","ObservationIcon","AerialObservationIcon","ImageObservationIcon","clicked","buttonColor","ObservationError","lowCutoff","highCutoff","minHeightContent","toggleOptionParent","toggleOptionCheckbox","toggleOptionFlex","userWarning","selectMargin","checkboxPadding","ResidualError","ImageAlignerAdvanced","alignerAdvDialog","removeDialog","setCalculating","alignerMatrixPath","setAlignerMatrixPath","closePrompt","setClosePrompt","alignPosition","setAlignPosition","alignRotation","setAlignRotation","newRotation","setNewRotation","newOffset","setNewOffset","parseResiduals","resArray","res","rounded","isTableEmpty","removed","noCameras","imageClicked","pointClicked","img_obs","pc_obs","hasAdvancedAlignment","hasAlignment","requiredRows","camID","tmpObservationPath","tmpEncompassPath","observationsCSV","encompassCSV","observationsCSVContent","encompassCSVContent","isConverted","largeResiduals","camPoseEntry","initialPath","correctionName","correctionPath","residualsTemp","titleTop","AlignerShortcuts","ImageAlignerBasic","alignerBasicDialog","singleAlignment","setSingleAlignment","hasActiveCamera","savedAngle","activeCameraName","isModified","epsilon","checkDataModified","transformInfo","transformValues","AlignmentError","lowCutoffWithUnits","highCutoffWithUnits","localAlignerDialog","setRotate","setUtmZone","savePrompt","setSavePrompt","setOldProjection","updateViewerProjection","deleteViewerProjection","aerialSelected","aerialClicked","aerialObs","map_obs","translateX","translateY","scaling","getEstimator","tempProjection","LabelImportType","geometryLimit","titleInfo","titleMin","listContent","folderList","labelFixedHeight","labelParent","labelTitleWarning","labelTitleError","classificationText","progressToolbar","toolbarLinear","toolbarProgressCenter","downloadMargin","downloadResourceDialog","tableDropdown","checkBoxWithLabel","mappingMargin","checkBoxParent","captionPadding","paddingBottomAndTop","paddingBottomAndTopMinimal","fileButtonDiv","outputFolder","infoLabel","flexPaper","Label","isScrolling","labelName","isSceneLabel","getInfo","setGetInfo","isTrainingLabel","scoreValidity","scoreClass","GetInfoWindow","CategoryContent","listRef","scrollingDivLength","useScrollingDiv","scrollingDivHeight","scrollToItem","useIsScrolling","itemCount","itemSize","CategoryExpand","TrainingArea","setDeletePrompt","addNewLabelDisabled","addNewlabelTooltip","disableTypography","Category","isValidCategory","labelDisabled","runTextDetection","editPrompt","setEditPrompt","sortPrompt","setSortPrompt","textDetectPrompt","setTextDetectPrompt","setSorted","labelsAdded","handleToggleVisibility","numLabelsTooltip","substr","ScoreSortingParameters","runSort","scoreValue","defaultScore","TextDetectionParameters","LabelIntersectDialog","forceInitialProgress","setTrainClassifyExe","setTrainClassifyProgress","resetExecutableValues","checkTrainingData","pointClouds","setProcessType","LASfiles","minLasVersion","visibleClouds","cloudsAvailable","maxNumClasses","availableLasClasses","imageSamplingDistance","setImageSamplingDistance","setMinCameraDistance","setMaxCameraDistance","maxIntersectDistance","setMaxIntersectDistance","clusterDistance","setClusterDistance","numMatchesRequired","setNumMatchesRequired","setMinAngle","categoryClasses","setCategoryClasses","setOverwrite","extractPoints","setExtractPoints","objSize","setObjSize","collapse1","setCollapse1","collapse2","setCollapse2","ignoreClasses","setIgnoreClasses","runIntersection","tempCocoPath","csvEncompassPath","classesToIgnore","ic","categoryClassesNames","categoryClassesNums","lasOutputPath","successEstimate","successLabelInPC","successCombine","successConvert","convertAttempted","successLasWritten","csvOutputPaths","classifiedPaths","position_estimate_progress","positions_found","csvs_written","labels_found_pointcloud","combine_las","combine_las_complete","las_to_3dp","las_to_3dp_success","writing_las","las_written","las_classified_written","resetDefaultValues","categoriesTemp","lasClass","getCategoryClasses","ignoreTemp","getIgnoreClasses","destination","rowsTemp","ignoreClass","updateIgnoreClasses","ClassifyPointsDialog","useableClouds","weightByDist","setWeightByDist","ignoreHidden","setIgnoreHidden","maxDist","setMaxDist","minCameras","setMinCameras","runClassifyFromLabel","imagePercent","pointPercent","ImportDialog","importData","setImportData","isOrthoLabel","categoryList","setLabelLoadProgress","importCategory","setImportCategory","importLarge","setImportLarge","importPoints","setImportPoints","importLines","setImportLines","setCheckOverlap","lineBuffer","setLineBuffer","pointBuffer","setPointBuffer","hasLargeClasses","categoryNames","filterAnnotationTypes","validBufferSize","minIterations","maxIterations","getMappedCategory","createSelect","getLayerMenuItems","Ignore","numGeometry","Default","importCategories","newCategoryName","anno","ClassifyFromAerial","setProgress","setRows","sortedAlpha","setSortedAlpha","sortByNum","setSortByNum","overwriteFile","setOverwriteFile","preserveGround","setPreserveGround","newLasPath","setNewLasPath","mixedData","checkNamesForClass","classifyPointclouds","applicationOrder","lasClasses","inputPaths","overwriteGround","polygonData","class","tempTextPath","newCloudPaths","label_bounds_error","overwrite_failure","output_paths","sortButtonTitle","reverseSort","sortRowsByClassNum","sortRowsAlphabetically","sortReset","ClassificationParameters","runClassification","modelPath","setModelPath","runOnCPU","setRunOnCPU","usePretrained","setUsePretrained","TrainingParameters","runTraining","defaultIterations","pretrainedPath","setPretrainedPath","modelName","setModelName","imageTileSize","setImageTileSize","iterations","setIterations","orignalText","txtList","newText","updateLabelText","classValid","classHighlight","txt","handleTextChange","spellcheck","setSpellcheck","setSortType","ImageLabelling","imageLabelDialog","labelType","setLabelType","setAddCategory","classifyLasPrompt","setClassifyLasPrompt","labelLoadProgress","classifyAerialProgress","setClassifyAerialProgress","trainClassifyProgress","updateTrainClassifyProgress","trainClassifyExe","processType","classifyImage","setClassifyImage","readingLabelFile","setReadingLabelFile","training","setTraining","trainingURL","setTrainingURL","downloadResourcesDialog","setDownloadResourcesDialog","trainingPrompt","setTrainingPrompt","classificationPrompt","setClassificationPrompt","labelExportOpen","setLabelExportOpen","classifyPointsPanoOpen","setClassifyPointsPanoOpen","textDetection","setTextDetection","pointCloudsUsable","handleCancelProgress","handleCategoryChange","showTrainingWindow","canTrain","exportLabels3DL","exportToLinework","outputKey","importLabelsPTH","downloading_resources","extracting_resources","coco_data","importLabelData","importLabelsLinework","label_data","importLabels3DL","cudaErrorDialog","cudaError","selection","mlResourceErrorDialog","spellcheckCommand","labelJSON","imageJSON","noMlResources","exportDisabled","trainingLinkDisabled","noLabels","noImages","labelDisabledNoLabels","labelDisabledNoImages","localizedProcessType","modalName","downloadTooltip","imagePaths","canClassify","canRunClassification","canRunAerialToLas","combinedExtension","areas","pretrainedModelPath","gpu_memory_error","model_diverge_error","model_file_path","class_number_mismatch","old_classes","new_classes","CircularProgress","borderRight","QuickNav","currentPosition","closestPosition","lookatScene","getBestSceneState","folderAssetIds","folderAsset","getFolderAssets","isSelected","folderAssets","numFolderAssets","numAssetsVisible","folderOptions","openNav","mkdirs","moveCameraData","imagesPath","imagesData","imageName","newImagePath","assetsFolder","getAssetIndex","moveAssetData","singleFileOutput","handleExportError","inputPath","moveStreamablePointsData","pointPath","moveGenericPointCloud","onExportError","copyToFile","shpInput","shpOutput","dbfInput","dbfOutput","moveModelData","exporterOptsDefaults","onError","getStaticExporter","buildPath","getBuildPath","cancelFlag","cancel","webOutputPath","rootOutputPath","assetIndex","finalPath","updateStreamablePointsState","updateRawPointsState","updateCameraDataState","updateModelDataState","matrixPath","updateCameraTransformPath","miniViewerPath","getMiniViewerPath","exeOutputPath","globalSettingsPath","projectJson","projectPath","BulletListItem","NewProjectInfo","landXMLFiles","webmapSources","numGenericPointCloud","numberOfImages","cameraAsset","tagAsset","exportText","contentCenter","cancelProgress","cancelContent","switchLabel","switchElement","StaticExporter","exporterDialog","messageDialog","successDialog","cancelDialog","setSingleFileOutput","exportTopMessage","setExportTopMessage","exportBottomMessage","setExportBottomMessage","exportPercent","updateExportPercent","isExportRunning","setIsExportRunning","startExport","cancelExport","setExportPercent","canExport","onExportFinished","setExportMessage","exportToStatic","exportName","sanitizedName","sanitize","SHP_FILE_TYPES","POTREE_FILES","onStart","getUploadURL","projectID","getCloudExporter","statuses","panoramics","panoAsset","planars","pointCloudAsset","orthomosaics","orthoAsset","landxmls","landXMLAsset","ifcAsset","shpFiles","shpAsset","dxfFiles","dxfAsset","webmapAsset","map_type","link","projectState","appVersion","measurementUnits","request","createProject","version_mismatch","server","minimum_version","uploadList","uploads","uploadId","processPoints","getAssetsToUpload","tempOutputPath","status_code","StatusCode","LinkedProjectInfo","AssetStatusText","Uploaded","Uploading","Preparing","Errored","Queued","getColor","getText","CloudExporter","assetStatuses","setAssetStatuses","isExportFinished","setIsExportFinished","projectExists","setProjectExists","projectURL","setProjectURL","handleExportCancel","exportToCloud","exists","originalID","checkProject","uploadMessage","assetStatus","status_text","clippingBoxParent","clippingBoxButtons","operationList","overflowY","boxOrientation","dropdownRoot","dropdownSelect","PointMarkupBox","disableGutters","onMouseOver","PointMarkupGroup","operation","isSplit","newBoxDisabled","operationBoxes","defaultIgnoreValue","classOptions","displayName","DataExportSplit","markupGroups","exportPoints","setExportPoints","exportImages","setExportImages","inputFoldersPoints","inputFolderCameras","operationData","outputPaths","DataExportMarkup","PointMarkup","pointMarkupDialog","toolType","setToolType","exportPromptMarkup","setExportPromptMarkup","exportPromptSplit","setExportPromptSplit","newOperationPrompt","setNewOperationPrompt","newOutputPrompt","setNewOutputPrompt","conversionProgress","setConversionProgress","isPointMarkup","isFolderSplit","dialogTitle","copyClipboard","measurementUnitsParent","flexWrap","measurementUnitsRadio","imageOnlyInfoButton","marginside","expandText","bold","alignmentSelect","cell","tableCell","cellParent","measureTable","calculateButton","recalculate","recalculateButton","ExportDialog","exportType","setExportType","setOrdering","Shapefile","Data","MeasureTypeIcon","setMeasureType","ImportExportMeasureIcon","ClipboardCopy","MeasurementInfo3DLength","MeasurementInfoHeight","MeasurementInfo3DArea","isVolume","getVolumeComponent","MeasurementInfo2DArea","measureTypeText","MeasurementInfo2DLength","MeasurementInfoVolume","volumeMethodText","volumeRateText","MeasurementInfoStation","MeasurementCard","verticesReprojected","generateVertexPositions","is3DArea","is2DArea","is3DLength","is2DLength","isStationMeasurement","Measurements","exportDialog","xmlAssets","activeMeasurePrompt","setActiveMeasurePrompt","alignmentChoice","setAlignmentChoice","setMeasureUnits","loadImportData","encoded","decodeURIComponent","onModalClose","xmlAlignments","updateDefaultDropdown","reversed","iconProps","importDisabled","allowStationMeasurements","RadioGroup","Radio","fileDialog","accept","reader","FileReader","readAsText","buttonParentLeft","buttonParentRight","smallButton","buttonRight","multiImageHeader","fontFamily","WindowButton","MultiImageInfo","clampedColor","midValue","observationStyle1","observationStyle2","observationText1","observationText2","errorStyle","errorValue","errorElement","distanceStyle1","distanceValue1","distanceElement1","distanceStyle2","distanceValue2","distanceElement2","customPromptOpen","setCustomPromptOpen","customPromptState","setCustomPromptState","textLines","dependencies","dialogDiv","dialogContent","lineHeight","dialogPaper","divContent","indent","listItems","logoImage","support","titleParent","AboutDialog","helpDialog","javascriptDependencies","jquery","ol","react","three","typescript","devDependencies","pythonDependencies","numpy","scipy","matplotlib","pykml","lxml","miscDependancies","getDependencies","logoPath","underline","rel","consoleDialogHeader","consoleDialogTitle","consoleDialogClose","consoleHeight","consoleLine","TaskQueue","ConsoleWindow","selectedTaskID","lineData","setLineData","activeTask","scrollTop","ProjectListRow","accentColor","stc","projectResponse","settingsResponse","settingsJSON","borderLeft","CloudProjectList","userProjects","setUserProjects","itemsSearch","handleSortChange","sortByDate","dateA","dateB","nameParts","initialSort","nameA","nameB","sortByName","useItemsSearch","sortOptions","projects","isAdmin","getUserProjects","hasProjects","sortValue","DragDropLoader","closest","ProjectLoader","loadFromCompiledExe","rawArgs","argv","arg","getAllFileArgs","oncontextmenu","cloudProject","loadFromStaticSite","AppBackdrop","backdropOpen","setBackdropOpen","Backdrop","snackbar","AppWithAuth","appAccess","setAppAccess","accessDialog","App","measurementsDialog","customURLDialog","localObservations","alignerObservations","multiImageOpen","pointProfileOpen","multiImageState","handleLinkWithoutTargets","mainWindow","quit","hotToast"],"mappings":"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B,6CnCqFvC,mBoCrFa,IAA0B,6CpCsFvC,mBqCtFa,IAA0B,6CrCuFvC,mBsCvFa,IAA0B,6CtCwFvC,mBuCxFa,IAA0B,6CvCyFvC,mBwCzFa,IAA0B,6CxC0FvC,mByC1Fa,IAA0B,6CzC2FvC,mB0C3Fa,IAA0B,6C1C4FvC,oB2C5Fa,IAA0B,8C3C6FvC,oB4C7Fa,IAA0B,8C5C8FvC,oB6C9Fa,IAA0B,8C7C+FvC,oB8C/Fa,IAA0B,8C9CgGvC,oB+ChGa,IAA0B,8C/CiGvC,oBgDjGa,IAA0B,+CCsE1BA,OApCE,CACf,iBCnCa,IAA0B,2CDoCvC,iBEpCa,IAA0B,2CFqCvC,oBGrCa,IAA0B,8CHsCvC,eItCa,IAA0B,yCJuCvC,WKvCa,IAA0B,qCLwCvC,gBMxCa,IAA0B,0CNyCvC,cOzCa,IAA0B,wCP0CvC,qBQ1Ca,IAA0B,+CR2CvC,kBS3Ca,IAA0B,4CT4CvC,oBU5Ca,IAA0B,8CV6CvC,cW7Ca,IAA0B,wCX8CvC,gBY9Ca,IAA0B,0CZ+CvC,ea/Ca,IAA0B,yCbgDvC,mBchDa,IAA0B,6CdiDvC,qBejDa,IAA0B,+CfkDvC,kBgBlDa,IAA0B,4ChBmDvC,oBiBnDa,IAA0B,8CjBoDvC,iBkBpDa,IAA0B,2ClBqDvC,emBrDa,IAA0B,yCnBsDvC,aoBtDa,IAA0B,uCpBuDvC,cqBvDa,IAA0B,wCrBwDvC,0BsBxDa,IAA0B,oDtByDvC,iBuBzDa,IAA0B,2CvB0DvC,gBwB1Da,IAA0B,0CxB2DvC,iByB3Da,IAA0B,2CzB4DvC,0B0B5Da,IAA0B,oD1B6DvC,oB2B7Da,IAA0B,8C3B8DvC,qB4B9Da,IAA0B,+C5B+DvC,gB6B/Da,IAA0B,0C7BgEvC,iB8BhEa,IAA0B,2C9BiEvC,a+BjEa,IAA0B,uC/BkEvC,cgClEa,IAA0B,wChCmEvC,mBiCnEa,IAA0B,8CC4H1BA,OA/DE,CACf,aC9Da,IAA0B,uCD+DvC,YE/Da,IAA0B,sCFgEvC,YGhEa,IAA0B,sCHiEvC,YIjEa,IAA0B,sCJkEvC,eKlEa,IAA0B,yCLmEvC,YMnEa,IAA0B,sCNoEvC,iBOpEa,IAA0B,2CPqEvC,WQrEa,IAA0B,qCRsEvC,aStEa,IAA0B,uCTuEvC,iBUvEa,IAA0B,2CVwEvC,cWxEa,IAA0B,wCXyEvC,eYzEa,IAA0B,yCZ0EvC,ea1Ea,IAA0B,yCb2EvC,cc3Ea,IAA0B,wCd4EvC,Ye5Ea,IAA0B,sCf6EvC,cgB7Ea,IAA0B,wChB8EvC,WiB9Ea,IAA0B,qCjB+EvC,WkB/Ea,IAA0B,qClBgFvC,YmBhFa,IAA0B,sCnBiFvC,oBoBjFa,IAA0B,8CpBkFvC,kBqBlFa,IAA0B,4CrBmFvC,kBsBnFa,IAA0B,4CtBoFvC,kBuBpFa,IAA0B,4CvBqFvC,kBwBrFa,IAA0B,4CxBsFvC,kByBtFa,IAA0B,4CzBuFvC,kB0BvFa,IAA0B,4C1BwFvC,kB2BxFa,IAA0B,4C3ByFvC,e4BzFa,IAA0B,yC5B0FvC,oB6B1Fa,IAA0B,8C7B2FvC,oB8B3Fa,IAA0B,8C9B4FvC,a+B5Fa,IAA0B,uC/B6FvC,kBgC7Fa,IAA0B,4ChC8FvC,iBiC9Fa,IAA0B,2CjC+FvC,YkC/Fa,IAA0B,sClCgGvC,gBmChGa,IAA0B,0CnCiGvC,gBoCjGa,IAA0B,0CpCkGvC,gBqClGa,IAA0B,0CrCmGvC,gBsCnGa,IAA0B,0CtCoGvC,iBuCpGa,IAA0B,2CvCqGvC,ewCrGa,IAA0B,yCxCsGvC,cyCtGa,IAA0B,wCzCuGvC,e0CvGa,IAA0B,yC1CwGvC,iB2CxGa,IAA0B,2C3CyGvC,gB4CzGa,IAA0B,0C5C0GvC,gB6C1Ga,IAA0B,0C7C2GvC,gB8C3Ga,IAA0B,0C9C4GvC,e+C5Ga,IAA0B,yC/C6GvC,kBgD7Ga,IAA0B,4ChD8GvC,mBiD9Ga,IAA0B,6CjD+GvC,WkD/Ga,IAA0B,qClDgHvC,mBmDhHa,IAA0B,6CnDiHvC,eoDjHa,IAA0B,yCpDkHvC,cqDlHa,IAA0B,wCrDmHvC,gBsDnHa,IAA0B,0CtDoHvC,WuDpHa,IAA0B,qCvDqHvC,WwDrHa,IAA0B,qCxDsHvC,0ByDtHa,IAA0B,oDzDuHvC,0B0DvHa,IAA0B,oD1DwHvC,0B2DxHa,IAA0B,oD3DyHvC,0B4DzHa,IAA0B,qDCgF1BA,OAzCE,CACf,mCCxCa,IAA0B,6DDyCvC,sCEzCa,IAA0B,gEF0CvC,+BG1Ca,IAA0B,yDH2CvC,oCI3Ca,IAA0B,8DJ4CvC,iCK5Ca,IAA0B,2DL6CvC,kCM7Ca,IAA0B,4DN8CvC,mDO9Ca,IAA0B,6EP+CvC,oDQ/Ca,IAA0B,8ERgDvC,qCShDa,IAA0B,+DTiDvC,qCUjDa,IAA0B,+DVkDvC,kCWlDa,IAA0B,4DXmDvC,qCYnDa,IAA0B,+DZoDvC,mCapDa,IAA0B,6DbqDvC,+BcrDa,IAA0B,yDdsDvC,qCetDa,IAA0B,+DfuDvC,0BgBvDa,IAA0B,oDhBwDvC,iBiBxDa,IAA0B,2CjByDvC,gBkBzDa,IAA0B,0ClB0DvC,oBmB1Da,IAA0B,8CnB2DvC,sBoB3Da,IAA0B,gDpB4DvC,sBqB5Da,IAA0B,gDrB6DvC,uBsB7Da,IAA0B,iDtB8DvC,uBuB9Da,IAA0B,iDvB+DvC,kBwB/Da,IAA0B,4CxBgEvC,kByBhEa,IAA0B,4CzBiEvC,wB0BjEa,IAA0B,kD1BkEvC,sB2BlEa,IAA0B,gD3BmEvC,8B4BnEa,IAA0B,wD5BoEvC,4B6BpEa,IAA0B,sD7BqEvC,sB8BrEa,IAA0B,gD9BsEvC,uB+BtEa,IAA0B,iD/BuEvC,wBgCvEa,IAA0B,kDhCwEvC,sCiCxEa,IAA0B,gEjCyEvC,gCkCzEa,IAA0B,0DlC0EvC,uBmC1Ea,IAA0B,iDnC2EvC,wBoC3Ea,IAA0B,kDpC4EvC,oBqC5Ea,IAA0B,8CrC6EvC,sBsC7Ea,IAA0B,iDCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,2ECA1B,OAA0B,wDCA1B,OAA0B,+ECA1B,OAA0B,8ECA1B,OAA0B,mECA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,qDCA1B,OAA0B,gECA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,wDCA1B,OAA0B,qDCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,2ECA1B,OAA0B,wDCA1B,OAA0B,sDCA1B,OAA0B,gECA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,iECA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,4ECA1B,OAA0B,mFCA1B,OAA0B,uFCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,6DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,uDCA1B,OAA0B,wDCA1B,OAA0B,wECA1B,OAA0B,yECA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,kFCA1B,OAA0B,wECA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,kECA1B,OAA0B,mECA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,wECA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,8DCA1B,OAA0B,0DCA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,8ECA1B,OAA0B,kECA1B,OAA0B,mECA1B,OAA0B,sECA1B,OAA0B,6ECA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,2DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,wDCA1B,OAA0B,8DCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,sDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,mECA1B,OAA0B,qECA1B,OAA0B,8DCA1B,OAA0B,oECA1B,OAA0B,+DCA1B,OAA0B,qECA1B,OAA0B,kECA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,iECA1B,OAA0B,oECA1B,OAA0B,4DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,wDCA1B,OAA0B,2DCA1B,OAA0B,4DCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,0DCA1B,OAA0B,gECA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,+DCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,2DCA1B,OAA0B,6DCA1B,OAA0B,qECA1B,OAA0B,gECA1B,OAA0B,0DCA1B,OAA0B,8DCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,+DCA1B,OAA0B,2ECA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sECA1B,OAA0B,sFCA1B,OAA0B,sFCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,wDCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,gECA1B,OAA0B,oFCA1B,OAA0B,oFCA1B,OAA0B,oFCA1B,OAA0B,oFCA1B,OAA0B,oFCA1B,OAA0B,oFCA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,wECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,6DCA1B,OAA0B,6FCA1B,OAA0B,+DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,oECA1B,OAA0B,mECA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,yDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,gFCA1B,OAA0B,qDCA1B,OAA0B,sDCA1B,OAA0B,yDCA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,sECA1B,OAA0B,uECA1B,OAA0B,2ECA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,gECA1B,OAA0B,0DCA1B,OAA0B,iECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,wECA1B,OAA0B,wECA1B,OAA0B,oDCA1B,OAA0B,sDCA1B,OAA0B,wECA1B,OAA0B,8DCA1B,OAA0B,wECA1B,OAA0B,oECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,qECA1B,OAA0B,iECA1B,OAA0B,8DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,sDCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,oFCA1B,OAA0B,8DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,0DCA1B,OAA0B,uECA1B,OAA0B,iECA1B,OAA0B,oECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,8DCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,yDCA1B,OAA0B,wDCA1B,OAA0B,mFCA1B,OAA0B,uECA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,0DCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,kFCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,uDCA1B,OAA0B,4DCA1B,OAA0B,kECA1B,OAA0B,qECA1B,OAA0B,mECA1B,OAA0B,oDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,2ECA1B,OAA0B,0DCA1B,OAA0B,iECA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,yECA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,2DCA1B,OAA0B,sECA1B,OAA0B,yECA1B,OAA0B,8DCA1B,OAA0B,yDCA1B,OAA0B,sECA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,0DCA1B,OAA0B,uDCA1B,OAA0B,6DCA1B,OAA0B,wDCA1B,OAA0B,8DCA1B,OAA0B,wDCA1B,OAA0B,+DCA1B,OAA0B,mECA1B,OAA0B,qECA1B,OAA0B,0DCA1B,OAA0B,+DCA1B,OAA0B,yECA1B,OAA0B,qECA1B,OAA0B,oDCA1B,OAA0B,2DCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,8DCA1B,OAA0B,4DCA1B,OAA0B,oECA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,+DCA1B,OAA0B,yECA1B,OAA0B,uDCA1B,OAA0B,+DCA1B,OAA0B,8DCA1B,OAA0B,gECA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,gECA1B,OAA0B,4ECA1B,OAA0B,kECA1B,OAA0B,gECA1B,OAA0B,uECA1B,OAA0B,wDCA1B,OAA0B,yDCA1B,OAA0B,qECA1B,OAA0B,iECA1B,OAA0B,mECA1B,OAA0B,sECA1B,OAA0B,wDCA1B,OAA0B,kECA1B,OAA0B,8ECA1B,OAA0B,+ECA1B,OAA0B,kFCA1B,OAA0B,wECA1B,OAA0B,2ECA1B,OAA0B,4ECA1B,OAA0B,iECA1B,OAA0B,2ECA1B,OAA0B,6ECA1B,OAA0B,8ECA1B,OAA0B,+ECA1B,OAA0B,+ECA1B,OAA0B,+ECA1B,OAA0B,kFCA1B,OAA0B,2FCA1B,OAA0B,+ECA1B,OAA0B,+ECA1B,OAA0B,kFCA1B,OAA0B,2FCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,qECA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,uECA1B,OAA0B,sFCA1B,OAA0B,sFCA1B,OAA0B,oECA1B,OAA0B,uECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,2ECA1B,OAA0B,uECA1B,OAA0B,4ECA1B,OAA0B,2ECA1B,OAA0B,2DCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,yFCA1B,OAA0B,yFCA1B,OAA0B,gFCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,0ECA1B,OAA0B,oECA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,iECA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,wFCA1B,OAA0B,wFCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,iECA1B,OAA0B,wECA1B,OAA0B,8DCA1B,OAA0B,yECA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,6DCA1B,OAA0B,qECA1B,OAA0B,+DCA1B,OAA0B,iECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,6DCA1B,OAA0B,8DCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,iECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,2ECA1B,OAA0B,yDCA1B,OAA0B,iECA1B,OAA0B,iDCA1B,OAA0B,0ECA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,yDCA1B,OAA0B,qECA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,uECA1B,OAA0B,mECA1B,OAA0B,4DCA1B,OAA0B,iDCA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,wECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,wECA1B,OAA0B,wECA1B,OAA0B,wECA1B,OAA0B,wECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,qECA1B,OAA0B,0ECA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,oDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,4ECA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,sECA1B,OAA0B,uECA1B,OAA0B,0ECA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,gECA1B,OAA0B,wDCA1B,OAA0B,4ECA1B,OAA0B,6DCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,iECA1B,OAA0B,qECA1B,OAA0B,qDCA1B,OAA0B,2DCA1B,OAA0B,wECA1B,OAA0B,yECA1B,OAA0B,6DCA1B,OAA0B,sECA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,sECA1B,OAA0B,uDCA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,4FCA1B,OAA0B,4FCA1B,OAA0B,6ECA1B,OAA0B,gFCA1B,OAA0B,gFCA1B,OAA0B,+DCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,mECA1B,OAA0B,oECA1B,OAA0B,+DCA1B,OAA0B,8DCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,sECA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,iFCA1B,OAA0B,iFCA1B,OAA0B,iFCA1B,OAA0B,0ECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,+DCA1B,OAA0B,kFCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,+ECA1B,OAA0B,gECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,iECA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,0FCA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,iECA1B,OAA0B,sDCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,mECA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,oECA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,mECA1B,OAA0B,8DCA1B,OAA0B,0DCA1B,OAA0B,wDCA1B,OAA0B,2ECA1B,OAA0B,iECA1B,OAA0B,wDCA1B,OAA0B,yDCA1B,OAA0B,uECA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,+ECA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,iFCA1B,OAA0B,iFCA1B,OAA0B,iFCA1B,OAA0B,iFCA1B,OAA0B,4FCA1B,OAA0B,4FCA1B,OAA0B,4ECA1B,OAA0B,0GCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,2DCA1B,OAA0B,+DCA1B,OAA0B,2ECA1B,OAA0B,kECA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,sECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,4ECA1B,OAA0B,4ECA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,2DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,iFCA1B,OAA0B,iFCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,6DCA1B,OAA0B,kECA1B,OAA0B,6DCA1B,OAA0B,qECA1B,OAA0B,wDCA1B,OAA0B,yDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,kDCA1B,OAA0B,+ECA1B,OAA0B,+ECA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,uDCA1B,OAA0B,sDCA1B,OAA0B,iDCA1B,OAA0B,iDCA1B,OAA0B,2DCA1B,OAA0B,0DCA1B,OAA0B,0ECA1B,OAA0B,iECA1B,OAA0B,uDCA1B,OAA0B,yDCA1B,OAA0B,iFCA1B,OAA0B,+ECA1B,OAA0B,gFCA1B,OAA0B,wDCA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,4DCA1B,OAA0B,wDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,gECA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,kFCA1B,OAA0B,4ECA1B,OAA0B,oDCA1B,OAA0B,mDCA1B,OAA0B,mDCA1B,OAA0B,mDCA1B,OAA0B,0DCA1B,OAA0B,mFCA1B,OAA0B,wFCA1B,OAA0B,8ECA1B,OAA0B,wFCA1B,OAA0B,0DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,kECA1B,OAA0B,yECA1B,OAA0B,qECA1B,OAA0B,wDCA1B,OAA0B,sDCA1B,OAA0B,kDCA1B,OAA0B,0ECA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,0ECA1B,OAA0B,0ECA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,+DCA1B,OAA0B,qDCA1B,OAA0B,6DCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,0DCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,6DCA1B,OAA0B,yECA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,iDCA1B,OAA0B,gDCA1B,OAA0B,gDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,gDCA1B,OAA0B,gDCA1B,OAA0B,+CCA1B,OAA0B,+CCA1B,OAA0B,oDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,+CCA1B,OAA0B,+CCA1B,OAA0B,qECA1B,OAA0B,qECA1B,OAA0B,4DCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,+ECA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,kECA1B,OAA0B,qECA1B,OAA0B,sECA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,kDCA1B,OAA0B,0DCA1B,OAA0B,2DCA1B,OAA0B,mFCA1B,OAA0B,sDCA1B,OAA0B,sECA1B,OAA0B,6CCA1B,OAA0B,6CCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,kECA1B,OAA0B,kECA1B,OAA0B,wDCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,gECA1B,OAA0B,iECA1B,OAA0B,2ECA1B,OAA0B,4ECA1B,OAA0B,6ECA1B,OAA0B,8ECA1B,OAA0B,8DCA1B,OAA0B,6ECA1B,OAA0B,+DCA1B,OAA0B,8ECA1B,OAA0B,8DCA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,+DCA1B,OAA0B,4ECA1B,OAA0B,qDCA1B,OAA0B,qDCA1B,OAA0B,2DCA1B,OAA0B,4DCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,gECA1B,OAA0B,gECA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,oDCA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,sECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,uECA1B,OAA0B,+CCA1B,OAA0B,0DCA1B,OAA0B,0DCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,8CCA1B,OAA0B,gDCA1B,OAA0B,mDCA1B,OAA0B,uDCA1B,OAA0B,8CCA1B,OAA0B,8CCA1B,OAA0B,mDCA1B,OAA0B,oDCA1B,OAA0B,iDCA1B,OAA0B,kDCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,mECA1B,OAA0B,mECA1B,OAA0B,oECA1B,OAA0B,oECA1B,OAA0B,wDCA1B,OAA0B,kDCA1B,OAA0B,8ECA1B,OAA0B,8ECA1B,OAA0B,+ECA1B,OAA0B,+ECA1B,OAA0B,sFCA1B,OAA0B,sFCA1B,OAA0B,sFCA1B,OAA0B,sFCA1B,OAA0B,uFCA1B,OAA0B,uFCA1B,OAA0B,uFCA1B,OAA0B,uFCA1B,OAA0B,uECA1B,OAA0B,wECA1B,OAA0B,kECA1B,OAA0B,2DCA1B,OAA0B,uDCA1B,OAA0B,mDCA1B,OAA0B,oDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wDCA1B,OAA0B,wECA1B,OAA0B,wECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,qECA1B,OAA0B,sECA1B,OAA0B,0DCA1B,OAA0B,yDCA1B,OAA0B,sDCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,6DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,yDCA1B,OAA0B,8DCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,yDCA1B,OAA0B,yDCA1B,OAA0B,wDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,iECA1B,OAA0B,iECA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,sDCA1B,OAA0B,wDCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,wDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,uDCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,8DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,oDCA1B,OAA0B,oDCA1B,OAA0B,6DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,4DCA1B,OAA0B,yDCA1B,OAA0B,0DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,2DCA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,yECA1B,OAA0B,4ECA1B,OAA0B,4ECA1B,OAA0B,4ECA1B,OAA0B,4ECA1B,OAA0B,4ECA1B,OAA0B,4ECA1B,OAA0B,+DCA1B,OA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C,uCI30Fa,IAA0B,iEJ40FvC,kCK50Fa,IAA0B,4DL60FvC,kCM70Fa,IAA0B,4DN80FvC,wCO90Fa,IAA0B,kEP+0FvC,+BQ/0Fa,IAA0B,yDRg1FvC,2BSh1Fa,IAA0B,qDTi1FvC,gCUj1Fa,IAA0B,0DVk1FvC,iCWl1Fa,IAA0B,2DXm1FvC,yBYn1Fa,IAA0B,mDZo1FvC,yBap1Fa,IAA0B,mDbq1FvC,yBcr1Fa,IAA0B,mDds1FvC,yBet1Fa,IAA0B,mDfu1FvC,yBgBv1Fa,IAA0B,mDhBw1FvC,yBiBx1Fa,IAA0B,mDjBy1FvC,yBkBz1Fa,IAA0B,mDlB01FvC,0BmB11Fa,IAA0B,oDnB21FvC,0BoB31Fa,IAA0B,oDpB41FvC,6CqB51Fa,IAA0B,uErB61FvC,8CsB71Fa,IAA0B,wEtB81FvC,0BuB91Fa,IAA0B,oDvB+1FvC,0BwB/1Fa,IAA0B,oDxBg2FvC,0ByBh2Fa,IAA0B,oDzBi2FvC,0B0Bj2Fa,IAA0B,oD1Bk2FvC,0B2Bl2Fa,IAA0B,oD3Bm2FvC,0B4Bn2Fa,IAA0B,oD5Bo2FvC,0B6Bp2Fa,IAA0B,oD7Bq2FvC,oB8Br2Fa,IAA0B,8C9Bs2FvC,oB+Bt2Fa,IAA0B,8C/Bu2FvC,0BgCv2Fa,IAA0B,oDhCw2FvC,2BiCx2Fa,IAA0B,qDjCy2FvC,8BkCz2Fa,IAA0B,wDlC02FvC,gDmC12Fa,IAA0B,0EnC22FvC,0BoC32Fa,IAA0B,oDpC42FvC,oCqC52Fa,IAA0B,8DrC62FvC,mCsC72Fa,IAA0B,6DtC82FvC,mCuC92Fa,IAA0B,6DvC+2FvC,mCwC/2Fa,IAA0B,6DxCg3FvC,oCyCh3Fa,IAA0B,8DzCi3FvC,oC0Cj3Fa,IAA0B,8D1Ck3FvC,oC2Cl3Fa,IAA0B,8D3Cm3FvC,sB4Cn3Fa,IAA0B,gD5Co3FvC,sB6Cp3Fa,IAA0B,gD7Cq3FvC,sB8Cr3Fa,IAA0B,gD9Cs3FvC,iC+Ct3Fa,IAA0B,2D/Cu3FvC,oCgDv3Fa,IAA0B,8DhDw3FvC,oCiDx3Fa,IAA0B,8DjDy3FvC,qCkDz3Fa,IAA0B,+DlD03FvC,qCmD13Fa,IAA0B,+DnD23FvC,oBoD33Fa,IAA0B,8CpD43FvC,6BqD53Fa,IAA0B,uDrD63FvC,2BsD73Fa,IAA0B,qDtD83FvC,2BuD93Fa,IAA0B,qDvD+3FvC,2BwD/3Fa,IAA0B,qDxDg4FvC,sCyDh4Fa,IAA0B,gEzDi4FvC,iC0Dj4Fa,IAA0B,2D1Dk4FvC,iC2Dl4Fa,IAA0B,2D3Dm4FvC,6B4Dn4Fa,IAA0B,uD5Do4FvC,6B6Dp4Fa,IAA0B,uD7Dq4FvC,6B8Dr4Fa,IAA0B,uD9Ds4FvC,6B+Dt4Fa,IAA0B,uD/Du4FvC,4BgEv4Fa,IAA0B,sDhEw4FvC,4BiEx4Fa,IAA0B,sDjEy4FvC,4BkEz4Fa,IAA0B,sDlE04FvC,4BmE14Fa,IAA0B,sDnE24FvC,4BoE34Fa,IAA0B,sDpE44FvC,wCqE54Fa,IAA0B,kErE64FvC,6BsE74Fa,IAA0B,uDtE84FvC,6BuE94Fa,IAA0B,uDvE+4FvC,6BwE/4Fa,IAA0B,uDxEg5FvC,6ByEh5Fa,IAA0B,uDzEi5FvC,6B0Ej5Fa,IAA0B,uD1Ek5FvC,6B2El5Fa,IAA0B,uD3Em5FvC,0B4En5Fa,IAA0B,oD5Eo5FvC,0B6Ep5Fa,IAA0B,oD7Eq5FvC,0B8Er5Fa,IAA0B,oD9Es5FvC,0B+Et5Fa,IAA0B,oD/Eu5FvC,0BgFv5Fa,IAA0B,oDhFw5FvC,uBiFx5Fa,IAA0B,iDjFy5FvC,uBkFz5Fa,IAA0B,iDlF05FvC,8BmF15Fa,IAA0B,wDnF25FvC,8BoF35Fa,IAA0B,wDpF45FvC,qBqF55Fa,IAA0B,+CrF65FvC,qBsF75Fa,IAA0B,+CtF85FvC,qBuF95Fa,IAA0B,+CvF+5FvC,sBwF/5Fa,IAA0B,gDxFg6FvC,wByFh6Fa,IAA0B,kDzFi6FvC,wB0Fj6Fa,IAA0B,kD1Fk6FvC,wB2Fl6Fa,IAA0B,kD3Fm6FvC,wB4Fn6Fa,IAA0B,kD5Fo6FvC,wB6Fp6Fa,IAA0B,kD7Fq6FvC,wB8Fr6Fa,IAA0B,kD9Fs6FvC,wB+Ft6Fa,IAA0B,kD/Fu6FvC,0DgGv6Fa,IAA0B,oFhGw6FvC,mCiGx6Fa,IAA0B,6DjGy6FvC,mCkGz6Fa,IAA0B,6DlG06FvC,mCmG16Fa,IAA0B,6DnG26FvC,mCoG36Fa,IAA0B,6DpG46FvC,6CqG56Fa,IAA0B,uErG66FvC,yCsG76Fa,IAA0B,mEtG86FvC,oCuG96Fa,IAA0B,8DvG+6FvC,oCwG/6Fa,IAA0B,8DxGg7FvC,oCyGh7Fa,IAA0B,8DzGi7FvC,0C0Gj7Fa,IAA0B,oE1Gk7FvC,qC2Gl7Fa,IAA0B,+D3Gm7FvC,qC4Gn7Fa,IAA0B,+D5Go7FvC,qC6Gp7Fa,IAA0B,+D7Gq7FvC,qC8Gr7Fa,IAA0B,+D9Gs7FvC,qC+Gt7Fa,IAA0B,+D/Gu7FvC,+BgHv7Fa,IAA0B,yDhHw7FvC,+BiHx7Fa,IAA0B,yDjHy7FvC,+BkHz7Fa,IAA0B,yDlH07FvC,+BmH17Fa,IAA0B,yDnH27FvC,+BoH37Fa,IAA0B,yDpH47FvC,+BqH57Fa,IAA0B,yDrH67FvC,4BsH77Fa,IAA0B,sDtH87FvC,8BuH97Fa,IAA0B,wDvH+7FvC,8BwH/7Fa,IAA0B,wDxHg8FvC,8ByHh8Fa,IAA0B,wDzHi8FvC,8B0Hj8Fa,IAA0B,wD1Hk8FvC,8B2Hl8Fa,IAA0B,wD3Hm8FvC,8B4Hn8Fa,IAA0B,wD5Ho8FvC,8B6Hp8Fa,IAA0B,wD7Hq8FvC,8B8Hr8Fa,IAA0B,wD9Hs8FvC,iC+Ht8Fa,IAA0B,2D/Hu8FvC,kCgIv8Fa,IAA0B,4DhIw8FvC,sCiIx8Fa,IAA0B,gEjIy8FvC,qDkIz8Fa,IAA0B,+ElI08FvC,uCmI18Fa,IAA0B,iEnI28FvC,sDoI38Fa,IAA0B,gFpI48FvC,4CqI58Fa,IAA0B,sErI68FvC,yCsI78Fa,IAA0B,mEtI88FvC,0CuI98Fa,IAA0B,oEvI+8FvC,+BwI/8Fa,IAA0B,yDxIg9FvC,+ByIh9Fa,IAA0B,yDzIi9FvC,+B0Ij9Fa,IAA0B,yD1Ik9FvC,+B2Il9Fa,IAA0B,yD3Im9FvC,+B4In9Fa,IAA0B,yD5Io9FvC,+B6Ip9Fa,IAA0B,yD7Iq9FvC,+B8Ir9Fa,IAA0B,yD9Is9FvC,sB+It9Fa,IAA0B,gD/Iu9FvC,sBgJv9Fa,IAA0B,gDhJw9FvC,sBiJx9Fa,IAA0B,gDjJy9FvC,sBkJz9Fa,IAA0B,gDlJ09FvC,sBmJ19Fa,IAA0B,gDnJ29FvC,sBoJ39Fa,IAA0B,gDpJ49FvC,sBqJ59Fa,IAA0B,gDrJ69FvC,yBsJ79Fa,IAA0B,mDtJ89FvC,yBuJ99Fa,IAA0B,mDvJ+9FvC,yBwJ/9Fa,IAA0B,mDxJg+FvC,kCyJh+Fa,IAA0B,4DzJi+FvC,0B0Jj+Fa,IAA0B,oD1Jk+FvC,0B2Jl+Fa,IAA0B,oD3Jm+FvC,0B4Jn+Fa,IAA0B,oD5Jo+FvC,+B6Jp+Fa,IAA0B,yD7Jq+FvC,+B8Jr+Fa,IAA0B,yD9Js+FvC,+B+Jt+Fa,IAA0B,yD/Ju+FvC,+BgKv+Fa,IAA0B,yDhKw+FvC,+BiKx+Fa,IAA0B,yDjKy+FvC,+BkKz+Fa,IAA0B,yDlK0+FvC,sBmK1+Fa,IAA0B,gDnK2+FvC,sBoK3+Fa,IAA0B,gDpK4+FvC,2BqK5+Fa,IAA0B,qDrK6+FvC,2BsK7+Fa,IAA0B,qDtK8+FvC,kCuK9+Fa,IAA0B,4DvK++FvC,mCwK/+Fa,IAA0B,6DxKg/FvC,iCyKh/Fa,IAA0B,2DzKi/FvC,uB0Kj/Fa,IAA0B,iD1Kk/FvC,4B2Kl/Fa,IAA0B,sD3Km/FvC,4C4Kn/Fa,IAA0B,sE5Ko/FvC,iC6Kp/Fa,IAA0B,2D7Kq/FvC,iC8Kr/Fa,IAA0B,2D9Ks/FvC,iC+Kt/Fa,IAA0B,2D/Ku/FvC,iCgLv/Fa,IAA0B,2DhLw/FvC,4BiLx/Fa,IAA0B,sDjLy/FvC,4BkLz/Fa,IAA0B,sDlL0/FvC,4BmL1/Fa,IAA0B,sDnL2/FvC,4BoL3/Fa,IAA0B,sDpL4/FvC,4BqL5/Fa,IAA0B,sDrL6/FvC,4BsL7/Fa,IAA0B,sDtL8/FvC,4BuL9/Fa,IAA0B,sDvL+/FvC,4BwL//Fa,IAA0B,sDxLggGvC,oByLhgGa,IAA0B,8CzLigGvC,4B0LjgGa,IAA0B,sD1LkgGvC,uC2LlgGa,IAA0B,iE3LmgGvC,uC4LngGa,IAA0B,iE5LogGvC,uC6LpgGa,IAA0B,iE7LqgGvC,wC8LrgGa,IAA0B,kE9LsgGvC,wC+LtgGa,IAA0B,kE/LugGvC,wCgMvgGa,IAA0B,kEhMwgGvC,wCiMxgGa,IAA0B,kEjMygGvC,oCkMzgGa,IAA0B,8DlM0gGvC,qCmM1gGa,IAA0B,+DnM2gGvC,+BoM3gGa,IAA0B,yDpM4gG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","file":"static/js/main.b423360b.chunk.js","sourcesContent":["import { useCallback, useState } from 'react';\r\n\r\ninterface DialogController {\r\n open: boolean\r\n data?: any;\r\n handleClose: () => void;\r\n handleOpen: (data?: any) => void;\r\n}\r\n\r\ninterface DialogState {\r\n open: boolean;\r\n data: any;\r\n}\r\n\r\nexport const useDialog = (): DialogController => {\r\n const [state, setState] = useState({\r\n open: false,\r\n data: null\r\n });\r\n\r\n const handleOpen = useCallback((data = null): void => {\r\n setState({\r\n open: true,\r\n data\r\n });\r\n },[]);\r\n\r\n const handleClose = useCallback((): void => {\r\n setState({\r\n open: false,\r\n data: null\r\n });\r\n }, []);\r\n\r\n return {\r\n open: state.open,\r\n data: state.data,\r\n handleClose,\r\n handleOpen\r\n };\r\n};\r\n","import { useContext } from 'react';\r\nimport { TaskQueueContext } from '../providers';\r\n\r\nexport const useTaskQueue = () => useContext(TaskQueueContext);\r\n","import { useContext } from 'react';\r\nimport { ViewerContext } from '../providers';\r\n\r\nexport const useViewer = () => useContext(ViewerContext);\r\n","import { useContext } from 'react';\r\nimport { ActiveToolContext } from '../providers';\r\n\r\nexport const useActiveTool = () => useContext(ActiveToolContext);\r\n","import { useSelector } from \"react-redux\";\r\nimport { selectSessionID } from \"../redux/project-slice\";\r\n\r\n// eslint-disable-next-line react-hooks/rules-of-hooks\r\nexport const useUniqueProjectID = () => useSelector(selectSessionID);\r\n","import type { MutableRefObject } from 'react';\r\nimport { useCallback, useRef, useState } from 'react';\r\n\r\ninterface PopoverController {\r\n anchorRef: MutableRefObject;\r\n handleOpen: () => void;\r\n handleClose: () => void;\r\n handleToggle: () => void;\r\n open: boolean;\r\n}\r\n\r\nexport function usePopover(): PopoverController {\r\n const anchorRef = useRef(null);\r\n const [open, setOpen] = useState(false);\r\n\r\n const handleOpen = useCallback(\r\n (): void => {\r\n setOpen(true);\r\n },\r\n []\r\n );\r\n\r\n const handleClose = useCallback(\r\n (): void => {\r\n setOpen(false);\r\n },\r\n []\r\n );\r\n\r\n const handleToggle = useCallback(\r\n (): void => {\r\n setOpen((prevState) => !prevState);\r\n },\r\n []\r\n );\r\n\r\n return {\r\n anchorRef,\r\n handleClose,\r\n handleOpen,\r\n handleToggle,\r\n open\r\n };\r\n}\r\n","import { useContext } from 'react';\r\nimport { AuthContext } from '../providers';\r\n\r\nexport const useAuth = () => useContext(AuthContext);\r\n","import { useCallback, useState } from 'react';\r\n\r\ninterface ContextStateController {\r\n open: boolean;\r\n data?: any;\r\n anchorPosition: {left: number, top: number};\r\n handleClose(): void;\r\n handleOpen(event, data?): void;\r\n}\r\n\r\ninterface AnchorPosition {\r\n left: number | null;\r\n top: number | null;\r\n}\r\n\r\ninterface ContextState {\r\n open: boolean;\r\n data: any;\r\n anchorPosition: AnchorPosition;\r\n}\r\n\r\nexport const useContextMenu = (): ContextStateController => {\r\n const [state, setState] = useState({\r\n open: false,\r\n data: {},\r\n anchorPosition: undefined\r\n });\r\n\r\n const handleOpen = useCallback((event, data = {}) => {\r\n event.preventDefault();\r\n\r\n const anchorPosition = {\r\n left: event.clientX + 10,\r\n top: event.clientY - 20\r\n };\r\n\r\n setState({\r\n open: true,\r\n data,\r\n anchorPosition\r\n });\r\n },[]);\r\n\r\n const handleClose = useCallback((): void => {\r\n setState({\r\n open: false,\r\n data: {},\r\n anchorPosition: undefined\r\n });\r\n }, []);\r\n\r\n return {\r\n open: state.open,\r\n data: state.data,\r\n anchorPosition: state.anchorPosition,\r\n handleClose,\r\n handleOpen\r\n };\r\n};\r\n","import { useContext } from 'react';\r\nimport { GlobalSettingsContext } from '../providers';\r\n\r\nexport const useGlobalSettings = () => useContext(GlobalSettingsContext);\r\n","import { useContext } from 'react';\r\nimport { WebSocketContext } from '../providers';\r\n\r\nexport const useWebSockets = () => useContext(WebSocketContext);\r\n","import { useContext } from 'react';\r\nimport { BookmarksContext } from '../providers';\r\n\r\nexport const useBookmarks = () => useContext(BookmarksContext);\r\n","function webpackEmptyContext(req) {\n\tvar e = new Error(\"Cannot find module '\" + req + \"'\");\n\te.code = 'MODULE_NOT_FOUND';\n\tthrow e;\n}\nwebpackEmptyContext.keys = function() { return []; };\nwebpackEmptyContext.resolve = webpackEmptyContext;\nmodule.exports = webpackEmptyContext;\nwebpackEmptyContext.id = 1010;","import {Projection, Transform} from '../redux/projections-slice';\r\nimport {isStaticSite, storage} from \"../electron-modules\";\r\n\r\nexport const unknownProjectionMeters = {\r\n type: 'proj4',\r\n default: true,\r\n name: \"unknown-projection-m\",\r\n string: '+proj=utm +zone=10 +ellps=WGS84 +datum=WGS84 +units=m',\r\n} as Projection;\r\n\r\nexport const unknownProjectionFeet = {\r\n type: 'proj4',\r\n default: true,\r\n name: \"unknown-projection-ft\",\r\n string: '+proj=utm +zone=10 +ellps=WGS84 +datum=WGS84 +units=ft',\r\n} as Projection;\r\n\r\nexport const defaultProjection = {\r\n type: 'proj4',\r\n name: '',\r\n string: ''\r\n} as Projection;\r\n\r\nexport const defaultTransform = {\r\n origin: Array(3).fill(0),\r\n translation: Array(3).fill(0),\r\n rotation: 0,\r\n scale: 1\r\n} as Transform;\r\n\r\nexport const uniqueProjectionID = (text) : string => {\r\n return text.replace(/\\s/g, '.');\r\n};\r\n\r\nclass UserProjections {\r\n public data: Projection[] = [];\r\n private readonly file: string;\r\n\r\n constructor() {\r\n this.file = 'user-projections';\r\n this.load();\r\n }\r\n\r\n getByName(name: string): Projection {\r\n return this.data\r\n .find(projection => projection.name === name);\r\n }\r\n\r\n getByString(proj: string): Projection {\r\n return this.data\r\n .filter(projection => !projection.transform)\r\n .find(projection => projection.string === proj);\r\n }\r\n\r\n withUniqueName(projection: Projection) {\r\n let suffix = 0;\r\n let name = projection.name;\r\n\r\n while (true) {\r\n if (!userProjections.getByName(name)) break;\r\n suffix += 1;\r\n name = `${name} (${suffix})`;\r\n }\r\n\r\n return {...projection, name};\r\n }\r\n\r\n async save(data: Projection) {\r\n if (this.getByName(data.name)) return false;\r\n\r\n this.data.push(data);\r\n storage.setSync(this.file, this.data);\r\n\r\n this.load();\r\n return true;\r\n }\r\n\r\n load() {\r\n if (isStaticSite) return {};\r\n let data = storage.getSync(this.file);\r\n this.data = Array.isArray(data) ? data : [];\r\n }\r\n\r\n delete(name: string) {\r\n if (!this.getByName(name)) return;\r\n\r\n const rows = this.data.map(x => x.name);\r\n const index = rows.indexOf(name);\r\n this.data.splice(index, 1);\r\n\r\n storage.setSync(this.file, this.data);\r\n this.load();\r\n }\r\n\r\n update(name: string, data: Projection) {\r\n if (!this.getByName(name)) return false;\r\n\r\n this.delete(name);\r\n return this.save(data);\r\n }\r\n}\r\n\r\nexport const userProjections = new UserProjections();\r\n","import React, {useEffect} from 'react';\r\nimport clsx from 'clsx';\r\nimport Button from '@mui/material/Button';\r\nimport Dialog from '@mui/material/Dialog';\r\nimport IconButton from '@mui/material/IconButton';\r\nimport CloseIcon from '@mui/icons-material/Close';\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport { Theme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n userProjections,\r\n defaultProjection,\r\n defaultTransform,\r\n uniqueProjectionID\r\n} from './projections';\r\nimport {useState} from 'react';\r\nimport {\r\n AppBar,\r\n Checkbox,\r\n FormControlLabel,\r\n Grid,\r\n InputAdornment,\r\n InputLabel,\r\n MenuItem,\r\n Select,\r\n Tab,\r\n Tabs,\r\n TextField,\r\n Typography\r\n} from '@mui/material';\r\nimport LocalScene, { isValidProjection } from '../viewer/projections';\r\nimport {\r\n DropdownWithLabel,\r\n EnhancedTable,\r\n InputWithLabel,\r\n PromptDialog,\r\n TabPanel,\r\n TabProps\r\n} from '../components';\r\nimport { toast } from '../app';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useDialog, useUniqueProjectID } from '../hooks';\r\nimport { registerEvent } from '../electron-modules';\r\nimport { useTableState } from '../hooks/use-table-state';\r\nimport { EnhancedTableState } from '../types/enhanced-table';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n title: {\r\n margin: 0,\r\n padding: theme.spacing(1,2,1,2),\r\n },\r\n content: {\r\n padding: theme.spacing(0),\r\n paddingTop: \"0px !important\"\r\n },\r\n titleClose: {\r\n color: \"white\"\r\n },\r\n marginTop: {\r\n marginTop: theme.spacing(2)\r\n },\r\n marginBottom: {\r\n marginBottom: theme.spacing(2)\r\n },\r\n adornedEnd: {\r\n paddingRight: theme.spacing(0)\r\n },\r\n utmParent: {\r\n display: \"flex\"\r\n },\r\n utmZone: {\r\n flex: 2\r\n },\r\n utmButton: {\r\n flex: 1,\r\n marginLeft: theme.spacing(1)\r\n },\r\n button: {\r\n marginTop: theme.spacing(2),\r\n marginLeft: theme.spacing(1)\r\n },\r\n dropdown: {\r\n minWidth: 200,\r\n },\r\n formControl: {\r\n width: '100%'\r\n },\r\n buttonDiv: {\r\n textAlign: \"right\"\r\n },\r\n tabsParent: {\r\n display: \"flex\",\r\n padding: theme.spacing(0, 1)\r\n },\r\n tabsHeaders: {\r\n flex: 1\r\n }\r\n }),\r\n);\r\n\r\ninterface UserProjectionPanelProps {\r\n loadProjectionToEdit: (projectionData, newProjection) => void;\r\n setActiveTab: (value) => void;\r\n tableState: EnhancedTableState;\r\n}\r\n\r\nconst UserProjectionPanel = (props: UserProjectionPanelProps) => {\r\n const {loadProjectionToEdit, setActiveTab, tableState} = props;\r\n const {t} = useTranslation();\r\n\r\n const deleteDialog = useDialog();\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t('projections.projection-name'),\r\n searchable: true\r\n },\r\n {\r\n id: 'type',\r\n label: t('projections.projection-type')\r\n },\r\n {\r\n id: 'custom',\r\n label: t('projections.custom-parameters')\r\n },\r\n ];\r\n\r\n // Convert projections to data row\r\n const data = userProjections.data;\r\n\r\n const getRows = () => {\r\n return data.map(option => {\r\n return {\r\n id: uniqueProjectionID(option.name),\r\n name: option.name,\r\n custom: option.transform ? t('general.yes') : t('general.no'),\r\n type: option.type,\r\n disabled: LocalScene.isDataProjection(option.name)\r\n };\r\n });\r\n };\r\n\r\n const onClick = (row) => {\r\n const results = data.filter(x => x.name === row.name);\r\n if (results.length !== 1) {\r\n return;\r\n }\r\n\r\n const projection = results[0];\r\n loadProjectionToEdit(projection, false);\r\n setActiveTab(1);\r\n };\r\n\r\n const onDelete = (row) => {\r\n const results = data.filter(x => x.name === row.name);\r\n if (results.length !== 1) {\r\n return;\r\n }\r\n\r\n // Delete projection + force reload\r\n const projection = results[0];\r\n userProjections.delete(projection.name);\r\n toast.error(t(\"toast.projection-deleted\"));\r\n\r\n // Force projection list refresh\r\n setActiveTab(0);\r\n };\r\n\r\n const rows = getRows();\r\n\r\n const actions = [\r\n {\r\n title: t(\"buttons.delete\"),\r\n icon: ,\r\n onClick: (row) => {\r\n deleteDialog.handleOpen(row);\r\n }\r\n }\r\n ];\r\n\r\n let deletePrompt = \"\";\r\n if (deleteDialog.open) {\r\n deletePrompt = t('projections.do_you_want_to_delete_this_projection_row_name', {\r\n name: deleteDialog.data.name\r\n });\r\n }\r\n\r\n return (\r\n \r\n
\r\n {rows.length === 0 && (\r\n {t('projections.no-user-projections-have-been-added')}\r\n )}\r\n\r\n {(rows.length > 0) && ()}\r\n
\r\n\r\n {/* Delete Dialog */}\r\n {\r\n onDelete(deleteDialog.data);\r\n deleteDialog.handleClose();\r\n }}\r\n title={t(\"enhanced-table.prompt-delete-title\")}\r\n prompt={deletePrompt}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n
\r\n );\r\n};\r\n\r\ninterface EditPanelProps {\r\n setActiveTab: (value) => void;\r\n customProjection: any;\r\n hasTransform: boolean;\r\n newProjection: boolean;\r\n existingName: string;\r\n updateEditableValues: (values) => void\r\n setHasTransform: React.Dispatch;\r\n}\r\n\r\nconst EditPanel = (props: EditPanelProps) => {\r\n const {customProjection, updateEditableValues,\r\n hasTransform, setHasTransform,\r\n newProjection, setActiveTab, existingName} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const name = customProjection.name;\r\n const type = customProjection.type;\r\n const projString = customProjection.string;\r\n\r\n const transform = customProjection.transform;\r\n const origin = transform.origin;\r\n const translate = transform.translation;\r\n const rotation = transform.rotation;\r\n const scale = transform.scale;\r\n\r\n const handleChecked = (event) => {\r\n setHasTransform(event.target.checked);\r\n };\r\n\r\n const saveProjection = () => {\r\n // Create copy of our data\r\n let data = JSON.parse(JSON.stringify(customProjection));\r\n\r\n // Use trimmed versions of name and string\r\n data.name = nameTrim;\r\n data.string = stringTrim;\r\n\r\n if (!hasTransform) {\r\n delete data.transform;\r\n }\r\n\r\n const nameChanged = data.name !== existingName;\r\n const duplicateName = userProjections.getByName(data.name);\r\n\r\n // Check for duplicates if our name has changed\r\n if (nameChanged && duplicateName) {\r\n toast.error(t(\"toast.projection-duplicate\"));\r\n return;\r\n }\r\n\r\n // Check for valid projection string\r\n let validProjection = isValidProjection(projString);\r\n if (!validProjection) {\r\n toast.error(t(\"toast.projection-invalid\"));\r\n return;\r\n }\r\n\r\n const success = newProjection\r\n ? userProjections.save(data)\r\n : userProjections.update(existingName, data);\r\n\r\n if (!success) return;\r\n\r\n if (newProjection) {\r\n toast.success(t(\"toast.projection-added\"));\r\n } else {\r\n toast.success(t(\"toast.projection-updated\"));\r\n }\r\n\r\n setActiveTab(0);\r\n };\r\n\r\n // Remove excess whitespace from name and string\r\n let nameTrim = name.trim();\r\n let stringTrim = projString.trim();\r\n\r\n let originXError = origin[0] === \"\";\r\n let originYError = origin[1] === \"\";\r\n let originZError = origin[2] === \"\";\r\n\r\n let translateXError = translate[0] === \"\";\r\n let translateYError = translate[1] === \"\";\r\n let translateZError = translate[2] === \"\";\r\n\r\n let rotationError = rotation === \"\";\r\n let scaleError = scale === \"\";\r\n\r\n let canSubmit = (nameTrim !== \"\")\r\n && stringTrim !== \"\";\r\n\r\n if (hasTransform) {\r\n canSubmit = canSubmit\r\n && !originXError\r\n && !originYError\r\n && !originZError\r\n && !translateXError\r\n && !translateYError\r\n && !translateZError\r\n && !rotationError\r\n && !scaleError;\r\n }\r\n\r\n const updateType = (value) => {\r\n // Update projection type and clear projection string\r\n updateEditableValues({\r\n 'type': value,\r\n 'string': \"\"\r\n });\r\n };\r\n\r\n const updateName = (value) => {\r\n updateEditableValues({\"name\": value});\r\n };\r\n\r\n const updateString = (value) => {\r\n let string = (customProjection['type'] === \"epsg\")\r\n ? `EPSG:${value}`\r\n : value;\r\n\r\n updateEditableValues({\"string\": string});\r\n };\r\n\r\n const updateOrigin = (event, index) => {\r\n const value = parseFloat(event.target.value);\r\n let transform = customProjection.transform;\r\n transform['origin'][index] = isNaN(value) ? \"\" : value;\r\n\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n const updateTranslation = (event, index) => {\r\n const value = parseFloat(event.target.value);\r\n let transform = customProjection.transform;\r\n transform['translation'][index] = isNaN(value) ? \"\" : value;\r\n\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n const updateScale = (event) => {\r\n const value = parseFloat(event.target.value);\r\n let transform = customProjection.transform;\r\n transform['scale'] = isNaN(value) ? \"\" : value;\r\n\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n const updateRotation = (event) => {\r\n let value = parseFloat(event.target.value);\r\n let transform = customProjection.transform;\r\n transform['rotation'] = isNaN(value) ? \"\" : value;\r\n\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n return (\r\n
\r\n\r\n \r\n\r\n {/** Projection Type */}\r\n \r\n \r\n \r\n\r\n {/** Projection Name */}\r\n \r\n \r\n \r\n\r\n {/** Projection string (proj4) */}\r\n {type===\"proj4\" && (\r\n \r\n )}\r\n\r\n {/** Projection string (WKT) */}\r\n {type===\"wkt\" && (\r\n \r\n )}\r\n\r\n \r\n\r\n \r\n }\r\n label={t('projections.additional-parameters')}\r\n />\r\n\r\n {hasTransform && (\r\n {/* Origin */}\r\n \r\n \r\n {\r\n updateOrigin(e, 0);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\r\n }}\r\n error={originXError}\r\n />\r\n \r\n\r\n \r\n {\r\n updateOrigin(e, 1);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\r\n }}\r\n error={originYError}\r\n />\r\n \r\n\r\n \r\n {\r\n updateOrigin(e, 2);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\r\n }}\r\n error={originZError}\r\n />\r\n \r\n \r\n\r\n {/* Translation */}\r\n \r\n \r\n {\r\n updateTranslation(e, 0);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\r\n }}\r\n error={translateXError}\r\n />\r\n \r\n\r\n \r\n {\r\n updateTranslation(e, 1);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\r\n }}\r\n error={translateYError}\r\n />\r\n \r\n\r\n \r\n {\r\n updateTranslation(e, 2);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\r\n }}\r\n error={translateZError}\r\n />\r\n \r\n \r\n\r\n {/* Rotation and scaling */}\r\n \r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n )}\r\n\r\n
\r\n {!newProjection && ( {\r\n setActiveTab(0);\r\n }}\r\n className={classes.button}\r\n >\r\n {t(\"buttons.cancel\")}\r\n )}\r\n\r\n \r\n {newProjection ? t('projections.add-projection') : t('projections.save-changes')}\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\ninterface SearchPanelProps {\r\n loadProjectionToEdit: (projectionData, newProjection) => void;\r\n setActiveTab: (value) => void;\r\n tableState: EnhancedTableState;\r\n}\r\n\r\nconst SearchPanel = (props: SearchPanelProps) => {\r\n const {tableState, setActiveTab, loadProjectionToEdit} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const [type, setType] = useState(\"text\");\r\n const [searchTerm, setSearchTerm] = useState(\"\");\r\n const [hemisphere, setHemisphere] = useState(\"N\");\r\n const [searching, setSearching] = useState(false);\r\n const [searchResults, setSearchResults] = useState([]);\r\n\r\n const handleChange = (event) => {\r\n setType(event.target.value);\r\n };\r\n\r\n const handleHemisphere = (event) => {\r\n setHemisphere(event.target.value);\r\n };\r\n\r\n const handleString = (event) => {\r\n setSearchTerm(event.target.value);\r\n };\r\n\r\n const searchOnline = () => {\r\n if (searchTerm === \"\") {\r\n return;\r\n }\r\n\r\n let value = searchTerm;\r\n if (type === \"utm\") {\r\n value = `utm ${value}${hemisphere}`;\r\n }\r\n\r\n tableState.reset();\r\n getProjections(value);\r\n };\r\n\r\n const getProjections = (searchText, pageNumber = 1, previousResults = [], maxPageNumber = 10) => {\r\n if (pageNumber === 1) {\r\n setSearchResults([]);\r\n setSearching(true);\r\n }\r\n\r\n const text = type !== \"epsg\" ?\r\n `${searchText} kind:PROJCRS` :\r\n searchText;\r\n\r\n const url = \"https://epsg.io/?q=\" + text + \"&format=json&page=\" + pageNumber;\r\n\r\n fetch(url)\r\n .then(response => response.json())\r\n .then(data => {\r\n const results = data.results;\r\n const parsed = [];\r\n\r\n results.forEach(result => {\r\n if (type === \"epsg\") {\r\n if (result.code !== searchText) {\r\n return;\r\n }\r\n }\r\n\r\n if (result.proj4 === \"\") {\r\n return;\r\n }\r\n\r\n parsed.push(result);\r\n });\r\n\r\n const combined = [...previousResults, ...parsed];\r\n setSearchResults(combined);\r\n\r\n if ((results.length > 0) && (pageNumber < maxPageNumber)) {\r\n setTimeout(() =>{\r\n getProjections(searchText, pageNumber + 1, combined);\r\n }, 250);\r\n } else {\r\n setSearching(false);\r\n }\r\n });\r\n };\r\n\r\n const onClick = (row) => {\r\n loadProjectionToEdit({\r\n type: \"proj4\",\r\n name: row.name,\r\n string: row.proj4\r\n }, true);\r\n setActiveTab(1);\r\n };\r\n\r\n const getRows = () => {\r\n return searchResults.map(projection => {\r\n return {\r\n id: uniqueProjectionID(projection.name),\r\n name: projection.name as string,\r\n epsg: parseInt(projection.code),\r\n proj4: projection.proj4 as string,\r\n };\r\n });\r\n };\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t('projections.name')\r\n },\r\n {\r\n id: 'epsg',\r\n label: t('projections.epsg'),\r\n numeric: true\r\n },\r\n {\r\n id: 'proj4',\r\n label: t('projections.proj4-string')\r\n },\r\n ];\r\n\r\n const rows = getRows();\r\n\r\n return (\r\n
\r\n {/* Search Type */}\r\n
\r\n \r\n {t('projections.search-type')}\r\n \r\n \r\n {t('projections.text')}\r\n {t('projections.utm-zone')}\r\n {t('projections.epsg-code')}\r\n \r\n
\r\n\r\n {/* UTM Zone */}\r\n {type===\"utm\" && (
\r\n \r\n {t('projections.utm-zone')}\r\n \r\n }}\r\n className={clsx(classes.marginTop, classes.utmZone)}\r\n />\r\n\r\n \r\n {t('directions.north')}\r\n {t('directions.south')}\r\n \r\n\r\n
)}\r\n\r\n {/* EPSG Code */}\r\n {type===\"epsg\" && (EPSG:,\r\n }}\r\n className={classes.marginTop}\r\n />)}\r\n\r\n {/* Text Search */}\r\n {type===\"text\" && ()}\r\n\r\n {/* Search button */}\r\n
\r\n \r\n {searching ? t('projections.searching-epsg-io') : t('projections.search-online')}\r\n \r\n
\r\n\r\n {/* Results table */}\r\n {(rows.length > 0) && }\r\n
\r\n );\r\n};\r\n\r\ninterface StyledPanelProps {\r\n value: number;\r\n index: number;\r\n children: React.ReactNode;\r\n}\r\n\r\nconst StyledPanel = (props: StyledPanelProps) => {\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport const ProjectionsManager = () => {\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const projectionsDialog = useDialog();\r\n\r\n // Must be defined here to persist (dialog is not mounted)\r\n const userTableState = useTableState({defaultSort: \"name\"});\r\n const searchTableState = useTableState();\r\n\r\n const [existingName, setExistingName] = useState(\"\");\r\n const [newProjection, setNewProjection] = useState(false);\r\n const [activeTab, setTabValue] = useState(0);\r\n const [customProjection, setCustomProjection] = useState({});\r\n const [hasTransform, setHasTransform] = useState(false);\r\n\r\n const setActiveTab = (value) => {\r\n if (value === 0) {\r\n clearProjectionValues();\r\n }\r\n\r\n setTabValue(value);\r\n };\r\n\r\n const updateEditableValues = (newValues) => {\r\n const combined = {...customProjection, ...newValues};\r\n setCustomProjection(combined);\r\n };\r\n\r\n const clearProjectionValues = () => {\r\n loadProjectionToEdit(defaultProjection, true);\r\n };\r\n\r\n const loadProjectionToEdit = (projectionData, newProjection) => {\r\n const dataCopy = JSON.parse(JSON.stringify(projectionData));\r\n const hasTransform = dataCopy.hasOwnProperty(\"transform\");\r\n if (!hasTransform) {\r\n const transformCopy = JSON.parse(JSON.stringify(defaultTransform));\r\n dataCopy.transform = transformCopy;\r\n }\r\n\r\n setHasTransform(hasTransform);\r\n setCustomProjection({...dataCopy});\r\n setExistingName(dataCopy.name);\r\n setNewProjection(newProjection);\r\n };\r\n\r\n const handleChange = (event, newactiveTab) => {\r\n setActiveTab(newactiveTab);\r\n };\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n projectionsDialog.handleClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-projection-manager\", () => {\r\n projectionsDialog.handleOpen();\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n clearProjectionValues();\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!projectionsDialog.open) return;\r\n userProjections.load();\r\n }, [projectionsDialog.open]);\r\n\r\n return (\r\n
\r\n \r\n\r\n \r\n
\r\n \r\n \r\n {newProjection && ()}\r\n {!newProjection && ()}\r\n \r\n \r\n\r\n {/* Close button */}\r\n \r\n \r\n \r\n\r\n
\r\n
\r\n\r\n {/* Existing projections */}\r\n \r\n \r\n \r\n\r\n {/* Custom projections */}\r\n \r\n \r\n \r\n\r\n {/* Online projection search */}\r\n \r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n","import React, { useEffect, useState } from \"react\";\r\nimport { useDispatch, useSelector } from \"react-redux\";\r\nimport { CheckboxWithLabel, NeverAskCheckbox, SimpleDialog } from \"../components\";\r\nimport { sendCustomEvent } from \"../events\";\r\nimport { useDialog, useUniqueProjectID } from \"../hooks\";\r\nimport {\r\n Projection,\r\n selectDataProjection,\r\n updateDataProjection,\r\n updateViewProjection\r\n} from \"../redux/projections-slice\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { Grid, Pagination, Paper, Stack, Typography, useTheme } from \"@mui/material\";\r\nimport { resetAerialState, resetCameraState } from \"../redux/camera-slice\";\r\nimport { userProjections } from \".\";\r\nimport path from \"path\";\r\nimport { PythonExecutable } from \"../executable\";\r\n\r\nconst eventKey = \"las-projection\";\r\n\r\ninterface ProjectionValues {\r\n assetPaths: string[];\r\n resolve: Function\r\n}\r\n\r\ninterface ProjectionData {\r\n fileName: string;\r\n projection: Projection;\r\n}\r\n\r\nconst getProjection = (assetPaths: string[]) : Promise => {\r\n const exe = new PythonExecutable();\r\n\r\n return new Promise(resolve => {\r\n let projections: Projection[] = [];\r\n\r\n let commands = [\r\n \"-p\", \"decode_projection\",\r\n \"--input_paths\", assetPaths,\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (!jsonData) return;\r\n projections = jsonData;\r\n },\r\n onClose: () => {\r\n resolve(projections);\r\n }\r\n });\r\n });\r\n};\r\n\r\nconst ProjectionItem = (props: ProjectionData) => {\r\n const {fileName, projection} = props;\r\n\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n {projection && \r\n \r\n {t('projections.filename')}\r\n \r\n\r\n \r\n {fileName}\r\n \r\n\r\n \r\n {t('projections.projection-name')}\r\n \r\n\r\n \r\n {projection.name}\r\n \r\n\r\n \r\n {t('projections.projection_string')}\r\n \r\n\r\n \r\n {projection.string}\r\n \r\n }\r\n \r\n );\r\n};\r\n\r\nexport const ProjectionsDetector = () => {\r\n const dialog = useDialog();\r\n const dispatch = useDispatch();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {t} = useTranslation();\r\n\r\n const [items, setItems] = useState([]);\r\n const [saveProjection, setSaveProjection] = useState(false);\r\n const [neverAsk, setNeverAsk] = useState(true);\r\n const [needsCheck, setNeedsCheck] = useState(true);\r\n const [page, setPage] = useState(1);\r\n\r\n const dataProjection = useSelector(selectDataProjection);\r\n\r\n /** LAS projection event listener */\r\n useEffect(() => {\r\n const callback = async (event) => {\r\n const {assetPaths, resolve} = event.detail as ProjectionValues;\r\n\r\n if (!dataProjection.default || !needsCheck) {\r\n resolve();\r\n return;\r\n }\r\n\r\n const fileNames = assetPaths.map(x => path.basename(x));\r\n const projections = await getProjection(assetPaths);\r\n\r\n const data = [] as ProjectionData[];\r\n\r\n for (let i=0; i {\r\n document.removeEventListener(eventKey, callback);\r\n };\r\n }, [dataProjection, needsCheck]);\r\n\r\n useEffect(() => {\r\n /** Reset when new project is loaded */\r\n dialog.handleClose();\r\n setNeverAsk(true);\r\n setNeedsCheck(true);\r\n setItems([]);\r\n }, [uniqueProjectID]);\r\n\r\n const handlePage = (event: React.ChangeEvent, value: number) => {\r\n setPage(value);\r\n };\r\n\r\n const onSubmit = async () => {\r\n dispatch(resetCameraState(null));\r\n dispatch(resetAerialState(null));\r\n\r\n if (existingProjection) {\r\n dispatch(updateDataProjection(existingProjection));\r\n dispatch(updateViewProjection(existingProjection));\r\n } else {\r\n if (saveProjection) {\r\n userProjections.save(uniqueProjection);\r\n }\r\n\r\n dispatch(updateDataProjection(uniqueProjection));\r\n dispatch(updateViewProjection(uniqueProjection));\r\n }\r\n\r\n dialog.handleClose();\r\n setNeedsCheck(false);\r\n\r\n const resolve = dialog.data;\r\n setTimeout(resolve, 500);\r\n };\r\n\r\n const onClose = async () => {\r\n dialog.handleClose();\r\n setNeedsCheck(!neverAsk);\r\n\r\n const resolve = dialog.data;\r\n setTimeout(resolve, 500);\r\n };\r\n\r\n const selected = items[page - 1];\r\n const hasMultiple = items.length > 1;\r\n\r\n const projection = selected\r\n ? selected.projection\r\n : null;\r\n\r\n const existingProjection = projection\r\n ? userProjections.getByString(projection.string)\r\n : null;\r\n\r\n const uniqueProjection = projection\r\n ? userProjections.withUniqueName(projection)\r\n : null;\r\n\r\n const useExisting = !!existingProjection;\r\n const createNew = !existingProjection;\r\n\r\n const buttonText = existingProjection\r\n ? t('projections.use_projection')\r\n : t('projections.import_projection');\r\n\r\n return (\r\n \r\n {useExisting && \r\n {t('projections.las_projection_detected_existing')}\r\n }\r\n\r\n {createNew && \r\n {t('projections.las_projection_detected')}\r\n }\r\n\r\n \r\n \r\n\r\n {hasMultiple && }\r\n \r\n\r\n {createNew && \r\n \r\n }\r\n\r\n \r\n\r\n \r\n );\r\n};\r\n\r\nexport const checkLASProjections = (assetPaths: string[]) : Promise => {\r\n return new Promise(resolve => {\r\n sendCustomEvent(eventKey, {\r\n assetPaths: assetPaths,\r\n resolve: resolve\r\n });\r\n });\r\n};\r\n","import React from \"react\";\r\nimport { ThemeProvider, Theme, StyledEngineProvider } from \"@mui/material\";\r\nimport {AppWithAuth} from \"./app\";\r\nimport {store} from \"./redux/store\";\r\nimport {Provider} from \"react-redux\";\r\nimport './localization';\r\nimport {\r\n TaskQueueProvider,\r\n ViewerProvider,\r\n ActiveToolProvider,\r\n AuthProvider,\r\n BookmarksProvider,\r\n GlobalSettingsProvider,\r\n WebSocketProvider,\r\n BrandingProvider\r\n} from \"./providers\";\r\nimport { useBranding } from \"./hooks/use-branding\";\r\n\r\ndeclare module '@mui/styles/defaultTheme' {\r\n // eslint-disable-next-line @typescript-eslint/no-empty-interface\r\n interface DefaultTheme extends Theme {}\r\n}\r\n\r\nconst ThemedViewer = () => {\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst EngineViewer = () => {\r\n const branding = useBranding();\r\n const theme = branding.theme;\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport default ThemedViewer;","import React from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport EngineViewer from './engine-viewer';\r\n\r\nReactDOM.render(\r\n ,\r\n document.getElementById('root')\r\n);","import {configureStore, combineReducers, nanoid, MiddlewareArray} from '@reduxjs/toolkit';\r\nimport projectReducer from './project-slice';\r\nimport foldersReducer from './folders-slice';\r\nimport assetsReducer from './assets-slice';\r\nimport projectionsReducer from './projections-slice';\r\nimport settingsReducer from './settings-slice';\r\nimport cameraReducer from './camera-slice';\r\nimport bookmarksReducer, { Bookmark } from './bookmarks-slice';\r\nimport customLinksReducer from './custom-links-slice';\r\nimport thunk from 'redux-thunk';\r\nimport {\r\n isMobile,\r\n getModifiedSceneState,\r\n getModifiedAerialState,\r\n toBoolean\r\n} from '../viewer/utilities';\r\nimport { useDispatch } from 'react-redux';\r\nimport { setTagQueryString } from '../urls';\r\n\r\nconst appReducer = combineReducers({\r\n project: projectReducer,\r\n camera: cameraReducer,\r\n folders: foldersReducer,\r\n projections: projectionsReducer,\r\n settings: settingsReducer,\r\n assets: assetsReducer,\r\n bookmarks: bookmarksReducer,\r\n custom_links: customLinksReducer\r\n});\r\n\r\nconst updateStateFromParameters = (state, parameters) => {\r\n if (!parameters) return state;\r\n\r\n const {sceneState, aerialState} = state.camera;\r\n\r\n state.camera.sceneState = getModifiedSceneState(\r\n sceneState, parameters);\r\n\r\n state.camera.aerialState = getModifiedAerialState(\r\n aerialState, parameters);\r\n\r\n if (\"expanded\" in parameters) {\r\n const switched = toBoolean(parameters.expanded);\r\n state.settings.switched = switched;\r\n }\r\n\r\n return state;\r\n};\r\n\r\nconst updateStateFromBookmark = (state, parameters) => {\r\n if (!parameters) return state;\r\n\r\n if (\"bookmark\" in parameters) {\r\n const bookmarkID = parameters.bookmark;\r\n const bookmark = state.bookmarks.find(bookmark => {\r\n return bookmark.id === bookmarkID;\r\n }) as Bookmark;\r\n\r\n if (!bookmark) return state;\r\n\r\n state.settings = bookmark.settings;\r\n state.camera.aerialState = bookmark.aerialState;\r\n state.camera.sceneState = bookmark.sceneState;\r\n\r\n state.assets.forEach(asset => {\r\n asset.visible = bookmark.visibleAssets.includes(asset.id);\r\n });\r\n }\r\n\r\n return state;\r\n};\r\n\r\nconst updateStateFromTag = (state, parameters) => {\r\n if (!parameters) return state;\r\n\r\n if (\"tag\" in parameters) {\r\n setTagQueryString(parameters.tag);\r\n }\r\n\r\n return state;\r\n};\r\n\r\nconst rootReducer = (state, action) => {\r\n const newProject = action.type === 'NEW';\r\n const loadConfig = action.type === 'LOAD';\r\n const configInit = state === undefined;\r\n\r\n if (newProject) {\r\n state = undefined;\r\n } else if (loadConfig) {\r\n const {projectJSON} = action.payload;\r\n state = projectJSON;\r\n }\r\n\r\n state = appReducer(state, action);\r\n\r\n if (loadConfig) {\r\n // Modify project state based on URL parameters\r\n const {parameters} = action.payload;\r\n state = updateStateFromParameters(state, parameters);\r\n state = updateStateFromBookmark(state, parameters);\r\n state = updateStateFromTag(state, parameters);\r\n }\r\n\r\n if (configInit || newProject) {\r\n state = appReducer(state, {\r\n type: \"settings/applySavedDefaults\",\r\n payload: null\r\n });\r\n }\r\n\r\n if (newProject) {\r\n /** Create unique project ID */\r\n state = appReducer(state, {\r\n type: \"project/updateProjectID\",\r\n payload: nanoid()\r\n });\r\n }\r\n\r\n if (newProject || loadConfig) {\r\n /** Update unique session ID */\r\n state = appReducer(state, {\r\n type: \"project/updateSessionID\",\r\n payload: nanoid()\r\n });\r\n }\r\n\r\n // Asset drawer will be forced to closed\r\n // for mobile devices on initial load\r\n if (loadConfig && isMobile) {\r\n state = appReducer(state, {\r\n type: \"settings/changeAssetDrawerState\",\r\n payload: false\r\n });\r\n }\r\n\r\n if (loadConfig) {\r\n appReducer(state, {\r\n type: \"settings/changeDefaultSettings\",\r\n payload: null\r\n });\r\n }\r\n\r\n return state;\r\n};\r\n\r\nconst middleware = new MiddlewareArray()\r\n .concat(thunk);\r\n\r\nexport const store = configureStore({\r\n reducer: rootReducer,\r\n middleware\r\n});\r\n\r\nexport type AppDispatch = typeof store.dispatch;\r\n\r\n/** Custom useDispatch with proper typing for our store */\r\nexport const useAppDispatch: () => AppDispatch = useDispatch;","import { fse, isCloudSite, isStaticSite } from '../electron-modules';\r\nimport { isValidURL } from './utilities';\r\n\r\ninterface ByteRange {\r\n first: number\r\n last: number\r\n}\r\n\r\nexport const readFileJSON = (path: string): Promise => {\r\n if (isStaticSite || isCloudSite || isValidURL(path)) {\r\n return readJsonFromURL(path);\r\n } else {\r\n return readJsonElectron(path);\r\n }\r\n};\r\n\r\nexport const readFileText = (path: string): Promise => {\r\n if (isStaticSite || isCloudSite || isValidURL(path)) {\r\n return readTextFromURL(path);\r\n } else {\r\n return readTextElectron(path);\r\n }\r\n};\r\n\r\ninterface FileReadOptions {\r\n byteRange?: ByteRange;\r\n}\r\n\r\nexport const readFileBuffer = (path: string, options: FileReadOptions = {}) => {\r\n if (isStaticSite || isCloudSite || isValidURL(path)) {\r\n return readBufferFromURL(path, options);\r\n } else {\r\n return readBufferElectron(path, options);\r\n }\r\n};\r\n\r\nconst readJsonFromURL = async (path) => {\r\n let headers = {\r\n 'Content-Type': 'application/json'\r\n };\r\n\r\n const response = await fetch(path, {headers});\r\n\r\n if ((response.status === 404) || (response.status === 403)) {\r\n throw new Error(\"File Not Found\");\r\n }\r\n\r\n const data = await response.json();\r\n return data;\r\n};\r\n\r\nconst readJsonElectron = async (path) => {\r\n const data = await fse.readFile(path, 'utf-8');\r\n return JSON.parse(data);\r\n};\r\n\r\nconst readTextFromURL = async (path) => {\r\n let headers = {\r\n 'Content-Type': 'text/html; charset=utf-8'\r\n };\r\n\r\n const response = await fetch(path, {headers});\r\n\r\n if ((response.status === 404) || (response.status === 403)) {\r\n throw new Error(\"File Not Found\");\r\n }\r\n\r\n const data = await response.text();\r\n return data;\r\n};\r\n\r\nconst readTextElectron = async (path) => {\r\n return await fse.readFile(path, 'utf-8');\r\n};\r\n\r\nconst readBufferFromURL = async (path, options: FileReadOptions = {}) : Promise => {\r\n const {byteRange = null} = options;\r\n\r\n let headers = {};\r\n\r\n if (byteRange) {\r\n const first = byteRange.first;\r\n const last = byteRange.last - 1;\r\n headers['Content-Type'] = 'multipart/byteranges';\r\n headers['Range'] = `bytes=${first}-${last}`;\r\n }\r\n\r\n const response = await fetch(path, {headers});\r\n\r\n if ((response.status === 404) || (response.status === 403)) {\r\n throw new Error(\"File Not Found\");\r\n }\r\n\r\n const data = await response.arrayBuffer();\r\n\r\n if (byteRange) {\r\n const bytesRequested = byteRange.last - byteRange.first;\r\n if (data.byteLength !== bytesRequested) {\r\n throw new Error(\"Invalid number of bytes read\");\r\n }\r\n }\r\n\r\n if (data.byteLength === 0) {\r\n throw new Error(\"File Not Found\");\r\n }\r\n\r\n return data;\r\n};\r\n\r\nconst readBufferElectron = async (path, options: FileReadOptions = {}) : Promise => {\r\n const {byteRange = null} = options;\r\n\r\n if (byteRange) {\r\n const byteLength = byteRange.last - byteRange.first;\r\n const tmpBuffer = Buffer.alloc(byteLength);\r\n\r\n const file = await fse.open(path, \"r\");\r\n const {buffer, bytesRead} = await fse.read(\r\n file, tmpBuffer, 0, byteLength, byteRange.first);\r\n fse.close(file);\r\n\r\n if (bytesRead === 0) {\r\n throw new Error(\"No bytes read\");\r\n }\r\n\r\n return buffer.buffer;\r\n } else {\r\n const data = await fse.readFile(path);\r\n return data.buffer;\r\n }\r\n};\r\n","import { useCallback, useState } from \"react\";\r\nimport {\r\n EnhancedTableColumn,\r\n EnhancedTableRow,\r\n EnhancedTableState,\r\n TableSortDir\r\n} from \"../types/enhanced-table\";\r\nimport { debounce } from 'throttle-debounce';\r\n\r\ninterface TableStateProps {\r\n defaultSort?: string;\r\n pageSize?: number;\r\n}\r\n\r\nexport const useTableState = (props: TableStateProps = {}) : EnhancedTableState => {\r\n const {defaultSort, pageSize = 10} = props;\r\n\r\n const [query, setQuery] = useState(\"\");\r\n const [sortDir, setSortDir] = useState('asc');\r\n const [sortBy, setSortBy] = useState(defaultSort);\r\n const [pageNumber, setPageNumber] = useState(0);\r\n const [rowsPerPage, setRowsPerPage] = useState(pageSize);\r\n\r\n const reset = () => {\r\n setQuery(\"\");\r\n setSortDir(\"asc\");\r\n setSortBy(defaultSort);\r\n setPageNumber(0);\r\n setRowsPerPage(pageSize);\r\n };\r\n\r\n const descendingComparator = (a, b, sortBy) => {\r\n let compA = a[sortBy];\r\n let compB = b[sortBy];\r\n\r\n if (typeof compA === \"string\") {\r\n compA = compA.toLowerCase();\r\n }\r\n\r\n if (typeof compB === \"string\") {\r\n compB = compB.toLowerCase();\r\n }\r\n\r\n if (compB < compA) {\r\n return -1;\r\n } else if (compB > compA) {\r\n return 1;\r\n } else {\r\n return 0;\r\n }\r\n };\r\n\r\n const getComparator = (sortDir, sortBy) => {\r\n return sortDir === 'desc'\r\n ? (a, b) => descendingComparator(a, b, sortBy)\r\n : (a, b) => -descendingComparator(a, b, sortBy);\r\n };\r\n\r\n const handlePageNumberChange = (event, value) => {\r\n setPageNumber(value);\r\n };\r\n\r\n const handleRowsPerPageChange = (event) => {\r\n const value = parseInt(event.target.value, 10);\r\n setRowsPerPage(value);\r\n setPageNumber(0);\r\n };\r\n\r\n const handleSearchChange = useCallback(debounce(200, (value) => {\r\n setQuery(value);\r\n setPageNumber(0);\r\n }), []);\r\n\r\n const handleRequestSort = (event, value) => {\r\n const ascending = sortBy === value && sortDir === 'asc';\r\n setSortDir(ascending ? 'desc' : 'asc');\r\n setSortBy(value);\r\n };\r\n\r\n const handleSearch = (columns: EnhancedTableColumn[], rows: EnhancedTableRow[]) => {\r\n if (!query) return rows;\r\n\r\n const queryParts = query\r\n .split(\" \")\r\n .map(x => x.toLowerCase());\r\n\r\n const searchableColumns = columns\r\n .filter(column => column.searchable)\r\n .map(column => column.id);\r\n\r\n return rows.filter(row => {\r\n let valid = false;\r\n\r\n searchableColumns.forEach(column => {\r\n if (valid) return;\r\n\r\n const parts = row[column]\r\n .split(\" \")\r\n .map(x => x.toLowerCase());\r\n\r\n valid = valid || queryParts.filter(text => {\r\n return parts.filter(x => x.includes(text)).length > 0;\r\n }).length === queryParts.length;\r\n });\r\n\r\n return valid;\r\n });\r\n };\r\n\r\n const handleSort = (columns: EnhancedTableColumn[], rows: EnhancedTableRow[]) => {\r\n const column = columns.find(column => column.id === sortBy);\r\n if (!column) return rows;\r\n\r\n const comparator = column.sortBy\r\n ? getComparator(sortDir, column.sortBy)\r\n : getComparator(sortDir, sortBy);\r\n\r\n rows.sort(comparator);\r\n return rows;\r\n };\r\n\r\n const handlePages = (rows: EnhancedTableRow[]) => {\r\n return rows.slice(\r\n pageNumber * rowsPerPage,\r\n pageNumber * rowsPerPage + rowsPerPage\r\n );\r\n };\r\n\r\n return {\r\n query,\r\n rowsPerPage,\r\n pageNumber,\r\n sortDir,\r\n sortBy,\r\n handlePageNumberChange,\r\n handleRowsPerPageChange,\r\n handleSearchChange,\r\n handleRequestSort,\r\n handleSearch,\r\n handleSort,\r\n handlePages,\r\n reset\r\n };\r\n};","import {createSlice, nanoid, PayloadAction} from '@reduxjs/toolkit';\r\nimport api from '../api';\r\nimport {\r\n e57FileFormat,\r\n encompassFileFormat,\r\n potreeFileFormat,\r\n lasFileFormat\r\n} from '../file-extensions';\r\nimport { TagSize } from '../types/tags';\r\nimport { ServerType } from '../types/web-sources';\r\nimport { SceneCameraState } from './camera-slice';\r\n\r\nexport interface PlanarConfig {\r\n width: number;\r\n height: number;\r\n cx: number;\r\n cy: number;\r\n fx: number;\r\n fy: number;\r\n}\r\n\r\nexport interface CameraData {\r\n id: string;\r\n x: number;\r\n y: number;\r\n z: number;\r\n roll: number;\r\n pitch: number;\r\n yaw: number;\r\n path: string;\r\n name: string;\r\n config?: PlanarConfig;\r\n}\r\n\r\nexport interface OrthoData {\r\n imageBounds: [];\r\n imageDataSplit: [];\r\n imageData: string;\r\n imageSize: [number, number];\r\n imageSizeOriginal: [number, number];\r\n imagePath: string;\r\n scaleX: number;\r\n scaleY: number;\r\n}\r\n\r\nexport interface TagItemData {\r\n id: string;\r\n name: string;\r\n comment: string;\r\n date: string;\r\n x: number;\r\n y: number;\r\n z?: number;\r\n sceneState: SceneCameraState;\r\n annotations: TagAnnotation[];\r\n}\r\n\r\nexport interface TagAnnotation {\r\n id: string;\r\n definition: object;\r\n}\r\n\r\nexport interface TagData {\r\n size: TagSize;\r\n texture: string;\r\n items: TagItemData[];\r\n}\r\n\r\nexport interface LineworkLayerData {\r\n id: string;\r\n name: string;\r\n visible: boolean;\r\n color: string;\r\n}\r\n\r\nexport interface WebMapData {\r\n url: string;\r\n type: ServerType;\r\n public: boolean;\r\n layers: WebMapLayerData[];\r\n}\r\n\r\nexport interface WebMapLayerData {\r\n id: string;\r\n name: string;\r\n visible: boolean;\r\n identifier: string;\r\n}\r\n\r\ninterface XMLAlignment {\r\n id: string;\r\n name: string;\r\n length: number;\r\n staStart: number;\r\n about: string;\r\n geometry: object[];\r\n}\r\n\r\nexport interface XMLData {\r\n info: object;\r\n units: object;\r\n alignments: XMLAlignment[];\r\n enu: boolean;\r\n}\r\n\r\ntype assetData = OrthoData | CameraData[] | TagData\r\n | LineworkLayerData[] | XMLData | WebMapData\r\n\r\n\r\nexport interface Asset {\r\n id: string;\r\n name: string;\r\n path: string;\r\n saved: boolean;\r\n cloud: boolean;\r\n date: string;\r\n visible: boolean;\r\n folderID: string;\r\n type: AssetType;\r\n data: assetData;\r\n}\r\n\r\nexport interface WebSourceAsset extends Asset {\r\n type: AssetType.Webmap;\r\n data: WebMapData;\r\n}\r\n\r\nexport interface AssetInfo {\r\n name: string;\r\n path: string;\r\n folderID: string;\r\n type: AssetType;\r\n data?: assetData;\r\n}\r\n\r\nexport enum AssetType {\r\n LAS = 0,\r\n Encompass = 1,\r\n Panoramic = 2,\r\n Unknown = 3,\r\n OrthoMosaic = 4,\r\n Planar = 5,\r\n E57Points = 6,\r\n Tag = 7,\r\n IFC = 8,\r\n Potree = 9,\r\n SHP = 10,\r\n DXF = 11,\r\n LandXML = 12,\r\n Webmap = 13\r\n}\r\n\r\nexport const pointCloudType = (ext: string): AssetType => {\r\n if (ext === lasFileFormat) {\r\n return AssetType.LAS;\r\n } else if (ext === encompassFileFormat) {\r\n return AssetType.Encompass;\r\n } else if (ext === e57FileFormat) {\r\n return AssetType.E57Points;\r\n } else if (ext === potreeFileFormat) {\r\n return AssetType.Potree;\r\n } else {\r\n return AssetType.Unknown;\r\n }\r\n};\r\n\r\nconst getByID = (state, assetID: string) => {\r\n return state.find(asset => asset.id === assetID);\r\n};\r\n\r\nconst getAssetByTagID = (state, tagID: string): Asset => {\r\n for (let asset of state) {\r\n if (asset.type !== AssetType.Tag) continue;\r\n\r\n const tags = (asset.data as TagData).items;\r\n const tagIDs = tags.map(x => x.id);\r\n if (tagIDs.includes(tagID)) return asset;\r\n }\r\n};\r\n\r\nconst getAssetByWebMapLayerID = (state, layerID: string): Asset => {\r\n for (let asset of state) {\r\n if (asset.type !== AssetType.Webmap) continue;\r\n\r\n const layers = (asset.data as WebMapData).layers;\r\n const layerIDs = layers.map(x => x.id);\r\n if (layerIDs.includes(layerID)) return asset;\r\n }\r\n};\r\n\r\nconst getAssetByModelLayerID = (state, layerID: string): Asset => {\r\n for (let asset of state) {\r\n const isModelWithLayers = (asset.type === AssetType.DXF)\r\n || (asset.type === AssetType.SHP);\r\n if (!isModelWithLayers) continue;\r\n\r\n const layers = asset.data as LineworkLayerData[];\r\n const layerIDs = layers.map(x => x.id);\r\n if (layerIDs.includes(layerID)) return asset;\r\n }\r\n};\r\n\r\nconst getAssetPayload = (item: AssetInfo): Asset => {\r\n return {\r\n id: nanoid(),\r\n name: item.name,\r\n path: item.path,\r\n date: new Date().toISOString(),\r\n type: item.type,\r\n folderID: item.folderID,\r\n visible: true,\r\n saved: false,\r\n cloud: false,\r\n data: item.data\r\n } as Asset;\r\n};\r\n\r\nexport const assetsSlice = createSlice({\r\n name: 'assets',\r\n initialState: [] as Asset[],\r\n reducers: {\r\n addAsset: (state, action: PayloadAction) => {\r\n const asset = getAssetPayload(action.payload);\r\n state.push(asset);\r\n },\r\n addAssets: (state, action: PayloadAction) => {\r\n action.payload.forEach(payload => {\r\n const asset = getAssetPayload(payload);\r\n state.push(asset);\r\n });\r\n },\r\n updateAsset: (state, action: PayloadAction<{\r\n assetID: string,\r\n folderID?: string,\r\n visible?: boolean,\r\n name?: string,\r\n size?: TagSize,\r\n texture?: string,\r\n enu?: boolean\r\n }>) => {\r\n const {assetID, ...updates} = action.payload;\r\n\r\n const asset = getByID(state, assetID);\r\n if (!asset) return;\r\n\r\n for (let key in updates) {\r\n // Generic asset values\r\n if (asset.hasOwnProperty(key)) {\r\n asset[key] = updates[key];\r\n };\r\n\r\n // Data specific values\r\n if (asset.data && asset.data.hasOwnProperty(key)) {\r\n asset.data[key] = updates[key];\r\n };\r\n };\r\n },\r\n deleteAsset: (state, action: PayloadAction) => {\r\n return state.filter(asset => asset.id !== action.payload);\r\n },\r\n\r\n toggleFolderVisibility: (state, action) => {\r\n const {folderID, visible} = action.payload;\r\n const assets = state.filter(asset => asset.folderID === folderID);\r\n\r\n assets.forEach(asset => {\r\n asset.visible = visible;\r\n });\r\n },\r\n setVisibleAssets: (state, action) => {\r\n const visibleAssets = action.payload;\r\n state.forEach(asset => {\r\n asset.visible = visibleAssets.includes(asset.id);\r\n });\r\n },\r\n setVisibleFolder: (state, action) => {\r\n const folderID = action.payload;\r\n state.forEach(asset => {\r\n asset.visible = asset.folderID === folderID;\r\n });\r\n },\r\n setSavedState: (state, action) => {\r\n state.forEach(asset => {\r\n asset.saved = true;\r\n });\r\n },\r\n\r\n /** Model files */\r\n updateModelLayer: (state, action: PayloadAction<{\r\n layerID: string,\r\n visible?: boolean,\r\n color?: string\r\n }>) => {\r\n const {layerID, color, visible} = action.payload;\r\n const asset = getAssetByModelLayerID(state, layerID);\r\n if (!asset) return;\r\n\r\n const layers = asset.data as LineworkLayerData[];\r\n const layer = layers.find(x => x.id === layerID);\r\n if (!layer) return;\r\n\r\n if (\"visible\" in action.payload) {\r\n layer.visible = visible;\r\n }\r\n\r\n if (\"color\" in action.payload) {\r\n layer.color = color;\r\n }\r\n },\r\n\r\n /** Web sources */\r\n updateWebMapLayer: (state, action: PayloadAction<{\r\n layerID: string,\r\n visible: boolean\r\n }>) => {\r\n const {layerID, visible} = action.payload;\r\n const asset = getAssetByWebMapLayerID(state, layerID);\r\n if (!asset) return;\r\n\r\n const layers = (asset.data as WebMapData).layers;\r\n const layer = layers.find(x => x.id === layerID);\r\n if (!layer) return;\r\n\r\n layer.visible = visible;\r\n },\r\n\r\n /** Tag Items */\r\n createTags: (state, action: PayloadAction<{\r\n assetID: string;\r\n tags: TagItemData[];\r\n }>) => {\r\n const {assetID, tags} = action.payload;\r\n\r\n const asset = getByID(state, assetID);\r\n if (!asset) return;\r\n\r\n createTagsHelper(asset, tags);\r\n\r\n // Update cloud site\r\n api.tags.create(assetID, tags);\r\n },\r\n deleteTag: (state, action: PayloadAction) => {\r\n const tagID = action.payload;\r\n const asset = getAssetByTagID(state, tagID);\r\n if (!asset) return;\r\n\r\n deleteTagHelper(asset, tagID);\r\n\r\n // Update cloud site\r\n api.tags.delete(tagID);\r\n },\r\n updateTag: (state, action: PayloadAction<{\r\n tagID: string,\r\n name?: string,\r\n comment?: string,\r\n assetID?: string,\r\n annotations?: TagAnnotation[],\r\n sceneState?: SceneCameraState\r\n }>) => {\r\n const {tagID, ...updates} = action.payload;\r\n const asset = getAssetByTagID(state, tagID);\r\n if (!asset) return;\r\n\r\n const items = (asset.data as TagData).items;\r\n const tag = items.find(tag => tag.id === tagID);\r\n if (!tag) return;\r\n\r\n // Tags pulled from online might be missing certain attributes\r\n if (!tag.hasOwnProperty(\"annotations\")) {\r\n tag.annotations = [];\r\n }\r\n\r\n for (let key in updates) {\r\n if (tag.hasOwnProperty(key)) {\r\n tag[key] = updates[key];\r\n };\r\n };\r\n\r\n // Specific case for asset ID, since we store our tags in a strange way\r\n if (\"assetID\" in updates) {\r\n const newAssetID = updates.assetID;\r\n const newAsset = state.find(asset => asset.id === newAssetID);\r\n deleteTagHelper(asset, tagID);\r\n createTagsHelper(newAsset, [tag]);\r\n }\r\n\r\n // Update modified date\r\n tag.date = new Date().toISOString();\r\n\r\n // Update cloud site\r\n api.tags.update(tagID, {...updates, date: tag.date});\r\n },\r\n\r\n /** Websocket specific */\r\n wsCreateAsset: (state, action: PayloadAction) => {\r\n const asset = action.payload;\r\n if (getByID(state, asset.id)) return;\r\n\r\n state.push(asset);\r\n },\r\n wsUpdateAsset: (state, action: PayloadAction) => {\r\n const {id, ...updates} = action.payload;\r\n let asset = getByID(state, id);\r\n if (!asset) return;\r\n\r\n for (let key in updates) {\r\n if (asset.hasOwnProperty(key)) {\r\n asset[key] = updates[key];\r\n };\r\n };\r\n },\r\n wsDeleteAsset: (state, action: PayloadAction) => {\r\n const assetID = action.payload;\r\n return state.filter(asset => asset.id !== assetID);\r\n },\r\n }\r\n});\r\n\r\nconst deleteTagHelper = (asset: Asset, tagID: string) => {\r\n const items = (asset.data as TagData).items\r\n .filter(item => item.id !== tagID);\r\n\r\n asset.data = {\r\n ...asset.data,\r\n items\r\n } as TagData;\r\n};\r\n\r\nconst createTagsHelper = (asset: Asset, tags: TagItemData[]) => {\r\n const items = [...(asset.data as TagData).items, ...tags];\r\n\r\n asset.data = {\r\n ...asset.data,\r\n items\r\n } as TagData;\r\n};\r\n\r\n/** Create new asset */\r\nexport const createAsset = (options: {\r\n name: string;\r\n folderID: string;\r\n path?: string;\r\n type: AssetType;\r\n texture: string;\r\n size: TagSize;\r\n}) => {\r\n const {name, folderID, type, path=null} = options;\r\n\r\n return async (dispatch, getState) => {\r\n\r\n let assetData;\r\n\r\n if (type === AssetType.Tag) {\r\n assetData = {\r\n size: options.size,\r\n texture: options.texture,\r\n items: []\r\n } as TagData;\r\n }\r\n\r\n dispatch(assetsSlice.actions.addAsset({\r\n folderID,\r\n name,\r\n path,\r\n type,\r\n data: assetData\r\n }));\r\n\r\n const assets = getState().assets as Asset[];\r\n const [asset] = assets.slice(-1);\r\n\r\n if (type === AssetType.Tag) {\r\n await api.tags.createCollection(folderID, asset);\r\n }\r\n\r\n return asset;\r\n };\r\n};\r\n\r\n/** Delete asset */\r\nexport const deleteAsset = (assetID: string) => {\r\n return (dispatch, getState) => {\r\n const assets = getState().assets as Asset[];\r\n const asset = assets.find(asset => asset.id === assetID);\r\n if (!asset) return;\r\n\r\n dispatch(assetsSlice.actions.deleteAsset(assetID));\r\n\r\n if (asset.type === AssetType.Tag) {\r\n api.tags.deleteCollection(assetID);\r\n }\r\n };\r\n};\r\n\r\n/** Update asset values */\r\nexport const updateAsset = (options: {\r\n assetID: string,\r\n name?: string,\r\n visible?: boolean,\r\n folderID?: string,\r\n texture?: string,\r\n size?: TagSize,\r\n enu?: boolean\r\n}) => {\r\n const {assetID, ...updates} = options;\r\n\r\n return (dispatch, getState) => {\r\n const assets = getState().assets as Asset[];\r\n const asset = assets.find(asset => asset.id === assetID);\r\n if (!asset) return;\r\n\r\n dispatch(assetsSlice.actions.updateAsset(options));\r\n\r\n if (asset.type === AssetType.Tag) {\r\n api.tags.updateCollection(assetID, updates);\r\n }\r\n };\r\n};\r\n\r\nexport default assetsSlice.reducer;\r\n\r\nexport const {\r\n wsCreateAsset,\r\n wsUpdateAsset,\r\n wsDeleteAsset,\r\n addAsset,\r\n addAssets,\r\n createTags,\r\n setVisibleAssets,\r\n updateWebMapLayer,\r\n updateModelLayer,\r\n toggleFolderVisibility,\r\n updateTag,\r\n setVisibleFolder,\r\n setSavedState,\r\n deleteTag\r\n} = assetsSlice.actions;\r\n\r\nexport const selectAllAssets = state => {\r\n return state.assets as Asset[];\r\n};\r\n\r\nexport const getVisibleAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => asset.visible);\r\n};\r\n\r\nexport const getModelAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return (asset.type === AssetType.IFC)\r\n || (asset.type === AssetType.SHP)\r\n || (asset.type === AssetType.DXF);\r\n });\r\n};\r\n\r\nexport const getTagAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return asset.type === AssetType.Tag;\r\n });\r\n};\r\n\r\nexport const getPointCloudAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return (asset.type === AssetType.Encompass)\r\n || (asset.type === AssetType.LAS)\r\n || (asset.type === AssetType.E57Points)\r\n || (asset.type === AssetType.Potree);\r\n });\r\n};\r\n\r\nexport const getCameraFileAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return asset.type === AssetType.Panoramic\r\n || asset.type === AssetType.Planar;\r\n });\r\n};\r\n\r\nexport const getOrthoAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return asset.type === AssetType.OrthoMosaic;\r\n });\r\n};\r\n\r\nexport const getLandXMLAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return asset.type === AssetType.LandXML;\r\n });\r\n};\r\n\r\nexport const getWebMapAssets = (assets: Asset[]) => {\r\n return assets.filter(asset => {\r\n return asset.type === AssetType.Webmap;\r\n });\r\n};\r\n\r\n","import {createSlice, nanoid, PayloadAction} from '@reduxjs/toolkit';\r\nimport api from '../api';\r\nimport { AerialViewState, SceneCameraState } from './camera-slice';\r\nimport { SettingsState } from './settings-slice';\r\n\r\nexport interface Bookmark {\r\n id: string;\r\n name: string;\r\n date: string;\r\n position: number[];\r\n visible: boolean;\r\n visibleAssets: string[],\r\n settings: SettingsState;\r\n aerialState: AerialViewState;\r\n sceneState: SceneCameraState;\r\n}\r\n\r\nconst getByID = (state, bookmarkID: string) => {\r\n return state.find(bookmark => bookmark.id === bookmarkID);\r\n};\r\n\r\nexport const bookmarksSlice = createSlice({\r\n name: 'bookmarks',\r\n initialState: [] as Bookmark[],\r\n reducers: {\r\n createBookmark: (state, action: PayloadAction<{\r\n name: string,\r\n position: number[],\r\n visibleAssets: string[],\r\n settings: SettingsState,\r\n aerialState: AerialViewState,\r\n sceneState: SceneCameraState\r\n }>) => {\r\n const attributes = action.payload;\r\n\r\n const bookmark = {\r\n id: nanoid(),\r\n date: new Date().toISOString(),\r\n visible: true,\r\n ...attributes\r\n };\r\n\r\n state.push(bookmark);\r\n\r\n // Update cloud site\r\n api.bookmarks.create(bookmark);\r\n },\r\n updateBookmark: (state, action: PayloadAction<{\r\n bookmarkID: string,\r\n name?: string,\r\n position?: number[],\r\n visible?: boolean,\r\n visibleAssets?: string[],\r\n settings?: SettingsState,\r\n aerialState?: AerialViewState,\r\n sceneState?: SceneCameraState;\r\n }>) => {\r\n const {bookmarkID, ...updates} = action.payload;\r\n\r\n const bookmark = getByID(state, bookmarkID);\r\n if (!bookmark) return;\r\n\r\n for (let key in updates) {\r\n if (bookmark.hasOwnProperty(key)) {\r\n bookmark[key] = updates[key];\r\n };\r\n };\r\n\r\n // Update modified date\r\n bookmark.date = new Date().toISOString();\r\n\r\n // Update cloud site\r\n api.bookmarks.update(bookmarkID, {...updates, date: bookmark.date});\r\n },\r\n deleteBookmark: (state, action: PayloadAction) => {\r\n const bookmarkID = action.payload;\r\n const modified = state.filter(bookmark => bookmark.id !== bookmarkID);\r\n\r\n // Update cloud site\r\n api.bookmarks.delete(bookmarkID);\r\n\r\n return modified;\r\n },\r\n\r\n /** Websocket specific */\r\n wsCreateBookmark: (state, action: PayloadAction) => {\r\n const bookmark = action.payload;\r\n if (getByID(state, bookmark.id)) return;\r\n\r\n state.push(bookmark);\r\n },\r\n wsUpdateBookmark: (state, action: PayloadAction) => {\r\n const {id, ...updates} = action.payload;\r\n\r\n let bookmark = getByID(state, id);\r\n if (!bookmark) return;\r\n\r\n for (let key in updates) {\r\n if (bookmark.hasOwnProperty(key)) {\r\n bookmark[key] = updates[key];\r\n };\r\n };\r\n },\r\n wsDeleteBookmark: (state, action: PayloadAction) => {\r\n const bookmarkID = action.payload;\r\n return state.filter(bookmark => bookmark.id !== bookmarkID);\r\n },\r\n }\r\n});\r\n\r\nexport default bookmarksSlice.reducer;\r\n\r\nexport const {\r\n wsCreateBookmark,\r\n wsUpdateBookmark,\r\n wsDeleteBookmark,\r\n createBookmark,\r\n deleteBookmark,\r\n updateBookmark,\r\n} = bookmarksSlice.actions;\r\n\r\nexport const selectAllBookmarks = state => state.bookmarks as Bookmark[];\r\n","import proj4 from \"proj4\";\r\nimport nudged from \"nudged\";\r\nimport {transform} from 'ol/proj';\r\nimport {Projection, Transform} from '../redux/projections-slice';\r\nimport PCA from 'pca-js';\r\nimport { executeWithoutLogging } from \"./utilities\";\r\nimport {\r\n Euler,\r\n MathUtils,\r\n Matrix4,\r\n Quaternion,\r\n Vector3\r\n} from 'three';\r\nimport { AsyncWorkerPool } from \"./worker-pool\";\r\nimport { Units } from \"../types/project\";\r\n\r\nconst transformCache = {};\r\n\r\nconst unitsToValue = {\r\n \"m\": 1.0,\r\n \"ft\": 0.3048,\r\n \"us-ft\": 1200.0 / 3937.0\r\n};\r\n\r\nexport const latitudeLongitude = {\r\n type: \"proj4\",\r\n name: \"latlong\",\r\n string: \"+proj=longlat +ellps=WGS84 +datum=NAD83 +no_defs\"\r\n} as Projection;\r\n\r\nexport const webMercator = {\r\n type: \"proj4\",\r\n name: \"web mercator\",\r\n string: \"+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6378137 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\"\r\n} as Projection;\r\n\r\nconst workerPool = new AsyncWorkerPool(\"reproject-points.js\");\r\n\r\n/** @private */\r\nconst verifyProjection = (projection: Projection) => {\r\n const modified = {...projection};\r\n\r\n if (modified.type === \"proj4\") {\r\n modified.string = verifyProjectionString(modified);\r\n }\r\n\r\n modified.transform = verifyTransformObject(modified);\r\n\r\n return modified;\r\n};\r\n\r\ninterface TransformFunction {\r\n forward(coords: number[]): number[]\r\n inverse(coords: number[]): number[]\r\n}\r\n\r\n/** @private */\r\nconst getTransform = (projectionFrom: Projection, projectionTo: Projection) => {\r\n const transformKey = `${projectionFrom.string}-${projectionTo.string}`;\r\n\r\n let transform: TransformFunction;\r\n let heightScale: number;\r\n\r\n if (transformKey in transformCache) {\r\n transform = transformCache[transformKey].transform;\r\n heightScale = transformCache[transformKey].heightScale;\r\n } else {\r\n transform = proj4(projectionFrom.string, projectionTo.string);\r\n\r\n const projToMeters1 = projectionToMeters(projectionFrom);\r\n const projToMeters2 = projectionToMeters(projectionTo);\r\n heightScale = projToMeters2 / projToMeters1;\r\n\r\n transformCache[transformKey] = {transform, heightScale};\r\n }\r\n\r\n return {transform, heightScale};\r\n};\r\n\r\n/** Calculate transform paramters given local and transformed points */\r\nexport const estimateTransform = (estimator: string, inputValues, outputValues) => {\r\n const domain = inputValues.map(value => {\r\n return {x: value[0], y: value[1]};\r\n });\r\n\r\n const range = outputValues.map(value => {\r\n return {x: value[0], y: value[1]};\r\n });\r\n\r\n if (!estimator.includes(\"T\")) {\r\n console.error(\"Translation is required for estimator\");\r\n\r\n return {\r\n transform: null,\r\n errors: null\r\n };\r\n }\r\n\r\n const estimate = nudged.estimate({estimator, domain, range});\r\n const scale = nudged.transform.getScale(estimate);\r\n const rotation = nudged.transform.getRotation(estimate);\r\n const translation = nudged.transform.getTranslation(estimate);\r\n const transformed = nudged.point.transformMany(domain, estimate);\r\n\r\n // Calculate per-point difference\r\n const errors = [];\r\n for (let i=0; i => {\r\n return new Promise(async (resolve, reject) => {\r\n const values = {\r\n positions: points,\r\n projectionFrom,\r\n projectionTo\r\n };\r\n\r\n const {success, response} = await workerPool.postMessage(values);\r\n\r\n if (success) {\r\n resolve(response);\r\n } else {\r\n console.error(response);\r\n reject(response);\r\n }\r\n });\r\n};\r\n\r\n/** @private Reproject a single point. Internal use only */\r\nconst reprojectPoint = (position, projectionFrom: Projection, projectionTo: Projection): Vector3 => {\r\n position = position.isVector3\r\n ? position.toArray()\r\n : [...position];\r\n\r\n const rotateAxis = new Vector3(0, 0, 1);\r\n\r\n // Apply initial transformation\r\n if (projectionFrom.transform) {\r\n const {translation, rotation, scale, origin} = projectionFrom.transform;\r\n const angle = MathUtils.degToRad(rotation);\r\n\r\n position = new Vector3(...position)\r\n .sub(new Vector3(...translation))\r\n .applyAxisAngle(rotateAxis, -1 * angle)\r\n .divide(new Vector3(scale, scale, 1.0))\r\n .add(new Vector3(...origin))\r\n .toArray();\r\n }\r\n\r\n // Apply point reprojection\r\n if (projectionFrom.string !== projectionTo.string) {\r\n const {transform, heightScale} = getTransform(projectionFrom, projectionTo);\r\n position = transform.forward(position);\r\n\r\n // Height scaling is not applied by library\r\n position[2] /= heightScale;\r\n }\r\n\r\n // Apply secondary transformation\r\n if (projectionTo.transform) {\r\n const {translation, rotation, scale, origin} = projectionTo.transform;\r\n const angle = MathUtils.degToRad(rotation);\r\n\r\n position = new Vector3(...position)\r\n .sub(new Vector3(...origin))\r\n .multiply(new Vector3(scale, scale, 1.0))\r\n .applyAxisAngle(rotateAxis, angle)\r\n .add(new Vector3(...translation))\r\n .toArray();\r\n }\r\n\r\n return new Vector3(...position);\r\n};\r\n\r\nexport const closestUtmZone = (lonlat: Vector3, units: string) => {\r\n const utmZone = Math.ceil((180 + lonlat.x) / 6);\r\n\r\n const projection = {\r\n type: \"proj4\",\r\n name: `UTM ${utmZone}N (${units})`,\r\n string: `+proj=utm +zone=${utmZone} +ellps=WGS84 +datum=WGS84 +units=${units}`\r\n } as Projection;\r\n\r\n return {projection, utmZone};\r\n};\r\n\r\nclass ScenePointConverter {\r\n protected _sceneShift: Vector3;\r\n protected _sceneScale: Vector3;\r\n protected _dataProjection: Projection;\r\n protected _viewProjection: Projection;\r\n public dataToMeters: number\r\n public dataProjectionUnits = Units.Meters\r\n public viewProjectionUnits = Units.Meters\r\n private isLonLatProject = false;\r\n public initialized = false;\r\n\r\n get dataProjection() {\r\n return this._dataProjection;\r\n }\r\n\r\n get viewProjection() {\r\n return this._viewProjection;\r\n }\r\n\r\n get dataProjectionName() {\r\n return this.dataProjection.name;\r\n }\r\n\r\n get viewProjectionName() {\r\n return this.viewProjection.name;\r\n }\r\n\r\n get sceneOffset() {\r\n return this._sceneShift;\r\n }\r\n\r\n get sceneScale() {\r\n return this._sceneScale;\r\n }\r\n\r\n engineStyleProjection(projection: Projection) {\r\n const proj4String = projection.string;\r\n const hasTransform = projection.transform ? true : false;\r\n\r\n let results;\r\n if (hasTransform === false) {\r\n // Standard projection\r\n results = proj4String;\r\n } else {\r\n // Projection with transform (engine style projections are saved differently)\r\n const data = projection.transform;\r\n const origin = data.origin;\r\n const translation = data.translation;\r\n const rotation = data.rotation;\r\n const scale = data.scale;\r\n\r\n const transform = {\r\n origin_east: origin[0],\r\n origin_north: origin[1],\r\n origin_elevation: origin[2],\r\n translation_east: translation[0],\r\n translation_north: translation[1],\r\n translation_elevation: translation[2],\r\n rotation: rotation,\r\n scale_factor_h: scale,\r\n scale_factor_v: 1.0,\r\n };\r\n\r\n results = [proj4String, transform];\r\n }\r\n\r\n const projectionString = JSON.stringify(results);\r\n return projectionString;\r\n }\r\n\r\n isDataProjection(name) {\r\n if (!this._dataProjection) return false;\r\n return (this._dataProjection.name === name) ||\r\n (this._viewProjection.name === name);\r\n }\r\n\r\n setDataProjection(projection: Projection) {\r\n this._dataProjection = verifyProjection(projection);\r\n this.dataToMeters = projectionToMeters(this._dataProjection);\r\n this.dataProjectionUnits = projectionToUnits(this._dataProjection);\r\n this.isLonLatProject = isLonLatProjection(this._dataProjection);\r\n this.resetSceneShift();\r\n }\r\n\r\n setViewProjection(projection: Projection) {\r\n this._viewProjection = verifyProjection(projection);\r\n this.viewProjectionUnits = projectionToUnits(this._viewProjection);\r\n }\r\n\r\n resetSceneShift() {\r\n this.initialized = false;\r\n this._sceneShift = null;\r\n this._sceneScale = new Vector3(1.0, 1.0, 1.0);\r\n }\r\n\r\n checkForOffset(offset: Vector3) {\r\n if (this._sceneShift) return;\r\n\r\n this.initialized = true;\r\n this._sceneShift = offset.clone();\r\n\r\n if (this.isLonLatProject) {\r\n // Create an approximate latlon --> meters mapping based on the\r\n // offset point. Be aware that the accuracy is worse the further\r\n // away from the central point that you go\r\n\r\n let dx = haversineDistance(\r\n new Vector3(offset.x, offset.y, 0),\r\n new Vector3(offset.x + 1, offset.y, 0)\r\n );\r\n\r\n let dy = haversineDistance(\r\n new Vector3(offset.x, offset.y, 0),\r\n new Vector3(offset.x, offset.y + 1, 0)\r\n );\r\n\r\n this._sceneScale = new Vector3(dx, dy, 1.0);\r\n } else {\r\n this._sceneScale = new Vector3(1.0, 1.0, 1.0);\r\n }\r\n }\r\n\r\n offsetToScene(offset: Vector3) {\r\n this.checkForOffset(offset);\r\n let difference = new Vector3()\r\n .add(offset)\r\n .sub(this._sceneShift);\r\n\r\n return difference;\r\n }\r\n\r\n /** @private Convert from data projection to lonlat */\r\n _dataToLonLat(value) {\r\n return new ProjectedCoordinate(value, this._dataProjection).toLonLat();\r\n }\r\n\r\n /** @private Convert from data projection to aerial coordinates */\r\n _dataToAerial(value) {\r\n const lonLat = this._dataToLonLat(value);\r\n const mercator = reprojectPoint(lonLat, latitudeLongitude, webMercator);\r\n return mercator.toArray().slice(0,2);\r\n }\r\n\r\n /** @private Convert from scene coordinates (meters) to data projection */\r\n _sceneToData(value) {\r\n let position = new Vector3().copy(value);\r\n\r\n if (this.isLonLatProject) {\r\n position.divide(this._sceneScale);\r\n }\r\n\r\n position.add(this._sceneShift)\r\n .divideScalar(this.dataToMeters);\r\n\r\n return position;\r\n }\r\n\r\n /** @private Convert from data projection to scene coordinates (meters) */\r\n _dataToScene(value) {\r\n const position = new Vector3().copy(value)\r\n .multiplyScalar(this.dataToMeters);\r\n\r\n this.checkForOffset(position);\r\n position.sub(this._sceneShift);\r\n\r\n if (this.isLonLatProject) {\r\n position.multiply(this._sceneScale);\r\n }\r\n\r\n return new SceneCoordinate(position);\r\n }\r\n\r\n /** @private Convert from scene coordinates (meters) to web mercator */\r\n _sceneToAerial(value) {\r\n let dataProjection = this._sceneToData(value);\r\n return this._dataToAerial(dataProjection);\r\n }\r\n\r\n /** @private Convert from scene coordinates (meters) to lonlat */\r\n _sceneToLonLat(value) {\r\n let dataProjection = this._sceneToData(value);\r\n return this._dataToLonLat(dataProjection);\r\n }\r\n}\r\n\r\n/** Base Coordinate class is Vector3 with a few extras */\r\nclass Coordinate extends Vector3 {\r\n constructor(value = null) {\r\n let x = 0;\r\n let y = 0;\r\n let z = 0;\r\n\r\n if (value !== null) {\r\n if (value.isVector3 || (value instanceof Coordinate)) {\r\n x = value.x;\r\n y = value.y;\r\n z = value.z;\r\n } else {\r\n x = value[0];\r\n y = value[1];\r\n z = (value.length === 3) ? value[2] : 0;\r\n }\r\n }\r\n\r\n super(x,y,z);\r\n }\r\n\r\n get vector() {\r\n return new Vector3(this.x, this.y, this.z);\r\n }\r\n\r\n clone() {\r\n return new Vector3().copy(this);\r\n }\r\n}\r\n\r\n/** Coordinate in scene coordinates */\r\nexport class SceneCoordinate extends Coordinate {\r\n constructor(value = null) {\r\n super(value);\r\n }\r\n\r\n toAerial() {\r\n return LocalScene._sceneToAerial(this);\r\n }\r\n\r\n toLonLat() {\r\n return LocalScene._sceneToLonLat(this);\r\n }\r\n\r\n toGeocentric() {\r\n const lonlat = LocalScene._sceneToLonLat(this);\r\n return new LonLatCoordinate(lonlat).toGeocentric();\r\n }\r\n\r\n toDataProjection() {\r\n const value = LocalScene._sceneToData(this);\r\n return new DataProjectionCoordinate(value);\r\n }\r\n\r\n toViewProjection() {\r\n return this.toDataProjection().toViewProjection();\r\n }\r\n}\r\n\r\n/** Coordinate in geocentric */\r\nexport class GeocentricCoordinate extends Coordinate {\r\n constructor(value = null) {\r\n super(value);\r\n }\r\n\r\n toDataProjection() {\r\n const value = this.toProjection(LocalScene.dataProjection);\r\n return new DataProjectionCoordinate(value);\r\n }\r\n\r\n toViewProjection() {\r\n const value = this.toProjection(LocalScene.viewProjection);\r\n return new ViewProjectionCoordinate(value);\r\n }\r\n\r\n toScene() {\r\n const value = this.toProjection(LocalScene.dataProjection);\r\n return LocalScene._dataToScene(value);\r\n }\r\n\r\n toLonLat() {\r\n let x = this.x * 1.0;\r\n let y = this.y * 1.0;\r\n let z = this.z * 1.0;\r\n\r\n let a = 6378137; // wgs84\r\n let f = 1 / 298.257223563; // wgs84\r\n\r\n let b = a * (1 - f);\r\n let e = Math.sqrt((Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(a, 2));\r\n b = Math.sqrt(Math.pow(a, 2) * (1 - Math.pow(e, 2)));\r\n\r\n let ep = Math.sqrt((Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(b, 2));\r\n let p = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));\r\n let th = Math.atan2(a * z, b * p);\r\n let lon = Math.atan2(y, x);\r\n let lat = Math.atan2((z + Math.pow(ep, 2) * b * Math.pow(Math.sin(th), 3)),\r\n (p - Math.pow(e, 2) * a * Math.pow(Math.cos(th), 3)));\r\n let N = a / (Math.sqrt(1 - Math.pow(e, 2) * Math.pow(Math.sin(lat), 2)));\r\n let alt = p / Math.cos(lat) - N;\r\n lon = lon % (2 * Math.PI);\r\n\r\n if (Math.abs(x) < 1.0 && Math.abs(y) < 1.0) {\r\n alt = Math.abs(z) - b;\r\n }\r\n\r\n lon = lon * 180.0 / Math.PI;\r\n lat = lat * 180.0 / Math.PI;\r\n\r\n return new Vector3(lon, lat, alt);\r\n }\r\n\r\n toProjection(projection: Projection) {\r\n const lonlat = this.toLonLat();\r\n const value = reprojectPoint(lonlat, latitudeLongitude, projection);\r\n return new ProjectedCoordinate(value, projection);\r\n }\r\n}\r\n\r\n/** Coordinate in generic projection */\r\nexport class ProjectedCoordinate extends Coordinate {\r\n public projection: Projection;\r\n\r\n constructor(value, projection) {\r\n super(value);\r\n this.projection = projection;\r\n }\r\n\r\n toGeocentric() {\r\n const lonlat = this.toLonLat();\r\n return new LonLatCoordinate(lonlat).toGeocentric();\r\n }\r\n\r\n toLonLat() {\r\n return this.toProjection(latitudeLongitude);\r\n }\r\n\r\n toAerial() {\r\n const mercator = this.toProjection(webMercator);\r\n return mercator.toArray().slice(0,2);\r\n }\r\n\r\n toScene() {\r\n const value = this.toProjection(LocalScene.dataProjection);\r\n return LocalScene._dataToScene(value);\r\n }\r\n\r\n toProjection(projection) {\r\n if (this.projection === projection) return this;\r\n\r\n const value = reprojectPoint(this, this.projection, projection);\r\n return new ProjectedCoordinate(value, projection);\r\n }\r\n\r\n toViewProjection() {\r\n const value = this.toProjection(LocalScene.viewProjection);\r\n return new ViewProjectionCoordinate(value);\r\n }\r\n\r\n toDataProjection() {\r\n const value = this.toProjection(LocalScene.dataProjection);\r\n return new DataProjectionCoordinate(value);\r\n }\r\n\r\n distanceTo(value) {\r\n if (value instanceof ProjectedCoordinate) {\r\n let isLonLat1 = isLonLatProjection(this.projection);\r\n let isLonLat2 = isLonLatProjection(value.projection);\r\n if (isLonLat1 && isLonLat2) {\r\n return haversineDistance(this, value);\r\n }\r\n\r\n return this.vector.distanceTo(value.vector);\r\n }\r\n\r\n return this.vector.distanceTo(value);\r\n }\r\n}\r\n\r\n/** Coordinate in web mercator projection */\r\nexport class AerialCoordinate extends ProjectedCoordinate {\r\n constructor(value) {\r\n super(value, webMercator);\r\n }\r\n}\r\n\r\n/** Coordinate in latitude longitude */\r\nexport class LonLatCoordinate extends Coordinate {\r\n constructor(value) {\r\n super(value);\r\n }\r\n\r\n toGeocentric() {\r\n let lon = this.x * Math.PI / 180.0;\r\n let lat = this.y * Math.PI / 180.0;\r\n let alt = this.z;\r\n\r\n let a = 6378137;\r\n let f = 1 / 298.257223563;\r\n\r\n let b = a * (1 - f);\r\n let e = Math.sqrt((Math.pow(a, 2) - Math.pow(b, 2)) / Math.pow(a, 2));\r\n\r\n let N = a / Math.sqrt(1 - Math.pow(e, 2) * Math.pow(Math.sin(lat), 2));\r\n let x = (N + alt) * Math.cos(lat) * Math.cos(lon);\r\n let y = (N + alt) * Math.cos(lat) * Math.sin(lon);\r\n let z = (N * (Math.pow(b, 2) / Math.pow(a, 2)) + alt) * Math.sin(lat);\r\n\r\n return new GeocentricCoordinate([x, y, z]);\r\n }\r\n\r\n toProjection(projection) {\r\n let ecef = this.toGeocentric();\r\n return ecef.toProjection(projection);\r\n }\r\n\r\n toDataProjection() {\r\n let ecef = this.toGeocentric();\r\n return ecef.toDataProjection();\r\n }\r\n}\r\n\r\n/** Coordinate in project data projection */\r\nexport class DataProjectionCoordinate extends ProjectedCoordinate {\r\n constructor(value = null) {\r\n super(value, LocalScene.dataProjection);\r\n }\r\n}\r\n\r\n/** Coordinate in project view projection */\r\nexport class ViewProjectionCoordinate extends ProjectedCoordinate {\r\n constructor(value = null) {\r\n super(value, LocalScene.viewProjection);\r\n }\r\n}\r\n\r\n/** Spherical position, with theta/phi in degrees */\r\nexport class SphericalPosition {\r\n public radius;\r\n private _theta;\r\n private _phi;\r\n private limits;\r\n\r\n constructor() {\r\n this.radius = 0;\r\n this._theta = 0;\r\n this._phi = 0;\r\n this.limits = [0.01, 179.9];\r\n }\r\n\r\n get theta() {\r\n return (this._theta + 360) % 360;\r\n }\r\n\r\n get phi() {\r\n return (this._phi + 360) % 360;\r\n }\r\n\r\n round(value, precision) {\r\n let divisor = Math.pow(10, precision);\r\n return Math.round(value * divisor) / divisor;\r\n }\r\n\r\n fromVectors(pivot, orbit) {\r\n let offset = new Vector3().add(orbit).sub(pivot);\r\n let radius = offset.length();\r\n\r\n let theta = Math.atan2(offset.y, offset.x);\r\n theta = MathUtils.radToDeg(theta);\r\n\r\n let dist2d = Math.sqrt(Math.pow(offset.x, 2) + Math.pow(offset.y, 2));\r\n let phi = Math.atan2(dist2d, offset.z);\r\n phi = MathUtils.radToDeg(phi);\r\n phi = Math.max(this.limits[0], phi);\r\n phi = Math.min(this.limits[1], phi);\r\n\r\n this._theta = this.round(theta, 3);\r\n this._phi = this.round(phi, 3);\r\n this.radius = this.round(radius, 3);\r\n\r\n return this;\r\n }\r\n\r\n fromValues(radius, theta, phi) {\r\n this.radius = radius;\r\n this._theta = theta;\r\n this._phi = phi;\r\n\r\n return this;\r\n }\r\n\r\n toVector3() {\r\n let theta = MathUtils.degToRad(this.theta);\r\n let phi = MathUtils.degToRad(this.phi);\r\n\r\n let x = this.radius * Math.cos(theta) * Math.sin(phi);\r\n let y = this.radius * Math.sin(theta) * Math.sin(phi);\r\n let z = this.radius * Math.cos(phi);\r\n\r\n return new Vector3(x, y, z);\r\n }\r\n}\r\n\r\n/* Utility functions */\r\nexport const isValidProjection = (value: string) => {\r\n try {\r\n proj4(value);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport const getEulerInverse = (euler: Euler) => {\r\n let quaternion = new Quaternion();\r\n quaternion.setFromEuler(euler).invert();\r\n return new Euler().setFromQuaternion(quaternion);\r\n};\r\n\r\nexport const geometryToArray = (geometry, projection = null) => {\r\n let polygon = [];\r\n let coordinates = geometry.flatCoordinates;\r\n let totalPoints = coordinates.length / 2.0;\r\n\r\n for (var i = 0; i < totalPoints; i++) {\r\n let x = coordinates[2 * i + 0];\r\n let y = coordinates[2 * i + 1];\r\n let lonlat = transform([x, y, 0], 'EPSG:3857', 'EPSG:4326');\r\n let ecef = new LonLatCoordinate(lonlat).toGeocentric();\r\n\r\n if (projection) {\r\n let point = ecef.toProjection(projection);\r\n polygon.push(point.toArray());\r\n } else {\r\n polygon.push(ecef.toArray());\r\n }\r\n }\r\n\r\n return polygon;\r\n};\r\n\r\ninterface EigenResult {\r\n value: number;\r\n vector: Vector3\r\n}\r\n\r\nexport const calculateEigenVectors = (points: Vector3[]) => {\r\n const mean = new Vector3();\r\n points.forEach(vertex => {\r\n mean.add(vertex);\r\n });\r\n mean.divideScalar(points.length);\r\n\r\n const array = points.map(vertex => {\r\n return new Vector3()\r\n .add(vertex)\r\n .sub(mean)\r\n .toArray();\r\n });\r\n\r\n const eigen = executeWithoutLogging(() => {\r\n const result = PCA.getEigenVectors(array);\r\n\r\n return result.map(eigen => {\r\n return {\r\n value: eigen.eigenvalue,\r\n vector: new Vector3().fromArray(eigen.vector)\r\n };\r\n });\r\n }) as EigenResult[];\r\n\r\n return {eigen, mean};\r\n};\r\n\r\nexport const calculatePointsPCA = (points: Vector3[], flatten: boolean) => {\r\n let {eigen, mean} = calculateEigenVectors(points);\r\n\r\n let matrix = new Matrix4();\r\n matrix.makeBasis(\r\n eigen[0].vector,\r\n eigen[1].vector,\r\n eigen[2].vector\r\n );\r\n matrix.transpose();\r\n\r\n const adjusted = points.map(point => {\r\n return new Vector3()\r\n .copy(point)\r\n .sub(mean)\r\n .applyMatrix4(matrix);\r\n });\r\n\r\n if (!flatten) return adjusted;\r\n\r\n let flatArray = [];\r\n\r\n adjusted.forEach(point => {\r\n flatArray = [...flatArray, ...point.toArray()];\r\n });\r\n\r\n return flatArray;\r\n};\r\n\r\nexport const projectionToUnits = (projection: Projection) => {\r\n const unitLength = projectionToMeters(projection);\r\n\r\n let units: Units;\r\n\r\n switch (unitLength) {\r\n case unitsToValue[\"m\"]:\r\n units = Units.Meters;\r\n break;\r\n case unitsToValue[\"ft\"]:\r\n units = Units.Feet;\r\n break;\r\n case unitsToValue[\"us-ft\"]:\r\n units = Units.SurveyFeet;\r\n break;\r\n default:\r\n units = Units.Meters;\r\n break;\r\n }\r\n\r\n return units;\r\n};\r\n\r\nexport const projectionToMeters = (projection: Projection) => {\r\n if (!projection) return 1.0;\r\n\r\n const proj = proj4.Proj(projection.string);\r\n\r\n if (projection.type === \"wkt\") {\r\n return proj['UNIT'].convert;\r\n } else if (\"to_meter\" in proj) {\r\n return proj['to_meter'];\r\n } else if (\"units\" in proj) {\r\n const units = proj['units'] as string;\r\n return unitsToValue[units];\r\n }\r\n\r\n return 1.0;\r\n};\r\n\r\nexport const isLonLatProjection = (projection) => {\r\n const proj = proj4.Proj(projection.string);\r\n return proj['projName'] === \"longlat\";\r\n};\r\n\r\nconst haversineDistance = (P1: Vector3, P2: Vector3) => {\r\n let earthRadius = 6371000;\r\n\r\n let diffLat = (P2.y - P1.y) * Math.PI / 180;\r\n let diffLng = (P2.x - P1.x) * Math.PI / 180;\r\n\r\n let arc = Math.cos(P1.y * Math.PI / 180)\r\n * Math.cos(P2.y * Math.PI / 180)\r\n * Math.sin(diffLng / 2) * Math.sin(diffLng / 2)\r\n + Math.sin(diffLat / 2) * Math.sin(diffLat / 2);\r\n let line = 2 * Math.atan2(Math.sqrt(arc), Math.sqrt(1 - arc));\r\n\r\n let distance2d = earthRadius * line;\r\n let height = P2.z - P1.z;\r\n\r\n let distance = Math.pow(distance2d, 2) + Math.pow(height, 2);\r\n distance = Math.sqrt(distance);\r\n\r\n return distance;\r\n};\r\n\r\nconst verifyTransformObject = (data) => {\r\n let transform = data.transform;\r\n if (!transform) {\r\n return null;\r\n }\r\n\r\n if (transform.hasOwnProperty('translation_north')) {\r\n return {\r\n origin: [\r\n transform.origin_east,\r\n transform.origin_north,\r\n transform.origin_elevation ? transform.origin_elevation : 0\r\n ],\r\n translation: [\r\n transform.translation_east,\r\n transform.translation_north,\r\n transform.translation_elevation\r\n ],\r\n scale: transform.scale_factor_h,\r\n rotation: transform.rotation\r\n } as Transform;\r\n }\r\n\r\n return Object.assign({}, transform);\r\n};\r\n\r\nconst verifyProjectionString = (projection: Projection) => {\r\n let string = projection.string;\r\n\r\n // longlat projection is returned directly\r\n if (isLonLatProjection(projection)) {\r\n return string;\r\n }\r\n\r\n // Return EPSG codes directly\r\n if (string.toUpperCase().indexOf(\"EPSG\") === 0) {\r\n return string;\r\n }\r\n\r\n // Add missing fields\r\n if (string.indexOf(\"y_0\") === -1) {\r\n string = string + \" +y_0=0\";\r\n }\r\n\r\n if (string.indexOf(\"x_0\") === -1) {\r\n string = string + \" +x_0=0\";\r\n }\r\n\r\n if (string.indexOf(\"lon_0\") === -1) {\r\n string = string + \" +lon_0=0\";\r\n }\r\n\r\n if (string.indexOf(\"lat_0\") === -1) {\r\n string = string + \" +lat_0=0\";\r\n }\r\n\r\n string = string.split(\" +\").join(\" \");\r\n string = string.split(\" \").join(\" +\");\r\n if (string[0] !== \"+\") {\r\n string = \"+\" + string;\r\n }\r\n\r\n return string;\r\n};\r\n\r\nconst LocalScene = new ScenePointConverter();\r\nexport default LocalScene;\r\n","import classificationsShader from \"./viewer/textures/colormaps/classifications.png\";\r\n\r\nexport interface Classification {\r\n id: number;\r\n name: string;\r\n alias: Array<[]>;\r\n}\r\n\r\nconst numberOfDefinedClassifications = 19;\r\nexport const numberOfClassifications = 256;\r\n\r\nexport const classifications = [\r\n {\r\n id: 0,\r\n name: \"Never Classified\",\r\n alias: [\"never classified\", \"unclassified\"]\r\n },\r\n {\r\n id: 1,\r\n name: \"Unassigned\",\r\n alias: [\"unassigned\", \"snow\"]\r\n },\r\n {\r\n id: 2,\r\n name: \"Ground\",\r\n alias: ['ground', 'dtm', 'base', 'earth', 'dirt', 'land', 'd.t.m'],\r\n },\r\n {\r\n id: 3,\r\n name: \"Low Vegetation\",\r\n alias: ['low_vegetation','low vegetation', 'low_veg', 'low veg', 'lo veg','lo_veg', 'grass'],\r\n\r\n },\r\n {\r\n id: 4,\r\n name: \"Medium Vegetation\",\r\n alias: ['vegetation', 'tree', 'trees', 'bushes', 'lawn', 'forest', 'garden',\r\n 'gardens', 'arbor', 'flora', 'crops', 'crop', 'green', 'greenery',\r\n 'medium_vegetation', 'medium vegetation', 'med_veg', 'med veg', 'medium veg',\r\n 'medium_veg']\r\n },\r\n {\r\n id: 5,\r\n name: \"High Vegetation\",\r\n alias: ['high_vegetation', 'high vegetation', 'high_veg', 'high veg', 'hi veg',\r\n 'hi veg', 'canopy']\r\n },\r\n {\r\n id: 6,\r\n name: \"Building\",\r\n alias: ['building', 'buildings', 'structures', 'built', 'house']\r\n },\r\n {\r\n id: 7,\r\n name: \"Noise\",\r\n alias: ['noise', 'errors', 'multipass']\r\n },\r\n {\r\n id: 8,\r\n name: 'Model Key/Reserved',\r\n alias: ['lightpole', 'light pole', 'pole', 'power pole', 'powerpole', 'lightpoles',\r\n 'light poles', 'light_poles', 'power_pole', 'power_poles', 'model key', 'reserved']\r\n },\r\n {\r\n id: 9,\r\n name: \"Water\",\r\n alias: ['water', 'river', 'stream', 'sea', 'ocean', 'lake', 'bay','lagoon','lakes',\r\n 'rivers', 'streams', 'lagoons', 'waterway', 'waterways']\r\n },\r\n {\r\n id: 10,\r\n name: \"Rail\",\r\n alias: ['rail', 'railroad', 'rail road', 'train', 'trains', 'rail-road', 'rail_road',\r\n 'railway', 'railways', 'railroads']\r\n },\r\n {\r\n id: 11,\r\n name: \"Road Surface\",\r\n alias: ['road', 'roads', 'streets', 'highway', 'highways', 'avenues', 'pavement',\r\n 'road surface', 'road_surface', 'road surfaces', 'road_surfaces']\r\n },\r\n {\r\n id: 12,\r\n name: 'Overlap/Reserved',\r\n alias: ['overlap', 'overlap reserved', 'overlap_reserved']\r\n },\r\n {\r\n id: 13,\r\n name: \"Wire - Guard\",\r\n alias: ['wire guard', 'wire-guard', 'wires - guard', 'wire_guard']\r\n },\r\n {\r\n id: 14,\r\n name: \"Wire - Conductor\",\r\n alias: ['wire conductor', 'wire-conductor', 'wires - conductor', 'wire_conductor']\r\n },\r\n {\r\n id: 15,\r\n name: \"Transmission Tower\",\r\n alias: ['transmission tower', 'transmission-tower', 'transmission_tower']\r\n },\r\n {\r\n id: 16,\r\n name: \"Wire - Connector\",\r\n alias: ['powerlines', 'power lines', 'powerline', 'power line', 'power_lines',\r\n 'power_line', 'wire', 'wires', 'connectors', 'wire_connector', 'wire connector',\r\n 'wire_connectors', 'wire connectors']\r\n },\r\n {\r\n id: 17,\r\n name: \"Bridge Deck\",\r\n alias: ['bridge', 'bridge deck', 'bridge-deck', 'bridge_deck', 'bridges', 'overpass',\r\n 'overpasses', 'fly over', 'fly-over', 'fly_over']\r\n },\r\n {\r\n id: 18,\r\n name: \"High Noise\",\r\n alias: ['high noise', 'high_noise', 'high-noise', 'highnoise', 'sky']\r\n },\r\n ...Array.from(Array(numberOfClassifications - numberOfDefinedClassifications).keys()).map(key => ({id: key + numberOfDefinedClassifications, name: 'Reserved', alias:[]}))\r\n];\r\n\r\nexport const getClassificationColors = (): Promise => {\r\n return new Promise(resolve => {\r\n const image = new Image();\r\n\r\n image.onload = () => {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = image.width;\r\n canvas.height = image.height;\r\n\r\n const context = canvas.getContext('2d');\r\n context.drawImage(image, 0, 0);\r\n\r\n const imageData = context.getImageData(0, 0, canvas.width, canvas.height);\r\n let colors = [];\r\n\r\n for (let i = 0; i < classifications.length; i++) {\r\n let index = i * 4;\r\n\r\n let red = imageData.data[index] << 16;\r\n let green = imageData.data[index + 1] << 8;\r\n let blue = imageData.data[index + 2];\r\n\r\n const hexColor = `#${(red + blue + green).toString(16).padStart(6, '0')}`;\r\n colors.push(hexColor);\r\n }\r\n\r\n resolve(colors);\r\n };\r\n\r\n image.src = classificationsShader;\r\n });\r\n};","import tagsActions from \"./tags\";\r\nimport bookmarkActions from \"./bookmarks\";\r\nimport foldersActions from \"./folders\";\r\n\r\nconst actions = {\r\n folders: foldersActions,\r\n tags: tagsActions,\r\n bookmarks: bookmarkActions\r\n};\r\n\r\nexport default actions;","import { isCloudSite, cloudProjectID } from \"../electron-modules\";\r\nimport { withOriginalID } from \"../export/utils/misc\";\r\nimport { Folder } from \"../redux/folders-slice\";\r\nimport { engineCloudURL } from \"../urls\";\r\n\r\nconst createFolder = async (folder: Folder) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/projects/${cloudProjectID}/folders`;\r\n await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(withOriginalID(folder))\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst actions = {\r\n create: createFolder\r\n};\r\n\r\nexport default actions;","import { isCloudSite } from \"../electron-modules\";\r\nimport { withOriginalID } from \"../export/utils/misc\";\r\nimport { Asset, TagAnnotation, TagData, TagItemData } from \"../redux/assets-slice\";\r\nimport { SceneCameraState } from \"../redux/camera-slice\";\r\nimport { TagSize } from \"../types/tags\";\r\nimport { engineCloudURL } from \"../urls\";\r\n\r\n\r\nconst createTagCollection = async (folderID: string, asset: Asset) => {\r\n if (!isCloudSite) return;\r\n\r\n const {texture, size} = asset.data as TagData;\r\n const tagCollection = {...asset, texture, size};\r\n delete tagCollection.data;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/folders/${folderID}/tag-collections`;\r\n await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(withOriginalID(tagCollection))\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst deleteTagCollection = async (assetID: string) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/tag-collections/${assetID}`;\r\n await fetch(url, {method: \"DELETE\"});\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst updateTagCollection = async (assetID: string, options: {\r\n name?: string,\r\n visible?: boolean,\r\n size?: TagSize,\r\n texture?: string,\r\n}) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/tag-collections/${assetID}`;\r\n await fetch(url, {\r\n method: \"PUT\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(options)\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst createTags = async (assetID: string, tags: TagItemData[]) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/tag-collections/${assetID}/tags`;\r\n await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(tags.map(tag => withOriginalID(tag)))\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst updateTag = async (tagID: string, options: {\r\n name?: string,\r\n comment?: string,\r\n sceneState?: SceneCameraState,\r\n annotations?: TagAnnotation[],\r\n assetID?: string,\r\n date?: string\r\n}) => {\r\n if (!isCloudSite) return;\r\n\r\n if (\"assetID\" in options) {\r\n // api expects a different format\r\n options['assetId'] = options.assetID;\r\n delete options.assetID;\r\n }\r\n\r\n if (\"annotations\" in options) {\r\n // the update expects originalId\r\n (options as any)['annotations'] = options['annotations']\r\n .map(annotation => withOriginalID(annotation));\r\n }\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/tags/${tagID}`;\r\n await fetch(url, {\r\n method: \"PUT\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(options)\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst deleteTag = async (tagID: string) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/tags/${tagID}`;\r\n await fetch(url, {method: \"DELETE\"});\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst actions = {\r\n create: createTags,\r\n delete: deleteTag,\r\n update: updateTag,\r\n createCollection: createTagCollection,\r\n deleteCollection: deleteTagCollection,\r\n updateCollection: updateTagCollection\r\n};\r\n\r\nexport default actions;","import { cloudProjectID, isCloudSite } from \"../electron-modules\";\r\nimport { withOriginalID } from \"../export/utils/misc\";\r\nimport { Bookmark } from \"../redux/bookmarks-slice\";\r\nimport { AerialViewState, SceneCameraState } from \"../redux/camera-slice\";\r\nimport { SettingsState } from \"../redux/settings-slice\";\r\nimport { engineCloudURL } from \"../urls\";\r\n\r\nconst createBookmark = async (bookmark: Bookmark) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/projects/${cloudProjectID}/bookmarks`;\r\n await fetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(withOriginalID(bookmark))\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\ninterface UpdateOptions {\r\n name?: string,\r\n date?: string,\r\n position?: number[],\r\n visible?: boolean,\r\n visibleAssets?: string[],\r\n settings?: SettingsState,\r\n aerialState?: AerialViewState,\r\n sceneState?: SceneCameraState;\r\n}\r\n\r\nconst updateBookmark = async (bookmarkID: string, options: UpdateOptions) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/bookmarks/${bookmarkID}`;\r\n await fetch(url, {\r\n method: \"PUT\",\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n },\r\n body: JSON.stringify(options)\r\n });\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst deleteBookmark = async (bookmarkID: string) => {\r\n if (!isCloudSite) return;\r\n\r\n try {\r\n const url = `${engineCloudURL}/api/bookmarks/${bookmarkID}`;\r\n await fetch(url, {method: \"DELETE\"});\r\n } catch(err) {\r\n console.error(err);\r\n }\r\n};\r\n\r\nconst actions = {\r\n create: createBookmark,\r\n delete: deleteBookmark,\r\n update: updateBookmark,\r\n};\r\n\r\nexport default actions;","import isHtml from 'is-html';\r\n\r\nexport const asyncTimeout = (ms) => {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n};\r\n\r\nexport const isHTML = (value: any) => {\r\n return (typeof value === \"string\") ? isHtml(value) : false;\r\n};\r\n","export const sendCustomEvent = (type, detail) => {\r\n const event = new CustomEvent(type, {detail});\r\n document.dispatchEvent(event);\r\n};","import { Vector3 } from \"three\";\r\nimport { Viewer } from \"../main\";\r\n\r\nexport class ChangeDetector {\r\n private viewer: Viewer;\r\n\r\n private oldZoom = 0;\r\n private oldFov = 0;\r\n private oldLookatVector = new Vector3();\r\n private oldCameraPosition = new Vector3();\r\n private oldUpVector = new Vector3();\r\n private oldCameraID = null;\r\n private oldHeight = 0;\r\n private oldWidth = 0;\r\n private oldOrbitState = false;\r\n\r\n // Specific changes are exposed to the public\r\n public orbitChanged = false;\r\n public cameraChanged = false;\r\n public changed = false;\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n }\r\n\r\n get newFov() {\r\n return this.viewer.fov;\r\n }\r\n\r\n get newZoom() {\r\n return this.viewer.getAerialZoomLevel();\r\n }\r\n\r\n get newLookatVector() {\r\n return this.viewer.lookatVector;\r\n }\r\n\r\n get newUpVector() {\r\n return this.viewer.upVector;\r\n }\r\n\r\n get newCameraID() {\r\n return this.viewer.getCurrentCameraName();\r\n }\r\n\r\n get newHeight() {\r\n return this.viewer.height;\r\n }\r\n\r\n get newWidth() {\r\n return this.viewer.width;\r\n }\r\n\r\n get newOrbitState() {\r\n return this.viewer.orbitState;\r\n }\r\n\r\n get newCameraPosition() {\r\n const camera = this.viewer.camera;\r\n return camera.position.clone();\r\n }\r\n\r\n update() {\r\n this.changed = false;\r\n\r\n try {\r\n let lookatChanged = this.oldLookatVector\r\n .angleTo(this.newLookatVector) > 1e-5;\r\n let upChanged = this.oldUpVector\r\n .angleTo(this.newUpVector) > 1e-5;\r\n let positionChanged = this.oldCameraPosition\r\n .distanceTo(this.newCameraPosition) > 1e-5;\r\n let fovChanged = this.oldFov !== this.newFov;\r\n let zoomChanged = this.oldZoom !== this.newZoom;\r\n let cameraChanged = this.oldCameraID !== this.newCameraID;\r\n let heightChanged = this.oldHeight !== this.newHeight;\r\n let widthChanged = this.oldWidth !== this.newWidth;\r\n let orbitChanged = this.oldOrbitState !== this.newOrbitState;\r\n\r\n this.oldZoom = this.newZoom;\r\n this.oldFov = this.newFov;\r\n this.oldLookatVector = this.newLookatVector;\r\n this.oldCameraPosition = this.newCameraPosition;\r\n this.oldUpVector = this.newUpVector;\r\n this.oldCameraID = this.newCameraID;\r\n this.oldHeight = this.newHeight;\r\n this.oldWidth = this.newWidth;\r\n this.oldOrbitState = this.newOrbitState;\r\n\r\n this.cameraChanged = cameraChanged;\r\n this.orbitChanged = orbitChanged;\r\n\r\n this.changed = lookatChanged || upChanged || fovChanged\r\n || zoomChanged || cameraChanged || heightChanged\r\n || widthChanged || orbitChanged || positionChanged;\r\n } catch {\r\n this.changed = false;\r\n }\r\n };\r\n}","import { Units } from \"../../types/project\";\r\n\r\nexport class UnitConverter {\r\n private metresToSurveyFeetRatio = 1200 / 3937;\r\n private metresToFeetRatio = 0.3048;\r\n\r\n public convert(value, fromUnits: Units, toUnits: Units, fixedLength=null) {\r\n const allowedUnits = Object.values(Units);\r\n\r\n if (!allowedUnits.includes(fromUnits)) {\r\n throw TypeError(`Units must be ${allowedUnits}`);\r\n }\r\n\r\n if (!allowedUnits.includes(toUnits)) {\r\n throw TypeError(`Units must be ${allowedUnits}`);\r\n }\r\n\r\n if (isNaN(value)) {\r\n throw new Error('Value must be a number');\r\n }\r\n\r\n let convertedValue = value;\r\n\r\n if (fromUnits !== toUnits) {\r\n const ratio = fromUnits === Units.Feet\r\n ? this.metresToFeetRatio\r\n : this.metresToSurveyFeetRatio;\r\n\r\n if (fromUnits === Units.Feet || fromUnits === Units.SurveyFeet) {\r\n convertedValue *= ratio;\r\n }\r\n\r\n if (toUnits === Units.Feet || toUnits === Units.SurveyFeet) {\r\n convertedValue /= ratio;\r\n }\r\n }\r\n\r\n if (fixedLength !== null) {\r\n convertedValue = parseFloat(convertedValue.toFixed(fixedLength));\r\n }\r\n\r\n return convertedValue;\r\n }\r\n}\r\n","import {\r\n Vector3,\r\n MathUtils,\r\n PerspectiveCamera,\r\n Object3D,\r\n Box3,\r\n Vector2\r\n} from \"three\";\r\nimport linspace from \"exact-linspace\";\r\nimport isUrl from \"is-url\";\r\nimport * as olColor from 'ol/color';\r\nimport { Viewer } from \"../main\";\r\n\r\nexport const isMobile = /android|webos|iphone|ipad|ipod|blackberry|playbook|BB10|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase());\r\n\r\nexport const isValidURL = (path: string) => {\r\n return isUrl(encodeURI(path));\r\n};\r\n\r\nexport const getProjFactor = (fov, distance, screenHeight) => {\r\n let projFactor = 1.0 / Math.tan(fov / 2);\r\n projFactor /= distance;\r\n projFactor *= screenHeight / 2;\r\n return projFactor;\r\n};\r\n\r\nexport const getPointScale = (camera: PerspectiveCamera, mesh: Object3D, size=50) => {\r\n const meshPosition = new Vector3();\r\n mesh.getWorldPosition(meshPosition);\r\n\r\n const fov = MathUtils.degToRad(Math.max(20, camera.fov));\r\n const distance = Math.max(1.0, meshPosition.distanceTo(camera.position));\r\n const projFactor = getProjFactor(fov, distance, window.innerHeight);\r\n return size / projFactor;\r\n};\r\n\r\nexport const toVector2 = (vector: Vector3) => {\r\n return new Vector2(vector.x, vector.y);\r\n};\r\n\r\nexport const toScreenPosition = (viewer: Viewer, position: Vector3) => {\r\n var uv = new Vector3();\r\n uv.set(position.x, position.y, position.z);\r\n uv.project(viewer.camera);\r\n\r\n uv.x = (uv.x + 1) * (viewer.width / 2);\r\n uv.y = (-uv.y + 1) * (viewer.height / 2);\r\n\r\n uv.x = Math.round(uv.x);\r\n uv.y = Math.round(uv.y);\r\n uv.z = 0;\r\n\r\n return uv;\r\n};\r\n\r\nexport const eventToPixel = (event) => {\r\n let uv = new Vector3();\r\n\r\n if (event.offsetX) {\r\n // chrome,ie,safari\r\n uv.x = event.offsetX;\r\n uv.y = event.offsetY;\r\n } else {\r\n // firefox\r\n uv.x = event.layerX;\r\n uv.y = event.layerY;\r\n }\r\n\r\n return uv;\r\n};\r\n\r\nexport const randomHexColor = () => {\r\n return \"#000000\".replace(/0/g, function() {\r\n return (~~(Math.random() * 16)).toString(16);\r\n });\r\n};\r\n\r\nexport const closestPowerOfTwo = value => {\r\n if (value === 0) {\r\n return 0;\r\n }\r\n\r\n let power = Math.ceil(Math.log(value) / Math.log(2));\r\n let result = Math.pow(2, power) - 1;\r\n return result;\r\n};\r\n\r\nexport const roundDigit = (num, digits) => {\r\n let multiplyFactor = Math.pow(10, digits);\r\n return Math.round( num * multiplyFactor + Number.EPSILON ) / multiplyFactor;\r\n};\r\n\r\nexport const executeWithoutLogging = callback => {\r\n const logger = console.log;\r\n console.log = function() {};\r\n let response = callback();\r\n console.log = logger;\r\n return response;\r\n};\r\n\r\nexport const windowSafeDateISO = () => {\r\n const date = new Date();\r\n return date.toISOString()\r\n .slice(0, 19)\r\n .replace('T', ' ')\r\n .replace(/:/g, \"-\");\r\n};\r\n\r\nexport const chunkedArray = (array, size) => {\r\n let tmp = [...array];\r\n let results = [];\r\n while (tmp.length) {\r\n results.push(tmp.splice(0, size));\r\n }\r\n return results;\r\n};\r\n\r\nexport const coordinatesToArray = (points) => {\r\n let numPoints = points.length / 2;\r\n let newPoints = [];\r\n for (let i=0;i {\r\n if (start === end) {\r\n return new Array(steps).fill(start);\r\n }\r\n\r\n return linspace(start, end, steps);\r\n};\r\n\r\nexport const toBoolean = (value: string | number) : boolean => {\r\n const integerValue = typeof value === \"number\"\r\n ? value\r\n : parseInt(value);\r\n\r\n return !!integerValue;\r\n};\r\n\r\nexport const mergeBoundingBoxes = (boundingBoxes: Box3[]) => {\r\n let combined: Box3 = null;\r\n\r\n boundingBoxes.forEach(bbox => {\r\n if (!bbox) return;\r\n\r\n if (combined === null) {\r\n combined = new Box3(\r\n bbox.min.clone(),\r\n bbox.max.clone()\r\n );\r\n } else {\r\n combined = new Box3(\r\n new Vector3(\r\n Math.min(combined.min.x, bbox.min.x),\r\n Math.min(combined.min.y, bbox.min.y),\r\n Math.min(combined.min.z, bbox.min.z)\r\n ),\r\n new Vector3(\r\n Math.max(combined.max.x, bbox.max.x),\r\n Math.max(combined.max.y, bbox.max.y),\r\n Math.max(combined.max.z, bbox.max.z)\r\n )\r\n );\r\n }\r\n });\r\n\r\n return combined;\r\n};\r\n\r\n\r\nexport const getCoordinateBounds = (coordinates: number[][]) => {\r\n let min = [Infinity, Infinity, Infinity];\r\n let max = [-Infinity, -Infinity, -Infinity];\r\n\r\n coordinates.forEach(coordinate => {\r\n min[0] = Math.min(min[0], coordinate[0]);\r\n min[1] = Math.min(min[1], coordinate[1]);\r\n min[2] = Math.min(min[2], coordinate[2]);\r\n\r\n max[0] = Math.max(max[0], coordinate[0]);\r\n max[1] = Math.max(max[1], coordinate[1]);\r\n max[2] = Math.max(max[2], coordinate[2]);\r\n });\r\n\r\n return {\r\n min: new Vector3().fromArray(min),\r\n max: new Vector3().fromArray(max)\r\n };\r\n};\r\n\r\n\r\nexport const allIndexOf = (array, item) => {\r\n let index = array.indexOf(item);\r\n let indices = [];\r\n\r\n while (index !== -1) {\r\n indices.push(index);\r\n index = array.indexOf(item, ++index);\r\n }\r\n\r\n return indices;\r\n};\r\n\r\nexport const withOpacity = (color: string, opacity: number) => {\r\n let colorWithOpacity = olColor.asArray(color).slice();\r\n colorWithOpacity[3] = opacity;\r\n return colorWithOpacity;\r\n};\r\n","import { Plane, Vector3 } from \"three\";\r\n\r\nconst simplepolygon = require('simplepolygon');\r\n\r\nexport const pointInPolygon = (point, vertices) => {\r\n let numberOfVertices = vertices.length;\r\n let insidePolygon = false;\r\n\r\n let j = numberOfVertices - 1;\r\n for (var i = 0; i < numberOfVertices; i++) {\r\n let verti = vertices[i];\r\n let vertj = vertices[j];\r\n\r\n let dx = vertj.x - verti.x;\r\n let dy1 = point.y - verti.y;\r\n let dy2 = vertj.y - verti.y;\r\n\r\n let cond1 = (verti.y > point.y) !== (vertj.y > point.y);\r\n let cond2 = point.x < (dx * dy1 / dy2 + verti.x);\r\n\r\n // currently checks [boundMin, boundMax)\r\n\r\n if (cond1 && cond2) {\r\n insidePolygon = !insidePolygon;\r\n }\r\n j = i;\r\n }\r\n return insidePolygon;\r\n};\r\n\r\nexport const planeFromVectors = (directions) => {\r\n let normal = new Vector3();\r\n directions.forEach(vertex => {\r\n normal.add(vertex);\r\n });\r\n\r\n normal.divideScalar(directions.length);\r\n normal.setLength(1.0);\r\n\r\n return new Plane(normal);\r\n};\r\n\r\nexport const checkValidPolygon = (coordinates) => {\r\n try {\r\n // Unshifted points give false positives sometimes\r\n let origin = coordinates[0];\r\n let shifted = coordinates.map(x => {\r\n return [x[0]-origin[0], x[1]-origin[1]];\r\n });\r\n\r\n let poly = {\r\n type: \"Feature\",\r\n geometry: {\r\n type: \"Polygon\",\r\n coordinates: [shifted]\r\n }\r\n };\r\n\r\n let result = simplepolygon(poly);\r\n return result.features.length === 1;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n","import { MathUtils } from 'three';\r\nimport { transform } from 'ol/proj';\r\nimport { toast } from '../../app';\r\nimport {\r\n AerialViewState,\r\n initialSceneState,\r\n SceneCameraState\r\n} from '../../redux/camera-slice';\r\nimport { t } from '../../localization';\r\n\r\nexport const parseURLParams = (url: string) => {\r\n const hash = new URL(url).hash.substring(1);\r\n if (hash === \"\") return;\r\n\r\n const urlParams = new URLSearchParams(hash);\r\n const parameters = Object.fromEntries(urlParams);\r\n\r\n return parameters;\r\n};\r\n\r\nexport const getModifiedAerialState = (aerialState: AerialViewState, params) => {\r\n let modified = {...aerialState};\r\n\r\n if ((\"lon\" in params) && (\"lat\" in params)) {\r\n const lat = parseFloat(params.lat);\r\n const lon = parseFloat(params.lon);\r\n\r\n if (isNaN(lat) || isNaN(lon)) {\r\n toast.warning(t(\"toast.parse-error-lat-lon\"));\r\n } else {\r\n modified.center = transform([lon, lat], 'EPSG:4326', 'EPSG:3857');\r\n }\r\n }\r\n\r\n if (\"zoom\" in params) {\r\n const zoom = parseInt(params.zoom);\r\n\r\n if (isNaN(zoom)) {\r\n toast.warning(t(\"toast.parse-error-aerial-zoom\"));\r\n } else {\r\n modified.zoom = zoom;\r\n }\r\n }\r\n\r\n if (\"rotation\" in params) {\r\n const rotation = parseFloat(params.rotation);\r\n\r\n if (isNaN(rotation)) {\r\n toast.warning(t(\"toast.parse-error-aerial-rotate\"));\r\n } else {\r\n modified.rotation = MathUtils.degToRad(rotation);\r\n }\r\n }\r\n\r\n return modified;\r\n};\r\n\r\nexport const getModifiedSceneState = (sceneState: SceneCameraState, params) => {\r\n let modified = {...sceneState};\r\n\r\n if ((\"px\" in params) && (\"py\" in params) && (\"pz\" in params)) {\r\n if ((\"ox\" in params) && (\"oy\" in params) && (\"oz\" in params)) {\r\n const ox = parseFloat(params.ox);\r\n const oy = parseFloat(params.oy);\r\n const oz = parseFloat(params.oz);\r\n\r\n const px = parseFloat(params.px);\r\n const py = parseFloat(params.py);\r\n const pz = parseFloat(params.pz);\r\n\r\n const hasError = isNaN(ox)\r\n || isNaN(oy)\r\n || isNaN(oz)\r\n || isNaN(px)\r\n || isNaN(py)\r\n || isNaN(pz);\r\n\r\n if (hasError) {\r\n toast.warning(t(\"toast.parse-error-3d-mode\"));\r\n } else {\r\n return {\r\n ...initialSceneState,\r\n orbit: [ox, oy, oz],\r\n pivot: [px, py, pz]\r\n };\r\n }\r\n }\r\n }\r\n\r\n if ((\"x\" in params) && (\"y\" in params) && (\"z\" in params)) {\r\n const x = parseFloat(params.x);\r\n const y = parseFloat(params.y);\r\n const z = parseFloat(params.z);\r\n\r\n const hasError = isNaN(x)\r\n || isNaN(y)\r\n || isNaN(z);\r\n\r\n if (hasError) {\r\n toast.warning(t(\"toast.parse-error-xyz\"));\r\n } else {\r\n // Clear all values and update lookat\r\n modified = {\r\n ...initialSceneState,\r\n lookat: [x,y,z]\r\n };\r\n }\r\n }\r\n\r\n if (\"cam\" in params) {\r\n // Set camera and clear orbit values\r\n modified.camera = params.cam;\r\n modified.orbit = null;\r\n modified.pivot = null;\r\n }\r\n\r\n if ((\"theta\" in params) && (\"phi\" in params)) {\r\n const theta = parseFloat(params.theta);\r\n const phi = parseFloat(params.phi);\r\n\r\n if (isNaN(theta) || isNaN(phi)) {\r\n toast.warning(t(\"toast.parse-error-angle\"));\r\n } else {\r\n modified.angles = [\r\n MathUtils.degToRad(theta),\r\n MathUtils.degToRad(phi)\r\n ];\r\n }\r\n }\r\n\r\n if (\"fov\" in params) {\r\n const fov = parseFloat(params.fov);\r\n\r\n if (isNaN(fov)) {\r\n toast.warning(t(\"toast.parse-error-camera-fov\"));\r\n } else {\r\n modified.fov = fov;\r\n }\r\n }\r\n\r\n return modified;\r\n};\r\n","import {Vector as VectorSource} from \"ol/source\";\r\nimport {Vector as VectorLayer} from \"ol/layer\";\r\nimport {Polygon} from \"ol/geom\";\r\nimport {Feature} from \"ol\";\r\nimport { SceneCoordinate } from '../projections';\r\nimport { Stroke, Style } from \"ol/style\";\r\n\r\nconst mapBoundsStyle = new Style({\r\n stroke: new Stroke({\r\n color: 'rgba(0, 0, 0, 0.5)',\r\n width: 2\r\n }),\r\n});\r\n\r\nexport const boundsToMapLayer = (boundingBox) => {\r\n // Generate polygon layer from bounding box, based on scene coordinates\r\n let {min, max} = boundingBox;\r\n\r\n const polygonPoints = [\r\n new SceneCoordinate([min.x, min.y, 0]).toAerial(),\r\n new SceneCoordinate([min.x, max.y, 0]).toAerial(),\r\n new SceneCoordinate([max.x, max.y, 0]).toAerial(),\r\n new SceneCoordinate([max.x, min.y, 0]).toAerial(),\r\n new SceneCoordinate([min.x, min.y, 0]).toAerial()\r\n ];\r\n\r\n // Creating the minimap mesh layer\r\n let vectorsource = new VectorSource({\r\n wrapX: false\r\n });\r\n\r\n let geometry = new Polygon([polygonPoints], \"XY\");\r\n let feature = new Feature(geometry);\r\n vectorsource.addFeature(feature);\r\n\r\n let layer = new VectorLayer({\r\n zIndex: 1,\r\n source: vectorsource,\r\n style: mapBoundsStyle\r\n });\r\n\r\n return layer;\r\n};\r\n","import { fse, isCloudSite, isStaticSite } from \"../../electron-modules\";\r\nimport { isValidURL } from \"./misc-utils\";\r\n\r\nexport const fetchImage = async (path: string, signal: AbortSignal = null) => {\r\n let blob;\r\n\r\n if (isStaticSite || isCloudSite || isValidURL(path)) {\r\n const response = await fetch(path, {signal});\r\n blob = await response.blob();\r\n } else {\r\n const file = await fse.readFile(path);\r\n blob = new Blob([file]);\r\n }\r\n\r\n const image = await createImageBitmap(blob, {\r\n imageOrientation: 'flipY',\r\n colorSpaceConversion: \"none\"\r\n });\r\n\r\n return image;\r\n};\r\n\r\nexport const resizeImage = async (image: ImageBitmap, width: number, height: number) => {\r\n const resized = await createImageBitmap(image, {\r\n resizeWidth: width,\r\n resizeHeight: height,\r\n resizeQuality: \"low\",\r\n colorSpaceConversion: \"none\"\r\n });\r\n\r\n console.warn(`Image has been resized from (${image.width}x${image.height}) to (${width}x${height})`);\r\n\r\n image.close();\r\n\r\n return resized;\r\n};\r\n","import {MOUSE} from \"three\";\r\n\r\nexport enum ControlType {\r\n Encompass,\r\n Reverse,\r\n Autocad\r\n}\r\n\r\nexport const ControlModes = {\r\n 0: { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT },\r\n 1: { ORBIT: MOUSE.RIGHT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.LEFT },\r\n 2: { ORBIT: -1, ZOOM: -1, PAN: MOUSE.MIDDLE }\r\n};\r\n","import {createSlice, nanoid, PayloadAction} from '@reduxjs/toolkit';\r\n\r\nexport interface CustomURL {\r\n id: string;\r\n name: string;\r\n date: string;\r\n url: string;\r\n target: string;\r\n showInScene: boolean;\r\n showInAerial: boolean;\r\n }\r\n\r\nconst getByID = (state, linkID: string) => {\r\n return state.find(url => url.id === linkID);\r\n};\r\n\r\nexport const customLinkSlice = createSlice({\r\n name: 'custom_links',\r\n initialState: [] as CustomURL[],\r\n reducers: {\r\n createCustomLink: (state, action: PayloadAction<{\r\n name: string,\r\n url: string,\r\n target: string,\r\n showInScene: boolean,\r\n showInAerial: boolean\r\n }>) => {\r\n const attributes = action.payload;\r\n\r\n const customURL = {\r\n id: nanoid(),\r\n date: new Date().toISOString(),\r\n ...attributes\r\n };\r\n\r\n state.push(customURL);\r\n },\r\n updateCustomLink: (state, action: PayloadAction<{\r\n linkID: string,\r\n name?: string,\r\n url?: string,\r\n target?: string,\r\n showInScene?: boolean,\r\n showInAerial?: boolean\r\n }>) => {\r\n const {linkID, ...updates} = action.payload;\r\n\r\n const customURL = getByID(state, linkID);\r\n if (!customURL) return;\r\n\r\n for (let key in updates) {\r\n if (customURL.hasOwnProperty(key)) {\r\n customURL[key] = updates[key];\r\n };\r\n };\r\n\r\n // Update modified date\r\n customURL.date = new Date().toISOString();\r\n },\r\n deleteCustomLink: (state, action: PayloadAction) => {\r\n return state.filter(url => url.id !== action.payload);\r\n }\r\n }\r\n});\r\n\r\nexport default customLinkSlice.reducer;\r\n\r\nexport const {\r\n createCustomLink,\r\n updateCustomLink,\r\n deleteCustomLink\r\n} = customLinkSlice.actions;\r\n\r\nexport const selectAllCustomLinks = state => state.custom_links as CustomURL[];\r\n","export class AsyncWorkerPool {\r\n private fileName: string;\r\n private numWorkers = 1;\r\n private workers = [];\r\n private queue = [];\r\n\r\n constructor(fileName: string, numWorkers=2) {\r\n this.fileName = fileName;\r\n this.numWorkers = numWorkers;\r\n this.initWorkers();\r\n }\r\n\r\n initWorkers() {\r\n const filePath = `${process.env.PUBLIC_URL}/workers/${this.fileName}`;\r\n\r\n for (let i=0; i {\r\n return new Promise(resolve => {\r\n this.queue.push({message, transfer, resolve});\r\n this.processQueue();\r\n });\r\n }\r\n\r\n /** @private */\r\n processQueue() {\r\n if (this.workers.length === 0) return;\r\n if (this.queue.length === 0) return;\r\n\r\n const worker = this.workers.shift();\r\n const {message, transfer, resolve} = this.queue.shift();\r\n\r\n worker.onmessage = event => {\r\n resolve(event.data);\r\n\r\n // Return worker to array\r\n this.workers.push(worker);\r\n\r\n // Process next item in queue\r\n this.processQueue();\r\n };\r\n\r\n worker.postMessage(message, transfer);\r\n }\r\n}","export enum ProjectType {\r\n Standard = 0,\r\n Static = 1,\r\n Cloud = 2\r\n}\r\n\r\nexport enum AccessType {\r\n ViewOnly = 0,\r\n Standard = 1,\r\n Admin = 2\r\n}\r\n\r\nexport enum Units {\r\n Meters = \"m\",\r\n Feet = \"ft\",\r\n SurveyFeet = \"sft\"\r\n}","\r\nexport const solv3dPrimary = '#162031';\r\nexport const solv3dSecondary ='#DD0C29';\r\n\r\nexport const mosaicPrimary = '#A31C2E';\r\nexport const mosaicSecondary ='#33281F';","import { darken, lighten, createTheme as createMuiTheme } from \"@mui/material\";\r\nimport {\r\n solv3dPrimary,\r\n solv3dSecondary,\r\n mosaicPrimary,\r\n mosaicSecondary\r\n} from \"./colors\";\r\nimport { Brand } from \"../providers\";\r\n\r\nexport const themeSpacing = 8;\r\n\r\nexport const createTheme = (brand: Brand) => {\r\n const isMosaic = brand === \"mosaic\";\r\n\r\n const primaryColor = isMosaic\r\n ? mosaicPrimary\r\n : solv3dPrimary;\r\n\r\n const secondaryColor = isMosaic\r\n ? mosaicSecondary\r\n : solv3dSecondary;\r\n\r\n return createMuiTheme({\r\n spacing: themeSpacing,\r\n components: {\r\n MuiPopover: {\r\n styleOverrides: {\r\n root: {\r\n \"z-index\": \"1301 !important\"\r\n }\r\n }\r\n },\r\n MuiTooltip: {\r\n defaultProps: {\r\n disableInteractive: true\r\n },\r\n styleOverrides: {\r\n tooltip: {\r\n backgroundColor: \"rgba(0, 0, 0, 0.7)\",\r\n },\r\n arrow: {\r\n \"&::before\": {\r\n backgroundColor: \"rgba(0, 0, 0, 0.7)\",\r\n border: \"0px\"\r\n }\r\n }\r\n }\r\n },\r\n MuiDialogTitle: {\r\n styleOverrides: {\r\n root: {\r\n padding: themeSpacing,\r\n fontSize: \"1.0rem !important\"\r\n },\r\n }\r\n },\r\n MuiDialogContent: {\r\n styleOverrides: {\r\n root: {\r\n padding: 2 * themeSpacing,\r\n }\r\n }\r\n },\r\n MuiIconButton: {\r\n styleOverrides: {\r\n root: {\r\n padding: themeSpacing\r\n }\r\n }\r\n },\r\n MuiSelect: {\r\n defaultProps: {\r\n size: \"small\",\r\n variant: \"standard\"\r\n }\r\n },\r\n MuiTextField: {\r\n defaultProps: {\r\n size: \"small\",\r\n variant: \"standard\"\r\n }\r\n },\r\n MuiTabs: {\r\n defaultProps: {\r\n indicatorColor: \"secondary\",\r\n textColor: \"inherit\"\r\n }\r\n },\r\n MuiSwitch: {\r\n defaultProps: {\r\n size: \"small\",\r\n color: \"secondary\"\r\n }\r\n },\r\n MuiCheckbox: {\r\n defaultProps: {\r\n size: \"small\",\r\n color: \"secondary\"\r\n }\r\n },\r\n MuiRadio: {\r\n defaultProps: {\r\n size: \"small\",\r\n color: \"secondary\"\r\n }\r\n }\r\n },\r\n palette: {\r\n primary: {\r\n main: primaryColor,\r\n light: lighten(primaryColor, 0.25),\r\n dark: darken(primaryColor, 0.25)\r\n },\r\n secondary: {\r\n main: secondaryColor,\r\n light: lighten(secondaryColor, 0.25),\r\n dark: darken(secondaryColor, 0.25)\r\n },\r\n mode: \"light\"\r\n },\r\n mixins: {\r\n toolbar: {\r\n // override default\r\n }\r\n }\r\n });\r\n};\r\n","import { Coordinate } from \"ol/coordinate\";\r\n\r\nexport enum VolumeType {\r\n MultiPlane,\r\n LowestPlane\r\n}\r\n\r\nexport enum SamplingRate {\r\n High=0.25,\r\n Medium=0.5,\r\n Low=1.0\r\n}\r\n\r\nexport enum MeasureType {\r\n None=\"none\",\r\n Length=\"length\",\r\n SnapUp=\"snap-up\",\r\n SnapDown=\"snap-down\",\r\n Height=\"height\",\r\n Point=\"point\",\r\n Area=\"area\",\r\n Volume=\"volume\",\r\n Station=\"station_measurement\"\r\n}\r\n\r\nexport enum AerialMeasureType {\r\n Spherical,\r\n Planar\r\n}\r\n\r\nexport interface AerialSegment {\r\n midpoint: Coordinate;\r\n length: number\r\n}\r\n\r\nexport enum MeasureExportType {\r\n Data=\"dat\",\r\n CSV=\"csv\",\r\n DXF=\"dxf\",\r\n Shapefile=\"shp\"\r\n}","import { t } from \"./localization\";\r\n\r\nexport const LocalizedFileFilter = (key: string, extensions: string[]) => {\r\n return [{\r\n get name() {\r\n return t(key);\r\n },\r\n extensions\r\n }];\r\n};\r\n\r\nexport const getCombinedExtension = (key, filters) => {\r\n let extensions = [];\r\n filters.forEach(filter => {\r\n if (!filter) return;\r\n filter.forEach(x => {\r\n extensions = [...extensions, ...x.extensions];\r\n });\r\n });\r\n\r\n return [{\r\n get name() {\r\n return t(key);\r\n },\r\n extensions\r\n }];\r\n};\r\n\r\nexport const lasFileFormat = \"las\";\r\nexport const encompassFileFormat = \"idx\";\r\nexport const e57FileFormat = \"e57\";\r\nexport const potreeFileFormat = \"bin\";\r\nexport const pngFileFormat = 'png';\r\n\r\nexport const pngFilter = LocalizedFileFilter(\r\n 'dialog.extension-image-files-png', [pngFileFormat]);\r\n\r\nexport const pointCloudFileFormats = [lasFileFormat,\r\n encompassFileFormat, e57FileFormat, potreeFileFormat];\r\n\r\nexport const pointCloudFilter = LocalizedFileFilter(\r\n \"dialog.extension-pointclouds\", pointCloudFileFormats);\r\n\r\nexport const configFileType = \"json\";\r\nexport const configFilter = LocalizedFileFilter(\r\n \"dialog.extension-project\", [configFileType]);\r\n\r\nexport const customURLFileType = \"json\";\r\nexport const customURLFilter = LocalizedFileFilter(\r\n \"dialog.custom-url\", [customURLFileType]);\r\n\r\nexport const imageOrthoFormat = ['tif', 'tiff'];\r\nexport const imageOrthoFilter = LocalizedFileFilter(\r\n \"dialog.extension-ortho\", imageOrthoFormat);\r\n\r\nexport const imageCSVFormat = ['csv', 'txt', 'rzml'];\r\nexport const imageCSVFilter = LocalizedFileFilter(\r\n \"dialog.extension-images\", imageCSVFormat);\r\n\r\nexport const projFileFormat = ['eprj'];\r\n\r\nexport const imagePlanarFormat = ['plnr'];\r\nexport const imagePlanarFilter = LocalizedFileFilter(\r\n \"dialog.extension-planar\", imagePlanarFormat);\r\n\r\nexport const csvExportFilter = LocalizedFileFilter(\r\n \"dialog.extension-csv\", [\"csv\"]);\r\n\r\nexport const cameraMatrixFilter = LocalizedFileFilter(\r\n \"dialog.extension-4x4\", [\"4x4\"]);\r\n\r\nexport const measureDataFormat = \"3dm\";\r\nexport const measureDataFilter = LocalizedFileFilter(\r\n \"dialog.measure-data\", [measureDataFormat]);\r\n\r\nexport const measureCSVFilter = LocalizedFileFilter(\r\n \"dialog.measure-csv\", ['csv']);\r\n\r\nexport const tagCSVFilter = LocalizedFileFilter(\r\n \"dialog.tag-csv\", ['csv']);\r\n\r\nexport const DXFFileFormat = \"dxf\";\r\nexport const SHPFileFormat = \"shp\";\r\nexport const IFCFileFormat = \"ifc\";\r\nexport const xmlFileFormat = \"xml\";\r\nconst zipExtension = \"zip\";\r\n\r\nconst drawingFormats = [DXFFileFormat, SHPFileFormat, zipExtension];\r\n\r\nexport const drawingFilter = LocalizedFileFilter(\r\n \"dialog.drawing-files\", drawingFormats);\r\n\r\nexport const IFCModelFilter = LocalizedFileFilter(\r\n \"dialog.extension-ifc\", [IFCFileFormat]);\r\n\r\nexport const DXFModelFilter = LocalizedFileFilter(\r\n \"dialog.extension-dxf\", [DXFFileFormat]);\r\n\r\nexport const SHPModelFilter = LocalizedFileFilter(\r\n \"dialog.extension-shp\", [SHPFileFormat]);\r\n\r\nexport const ZIPFileFilter = LocalizedFileFilter(\r\n \"dialog.extension-zip\", [zipExtension]);\r\n\r\nconst modelFormats = [DXFFileFormat, SHPFileFormat, IFCFileFormat];\r\n\r\nexport const modelFileFilter = LocalizedFileFilter(\r\n \"dialog.model-files\", modelFormats);\r\n\r\nconst labelExtension = \"3dl\";\r\nexport const labelFilter = LocalizedFileFilter(\r\n \"dialog.label-file\", [labelExtension]);\r\n\r\nconst modelExtension = \"pth\";\r\nexport const modelFilter = LocalizedFileFilter(\r\n \"dialog.model-file\", [modelExtension]);\r\n\r\nconst xmlExtension = \"xml\";\r\nexport const xmlFileFilter = LocalizedFileFilter(\r\n \"dialog.xml-file\", [xmlExtension]);\r\n\r\nexport const lasFileFilter = LocalizedFileFilter(\r\n \"dialog.extension-las\", [lasFileFormat]\r\n);\r\n","import {createSlice, PayloadAction} from '@reduxjs/toolkit';\r\nimport {Classification, classifications} from \"../classifications\";\r\nimport {isStaticSite, storage} from \"../electron-modules\";\r\nimport {cloneDeep} from 'lodash';\r\nimport { isMobile } from '../viewer/utilities';\r\n\r\nexport interface Clamp {\r\n min: number;\r\n max: number;\r\n}\r\n\r\nexport type ColorMapKey = 'heat-map' | 'awesome-green' | 'pastel-shades' | 'blue-orange' |\r\n 'black-orange' | 'blue-hue' | 'blue-red' | 'jet' | 'grayscale';\r\n\r\nexport enum ColorType {\r\n Intensity,\r\n RGB,\r\n Height,\r\n Classification\r\n}\r\n\r\nexport enum MarkerNavType {\r\n Arrows,\r\n Markers,\r\n None\r\n}\r\n\r\nexport interface ClassificationSetting extends Classification {\r\n visible: boolean;\r\n available: boolean;\r\n}\r\n\r\nexport interface SettingsState {\r\n colorMap: ColorMapKey;\r\n colorType: ColorType;\r\n dynamicSize: boolean;\r\n circularPoints: boolean;\r\n arrowMarkers: MarkerNavType;\r\n drawerOpen: boolean;\r\n activeTab: number;\r\n opacity: number;\r\n heightClip: Clamp;\r\n intensityClip: Clamp;\r\n cloudScale: number;\r\n cloudMinimum: number;\r\n cloudMaxPoints: number;\r\n cloudDistance: number;\r\n tagDistance: number;\r\n modelDistance: number;\r\n classifications: ClassificationSetting[];\r\n switched: boolean;\r\n}\r\n\r\nconst defaultIntensityClip = {\r\n min: 0,\r\n max: 1\r\n} as Clamp;\r\n\r\nconst defaultHeightClip = {\r\n min: 0,\r\n max: 1\r\n} as Clamp;\r\n\r\nconst defaultClassifications = classifications.map(classification => ({\r\n visible: true,\r\n available: false,\r\n ...classification\r\n}));\r\n\r\nexport const initialSettingsState = {\r\n colorMap: 'jet',\r\n colorType: ColorType.Height,\r\n dynamicSize: true,\r\n circularPoints: true,\r\n arrowMarkers: MarkerNavType.Arrows,\r\n activeTab: 0,\r\n opacity: 0.5,\r\n cloudMaxPoints: 5,\r\n cloudDistance: 1000,\r\n cloudScale: 1.0,\r\n cloudMinimum: 2.0,\r\n tagDistance: 1000,\r\n modelDistance: 1000,\r\n switched: false,\r\n drawerOpen: !isMobile,\r\n heightClip: defaultHeightClip,\r\n intensityClip: defaultIntensityClip,\r\n classifications: defaultClassifications,\r\n} as SettingsState;\r\n\r\nconst loadSavedDefaults = () => {\r\n if (isStaticSite) return {};\r\n\r\n return storage.getSync(\"default-settings\");\r\n};\r\n\r\nconst saveSettingsDefaults = (state) => {\r\n if (isStaticSite) return;\r\n\r\n const copy = cloneDeep(state);\r\n\r\n // Remove anything that doesn't need defaults\r\n delete copy.classifications;\r\n delete copy.activeTab;\r\n delete copy.opacity;\r\n delete copy.cloudDistance;\r\n delete copy.heightClip;\r\n delete copy.intensityClip;\r\n\r\n storage.setSync(\"default-settings\", copy);\r\n};\r\n\r\nconst applySavedSettings = (state, settings) => {\r\n const keys = Object.keys(settings);\r\n keys.forEach(key => {\r\n if (state.hasOwnProperty(key)) {\r\n state[key] = settings[key];\r\n }\r\n });\r\n};\r\n\r\nexport const settingsSlice = createSlice({\r\n name: 'settings',\r\n initialState: initialSettingsState,\r\n reducers: {\r\n updateSettingsState: (state, action) => {\r\n applySavedSettings(state, action.payload);\r\n },\r\n applySavedDefaults: (state, action) => {\r\n // Apply any forced defaults\r\n state.activeTab = 0;\r\n\r\n // Apply saved defaults\r\n const defaults = loadSavedDefaults();\r\n applySavedSettings(state, defaults);\r\n },\r\n changeDefaultSettings: (state, action) => {\r\n saveSettingsDefaults(state);\r\n },\r\n changeOpacity: (state, action: PayloadAction) => {\r\n state.opacity = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeTagDistance: (state, action: PayloadAction) => {\r\n state.tagDistance = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeModelDistance: (state, action: PayloadAction) => {\r\n state.modelDistance = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeCloudDistance: (state, action: PayloadAction) => {\r\n state.cloudDistance = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeCloudMaxPoints: (state, action: PayloadAction) => {\r\n state.cloudMaxPoints = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeCloudScale: (state, action: PayloadAction) => {\r\n state.cloudScale = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeCloudMinimum: (state, action: PayloadAction) => {\r\n state.cloudMinimum = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeHeightClip: (state, action: PayloadAction) => {\r\n state.heightClip = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeIntensityClip: (state, action: PayloadAction) => {\r\n state.intensityClip = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeColorMap: (state, action: PayloadAction) => {\r\n state.colorMap = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeColorType: (state, action: PayloadAction) => {\r\n state.colorType = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeDynamicSize: (state, action: PayloadAction) => {\r\n state.dynamicSize = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeCircularPoints: (state, action: PayloadAction) => {\r\n state.circularPoints = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeAvailableClassifications: (state, action: PayloadAction) => {\r\n const availableClassifications = new Set(action.payload);\r\n state.classifications = state.classifications\r\n .map(classification => ({...classification, available: availableClassifications.has(classification.id)}));\r\n },\r\n changeClassificationVisibility: (state, action) => {\r\n const classification = state.classifications.find(classification => classification.id === action.payload);\r\n\r\n if (classification) {\r\n classification.visible = !classification.visible;\r\n }\r\n },\r\n changeAllClassificationVisibility: (state, action) => {\r\n state.classifications = state.classifications.map(classification => ({...classification, visible: action.payload}));\r\n },\r\n changeSwitched: (state, action: PayloadAction) => {\r\n state.switched = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeSelectedTab: (state, action: PayloadAction) => {\r\n state.activeTab = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeAssetDrawerState: (state, action: PayloadAction) => {\r\n state.drawerOpen = action.payload;\r\n saveSettingsDefaults(state);\r\n },\r\n changeArrowMarkers: (state, action: PayloadAction) => {\r\n state.arrowMarkers = action.payload;\r\n saveSettingsDefaults(state);\r\n }\r\n }\r\n});\r\n\r\nexport const {\r\n changeOpacity,\r\n changeTagDistance,\r\n changeCloudDistance,\r\n changeModelDistance,\r\n changeCloudMaxPoints,\r\n changeCloudScale,\r\n changeCloudMinimum,\r\n changeHeightClip,\r\n changeIntensityClip,\r\n changeColorMap,\r\n changeColorType,\r\n changeDynamicSize,\r\n changeCircularPoints,\r\n changeAvailableClassifications,\r\n changeClassificationVisibility,\r\n changeAllClassificationVisibility,\r\n changeSwitched,\r\n changeSelectedTab,\r\n changeAssetDrawerState,\r\n changeArrowMarkers,\r\n updateSettingsState\r\n} = settingsSlice.actions;\r\n\r\nexport default settingsSlice.reducer;\r\n\r\nexport const selectOpacity = state => state.settings.opacity as number;\r\nexport const selectTagDistance = state => state.settings.tagDistance as number;\r\nexport const selectCloudDistance = state => state.settings.cloudDistance as number;\r\nexport const selectCloudMaxPoints = state => state.settings.cloudMaxPoints as number;\r\nexport const selectCloudScale = state => state.settings.cloudScale as number;\r\nexport const selectCloudMinimum = state => state.settings.cloudMinimum as number;\r\nexport const selectHeightClip = state => state.settings.heightClip as Clamp;\r\nexport const selectIntensityClip = state => state.settings.intensityClip as Clamp;\r\nexport const selectColorMap = state => state.settings.colorMap as ColorMapKey;\r\nexport const selectColorType = state => state.settings.colorType as ColorType;\r\nexport const selectDynamicSize = state => state.settings.dynamicSize as boolean;\r\nexport const selectCircularPoints = state => state.settings.circularPoints as boolean;\r\nexport const selectViewerSwitched = state => state.settings.switched as boolean;\r\nexport const selectSelectedTab = state => state.settings.activeTab as number;\r\nexport const selectAssetDrawerState = state => state.settings.drawerOpen as boolean;\r\nexport const selectArrowMarkers = state => state.settings.arrowMarkers as MarkerNavType;\r\nexport const selectClassifications = state => state.settings.classifications as ClassificationSetting[];\r\n\r\nexport const getAvailableClassifications = (classifications: ClassificationSetting[]) => {\r\n return classifications.filter(classification => classification.available);\r\n};\r\n\r\nexport const getClassificationVisibilities = (classifications: ClassificationSetting[]) => {\r\n return classifications.map(classification => ({\r\n visible: classification.visible,\r\n id: classification.id\r\n }));\r\n};\r\n\r\nexport const selectModelDistance = (state) : number => {\r\n if (\"modelDistance\" in state.settings) {\r\n return state.settings.modelDistance;\r\n }\r\n\r\n // Return the default value if nothing exists\r\n return initialSettingsState.modelDistance;\r\n};","import memoizeFormatConstructor from 'intl-format-cache';\r\n\r\nconst getDateTimeFormat = memoizeFormatConstructor(Intl.DateTimeFormat);\r\n\r\nconst defaultOptions = {\r\n timeStyle: \"short\",\r\n dateStyle: \"short\"\r\n} as Intl.DateTimeFormatOptions;\r\n\r\n/**\r\n * Convert date to locale string using cached formatter.\r\n * This is much faster than Date.toLocaleString\r\n * */\r\nexport const toLocaleString = (text: string, language: string, options = defaultOptions): string => {\r\n const createdAt = new Date(text);\r\n const formatter = getDateTimeFormat(language, options);\r\n return formatter.format(createdAt);\r\n};","export default __webpack_public_path__ + \"static/media/classifications.24975ac9.png\";","import { useContext } from 'react';\r\nimport { BrandingContext } from '../providers';\r\n\r\nexport const useBranding = () => useContext(BrandingContext);\r\n","import React from \"react\";\r\nimport { Button, IconButton, Theme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { ArrowTooltip } from \".\";\r\nimport clsx from 'clsx';\r\nimport { isHTML } from \"../utilities/misc\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n olButtonParent: {\r\n background: \"var(--ol-subtle-background-color)\",\r\n position: 'absolute',\r\n\r\n zIndex: 10,\r\n borderRadius: \"4px\"\r\n },\r\n olButtonTopLeft: {\r\n top: \"0.5em\",\r\n left: \"0.5em\",\r\n },\r\n olButtonBottomLeft: {\r\n bottom: \"0.5em\",\r\n left: \"0.5em\",\r\n },\r\n olButton: {\r\n padding: \"0px\",\r\n margin: \"1px\",\r\n borderRadius: \"2px\",\r\n backgroundColor: \"var(--ol-background-color) !important\",\r\n color: \"var(--ol-subtle-foreground-color)\",\r\n minWidth: \"22px\",\r\n \"&:hover\": {\r\n outline: \"1px solid var(--ol-subtle-foreground-color)\",\r\n color: \"var(--ol-foreground-color)\"\r\n },\r\n \"& svg\": {\r\n width: \"22px\",\r\n height: \"22px\"\r\n }\r\n },\r\n olButtonRotate: {\r\n \"-webkit-transition\": \"-webkit-transform .3s ease-in-out\",\r\n transition: \"transform .3s ease-in-out\",\r\n \"&:hover\": {\r\n \"-webkit-transform\": \"rotate(-180deg)\",\r\n transform: \"rotate(-180deg)\"\r\n }\r\n }\r\n }),\r\n);\r\n\r\nexport interface EnhancedIconButtonProps {\r\n title: string\r\n visible?: boolean\r\n onClick?(event?): void,\r\n disabled?: boolean\r\n children?: any\r\n}\r\n\r\nexport const EnhancedIconButton = (props: EnhancedIconButtonProps) => {\r\n const {title, visible=true, onClick, disabled=false, children} = props;\r\n\r\n let tooltipText = disabled\r\n ? `${title} (Disabled)`\r\n : title;\r\n\r\n const renderAsHTML = isHTML(tooltipText);\r\n\r\n let tooltipTitle = renderAsHTML\r\n ? (
)\r\n : tooltipText;\r\n\r\n return (\r\n \r\n {visible && (\r\n {\r\n if (disabled) return;\r\n if (!onClick) return;\r\n onClick(event);\r\n }}\r\n style={{\r\n ...(disabled && {opacity: 0.3}),\r\n }}\r\n >\r\n {children}\r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\ninterface OpenLayersIconProps {\r\n rotate?: boolean;\r\n onClick(event): void;\r\n placement: \"top-left\" | \"bottom-left\";\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const OpenLayersIcon = (props: OpenLayersIconProps) => {\r\n const {rotate=false, placement, onClick} = props;\r\n const classes = useStyles();\r\n\r\n return (\r\n
\r\n \r\n {props.children}\r\n \r\n
\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { ListItemIcon, ListItemIconProps, useTheme } from \"@mui/material\";\r\n\r\ninterface DenseIconProps extends ListItemIconProps {\r\n centered?: boolean;\r\n}\r\n\r\nexport const DenseIcon = (props: DenseIconProps) => {\r\n const theme = useTheme();\r\n const {centered=false, children, ...other} = props;\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};","import {\r\n Button,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n IconButton,\r\n LinearProgress,\r\n TextField,\r\n Theme,\r\n useTheme,\r\n} from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport clsx from 'clsx';\r\nimport React, {useEffect, useMemo, useState} from \"react\";\r\nimport CloseIcon from '@mui/icons-material/Close';\r\nimport ErrorOutlineIcon from '@mui/icons-material/ErrorOutline';\r\nimport CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';\r\nimport Draggable from \"react-draggable\";\r\nimport {headerHeight} from \"../app\";\r\nimport MenuItem from '@mui/material/MenuItem';\r\nimport Select from '@mui/material/Select';\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { isEqual } from 'lodash';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useViewer } from \"../hooks\";\r\nimport {themeSpacing} from \"../theme\";\r\n\r\nconst minDialogWidth = 300; // Used for prompt, dropdown, text... etc\r\n\r\ntype DialogWidth = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\"\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n draggableTitleClose: {\r\n color: theme.palette.grey[500],\r\n marginRight: theme.spacing(1)\r\n },\r\n draggableContent: {\r\n padding: theme.spacing(0),\r\n paddingTop: \"0px !important\",\r\n height: \"fit-content\",\r\n width: \"fit-content\",\r\n maxWidth: 'none',\r\n maxHeight: 'none'\r\n },\r\n draggableMouseDown: {\r\n \"z-index\": `${theme.zIndex.modal + 1} !important`\r\n },\r\n draggableContentParent: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n minWidth: \"400px\",\r\n maxWidth: \"75vw\",\r\n minHeight: \"200px\",\r\n maxHeight: \"75vh\",\r\n overflow: \"hidden\",\r\n position: \"relative\",\r\n zIndex: 1 // Fixes slimscroll visual issues\r\n },\r\n draggableTopDiv: {\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n },\r\n draggableBackdropPaper: {\r\n height: \"inherit\",\r\n padding: theme.spacing(1)\r\n },\r\n draggableBackdropRounded: {\r\n borderRadius: theme.spacing(0.5),\r\n height: \"inherit\",\r\n },\r\n draggableRoundCorner: {\r\n backgroundColor: \"transparent\"\r\n },\r\n draggableTitle: {\r\n userSelect: \"none\",\r\n cursor: \"grab\",\r\n flex: \"1 !important\"\r\n },\r\n draggableTitleDown: {\r\n cursor: \"grabbing\"\r\n },\r\n progressContent: {\r\n padding: `${theme.spacing(3)} !important`,\r\n },\r\n progressNoTransition: {\r\n transition: \"none\"\r\n },\r\n simpleDialogMain: {\r\n \"z-index\": `${theme.zIndex.modal + 1} !important`\r\n },\r\n simpleDialogHeader: {\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n },\r\n simpleDialogTitle: {\r\n userSelect: \"none\",\r\n flex: 1\r\n },\r\n simpleDialogClose: {\r\n color: theme.palette.grey[500],\r\n marginRight: theme.spacing(1)\r\n }\r\n }),\r\n);\r\n\r\ninterface PromptDialogProps {\r\n open: boolean;\r\n title: string;\r\n prompt: string;\r\n button: string;\r\n onCancel(): void;\r\n onSubmit(): void;\r\n}\r\n\r\nexport const PromptDialog = (props: PromptDialogProps) => {\r\n const {open, title, prompt, button, onCancel, onSubmit} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n \r\n {title}\r\n \r\n\r\n \r\n \r\n {prompt}\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface AlertDialogProps {\r\n open: boolean;\r\n error?: boolean\r\n title: string;\r\n onClose(): void;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const AlertDialog = (props: AlertDialogProps) => {\r\n const {open, onClose, title, error=false} = props;\r\n\r\n const {t} = useTranslation();\r\n const theme = useTheme();\r\n\r\n return (\r\n \r\n
\r\n {error && }\r\n\r\n {!error && }\r\n\r\n \r\n {title}\r\n \r\n
\r\n\r\n \r\n {props.children}\r\n \r\n\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface TextDialogProps {\r\n open: boolean;\r\n title: string;\r\n label: string;\r\n prompt: string;\r\n placeholder?: string;\r\n onCancel(): void;\r\n onSubmit(value: string): void;\r\n clear?: boolean;\r\n}\r\n\r\nexport const TextDialog = (props: TextDialogProps) => {\r\n const {open, onSubmit, onCancel, label, prompt,\r\n placeholder=\"\", clear=false} = props;\r\n\r\n const [text, setText] = useState(\"\");\r\n const [disabled, setDisabled] = useState(true);\r\n const {t} = useTranslation();\r\n\r\n const handleTextChange = (event) => {\r\n setText(event.target.value);\r\n };\r\n\r\n useEffect(() => {\r\n if (text.trim() !== '') {\r\n setDisabled(false);\r\n } else {\r\n setDisabled(true);\r\n }\r\n }, [text]);\r\n\r\n useEffect(() => {\r\n setText(placeholder);\r\n }, [open]);\r\n\r\n const handleCancel = () => {\r\n onCancel();\r\n setText(placeholder);\r\n };\r\n\r\n const handleSubmit = () => {\r\n const trimmedText = text.trim();\r\n\r\n onSubmit(trimmedText);\r\n\r\n if (clear) {\r\n setText('');\r\n } else {\r\n setText(trimmedText);\r\n }\r\n };\r\n\r\n const handleKeyDown = (event) => {\r\n if (event.key === 'Enter') {\r\n if (text === '') {\r\n return;\r\n }\r\n\r\n handleSubmit();\r\n }\r\n };\r\n\r\n return (\r\n \r\n {props.title}\r\n \r\n \r\n {prompt}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface DropdownDialogProps {\r\n open: boolean;\r\n title: string;\r\n prompt: string;\r\n defaultValue: any;\r\n onCancel(): void;\r\n onSubmit(value: any): void;\r\n options: [value: any, text: string][];\r\n}\r\n\r\nexport const DropDownDialog = (props: DropdownDialogProps) => {\r\n const {open, defaultValue, title, prompt, options, onCancel, onSubmit} = props;\r\n\r\n const [value, setValue] = useState(defaultValue);\r\n const {t} = useTranslation();\r\n\r\n const resetDefaults = () => {\r\n setValue(defaultValue);\r\n };\r\n\r\n const handleSubmit = () => {\r\n onSubmit(value);\r\n };\r\n\r\n const handleChange = (event) => {\r\n setValue(event.target.value);\r\n };\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n return (\r\n \r\n {title}\r\n \r\n \r\n {prompt}\r\n \r\n \r\n {options.map((option, index) => {\r\n const [value, text] = option;\r\n\r\n return (\r\n \r\n {text}\r\n \r\n );\r\n })}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface SimpleDialogProps {\r\n open: boolean\r\n title: string\r\n button?: string\r\n onSubmit?(): void\r\n onClose(): void\r\n canSubmit?: boolean\r\n canClose?: boolean\r\n maxWidth?: DialogWidth\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const SimpleDialog = (props: SimpleDialogProps) => {\r\n const {title, button = \"Submit\", open, onSubmit, onClose,\r\n canSubmit=true, canClose=true, children, maxWidth=\"sm\",\r\n ...other} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n
\r\n \r\n {title}\r\n \r\n\r\n {/* Close button */}\r\n \r\n \r\n \r\n
\r\n\r\n \r\n {children}\r\n \r\n\r\n \r\n \r\n {t('buttons.cancel')}\r\n \r\n\r\n {!!onSubmit && (\r\n \r\n {button}\r\n \r\n )}\r\n \r\n\r\n \r\n );\r\n};\r\n\r\ninterface DraggableDialogProps {\r\n open: boolean\r\n title: string\r\n onClose?(): void\r\n initialHeight?: number | string\r\n initialWidth?: number | string\r\n resize?: boolean\r\n children: React.ReactNode;\r\n}\r\n\r\ninterface DialogSize {\r\n width: string | number;\r\n height: string | number;\r\n}\r\n\r\ninterface DialogPosition {\r\n x: number;\r\n y: number;\r\n}\r\n\r\nexport const DraggableDialog = (props: DraggableDialogProps) => {\r\n const {open, title, resize=true, initialHeight = \"fit-content\",\r\n initialWidth = \"450px\", onClose} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const resizeElementID = useMemo(() => nanoid(), []);\r\n const paperPropID = useMemo(() => nanoid(), []);\r\n\r\n const [mouseDown, setMouseDown] = useState(false);\r\n const [dialogSize, setDialogSize] = useState({\r\n width: initialWidth,\r\n height: initialHeight\r\n });\r\n const [dialogPosition, setDialogPosition] = useState({\r\n x: themeSpacing * 2,\r\n y: themeSpacing * 2 + headerHeight\r\n });\r\n\r\n const onDragMouseDown = () => {\r\n setMouseDown(true);\r\n };\r\n\r\n const onDragMouseUp = () => {\r\n setMouseDown(false);\r\n };\r\n\r\n const onDrag = (event, data) => {\r\n const {x,y} = data;\r\n setDialogPosition({x, y});\r\n };\r\n\r\n const checkOutOfBounds = () => {\r\n let element = document.getElementById(paperPropID);\r\n if (!element) return;\r\n\r\n const dialogWidth = element.clientWidth + 2*themeSpacing;\r\n const dialogHeight = element.clientHeight + 2*themeSpacing;\r\n\r\n const parentWidth = window.innerWidth;\r\n const parentHeight = window.innerHeight;\r\n\r\n const dialogLeft = dialogPosition.x;\r\n const dialogTop = dialogPosition.y;\r\n const dialogBottom = dialogTop + dialogHeight;\r\n const dialogRight = dialogLeft + dialogWidth;\r\n\r\n const newPosition = {...dialogPosition};\r\n\r\n if (dialogRight > parentWidth) {\r\n newPosition.x = Math.max(0, parentWidth - dialogWidth);\r\n }\r\n\r\n if (dialogBottom > parentHeight) {\r\n newPosition.y = Math.max(0, parentHeight - dialogHeight);\r\n }\r\n\r\n if (!isEqual(dialogPosition, newPosition)) {\r\n setDialogPosition(newPosition);\r\n }\r\n };\r\n\r\n /** Check for out of bounds */\r\n useEffect(() => {\r\n if (!open || !resize) return;\r\n\r\n const interval = setInterval(() => {\r\n checkOutOfBounds();\r\n }, 100);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [open, dialogPosition]);\r\n\r\n /** Remember resized dimensions */\r\n useEffect(() => {\r\n if (open || !resize) return;\r\n\r\n let element = document.getElementById(resizeElementID);\r\n if (!element) return;\r\n\r\n const width = element.style.width;\r\n const height = element.style.height;\r\n\r\n // If our height is still fit-content it means that the dialog was\r\n // never resized and that we shouldnt force any specific height\r\n if (height === \"fit-content\") return;\r\n\r\n setDialogSize({width, height});\r\n }, [open]);\r\n\r\n return (\r\n \r\n \r\n \r\n {/* Draggable title */}\r\n \r\n {title}\r\n \r\n\r\n {/* Close button */}\r\n \r\n \r\n \r\n
\r\n\r\n \r\n {props.children}\r\n \r\n\r\n \r\n \r\n );\r\n};\r\n\r\ninterface ProgressDialogProps {\r\n open: boolean;\r\n text: string;\r\n percent: number;\r\n animated?: boolean\r\n}\r\n\r\nexport const ProgressDialog = (props: ProgressDialogProps) => {\r\n const {open, text, percent, animated=false} = props;\r\n const classes = useStyles();\r\n\r\n return (\r\n \r\n \r\n \r\n {text} {percent.toFixed(2)}%\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface LabelCategoryDialogProps {\r\n open: boolean;\r\n onClose(): void\r\n id?: string\r\n}\r\n\r\nexport const LabelCategoryDialog = (props) => {\r\n const {open, onClose, id} = props as LabelCategoryDialogProps;\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const getSelectedLabels = () => {\r\n const selectedLabelIDs = viewer?.highlightedLabels().map(label => label.id);\r\n const nonSelected = selectedLabelIDs ? (selectedLabelIDs.length === 0) : true;\r\n const idSelected = (id !== undefined);\r\n return (nonSelected || idSelected) ? [id] : selectedLabelIDs;\r\n };\r\n\r\n const getCategoryDropdown = () => {\r\n let allCategories = viewer?.getAllCategories();\r\n const highlightedCategories = getSelectedLabels().map(labelID => viewer?.getCategoryByLabelID(labelID));\r\n const choosableCategories = allCategories?.filter(category => !highlightedCategories.includes(category));\r\n const dropDownList: [value: any, text: string][] = choosableCategories ? choosableCategories.map(category => {\r\n return [category.id, category.name];}) : [[0, '']];\r\n return dropDownList;\r\n };\r\n\r\n const getDefaultValue = () => {\r\n const dropDownList = getCategoryDropdown();\r\n if (dropDownList.length === 0) {\r\n return null;\r\n } else {\r\n return dropDownList[0][0];\r\n }\r\n };\r\n\r\n const handleChangeCategory = (value: any) => {\r\n const labelIDs = getSelectedLabels();\r\n viewer.transferLabel(labelIDs, value);\r\n onClose();\r\n };\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\n","import React, {memo} from \"react\";\r\nimport { Grid, InputLabel, Theme, Typography } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { Draggable } from 'react-beautiful-dnd';\r\nimport ListItem from '@mui/material/ListItem';\r\nimport {\r\n DragDropContext,\r\n Droppable,\r\n OnDragEndResponder\r\n} from 'react-beautiful-dnd';\r\nimport { NumberField } from \".\";\r\nimport {t} from \"../localization\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n draggingListItem: {\r\n background: 'rgb(235,235,235)'\r\n },\r\n staticListItem: {\r\n borderBottom: \"2px dashed lightgray\"\r\n },\r\n flexGrow: {\r\n flexGrow: 1\r\n }\r\n })\r\n);\r\n\r\ninterface DraggableItemProps {\r\n id: string;\r\n primary: string;\r\n secondary: number;\r\n error?: boolean;\r\n index: number;\r\n min?: number,\r\n max?: number,\r\n step?: number\r\n}\r\n\r\ninterface DraggableListItemProps {\r\n item: DraggableItemProps;\r\n index: number;\r\n setData: React.Dispatch;\r\n inputName: string;\r\n listLength: number;\r\n}\r\n\r\nconst DraggableListItem = (props: DraggableListItemProps) => {\r\n const {item, index, setData, inputName, listLength} = props;\r\n const classes = useStyles();\r\n const useStaticListItem = (index === listLength-1) ? '' : classes.staticListItem;\r\n\r\n return (\r\n \r\n {(provided, snapshot) => (\r\n \r\n
\r\n \r\n \r\n {t(\"labels.category-name\")}\r\n \r\n \r\n {inputName}\r\n \r\n \r\n \r\n \r\n {item.primary}\r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n )}\r\n
\r\n );\r\n};\r\n\r\ninterface DraggableListProps {\r\n items: DraggableItemProps[];\r\n onDragEnd: OnDragEndResponder;\r\n setData: any;\r\n inputName: string;\r\n}\r\n\r\nexport const DraggableList = memo((props: DraggableListProps) => {\r\n const {items, onDragEnd, setData, inputName} = props;\r\n\r\n return (\r\n \r\n \r\n {provided => (\r\n
\r\n {items.map((item, index) => (\r\n \r\n ))}\r\n {provided.placeholder}\r\n
\r\n )}\r\n
\r\n
\r\n );\r\n});\r\n","import React, {useEffect, useState} from 'react';\r\nimport {\r\n Checkbox,\r\n Input,\r\n MenuItem,\r\n Paper,\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableContainer,\r\n TableHead,\r\n TablePagination,\r\n TableRow,\r\n TableSortLabel,\r\n Theme,\r\n Typography,\r\n useTheme,\r\n} from '@mui/material';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport SearchIcon from '@mui/icons-material/Search';\r\nimport MoreHorizIcon from '@mui/icons-material/MoreHoriz';\r\nimport clsx from 'clsx';\r\nimport {ArrowTooltip, DenseIcon, DenseMenu, EnhancedIconButton} from '.';\r\nimport {useTranslation} from 'react-i18next';\r\nimport {\r\n EnhancedTableBodyProps,\r\n EnhancedTableCellProps,\r\n EnhancedTableCheckboxHeadProps,\r\n EnhancedTableHeadProps,\r\n EnhancedTableProps\r\n} from '../types/enhanced-table';\r\nimport {toLocaleString} from '../utilities/dates';\r\nimport {useContextMenu} from '../hooks';\r\nimport { isHTML } from '../utilities/misc';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n header: {\r\n fontWeight: \"bold\",\r\n userSelect: \"none\",\r\n whiteSpace: \"nowrap\"\r\n },\r\n densePadding: {\r\n padding: `${theme.spacing(0.5)} ${theme.spacing(1.0)} !important`,\r\n },\r\n denseFooter: {\r\n height: theme.spacing(4),\r\n minHeight: \"0px\",\r\n overflow: \"hidden\"\r\n },\r\n hiddenSort: {\r\n border: 0,\r\n clip: 'rect(0 0 0 0)',\r\n height: 1,\r\n margin: -1,\r\n overflow: 'hidden',\r\n padding: 0,\r\n position: 'absolute',\r\n top: 20,\r\n width: 1,\r\n },\r\n noSelect: {\r\n userSelect: \"none\"\r\n },\r\n rowDisabled: {\r\n \"& th\": {\r\n opacity: 0.3\r\n },\r\n \"& td\": {\r\n opacity: 0.3\r\n }\r\n },\r\n rowIcon: {\r\n fontSize: \"1em\"\r\n },\r\n buttonCell: {\r\n width: \"1%\",\r\n whiteSpace: \"nowrap\",\r\n padding: \"0px !important\"\r\n },\r\n buttonHeader: {\r\n padding: \"0px !important\"\r\n },\r\n tableRow: {\r\n \"& td:last-child\": {\r\n paddingRight: `${theme.spacing(1.5)} !important`\r\n },\r\n \"& td:first-child\": {\r\n paddingLeft: `${theme.spacing(1.5)} !important`\r\n },\r\n \"& th:last-child\": {\r\n paddingRight: `${theme.spacing(1.5)} !important`\r\n },\r\n \"& th:first-child\": {\r\n paddingLeft: `${theme.spacing(1.5)} !important`\r\n }\r\n }\r\n }),\r\n);\r\n\r\n/** Column header with label and checkbox */\r\nexport const EnhancedTableCheckboxHead = (props: EnhancedTableCheckboxHeadProps) => {\r\n const {label, values, onChange} = props;\r\n\r\n const numVisible = values.filter(x => x === true).length;\r\n const checked = numVisible > 0;\r\n const indeterminate = checked && (values.length !== numVisible);\r\n\r\n return (\r\n \r\n {\r\n // Stop click event from triggering sort function\r\n event.stopPropagation();\r\n }}\r\n onChange={(event) => {\r\n onChange(indeterminate || event.target.checked);\r\n }}\r\n />\r\n\r\n {label}\r\n \r\n );\r\n};\r\n\r\nconst EnhancedTableHead = (props: EnhancedTableHeadProps) => {\r\n const {sortDir, sortBy, onRequestSort, columns, actions, dense} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const createSortHandler = (property) => (event) => {\r\n onRequestSort(event, property);\r\n };\r\n\r\n const hasActions = actions.length > 0;\r\n\r\n return (\r\n \r\n \r\n {columns.map(column => {\r\n\r\n const {id, label, center, sortable=true} = column;\r\n\r\n return (\r\n \r\n {/* Non-sortable column header */}\r\n {!sortable && \r\n {label}\r\n }\r\n\r\n {/* Sortable column header */}\r\n {sortable && \r\n {label}\r\n {sortBy === id ? (\r\n \r\n {sortDir === 'desc' ? 'sorted descending' : 'sorted ascending'}\r\n \r\n ) : null}\r\n }\r\n \r\n );\r\n })}\r\n\r\n {/** Custom actions */}\r\n {hasActions && }\r\n\r\n \r\n \r\n );\r\n};\r\n\r\nconst EnhancedTableBody = (props: EnhancedTableBodyProps) => {\r\n const {rows, actions, columns, onClick, dense,\r\n setSelectedRow, handleContextMenu} = props;\r\n\r\n const classes = useStyles();\r\n const hasActions = actions.length > 0;\r\n\r\n return (\r\n \r\n {rows.map(row =>\r\n \r\n {columns.map((column, index) =>\r\n \r\n )}\r\n\r\n {/** Custom actions */}\r\n {hasActions && \r\n {\r\n setSelectedRow(row);\r\n handleContextMenu(event);\r\n }}\r\n >\r\n \r\n \r\n }\r\n\r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\nconst EnhancedTableCell = (props: EnhancedTableCellProps) => {\r\n const {row, column, dense, index, onClick} = props;\r\n\r\n const theme = useTheme();\r\n const {i18n} = useTranslation();\r\n\r\n const key = `${row.id}_${column.id}`;\r\n const text = row[column.id] as any;\r\n const isString = typeof(text) === \"string\";\r\n const condition = (column.numeric || text.length <= 100);\r\n\r\n const cellContent = (column, content, condition) => {\r\n if (column.date) {\r\n return toLocaleString(content, i18n.language);\r\n }\r\n\r\n const renderAsHTML = isHTML(content);\r\n\r\n if (renderAsHTML) {\r\n if (column.tooltip) {\r\n return (\r\n \r\n
\r\n \r\n );\r\n } else {\r\n return (\r\n
\r\n );\r\n }\r\n }\r\n\r\n if (isString) {\r\n content = condition ? content : `${content.slice(0,100)}...`;\r\n }\r\n\r\n if (column.tooltip) {\r\n return (\r\n \r\n
\r\n {content}\r\n
\r\n
\r\n );\r\n }\r\n\r\n return content;\r\n };\r\n\r\n const title = isString ? text : \"\";\r\n const content = cellContent(column, text, condition);\r\n\r\n return (\r\n {\r\n if (row.disabled || !onClick) return;\r\n onClick(row, index);\r\n }}\r\n style={{\r\n ...(column.wordBreak && {\r\n wordBreak: \"break-all\"\r\n }),\r\n ...(column.forceOpacity && {\r\n opacity: 1.0\r\n }),\r\n ...(column.pointer && {\r\n cursor: \"pointer\"\r\n }),\r\n ...(column.center && {\r\n textAlign: \"center\"\r\n }),\r\n ...(dense && {\r\n padding: `${theme.spacing(0.5)} ${theme.spacing(1.0)}`\r\n })\r\n }}\r\n title={title}\r\n >\r\n {content}\r\n \r\n );\r\n};\r\n\r\nexport const EnhancedTable = (props: EnhancedTableProps) => {\r\n const {state, columns, rows, actions=[], onClick,\r\n dense = true, maxHeight} = props;\r\n\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n\r\n const contextMenu = useContextMenu();\r\n\r\n const [search, setSearch] = useState(\"\");\r\n const [selectedRow, setSelectedRow] = useState(null);\r\n\r\n const onSearch = (event) => {\r\n const value = event.target.value;\r\n state.handleSearchChange(value);\r\n setSearch(value);\r\n };\r\n\r\n useEffect(() => {\r\n // Restore previously saved search terms\r\n //setSearch(state.query);\r\n\r\n // Reset the search string\r\n setSearch(\"\");\r\n state.handleSearchChange(\"\");\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (state.pageNumber <= maxPageNumber) return;\r\n state.handlePageNumberChange(null, maxPageNumber);\r\n }, [state.pageNumber, rows]);\r\n\r\n let tableRows = state.handleSearch(columns, [...rows]);\r\n\r\n // Number of rows must be calculated after\r\n // search and before pagination\r\n const numberOfRows = tableRows.length;\r\n\r\n tableRows = state.handleSort(columns, tableRows);\r\n tableRows = state.handlePages(tableRows);\r\n\r\n // Make sure our max page is valid\r\n const maxPageNumber = Math.max(\r\n 0, Math.ceil(numberOfRows / state.rowsPerPage) - 1);\r\n const pageNumber = Math.min(state.pageNumber, maxPageNumber);\r\n\r\n const searchable = columns.filter(\r\n column => column.searchable).length > 0;\r\n\r\n return (\r\n \r\n
\r\n \r\n\r\n {/** Search bar */}\r\n {searchable && }\r\n />}\r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n\r\n \r\n `${page.from}–${page.to} ${t(\"enhanced-table.displayed-rows-of\")} ${page.count !== -1 ?\r\n page.count : `${t(\"enhanced-table.displayed-rows-more-than\")} ${page.to}`}`\r\n }\r\n getItemAriaLabel={(type) => {\r\n if (type === \"next\") {\r\n return t(\"enhanced-table.next-page\");\r\n } else if (type === \"previous\") {\r\n return t(\"enhanced-table.prev-page\");\r\n } else {\r\n return \"\";\r\n }\r\n }}\r\n page={pageNumber}\r\n classes={{\r\n toolbar: dense ? classes.denseFooter : \"\"\r\n }}\r\n onPageChange={state.handlePageNumberChange}\r\n onRowsPerPageChange={state.handleRowsPerPageChange}\r\n />\r\n\r\n \r\n
\r\n\r\n {/** Context menu */}\r\n \r\n {actions.map((action, index) =>\r\n {\r\n if (!selectedRow) return;\r\n action.onClick(selectedRow);\r\n contextMenu.handleClose();\r\n }}\r\n >\r\n \r\n {action.icon}\r\n \r\n\r\n \r\n {action.title}\r\n \r\n \r\n )}\r\n \r\n\r\n
\r\n );\r\n};\r\n","import React, { useEffect, useImperativeHandle, useRef, useState } from \"react\";\r\nimport { DenseIcon } from \"./dense-icon\";\r\nimport { Divider, Grow, Menu, MenuItem, MenuItemProps, Typography, useTheme } from \"@mui/material\";\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport ArrowRight from '@mui/icons-material/ArrowRight';\r\nimport clsx from 'clsx';\r\nimport { DividerProps } from \"@mui/material/Divider/Divider\";\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n subMenuRoot: (props: {open: boolean}) => ({\r\n justifyContent: \"space-between\",\r\n backgroundColor: props.open\r\n ? theme.palette.action.hover\r\n : 'rgba(0,0,0,0)'\r\n }),\r\n subMenuLabel: {\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n }\r\n}));\r\n\r\ninterface NestedMenuItemProps extends Omit {\r\n parentMenuOpen: boolean\r\n label?: React.ReactNode\r\n rightIcon?: React.ReactNode\r\n dense: boolean,\r\n ContainerProps?: React.HTMLAttributes & React.RefAttributes\r\n button?: true | undefined\r\n}\r\n\r\n/**\r\n * https://github.com/azmenak/material-ui-nested-menu-item\r\n * Modifications have been made to close submenu when open is false.\r\n * This is required because we use keepMounted on all of our menus. Also\r\n * modified the right arrow to be better aligned\r\n**/\r\nconst NestedMenuItem = React.forwardRef((props: NestedMenuItemProps, ref) => {\r\n const {\r\n parentMenuOpen,\r\n label,\r\n rightIcon = ,\r\n dense = false,\r\n children,\r\n className,\r\n tabIndex: tabIndexProp,\r\n ContainerProps: ContainerPropsProp = {},\r\n ...MenuItemProps\r\n } = props;\r\n\r\n const {ref: containerRefProp, ...ContainerProps} = ContainerPropsProp;\r\n\r\n const menuItemRef = useRef(null);\r\n useImperativeHandle(ref, () => menuItemRef.current);\r\n\r\n const containerRef = useRef(null);\r\n useImperativeHandle(containerRefProp, () => containerRef.current);\r\n\r\n const menuContainerRef = useRef(null);\r\n\r\n const [isSubMenuOpen, setIsSubMenuOpen] = useState(false);\r\n\r\n const handleMouseEnter = (event: React.MouseEvent) => {\r\n setIsSubMenuOpen(true);\r\n\r\n if (ContainerProps?.onMouseEnter) {\r\n ContainerProps.onMouseEnter(event);\r\n }\r\n };\r\n\r\n const handleMouseLeave = (event: React.MouseEvent) => {\r\n setIsSubMenuOpen(false);\r\n\r\n if (ContainerProps?.onMouseLeave) {\r\n ContainerProps.onMouseLeave(event);\r\n }\r\n };\r\n\r\n // Check if any immediate children are active\r\n const isSubmenuFocused = () => {\r\n const active = containerRef.current?.ownerDocument?.activeElement;\r\n for (const child of menuContainerRef.current?.children ?? []) {\r\n if (child === active) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n };\r\n\r\n const handleFocus = (event: React.FocusEvent) => {\r\n if (event.target === containerRef.current) {\r\n setIsSubMenuOpen(true);\r\n }\r\n\r\n if (ContainerProps?.onFocus) {\r\n ContainerProps.onFocus(event);\r\n }\r\n };\r\n\r\n const handleKeyDown = (event: React.KeyboardEvent) => {\r\n if (event.key === 'Escape') {\r\n return;\r\n }\r\n\r\n if (isSubmenuFocused()) {\r\n event.stopPropagation();\r\n }\r\n\r\n const active = containerRef.current?.ownerDocument?.activeElement;\r\n\r\n if (event.key === 'ArrowLeft' && isSubmenuFocused()) {\r\n containerRef.current?.focus();\r\n }\r\n\r\n if (\r\n event.key === 'ArrowRight' &&\r\n event.target === containerRef.current &&\r\n event.target === active\r\n ) {\r\n const firstChild = menuContainerRef.current?.children[0] as\r\n | HTMLElement\r\n | undefined;\r\n firstChild?.focus();\r\n }\r\n };\r\n\r\n /** Custom Code */\r\n useEffect(() => {\r\n setIsSubMenuOpen(false);\r\n }, [parentMenuOpen]);\r\n\r\n const open = isSubMenuOpen && parentMenuOpen;\r\n const classes = useStyles({open});\r\n\r\n // Root element must have a `tabIndex` attribute for keyboard navigation\r\n let tabIndex;\r\n if (!props.disabled) {\r\n tabIndex = tabIndexProp !== undefined ? tabIndexProp : -1;\r\n }\r\n\r\n return (\r\n \r\n \r\n {/** Custom Code */}\r\n
{label}
\r\n
{rightIcon}
\r\n \r\n\r\n {\r\n setIsSubMenuOpen(false);\r\n }}\r\n >\r\n
\r\n {children}\r\n
\r\n \r\n
\r\n );\r\n});\r\n\r\ninterface NestedMenuProps {\r\n parentMenuOpen: boolean;\r\n text: string;\r\n ref?: any;\r\n icon: any;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const NestedMenu = React.forwardRef((props: NestedMenuProps, ref) => {\r\n const {parentMenuOpen, text, icon} = props;\r\n\r\n return (\r\n \r\n {icon}\r\n {text}\r\n \r\n }\r\n ref={ref}\r\n parentMenuOpen={parentMenuOpen}\r\n >\r\n {props.children}\r\n \r\n );\r\n});\r\n\r\nexport const MenuDivider = React.forwardRef((props: DividerProps, ref) => {\r\n return (\r\n \r\n );\r\n});\r\n\r\ninterface DenseMenuProps {\r\n open: boolean;\r\n onClose(): void;\r\n onEnter?(): void;\r\n anchorPosition: {left: number, top: number};\r\n keepMounted?: boolean;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const DenseMenu = React.forwardRef((props: DenseMenuProps, ref) => {\r\n const {keepMounted=true, children, onEnter, ...other} = props;\r\n\r\n const theme = useTheme();\r\n\r\n const {enteringScreen} = theme.transitions.duration;\r\n\r\n const transitionProps = {\r\n timeout: {\r\n enter: enteringScreen,\r\n exit: 0\r\n },\r\n ...(onEnter) && {onEnter}\r\n };\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n});\r\n\r\n","\r\nimport React, {\r\n memo,\r\n ReactElement,\r\n useCallback,\r\n useMemo,\r\n useState,\r\n useEffect\r\n} from \"react\";\r\nimport {\r\n Grow,\r\n Tooltip,\r\n TooltipProps,\r\n useTheme\r\n} from \"@mui/material\";\r\nimport {useTranslation} from \"react-i18next\";\r\nimport { isHTML } from \"../utilities/misc\";\r\n\r\nexport const ArrowTooltip = (props: TooltipProps) => {\r\n return (\r\n \r\n {props.children as any}\r\n \r\n );\r\n};\r\n\r\ninterface CursorTooltipProps {\r\n lines: string[]\r\n children: ReactElement,\r\n disableToggle?: boolean\r\n disableZoom?: boolean;\r\n}\r\n\r\nexport const CursorTooltip = memo((props: CursorTooltipProps) => {\r\n const {lines, children, disableToggle = false, disableZoom = false} = props;\r\n\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n\r\n const [hidden, setHidden] = useState(false);\r\n\r\n const title = useMemo(() => {\r\n if ((lines.length === 0) || hidden) return;\r\n\r\n const modifiedLines = [...lines];\r\n const hasLines = lines.length > 0;\r\n\r\n if (hasLines && !disableZoom) {\r\n const text = t('tooltip.hold_key_to_zoom');\r\n modifiedLines.push(text);\r\n }\r\n\r\n if (hasLines && !disableToggle) {\r\n const text = t('tooltip.toggle-tooltip');\r\n modifiedLines.push(text);\r\n }\r\n\r\n return modifiedLines.map((value, index) => {\r\n const renderAsHTML = isHTML(value);\r\n\r\n const text = renderAsHTML\r\n ? (
)\r\n : value;\r\n\r\n return (\r\n
\r\n {text}\r\n
\r\n );\r\n });\r\n }, [lines, hidden]);\r\n\r\n const onClose = useCallback(() => {\r\n setHidden(false);\r\n }, []);\r\n\r\n const {enteringScreen} = theme.transitions.duration;\r\n\r\n const transitionProps = {\r\n timeout: {\r\n enter: enteringScreen,\r\n exit: 0\r\n }\r\n };\r\n\r\n /** Tooltip toggle hotkey event listener */\r\n useEffect(() => {\r\n if (disableToggle) return;\r\n\r\n if (lines.length === 0) {\r\n setHidden(false);\r\n return;\r\n }\r\n\r\n const onHotkey = (event => {\r\n if (event.target instanceof HTMLInputElement) {\r\n return;\r\n }\r\n\r\n if (event.which === 192) {\r\n setHidden(!hidden);\r\n }\r\n });\r\n\r\n window.addEventListener('keydown', onHotkey, false);\r\n\r\n return () => {\r\n window.removeEventListener('keydown', onHotkey, false);\r\n };\r\n }, [lines, hidden]);\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n});\r\n","import React, {\r\n useCallback,\r\n useEffect,\r\n useMemo,\r\n useState,\r\n} from \"react\";\r\nimport {\r\n InputAdornment,\r\n InputLabel,\r\n MenuItem,\r\n Select,\r\n Switch,\r\n TextField,\r\n Theme,\r\n Typography,\r\n IconButton,\r\n Input,\r\n useTheme,\r\n ListItem,\r\n FormControl,\r\n Checkbox,\r\n FormControlLabel,\r\n FormGroup,\r\n} from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport clsx from 'clsx';\r\nimport slash from 'slash';\r\nimport { dialog } from \"../electron-modules\";\r\nimport LocalScene from \"../viewer/projections\";\r\nimport { UnitConverter } from \"../viewer/utilities\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport FolderIcon from \"@mui/icons-material/Folder\";\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport CloseIcon from '@mui/icons-material/Close';\r\nimport CheckIcon from '@mui/icons-material/Check';\r\nimport {AttachFile, Delete, Save} from \"@mui/icons-material\";\r\nimport { MenuDivider } from \"./menu-items\";\r\nimport { useAuth } from \"../hooks\";\r\nimport { ArrowTooltip } from \"./tooltips\";\r\nimport { isHTML } from \"../utilities/misc\";\r\nimport { ColorPicker } from \".\";\r\nimport { Units } from \"../types/project\";\r\n\r\nconst converter = new UnitConverter();\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n flexibleHeight: {\r\n height: \"100%\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n justifyContent: \"space-between\",\r\n \"& span\": {\r\n flex: 1\r\n }\r\n },\r\n filePath: {\r\n wordBreak: \"break-word\"\r\n },\r\n dropdownWithLabel: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n justifyContent: \"space-between\",\r\n \"& span\": {\r\n flex: 1\r\n }\r\n },\r\n paddingBottom: {\r\n paddingBottom: `${theme.spacing(1)} !important`,\r\n },\r\n inputParent: {\r\n width: \"100%\",\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n minHeight: theme.spacing(3),\r\n paddingBottom: theme.spacing(0.5)\r\n },\r\n inputLabel: {\r\n height: \"fit-content\",\r\n whiteSpace: \"normal\"\r\n },\r\n buttonMargin: {\r\n margin: theme.spacing(-1, 0)\r\n },\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n })\r\n);\r\n\r\ninterface NumberData {\r\n value: number | string;\r\n error: boolean;\r\n index?: number;\r\n}\r\n\r\ninterface NumberFieldProps {\r\n data: NumberData;\r\n setData: React.Dispatch>;\r\n min: number;\r\n max: number;\r\n step?: number;\r\n adornment?: string;\r\n index?: number;\r\n units?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport const NumberField = (props: NumberFieldProps) => {\r\n const {units=false, ...other} = props;\r\n\r\n return units\r\n ? \r\n : ;\r\n};\r\n\r\ninterface NumberFieldWithLabelProps extends NumberFieldProps {\r\n title: string;\r\n label?: string;\r\n}\r\n\r\nexport const NumberFieldWithLabel = (props: NumberFieldWithLabelProps) => {\r\n const {title, label, ...other} = props;\r\n\r\n const classes = useStyles();\r\n\r\n return (\r\n
\r\n
\r\n {title}\r\n
\r\n\r\n \r\n {label}\r\n \r\n\r\n \r\n
\r\n );\r\n};\r\n\r\nconst NumberFieldNoUnits = (props: NumberFieldProps) => {\r\n const {data, setData, min, max, adornment, step=1.0, index=0, ...other} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n // NOTE: Space character is required for even positioning in UI\r\n const helperText = data.error\r\n ? t('dialog.accepted-range-is-min-max', {min, max})\r\n : undefined;\r\n\r\n const endAdornment = adornment\r\n ? {adornment}\r\n : null;\r\n\r\n return (\r\n {\r\n let hasError = false;\r\n\r\n let floatValue = parseFloat(event.target.value);\r\n if (isNaN(floatValue)) {\r\n hasError = true;\r\n }\r\n\r\n if (floatValue > max) {\r\n hasError = true;\r\n } else if (floatValue < min) {\r\n hasError = true;\r\n }\r\n\r\n setData({\r\n value: event.target.value,\r\n error: hasError,\r\n index: index\r\n });\r\n }}\r\n />\r\n );\r\n};\r\n\r\nconst NumberFieldWithUnits = (props: NumberFieldProps) => {\r\n const {data, min, max, setData, step=1.0, ...other} = props;\r\n const units = LocalScene.viewProjectionUnits;\r\n\r\n const [convertedMin, setConvertedMin] = useState(0);\r\n const [convertedMax, setConvertedMax] = useState(0);\r\n const [convertedData, setConvertedData] = useState({\r\n value: 0,\r\n error: false\r\n });\r\n\r\n const convertNearestStep = (value, roundFunc) => {\r\n if (units === Units.Meters) {\r\n return value;\r\n };\r\n\r\n const converted = converter.convert(value, Units.Meters, units, 2);\r\n let numSteps = roundFunc(converted / step);\r\n return parseFloat((numSteps * step).toFixed(2));\r\n };\r\n\r\n useEffect(() => {\r\n // Initial conversion from meters to new units\r\n setConvertedMin(convertNearestStep(min, Math.floor));\r\n setConvertedMax(convertNearestStep(max, Math.ceil));\r\n setConvertedData({\r\n value: convertNearestStep(data.value, Math.floor),\r\n error: data.error\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n // Update the original state\r\n setData({...convertedData});\r\n }, [convertedData]);\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport type DropdownOption = [value: any, text: string];\r\n\r\ninterface DropdownWithLabelProps {\r\n title: string;\r\n label?: string;\r\n value: string | number;\r\n onChange: (value) => void;\r\n disabled?: boolean;\r\n seperator?: number[]\r\n options: DropdownOption[];\r\n}\r\n\r\nexport const DropdownWithLabel = (props: DropdownWithLabelProps) => {\r\n const {title, label, value, onChange, disabled=false,\r\n seperator, options} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const menuOptions = useMemo(() => {\r\n return optionsToDropdown(options, seperator);\r\n }, [options]);\r\n\r\n return (\r\n
\r\n
\r\n \r\n {title}\r\n \r\n
\r\n\r\n {label && \r\n {label}\r\n }\r\n\r\n {\r\n onChange(event.target.value);\r\n }}\r\n >\r\n {menuOptions}\r\n \r\n
\r\n );\r\n};\r\n\r\ninterface DropdownWithLabelInlineProps {\r\n title: string;\r\n value: string | number;\r\n onChange: (value) => void;\r\n options: [value: any, text: string][];\r\n}\r\n\r\nexport const DropdownWithLabelInline = (props: DropdownWithLabelInlineProps) => {\r\n const {title, value, options, onChange} = props;\r\n const theme = useTheme();\r\n\r\n const menuOptions = useMemo(() => {\r\n return optionsToDropdown(options);\r\n }, [options]);\r\n\r\n return (\r\n \r\n \r\n {title}\r\n \r\n\r\n \r\n {\r\n onChange(event.target.value);\r\n }}\r\n >\r\n {menuOptions}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const optionsToDropdown = (options: [value: any, text: string][], seperator?: number[]) => {\r\n let menuOptions = [];\r\n\r\n options.forEach((data, index) => {\r\n const [value, text] = data;\r\n\r\n menuOptions.push((\r\n \r\n {text}\r\n \r\n ));\r\n\r\n const hasSeperator = seperator && seperator.includes(index);\r\n const isLastItem = index === options.length - 1;\r\n\r\n if (hasSeperator && !isLastItem) {\r\n menuOptions.push((\r\n \r\n ));\r\n }\r\n });\r\n\r\n return menuOptions;\r\n};\r\n\r\ninterface FolderWithLabelProps {\r\n title: string;\r\n label?: string;\r\n value: string | number;\r\n onChange: (value) => void;\r\n}\r\n\r\nexport const FolderWithLabel = (props: FolderWithLabelProps) => {\r\n const {title, label, value, onChange} = props;\r\n const classes = useStyles();\r\n\r\n const handleFolderChange = async () => {\r\n const result = await dialog.showOpenDialog({\r\n properties: ['openDirectory']\r\n });\r\n\r\n if (result.canceled) return;\r\n let folderPath = slash(result.filePaths[0]);\r\n onChange(folderPath);\r\n };\r\n\r\n return (\r\n
\r\n
\r\n \r\n {title}\r\n \r\n\r\n \r\n \r\n \r\n
\r\n\r\n \r\n {value ? value : label}\r\n \r\n
\r\n );\r\n};\r\n\r\ninterface FileWithLabelProps {\r\n title: string;\r\n label?: string;\r\n filter: {name: string; extensions: string[]}[]\r\n value: string | number;\r\n onChange: (value) => void;\r\n optional?: boolean;\r\n saveFile?: boolean;\r\n}\r\n\r\nexport const FileWithLabel = (props: FileWithLabelProps) => {\r\n const {title, label, filter, value, onChange,\r\n optional=false, saveFile=false} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const handleFileChange = () => {\r\n dialog.showOpenDialog({\r\n title: title,\r\n properties: ['openFile'],\r\n filters: filter\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n let folderPath = slash(result.filePaths[0]);\r\n onChange(folderPath);\r\n });\r\n };\r\n\r\n const handleSaveFileChange = () => {\r\n dialog.showSaveDialog({\r\n title: title,\r\n filters: filter\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n onChange(result.filePath);\r\n });\r\n };\r\n\r\n const handleChange = saveFile\r\n ? handleSaveFileChange\r\n : handleFileChange;\r\n\r\n return (\r\n
\r\n
\r\n \r\n {title}\r\n \r\n\r\n
\r\n {value && optional && ( {\r\n onChange(null);\r\n }}\r\n size=\"large\">\r\n \r\n )}\r\n\r\n \r\n {saveFile ? \r\n : }\r\n \r\n
\r\n\r\n
\r\n\r\n \r\n {value ? value : label}\r\n \r\n
\r\n );\r\n};\r\n\r\ninterface InputWithLabelProps {\r\n title: string;\r\n label?: string | JSX.Element;\r\n value: string | number;\r\n onChange: (value) => void;\r\n required?: boolean;\r\n disabled?: boolean;\r\n error?: boolean;\r\n multiline?: boolean;\r\n placeholder?: string;\r\n}\r\n\r\nexport const InputWithLabel = (props: InputWithLabelProps) => {\r\n const classes = useStyles();\r\n const {value, title, onChange, label, required=true,\r\n disabled=false, error=false, ...other} = props;\r\n\r\n const [touched, setTouched] = useState(false);\r\n\r\n const onInputChange = useCallback((event) => {\r\n onChange(event.target.value);\r\n }, [onChange]);\r\n\r\n const onBlur = useCallback(() => {\r\n setTouched(true);\r\n }, []);\r\n\r\n return (\r\n
\r\n
\r\n {title}\r\n
\r\n\r\n \r\n\r\n \r\n {label}\r\n \r\n
\r\n );\r\n};\r\n\r\ninterface TextWithLabelProps {\r\n title: string\r\n value?: string\r\n label?: string | JSX.Element\r\n}\r\n\r\nexport const TextWithLabel = (props: TextWithLabelProps) => {\r\n const {title, label, value} = props;\r\n\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n\r\n const renderAsHTML = isHTML(value);\r\n const style = theme.typography.body1 as any;\r\n\r\n return (\r\n
\r\n
\r\n {title}\r\n
\r\n\r\n {value && \r\n {renderAsHTML && }\r\n\r\n {!renderAsHTML && \r\n {value}\r\n }\r\n }\r\n\r\n {label && \r\n {label}\r\n }\r\n
\r\n );\r\n};\r\n\r\ninterface TextFieldWithLabelInlineProps {\r\n title: string\r\n value: string\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const TextFieldWithLabelInline = (props: TextFieldWithLabelInlineProps) => {\r\n const {value, setValue, title} = props;\r\n\r\n const theme = useTheme();\r\n\r\n const onChange = useCallback((event) => {\r\n setValue(event.target.value);\r\n }, []);\r\n\r\n return (\r\n \r\n \r\n {title}\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface CheckboxWithLabelProps {\r\n title: string;\r\n label?: string;\r\n value: boolean;\r\n onChange: (value) => void;\r\n}\r\n\r\nexport const CheckboxWithLabel = (props: CheckboxWithLabelProps) => {\r\n const {title, label, value, onChange} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const onCheckboxChange = useCallback((_, checked) => {\r\n onChange(checked);\r\n }, [onChange]);\r\n\r\n return (\r\n
\r\n
\r\n \r\n {title}\r\n \r\n\r\n \r\n
\r\n\r\n \r\n {label}\r\n \r\n
\r\n );\r\n};\r\n\r\ninterface SwitchWithLabelProps {\r\n label: string;\r\n tooltip?: string;\r\n startAdornment?: React.ReactNode;\r\n checked: boolean;\r\n onChange: (event, checked: boolean) => void;\r\n}\r\n\r\nexport const SwitchWithLabel = (props: SwitchWithLabelProps) => {\r\n const {label, tooltip, startAdornment, checked, onChange} = props;\r\n\r\n const theme = useTheme();\r\n\r\n return (\r\n
\r\n
\r\n {startAdornment}\r\n\r\n \r\n {label}\r\n \r\n
\r\n\r\n {tooltip && (\r\n \r\n \r\n \r\n )}\r\n\r\n {!tooltip && (\r\n \r\n )}\r\n\r\n
\r\n );\r\n};\r\n\r\ninterface SwitchWithLabelInlineProps {\r\n title: string;\r\n value: boolean;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const SwitchWithLabelInline = (props: SwitchWithLabelInlineProps) => {\r\n const {title, value, setValue} = props;\r\n const theme = useTheme();\r\n\r\n const onChange = useCallback(() => {\r\n setValue(!value);\r\n }, [value]);\r\n\r\n return (\r\n \r\n {title}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface EditableTextFieldProps {\r\n title: string;\r\n value: string;\r\n onSubmit(value: string): void;\r\n}\r\n\r\nexport const EditableTextField = (props: EditableTextFieldProps) => {\r\n const {title, value, onSubmit} = props;\r\n\r\n const theme = useTheme();\r\n const {permissions} = useAuth();\r\n\r\n const [editing, setEditing] = useState(false);\r\n const [newValue, setNewValue] = useState(\"\");\r\n\r\n const renderAsHTML = isHTML(value);\r\n const style = theme.typography.body1 as any;\r\n\r\n useEffect(() => {\r\n setEditing(false);\r\n }, [value]);\r\n\r\n return (\r\n
\r\n
\r\n {title}\r\n\r\n {permissions.edit && {\r\n onSubmit(newValue);\r\n }}\r\n onClick={() => {\r\n setNewValue(value);\r\n }}\r\n />}\r\n\r\n
\r\n\r\n {editing && {\r\n setNewValue(event.target.value);\r\n }}\r\n />}\r\n\r\n {!editing && \r\n {renderAsHTML && }\r\n\r\n {!renderAsHTML && \r\n {value}\r\n }\r\n }\r\n
\r\n );\r\n};\r\n\r\ninterface EditableDropdownProps {\r\n title: string;\r\n value: string;\r\n onSubmit(value: string): void;\r\n options: [value: any, text: string][];\r\n}\r\n\r\nexport const EditableDropdown = (props: EditableDropdownProps) => {\r\n const {title, value, onSubmit, options} = props;\r\n\r\n const theme = useTheme();\r\n const {permissions} = useAuth();\r\n const {t} = useTranslation();\r\n\r\n const [editing, setEditing] = useState(false);\r\n const [newValue, setNewValue] = useState(null);\r\n\r\n const currentOption = options\r\n .find(option => option[0] === value);\r\n\r\n const newOption = options\r\n .find(option => option[0] === newValue);\r\n\r\n const menuOptions = useMemo(() => {\r\n return options.map((option, index) => {\r\n const [value, text] = option;\r\n\r\n return (\r\n \r\n {text}\r\n \r\n );\r\n });\r\n }, [options]);\r\n\r\n useEffect(() => {\r\n setEditing(false);\r\n }, [value]);\r\n\r\n useEffect(() => {\r\n if (newOption) return;\r\n setEditing(false);\r\n }, [newOption]);\r\n\r\n return (\r\n
\r\n
\r\n {title}\r\n\r\n {permissions.edit && onSubmit(newValue)}\r\n onClick={() => setNewValue(value)}\r\n />}\r\n
\r\n\r\n {editing && {\r\n setNewValue(event.target.value);\r\n }}\r\n >\r\n {menuOptions}\r\n }\r\n\r\n {!editing && \r\n {currentOption ? currentOption[1] : t(\"general.unknown\")}\r\n }\r\n
\r\n );\r\n};\r\n\r\ninterface EditButtonProps {\r\n onClick?: () => void;\r\n onSubmit: () => void;\r\n onCancel?: () => void;\r\n editing: boolean;\r\n setEditing: React.Dispatch;\r\n}\r\n\r\nexport const EditButtonGroup = (props: EditButtonProps) => {\r\n const {onClick, onSubmit, onCancel, editing, setEditing} = props;\r\n\r\n const theme = useTheme();\r\n\r\n return (\r\n
\r\n {/** Edit */}\r\n {!editing && {\r\n setEditing(true);\r\n onClick?.();\r\n }}\r\n size=\"large\">\r\n \r\n }\r\n\r\n {/** Cancel */}\r\n {editing && {\r\n setEditing(false);\r\n onCancel?.();\r\n }}\r\n style={{\r\n color: theme.palette.error.main\r\n }}\r\n size=\"large\">\r\n \r\n }\r\n\r\n {/** Confirm */}\r\n {editing && {\r\n setEditing(false);\r\n onSubmit();\r\n }}\r\n style={{\r\n color: theme.palette.success.main\r\n }}\r\n size=\"large\">\r\n \r\n }\r\n\r\n
\r\n );\r\n};\r\n\r\ninterface ColorPickerWithLabelInlineProps {\r\n title: string;\r\n value: string;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const ColorPickerWithLabelInline = (props: ColorPickerWithLabelInlineProps) => {\r\n const {title, value, setValue} = props;\r\n const theme = useTheme();\r\n\r\n return (\r\n \r\n {title}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface NeverAskCheckboxProps {\r\n value: boolean;\r\n onChange: React.Dispatch\r\n}\r\n\r\nexport const NeverAskCheckbox = (props: NeverAskCheckboxProps) => {\r\n const {value, onChange} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n const handleChange = (event) => {\r\n onChange(event.target.checked);\r\n };\r\n\r\n return (\r\n \r\n \r\n }\r\n label={\r\n \r\n {t('labels.never_ask_again')}\r\n \r\n }\r\n />\r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport {\r\n Box,\r\n LinearProgress,\r\n LinearProgressProps,\r\n Typography\r\n} from '@mui/material';\r\nimport { roundDigit } from '../viewer/utilities';\r\n\r\n// TODO: replace other linear progress with label with this (might need extra customization)\r\n\r\nexport const LinearProgressWithLabel = (props: LinearProgressProps & { value: number }) => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n {`${roundDigit(props.value, 2)}%`}\r\n \r\n \r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport {Box} from '@mui/material';\r\n\r\ninterface TabPanelProps {\r\n value: number;\r\n index: number;\r\n PanelProps?: object;\r\n BoxProps?: object;\r\n children: React.ReactNode\r\n}\r\n\r\nexport const TabPanel = (props: TabPanelProps) => {\r\n const {PanelProps={}, BoxProps={}, value, index} = props;\r\n\r\n const visible = value === index;\r\n\r\n return (\r\n \r\n {visible && \r\n \r\n {props.children}\r\n \r\n
}\r\n \r\n );\r\n};\r\n\r\nexport const TabProps = (index) => {\r\n return {\r\n id: `tab-${index}`,\r\n 'aria-controls': `tabpanel-${index}`,\r\n };\r\n};","import { Button, Chip, Divider, Icon, Theme, Typography, useTheme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport React, { useEffect, useMemo, useState } from \"react\";\r\nimport clsx from 'clsx';\r\nimport { ArrowTooltip } from \".\";\r\nimport { Scrollbars } from 'react-custom-scrollbars';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { DividerProps } from \"@mui/material/Divider\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n verticalDivider: {\r\n padding: theme.spacing(0.5, 0.25),\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n },\r\n icons: {\r\n '& > .fa': {\r\n margin: theme.spacing(2),\r\n },\r\n display: \"flex\",\r\n padding: theme.spacing(0.5),\r\n },\r\n iconButton: {\r\n minWidth: \"0px !important\",\r\n flex: 1\r\n },\r\n iconSize: {\r\n fontSize: \"1.0em\",\r\n width: \"auto\"\r\n },\r\n success: {\r\n color: theme.palette.success.main\r\n },\r\n error: {\r\n color: theme.palette.error.main\r\n },\r\n disabled: {\r\n opacity: 0.3\r\n },\r\n listIcon: {\r\n color: \"rgba(0, 0, 0, 0.54)\",\r\n fontSize: \"20px\"\r\n }\r\n })\r\n);\r\n\r\ninterface DenseDividerProps extends DividerProps {\r\n spacing?: number[] | number;\r\n}\r\n\r\nexport const DenseDivider = (props: DenseDividerProps) => {\r\n const {spacing, ...other} = props;\r\n\r\n let spacingDown;\r\n let spacingUp;\r\n\r\n if (typeof(spacing) == \"number\") {\r\n spacingDown = spacing;\r\n spacingUp = spacing;\r\n } else if (typeof(spacing) == \"object\") {\r\n spacingUp = spacing[0];\r\n spacingDown = spacing[1];\r\n } else {\r\n spacingUp = 20;\r\n spacingDown = 20;\r\n }\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface DividerWithTextProps {\r\n label: string;\r\n paddingTop?: number;\r\n paddingBottom?: number;\r\n}\r\n\r\n/**\r\n * Creates a divider with a chip element in the middle. Something\r\n * similar exists in the new material ui (5.x and up), but not in\r\n * our version (4.x), so we make our own instead.\r\n */\r\nexport const DividerWithText = (props: DividerWithTextProps) => {\r\n const theme = useTheme();\r\n\r\n const {label, paddingTop=32, paddingBottom=0} = props;\r\n\r\n return (\r\n
\r\n
\r\n\r\n \r\n \r\n \r\n\r\n
\r\n
\r\n );\r\n};\r\n\r\ninterface IconToolBarProps {\r\n margin?: number;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const IconToolBar = (props: IconToolBarProps) => {\r\n const {children, margin=0} = props;\r\n\r\n const classes = useStyles();\r\n\r\n return (\r\n
\r\n {children}\r\n
\r\n );\r\n};\r\n\r\nexport const ToolBarDivider = () => {\r\n const classes = useStyles();\r\n\r\n return (\r\n {\"|\"}\r\n );\r\n};\r\n\r\ninterface FontAwesomeIconProps {\r\n icon: string;\r\n success?: boolean;\r\n error?: boolean;\r\n disabled?: boolean;\r\n listIcon?: boolean;\r\n color?: \"inherit\" | \"disabled\" | \"success\" | \"error\" | \"primary\" | \"secondary\" | \"action\" | \"info\" | \"warning\";\r\n}\r\n\r\nexport const FontAwesomeIcon = (props: FontAwesomeIconProps) => {\r\n const {icon, color = \"primary\", success, error, disabled, listIcon} = props;\r\n\r\n const classes = useStyles();\r\n const errorColor = error ? classes.error : \"\";\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface ToolBarButtonProps {\r\n icon: string;\r\n title: string;\r\n onClick: (event?) => void;\r\n visible?: boolean;\r\n success?: boolean;\r\n error?: boolean;\r\n disabled?: boolean;\r\n color?: \"inherit\" | \"disabled\" | \"success\" | \"error\" | \"primary\" | \"secondary\" | \"action\" | \"info\" | \"warning\";\r\n}\r\n\r\nexport const ToolBarButton = (props: ToolBarButtonProps) => {\r\n const {icon, visible=true, title, onClick, color, success,\r\n error, disabled, ...other} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const tooltipText = disabled\r\n ? `${title} (${t('toolbar.button-disabled')})`\r\n : title;\r\n\r\n return (\r\n \r\n {visible && (\r\n \r\n \r\n \r\n )}\r\n \r\n );\r\n};\r\n\r\ninterface SlimScrollbarProps {\r\n scrollHeight?: number;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const SlimScrollbar = (props: SlimScrollbarProps) => {\r\n const {scrollHeight, children} = props;\r\n\r\n return (\r\n \r\n {/** Use scroll height that was passed in */}\r\n {scrollHeight && (\r\n {children}\r\n )}\r\n\r\n {/** No scroll height was provided */}\r\n {!scrollHeight && (\r\n {children}\r\n )}\r\n \r\n );\r\n};\r\n\r\ninterface DynamicScrollbarProps {\r\n scrollHeight: number;\r\n scrollPercent: number;\r\n children: React.ReactNode;\r\n}\r\n\r\nexport const DynamicScrollbar = (props: DynamicScrollbarProps) => {\r\n const {scrollHeight, scrollPercent, children} = props;\r\n\r\n const [scroll, setScroll] = useState(false);\r\n const [maxHeight, setMaxHeight] = useState(0);\r\n const listElementID = useMemo(() => nanoid(), []);\r\n\r\n const getMaxHeight = () => {\r\n const percentHeight = (scrollPercent/100) * window.innerHeight;\r\n return Math.min(scrollHeight, percentHeight);\r\n };\r\n\r\n const checkScrollHeight = () => {\r\n let element = document.getElementById(listElementID);\r\n if (!element) return;\r\n\r\n const height = element.offsetHeight;\r\n const maxHeight = getMaxHeight();\r\n\r\n setScroll(height > maxHeight);\r\n setMaxHeight(maxHeight);\r\n };\r\n\r\n useEffect(() => {\r\n checkScrollHeight();\r\n window.addEventListener('resize', checkScrollHeight);\r\n\r\n return () => {\r\n window.removeEventListener('resize', checkScrollHeight);\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n checkScrollHeight();\r\n }, [children, window.innerHeight]);\r\n\r\n return (\r\n \r\n {(!scroll) && (\r\n
\r\n {children}\r\n
\r\n )}\r\n\r\n {(scroll) && (\r\n \r\n
\r\n {children}\r\n
\r\n
\r\n )}\r\n
\r\n );\r\n};","import { memo } from \"react\";\r\n\r\n/** Component that only gets evaluated when the open state is modified */\r\nexport const memoWithOpen = (component) => {\r\n const areEqual = (prevProps, nextProps) => {\r\n return prevProps.open === nextProps.open;\r\n };\r\n\r\n return memo(component, areEqual);\r\n};","import {\r\n dialog,\r\n getCurrentWindow,\r\n Menu,\r\n isDevMode,\r\n remote,\r\n shell,\r\n logDirectoryPath,\r\n exitFromApp,\r\n clearTempFolder\r\n} from './electron-modules';\r\nimport {\r\n WorkflowExecutable,\r\n PythonExecutable\r\n} from \"./executable\";\r\nimport {t} from './localization';\r\n\r\nconst menuStateCache = {} as any;\r\n\r\nconst fileMenu = {\r\n get label() {\r\n return t(\"electron-menu.file.header\");\r\n },\r\n submenu: [\r\n {\r\n get label() {\r\n return t(\"electron-menu.file.open-workflow\");\r\n },\r\n click: async () => {\r\n new WorkflowExecutable().run({\r\n commands: []\r\n });\r\n }\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.file.global-settings\");\r\n },\r\n click: async () => {\r\n sendToMainWindow('open-global-settings');\r\n }\r\n },\r\n {\r\n type: 'separator'\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.file.new-project\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"new-project\");\r\n }\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.file.open-project\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"load-project\");\r\n }\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.file.open-project-cloud\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-cloud-projects\");\r\n }\r\n },\r\n {\r\n id: \"save-project\",\r\n get label() {\r\n return t(\"electron-menu.file.save-project\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"save-project\");\r\n }\r\n },\r\n {\r\n id: \"save-project-as\",\r\n get label() {\r\n return t(\"electron-menu.file.save-as\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"save-project-as\");\r\n }\r\n },\r\n {\r\n type: 'separator'\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.file.exit-without-saving\");\r\n },\r\n click: async () => {\r\n exitFromApp();\r\n }\r\n },\r\n ]\r\n};\r\n\r\nconst helpMenu = {\r\n get label() {\r\n return t(\"electron-menu.help.header\");\r\n },\r\n submenu: [\r\n {\r\n get label() {\r\n return t(\"electron-menu.help.about\");\r\n },\r\n click: async () => {\r\n sendToMainWindow('open-about');\r\n },\r\n },\r\n {\r\n visible: isDevMode,\r\n accelerator: 'Shift+F12',\r\n get label() {\r\n return t(\"electron-menu.help.dev-tools\");\r\n },\r\n click: () => {\r\n const mainWindow = remote.getCurrentWindow();\r\n mainWindow.toggleDevTools();\r\n },\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.help.open-logs\");\r\n },\r\n click: async () => {\r\n shell.openPath(logDirectoryPath);\r\n }\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.help.clear-cache\");\r\n },\r\n click: async () => {\r\n clearMlResources();\r\n }\r\n },\r\n {\r\n get label() {\r\n return t(\"electron-menu.help.support\");\r\n },\r\n click: async () => {\r\n shell.openExternal('https://solv3d.com/support/');\r\n }\r\n },\r\n ]\r\n};\r\n\r\nconst toolsMenu = {\r\n id: 'tools',\r\n get label() {\r\n return t(\"electron-menu.tools.header\");\r\n },\r\n submenu: [\r\n {\r\n id: 'projections',\r\n get label() {\r\n return t(\"electron-menu.tools.projections.header\");\r\n },\r\n submenu: [\r\n {\r\n id: 'projection-manager',\r\n get label() {\r\n return t(\"electron-menu.tools.projections.manager\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-projection-manager\");\r\n }\r\n },\r\n {\r\n id: 'local-projections',\r\n get label() {\r\n return t(\"electron-menu.tools.projections.local\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-local-projection\");\r\n }\r\n },\r\n ]\r\n },\r\n {\r\n id: \"aligner-menu\",\r\n get label() {\r\n return t(\"electron-menu.tools.data-aligner.header\");\r\n },\r\n submenu: [\r\n {\r\n id: 'aligner-advanced-menu',\r\n enabled: false,\r\n get label() {\r\n return t(\"electron-menu.tools.data-aligner.advanced\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-image-aligner-adv\");\r\n }\r\n },\r\n {\r\n id: 'aligner-basic-menu',\r\n enabled: false,\r\n get label() {\r\n return t(\"electron-menu.tools.data-aligner.basic\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-image-aligner-basic\");\r\n }\r\n },\r\n ]\r\n },\r\n {\r\n id: \"training-menu\",\r\n get label() {\r\n return t(\"electron-menu.tools.training.header\");\r\n },\r\n submenu: [\r\n {\r\n id: 'label-ortho-menu',\r\n enabled: false,\r\n get label() {\r\n return t(\"electron-menu.tools.training.ortho\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-label-ortho\");\r\n }\r\n },\r\n {\r\n id: 'label-scene-menu',\r\n get label() {\r\n return t(\"electron-menu.tools.training.scene\");\r\n },\r\n enabled: false,\r\n click: async () => {\r\n sendToMainWindow(\"open-label-scene\");\r\n }\r\n },\r\n ]\r\n },\r\n {\r\n id: 'point-markup-menu',\r\n get label() {\r\n return t(\"electron-menu.tools.markup.header\");\r\n },\r\n submenu: [\r\n {\r\n id: \"point-markup\",\r\n get label() {\r\n return t(\"electron-menu.tools.markup.modify\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-point-markup\");\r\n }\r\n },\r\n {\r\n id: \"data-splitting\",\r\n get label() {\r\n return t(\"electron-menu.tools.markup.split\");\r\n },\r\n click: async () => {\r\n sendToMainWindow(\"open-data-splitting\");\r\n }\r\n },\r\n ]\r\n },\r\n {\r\n id: 'exporter-menu',\r\n get label() {\r\n return t(\"electron-menu.tools.export.header\");\r\n },\r\n submenu: [\r\n {\r\n id: \"static-exporter-menu\",\r\n get label() {\r\n return t(\"electron-menu.tools.export.local\");\r\n },\r\n enabled: false,\r\n click: async () => {\r\n sendToMainWindow(\"open-static-export\");\r\n }\r\n },\r\n {\r\n id: \"cloud-exporter-menu\",\r\n get label() {\r\n return t(\"electron-menu.tools.export.cloud\");\r\n },\r\n enabled: false,\r\n click: async () => {\r\n sendToMainWindow(\"open-cloud-export\");\r\n }\r\n }\r\n ]\r\n }\r\n ]\r\n};\r\n\r\nconst debugMenu = {\r\n get label() {\r\n return t(\"electron-menu.debug.refresh\");\r\n },\r\n click: async () => {\r\n await clearTempFolder();\r\n getCurrentWindow().reload();\r\n }\r\n};\r\n\r\nconst sendToMainWindow = (message, payload=null) => {\r\n const mainWindow = remote.getCurrentWindow();\r\n mainWindow.webContents.send(message, payload);\r\n};\r\n\r\nconst clearMlResources = () => {\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", \"remove_ml_resources\",\r\n \"--remove\", true\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onClose: () => {\r\n dialog.showMessageBox({\r\n type: 'info',\r\n title: t(\"dialog.clear-cache-title\"),\r\n message: t(\"dialog.clear-cache-message\"),\r\n noLink: true\r\n });\r\n }\r\n });\r\n};\r\n\r\nconst setToolEnabled = (toolName, state) => {\r\n const menu = Menu.getApplicationMenu();\r\n const element = menu.getMenuItemById(toolName);\r\n if (!element) return;\r\n element.enabled = state;\r\n};\r\n\r\nconst setMenuState = async toolName => {\r\n if (isDevMode) {\r\n setToolEnabled(toolName, true);\r\n return;\r\n }\r\n\r\n if (toolName in menuStateCache) {\r\n const {running, state} = menuStateCache[toolName];\r\n if (running) return;\r\n\r\n // Apply saved menu state\r\n setToolEnabled(toolName, state);\r\n return;\r\n }\r\n\r\n // Insert default cache values\r\n menuStateCache[toolName] = {\r\n running: true,\r\n state: null\r\n };\r\n\r\n const exe = new PythonExecutable();\r\n\r\n exe.run({\r\n commands: ['--check-tool', toolName],\r\n showStatus: false,\r\n onLine: jsonData => {\r\n if (!jsonData.license_check) return;\r\n let {valid} = jsonData.license_check;\r\n\r\n // Update cache values\r\n menuStateCache[toolName] = {\r\n running: false,\r\n state: valid\r\n };\r\n\r\n setToolEnabled(toolName, valid);\r\n }\r\n });\r\n};\r\n\r\nconst checkAllowedMenuItems = async (isStandardProject: boolean) => {\r\n if (isStandardProject) {\r\n setMenuState('aligner-advanced-menu');\r\n setMenuState('static-exporter-menu');\r\n setMenuState('label-ortho-menu');\r\n setMenuState('label-scene-menu');\r\n } else {\r\n setToolEnabled('aligner-advanced-menu', false);\r\n setToolEnabled('training-menu', false);\r\n setToolEnabled('point-markup-menu', false);\r\n setToolEnabled('static-exporter-menu', false);\r\n setToolEnabled('save-project', false);\r\n setToolEnabled('save-project-as', false);\r\n }\r\n\r\n setMenuState('aligner-basic-menu');\r\n setMenuState('cloud-exporter-menu');\r\n};\r\n\r\nexport const buildElectronMenu = (isStandardProject: boolean) => {\r\n if (!Menu) return;\r\n\r\n const template = isDevMode\r\n ? [fileMenu, toolsMenu, helpMenu, debugMenu]\r\n : [fileMenu, toolsMenu, helpMenu];\r\n\r\n const menu = Menu.buildFromTemplate(template);\r\n Menu.setApplicationMenu(menu);\r\n checkAllowedMenuItems(isStandardProject);\r\n};\r\n","import React, { useEffect } from 'react';\r\nimport { useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { toast } from '../../app';\r\nimport { setLocalizedURL } from '../../localization';\r\nimport { ListItemText, MenuItem, Popover, Typography } from '@mui/material';\r\nimport { buildElectronMenu } from '../../electron-menu';\r\nimport { useViewer } from '../../hooks';\r\nimport { useSelector } from 'react-redux';\r\nimport { selectProjectType } from '../../redux/project-slice';\r\nimport { ProjectType } from '../../types/project';\r\n\r\nexport type Language = 'en' | 'de' | 'es' | 'fr' | 'ja' | 'ar';\r\n\r\nexport enum LanguageOptions {\r\n en = 'English',\r\n de = 'Deutsch',\r\n fr = 'Français',\r\n es = 'Español',\r\n ja = '日本語<',\r\n ar = 'عَرَبِيّ'\r\n};\r\n\r\ninterface LanguagePopoverProps {\r\n anchorEl: null | Element;\r\n onClose?: () => void;\r\n open?: boolean;\r\n}\r\n\r\nexport const LanguagePopover = (props: LanguagePopoverProps) => {\r\n const { anchorEl, onClose, open = false, ...other } = props;\r\n const { i18n, t } = useTranslation();\r\n const {viewer} = useViewer();\r\n\r\n const projectType = useSelector(selectProjectType);\r\n const isStandardProject = projectType === ProjectType.Standard;\r\n\r\n const handleChange = useCallback(async (language: Language): Promise => {\r\n onClose?.();\r\n await i18n.changeLanguage(language);\r\n const message = t('language-picker.language_changed');\r\n toast.success(message);\r\n }, [onClose, t, i18n]);\r\n\r\n useEffect(() => {\r\n buildElectronMenu(isStandardProject);\r\n viewer?.updateCompass();\r\n\r\n // Update language option in url. A small timeout is required\r\n const timeout = setTimeout(() => {\r\n setLocalizedURL(i18n.language);\r\n }, 500);\r\n\r\n return () => {\r\n clearTimeout(timeout);\r\n };\r\n }, [i18n.language, isStandardProject]);\r\n\r\n return (\r\n \r\n {(Object.keys(LanguageOptions) as Language[]).map((language) => {\r\n const text = LanguageOptions[language];\r\n\r\n return (\r\n handleChange(language)}\r\n key={language}\r\n >\r\n \r\n {text}\r\n \r\n )}\r\n />\r\n \r\n );\r\n })}\r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport { Button, Typography } from '@mui/material';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { usePopover } from '../../hooks';\r\nimport { Language, LanguageOptions, LanguagePopover } from './language-popover';\r\nimport { ArrowTooltip } from '../tooltips';\r\n\r\nexport const LanguageSwitch = () => {\r\n const { i18n, t } = useTranslation();\r\n const popover = usePopover();\r\n let text = LanguageOptions[i18n.language as Language];\r\n\r\n return (\r\n <>\r\n \r\n \r\n {\r\n text ? text : \"Unknown\"\r\n }\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport { Box, Button, Divider, Popover, Typography } from '@mui/material';\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useAuth } from '../../hooks';\r\nimport { isCloudSite } from '../../electron-modules';\r\nimport { AccessType } from '../../types/project';\r\n\r\ninterface AccountPopoverProps {\r\n anchorEl: null | Element;\r\n onClose?: () => void;\r\n open?: boolean;\r\n}\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n divider: {\r\n margin: theme.spacing(0, 1.5)\r\n },\r\n buttonParent: {\r\n display: \"flex\",\r\n padding: theme.spacing(0.5),\r\n justifyContent: \"center\"\r\n }\r\n })\r\n);\r\n\r\nexport const AccountPopover = (props: AccountPopoverProps) => {\r\n const { anchorEl, onClose, open = false } = props;\r\n\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n const { t } = useTranslation();\r\n\r\n const {linkAccount, signOut, loggedIn, user, permissions} = useAuth();\r\n\r\n const getAccountType = () => {\r\n switch (permissions.type) {\r\n case AccessType.ViewOnly:\r\n return t('user-account.view_only');\r\n case AccessType.Standard:\r\n return t('user-account.standard_user');\r\n case AccessType.Admin:\r\n return t('user-account.administrator');\r\n default:\r\n return t('user-account.unknown_user_type');\r\n }\r\n };\r\n\r\n const accountType = getAccountType();\r\n\r\n return (\r\n \r\n {/** Standard user profile */}\r\n {loggedIn && \r\n \r\n {(user?.firstName || user?.lastName) && \r\n {`${user.firstName} ${user.lastName}`}\r\n }\r\n\r\n {isCloudSite && \r\n {`(${accountType})`}\r\n }\r\n\r\n {user?.email && \r\n {user.email}\r\n }\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n {t(\"user-account.logout_engine_cloud\")}\r\n \r\n \r\n }\r\n\r\n {/** Anonymous view only */}\r\n {!loggedIn && isCloudSite && \r\n \r\n \r\n {t('user-account.accessing_the_project_as_an_anonymous')}\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n {t(\"user-account.login_engine_cloud\")}\r\n \r\n \r\n }\r\n\r\n {/** Unlinked account */}\r\n {!loggedIn && !isCloudSite && \r\n \r\n \r\n {t('user-account.an_linked_engine_cloud_account_is_required')}\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n {t(\"user-account.login_engine_cloud\")}\r\n \r\n \r\n }\r\n\r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport AccountCircleIcon from '@mui/icons-material/AccountCircle';\r\nimport { ArrowTooltip } from '../tooltips';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { usePopover } from '../../hooks';\r\nimport { IconButton } from '@mui/material';\r\nimport { AccountPopover } from './account-popover';\r\n\r\nexport const AccountButton = () => {\r\n const { t } = useTranslation();\r\n const popover = usePopover();\r\n\r\n return <>\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n ;\r\n};","import React, { useEffect } from \"react\";\r\nimport { toast, Toaster as HotToaster, useToasterStore } from 'react-hot-toast';\r\nimport { useTheme, alpha } from \"@mui/material\";\r\n\r\nexport const Toaster = () => {\r\n const theme = useTheme();\r\n const { toasts } = useToasterStore();\r\n\r\n const maxNumberToasts = 3;\r\n\r\n useEffect(() => {\r\n toasts\r\n .filter((t) => t.visible)\r\n .filter((_, i) => i >= maxNumberToasts)\r\n .forEach((t) => toast.remove(t.id));\r\n }, [toasts]);\r\n\r\n return (\r\n \r\n );\r\n};\r\n","import React, { useCallback } from \"react\";\r\nimport { Theme } from \"@mui/material\";\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport Typography, { TypographyProps } from \"@mui/material/Typography\";\r\nimport { openExternalLink } from \"../urls\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n typographyLink: {\r\n display: \"inline\",\r\n fontWeight: \"bold\",\r\n color: \"rgb(25, 118, 210)\",\r\n cursor: \"pointer\",\r\n \"&:hover\": {\r\n textDecoration: \"underline\",\r\n textDecorationColor: \"rgb(25, 118, 210, 0.4)\",\r\n }\r\n }\r\n }),\r\n);\r\n\r\ninterface TypographyLinkProps extends TypographyProps {\r\n text: string\r\n url: string\r\n}\r\n\r\nexport const TypographyLink = (props: TypographyLinkProps) => {\r\n const classes = useStyles();\r\n const {text, url, ...other} = props;\r\n\r\n const onClick = useCallback(() => {\r\n openExternalLink(url);\r\n }, [url]);\r\n\r\n return (\r\n \r\n {text}\r\n \r\n );\r\n};\r\n","import { Theme, Input } from \"@mui/material\";\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport React from \"react\";\r\nimport { useState, useEffect, useCallback } from \"react\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n colorPicker: {\r\n width: \"3.5em\",\r\n height: \"1.25em\",\r\n padding: \"0px\",\r\n border: \"1px solid darkgray\",\r\n borderRadius: \"2px\",\r\n \"&:hover\": {\r\n border: \"1px solid black\"\r\n }\r\n }\r\n })\r\n);\r\n\r\ninterface ColorPickerProps {\r\n value: string;\r\n onSubmit(value): void;\r\n disabled?: boolean;\r\n}\r\n\r\nexport const ColorPicker = (props: ColorPickerProps) => {\r\n const {value, onSubmit, disabled=false} = props;\r\n\r\n const classes = useStyles();\r\n const [color, setColor] = useState(\"#000000\");\r\n\r\n useEffect(() => {\r\n setColor(value);\r\n }, [value]);\r\n\r\n const onChange = useCallback((event) => {\r\n setColor(event.target.value);\r\n }, []);\r\n\r\n return (\r\n {\r\n onSubmit(color);\r\n }}\r\n disableUnderline={true}\r\n classes={{\r\n input: classes.colorPicker\r\n }}\r\n style={{\r\n opacity: disabled ? 0.38: 1\r\n }}\r\n type=\"color\"\r\n />\r\n );\r\n};","import {isDevMode, isElectronApp} from \"./electron-modules\";\r\n\r\ninterface LinkOptions {\r\n target?: string;\r\n name?: string;\r\n}\r\n\r\nconst engineCloudURLKey = \"engineCloudURL\";\r\n\r\nexport let tagQueryString = null;\r\n\r\nexport const setTagQueryString = (value: string) => {\r\n tagQueryString = value;\r\n};\r\n\r\nexport const setEngineCloudURL = (url: string, force: boolean = false): boolean => {\r\n if (!isElectronApp) {\r\n return false;\r\n }\r\n\r\n const currentEngineCloudURL = localStorage.getItem(engineCloudURLKey);\r\n\r\n if (currentEngineCloudURL && !force) {\r\n return false;\r\n }\r\n\r\n if (currentEngineCloudURL === url) {\r\n return false;\r\n }\r\n\r\n localStorage.setItem(engineCloudURLKey, url);\r\n engineCloudURL = url;\r\n\r\n return true;\r\n};\r\n\r\nexport let engineCloudURL = (() => {\r\n if (!isElectronApp) {\r\n return window.location.origin;\r\n }\r\n\r\n const engineCloudURL = localStorage.getItem(engineCloudURLKey);\r\n\r\n if (!engineCloudURL) {\r\n return isDevMode\r\n ? \"http://127.0.0.1:3001\"\r\n : \"https://engine.solv3d.com\";\r\n }\r\n\r\n return engineCloudURL;\r\n})();\r\n\r\nexport const redirectToLogin = () => {\r\n const searchParams = new URLSearchParams({\r\n returnTo: window.location.href\r\n }).toString();\r\n\r\n window.location.href = `/login?${searchParams}`;\r\n};\r\n\r\nexport const openExternalLink = (href: string, options: LinkOptions = {}) => {\r\n let element = document.createElement('a');\r\n\r\n element.setAttribute(\"href\", href);\r\n\r\n if (options.target) {\r\n element.setAttribute(\"target\", options.target);\r\n } else {\r\n element.setAttribute(\"target\", \"_blank\");\r\n }\r\n\r\n if (options.name) {\r\n element.setAttribute('download', options.name);\r\n }\r\n\r\n element.style.display = 'none';\r\n document.body.appendChild(element);\r\n element.click();\r\n document.body.removeChild(element);\r\n};","import {createSlice} from '@reduxjs/toolkit';\r\n\r\nexport interface AerialViewState {\r\n center: number[];\r\n zoom: number;\r\n rotation: number;\r\n basemap: string;\r\n}\r\n\r\nexport interface SceneCameraState {\r\n camera: string;\r\n fov: number;\r\n angles: number[];\r\n lookat: number[];\r\n orbit: number[];\r\n pivot: number[];\r\n}\r\n\r\ninterface CameraState {\r\n transform: string;\r\n adjustments: object,\r\n height: number;\r\n aerialState: AerialViewState;\r\n sceneState: SceneCameraState;\r\n}\r\n\r\nexport const initialAerialState = {\r\n center: [0, 0],\r\n zoom: 0,\r\n rotation: 0,\r\n basemap: \"open-street-maps\"\r\n} as AerialViewState;\r\n\r\nexport const initialSceneState = {\r\n camera: null,\r\n fov: null,\r\n angles: null,\r\n lookat: null,\r\n orbit: null,\r\n pivot: null\r\n} as SceneCameraState;\r\n\r\nexport const cameraStateSlice = createSlice({\r\n name: 'camera',\r\n initialState: {\r\n transform: null,\r\n adjustments: {},\r\n height: 3.0,\r\n aerialState: initialAerialState,\r\n sceneState: initialSceneState\r\n } as CameraState,\r\n reducers: {\r\n changeCameraTransform: (state, action) => {\r\n state.transform = action.payload;\r\n },\r\n changeCameraState: (state, action) => {\r\n state.sceneState = action.payload;\r\n },\r\n changeCameraHeight: (state, action) => {\r\n state.height = action.payload;\r\n },\r\n changeBasicAdjustments: (state, action) => {\r\n state.adjustments = action.payload;\r\n },\r\n changeSavedAerialState: (state, action) => {\r\n state.aerialState = action.payload;\r\n },\r\n resetCameraState: (state, action) => {\r\n state.sceneState = {...initialSceneState};\r\n },\r\n resetAerialState: (state, action) => {\r\n state.aerialState = {...initialAerialState};\r\n }\r\n }\r\n});\r\n\r\nexport const {\r\n changeCameraState,\r\n changeCameraTransform,\r\n changeCameraHeight,\r\n changeBasicAdjustments,\r\n changeSavedAerialState,\r\n resetCameraState,\r\n resetAerialState\r\n} = cameraStateSlice.actions;\r\n\r\nexport default cameraStateSlice.reducer;\r\n\r\nexport const selectCameraHeight = state => state.camera.height as number;\r\nexport const selectActiveCamera = state => state.camera.sceneState.camera as string;\r\nexport const selectCameraState = state => state.camera.sceneState as SceneCameraState;\r\nexport const selectOrbitMode = state => !!state.camera.sceneState.orbit as boolean;\r\nexport const selectCameraTransform = state => state.camera.transform as string;\r\nexport const selectBasicAdjustments = state => state.camera.adjustments as object;\r\nexport const selectSavedAerialState = state => state.camera.aerialState as AerialViewState;","/* eslint-disable import/no-webpack-loader-syntax */\r\nimport i18n from \"i18next\";\r\nimport { initReactI18next } from \"react-i18next\";\r\nimport LanguageDetector from \"i18next-browser-languagedetector\";\r\n\r\nimport en from \"./translations/en.json\";\r\nimport de from \"./translations/de.json\";\r\nimport fr from \"./translations/fr.json\";\r\nimport es from \"./translations/es.json\";\r\nimport ja from \"./translations/ja.json\";\r\nimport ar from \"./translations/ar.json\";\r\n\r\nconst resources = {\r\n en: {translation: en},\r\n de: {translation: de},\r\n fr: {translation: fr},\r\n es: {translation: es},\r\n ja: {translation: ja},\r\n ar: {translation: ar}\r\n};\r\n\r\n/** Makes sure that unsupported languages are ignored */\r\nconst supportedLngs = Object.keys(resources);\r\n\r\ni18n\r\n .use(initReactI18next)\r\n .use(LanguageDetector)\r\n .init({\r\n resources,\r\n detection: {\r\n cookieMinutes: 365*24*60 // one year\r\n },\r\n supportedLngs,\r\n fallbackLng: \"en\",\r\n interpolation: {\r\n escapeValue: false\r\n }\r\n });\r\n\r\nexport default i18n;\r\nexport const t = i18n.t;","export * from \"./i18n\";\r\n\r\n/** Add the language flag to the specified url */\r\nexport const getLocalizedURL = (url: string, language: string) => {\r\n return url.includes(\"?\")\r\n ? `${url}&lng=${language}`\r\n : `${url}?lng=${language}`;\r\n};\r\n\r\n/** Update the window url to include the language flag */\r\nexport const setLocalizedURL = (language: string) => {\r\n const url = new URL(window.location as any);\r\n url.searchParams.set('lng', language);\r\n window.history.pushState({}, '', url as any);\r\n};\r\n","import React, {useEffect, useState, memo} from \"react\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {fs, isStaticSite} from '../electron-modules';\r\nimport {DraggableDialog, IconToolBar, ToolBarButton, ToolBarDivider} from \"../components\";\r\nimport {\r\n FormHelperText,\r\n MenuItem,\r\n Select\r\n} from \"@mui/material\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport {dialog} from \"../electron-modules\";\r\nimport {\r\n pngFilter\r\n} from \"../file-extensions\";\r\nimport slash from \"slash\";\r\nimport { useViewer } from \"../hooks\";\r\nimport { openExternalLink } from \"../urls\";\r\nimport { Units } from \"../types/project\";\r\n\r\nconst useStyles = makeStyles((theme) =>\r\n createStyles({\r\n profileContainer: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n height: \"100%\"\r\n },\r\n toolbarDropdown: {\r\n flex: 1,\r\n paddingLeft: theme.spacing(1),\r\n paddingRight: theme.spacing(1)\r\n },\r\n profileChart: {\r\n flex: 1,\r\n overflow: \"hidden\",\r\n padding: theme.spacing(2)\r\n }\r\n })\r\n);\r\n\r\ninterface PointProfileProps {\r\n open: boolean;\r\n setOpen: (state: boolean) => void;\r\n}\r\n\r\nexport const PointProfile = memo((props: PointProfileProps) => {\r\n const {open, setOpen} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [samplingType, setSamplingType] = useState('lowest');\r\n const [displayUnits, setDisplayUnits] = useState(Units.Meters);\r\n\r\n const onRefModified = (container) => {\r\n if (!container) return;\r\n viewer.initProfileContainer(samplingType, displayUnits);\r\n };\r\n\r\n const reloadPointsProfile = () => {\r\n viewer.refreshPointProfile();\r\n };\r\n\r\n const resetPointsProfileView = () => {\r\n viewer.resetPointProfileView();\r\n };\r\n\r\n const savePointProfileImage = () => {\r\n if (isStaticSite) {\r\n savePointProfileImageBrowser();\r\n } else {\r\n savePointProfileImageElectron();\r\n }\r\n };\r\n\r\n const savePointProfileImageBrowser = () => {\r\n const imageBase64 = viewer.getPointProfileImage();\r\n const name = `${viewer.projectName}.png`;\r\n openExternalLink(imageBase64, {name});\r\n };\r\n\r\n const savePointProfileImageElectron = () => {\r\n dialog.showSaveDialog({\r\n defaultPath: viewer.projectName,\r\n filters: [...pngFilter],\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n if (result.filePath) {\r\n const filePath = slash(result.filePath);\r\n const imageBase64 = viewer.getPointProfileImage();\r\n let imageBase64Data = imageBase64.replace(/^data:image\\/\\w+;base64,/, '');\r\n\r\n const imageBuffer = Buffer.from(imageBase64Data, 'base64');\r\n fs.writeFileSync(filePath, imageBuffer, {encoding: \"base64\"});\r\n console.log(`Point Profile Image saved to ${filePath}`);\r\n }\r\n }).catch(error => {\r\n console.log(error);\r\n });\r\n return;\r\n };\r\n\r\n const updateUnits = (event) => {\r\n setDisplayUnits(event.target.value);\r\n };\r\n\r\n const updateSamplingType = (event) => {\r\n setSamplingType(event.target.value);\r\n };\r\n\r\n const onClose = () => {\r\n setOpen(false);\r\n };\r\n\r\n useEffect(() => {\r\n viewer?.setPointProfileSampling(samplingType);\r\n }, [viewer, samplingType]);\r\n\r\n useEffect(() => {\r\n viewer?.setPointProfileUnits(displayUnits);\r\n }, [viewer, displayUnits]);\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n viewer?.resetPointProfile();\r\n }, [viewer, open]);\r\n\r\n return (\r\n \r\n \r\n
\r\n\r\n \r\n\r\n
\r\n \r\n {t('units.meters')}\r\n {t('units.feet')}\r\n {t('units.survey-feet')}\r\n \r\n {t('profile.profile-units')}\r\n
\r\n\r\n
\r\n \r\n {t('profile.highest')}\r\n {t('profile.lowest')}\r\n {t('profile.all-points')}\r\n \r\n {t('profile.profile-type')}\r\n
\r\n\r\n \r\n\r\n {/* Refresh points base on view */}\r\n \r\n\r\n {/* Reset zoom and position */}\r\n \r\n\r\n {/* Download profile */}\r\n \r\n\r\n
\r\n\r\n
\r\n \r\n
\r\n\r\n
\r\n \r\n
\r\n );\r\n});","import {\r\n isDevMode,\r\n app,\r\n fs,\r\n fse,\r\n child,\r\n process,\r\n logDirectoryPath\r\n} from \"./electron-modules\";\r\nimport path from \"path\";\r\nimport manifest from \"../package.json\";\r\nimport slash from \"slash\";\r\n\r\nconst engineMessageTypeJSON = \"NODEJSJSONDATA\";\r\n\r\ninterface ExeRunOptions {\r\n commands: any[];\r\n showStatus?: boolean;\r\n saveLogs?: boolean;\r\n onLine?: (data) => void;\r\n onLogs?: (message: string) => void;\r\n onClose?: (error: boolean) => void;\r\n}\r\n\r\ninterface DevConfig {\r\n \"exe-python\": string;\r\n \"exe-main\": string;\r\n \"testing-python\": string;\r\n \"testing-engine\": string;\r\n \"testing\": boolean\r\n}\r\n\r\nconst getDevModeConfig = () => {\r\n if (!isDevMode) return;\r\n\r\n const appPath = slash(app.getAppPath());\r\n const text = fs.readFileSync(`${appPath}/develop.env`);\r\n const data = JSON.parse(text);\r\n\r\n if (data.testing) {\r\n console.warn(\"Running executable in dev mode\");\r\n }\r\n\r\n return data as DevConfig;\r\n};\r\n\r\nconst devModeConfig = getDevModeConfig();\r\n\r\nclass Executable {\r\n public exePath: string;\r\n public exeName: string;\r\n public running: boolean;\r\n private error = false;\r\n public child;\r\n public developerKey: string;\r\n public spawnDetached: boolean;\r\n public logText = [];\r\n private showStatus = true;\r\n\r\n constructor(exePath, exeName) {\r\n this.exePath = exePath;\r\n this.exeName = exeName;\r\n this.running = false;\r\n this.error = false;\r\n this.child = null;\r\n this.spawnDetached = false;\r\n }\r\n\r\n get path() {\r\n let basePath;\r\n let appPath = slash(app.getAppPath());\r\n let executablePath;\r\n\r\n if (devModeConfig) {\r\n if (devModeConfig.testing && this instanceof PythonExecutable) {\r\n executablePath = devModeConfig['testing-python'];\r\n } else {\r\n executablePath = devModeConfig[this.developerKey];\r\n }\r\n } else {\r\n // Calculate path using root + folder and name\r\n basePath = path.dirname(appPath);\r\n basePath = path.dirname(basePath);\r\n basePath = path.dirname(basePath);\r\n executablePath = path.join(basePath, this.exePath, this.exeName);\r\n }\r\n\r\n return executablePath;\r\n }\r\n\r\n statusMessage(message) {\r\n if (!this.showStatus) return;\r\n console.log(`[pid = ${this.child.pid}]: ${message}`);\r\n }\r\n\r\n parseCommandsList(commands) {\r\n // Convert objects to modified json\r\n for (let i=0;i {\r\n return ((index % 2) === 0)\r\n ? text\r\n : `\"${text}\"`;\r\n }).join(\" \");\r\n }\r\n\r\n run(options: ExeRunOptions) {\r\n if (this.running) {\r\n console.log(\"Cannot launch multiple instances\");\r\n return;\r\n }\r\n\r\n const {\r\n showStatus = true,\r\n saveLogs = false,\r\n commands = [],\r\n onClose,\r\n onLine,\r\n onLogs\r\n } = options;\r\n\r\n this.running = true;\r\n this.error = false;\r\n this.logText = [];\r\n this.showStatus = showStatus;\r\n\r\n let commandList = this.parseCommandsList(commands);\r\n let executablePath = this.path;\r\n\r\n let cwd = path.dirname(executablePath);\r\n this.child = child.spawn(executablePath, commandList, {\r\n cwd: cwd,\r\n env: {\r\n ...process.env,\r\n PYTHONUNBUFFERED: true,\r\n NODEJS: true\r\n },\r\n detached: this.spawnDetached\r\n });\r\n\r\n if (!this.child.pid) {\r\n console.error(`Error launching ${this.exeName} exe`);\r\n if (onClose) {\r\n onClose(true);\r\n }\r\n\r\n return;\r\n }\r\n\r\n let copyPasteCommands = this.copyableCommands(commandList);\r\n this.statusMessage(`${this.path} ${copyPasteCommands}`);\r\n\r\n this.child.on('close', () => {\r\n this.statusMessage(`close`);\r\n\r\n if (saveLogs) {\r\n let commandIndex = commandList.indexOf(\"-p\") + 1;\r\n if (commandIndex > 0) {\r\n let commandName = commandList[commandIndex];\r\n saveLogFile(commandName, this.logText);\r\n }\r\n }\r\n\r\n if (onClose) {\r\n onClose(this.error);\r\n }\r\n\r\n this.error = false;\r\n this.running = false;\r\n this.child = null;\r\n });\r\n\r\n if (onLine || onLogs || saveLogs) {\r\n this.child.stderr.on('data', (data) => {\r\n this.parseLines(data, onLine, onLogs);\r\n });\r\n\r\n this.child.stdout.on('data', (data) => {\r\n this.parseLines(data, onLine, onLogs);\r\n });\r\n }\r\n\r\n return this.child;\r\n }\r\n\r\n /** @private */\r\n parseLines(data, onLine: (data) => void, onLogs: (message: string) => void) {\r\n let dataString = data.toString();\r\n let lines = dataString.split(\"\\n\");\r\n\r\n lines.forEach(line => {\r\n line = line.trim();\r\n if (line === \"\") {\r\n return;\r\n }\r\n\r\n // Parse our response and only keep engine json response\r\n let split = line.split(\":\");\r\n let messageType = split[0].trim();\r\n let messageData = split.slice(1).join(\":\").trim();\r\n\r\n if (messageType === engineMessageTypeJSON) {\r\n try {\r\n let jsonData = JSON.parse(messageData);\r\n if (onLine) {\r\n onLine(jsonData);\r\n }\r\n } catch(err) {\r\n if (onLine) {\r\n onLine({});\r\n }\r\n }\r\n } else {\r\n if (onLogs) {\r\n onLogs(line);\r\n }\r\n this.logText.push(line);\r\n }\r\n });\r\n }\r\n\r\n destroy() {\r\n if (!this.running) {\r\n return;\r\n }\r\n\r\n this.running = false;\r\n this.error = true;\r\n\r\n try {\r\n child.execSync(\r\n `(Get-WmiObject -Class Win32_Process -Filter \"ProcessId = ${this.child.pid} OR ParentProcessId = ${this.child.pid}\").Terminate()`,\r\n {shell: \"powershell.exe\"}\r\n );\r\n } catch {\r\n // Do nothing\r\n }\r\n }\r\n}\r\n\r\nexport class PythonExecutable extends Executable {\r\n constructor() {\r\n super(\"exe-engine\", \"engine.exe\");\r\n this.developerKey = \"exe-python\";\r\n window.onbeforeunload = () => {\r\n this.destroy();\r\n };\r\n }\r\n\r\n write(text) {\r\n if (!this.running) {\r\n return;\r\n }\r\n\r\n this.child.stdin.write(text);\r\n }\r\n}\r\n\r\nexport class WorkflowExecutable extends Executable {\r\n constructor() {\r\n super(\"../\", `${manifest.workflowName}.exe`);\r\n this.developerKey = \"exe-main\";\r\n this.spawnDetached = true;\r\n }\r\n}\r\n\r\nconst saveLogFile = async (logPrefix, logText) => {\r\n const maxLogFiles = 50;\r\n\r\n const dateString = new Date()\r\n .toISOString()\r\n .replaceAll(\":\", \"-\");\r\n\r\n const logPath = path.join(\r\n logDirectoryPath,\r\n `${logPrefix} ${dateString}.txt`\r\n );\r\n\r\n const logs = logText.join(\"\\n\");\r\n await fse.writeFile(logPath, logs);\r\n\r\n const filenames = await fse.readdir(logDirectoryPath);\r\n if (filenames.length <= maxLogFiles) {\r\n return;\r\n }\r\n\r\n let oldest = new Date();\r\n let oldestFilePath;\r\n\r\n for (let filename of filenames) {\r\n const filePath = path.join(logDirectoryPath, filename);\r\n const stats = await fse.stat(filePath);\r\n\r\n if (stats.birthtime < oldest) {\r\n oldest = stats.birthtime;\r\n oldestFilePath = filePath;\r\n }\r\n }\r\n\r\n try {\r\n await fse.remove(oldestFilePath);\r\n } catch {\r\n // Nothing\r\n }\r\n};\r\n\r\nexport const trackToolUsage = (toolName: string) => {\r\n if (isDevMode) return;\r\n\r\n (async () => {\r\n new PythonExecutable().run({\r\n commands: ['--check-tool', toolName]\r\n });\r\n })();\r\n};","import path from \"path\";\r\nimport {app, storage, fs} from \"./electron-modules\";\r\nimport manifest from \"../package.json\";\r\n\r\nconst changeDuplicateNames = (projections) => {\r\n const projectionsByName = {};\r\n\r\n projections.forEach((projection) => {\r\n if (!projectionsByName[projection.name]) {\r\n projectionsByName[projection.name] = 2;\r\n } else {\r\n const newName = `${projection.name} (${projectionsByName[projection.name]})`;\r\n projectionsByName[projection.name]++;\r\n projection.name = newName;\r\n }\r\n });\r\n};\r\n\r\nexport const setStoragePath = (userSettings, isStaticSite) => {\r\n if (isStaticSite) return;\r\n\r\n const storagePath = path.join(app.getPath('appData'), 'SOLV3D Data');\r\n const engineStoragePath = path.join(app.getPath('appData'), `${manifest.workflowName}/storage`);\r\n const viewerStoragePath = path.join(app.getPath('appData'), `${manifest.productName}/storage`);\r\n\r\n if (!fs.existsSync(storagePath)) {\r\n fs.mkdirSync(storagePath);\r\n }\r\n\r\n for (const settingName of userSettings) {\r\n let oldName = path.join(viewerStoragePath, `${settingName}.json`);\r\n let newName = path.join(storagePath, `${settingName}.json`);\r\n if (fs.existsSync(oldName) && !fs.existsSync(newName)) {\r\n fs.copyFileSync(oldName, newName);\r\n }\r\n }\r\n if (fs.existsSync(path.join(storagePath, 'user-projections.json'))) {\r\n storage.setDataPath(storagePath);\r\n return;\r\n }\r\n\r\n const engineProjectionExist = fs.existsSync(path.join(engineStoragePath, 'user-projections.json'));\r\n const viewerProjectionExist = fs.existsSync(path.join(viewerStoragePath, 'projection.json'));\r\n\r\n let projectionData = [];\r\n if (viewerProjectionExist) {\r\n projectionData = [\r\n ...projectionData,\r\n ...storage.getSync('projection', {dataPath: viewerStoragePath})];\r\n }\r\n if (engineProjectionExist) {\r\n let engineProjections = storage.getSync('user-projections', {dataPath: engineStoragePath});\r\n Object.keys(engineProjections).forEach((key) => {\r\n let data = engineProjections[key];\r\n if ('transform' in data) {\r\n data.transform = {\r\n origin: data.transform.origin,\r\n translation: data.transform.translation,\r\n rotation: data.transform.rotation,\r\n scale: data.transform.scale\r\n };\r\n }\r\n let finalData = {type: 'proj4', name: key, ...data};\r\n projectionData.push(finalData);\r\n });\r\n }\r\n if (viewerProjectionExist && engineProjectionExist) {\r\n changeDuplicateNames(projectionData);\r\n }\r\n storage.setDataPath(storagePath);\r\n storage.setSync('user-projections', projectionData);\r\n};\r\n","import { nanoid } from '@reduxjs/toolkit';\r\nimport path from 'path';\r\nimport {setStoragePath} from \"./move-settings\";\r\n\r\n/** Electron specific modules that will fail for static html site */\r\n\r\nconst getCloudProjectID = () : string => {\r\n const pattern = /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i;\r\n const url = new URL(window.location.href);\r\n const parts = url.pathname.split(\"/\");\r\n return parts.find(x => pattern.test(x));\r\n};\r\n\r\nconst checkForCloudSite = (cloudProjectID) => {\r\n const url = new URL(window.location.href);\r\n const parts = url.pathname.split(\"/\");\r\n const hasViewer = parts.includes(\"viewer\");\r\n return hasViewer && !!cloudProjectID;\r\n};\r\n\r\nexport const electron = window.require\r\n ? window.require(\"electron\")\r\n : null;\r\n\r\nexport const child = electron\r\n ? window.require(\"child_process\")\r\n : null;\r\n\r\nexport const process = electron\r\n ? window.require(\"process\")\r\n : null;\r\n\r\nexport const remote = electron?.remote;\r\nexport const shell = electron?.shell;\r\nexport const ipcRenderer = electron?.ipcRenderer;\r\nexport const dialog = remote?.dialog;\r\nexport const app = remote?.app;\r\nexport const getCurrentWindow = remote?.getCurrentWindow;\r\nexport const Menu = remote?.Menu;\r\nexport const fs = remote?.require('fs');\r\nexport const fse = remote?.require('fs-extra');\r\nexport const glob = remote?.require('glob');\r\n\r\nexport const cloudProjectID = getCloudProjectID();\r\nexport const isStaticSite = !electron;\r\nexport const isElectronApp = !!electron;\r\nexport const isCloudSite = checkForCloudSite(cloudProjectID);\r\n\r\nexport const storage = electron\r\n ? remote.require('electron-json-storage')\r\n : null;\r\n\r\nexport const isDevMode = remote\r\n ? (app.isPackaged === false)\r\n : false;\r\n\r\nexport const tempDirectoryPath = app\r\n ? path.join(app.getPath('userData'), \"temp\", `temp-${nanoid()}`)\r\n : null;\r\n\r\nexport const logDirectoryPath = app\r\n ? path.join(app.getPath('userData'), \"logs\")\r\n : null;\r\n\r\nexport const getTemporaryFile = (suffix) => {\r\n return path.join(tempDirectoryPath, `${nanoid()}.${suffix}`);\r\n};\r\n\r\nexport const exitFromApp = async () => {\r\n await clearTempFolder();\r\n app.exit();\r\n};\r\n\r\nexport const clearTempFolder = async () => {\r\n if (isStaticSite) return;\r\n\r\n if (!fse.existsSync(tempDirectoryPath)) return;\r\n const filenames = await fse.readdir(tempDirectoryPath);\r\n const numRemoved = filenames.length;\r\n\r\n await fse.remove(tempDirectoryPath);\r\n if (numRemoved === 0) return;\r\n\r\n console.log(`Deleted ${numRemoved} temporary files`);\r\n};\r\n\r\nconst createInitialFolders = () => {\r\n if (isStaticSite) return;\r\n\r\n if (!fs.existsSync(tempDirectoryPath)) {\r\n console.log(\"Creating temporary folder...\");\r\n fs.mkdirSync(tempDirectoryPath, {recursive: true});\r\n }\r\n\r\n if (!fs.existsSync(logDirectoryPath)) {\r\n console.log(\"Creating log output folder...\");\r\n fs.mkdirSync(logDirectoryPath);\r\n }\r\n};\r\n\r\nexport const registerEvent = (eventName, callback) => {\r\n if(!ipcRenderer) return;\r\n ipcRenderer.removeAllListeners(eventName);\r\n ipcRenderer.on(eventName, callback);\r\n};\r\n\r\ncreateInitialFolders();\r\n\r\nconst userSettings = ['default-settings', 'global-settings'];\r\nsetStoragePath(userSettings, isStaticSite);","import { AssetType, WebSourceAsset } from \"../../redux/assets-slice\";\r\n\r\nexport const isModelFile = (asset) => {\r\n return (asset.type === AssetType.IFC)\r\n || (asset.type === AssetType.DXF)\r\n || (asset.type === AssetType.SHP);\r\n};\r\n\r\nexport const isStreamablePointsFile = (asset) => {\r\n return (asset.type === AssetType.Encompass)\r\n || (asset.type === AssetType.Potree);\r\n};\r\n\r\nexport const isRawPointsFile = (asset) => {\r\n return (asset.type === AssetType.LAS)\r\n || (asset.type === AssetType.E57Points);\r\n};\r\n\r\nexport const getModelLayers = (asset) => {\r\n return asset.data.map(layer => ({\r\n name: layer.name,\r\n originalId: layer.id,\r\n visible: layer.visible,\r\n color: layer.color\r\n }));\r\n};\r\n\r\nexport const getWebmapLayers = (asset: WebSourceAsset) => {\r\n return asset.data.layers.map(layer => ({\r\n originalId: layer.id,\r\n visible: layer.visible,\r\n identifier: String(layer.identifier),\r\n name: String(layer.name)\r\n }));\r\n};\r\n\r\nexport const getBaseAsset = (asset) => {\r\n return {\r\n name: asset.name,\r\n visible: asset.visible,\r\n originalId: asset.id,\r\n type: asset.type,\r\n };\r\n};\r\n\r\nexport const getTagsData = (asset) => {\r\n return asset.data.items.map(tag => {\r\n const values = {\r\n originalId: tag.id,\r\n name: tag.name,\r\n comment: tag.comment,\r\n date: tag.date,\r\n x: tag.x,\r\n y: tag.y,\r\n } as any;\r\n\r\n if (\"z\" in tag) {\r\n values.z = tag.z;\r\n }\r\n\r\n if (\"sceneState\" in tag) {\r\n values.sceneState = tag.sceneState;\r\n }\r\n\r\n if (\"annotations\" in tag) {\r\n values.annotations = tag.annotations\r\n .map(annotation => withOriginalID(annotation));\r\n }\r\n\r\n return values;\r\n });\r\n};\r\n\r\nexport const getImageData = (asset) => {\r\n return asset.data.map(image => {\r\n const values = {\r\n originalId: image.id,\r\n filename: image.name, // used for backwards compatability. replace with fileName after all clients are upgraded\r\n x: image.x,\r\n y: image.y,\r\n z: image.z,\r\n roll: image.roll,\r\n pitch: image.pitch,\r\n yaw: image.yaw\r\n };\r\n\r\n /** Planar images have additional information */\r\n if (asset.type === AssetType.Planar) {\r\n return {\r\n ...values,\r\n config: image.config\r\n };\r\n }\r\n\r\n return values;\r\n });\r\n};\r\n\r\ninterface ObjectProps {\r\n id: string;\r\n [key: string]: any;\r\n}\r\n\r\nexport const withOriginalID = (object: ObjectProps) => {\r\n const {id, ...other} = object;\r\n return {originalId: id, ...other};\r\n};","import {createSlice, nanoid} from '@reduxjs/toolkit';\r\nimport { ProjectType } from '../types/project';\r\n\r\ninterface ProjectState {\r\n id: string;\r\n name: string;\r\n path: string;\r\n type: ProjectType;\r\n uniqueSession: string;\r\n configVersion: string;\r\n}\r\n\r\nexport const defaultProjectTitle = 'project-settings.untitled-project';\r\n\r\n// Current config version\r\nexport const currentConfigVersion = \"3.25.0\";\r\n\r\n// Not possible to upgrade below this version\r\nexport const minimumConfigVersion = \"3.4.0\";\r\n\r\nexport const projectSlice = createSlice({\r\n name: 'project',\r\n initialState: {\r\n id: nanoid(),\r\n name: defaultProjectTitle,\r\n path: '',\r\n type: ProjectType.Standard,\r\n uniqueSession: nanoid(),\r\n configVersion: currentConfigVersion\r\n } as ProjectState,\r\n reducers: {\r\n updateProjectID: (state, action) => {\r\n state.id = action.payload;\r\n },\r\n updateSessionID: (state, action) => {\r\n state.uniqueSession = action.payload;\r\n },\r\n updateProjectName: (state, action) => {\r\n state.name = action.payload;\r\n },\r\n changePath: (state, action) => {\r\n state.path = action.payload;\r\n }\r\n }\r\n});\r\n\r\nexport const {\r\n updateProjectID,\r\n updateSessionID,\r\n updateProjectName,\r\n changePath\r\n} = projectSlice.actions;\r\n\r\nexport default projectSlice.reducer;\r\n\r\nexport const selectProjectID = (state): string => state.project.id as string;\r\nexport const selectProjectName = (state): string => state.project.name as string;\r\nexport const selectProjectType = (state): ProjectType => state.project.type as ProjectType;\r\nexport const selectSessionID = (state): string => state.project.uniqueSession as string;","import {nanoid, createSlice, PayloadAction} from '@reduxjs/toolkit';\r\nimport api from '../api';\r\n\r\nexport interface Folder {\r\n name: string;\r\n id: string;\r\n date: string;\r\n default?: boolean;\r\n allowAnonViewers: boolean,\r\n}\r\n\r\nexport const defaultFolderTitle = 'folder.default-folder';\r\n\r\nconst getByID = (state, folderID: string) => {\r\n return state.find(folder => folder.id === folderID);\r\n};\r\n\r\nconst generateDefaultFolder = () => {\r\n return {\r\n id: nanoid(),\r\n name: defaultFolderTitle,\r\n date: new Date().toISOString(),\r\n allowAnonViewers: true,\r\n default: true\r\n } as Folder;\r\n};\r\n\r\nexport const foldersSlice = createSlice({\r\n name: 'folders',\r\n initialState: [\r\n generateDefaultFolder()\r\n ],\r\n reducers: {\r\n createFolder: (state, action: PayloadAction<{\r\n name: string,\r\n allowAnonViewers: boolean\r\n }>) => {\r\n const {name, allowAnonViewers} = action.payload;\r\n\r\n const folder = {\r\n id: nanoid(),\r\n name,\r\n allowAnonViewers,\r\n date: new Date().toISOString(),\r\n default: false\r\n } as Folder;\r\n\r\n state.push(folder);\r\n },\r\n updateFolder: (state, action: PayloadAction<{\r\n folderID: string,\r\n name: string,\r\n allowAnonViewers: boolean\r\n }>) => {\r\n const {folderID, ...updates} = action.payload;\r\n\r\n const folder = getByID(state, folderID);\r\n if (!folder) return;\r\n\r\n for (let key in updates) {\r\n if (folder.hasOwnProperty(key)) {\r\n folder[key] = updates[key];\r\n };\r\n };\r\n\r\n if (!folder.default) return;\r\n\r\n // Add new default folder\r\n const newDefaultFolder = generateDefaultFolder();\r\n state.push(newDefaultFolder);\r\n\r\n // Set the current folder to custom\r\n folder.default = false;\r\n },\r\n deleteFolder: (state, action: PayloadAction) => {\r\n const folderID = action.payload;\r\n\r\n return state.filter(folder => {\r\n return folder.default || (folder.id !== folderID);\r\n });\r\n },\r\n\r\n /** Websocket specific */\r\n wsCreateFolder: (state, action: PayloadAction) => {\r\n const folder = action.payload;\r\n if (getByID(state, folder.id)) return;\r\n\r\n state.push(folder);\r\n },\r\n wsUpdateFolder: (state, action: PayloadAction) => {\r\n const {id, ...updates} = action.payload;\r\n\r\n let folder = getByID(state, id);\r\n if (!folder) return;\r\n\r\n for (let key in updates) {\r\n if (folder.hasOwnProperty(key)) {\r\n folder[key] = updates[key];\r\n };\r\n };\r\n },\r\n wsDeleteFolder: (state, action: PayloadAction) => {\r\n const folderID = action.payload;\r\n\r\n return state.filter(folder => {\r\n return folder.default || (folder.id !== folderID);\r\n });\r\n },\r\n }\r\n});\r\n\r\n/** Create a new folder and return the new folderID */\r\nexport const createFolder = (name = defaultFolderTitle, allowAnonViewers = true) => {\r\n return async (dispatch, getState) => {\r\n // Create new folder\r\n dispatch(foldersSlice.actions.createFolder({name, allowAnonViewers}));\r\n\r\n const folders = getState().folders as Folder[];\r\n const [folder] = folders.slice(-1);\r\n\r\n // Update cloud site\r\n await api.folders.create(folder);\r\n\r\n return folder;\r\n };\r\n};\r\n\r\nexport const {\r\n wsCreateFolder,\r\n wsUpdateFolder,\r\n wsDeleteFolder,\r\n deleteFolder,\r\n updateFolder\r\n} = foldersSlice.actions;\r\n\r\nexport default foldersSlice.reducer;\r\n\r\nexport const selectDefaultFolder = state =>\r\n state.folders.find(folder => folder.default) as Folder;\r\n\r\nexport const selectAllFolders = state => state.folders as Folder[];\r\n","import {createSlice, PayloadAction} from '@reduxjs/toolkit';\r\nimport {unknownProjectionMeters} from '../projections';\r\nimport { Units } from '../types/project';\r\n\r\nexport interface Projection {\r\n type: string,\r\n name?: string,\r\n string: string,\r\n default?: boolean,\r\n transform?: Transform\r\n}\r\n\r\nexport interface Transform {\r\n origin: number[];\r\n translation: number[];\r\n rotation: number;\r\n scale: number;\r\n}\r\n\r\ninterface ProjectionData {\r\n data: Projection;\r\n view: Projection;\r\n measureUnits: Units\r\n}\r\n\r\nexport const projectionsSlice = createSlice({\r\n name: 'projections',\r\n initialState: {\r\n data: unknownProjectionMeters,\r\n view: unknownProjectionMeters,\r\n measureUnits: Units.Meters\r\n } as ProjectionData,\r\n reducers: {\r\n updateDataProjection: (state, action: PayloadAction) => {\r\n state.data = action.payload;\r\n },\r\n updateViewProjection: (state, action: PayloadAction) => {\r\n state.view = action.payload;\r\n },\r\n changeMeasureUnits: (state, action: PayloadAction) => {\r\n state.measureUnits = action.payload;\r\n },\r\n }\r\n});\r\n\r\nexport const {\r\n updateDataProjection,\r\n updateViewProjection,\r\n changeMeasureUnits\r\n} = projectionsSlice.actions;\r\n\r\nexport default projectionsSlice.reducer;\r\n\r\nexport const selectViewProjection = state => state.projections.view as Projection;\r\nexport const selectDataProjection = state => state.projections.data as Projection;\r\nexport const selectMeasureUnits = state => state.projections.measureUnits as Units;","/* eslint-disable react-hooks/rules-of-hooks */\r\nimport React, { createContext, useEffect, useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { toast } from \"../app\";\r\nimport { isCloudSite, isElectronApp } from \"../electron-modules\";\r\nimport { getLocalizedURL } from \"../localization\";\r\nimport { engineCloudURL, openExternalLink, redirectToLogin } from \"../urls\";\r\nimport SuperTokens from \"supertokens-web-js\";\r\nimport { AccessType } from \"../types/project\";\r\nimport Session from \"supertokens-web-js/recipe/session\";\r\nimport EmailPassword from \"supertokens-web-js/recipe/emailpassword\";\r\nimport {signOut as stSignOut} from \"supertokens-web-js/lib/build/recipe/emailpassword\";\r\nimport { useWebSockets } from \"../hooks\";\r\nimport { ProviderProps } from \"./props\";\r\nimport semver from \"semver\";\r\nimport { currentConfigVersion } from \"../redux/project-slice\";\r\n\r\ninterface UserInfo {\r\n id: string;\r\n email: string;\r\n firstName: string;\r\n lastName: string;\r\n apiKey: string;\r\n}\r\n\r\ninterface ProjectPermissions {\r\n type: AccessType;\r\n access: boolean;\r\n create: boolean;\r\n delete: boolean;\r\n edit: boolean;\r\n}\r\n\r\nconst appCodeRefreshRate = 2000;\r\nconst appCodeMaxAttempts = 100;\r\nconst originalFetch = fetch;\r\n\r\nexport const asyncTimeout = (ms) => {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n};\r\n\r\nclass AuthHandler {\r\n public locked = false;\r\n private accessTokenKey = \"st-access-token\"\r\n private refreshTokenKey = \"st-refresh-token\"\r\n\r\n get accessToken() {\r\n return localStorage.getItem(this.accessTokenKey);\r\n }\r\n\r\n get refreshToken() {\r\n return localStorage.getItem(this.refreshTokenKey);\r\n }\r\n\r\n clearTokens() {\r\n localStorage.removeItem(this.accessTokenKey);\r\n localStorage.removeItem(this.refreshTokenKey);\r\n }\r\n\r\n checkForKey(headers, tokenKey: string) {\r\n if (!headers.has(tokenKey)) return;\r\n const token = headers.get(tokenKey);\r\n localStorage.setItem(tokenKey, token);\r\n }\r\n\r\n updateTokens(headers) {\r\n this.checkForKey(headers, this.accessTokenKey);\r\n this.checkForKey(headers, this.refreshTokenKey);\r\n }\r\n\r\n async wait() {\r\n while (this.locked) {\r\n await asyncTimeout(100);\r\n }\r\n }\r\n\r\n async fetch(input: string, init: RequestInit) {\r\n const {headers = {}, ...others} = init;\r\n\r\n const response = await originalFetch(input, {\r\n headers: {\r\n 'Authorization': `Bearer ${this.accessToken}`,\r\n ...headers,\r\n },\r\n ...others\r\n });\r\n\r\n return response;\r\n }\r\n\r\n async update() {\r\n this.locked = true;\r\n\r\n const url = `${engineCloudURL}/auth/session/refresh`;\r\n\r\n const response = await originalFetch(url, {\r\n method: \"POST\",\r\n headers: {\r\n 'rid': 'session',\r\n 'Authorization': `Bearer ${this.refreshToken}`\r\n }\r\n });\r\n\r\n let success = response.status === 200;\r\n\r\n if (success) {\r\n this.updateTokens(response.headers);\r\n }\r\n\r\n this.locked = false;\r\n\r\n return success;\r\n }\r\n}\r\n\r\nconst handler = new AuthHandler();\r\n\r\nconst initCustomFetch = () => {\r\n const customFetch = async (input: string, init: RequestInit = {}) => {\r\n if (!input.includes(engineCloudURL)) {\r\n return originalFetch(input, init);\r\n }\r\n\r\n if (handler.locked) {\r\n await handler.wait();\r\n }\r\n\r\n const response = await handler.fetch(input, init);\r\n\r\n if (response.status !== 401) {\r\n return response;\r\n }\r\n\r\n if (handler.locked) {\r\n return customFetch(input, init);\r\n }\r\n\r\n const updated = await handler.update();\r\n\r\n if (updated) {\r\n return customFetch(input, init);\r\n } else {\r\n throw new Error(\"Unauthorized\");\r\n }\r\n };\r\n\r\n window['fetch'] = customFetch;\r\n};\r\n\r\nconst initSuperTokens = () => {\r\n SuperTokens.init({\r\n appInfo: {\r\n appName: \"Engine Cloud\",\r\n apiDomain: window.location.origin,\r\n apiBasePath: \"/auth\"\r\n },\r\n recipeList: [\r\n Session.init(),\r\n EmailPassword.init(),\r\n ]\r\n });\r\n};\r\n\r\nconst initialUserState = {\r\n id: null,\r\n email: null,\r\n firstName: null,\r\n lastName: null,\r\n apiKey: null\r\n} as UserInfo;\r\n\r\nconst adminPermissions = {\r\n type: AccessType.Admin,\r\n access: true,\r\n create: true,\r\n delete: true,\r\n edit: true\r\n} as ProjectPermissions;\r\n\r\nconst emptyPermissions = {\r\n type: AccessType.ViewOnly,\r\n access: false,\r\n create: false,\r\n delete: false,\r\n edit: false\r\n} as ProjectPermissions;\r\n\r\nexport const AuthContext = createContext({\r\n user: null as UserInfo,\r\n permissions: null as ProjectPermissions,\r\n loggedIn: false,\r\n initialized: false,\r\n linkAccount: async () => false,\r\n signOut: () => {},\r\n getAppCode: async (activate: boolean) => null as string,\r\n checkVersion: async () => false\r\n});\r\n\r\nexport const AuthProvider = (props: ProviderProps) => {\r\n const { i18n, t } = useTranslation();\r\n\r\n const websockets = useWebSockets();\r\n\r\n const [state, setState] = useState({\r\n user: {...initialUserState},\r\n permissions: null,\r\n initialized: false\r\n });\r\n\r\n const linkAccount = async () => {\r\n try {\r\n const appCode = await getAppCode();\r\n const url = getLocalizedURL(\r\n `${engineCloudURL}/link?code=${appCode}`,\r\n i18n.language\r\n );\r\n\r\n openExternalLink(url);\r\n return useAppCode(appCode);\r\n } catch {\r\n toast.error(t('user-account.error_linking_account'));\r\n return false;\r\n }\r\n };\r\n\r\n const signOut = async () => {\r\n if (isCloudSite) {\r\n await stSignOut();\r\n redirectToLogin();\r\n } else {\r\n setState({\r\n ...state,\r\n user: {...initialUserState}\r\n });\r\n\r\n handler.clearTokens();\r\n toast.success(t('user-account.account_unlinked'));\r\n }\r\n\r\n websockets.disconnect();\r\n };\r\n\r\n const getAppCode = async (activate=false) => {\r\n const url = `${engineCloudURL}/api/app_codes/request`;\r\n const response = await fetch(url);\r\n const data = await response.json();\r\n const appCode = String(data.access_code);\r\n\r\n if (activate) {\r\n const url = `${engineCloudURL}/api/app_codes/activate/${appCode}`;\r\n await fetch(url, {method: \"PUT\"});\r\n }\r\n\r\n return appCode;\r\n };\r\n\r\n /** Consume app code until it returns a success code */\r\n const useAppCode = async (appCode: string): Promise => {\r\n if (!appCode) return true;\r\n\r\n return new Promise((resolve, reject) => {\r\n let retryAttempt = 0;\r\n\r\n const interval = setInterval(async () => {\r\n if (retryAttempt >= appCodeMaxAttempts) {\r\n resolve(false);\r\n clearInterval(interval);\r\n toast.error(t('user-account.error_linking_account'));\r\n return;\r\n }\r\n\r\n const url = `${engineCloudURL}/api/app_codes/consume/${appCode}`;\r\n const response = await fetch(url);\r\n const success = response.status === 200;\r\n\r\n if (success) {\r\n handler.updateTokens(response.headers);\r\n await initialize();\r\n toast.success(t('user-account.account_linked'));\r\n clearInterval(interval);\r\n resolve(true);\r\n }\r\n\r\n retryAttempt += 1;\r\n }, appCodeRefreshRate);\r\n });\r\n };\r\n\r\n const getUser = async () : Promise => {\r\n try {\r\n const url = `${engineCloudURL}/api/users/me`;\r\n const response = await fetch(url);\r\n if (response.status !== 200) {\r\n return initialUserState;\r\n }\r\n\r\n const user = await response.json();\r\n return user;\r\n } catch {\r\n return initialUserState;\r\n }\r\n };\r\n\r\n const checkVersion = async () => {\r\n try {\r\n const url = `${engineCloudURL}/viewer/version`;\r\n const response = await fetch(url);\r\n if (response.status !== 200) {\r\n return false;\r\n }\r\n\r\n const serverConfigVersion = await response.json();\r\n return semver.eq(currentConfigVersion, serverConfigVersion);\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n const getPermissions = async () : Promise => {\r\n try {\r\n const url = `${window.location.pathname}/permissions`;\r\n const response = await fetch(url);\r\n if (response.status !== 200) {\r\n return emptyPermissions;\r\n }\r\n\r\n const permissions = await response.json();\r\n return permissions;\r\n } catch {\r\n return emptyPermissions;\r\n }\r\n };\r\n\r\n const initialize = async () => {\r\n const newState = {...state};\r\n\r\n if (isCloudSite || isElectronApp) {\r\n const user = await getUser();\r\n newState.user = {...user};\r\n\r\n await websockets.connect(handler.accessToken);\r\n\r\n if (!user.id) {\r\n handler.clearTokens();\r\n }\r\n }\r\n\r\n if (isCloudSite) {\r\n const permissions = await getPermissions();\r\n newState.permissions = {...permissions};\r\n } else if (isElectronApp) {\r\n newState.permissions = {...adminPermissions};\r\n } else {\r\n newState.permissions = {\r\n ...emptyPermissions,\r\n access: true\r\n };\r\n }\r\n\r\n setState({...newState, initialized: true});\r\n };\r\n\r\n /** Initialize on first load */\r\n useEffect(() => {\r\n initialize();\r\n }, []);\r\n\r\n const {user, permissions, initialized} = state;\r\n const loggedIn = !!user.id;\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\n\r\nif (isCloudSite) {\r\n // Cloud site uses cookie based auth. Fetch function\r\n // is automatically patched with supertokens-web-js\r\n initSuperTokens();\r\n} else if (isElectronApp) {\r\n // Initialize custom header based auth with localStorage.\r\n // Fetch function is patched with a custom implementation\r\n initCustomFetch();\r\n}","import React, { createContext, useState } from \"react\";\r\nimport { ProviderProps } from \"./props\";\r\n\r\nexport const ActiveToolContext = createContext({\r\n activeToolOpen: false,\r\n setActiveToolOpen: (state: boolean) => {}\r\n});\r\n\r\nexport const ActiveToolProvider = (props: ProviderProps) => {\r\n const [activeToolOpen, setActiveToolOpen] = useState(false);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};","import React from \"react\";\r\nimport { createContext, useState } from \"react\";\r\nimport { Viewer } from \"../viewer/main\";\r\nimport { ProviderProps } from \"./props\";\r\n\r\nexport const ViewerContext = createContext({\r\n viewer: null as Viewer,\r\n setViewer: (value: any) => {}\r\n});\r\n\r\nexport const ViewerProvider = (props: ProviderProps) => {\r\n const [viewer, setViewer] = useState(null);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};","import React, { createContext, useEffect, useState } from \"react\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { PythonExecutable } from \"../executable\";\r\nimport { useUniqueProjectID } from \"../hooks\";\r\nimport { ProviderProps } from \"./props\";\r\n\r\nexport enum TaskStatus {\r\n Waiting,\r\n Running,\r\n Finished\r\n}\r\n\r\ninterface ExecutableTask {\r\n id: string,\r\n commands: string[],\r\n status: TaskStatus,\r\n exe: PythonExecutable,\r\n onFinish: Function\r\n}\r\n\r\nexport const TaskQueueContext = createContext({\r\n taskQueue: [] as ExecutableTask[],\r\n addRunningTask: (commands: string[], onFinish: Function) => {},\r\n stopRunningTask: (task: string) => {},\r\n clearTaskQueue: () => {}\r\n});\r\n\r\nexport const TaskQueueProvider = (props: ProviderProps) => {\r\n const [taskQueue, setTaskQueue] = useState([]);\r\n const [running, setRunning] = useState(false);\r\n const uniqueProjectID = useUniqueProjectID();\r\n\r\n const runningTask = taskQueue.find(x => x.status === TaskStatus.Running);\r\n\r\n const addRunningTask = (commands: string[], onFinish: Function) => {\r\n const newTask = {\r\n id: nanoid(),\r\n onFinish,\r\n commands,\r\n exe: new PythonExecutable(),\r\n status: TaskStatus.Waiting\r\n } as ExecutableTask;\r\n\r\n setTaskQueue([...taskQueue, newTask]);\r\n };\r\n\r\n const clearTaskQueue = () => {\r\n runningTask?.exe.destroy();\r\n setTaskQueue([]);\r\n setRunning(false);\r\n };\r\n\r\n const stopRunningTask = (taskID: string) => {\r\n const task = taskQueue.find(x => x.id === taskID);\r\n if (!task) return;\r\n\r\n task.exe.destroy();\r\n setRunning(false);\r\n };\r\n\r\n const updateTaskStatus = (taskID, status) => {\r\n const tasks = taskQueue.map(task => {\r\n if (task.id === taskID) {\r\n return {...task, status: status};\r\n }\r\n\r\n return task;\r\n });\r\n\r\n setTaskQueue([...tasks]);\r\n };\r\n\r\n const runAvailableTask = () => {\r\n const availableTasks = taskQueue\r\n .filter(x => x.status === TaskStatus.Waiting);\r\n\r\n if ((availableTasks.length === 0) || runningTask) return;\r\n\r\n const task = availableTasks[0];\r\n setRunning(true);\r\n updateTaskStatus(task.id, TaskStatus.Running);\r\n\r\n task.exe.run({\r\n commands: task.commands,\r\n saveLogs: true,\r\n onClose: async (error) => {\r\n if (error) return;\r\n setRunning(false);\r\n await task.onFinish();\r\n }\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n /** Clear task queue when new project is loaded */\r\n clearTaskQueue();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n runAvailableTask();\r\n }, [taskQueue]);\r\n\r\n useEffect(() => {\r\n if (running || !runningTask) return;\r\n updateTaskStatus(runningTask.id, TaskStatus.Finished);\r\n }, [running]);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n","import React, { useEffect } from \"react\";\r\nimport { createContext, useState } from \"react\";\r\nimport { isStaticSite, isCloudSite, storage, isElectronApp } from \"../electron-modules\";\r\nimport { useAuth } from \"../hooks\";\r\nimport { ControlType } from \"../types/controls\";\r\nimport { VolumeType, SamplingRate, AerialMeasureType } from \"../types/measurements\";\r\nimport { ProviderProps } from \"./props\";\r\n\r\nexport interface GlobalSettingsState {\r\n orthoQuality: number;\r\n orthoOpacity: number;\r\n controlType: ControlType;\r\n openQuickNav: boolean;\r\n aerialMeasureType: AerialMeasureType;\r\n volumeType: VolumeType;\r\n volumeSampleRate: SamplingRate;\r\n viewerBackground: string;\r\n aerialBackground: string;\r\n}\r\n\r\ninterface GlobalSettingsUpdate {\r\n orthoQuality?: number;\r\n orthoOpacity?: number;\r\n controlType?: ControlType;\r\n openQuickNav?: boolean;\r\n aerialMeasureType?: AerialMeasureType;\r\n volumeType?: VolumeType;\r\n volumeSampleRate?: SamplingRate;\r\n viewerBackground?: string;\r\n aerialBackground?: string;\r\n}\r\n\r\nexport const initialState = {\r\n orthoQuality: 0.75,\r\n orthoOpacity: 1,\r\n controlType: ControlType.Encompass,\r\n openQuickNav: true,\r\n aerialMeasureType: AerialMeasureType.Spherical,\r\n volumeType: VolumeType.MultiPlane,\r\n volumeSampleRate: SamplingRate.Medium,\r\n viewerBackground: \"#e2d1c3\",\r\n aerialBackground: \"#444444\"\r\n} as GlobalSettingsState;\r\n\r\nexport const GlobalSettingsContext = createContext({\r\n ...initialState,\r\n getState: () => null as GlobalSettingsState,\r\n update: (values: GlobalSettingsUpdate) => {}\r\n});\r\n\r\nexport const getGlobalSettingsFromStorage = async () => {\r\n if (isElectronApp) {\r\n return storage.getSync(\"global-settings\");\r\n }\r\n\r\n const cache = Date.now();\r\n const root = isCloudSite ? window.location.pathname : \".\";\r\n const configURL = `${root}/global-settings.json?cache=${cache}`;\r\n\r\n const response = await fetch(configURL);\r\n return await response.json();\r\n};\r\n\r\nexport const GlobalSettingsProvider = (props: ProviderProps) => {\r\n const [state, setState] = useState({...initialState});\r\n const { initialized } = useAuth();\r\n\r\n const loadFromStorage = async () => {\r\n try {\r\n const settings = await getGlobalSettingsFromStorage();\r\n const newState = {...state, ...settings};\r\n\r\n setState(newState);\r\n } catch {\r\n console.error(\"Error reading global settings\");\r\n }\r\n };\r\n\r\n const saveToStorage = (values: GlobalSettingsState) => {\r\n if (isStaticSite) return;\r\n storage.setSync(\"global-settings\", values);\r\n };\r\n\r\n const onUpdate = (values: GlobalSettingsUpdate) => {\r\n const newState = {...state, ...values};\r\n setState(newState);\r\n saveToStorage(newState);\r\n };\r\n\r\n const getState = () : GlobalSettingsState => {\r\n return {...state};\r\n };\r\n\r\n useEffect(() => {\r\n if (!initialized) return;\r\n\r\n loadFromStorage();\r\n }, [initialized]);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};","import React, { createContext, useState } from \"react\";\r\nimport { useDispatch } from \"react-redux\";\r\nimport { engineCloudURL } from \"../urls\";\r\nimport { io, Socket } from \"socket.io-client\";\r\nimport { isElectronApp } from \"../electron-modules\";\r\nimport {\r\n wsCreateFolder,\r\n wsDeleteFolder,\r\n wsUpdateFolder,\r\n} from \"../redux/folders-slice\";\r\nimport {\r\n wsCreateAsset,\r\n wsDeleteAsset,\r\n wsUpdateAsset,\r\n} from \"../redux/assets-slice\";\r\nimport {\r\n wsCreateBookmark,\r\n wsDeleteBookmark,\r\n wsUpdateBookmark,\r\n} from \"../redux/bookmarks-slice\";\r\nimport { ProviderProps } from \"./props\";\r\n\r\nenum EventType {\r\n JoinRoom = \"join_room\",\r\n LeaveRoom = \"leave_room\",\r\n CreateObject = \"create_asset\",\r\n DeleteObject = \"delete_asset\",\r\n UpdateObject = \"update_asset\",\r\n}\r\n\r\nenum ObjectType {\r\n Assets = \"assets\",\r\n Folders = \"folders\",\r\n Bookmarks = \"bookmarks\"\r\n}\r\n\r\nexport const WebSocketContext = createContext({\r\n connect: (accessToken: string) => {},\r\n disconnect: () => {},\r\n joinRoom: (roomID: string) => {}\r\n});\r\n\r\nexport const WebSocketProvider = (props: ProviderProps) => {\r\n const dispatch = useDispatch();\r\n\r\n const [socket, setSocket] = useState(null);\r\n const [currentRoomID, setCurrentRoomID] = useState(null);\r\n\r\n const connect = (accessToken: string) => {\r\n let extraHeaders = {};\r\n\r\n if (isElectronApp) {\r\n extraHeaders = {\r\n Authorization: `Bearer ${accessToken}`\r\n };\r\n }\r\n\r\n return new Promise(resolve => {\r\n const socket = io(engineCloudURL, {\r\n addTrailingSlash: false,\r\n extraHeaders\r\n });\r\n\r\n setSocket(socket);\r\n\r\n socket.on(\"connect\", () => {\r\n register(socket);\r\n resolve(true);\r\n });\r\n\r\n socket.on(\"connect_error\", () => {\r\n socket.disconnect();\r\n resolve(false);\r\n });\r\n });\r\n };\r\n\r\n const disconnect = () => {\r\n if (!socket?.connected) return;\r\n\r\n socket.disconnect();\r\n setSocket(null);\r\n };\r\n\r\n const onCreate = (message) => {\r\n const {type, data} = message;\r\n\r\n if (type === ObjectType.Assets) {\r\n dispatch(wsCreateAsset(data));\r\n } else if (type === ObjectType.Folders) {\r\n dispatch(wsCreateFolder(data));\r\n } else if (type === ObjectType.Bookmarks) {\r\n dispatch(wsCreateBookmark(data));\r\n }\r\n };\r\n\r\n const onUpdate = (message) => {\r\n const {type, data} = message;\r\n\r\n if (type === ObjectType.Assets) {\r\n dispatch(wsUpdateAsset(data));\r\n } else if (type === ObjectType.Folders) {\r\n dispatch(wsUpdateFolder(data));\r\n } else if (type === ObjectType.Bookmarks) {\r\n dispatch(wsUpdateBookmark(data));\r\n }\r\n };\r\n\r\n const onDelete = (message) => {\r\n const {type, objectID} = message;\r\n\r\n if (type === ObjectType.Assets) {\r\n dispatch(wsDeleteAsset(objectID));\r\n } else if (type === ObjectType.Folders) {\r\n dispatch(wsDeleteFolder(objectID));\r\n } else if (type === ObjectType.Bookmarks) {\r\n dispatch(wsDeleteBookmark(objectID));\r\n }\r\n };\r\n\r\n const register = (socket: Socket) => {\r\n socket.on(EventType.CreateObject, onCreate);\r\n socket.on(EventType.UpdateObject, onUpdate);\r\n socket.on(EventType.DeleteObject, onDelete);\r\n };\r\n\r\n const joinRoom = (roomID: string) => {\r\n if (!socket?.connected) return;\r\n\r\n if (currentRoomID) {\r\n // Leave previously joined room\r\n socket.emit(EventType.LeaveRoom, currentRoomID);\r\n }\r\n\r\n socket.emit(EventType.JoinRoom, roomID);\r\n setCurrentRoomID(roomID);\r\n };\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};","import React, { useMemo } from \"react\";\r\nimport { createContext } from \"react\";\r\nimport { useDispatch, useSelector } from \"react-redux\";\r\nimport { toast } from \"../app\";\r\nimport { useViewer } from \"../hooks\";\r\nimport { Bookmark, deleteBookmark, selectAllBookmarks } from \"../redux/bookmarks-slice\";\r\nimport LocalScene from \"../viewer/projections\";\r\nimport {isEqual} from 'lodash';\r\nimport { t } from \"i18next\";\r\nimport { selectAllAssets, getVisibleAssets, setVisibleAssets } from \"../redux/assets-slice\";\r\nimport { changeCameraState } from \"../redux/camera-slice\";\r\nimport { updateSettingsState } from \"../redux/settings-slice\";\r\nimport { ProviderProps } from \"./props\";\r\n\r\nexport const BookmarksContext = createContext({\r\n bookmarks: [] as Bookmark[],\r\n loadBookmark: (bookmarkID: string) : boolean => null,\r\n deleteBookmarks: () => {}\r\n});\r\n\r\nexport const BookmarksProvider = (props: ProviderProps) => {\r\n const {viewer} = useViewer();\r\n const dispatch = useDispatch();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const bookmarks = useSelector(selectAllBookmarks);\r\n\r\n const visibleAssets = useMemo(() => {\r\n return getVisibleAssets(assets);\r\n }, [assets]);\r\n\r\n /**\r\n * Get visible bookmark assets, ignoring assets that have\r\n * been removed from the project\r\n **/\r\n const getValidAssetIDs = (bookmark: Bookmark) => {\r\n const assetIDs = assets.map(asset => asset.id);\r\n return bookmark.visibleAssets.filter(assetID => {\r\n return assetIDs.includes(assetID);\r\n });\r\n };\r\n\r\n const loadBookmark = (bookmarkID: string) => {\r\n if (!viewer) return;\r\n\r\n if (!LocalScene.initialized) {\r\n toast.warning(t('bookmarks.invalid_position'));\r\n return;\r\n }\r\n\r\n const bookmark = bookmarks.find(x => x.id === bookmarkID);\r\n if (!bookmark) return;\r\n\r\n dispatch(updateSettingsState(bookmark.settings));\r\n\r\n viewer.applySavedAerialState(bookmark.aerialState);\r\n\r\n const visibleAssetIDs = visibleAssets.map(asset => asset.id);\r\n const bookmarkAssetIDs = getValidAssetIDs(bookmark);\r\n\r\n visibleAssetIDs.sort();\r\n bookmarkAssetIDs.sort();\r\n\r\n if (isEqual(visibleAssetIDs, bookmarkAssetIDs)) {\r\n // Apply scene state directly\r\n viewer.applySavedSceneState(bookmark.sceneState, true);\r\n } else {\r\n // Set saved scene state and apply new asset visibility\r\n viewer.setInitialStateFlag(false);\r\n dispatch(changeCameraState(bookmark.sceneState));\r\n dispatch(setVisibleAssets(bookmarkAssetIDs));\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const deleteBookmarks = () => {\r\n for (let bookmark of bookmarks) {\r\n dispatch(deleteBookmark(bookmark.id));\r\n }\r\n };\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};","export default __webpack_public_path__ + \"static/media/mosaic-logo.b9f9c9df.png\";","import React from \"react\";\r\nimport { createContext } from \"react\";\r\nimport { ProviderProps } from \"./props\";\r\nimport { isCloudSite } from \"../electron-modules\";\r\nimport mosaicLogo from \"../viewer/textures/misc/mosaic-logo.png\";\r\nimport { Theme } from \"@mui/material\";\r\nimport { createTheme } from \"../theme\";\r\nimport manifest from \"../../package.json\";\r\n\r\nexport type Brand = \"solv3d\" | \"mosaic\";\r\n\r\nexport const BrandingContext = createContext({\r\n companyName: null as string,\r\n appName: null as string,\r\n iconPath: null as string,\r\n theme: null as Theme\r\n});\r\n\r\nexport const BrandingProvider = (props: ProviderProps) => {\r\n let brand: Brand = \"solv3d\";\r\n\r\n if (isCloudSite) {\r\n if (typeof window !== \"undefined\") {\r\n if (window.location.hostname === \"mosaic.solv3d.com\" || window.location.hostname === \"engine.mosaic51.com\") {\r\n brand = \"mosaic\";\r\n }\r\n }\r\n } else {\r\n if (manifest.brand) {\r\n brand = manifest.brand as Brand;\r\n }\r\n }\r\n\r\n const isMosaic = brand === \"mosaic\";\r\n\r\n const appName = isMosaic\r\n ? \"Mosaic Engine\"\r\n : \"SOLV3D Engine\";\r\n\r\n const companyName = isMosaic\r\n ? \"Mosaic 51\"\r\n : \"Solv3D Inc.\";\r\n\r\n const iconPath = isMosaic\r\n ? mosaicLogo\r\n : null;\r\n\r\n const theme = createTheme(brand);\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};","\r\nconst spiralParamaters = (spiral, stepDist, sigDigs) => {\r\n\r\n if (spiral.spiType !== \"clothoid\") {\r\n console.error(`Unsupported Spiral Type: ${spiral.spiType}. Only clothoid spirals detected.`);\r\n return false;\r\n }\r\n\r\n const RL = Math.pow(parseFloat(spiral.constant), 2);\r\n let reverseCurve;\r\n let partial = false;\r\n\r\n if (spiral.radiusEnd === 'INF') {\r\n reverseCurve = true;\r\n } else if (spiral.radiusStart === 'INF'){\r\n reverseCurve = false;\r\n } else {\r\n reverseCurve = (spiral.radiusEnd > spiral.radiusStart);\r\n partial = true;\r\n }\r\n\r\n const cw = spiral.rot === \"cw\";\r\n let L = spiral.length;\r\n\r\n let delta;\r\n if (cw) {//cw\r\n if (reverseCurve){ // cw reverse curve\r\n delta = spiral.dirEnd;\r\n } else { // cw forward curve\r\n delta = -spiral.dirStart;\r\n }\r\n } else {// ccw\r\n if (reverseCurve) {// ccw reverse curve\r\n delta = -spiral.dirEnd;\r\n } else {// ccw forward curve\r\n delta = spiral.dirStart;\r\n }\r\n }\r\n\r\n let a = spiral.Start[0];\r\n let b = spiral.Start[1];\r\n let c = spiral.End[0];\r\n let d = spiral.End[1];\r\n\r\n let xStart;\r\n let yStart;\r\n\r\n let xEnd;\r\n let yEnd;\r\n\r\n let xCorr=0.0;\r\n let yCorr=0.0;\r\n let deltaCorr = 0.0;\r\n\r\n let segmentMin;\r\n let segmentMax;\r\n\r\n if (partial && !reverseCurve) { //partial forward curve\r\n let ls = RL / spiral.radiusStart;\r\n L += ls;\r\n segmentMin = parseInt((ls * sigDigs).toString());\r\n segmentMax = parseInt((L * sigDigs).toString());\r\n\r\n xCorr = ls - (Math.pow(ls, 5) / (40.0 * RL * RL)) +\r\n (Math.pow(ls, 9) / (3456.0 * Math.pow(RL, 4))) -\r\n (Math.pow(ls, 13) / (599040.0 * Math.pow(RL, 6)));\r\n yCorr = (Math.pow(ls, 3) / (6 * RL)) -\r\n (Math.pow(ls, 7) / (336.0 * Math.pow(RL, 3))) +\r\n (Math.pow(ls, 11) / (42240.0 * Math.pow(RL, 5))) -\r\n (Math.pow(ls, 15) / (9676800.0 * Math.pow(RL, 7)));\r\n deltaCorr = Math.pow(ls, 2) / (2 * RL);\r\n } else if (partial && reverseCurve){\r\n let le = RL / spiral.radiusEnd;\r\n let ls = RL / spiral.radiusStart;\r\n\r\n deltaCorr = Math.pow(le, 2) / (2 * RL);\r\n xCorr = le - (Math.pow(le, 5) / (40.0 * RL * RL)) +\r\n (Math.pow(le, 9) / (3456.0 * Math.pow(RL, 4))) -\r\n (Math.pow(le, 13) / (599040.0 * Math.pow(RL, 6)));\r\n yCorr = (Math.pow(le, 3) / (6 * RL)) -\r\n (Math.pow(le, 7) / (336.0 * Math.pow(RL, 3))) +\r\n (Math.pow(le, 11) / (42240.0 * Math.pow(RL, 5))) -\r\n (Math.pow(le, 15) / (9676800.0 * Math.pow(RL, 7)));\r\n\r\n segmentMin = parseInt((le * sigDigs).toString());\r\n segmentMax = parseInt((ls * sigDigs).toString());\r\n\r\n } else{\r\n segmentMin = 0;\r\n segmentMax = parseInt((L * sigDigs).toString());\r\n }\r\n\r\n let distMin = 1000000;\r\n let deltas = [\r\n delta, delta+deltaCorr, delta-deltaCorr,\r\n -1*(delta)-deltaCorr, -1*(delta)+deltaCorr, -delta];\r\n\r\n let endPointError = true;\r\n let chosenDelta = delta;\r\n\r\n deltas.forEach(deltaTrial => {\r\n let l = segmentMax / sigDigs;\r\n let x = l - (Math.pow(l, 5) / (40.0*RL*RL)) +\r\n (Math.pow(l,9) / (3456.0 * Math.pow(RL,4))) -\r\n (Math.pow(l,13) / (599040.0*Math.pow(RL,6)));\r\n\r\n let y = (Math.pow(l, 3) / (6*RL)) -\r\n (Math.pow(l,7) / (336.0*Math.pow(RL,3))) +\r\n (Math.pow(l, 11) / (42240.0*Math.pow(RL,5))) -\r\n (Math.pow(l, 15) / (9676800.0*Math.pow(RL, 7)));\r\n\r\n x -= xCorr;\r\n y -= yCorr;\r\n\r\n let xDiff = (x * Math.cos(deltaTrial) - y * Math.sin(deltaTrial));\r\n let yDiff = (x * Math.sin(deltaTrial) + y * Math.cos(deltaTrial));\r\n\r\n // console.log(`diffs x: ${xDiff} | y: ${yDiff}`);\r\n\r\n let xRotated;\r\n let yRotated;\r\n if (!reverseCurve) {//forward curve\r\n xRotated = a + xDiff;\r\n if (!cw) {//ccw forward\r\n yRotated = b - yDiff;\r\n } else {//cw forward\r\n yRotated = b + yDiff;\r\n }\r\n let dist = Math.sqrt(Math.pow(xRotated - c, 2)\r\n + Math.pow(yRotated - d, 2));\r\n if (dist < distMin) {\r\n distMin = dist;\r\n xEnd = xRotated;\r\n yEnd = yRotated;\r\n xStart = a;\r\n yStart = b;\r\n chosenDelta = deltaTrial;\r\n }\r\n if (dist <= Math.sqrt(2)*stepDist) {\r\n endPointError = false;\r\n }\r\n } else {//reverse curve\r\n xRotated = c - xDiff;\r\n if (!cw) {//ccw reverse\r\n yRotated = d - yDiff;\r\n } else {//cw reverse\r\n yRotated = d + yDiff;\r\n }\r\n\r\n let dist = Math.sqrt(Math.pow(xRotated - a, 2)\r\n + Math.pow(yRotated - b, 2));\r\n\r\n if (dist < distMin) {\r\n distMin = dist;\r\n xEnd = c;\r\n yEnd = d;\r\n xStart = xRotated;\r\n yStart = yRotated;\r\n chosenDelta = deltaTrial;\r\n }\r\n if (dist <= Math.sqrt(2)*stepDist) {\r\n endPointError = false;\r\n }\r\n }\r\n });\r\n if (endPointError) {\r\n console.error('Error in endpoint calculation');\r\n console.log(`Datum correct data: xDiff: ${a-c} | yDiff: ${b-d}`);\r\n console.log(`${xStart} | ${yStart} | at length ${segmentMin / sigDigs} | 0`);\r\n console.log(`${xEnd} | ${yEnd} | at length ${segmentMax / sigDigs} | ${spiral.length}`);\r\n console.log(`${xStart - a} | ${yStart - b} | at length ${segmentMin / sigDigs} | ${spiral.length}`);\r\n console.log(`${xEnd - c} | ${yEnd - d} | at length ${segmentMax / sigDigs} | ${spiral.length}`);\r\n }\r\n\r\n return {chosenDelta: chosenDelta, xStart: xStart, xEnd: xEnd, yStart: yStart,\r\n yEnd: yEnd, xCorr: xCorr, yCorr:yCorr, reverseCurve: reverseCurve, partial: partial,\r\n segmentMin: segmentMin, segmentMax:segmentMax, RL:RL, cw:cw, a:a, b:b, c:c, d:d\r\n };\r\n};\r\n\r\nexport const spiralIntersect = (spiral, point) => {\r\n const stepDist = 0.01;\r\n const sigDigs = 1000000;\r\n const spiralParams = spiralParamaters(spiral, stepDist, sigDigs);\r\n if (typeof spiralParams === \"boolean\") {\r\n return false;\r\n }\r\n let segmentMin = spiralParams.segmentMin;\r\n let segmentMax = spiralParams.segmentMax;\r\n\r\n // Now that the correct rotation and position corrections have been calculated\r\n // the entire spiral can be calculated, and the closest point to the clicked point can\r\n // be estimated.\r\n let spiralCoord=null;\r\n let distAlong=null;\r\n let distAcross = null;\r\n\r\n for (;segmentMin<=segmentMax;segmentMin+=stepDist*sigDigs) {\r\n if ((segmentMin+=stepDist*sigDigs) > segmentMax){\r\n segmentMin = segmentMax;\r\n }\r\n let l = segmentMin / sigDigs;\r\n\r\n let x = l - (Math.pow(l, 5) / (40.0*spiralParams.RL*spiralParams.RL)) +\r\n (Math.pow(l,9) / (3456.0 * Math.pow(spiralParams.RL,4))) -\r\n (Math.pow(l,13) / (599040.0*Math.pow(spiralParams.RL,6)));\r\n\r\n let y = (Math.pow(l, 3) / (6*spiralParams.RL)) -\r\n (Math.pow(l,7) / (336.0*Math.pow(spiralParams.RL,3))) +\r\n (Math.pow(l, 11) / (42240.0*Math.pow(spiralParams.RL,5))) -\r\n (Math.pow(l, 15) / (9676800.0*Math.pow(spiralParams.RL, 7)));\r\n\r\n x -= spiralParams.xCorr;\r\n y -= spiralParams.yCorr;\r\n\r\n let xDiff = (x * Math.cos(spiralParams.chosenDelta)\r\n - y * Math.sin(spiralParams.chosenDelta));\r\n let yDiff = (x * Math.sin(spiralParams.chosenDelta)\r\n + y * Math.cos(spiralParams.chosenDelta));\r\n let xAtLength, yAtLength, lengthLocal;\r\n if (spiralParams.partial) {\r\n lengthLocal = l - (segmentMin/sigDigs);\r\n } else {\r\n lengthLocal = l;\r\n }\r\n\r\n if (spiralParams.reverseCurve) {\r\n lengthLocal = spiral.length - lengthLocal;\r\n }\r\n\r\n if (!spiralParams.reverseCurve) {//forward curve\r\n xAtLength = spiralParams.a + xDiff;\r\n if (!spiralParams.cw) {//ccw forward\r\n yAtLength = spiralParams.b - yDiff;\r\n } else {//cw forward\r\n yAtLength = spiralParams.b + yDiff;\r\n }\r\n } else {//reverse curve\r\n xAtLength = spiralParams.c - xDiff;\r\n if (!spiralParams.cw) {//ccw reverse\r\n yAtLength = spiralParams.d - yDiff;\r\n } else {//cw reverse\r\n yAtLength = spiralParams.d + yDiff;\r\n }\r\n }\r\n\r\n const distAcrossNew = Math.sqrt(Math.pow(point[0] - xAtLength, 2)\r\n + Math.pow(point[1] - yAtLength, 2));\r\n // console.log(distAcrossNew)\r\n if (distAcross !== null) {\r\n const update = (distAcrossNew 0 ? 'L':'R';\r\n\r\n // console.log(`across: ${distAcross} | along: ${distAlong} | side: ${sideOfLine}`);\r\n\r\n return {distAcross: distAcross, distAlong: distAlong,\r\n sideOfLine:sideOfLine, coordinates:spiralCoord};\r\n};\r\n\r\nexport const lineDist = (geometry) => {\r\n const dist = Math.sqrt(Math.pow(geometry.Start[0] - geometry.End[0], 2) +\r\n Math.pow(geometry.Start[1] - geometry.End[1], 2));\r\n return dist;\r\n};\r\n\r\nexport const curveDist = (geometry) => {\r\n const dist = lineDist(geometry);\r\n const calcAngle = Math.acos(1 - (dist * dist) /\r\n (2 * geometry.radius * geometry.radius));\r\n return geometry.radius * calcAngle;\r\n};","import icon0 from './basic-pin-large-0.png';\r\nimport icon1 from './basic-pin-large-1.png';\r\nimport icon2 from './basic-pin-large-2.png';\r\nimport icon3 from './basic-pin-large-3.png';\r\nimport icon4 from './basic-pin-large-4.png';\r\nimport icon5 from './basic-pin-large-5.png';\r\nimport icon6 from './basic-pin-large-6.png';\r\nimport icon7 from './basic-pin-large-7.png';\r\nimport icon8 from './basic-pin-large-8.png';\r\nimport icon9 from './basic-pin-large-9.png';\r\nimport icon10 from './basic-pin-large-10.png';\r\nimport icon11 from './basic-pin-large-11.png';\r\nimport icon12 from './basic-pin-large-12.png';\r\nimport icon13 from './basic-pin-large-13.png';\r\nimport icon14 from './basic-pin-large-14.png';\r\nimport icon15 from './basic-pin-large-15.png';\r\nimport icon16 from './basic-pin-small-0.png';\r\nimport icon17 from './basic-pin-small-1.png';\r\nimport icon18 from './basic-pin-small-2.png';\r\nimport icon19 from './basic-pin-small-3.png';\r\nimport icon20 from './basic-pin-small-4.png';\r\nimport icon21 from './basic-pin-small-5.png';\r\nimport icon22 from './basic-pin-small-6.png';\r\nimport icon23 from './basic-pin-small-7.png';\r\nimport icon24 from './basic-pin-small-8.png';\r\nimport icon25 from './basic-pin-small-9.png';\r\nimport icon26 from './basic-pin-small-10.png';\r\nimport icon27 from './basic-pin-small-11.png';\r\nimport icon28 from './basic-pin-small-12.png';\r\nimport icon29 from './basic-pin-small-13.png';\r\nimport icon30 from './basic-pin-small-14.png';\r\nimport icon31 from './basic-pin-small-15.png';\r\nimport icon32 from './basic-push-pin-0.png';\r\nimport icon33 from './basic-push-pin-1.png';\r\nimport icon34 from './basic-push-pin-2.png';\r\nimport icon35 from './basic-push-pin-3.png';\r\nimport icon36 from './basic-push-pin-4.png';\r\nimport icon37 from './basic-push-pin-5.png';\r\nimport icon38 from './basic-push-pin-6.png';\r\nimport icon39 from './basic-push-pin-7.png';\r\nimport icon40 from './basic-push-pin-8.png';\r\nimport icon41 from './basic-push-pin-9.png';\r\nimport icon42 from './basic-push-pin-10.png';\r\nimport icon43 from './basic-push-pin-11.png';\r\nimport icon44 from './basic-push-pin-12.png';\r\nimport icon45 from './basic-push-pin-13.png';\r\nimport icon46 from './basic-push-pin-14.png';\r\nimport icon47 from './basic-push-pin-15.png';\r\n\r\nconst textures = {\r\n 'basic-pin-large-0': icon0,\r\n 'basic-pin-large-1': icon1,\r\n 'basic-pin-large-2': icon2,\r\n 'basic-pin-large-3': icon3,\r\n 'basic-pin-large-4': icon4,\r\n 'basic-pin-large-5': icon5,\r\n 'basic-pin-large-6': icon6,\r\n 'basic-pin-large-7': icon7,\r\n 'basic-pin-large-8': icon8,\r\n 'basic-pin-large-9': icon9,\r\n 'basic-pin-large-10': icon10,\r\n 'basic-pin-large-11': icon11,\r\n 'basic-pin-large-12': icon12,\r\n 'basic-pin-large-13': icon13,\r\n 'basic-pin-large-14': icon14,\r\n 'basic-pin-large-15': icon15,\r\n 'basic-pin-small-0': icon16,\r\n 'basic-pin-small-1': icon17,\r\n 'basic-pin-small-2': icon18,\r\n 'basic-pin-small-3': icon19,\r\n 'basic-pin-small-4': icon20,\r\n 'basic-pin-small-5': icon21,\r\n 'basic-pin-small-6': icon22,\r\n 'basic-pin-small-7': icon23,\r\n 'basic-pin-small-8': icon24,\r\n 'basic-pin-small-9': icon25,\r\n 'basic-pin-small-10': icon26,\r\n 'basic-pin-small-11': icon27,\r\n 'basic-pin-small-12': icon28,\r\n 'basic-pin-small-13': icon29,\r\n 'basic-pin-small-14': icon30,\r\n 'basic-pin-small-15': icon31,\r\n 'basic-push-pin-0': icon32,\r\n 'basic-push-pin-1': icon33,\r\n 'basic-push-pin-2': icon34,\r\n 'basic-push-pin-3': icon35,\r\n 'basic-push-pin-4': icon36,\r\n 'basic-push-pin-5': icon37,\r\n 'basic-push-pin-6': icon38,\r\n 'basic-push-pin-7': icon39,\r\n 'basic-push-pin-8': icon40,\r\n 'basic-push-pin-9': icon41,\r\n 'basic-push-pin-10': icon42,\r\n 'basic-push-pin-11': icon43,\r\n 'basic-push-pin-12': icon44,\r\n 'basic-push-pin-13': icon45,\r\n 'basic-push-pin-14': icon46,\r\n 'basic-push-pin-15': icon47,\r\n};\r\n\r\nexport default textures;","export default __webpack_public_path__ + \"static/media/basic-pin-large-0.75ec4490.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-1.de25c04d.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-2.23fb938d.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-3.65851ce1.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-4.9966d8be.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-5.790dd84e.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-6.a68198e2.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-7.4c3698cb.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-8.f7c1d345.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-9.a396cd2e.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-10.99e3c8ff.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-11.b8422548.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-12.d24a3926.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-13.fcd61555.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-14.6f043dcd.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-large-15.7f4dcc36.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-0.ac50d9dd.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-1.d45746d2.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-2.02ae7f5d.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-3.7751012c.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-4.edcfac5a.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-5.42c12183.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-6.542950ea.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-7.bdbb489b.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-8.dd94c859.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-9.78cbab57.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-10.1798390a.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-11.f6c044f3.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-12.5e716d0a.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-13.dca970d3.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-14.1c33bb37.png\";","export default __webpack_public_path__ + \"static/media/basic-pin-small-15.96c7fac3.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-0.959c4b2f.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-1.a4c240b1.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-2.61523e37.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-3.53684cd6.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-4.626c530e.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-5.493e3493.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-6.9025f632.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-7.be74b86d.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-8.662983fe.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-9.e8c0afd3.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-10.3c7e3c46.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-11.b0a43ba2.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-12.104ba8ac.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-13.30dbf535.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-14.e8adad8f.png\";","export default __webpack_public_path__ + \"static/media/basic-push-pin-15.1cd5a458.png\";","import icon0 from './001-ahead only.png';\r\nimport icon1 from './002-crossroads.png';\r\nimport icon2 from './003-falling rocks.png';\r\nimport icon3 from './004-give way.png';\r\nimport icon4 from './005-hump.png';\r\nimport icon5 from './006-left turn.png';\r\nimport icon6 from './007-parking.png';\r\nimport icon7 from './008-level crossing.png';\r\nimport icon8 from './009-speed limit.png';\r\nimport icon9 from './010-narrow bridge.png';\r\nimport icon10 from './011-no bike.png';\r\nimport icon11 from './012-no trucks.png';\r\nimport icon12 from './013-no alarm.png';\r\nimport icon13 from './014-no turn left.png';\r\nimport icon14 from './015-no motorcycles.png';\r\nimport icon15 from './016-speed limit.png';\r\nimport icon16 from './017-no overtaking.png';\r\nimport icon17 from './018-pedestrian.png';\r\nimport icon18 from './019-no entry.png';\r\nimport icon19 from './020-u turn.png';\r\nimport icon20 from './021-Two way.png';\r\nimport icon21 from './022-pedestrian crossing.png';\r\nimport icon22 from './023-right turn.png';\r\nimport icon23 from './024-road work.png';\r\nimport icon24 from './025-roundabout.png';\r\nimport icon25 from './026-pedestrian crossing.png';\r\nimport icon26 from './027-Slippery road.png';\r\nimport icon27 from './028-traffic lights.png';\r\nimport icon28 from './029-turn left.png';\r\nimport icon29 from './030-turn right.png';\r\nimport icon30 from './031-uneven.png';\r\nimport icon31 from './032-maximum.png';\r\nimport icon32 from './033-wild animals.png';\r\n\r\nconst textures = {\r\n '001-ahead only': icon0,\r\n '002-crossroads': icon1,\r\n '003-falling rocks': icon2,\r\n '004-give way': icon3,\r\n '005-hump': icon4,\r\n '006-left turn': icon5,\r\n '007-parking': icon6,\r\n '008-level crossing': icon7,\r\n '009-speed limit': icon8,\r\n '010-narrow bridge': icon9,\r\n '011-no bike': icon10,\r\n '012-no trucks': icon11,\r\n '013-no alarm': icon12,\r\n '014-no turn left': icon13,\r\n '015-no motorcycles': icon14,\r\n '016-speed limit': icon15,\r\n '017-no overtaking': icon16,\r\n '018-pedestrian': icon17,\r\n '019-no entry': icon18,\r\n '020-u turn': icon19,\r\n '021-Two way': icon20,\r\n '022-pedestrian crossing': icon21,\r\n '023-right turn': icon22,\r\n '024-road work': icon23,\r\n '025-roundabout': icon24,\r\n '026-pedestrian crossing': icon25,\r\n '027-Slippery road': icon26,\r\n '028-traffic lights': icon27,\r\n '029-turn left': icon28,\r\n '030-turn right': icon29,\r\n '031-uneven': icon30,\r\n '032-maximum': icon31,\r\n '033-wild animals': icon32,\r\n};\r\n\r\nexport default textures;","export default __webpack_public_path__ + \"static/media/001-ahead only.b36dbabc.png\";","export default __webpack_public_path__ + \"static/media/002-crossroads.abff42d3.png\";","export default __webpack_public_path__ + \"static/media/003-falling rocks.daff62e3.png\";","export default __webpack_public_path__ + \"static/media/004-give way.e8421679.png\";","export default __webpack_public_path__ + \"static/media/005-hump.b663a44b.png\";","export default __webpack_public_path__ + \"static/media/006-left turn.e8bd0364.png\";","export default __webpack_public_path__ + \"static/media/007-parking.c84744cd.png\";","export default __webpack_public_path__ + \"static/media/008-level crossing.053e35fb.png\";","export default __webpack_public_path__ + \"static/media/009-speed limit.825c6624.png\";","export default __webpack_public_path__ + \"static/media/010-narrow bridge.f8bce357.png\";","export default __webpack_public_path__ + \"static/media/011-no bike.6c786d64.png\";","export default __webpack_public_path__ + \"static/media/012-no trucks.bf3b4ed9.png\";","export default __webpack_public_path__ + \"static/media/013-no alarm.c6732ce5.png\";","export default __webpack_public_path__ + \"static/media/014-no turn left.7a57b70b.png\";","export default __webpack_public_path__ + \"static/media/015-no motorcycles.e72e07b7.png\";","export default __webpack_public_path__ + \"static/media/016-speed limit.96587810.png\";","export default __webpack_public_path__ + \"static/media/017-no overtaking.e093fefa.png\";","export default __webpack_public_path__ + \"static/media/018-pedestrian.49dc27d1.png\";","export default __webpack_public_path__ + \"static/media/019-no entry.31309892.png\";","export default __webpack_public_path__ + \"static/media/020-u turn.cc1171e5.png\";","export default __webpack_public_path__ + \"static/media/021-Two way.dad656b4.png\";","export default __webpack_public_path__ + \"static/media/022-pedestrian crossing.10e3b5d0.png\";","export default __webpack_public_path__ + \"static/media/023-right turn.01949354.png\";","export default __webpack_public_path__ + \"static/media/024-road work.b9ef5c5c.png\";","export default __webpack_public_path__ + \"static/media/025-roundabout.9ba22352.png\";","export default __webpack_public_path__ + \"static/media/026-pedestrian crossing.21ccb02a.png\";","export default __webpack_public_path__ + \"static/media/027-Slippery road.cb01f1f4.png\";","export default __webpack_public_path__ + \"static/media/028-traffic lights.195911bc.png\";","export default __webpack_public_path__ + \"static/media/029-turn left.ebfb7602.png\";","export default __webpack_public_path__ + \"static/media/030-turn right.c33332ed.png\";","export default __webpack_public_path__ + \"static/media/031-uneven.b33d0f06.png\";","export default __webpack_public_path__ + \"static/media/032-maximum.b544a731.png\";","export default __webpack_public_path__ + \"static/media/033-wild animals.96a2df8b.png\";","import icon0 from './001-narrow.png';\r\nimport icon1 from './002-merge.png';\r\nimport icon2 from './003-curve.png';\r\nimport icon3 from './004-curve.png';\r\nimport icon4 from './005-Junction.png';\r\nimport icon5 from './006-curve.png';\r\nimport icon6 from './007-crossroads.png';\r\nimport icon7 from './008-hump.png';\r\nimport icon8 from './009-uneven.png';\r\nimport icon9 from './010-roundabout.png';\r\nimport icon10 from './011-Two way.png';\r\nimport icon11 from './012-Junction.png';\r\nimport icon12 from './013-Junction.png';\r\nimport icon13 from './014-Two way.png';\r\nimport icon14 from './015-level.png';\r\nimport icon15 from './016-warning.png';\r\nimport icon16 from './017-hump.png';\r\nimport icon17 from './018-dock.png';\r\nimport icon18 from './019-merge.png';\r\nimport icon19 from './020-falling rocks.png';\r\nimport icon20 from './021-speed limit.png';\r\nimport icon21 from './022-speed limit.png';\r\nimport icon22 from './023-speed limit.png';\r\nimport icon23 from './024-speed limit.png';\r\nimport icon24 from './025-speed limit.png';\r\nimport icon25 from './026-speed limit.png';\r\nimport icon26 from './027-speed limit.png';\r\nimport icon27 from './028-priority.png';\r\nimport icon28 from './029-no overtaking.png';\r\nimport icon29 from './030-no turn right.png';\r\nimport icon30 from './031-u turn.png';\r\nimport icon31 from './032-no stopping.png';\r\nimport icon32 from './033-no waiting.png';\r\nimport icon33 from './034-ahead.png';\r\nimport icon34 from './035-turn left.png';\r\nimport icon35 from './036-keep left.png';\r\nimport icon36 from './037-direction.png';\r\nimport icon37 from './038-turn left.png';\r\nimport icon38 from './039-roundabout.png';\r\nimport icon39 from './040-no entry.png';\r\nimport icon40 from './041-parking.png';\r\nimport icon41 from './042-priority.png';\r\nimport icon42 from './043-cul de sac.png';\r\nimport icon43 from './044-countdown.png';\r\nimport icon44 from './045-countdown.png';\r\nimport icon45 from './046-countdown.png';\r\nimport icon46 from './047-hospital.png';\r\nimport icon47 from './048-information.png';\r\nimport icon48 from './049-speed camera.png';\r\nimport icon49 from './050-lane.png';\r\nimport icon50 from './051-end motorway.png';\r\nimport icon51 from './052-motorway.png';\r\nimport icon52 from './053-one way.png';\r\nimport icon53 from './054-direction.png';\r\nimport icon54 from './055-stop.png';\r\nimport icon55 from './056-road.png';\r\nimport icon56 from './057-emergency diversion.png';\r\nimport icon57 from './058-emergency diversion.png';\r\nimport icon58 from './059-emergency diversion.png';\r\nimport icon59 from './060-emergency diversion.png';\r\n\r\nconst textures = {\r\n '001-narrow': icon0,\r\n '002-merge': icon1,\r\n '003-curve': icon2,\r\n '004-curve': icon3,\r\n '005-Junction': icon4,\r\n '006-curve': icon5,\r\n '007-crossroads': icon6,\r\n '008-hump': icon7,\r\n '009-uneven': icon8,\r\n '010-roundabout': icon9,\r\n '011-Two way': icon10,\r\n '012-Junction': icon11,\r\n '013-Junction': icon12,\r\n '014-Two way': icon13,\r\n '015-level': icon14,\r\n '016-warning': icon15,\r\n '017-hump': icon16,\r\n '018-dock': icon17,\r\n '019-merge': icon18,\r\n '020-falling rocks': icon19,\r\n '021-speed limit': icon20,\r\n '022-speed limit': icon21,\r\n '023-speed limit': icon22,\r\n '024-speed limit': icon23,\r\n '025-speed limit': icon24,\r\n '026-speed limit': icon25,\r\n '027-speed limit': icon26,\r\n '028-priority': icon27,\r\n '029-no overtaking': icon28,\r\n '030-no turn right': icon29,\r\n '031-u turn': icon30,\r\n '032-no stopping': icon31,\r\n '033-no waiting': icon32,\r\n '034-ahead': icon33,\r\n '035-turn left': icon34,\r\n '036-keep left': icon35,\r\n '037-direction': icon36,\r\n '038-turn left': icon37,\r\n '039-roundabout': icon38,\r\n '040-no entry': icon39,\r\n '041-parking': icon40,\r\n '042-priority': icon41,\r\n '043-cul de sac': icon42,\r\n '044-countdown': icon43,\r\n '045-countdown': icon44,\r\n '046-countdown': icon45,\r\n '047-hospital': icon46,\r\n '048-information': icon47,\r\n '049-speed camera': icon48,\r\n '050-lane': icon49,\r\n '051-end motorway': icon50,\r\n '052-motorway': icon51,\r\n '053-one way': icon52,\r\n '054-direction': icon53,\r\n '055-stop': icon54,\r\n '056-road': icon55,\r\n '057-emergency diversion': icon56,\r\n '058-emergency diversion': icon57,\r\n '059-emergency diversion': icon58,\r\n '060-emergency diversion': icon59,\r\n};\r\n\r\nexport default textures;","export default __webpack_public_path__ + \"static/media/001-narrow.df856ac0.png\";","export default __webpack_public_path__ + \"static/media/002-merge.a4a30488.png\";","export default __webpack_public_path__ + \"static/media/003-curve.05546df5.png\";","export default __webpack_public_path__ + \"static/media/004-curve.8f7cd063.png\";","export default __webpack_public_path__ + \"static/media/005-Junction.4dffa6c5.png\";","export default __webpack_public_path__ + \"static/media/006-curve.e74f68f4.png\";","export default __webpack_public_path__ + \"static/media/007-crossroads.b4aeab6d.png\";","export default __webpack_public_path__ + \"static/media/008-hump.f5b1cab9.png\";","export default __webpack_public_path__ + \"static/media/009-uneven.397db48f.png\";","export default __webpack_public_path__ + \"static/media/010-roundabout.68d0ffbd.png\";","export default __webpack_public_path__ + \"static/media/011-Two way.d51a58d8.png\";","export default __webpack_public_path__ + \"static/media/012-Junction.bd60896e.png\";","export default __webpack_public_path__ + \"static/media/013-Junction.78c13ca2.png\";","export default __webpack_public_path__ + \"static/media/014-Two way.b345b22a.png\";","export default __webpack_public_path__ + \"static/media/015-level.f8296ff7.png\";","export default __webpack_public_path__ + \"static/media/016-warning.0019e601.png\";","export default __webpack_public_path__ + \"static/media/017-hump.30a7ba8f.png\";","export default __webpack_public_path__ + \"static/media/018-dock.fdf0064a.png\";","export default __webpack_public_path__ + \"static/media/019-merge.2190995c.png\";","export default __webpack_public_path__ + \"static/media/020-falling rocks.9f4df857.png\";","export default __webpack_public_path__ + \"static/media/021-speed limit.d6845db0.png\";","export default __webpack_public_path__ + \"static/media/022-speed limit.8064e31b.png\";","export default __webpack_public_path__ + \"static/media/023-speed limit.aed48e6f.png\";","export default __webpack_public_path__ + \"static/media/024-speed limit.1e362fee.png\";","export default __webpack_public_path__ + \"static/media/025-speed limit.347d7255.png\";","export default __webpack_public_path__ + \"static/media/026-speed limit.45d92974.png\";","export default __webpack_public_path__ + \"static/media/027-speed limit.980a6068.png\";","export default __webpack_public_path__ + \"static/media/028-priority.fc44147f.png\";","export default __webpack_public_path__ + \"static/media/029-no overtaking.58426286.png\";","export default __webpack_public_path__ + \"static/media/030-no turn right.acbc461d.png\";","export default __webpack_public_path__ + \"static/media/031-u turn.08809920.png\";","export default __webpack_public_path__ + \"static/media/032-no stopping.d7c7b42a.png\";","export default __webpack_public_path__ + \"static/media/033-no waiting.4e5fe72f.png\";","export default __webpack_public_path__ + \"static/media/034-ahead.58e48a36.png\";","export default __webpack_public_path__ + \"static/media/035-turn left.f545eb0c.png\";","export default __webpack_public_path__ + \"static/media/036-keep left.536a6a5c.png\";","export default __webpack_public_path__ + \"static/media/037-direction.d6d26740.png\";","export default __webpack_public_path__ + \"static/media/038-turn left.3517acec.png\";","export default __webpack_public_path__ + \"static/media/039-roundabout.e35a3904.png\";","export default __webpack_public_path__ + \"static/media/040-no entry.606b7596.png\";","export default __webpack_public_path__ + \"static/media/041-parking.2c36baed.png\";","export default __webpack_public_path__ + \"static/media/042-priority.8f2995ce.png\";","export default __webpack_public_path__ + \"static/media/043-cul de sac.1eda70a7.png\";","export default __webpack_public_path__ + \"static/media/044-countdown.cd86cb1a.png\";","export default __webpack_public_path__ + \"static/media/045-countdown.64bef15d.png\";","export default __webpack_public_path__ + \"static/media/046-countdown.7ede0d8c.png\";","export default __webpack_public_path__ + \"static/media/047-hospital.e4c63624.png\";","export default __webpack_public_path__ + \"static/media/048-information.803f80de.png\";","export default __webpack_public_path__ + \"static/media/049-speed camera.11651251.png\";","export default __webpack_public_path__ + \"static/media/050-lane.e8790c18.png\";","export default __webpack_public_path__ + \"static/media/051-end motorway.06ef8c65.png\";","export default __webpack_public_path__ + \"static/media/052-motorway.84800887.png\";","export default __webpack_public_path__ + \"static/media/053-one way.1028aeeb.png\";","export default __webpack_public_path__ + \"static/media/054-direction.ef3625e0.png\";","export default __webpack_public_path__ + \"static/media/055-stop.c8013090.png\";","export default __webpack_public_path__ + \"static/media/056-road.ae8fd707.png\";","export default __webpack_public_path__ + \"static/media/057-emergency diversion.e4fc4c07.png\";","export default __webpack_public_path__ + \"static/media/058-emergency diversion.cf3519dd.png\";","export default __webpack_public_path__ + \"static/media/059-emergency diversion.286133f6.png\";","export default __webpack_public_path__ + \"static/media/060-emergency diversion.8a4411bc.png\";","import icon0 from './construction--barrier--temporary.png';\r\nimport icon1 from './construction--flat--crosswalk-plain.png';\r\nimport icon2 from './construction--flat--driveway.png';\r\nimport icon3 from './construction--flat--flat-driveway.png';\r\nimport icon4 from './marking--discrete--arrow--left.png';\r\nimport icon5 from './marking--discrete--arrow--right.png';\r\nimport icon6 from './marking--discrete--arrow--split-left-or-straight.png';\r\nimport icon7 from './marking--discrete--arrow--split-right-or-straight.png';\r\nimport icon8 from './marking--discrete--arrow--straight.png';\r\nimport icon9 from './marking--discrete--crosswalk-zebra.png';\r\nimport icon10 from './marking--discrete--give-way-row.png';\r\nimport icon11 from './marking--discrete--give-way-single.png';\r\nimport icon12 from './marking--discrete--other-marking.png';\r\nimport icon13 from './marking--discrete--stop-line.png';\r\nimport icon14 from './marking--discrete--symbol--bicycle.png';\r\nimport icon15 from './marking--discrete--text.png';\r\nimport icon16 from './object--banner.png';\r\nimport icon17 from './object--bench.png';\r\nimport icon18 from './object--bike-rack.png';\r\nimport icon19 from './object--catch-basin.png';\r\nimport icon20 from './object--cctv-camera.png';\r\nimport icon21 from './object--fire-hydrant.png';\r\nimport icon22 from './object--junction-box.png';\r\nimport icon23 from './object--mailbox.png';\r\nimport icon24 from './object--manhole.png';\r\nimport icon25 from './object--parking-meter.png';\r\nimport icon26 from './object--phone-booth.png';\r\nimport icon27 from './object--sign--advertisement.png';\r\nimport icon28 from './object--sign--information.png';\r\nimport icon29 from './object--sign--store.png';\r\nimport icon30 from './object--street-light.png';\r\nimport icon31 from './object--support--pole.png';\r\nimport icon32 from './object--support--traffic-sign-frame.png';\r\nimport icon33 from './object--support--utility-pole.png';\r\nimport icon34 from './object--traffic-cone.png';\r\nimport icon35 from './object--traffic-light.png';\r\nimport icon36 from './object--trash-can.png';\r\nimport icon37 from './object--water-valve.png';\r\n\r\nconst textures = {\r\n 'construction--barrier--temporary': icon0,\r\n 'construction--flat--crosswalk-plain': icon1,\r\n 'construction--flat--driveway': icon2,\r\n 'construction--flat--flat-driveway': icon3,\r\n 'marking--discrete--arrow--left': icon4,\r\n 'marking--discrete--arrow--right': icon5,\r\n 'marking--discrete--arrow--split-left-or-straight': icon6,\r\n 'marking--discrete--arrow--split-right-or-straight': icon7,\r\n 'marking--discrete--arrow--straight': icon8,\r\n 'marking--discrete--crosswalk-zebra': icon9,\r\n 'marking--discrete--give-way-row': icon10,\r\n 'marking--discrete--give-way-single': icon11,\r\n 'marking--discrete--other-marking': icon12,\r\n 'marking--discrete--stop-line': icon13,\r\n 'marking--discrete--symbol--bicycle': icon14,\r\n 'marking--discrete--text': icon15,\r\n 'object--banner': icon16,\r\n 'object--bench': icon17,\r\n 'object--bike-rack': icon18,\r\n 'object--catch-basin': icon19,\r\n 'object--cctv-camera': icon20,\r\n 'object--fire-hydrant': icon21,\r\n 'object--junction-box': icon22,\r\n 'object--mailbox': icon23,\r\n 'object--manhole': icon24,\r\n 'object--parking-meter': icon25,\r\n 'object--phone-booth': icon26,\r\n 'object--sign--advertisement': icon27,\r\n 'object--sign--information': icon28,\r\n 'object--sign--store': icon29,\r\n 'object--street-light': icon30,\r\n 'object--support--pole': icon31,\r\n 'object--support--traffic-sign-frame': icon32,\r\n 'object--support--utility-pole': icon33,\r\n 'object--traffic-cone': icon34,\r\n 'object--traffic-light': icon35,\r\n 'object--trash-can': icon36,\r\n 'object--water-valve': icon37,\r\n};\r\n\r\nexport default textures;","export default __webpack_public_path__ + \"static/media/construction--barrier--temporary.c295cec2.png\";","export default __webpack_public_path__ + \"static/media/construction--flat--crosswalk-plain.3d80b1ca.png\";","export default __webpack_public_path__ + \"static/media/construction--flat--driveway.9fd50f90.png\";","export default __webpack_public_path__ + \"static/media/construction--flat--flat-driveway.dbed896e.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--arrow--left.5a8ed6fe.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--arrow--right.0c25ddcb.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--arrow--split-left-or-straight.26ea6315.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--arrow--split-right-or-straight.19848277.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--arrow--straight.c32e8693.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--crosswalk-zebra.41655dfd.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--give-way-row.d469bc27.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--give-way-single.88347f54.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--other-marking.0b3d3063.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--stop-line.926dabb3.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--symbol--bicycle.b160ff92.png\";","export default __webpack_public_path__ + \"static/media/marking--discrete--text.a473cb73.png\";","export default __webpack_public_path__ + \"static/media/object--banner.4261826e.png\";","export default __webpack_public_path__ + \"static/media/object--bench.de45c74e.png\";","export default __webpack_public_path__ + \"static/media/object--bike-rack.2d333cd5.png\";","export default __webpack_public_path__ + \"static/media/object--catch-basin.6c8a4f84.png\";","export default __webpack_public_path__ + \"static/media/object--cctv-camera.2eea74b0.png\";","export default __webpack_public_path__ + \"static/media/object--fire-hydrant.d91d17bd.png\";","export default __webpack_public_path__ + \"static/media/object--junction-box.75aae919.png\";","export default __webpack_public_path__ + \"static/media/object--mailbox.6bae4b92.png\";","export default __webpack_public_path__ + \"static/media/object--manhole.049795d8.png\";","export default __webpack_public_path__ + \"static/media/object--parking-meter.0c26ccb0.png\";","export default __webpack_public_path__ + \"static/media/object--phone-booth.b2671fc0.png\";","export default __webpack_public_path__ + \"static/media/object--sign--advertisement.1d13d128.png\";","export default __webpack_public_path__ + \"static/media/object--sign--information.88add084.png\";","export default __webpack_public_path__ + \"static/media/object--sign--store.6da73474.png\";","export default __webpack_public_path__ + \"static/media/object--street-light.99b39470.png\";","export default __webpack_public_path__ + \"static/media/object--support--pole.36dfcf46.png\";","export default __webpack_public_path__ + \"static/media/object--support--traffic-sign-frame.7bae73cd.png\";","export default __webpack_public_path__ + \"static/media/object--support--utility-pole.71ce4ba5.png\";","export default __webpack_public_path__ + \"static/media/object--traffic-cone.b0f05e52.png\";","export default __webpack_public_path__ + \"static/media/object--traffic-light.6dd482e0.png\";","export default __webpack_public_path__ + \"static/media/object--trash-can.4ba13bc2.png\";","export default __webpack_public_path__ + \"static/media/object--water-valve.848a98d0.png\";","export default __webpack_public_path__ + \"static/media/complementary--accident-area--g1.d5411006.png\";","export default __webpack_public_path__ + \"static/media/complementary--accident-area--g2.6b892819.png\";","export default __webpack_public_path__ + \"static/media/complementary--accident-area--g3.39c5aa2d.png\";","export default __webpack_public_path__ + \"static/media/complementary--accident-area--g4.c8960430.png\";","export default __webpack_public_path__ + \"static/media/complementary--advisory-exit-or-ramp-speed--g1.d5aa6bd3.png\";","export default __webpack_public_path__ + \"static/media/complementary--bicycles--g1.e8a92988.png\";","export default __webpack_public_path__ + \"static/media/complementary--bicycles-and-pedestrians-detour--g1.dcab8b13.png\";","export default __webpack_public_path__ + \"static/media/complementary--bicycles-or-pedestrians-detour--g1.e5138d21.png\";","export default __webpack_public_path__ + \"static/media/complementary--bicycles-turn-right--g1.b50cdd8a.png\";","export default __webpack_public_path__ + \"static/media/complementary--bike-route--g1.ad85731c.png\";","export default __webpack_public_path__ + \"static/media/complementary--bike-route--g3.1a874469.png\";","export default __webpack_public_path__ + \"static/media/complementary--both-directions--g1.1eaa27e4.png\";","export default __webpack_public_path__ + \"static/media/complementary--both-directions--g2.ab7a5976.png\";","export default __webpack_public_path__ + \"static/media/complementary--buses--g1.faffc898.png\";","export default __webpack_public_path__ + \"static/media/complementary--buses-and-trucks--g1.d1b0d33f.png\";","export default __webpack_public_path__ + \"static/media/complementary--camera--g1.41a87e99.png\";","export default __webpack_public_path__ + \"static/media/complementary--camera--g2.307561d6.png\";","export default __webpack_public_path__ + \"static/media/complementary--camera--g3.859735f8.png\";","export default __webpack_public_path__ + \"static/media/complementary--camera--g4.5bcf9af2.png\";","export default __webpack_public_path__ + \"static/media/complementary--camera--g5.811530fb.png\";","export default __webpack_public_path__ + \"static/media/complementary--caravan-trailers--g2.a2b733be.png\";","export default __webpack_public_path__ + \"static/media/complementary--caravan-trailers--g3.1ed469ef.png\";","export default __webpack_public_path__ + \"static/media/complementary--caravans--g2.ce71e539.png\";","export default __webpack_public_path__ + \"static/media/complementary--carts--g1.fea12c17.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-left--g1.57ac3093.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-left--g2.6443d98c.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-left--g3.a6c83c95.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-left--g4.77777d15.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-left--g5.2f7987c9.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-right--g1.f22f39f2.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-right--g2.71ba8ac6.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-right--g3.1dd25331.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-right--g4.651efd19.png\";","export default __webpack_public_path__ + \"static/media/complementary--chevron-right--g5.7734c675.png\";","export default __webpack_public_path__ + \"static/media/complementary--dangerous-or-pollutant-good--g1.3bf88255.png\";","export default __webpack_public_path__ + \"static/media/complementary--dead-end--g1.1e58d714.png\";","export default __webpack_public_path__ + \"static/media/complementary--detour--g1.227caa6a.png\";","export default __webpack_public_path__ + \"static/media/complementary--disabled-persons--g1.359b3b95.png\";","export default __webpack_public_path__ + \"static/media/complementary--distance--g1.108230dd.png\";","export default __webpack_public_path__ + \"static/media/complementary--distance--g2.f24fae54.png\";","export default __webpack_public_path__ + \"static/media/complementary--distance--g3.2d9b5876.png\";","export default __webpack_public_path__ + \"static/media/complementary--end-of-road-works--g1.92d44f56.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-bicycles--g1.a9f8a4b1.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-bicycles--g2.64490d3f.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-buses--g1.1ba43e99.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-carts--g1.68857953.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-motorcycles--g1.1c4d4f08.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-motorcycles--g2.f66bc691.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-polluting-level-green--g1.a4a5c035.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-polluting-level-green-yellow--g1.b02fc562.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-polluting-level-green-yellow-red--g1.36e116eb.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-tractors--g1.5fffbc13.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-tractors--g2.b5eb0923.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-trailers--g1.fb401260.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-trailers--g2.915ae4eb.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-trains--g1.969b8921.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-trams--g1.68209674.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-trucks--g1.e68b7c31.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-vehicles--g1.89da1dbd.png\";","export default __webpack_public_path__ + \"static/media/complementary--except-vehicles--g2.a39aee57.png\";","export default __webpack_public_path__ + \"static/media/complementary--go-left--g1.c3874410.png\";","export default __webpack_public_path__ + \"static/media/complementary--go-right--g1.f0fa8d37.png\";","export default __webpack_public_path__ + \"static/media/complementary--go-straight-or-turn-left--g1.0a66ac06.png\";","export default __webpack_public_path__ + \"static/media/complementary--go-straight-or-turn-right--g1.bf518ff3.png\";","export default __webpack_public_path__ + \"static/media/complementary--height-limit--g1.66143aeb.png\";","export default __webpack_public_path__ + \"static/media/complementary--height-limit--g2.5f8c440f.png\";","export default __webpack_public_path__ + \"static/media/complementary--including-bicycles-and-motorcycles--g1.ee870326.png\";","export default __webpack_public_path__ + \"static/media/complementary--including-buses-vehicles--g1.03851082.png\";","export default __webpack_public_path__ + \"static/media/complementary--keep-left--g1.9f4023c8.png\";","export default __webpack_public_path__ + \"static/media/complementary--keep-right--g1.4194a29d.png\";","export default __webpack_public_path__ + \"static/media/complementary--lane-control--g1.82117f8e.png\";","export default __webpack_public_path__ + \"static/media/complementary--lane-control--g2.c5f7c989.png\";","export default __webpack_public_path__ + \"static/media/complementary--lane-control--g3.ade4dcda.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-10--g1.53abf612.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-15--g1.c67ac701.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-20--g1.d2e11200.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-25--g1.ecdfffb1.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-30--g1.df513571.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-35--g1.bf20adba.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-40--g1.8969e2c1.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-45--g1.cdce0b1d.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-50--g1.6b808783.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-55--g1.be855ff8.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-60--g1.23136090.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-65--g1.058ac585.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-70--g1.361e8a6e.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-75--g1.3fd589fc.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-80--g1.4a213736.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-85--g1.ba8d0d8b.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-90--g1.c363995e.png\";","export default __webpack_public_path__ + \"static/media/complementary--maximum-speed-limit-95--g1.a5f29207.png\";","export default __webpack_public_path__ + \"static/media/complementary--motorcycles--g1.511b5604.png\";","export default __webpack_public_path__ + \"static/media/complementary--motorcycles--g2.593b05ac.png\";","export default __webpack_public_path__ + \"static/media/complementary--motorcycles--g3.1c3e0e2b.png\";","export default __webpack_public_path__ + \"static/media/complementary--motorcycles--g4.b3d432a8.png\";","export default __webpack_public_path__ + \"static/media/complementary--obstacle-delineator--g1.2be98597.png\";","export default __webpack_public_path__ + \"static/media/complementary--obstacle-delineator--g2.1e86ca50.png\";","export default __webpack_public_path__ + \"static/media/complementary--obstacle-delineator--g3.2445aeb2.png\";","export default __webpack_public_path__ + \"static/media/complementary--one-direction-left--g1.72b7311e.png\";","export default __webpack_public_path__ + \"static/media/complementary--one-direction-right--g1.ef8aa050.png\";","export default __webpack_public_path__ + \"static/media/complementary--pass-left--g1.e63e20d4.png\";","export default __webpack_public_path__ + \"static/media/complementary--pass-right--g1.8143583a.png\";","export default __webpack_public_path__ + \"static/media/complementary--pedestrians-and-bicycles--g1.46b1b0b1.png\";","export default __webpack_public_path__ + \"static/media/complementary--pedestrians-left--g1.b56a5492.png\";","export default __webpack_public_path__ + \"static/media/complementary--pedestrians-right--g1.01475b36.png\";","export default __webpack_public_path__ + \"static/media/complementary--photo-enforced--g1.7f00dc63.png\";","export default __webpack_public_path__ + \"static/media/complementary--playground--g1.7cc32db1.png\";","export default __webpack_public_path__ + \"static/media/complementary--priority-route-at-intersection--g1.339b5f15.png\";","export default __webpack_public_path__ + \"static/media/complementary--priority-route-at-intersection--g2.0f1e5df5.png\";","export default __webpack_public_path__ + \"static/media/complementary--priority-route-at-intersection--g3.a266b74b.png\";","export default __webpack_public_path__ + \"static/media/complementary--priority-route-at-intersection--g4.fc911c8e.png\";","export default __webpack_public_path__ + \"static/media/complementary--priority-route-at-intersection--g5.472959d3.png\";","export default __webpack_public_path__ + \"static/media/complementary--priority-route-at-intersection--g6.9b72a153.png\";","export default __webpack_public_path__ + \"static/media/complementary--railroad--g1.ac072e7a.png\";","export default __webpack_public_path__ + \"static/media/complementary--railroad--g2.7ae94b03.png\";","export default __webpack_public_path__ + \"static/media/complementary--railroad--g3.3ee9fe34.png\";","export default __webpack_public_path__ + \"static/media/complementary--restriction-in-both-directions--g1.076c822f.png\";","export default __webpack_public_path__ + \"static/media/complementary--roundabout-go-left--g1.4b39fec6.png\";","export default __webpack_public_path__ + \"static/media/complementary--roundabout-go-right--g1.c4bcfb99.png\";","export default __webpack_public_path__ + \"static/media/complementary--roundabout-go-straight--g1.8374e8e8.png\";","export default __webpack_public_path__ + \"static/media/complementary--slippery-for-caravan-trailers--g1.22bf4483.png\";","export default __webpack_public_path__ + \"static/media/complementary--snow--g2.d69deef2.png\";","export default __webpack_public_path__ + \"static/media/complementary--snow--g4.767b8bcc.png\";","export default __webpack_public_path__ + \"static/media/complementary--snow--g5.9cab1800.png\";","export default __webpack_public_path__ + \"static/media/complementary--snowmobiles--g1.040ef047.png\";","export default __webpack_public_path__ + \"static/media/complementary--soft-shoulder--g1.69316d35.png\";","export default __webpack_public_path__ + \"static/media/complementary--soft-shoulder--g2.7ca975f6.png\";","export default __webpack_public_path__ + \"static/media/complementary--steep-ascent--g1.530757ce.png\";","export default __webpack_public_path__ + \"static/media/complementary--steep-descent--g1.8c7f6ee5.png\";","export default __webpack_public_path__ + \"static/media/complementary--time-restrictions--g1.26eaeae5.png\";","export default __webpack_public_path__ + \"static/media/complementary--time-restrictions--g3.4c6120b8.png\";","export default __webpack_public_path__ + \"static/media/complementary--tow-away-zone--g1.8e752887.png\";","export default __webpack_public_path__ + \"static/media/complementary--tow-away-zone--g3.22f7f3eb.png\";","export default __webpack_public_path__ + \"static/media/complementary--tractors--g1.e217db9e.png\";","export default __webpack_public_path__ + \"static/media/complementary--traffic-queues--g1.798af17a.png\";","export default __webpack_public_path__ + \"static/media/complementary--trailers--g1.f2bf02fe.png\";","export default __webpack_public_path__ + \"static/media/complementary--trailers--g2.bbd07d83.png\";","export default __webpack_public_path__ + \"static/media/complementary--trailers--g3.e99a3109.png\";","export default __webpack_public_path__ + \"static/media/complementary--trailers--g4.b351db3d.png\";","export default __webpack_public_path__ + \"static/media/complementary--trains--g1.006bb9eb.png\";","export default __webpack_public_path__ + \"static/media/complementary--trams--g1.3bfc644b.png\";","export default __webpack_public_path__ + \"static/media/complementary--trees--g1.26a10d2b.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks--g1.679a2a43.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks--g2.930ba842.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks--g3.41659ea2.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-and-trailers--g1.67787aa2.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-buses-trailers--g1.af473f66.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-go-left--g1.2884aa5c.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-go-left-ahead--g1.abe94d9d.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-go-right--g1.82ab3332.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-go-right-ahead--g1.b575da79.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-go-straight--g1.76cd0c33.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-turn-left--g1.d2ead92b.png\";","export default __webpack_public_path__ + \"static/media/complementary--trucks-turn-right--g1.f2a4dae6.png\";","export default __webpack_public_path__ + \"static/media/complementary--turn-left--g1.6d813807.png\";","export default __webpack_public_path__ + \"static/media/complementary--turn-left--g2.6fd51622.png\";","export default __webpack_public_path__ + \"static/media/complementary--turn-right--g1.88241ef1.png\";","export default __webpack_public_path__ + \"static/media/complementary--turn-right--g2.4b154bb3.png\";","export default __webpack_public_path__ + \"static/media/complementary--two-way-traffic--g1.ecba5f2b.png\";","export default __webpack_public_path__ + \"static/media/complementary--two-way-traffic--g2.45a6a7c7.png\";","export default __webpack_public_path__ + \"static/media/complementary--two-way-traffic--g3.46b191f8.png\";","export default __webpack_public_path__ + \"static/media/complementary--two-way-traffic--g4.05df5af7.png\";","export default __webpack_public_path__ + \"static/media/complementary--two-way-traffic--g5.23d82cc1.png\";","export default __webpack_public_path__ + \"static/media/complementary--vehicles--g1.3e0f8a88.png\";","export default __webpack_public_path__ + \"static/media/complementary--vehicles--g2.546a3e5a.png\";","export default __webpack_public_path__ + \"static/media/complementary--vehicles-or-buses--g1.28a800fd.png\";","export default __webpack_public_path__ + \"static/media/complementary--weekends-or-holidays--g1.75bb96df.png\";","export default __webpack_public_path__ + \"static/media/complementary--weight-limit--g1.bdc6c055.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-foggy--g1.ce7480ff.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-rainy--g1.3e9a4e29.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-rainy--g2.5743ee89.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-rainy--g3.0b5ed3f3.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-snowy--g1.eb82e32c.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-snowy--g2.b221027b.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-snowy-or-rainy--g1.af3f362e.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-snowy-or-rainy--g2.bf4655ce.png\";","export default __webpack_public_path__ + \"static/media/complementary--when-wet--g1.11ed4478.png\";","export default __webpack_public_path__ + \"static/media/complementary--width-limit--g1.cef661be.png\";","export default __webpack_public_path__ + \"static/media/complementary--working-days--g1.313bbb27.png\";","export default __webpack_public_path__ + \"static/media/information--airport--g1.73af71fe.png\";","export default __webpack_public_path__ + \"static/media/information--airport--g2.81208f16.png\";","export default __webpack_public_path__ + \"static/media/information--bicycle-lane--g1.504421c1.png\";","export default __webpack_public_path__ + \"static/media/information--bicycles-both-ways--g1.c95bbe04.png\";","export default __webpack_public_path__ + \"static/media/information--bicycles-crossing--g1.f4c114cf.png\";","export default __webpack_public_path__ + \"static/media/information--bicycles-crossing--g2.bf76e715.png\";","export default __webpack_public_path__ + \"static/media/information--bicycles-crossing--g3.6a7abeba.png\";","export default __webpack_public_path__ + \"static/media/information--bike-route--g1.62a47331.png\";","export default __webpack_public_path__ + \"static/media/information--bike-route--g2.97104997.png\";","export default __webpack_public_path__ + \"static/media/information--built-up-area--g1.ac4f16b0.png\";","export default __webpack_public_path__ + \"static/media/information--built-up-area--g2.11ebb081.png\";","export default __webpack_public_path__ + \"static/media/information--bus-lane-straight--g1.4a1a0ce3.png\";","export default __webpack_public_path__ + \"static/media/information--bus-stop--g1.a7ecbcd5.png\";","export default __webpack_public_path__ + \"static/media/information--bus-stop--g2.81775f9e.png\";","export default __webpack_public_path__ + \"static/media/information--camera--g1.a402e59a.png\";","export default __webpack_public_path__ + \"static/media/information--camera--g2.d5adb6c7.png\";","export default __webpack_public_path__ + \"static/media/information--camera--g3.44300682.png\";","export default __webpack_public_path__ + \"static/media/information--camp--g1.84c6b6d9.png\";","export default __webpack_public_path__ + \"static/media/information--camp--g2.b85f120d.png\";","export default __webpack_public_path__ + \"static/media/information--car-pool-lane--g1.2eade6ef.png\";","export default __webpack_public_path__ + \"static/media/information--caravan-parking--g1.18735370.png\";","export default __webpack_public_path__ + \"static/media/information--caravan-trailer-parking--g1.71f0f60c.png\";","export default __webpack_public_path__ + \"static/media/information--cargo-loading-zone--g1.e90c9dac.png\";","export default __webpack_public_path__ + \"static/media/information--central-lane--g1.fe7e0080.png\";","export default __webpack_public_path__ + \"static/media/information--charging-station--g1.38a12cae.png\";","export default __webpack_public_path__ + \"static/media/information--children--g1.84e33dd2.png\";","export default __webpack_public_path__ + \"static/media/information--children--g2.aede4dee.png\";","export default __webpack_public_path__ + \"static/media/information--children-crossing--g5.829b1301.png\";","export default __webpack_public_path__ + \"static/media/information--cycling-two-abreast-permitted--g1.f7b5c1af.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end--g1.337632a7.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end--g2.313e9231.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end--g3.0f065135.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end--g4.50b3a50f.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-except-bicycles--g1.00a6125f.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-except-bicycles-and-pedestrians--g1.872ecfb2.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-except-bicycles-and-pedestrians--g2.403f04e3.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-left--g1.81116d41.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-left--g2.369ad9b4.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-right--g1.b3196029.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-right--g2.92903f2b.png\";","export default __webpack_public_path__ + \"static/media/information--dead-end-right--g3.00e4000a.png\";","export default __webpack_public_path__ + \"static/media/information--directions--g1.5b231c54.png\";","export default __webpack_public_path__ + \"static/media/information--disabled-persons--g1.4bcf3f61.png\";","export default __webpack_public_path__ + \"static/media/information--disabled-persons--g2.43579fe3.png\";","export default __webpack_public_path__ + \"static/media/information--disabled-persons--g3.312f93f3.png\";","export default __webpack_public_path__ + \"static/media/information--emergency-facility--g1.5f24e4fe.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-advisory-maximum-speed-limit-20--g1.83f3bca3.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-advisory-maximum-speed-limit-40--g1.d09cf637.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-advisory-maximum-speed-limit-60--g1.cbd3a657.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-advisory-maximum-speed-limit-70--g1.a14754dc.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-advisory-maximum-speed-limit-80--g1.20280fbf.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-advisory-maximum-speed-limit-90--g1.84ad37e8.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-bicycle-lane--g1.d2b5baa9.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-built-up-area--g1.d3c1e825.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-built-up-area--g2.c2932636.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-built-up-area--g3.d59cc0fb.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-built-up-area--g4.88e9bd6b.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-car-pool-lane--g1.83bbacf0.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-limited-access-road--g1.4d253455.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-living-street--g1.b9ad088e.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-living-street--g2.edcc67c9.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-10--g1.ca614575.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-20--g1.abe33ebd.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-25--g1.43799527.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-30--g1.779efce2.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-35--g1.674a262a.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-40--g1.baa5bd2c.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-50--g1.20353c86.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-60--g1.461328dc.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-70--g1.2e31daaf.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-75--g1.4bc31e63.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-80--g1.e2f688b1.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-90--g1.49bdceb5.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-100--g1.e83e0d13.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-110--g1.719ac78c.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-120--g1.57a848ce.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-minimum-speed-130--g1.58da3ff2.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-motorway--g1.645f1476.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-overtaking-permitted-heavy-good-vehicles--g1.b36d111d.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-road-works--g1.5b7f3560.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-tunnel--g1.90fc460c.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-tunnel--g2.7ac93cff.png\";","export default __webpack_public_path__ + \"static/media/information--end-of-two-way-traffic--g1.88eeaba6.png\";","export default __webpack_public_path__ + \"static/media/information--equestrians-permitted--g1.a22f8bf3.png\";","export default __webpack_public_path__ + \"static/media/information--exit-ahead--g1.95953c4c.png\";","export default __webpack_public_path__ + \"static/media/information--exit-ahead--g2.d7e0a668.png\";","export default __webpack_public_path__ + \"static/media/information--exit-ahead--g3.36f7fe6b.png\";","export default __webpack_public_path__ + \"static/media/information--flight-port--g1.6ffedaed.png\";","export default __webpack_public_path__ + \"static/media/information--food--g1.c3a95157.png\";","export default __webpack_public_path__ + \"static/media/information--food--g2.a19e0e4d.png\";","export default __webpack_public_path__ + \"static/media/information--gas-station--g1.835ad032.png\";","export default __webpack_public_path__ + \"static/media/information--gas-station--g2.397a57fc.png\";","export default __webpack_public_path__ + \"static/media/information--gas-station--g3.d417b630.png\";","export default __webpack_public_path__ + \"static/media/information--general-speed-limit-at-city-border--g1.162d9f16.png\";","export default __webpack_public_path__ + \"static/media/information--go-left--g1.b4653a1a.png\";","export default __webpack_public_path__ + \"static/media/information--go-right--g1.fb259e79.png\";","export default __webpack_public_path__ + \"static/media/information--go-straight--g1.2b4c9d90.png\";","export default __webpack_public_path__ + \"static/media/information--go-straight-or-left--g1.61f62586.png\";","export default __webpack_public_path__ + \"static/media/information--go-straight-or-right--g1.74189079.png\";","export default __webpack_public_path__ + \"static/media/information--go-straight-or-turn-left--g1.fe58d18a.png\";","export default __webpack_public_path__ + \"static/media/information--go-straight-or-turn-right--g1.01ba2725.png\";","export default __webpack_public_path__ + \"static/media/information--hazardous-goods-vehicles-lane--g1.5d266d26.png\";","export default __webpack_public_path__ + \"static/media/information--height-limit--g1.55576056.png\";","export default __webpack_public_path__ + \"static/media/information--height-limit--g2.28706fba.png\";","export default __webpack_public_path__ + \"static/media/information--highway-directions--g1.6ab6f919.png\";","export default __webpack_public_path__ + \"static/media/information--highway-exit--g1.8693888b.png\";","export default __webpack_public_path__ + \"static/media/information--highway-interchange--g1.247302e7.png\";","export default __webpack_public_path__ + \"static/media/information--highway-interstate-route--g1.692a691b.png\";","export default __webpack_public_path__ + \"static/media/information--highway-interstate-route--g2.accf6f1f.png\";","export default __webpack_public_path__ + \"static/media/information--highway-preferential-lane--g1.46a6e511.png\";","export default __webpack_public_path__ + \"static/media/information--highway-preferential-lane--g2.00aa828a.png\";","export default __webpack_public_path__ + \"static/media/information--highway-reference-location--g1.fd97a9dc.png\";","export default __webpack_public_path__ + \"static/media/information--highway-reference-location--g2.8a376ffd.png\";","export default __webpack_public_path__ + \"static/media/information--hiking--g1.e7ebd601.png\";","export default __webpack_public_path__ + \"static/media/information--hospital--g1.df445bc6.png\";","export default __webpack_public_path__ + \"static/media/information--hurricane-evacuation-route--g1.51f3af3c.png\";","export default __webpack_public_path__ + \"static/media/information--interstate-route--g1.970c0135.png\";","export default __webpack_public_path__ + \"static/media/information--lane-control-intersections--g1.7a491f54.png\";","export default __webpack_public_path__ + \"static/media/information--lane-control-left-turn--g1.b9518417.png\";","export default __webpack_public_path__ + \"static/media/information--lane-control-multiple-lanes--g1.ea69ae2c.png\";","export default __webpack_public_path__ + \"static/media/information--lane-control-multiple-lanes--g2.c56d8bde.png\";","export default __webpack_public_path__ + \"static/media/information--lane-control-right-turn--g1.5fa2157c.png\";","export default __webpack_public_path__ + \"static/media/information--limited-access-road--g1.10cc71f3.png\";","export default __webpack_public_path__ + \"static/media/information--litter-container--g1.08c4ff13.png\";","export default __webpack_public_path__ + \"static/media/information--living-street--g1.2147c93f.png\";","export default __webpack_public_path__ + \"static/media/information--living-street--g2.9e441868.png\";","export default __webpack_public_path__ + \"static/media/information--living-street--g3.25c4364f.png\";","export default __webpack_public_path__ + \"static/media/information--lodging--g1.b607f4af.png\";","export default __webpack_public_path__ + \"static/media/information--lodging--g2.22045613.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-10--g1.3b83bdd9.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-20--g1.b0190c7b.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-25--g1.4db75e5c.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-30--g1.23729b05.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-35--g1.6e07ff1c.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-40--g1.3414f977.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-50--g1.76ed27c6.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-60--g1.212570f9.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-70--g1.c8d65d5e.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-75--g1.4939a840.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-80--g1.a7714163.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-90--g1.0b274895.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-100--g1.7102a855.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-110--g1.633ec596.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-120--g1.bce2e4ca.png\";","export default __webpack_public_path__ + \"static/media/information--minimum-speed-130--g1.c5a36eb0.png\";","export default __webpack_public_path__ + \"static/media/information--motorway--g1.a94a8e76.png\";","export default __webpack_public_path__ + \"static/media/information--motorway-exit-ahead--g1.0691dc2f.png\";","export default __webpack_public_path__ + \"static/media/information--motorway-exit-ahead--g2.b8daa7b6.png\";","export default __webpack_public_path__ + \"static/media/information--motorway-exit-ahead--g3.8af9ebcc.png\";","export default __webpack_public_path__ + \"static/media/information--overtaking-allowed-heavy-good-vehicles--g1.39e05fa4.png\";","export default __webpack_public_path__ + \"static/media/information--parallel-parking--g1.c0d4c10a.png\";","export default __webpack_public_path__ + \"static/media/information--park-and-ride--g1.b750a298.png\";","export default __webpack_public_path__ + \"static/media/information--park-and-ride--g2.c953d0be.png\";","export default __webpack_public_path__ + \"static/media/information--parking--g1.df52d553.png\";","export default __webpack_public_path__ + \"static/media/information--parking--g2.87609a48.png\";","export default __webpack_public_path__ + \"static/media/information--parking--g3.7fd2c641.png\";","export default __webpack_public_path__ + \"static/media/information--parking--g4.09eab1e8.png\";","export default __webpack_public_path__ + \"static/media/information--parking--g5.37047c3d.png\";","export default __webpack_public_path__ + \"static/media/information--parking--g6.8b6482a2.png\";","export default __webpack_public_path__ + \"static/media/information--parking-area--g1.a2bc1b0f.png\";","export default __webpack_public_path__ + \"static/media/information--parking-with-restrictions--g1.55284b47.png\";","export default __webpack_public_path__ + \"static/media/information--pass-on-either-side--g1.5bd589b7.png\";","export default __webpack_public_path__ + \"static/media/information--passenger-loading-zone--g1.ab94bd58.png\";","export default __webpack_public_path__ + \"static/media/information--pedestrians-crossing--g1.c953e4e9.png\";","export default __webpack_public_path__ + \"static/media/information--pedestrians-crossing--g2.183ef6cc.png\";","export default __webpack_public_path__ + \"static/media/information--pedestrians-crossing--g3.39fc0c2e.png\";","export default __webpack_public_path__ + \"static/media/information--pedestrians-only--g4.6947b95d.png\";","export default __webpack_public_path__ + \"static/media/information--pedestrians-permitted--g1.5f6c67bf.png\";","export default __webpack_public_path__ + \"static/media/information--perpendicular-parking--g1.5c9b6826.png\";","export default __webpack_public_path__ + \"static/media/information--picnic-site--g1.6194592a.png\";","export default __webpack_public_path__ + \"static/media/information--playground--g1.300b5c9c.png\";","export default __webpack_public_path__ + \"static/media/information--recreational-vehicle-sanitary-station--g1.e0780834.png\";","export default __webpack_public_path__ + \"static/media/information--recycle-collection-center--g1.8a0f22c1.png\";","export default __webpack_public_path__ + \"static/media/information--rest-area--g1.23aa47b9.png\";","export default __webpack_public_path__ + \"static/media/information--road-bump--g1.59ac514a.png\";","export default __webpack_public_path__ + \"static/media/information--road-skating--g1.dbd17d5a.png\";","export default __webpack_public_path__ + \"static/media/information--safety-zone--g1.8bc0bf83.png\";","export default __webpack_public_path__ + \"static/media/information--safety-zone--g2.106d3366.png\";","export default __webpack_public_path__ + \"static/media/information--safety-zone--g3.82f31562.png\";","export default __webpack_public_path__ + \"static/media/information--shared-path-vehicles-and-motorcycles--g1.50a9ff18.png\";","export default __webpack_public_path__ + \"static/media/information--stairs--g1.71f0a107.png\";","export default __webpack_public_path__ + \"static/media/information--stairs--g2.17a18300.png\";","export default __webpack_public_path__ + \"static/media/information--stairs--g3.af1160fa.png\";","export default __webpack_public_path__ + \"static/media/information--stairs--g4.64156853.png\";","export default __webpack_public_path__ + \"static/media/information--stop-line--g1.e9808c91.png\";","export default __webpack_public_path__ + \"static/media/information--stop-permitted--g1.686135de.png\";","export default __webpack_public_path__ + \"static/media/information--street-name-one-line--g1.94494101.png\";","export default __webpack_public_path__ + \"static/media/information--street-name-three-lines--g1.80615ed6.png\";","export default __webpack_public_path__ + \"static/media/information--street-name-two-lines--g1.9fdf4282.png\";","export default __webpack_public_path__ + \"static/media/information--subway--g1.11a232ac.png\";","export default __webpack_public_path__ + \"static/media/information--telephone--g1.f3e76f2a.png\";","export default __webpack_public_path__ + \"static/media/information--telephone--g2.e30d7202.png\";","export default __webpack_public_path__ + \"static/media/information--telephone-device-for-the-deaf--g1.3dd43d70.png\";","export default __webpack_public_path__ + \"static/media/information--toll-station--g1.b1ef927a.png\";","export default __webpack_public_path__ + \"static/media/information--tourism-information--g1.e4c2c0fd.png\";","export default __webpack_public_path__ + \"static/media/information--tourist-attraction--g1.9aad0dc2.png\";","export default __webpack_public_path__ + \"static/media/information--traffic-merges-left--g1.3bc6a9de.png\";","export default __webpack_public_path__ + \"static/media/information--traffic-merges-right--g1.53636e9b.png\";","export default __webpack_public_path__ + \"static/media/information--trail-crossing--g1.65ee67cc.png\";","export default __webpack_public_path__ + \"static/media/information--trail-crossing--g2.9e0a8068.png\";","export default __webpack_public_path__ + \"static/media/information--trail-crossing--g3.9ee9d069.png\";","export default __webpack_public_path__ + \"static/media/information--trailer-camping--g1.742fd848.png\";","export default __webpack_public_path__ + \"static/media/information--train-or-light-rail-station--g1.1137babb.png\";","export default __webpack_public_path__ + \"static/media/information--tram-bus-stop--g1.840fc7f4.png\";","export default __webpack_public_path__ + \"static/media/information--tram-bus-stop--g2.742fb913.png\";","export default __webpack_public_path__ + \"static/media/information--trams-crossing--g1.a0f36a2d.png\";","export default __webpack_public_path__ + \"static/media/information--truck-lane-left--g1.c1c84eec.png\";","export default __webpack_public_path__ + \"static/media/information--truck-parking--g1.344e6e89.png\";","export default __webpack_public_path__ + \"static/media/information--truck-trailer-lane-right--g1.78d4967c.png\";","export default __webpack_public_path__ + \"static/media/information--truck-trailer-lane-straight--g1.5347b556.png\";","export default __webpack_public_path__ + \"static/media/information--trucks-both-ways--g1.e3ecbd84.png\";","export default __webpack_public_path__ + \"static/media/information--trucks-only--g1.979028f2.png\";","export default __webpack_public_path__ + \"static/media/information--tsunami-evacuation_route--g1.7ae34865.png\";","export default __webpack_public_path__ + \"static/media/information--tunnel--g1.03be4883.png\";","export default __webpack_public_path__ + \"static/media/information--tunnel--g2.7b559e17.png\";","export default __webpack_public_path__ + \"static/media/information--tunnel--g3.d2ceeebb.png\";","export default __webpack_public_path__ + \"static/media/information--tunnel-ahead--g1.546aa975.png\";","export default __webpack_public_path__ + \"static/media/information--turn-left--g1.f8929d0b.png\";","export default __webpack_public_path__ + \"static/media/information--turn-left-ahead--g1.1f03050a.png\";","export default __webpack_public_path__ + \"static/media/information--turn-right--g1.eb673195.png\";","export default __webpack_public_path__ + \"static/media/information--turn-right-ahead--g1.35a96c2a.png\";","export default __webpack_public_path__ + \"static/media/information--urban-area--g1.6b606baf.png\";","export default __webpack_public_path__ + \"static/media/information--vehicles-on-rails--g1.4a371ce8.png\";","export default __webpack_public_path__ + \"static/media/information--water-protection-zone--g1.44b0f53a.png\";","export default __webpack_public_path__ + \"static/media/information--weight-and-height-limit--g1.bc56d483.png\";","export default __webpack_public_path__ + \"static/media/information--weight-limit--g1.20f54728.png\";","export default __webpack_public_path__ + \"static/media/information--wireless-internet--g1.75122a71.png\";","export default __webpack_public_path__ + \"static/media/regulatory--advisory-maximum-speed-limit--g1.86b85613.png\";","export default __webpack_public_path__ + \"static/media/regulatory--all-directions-permitted--g1.e567ddaa.png\";","export default __webpack_public_path__ + \"static/media/regulatory--all-way--g1.1a3b2b2a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--atvs-permitted--g1.d5fe6ec3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--axle-limit--g1.8eb43884.png\";","export default __webpack_public_path__ + \"static/media/regulatory--axle-limit--g2.3974d220.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycle-lane-left--g1.4ca4b400.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycle-parking--g1.16ba1f72.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-and-buses-only--g1.148faf66.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-only--g1.440e2032.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-only--g2.1e88f01e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-only--g3.bcfb72cc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-only--g4.0de1b0cb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-push-button--g1.1364f84e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-push-button--g2.e86fdf7f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-stop-on-red--g1.1cda5add.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-wrong-way--g1.135ae71c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bicycles-yield-or-use-signal--g1.1f65e157.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bike-route--g1.10d044ee.png\";","export default __webpack_public_path__ + \"static/media/regulatory--building-direction--g1.fc70d3c5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--bus-priority-lane--g1.2ae10a51.png\";","export default __webpack_public_path__ + \"static/media/regulatory--buses-and-taxi-only--g1.b3d80414.png\";","export default __webpack_public_path__ + \"static/media/regulatory--buses-only--g1.5305590b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--buses-only--g2.38b5f21e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--circular-intersection--g1.e8f98101.png\";","export default __webpack_public_path__ + \"static/media/regulatory--circular-intersection--g2.364f2ae2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--circular-intersection--g3.08fdea2e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--circular-intersection--g4.daf2c245.png\";","export default __webpack_public_path__ + \"static/media/regulatory--cross-only-on-green--g1.1f626d4e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--cross-only-on-pedestrian-signal--g1.a36a6a28.png\";","export default __webpack_public_path__ + \"static/media/regulatory--crosswalk-stop-on-red--g1.39942771.png\";","export default __webpack_public_path__ + \"static/media/regulatory--cycling-restriction--g1.1b19c2a9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--cyclists-dismount-and-walk--g1.85523214.png\";","export default __webpack_public_path__ + \"static/media/regulatory--detour-left--g1.65da6dd7.png\";","export default __webpack_public_path__ + \"static/media/regulatory--detour-right--g1.ad60dd21.png\";","export default __webpack_public_path__ + \"static/media/regulatory--divided-highway-crossing--g1.f45cc71a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--divided-highway-ends--g1.c6006e84.png\";","export default __webpack_public_path__ + \"static/media/regulatory--divided-highway-starts--g1.846d4a16.png\";","export default __webpack_public_path__ + \"static/media/regulatory--do-not-block-intersection--g1.18bccc47.png\";","export default __webpack_public_path__ + \"static/media/regulatory--do-not-pass--g1.7f484967.png\";","export default __webpack_public_path__ + \"static/media/regulatory--do-not-stop-on-tracks--g1.f252110f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-all-directions-on-left--g1.39024df2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-all-directions-on-right--g1.25fcfc3e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-bicyclists-and-pedestrians--g1.b3dad17b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-go-left-or-right--g1.20dace34.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-go-straight-on-left--g1.644f5631.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-go-straight-on-right--g1.a4728fe2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-turn-left--g1.27ff5c95.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-turn-left-no-u-turn--g1.e566a2e4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-turn-left-or-straight--g1.042176f8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-lanes-turn-right-or-straight--g1.bb64e50c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-bicycles-and-pedestrians--g1.02ec2d5e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-bicycles-and-pedestrians--g2.5c75e267.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-bicycles-and-pedestrians--g3.4194fc44.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-equestrians-and-pedestrians--g1.5c1b32ad.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-equestrians-and-pedestrians-bicycles--g1.2c4013b0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-pedestrians-and-bicycles--g1.4dad084e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-pedestrians-and-bicycles--g2.5ffa4776.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-pedestrians-and-equestrians--g1.02f7d7a1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-path-pedestrians-bicycles-and-equestrians--g1.44369e6c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-speed-limits--g1.6752afbb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--dual-speed-limits--g2.4ac2d6f3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-bicycles-only--g1.afcf1e7b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-bicycles-only--g2.097b77a9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-bus-and-taxi-only--g1.95ed8ca1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-buses-only--g1.0201ae54.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-buses-only--g2.5f50ea96.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-cycling-restriction--g1.7b7df3dd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-dual-path-bicycles-and-pedestrians--g1.26b235af.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-dual-path-pedestrians-and-bicycles--g1.23e796cf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-equestrians-only--g1.0a1542f3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-low-beam-headlights--g1.91c69fc1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-10--g1.5ac21e5b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-10--g2.8db154ac.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-20--g1.7024c379.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-20--g2.ff6c8dc5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-25--g1.75e6cd18.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-25--g2.3fc08b6f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-30--g1.eb45f997.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-30--g2.bb4809fd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-35--g1.5f8ce558.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-35--g2.8d261d69.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-40--g1.85c54762.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-40--g2.c378a358.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-50--g1.8a58a37b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-50--g2.32f875a5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-60--g1.2f34a92d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-60--g2.0632d23d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-65--g1.b14098fd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-65--g2.a5254cbb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-70--g1.9fb8a3e9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-70--g2.a93c14f1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-75--g1.9d1b9782.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-75--g2.a0124c7a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-80--g1.8e331512.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-80--g2.e45f6301.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-90--g1.f7dbc484.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-90--g2.8c5d1def.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-100--g1.10cc7dd9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-100--g2.d22c2e70.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-110--g1.7c47334c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-110--g2.3a94b5b1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-120--g1.47e0a468.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-120--g2.ba84c756.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-130--g1.3edebaf2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit-130--g2.28b38021.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-maximum-speed-limit--g1.008d8f7c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-mopeds-and-bicycles-only--g1.b669ee49.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-heavy-goods-vehicles--g1.11347c2b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-horn--g1.38488514.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking--g1.f711db78.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking--g2.da883c93.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking--g3.66135c03.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking--g4.11329ed0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking--g5.4aa03694.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g1.ff79e44a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g2.16e2a814.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-overtaking-by-motorcycles--g1.a23aae0c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-parking--g1.c771dc80.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-parking--g2.8c4dba58.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-no-parking-or-stopping--g1.9448279b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-one-way-straight--g1.2ed363d3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-parking-zone--g1.cfb44d95.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-parking-zone--g2.96af1a66.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-pedestrians-only--g1.3091680c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-pedestrians-only--g2.55157960.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-pedestrians-only--g3.afe96de1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-pedestrians-only--g4.74b84e48.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-priority-road--g1.12c706be.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-prohibition--g1.24827b34.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-school-zone--g1.f865537a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-shared-path-bicycles-and-pedestrians--g1.f9807b65.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-shared-path-pedestrians-and-bicycles--g1.04370a0f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-snow-chains--g1.5a7931f2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-snow-chains--g2.7382850a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-snowmobiles-only--g1.d682bc63.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-speed-limit-zone--g1.15e8b883.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-speed-limit-zone--g2.300add15.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-speed-limit-zone--g3.a50f1e4d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-tractors-only--g1.bbb8849f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-trams-and-buses-only--g1.25dd9871.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-trams-only--g1.85ec27f9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-trucks-and-buses-only--g1.8a6ab26d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-trucks-only--g1.3dcb28f4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--end-of-trucks-only--g2.4e55b939.png\";","export default __webpack_public_path__ + \"static/media/regulatory--equestrians-only--g1.d64c6020.png\";","export default __webpack_public_path__ + \"static/media/regulatory--except-railroad-crossing--g1.eacd41fa.png\";","export default __webpack_public_path__ + \"static/media/regulatory--fine-for-littering--g1.dfa21d74.png\";","export default __webpack_public_path__ + \"static/media/regulatory--give-way-to-bicycles--g1.c339dedb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--give-way-to-oncoming-traffic--g1.d53ac85f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--give-way-to-oncoming-traffic--g2.51aed85b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-left-bicycles--g1.912457bf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-right-bicycles--g1.51e745f5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight--g1.ed3c15a6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight--g3.478e2d96.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-bicycles--g1.d41deae5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-or-turn-left--g1.78963e27.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-or-turn-left--g2.ad96042c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-or-turn-left--g3.5536a26a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-or-turn-right--g1.f11738ef.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-or-turn-right--g2.75a12caf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--go-straight-or-turn-right--g3.dcac6907.png\";","export default __webpack_public_path__ + \"static/media/regulatory--heavy-goods-vehicles-permitted--g1.9cdb128c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--height-limit--g1.98af1a7f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--high-beam-headlights--g1.e09c5b20.png\";","export default __webpack_public_path__ + \"static/media/regulatory--horn--g1.77ed51fc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--in-street-pedestrian-crossing--g1.e30c31dd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g1.679b6bd3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g2.c7dbfe8e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g3.8d435d1e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g4.0a18f6ba.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g5.83797d4a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g6.7c4481c4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-left--g7.8a94453c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g1.0a5be37f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g2.26ef1c48.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g3.0bf791e6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g4.cac2f808.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g5.f2e202d8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g6.3f2cfd3a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g7.102f84fe.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g8.2f374fc8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--keep-right--g9.19cca104.png\";","export default __webpack_public_path__ + \"static/media/regulatory--lane-control--g1.ebf113b6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--left-turn-yield-on-green--g1.103fabdc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--length-limit--g1.e26aac53.png\";","export default __webpack_public_path__ + \"static/media/regulatory--length-limit--g2.8ef7d18d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--light-rail-divided-highway--g1.db3927c2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--light-rail-do-not-pass--g1.a6efedce.png\";","export default __webpack_public_path__ + \"static/media/regulatory--light-rail-only--g1.254cad9a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--look--g1.25116d7f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--low-beam-headlights--g1.f0dfd718.png\";","export default __webpack_public_path__ + \"static/media/regulatory--low-beam-headlights--g2.d3ac6fa0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--low-beam-headlights--g3.27cdd23a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--low-speed-vehicle-permitted--g1.30c92b2d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-5--g1.12cfb1dc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-5--g3.206e7744.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-10--g1.f5f022da.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-10--g3.483cdc98.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-15--g1.c0560e73.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-15--g3.c766b7e0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-20--g1.3fb8b849.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-20--g3.f2750244.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-25--g1.00b372a9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-25--g2.3651694f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-30--g1.957a1971.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-30--g3.f035f7be.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-35--g1.176ca1fe.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-35--g2.bb66847f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-40--g1.44aeea27.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-40--g3.96779eaf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-45--g1.908b0551.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-45--g3.aafdb64d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-50--g1.265cb52e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-50--g3.f7bdf367.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-55--g2.112a3663.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-60--g1.ea23c09b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-60--g3.a3ea0058.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-65--g1.3903f621.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-65--g2.bb77e2c1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-70--g1.1896271e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-70--g3.b28c86fe.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-75--g2.1b34ed25.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-80--g1.a5644650.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-80--g3.026ebd10.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-85--g2.8c86c640.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-90--g1.bd9729a9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-90--g3.0b6fd891.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-100--g1.eeb7acc1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-100--g3.cdf80f0f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-110--g1.09c32e32.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-110--g3.bad7b480.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-120--g1.343b1010.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-120--g3.546873db.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-130--g1.7ffeb59e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-130--g3.bf38e05c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-5--g2.ebce1f01.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-5--g3.3af8efb4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-10--g1.8a5c0115.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-10--g2.ad5f7d90.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-10--g3.a82bcf90.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-15--g2.aca06df6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-15--g3.53994d0a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-20--g1.af9e4293.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-20--g2.9e88edec.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-20--g3.11d7d1c0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-25--g1.cc37b6a2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-25--g2.9a69ae6f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-25--g3.f1b81b62.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-30--g1.bba5d38c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-30--g2.24d963f4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-30--g3.62f401a5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-35--g1.45228792.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-35--g2.95331a23.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-35--g3.ad302825.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-40--g1.580d8dba.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-40--g2.ef8144ed.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-40--g3.40ecba48.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-45--g2.f41b3db9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-45--g3.62b6fde1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-50--g1.4657ea06.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-50--g2.b09b7508.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-50--g3.0aa73207.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-55--g2.7d194fac.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-55--g3.ed0a2e22.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-60--g1.58e5908a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-60--g2.aed4f160.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-60--g3.ea9c8fdb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-65--g2.54e6c1f0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-65--g3.4792115d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-70--g1.aa082679.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-70--g2.84465687.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-70--g3.ff4bfb81.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-75--g1.96dc879a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-75--g2.62c37706.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-75--g3.77267ab5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-80--g1.49dbc461.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-80--g2.7377246c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-80--g3.b35b5a61.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-85--g2.6c4b570d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-85--g3.d67b71de.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-90--g1.be1d5ec8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-100--g1.208820d6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-110--g1.2a1a5bb0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-120--g1.f5162198.png\";","export default __webpack_public_path__ + \"static/media/regulatory--maximum-speed-limit-led-130--g1.ab836ce5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--minimum-safe-distance--g1.e2f1a969.png\";","export default __webpack_public_path__ + \"static/media/regulatory--minimum-safe-distance--g2.f81b7cf1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--mopeds-and-bicycles-only--g1.6a32c318.png\";","export default __webpack_public_path__ + \"static/media/regulatory--motorcycles-and-bicycles-only--g1.5be11f05.png\";","export default __webpack_public_path__ + \"static/media/regulatory--motorcycles-only--g1.3599617f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--motorcycles-only--g2.1e5763c9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-5--g1.2d471622.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-10--g1.e49f6633.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-15--g1.74d7f0eb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-20--g1.e923f062.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-25--g1.1eee3953.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-30--g1.de686fba.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-35--g1.3a039535.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-40--g1.ed13d478.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-45--g1.13e9c312.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-50--g1.f36e3f30.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-55--g1.eda1a245.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-60--g1.d401082f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-65--g1.b036b665.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-70--g1.5dbee8eb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-75--g1.02809bff.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-80--g1.60f65bd6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--night-speed-limit-85--g1.bfca22ba.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-abnormal-vehicles--g1.9a1ba76a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-atvs--g1.351b1213.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles--g1.fbfdb4d6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles--g2.10ba3fba.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles--g3.aef27aee.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles-carts-or-hand-carts--g1.0980edb5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles-mopeds-or-motorcycles--g1.6deac529.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles-mopeds-or-motorcycles--g2.47379579.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles-or-hand-carts--g1.b307cb32.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles-or-motorcycles--g1.115b2e72.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-bicycles-tractors-or-carts--g1.c9248372.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-buses--g1.67236178.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-buses--g2.579a2458.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-buses--g3.6b590d19.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-caravan-trailers--g1.f42a260f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-caravans--g1.941fa0cc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-caravans-or-caravan-trailers--g1.ee733d20.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-cargo-loading--g1.1b0eeb2b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-carts--g1.928af1c6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-carts--g2.b6f19e6f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-carts--g3.74460970.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-carts-or-tractors--g1.9d3bbf40.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-construction-vehicles--g1.28ffa65d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-entry--g1.c657fa8f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-equestrians--g1.81627a3a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-go-straight-or-turn-left--g1.ba71ea9f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-go-straight-or-turn-right--g1.bf8a6fa3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-good-trailers--g2.bad20402.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-goods-vehicle-trailers--g1.764e3efc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-hand-carts--g1.7e3449ab.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-hand-carts--g2.19c3e969.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-hand-carts-or-bicycles--g1.0279d73d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-hawkers--g1.1e14d7e1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles--g1.8a560f33.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles--g2.9fff7565.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles--g3.91da44ae.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles--g4.216491f1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles--g5.959f1c6d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g1.37078248.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g2.2e3a18ee.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles-or-buses--g1.05787c73.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles-or-tractors--g1.a3d74207.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-heavy-goods-vehicles-or-trailers--g1.0e4821b9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-horizontal-turn--g1.ab7eda4b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-horn--g1.2695a31e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-horn--g2.5841efbd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-lane-change-to-left--g1.c3b5e313.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-lane-change-to-right--g1.65211254.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-learner-drivers--g1.3ebd3c5a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-left-or-u-turn--g1.b309afb9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-left-turn--g1.b330753f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-left-turn--g2.3a06039e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-left-turn--g3.34218609.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-left-turn--g4.f2416352.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-left-turn--g5.c53c6486.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-low-speed-vehicles--g1.4b08326a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-mopeds-or-bicycles--g1.72ce756c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicle-trailers--g1.db1f891e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles--g1.2bd757f6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles--g3.b3120ac6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles--g4.5e81bd00.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles--g5.d88792f9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles--g6.44fb91e7.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles--g7.2c8ec64f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles-except-motorcycles--g1.5af55863.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles-except-motorcycles--g2.7d175930.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles-except-motorcycles--g3.a4448c41.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles-or-bicycles--g1.317ebe25.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles-or-buses--g1.8e58f8bf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motor-vehicles-or-carts--g1.39349e1f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motorcycles--g1.f9dc81e3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-motorcycles--g2.65414d33.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking--g1.d876c125.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking--g2.2b83574c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking--g4.22b05cd4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking--g5.6b8e21fc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking--g6.dc77c0cd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking--g7.30b8ee6b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking-atvs--g1.6dd58589.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-overtaking-by-heavy-goods-vehicles--g1.f97c589c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g1.4ca5a89f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g2.a3c63e81.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g3.ced5e03c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g4.4c779b9c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g5.48af12a8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g6.6db7b740.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g7.da720b8d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g8.8a640aed.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking--g9.b969233b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-bicycles-or-motorcycles--g1.932ed75c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-bus-stop--g1.d790c322.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-or-no-stopping--g1.32cc0e7c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-or-no-stopping--g2.cbe40936.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-or-no-stopping--g3.f817e11a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-or-no-stopping--g4.8a3143db.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-parking-or-no-stopping--g5.c5a471d8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-passenger-loading--g1.9272ff3b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians--g1.654534fc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians--g2.c1cbab61.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians--g3.db9ef7ad.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians--g4.7f4a3d27.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians--g5.02c0c663.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians--g6.4d3714e7.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians-bicycles-animals-or-hand-carts--g1.e4fc9208.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians-or-bicycles--g1.4a8441a7.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians-or-bicycles--g2.0366930c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-pedestrians-or-bicycles--g3.426675bf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-rickshaws--g1.fc782f2c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-rickshaws--g2.61c13947.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-rickshaws--g3.ac5bec9d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-right-turn--g1.6e467745.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-right-turn--g2.97edc91d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-right-turn--g3.63dc1b44.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-right-turn-on-red--g1.f6ea7f5c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-skiing--g1.655b7641.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-snowmobiles--g1.cfa8001f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-snowmobiles--g2.2e3d9be1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-snowmobiles-or-atvs--g1.1bf91012.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping--g1.4fd0a542.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping--g2.22eabfcc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping--g3.60647b5f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping--g5.9c7f0f1e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping--g6.a5c23b68.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping--g7.349246a0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-stopping-on-pavement--g1.4ad4966b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-straight-through--g1.6fe4bf6d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-straight-through--g2.9e890383.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-studded-snow-chains--g1.788d151e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-through-trucks--g1.bad0c928.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-tour-buses--g1.fa7322d5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-tractors--g1.a2437580.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-tractors-mopeds-or-bicycles--g1.102563a8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-tractors-or-carts--g1.3829cc65.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-trailers--g1.309aba75.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-tricycles--g1.fa034d03.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-tricycles-or-hand-carts--g1.eafc4e68.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-turn-on-red--g1.d126fe1a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-turn-on-red--g2.b82499bd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-turn-on-red--g3.9040df5f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-turns--g1.32fc69c3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-turns--g2.0414b2fe.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-two-stage-right-turn-for-mopeds--g1.6b816a0e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-u-turn--g1.18b5ecf1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-u-turn--g2.7911ab30.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-u-turn--g3.d7392ba4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-dangerous-goods--g1.794908c9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-dangerous-goods--g2.b8c733f6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-dangerous-goods--g3.eed2c264.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-dangerous-goods--g4.5511e61f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-dangerous-water-pollutants--g1.988e8514.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-dangerous-water-pollutants--g2.93eebcbf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-explosives--g1.0565ddd2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--no-vehicles-carrying-explosives-or-dangerous-water-pollutants--g1.7a3c82c6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-left--g1.b090ec6f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-left--g2.50ea813a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-left--g3.0113405a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-right--g1.791c0a85.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-right--g2.8585b78c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-right--g3.9cdca710.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-straight--g1.47ea933f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--one-way-straight--g3.01f68d4b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--parking-fee-station--g1.70710155.png\";","export default __webpack_public_path__ + \"static/media/regulatory--parking-restrictions--g1.2b92b8a8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--parking-restrictions--g2.231db037.png\";","export default __webpack_public_path__ + \"static/media/regulatory--parking-restrictions--g3.4e6ef760.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pass-on-either-side--g1.ff7956d3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pass-on-either-side--g2.9dec1fee.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pass-on-either-side--g3.d1ffedcd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pass-with-care--g1.75f3b466.png\";","export default __webpack_public_path__ + \"static/media/regulatory--passing-lane-ahead--g1.f3e273fd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-bicycles-permitted--g1.3d105bf0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-keep-left--g1.674c2d80.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-only--g1.1fc71024.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-only--g2.4bfe3f3f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-only--g3.76d6977a.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-priority-zone--g1.a5b6727e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-push-button--g1.4e8319dc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--pedestrians-push-button--g2.fcfd976d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--priority-over-oncoming-vehicles--g1.db6faf10.png\";","export default __webpack_public_path__ + \"static/media/regulatory--priority-over-oncoming-vehicles--g2.7de31d11.png\";","export default __webpack_public_path__ + \"static/media/regulatory--priority-road--g1.a9c3ba8b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--priority-road--g2.922fe884.png\";","export default __webpack_public_path__ + \"static/media/regulatory--radar-enforced--g1.d785a081.png\";","export default __webpack_public_path__ + \"static/media/regulatory--reserved-parking--g1.3ad03559.png\";","export default __webpack_public_path__ + \"static/media/regulatory--reversible-lanes--g1.9fb06219.png\";","export default __webpack_public_path__ + \"static/media/regulatory--reversible-lanes--g2.969c0d44.png\";","export default __webpack_public_path__ + \"static/media/regulatory--road-closed--g1.9e903e6d.png\";","export default __webpack_public_path__ + \"static/media/regulatory--road-closed--g2.dda11416.png\";","export default __webpack_public_path__ + \"static/media/regulatory--road-closed-to-vehicles--g1.dca51279.png\";","export default __webpack_public_path__ + \"static/media/regulatory--road-closed-to-vehicles--g3.b3970891.png\";","export default __webpack_public_path__ + \"static/media/regulatory--roundabout--g1.8433aefc.png\";","export default __webpack_public_path__ + \"static/media/regulatory--roundabout--g2.50727331.png\";","export default __webpack_public_path__ + \"static/media/regulatory--roundabout--g3.2d0882dd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--shared-path-bicycles-and-pedestrians--g1.72464b6b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--shared-path-pedestrians-and-bicycles--g1.bf20db10.png\";","export default __webpack_public_path__ + \"static/media/regulatory--sidewalk-closed--g1.e4dd968e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--slanted-parking--g1.2c69ce1c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--snow-chains--g1.a656672c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--snow-chains--g2.84dc0228.png\";","export default __webpack_public_path__ + \"static/media/regulatory--snow-chains--g3.a156dd58.png\";","export default __webpack_public_path__ + \"static/media/regulatory--snowmobiles-only--g1.1dde78d9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--snowmobiles-permitted--g1.27015a7f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--speed-limit-zone--g1.981aeede.png\";","export default __webpack_public_path__ + \"static/media/regulatory--speeding-fines-increased--g1.31b9fc1b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--state-route--g1.721042d7.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stay-in-lane--g1.56d686b0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g1.7d97baab.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g2.483334d1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g3.4d1e72e1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g4.ee770dce.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g5.2a819d8f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g6.de739f11.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g7.9490caa4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g8.722f4b38.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g9.06825e07.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop--g10.505ed820.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop-here-on-red-or-flashing-light--g1.2e18bf3f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop-here-on-red-or-flashing-light--g2.1407c908.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop-signals--g1.9b8c0d01.png\";","export default __webpack_public_path__ + \"static/media/regulatory--stop-signals--g2.7cea9e75.png\";","export default __webpack_public_path__ + \"static/media/regulatory--tanks-only--g1.46e2c223.png\";","export default __webpack_public_path__ + \"static/media/regulatory--taxi-only--g1.77097a52.png\";","export default __webpack_public_path__ + \"static/media/regulatory--text--g1.14bfe577.png\";","export default __webpack_public_path__ + \"static/media/regulatory--text--g2.12b5de42.png\";","export default __webpack_public_path__ + \"static/media/regulatory--toll-pass-only--g1.971da401.png\";","export default __webpack_public_path__ + \"static/media/regulatory--tractors-only--g1.ea2f343e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--traffic-signal-photo-enforced--g1.f6a31551.png\";","export default __webpack_public_path__ + \"static/media/regulatory--trams-and-buses-only--g1.9d082cd5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--trams-only--g1.5a5684c6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--triple-lanes--g1.5f11c2cf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--triple-lanes-go-straight-center-lane--g1.e11d6237.png\";","export default __webpack_public_path__ + \"static/media/regulatory--triple-lanes-turn-left-center-lane--g1.e4a2f108.png\";","export default __webpack_public_path__ + \"static/media/regulatory--triple-lanes-turn-right-center-lane--g1.d4df745b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-route--g1.630b0b24.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-5--g1.29df11b6.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-10--g1.e7d67cd1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-15--g1.f67bb65f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-20--g1.d81afa41.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-25--g1.96be34eb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-30--g1.9df85672.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-35--g1.9a883455.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-40--g1.9800dbf8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-45--g1.69fdca3f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-50--g1.70f43e41.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-55--g1.1656c6f2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-60--g1.d6cf88aa.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-65--g1.b46b4bbd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-70--g1.b20a87d2.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-75--g1.d658980b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-80--g1.c243996e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--truck-speed-limit-85--g1.6125756c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--trucks-and-buses-only--g1.a55e77aa.png\";","export default __webpack_public_path__ + \"static/media/regulatory--trucks-on-right--g1.5ad11e57.png\";","export default __webpack_public_path__ + \"static/media/regulatory--trucks-only--g1.2caa4b16.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left--g1.12ef941b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left--g2.01af6a90.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left--g3.7a1a0373.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left-ahead--g1.35b3766c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left-ahead--g2.fd4eb44f.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left-or-right--g1.89ad6968.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left-or-right--g2.6eca1c7b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left-or-right--g3.0bee4d0c.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-left-or-u-turn--g1.8f5028c9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-right--g1.8b3bf63e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-right--g2.bfc39dfd.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-right--g3.1d726512.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-right-ahead--g1.76f304e8.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turn-right-ahead--g2.7774ded9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--turning-vehicles-yield-to-pedestrians--g1.99692a47.png\";","export default __webpack_public_path__ + \"static/media/regulatory--two-stage-right-turn-for-mopeds--g1.8d55bffb.png\";","export default __webpack_public_path__ + \"static/media/regulatory--two-way--g1.b64bf0c5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--u-turn--g1.c3a04a95.png\";","export default __webpack_public_path__ + \"static/media/regulatory--u-turn--g2.4e33c845.png\";","export default __webpack_public_path__ + \"static/media/regulatory--u-turn--g3.9d07cd2e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--use-crosswalk--g1.4941d3c3.png\";","export default __webpack_public_path__ + \"static/media/regulatory--vehicles-carrying-dangerous-goods-only--g1.3a569021.png\";","export default __webpack_public_path__ + \"static/media/regulatory--vehicles-carrying-dangerous-goods-permitted--g1.41785cc4.png\";","export default __webpack_public_path__ + \"static/media/regulatory--vehicles-carrying-explosives-only--g1.1ecbe4c0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--vehicles-carrying-hazardous-goods-permitted--g1.e45be8b9.png\";","export default __webpack_public_path__ + \"static/media/regulatory--vehicles-only--g1.de6ad106.png\";","export default __webpack_public_path__ + \"static/media/regulatory--wear-seat-belt--g1.f47a44cf.png\";","export default __webpack_public_path__ + \"static/media/regulatory--wear-seat-belt--g2.f386bc69.png\";","export default __webpack_public_path__ + \"static/media/regulatory--wear-seat-belt--g3.4cdb1888.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g1.817038a1.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g2.e1500a68.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g3.19d1b90e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g4.0d1fcb42.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g5.71d3ad85.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g6.c9ce9e57.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit--g7.11b45bd0.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit-per-axle--g1.d05b072b.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit-per-tandem-axle--g1.e1fb3ce7.png\";","export default __webpack_public_path__ + \"static/media/regulatory--weight-limit-with-trucks--g1.c0fc507e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--width-limit--g1.e94fb0a5.png\";","export default __webpack_public_path__ + \"static/media/regulatory--wrong-way--g1.4c1aec61.png\";","export default __webpack_public_path__ + \"static/media/regulatory--yield--g1.00724e2e.png\";","export default __webpack_public_path__ + \"static/media/regulatory--yield-or-stop-for-pedestrians--g1.bf8555de.png\";","export default __webpack_public_path__ + \"static/media/regulatory--your-speed--g1.354c97cb.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g1.a6065411.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g2.20400c8d.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g3.8f08b131.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g4.e39b418a.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g5.78034bb3.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g6.271d6630.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g7.7f6c0b7f.png\";","export default __webpack_public_path__ + \"static/media/warning--accident-area--g8.a06f3807.png\";","export default __webpack_public_path__ + \"static/media/warning--added-lane-from-entering-roadway--g1.bbd50002.png\";","export default __webpack_public_path__ + \"static/media/warning--added-lane-from-entering-roadway--g2.6c2e69cb.png\";","export default __webpack_public_path__ + \"static/media/warning--added-lane-left--g1.a8c7833e.png\";","export default __webpack_public_path__ + \"static/media/warning--added-lane-right--g1.d5032345.png\";","export default __webpack_public_path__ + \"static/media/warning--animal-drawn-vehicles--g1.38f47feb.png\";","export default __webpack_public_path__ + \"static/media/warning--arch-bridge--g1.5cc463ff.png\";","export default __webpack_public_path__ + \"static/media/warning--atv-and-snowmobiles--g1.6e6cfa37.png\";","export default __webpack_public_path__ + \"static/media/warning--atv-crossing--g1.627f932d.png\";","export default __webpack_public_path__ + \"static/media/warning--atv-crossing--g2.4048703b.png\";","export default __webpack_public_path__ + \"static/media/warning--axle-restriction--g1.37ac1b3c.png\";","export default __webpack_public_path__ + \"static/media/warning--bear-crossing--g1.5e1d24c8.png\";","export default __webpack_public_path__ + \"static/media/warning--bear-crossing--g2.cddc2568.png\";","export default __webpack_public_path__ + \"static/media/warning--bicycles-and-others--g1.64fe6c90.png\";","export default __webpack_public_path__ + \"static/media/warning--bicycles-caution-on-rail-tracks--g1.24127b37.png\";","export default __webpack_public_path__ + \"static/media/warning--bicycles-crossing--g1.742a95b5.png\";","export default __webpack_public_path__ + \"static/media/warning--bicycles-crossing--g2.aef0fc8a.png\";","export default __webpack_public_path__ + \"static/media/warning--bicycles-crossing--g3.6f7cbdff.png\";","export default __webpack_public_path__ + \"static/media/warning--bicycles-crossing--g4.bc459af3.png\";","export default __webpack_public_path__ + \"static/media/warning--bollard--g1.92dd9345.png\";","export default __webpack_public_path__ + \"static/media/warning--bridge--g1.5beed47f.png\";","export default __webpack_public_path__ + \"static/media/warning--bridge--g2.be0cc144.png\";","export default __webpack_public_path__ + \"static/media/warning--bus-stop-ahead--g1.d2042d63.png\";","export default __webpack_public_path__ + \"static/media/warning--bus-stop-ahead--g2.7fa78816.png\";","export default __webpack_public_path__ + \"static/media/warning--bus-stop-ahead--g3.0a2abcae.png\";","export default __webpack_public_path__ + \"static/media/warning--camel-crossing--g1.0fc63ebb.png\";","export default __webpack_public_path__ + \"static/media/warning--camel-crossing--g2.fe1abca3.png\";","export default __webpack_public_path__ + \"static/media/warning--camera--g1.97e5cab0.png\";","export default __webpack_public_path__ + \"static/media/warning--camera--g2.bf3bf685.png\";","export default __webpack_public_path__ + \"static/media/warning--carts--g1.2088f796.png\";","export default __webpack_public_path__ + \"static/media/warning--carts--g2.0188153d.png\";","export default __webpack_public_path__ + \"static/media/warning--checkpoint--g1.ee5447d8.png\";","export default __webpack_public_path__ + \"static/media/warning--children--g1.be722cbc.png\";","export default __webpack_public_path__ + \"static/media/warning--children--g2.802736a3.png\";","export default __webpack_public_path__ + \"static/media/warning--children--g3.7d28f751.png\";","export default __webpack_public_path__ + \"static/media/warning--children--g4.1e204dc8.png\";","export default __webpack_public_path__ + \"static/media/warning--children--g6.52ca9670.png\";","export default __webpack_public_path__ + \"static/media/warning--cliff--g1.a5923913.png\";","export default __webpack_public_path__ + \"static/media/warning--cliff--g2.b11bf115.png\";","export default __webpack_public_path__ + \"static/media/warning--closed-lane-in-triple-lanes--g1.5e11cdf9.png\";","export default __webpack_public_path__ + \"static/media/warning--closed-lane-in-triple-lanes--g2.478e5f17.png\";","export default __webpack_public_path__ + \"static/media/warning--construction-ahead--g1.c57e1e5e.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads--g1.14d61769.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads--g2.d93cf962.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads--g3.522ca193.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads--g4.1280a5a4.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads--g5.0af73743.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads--g6.50b62775.png\";","export default __webpack_public_path__ + \"static/media/warning--crossroads-with-priority-to-the-right--g1.7597a71a.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-left--g1.fc958342.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-left--g2.1b916c62.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-left--g3.a2b64322.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-left-with-junction--g1.0bd6a7a9.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-out-intersection-left--g1.e1afa97c.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-out-intersection-right--g1.b5a17894.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-right--g1.e03eb082.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-right--g2.b7f5e2a8.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-right--g3.9f2c56e1.png\";","export default __webpack_public_path__ + \"static/media/warning--curve-right-with-junction--g1.a3d85594.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-left--g1.4728c562.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-left--g2.c8bf2f3a.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-left--g4.69cf0606.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-right--g1.ab4c438d.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-right--g2.040eb808.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-right--g3.74a9268a.png\";","export default __webpack_public_path__ + \"static/media/warning--dangerous-crosswinds-right--g4.140e8377.png\";","export default __webpack_public_path__ + \"static/media/warning--dead-end--g1.822dc654.png\";","export default __webpack_public_path__ + \"static/media/warning--dead-end--g2.c8837f3e.png\";","export default __webpack_public_path__ + \"static/media/warning--dead-end--g3.b4178c04.png\";","export default __webpack_public_path__ + \"static/media/warning--dead-end-go-left--g1.e34e1902.png\";","export default __webpack_public_path__ + \"static/media/warning--dead-end-go-right--g1.b71f819e.png\";","export default __webpack_public_path__ + \"static/media/warning--descent-or-climbing-lanes-in-triple-lanes--g1.f42d15ba.png\";","export default __webpack_public_path__ + \"static/media/warning--detour-ahead--g1.62e99e19.png\";","export default __webpack_public_path__ + \"static/media/warning--detour-or-construction-ahead--g1.0dad4882.png\";","export default __webpack_public_path__ + \"static/media/warning--dip--g1.066fd9ff.png\";","export default __webpack_public_path__ + \"static/media/warning--dip--g2.149643b1.png\";","export default __webpack_public_path__ + \"static/media/warning--disabled-persons-crossing--g1.501e3c12.png\";","export default __webpack_public_path__ + \"static/media/warning--disabled-persons-crossing--g2.1097238b.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g1.4e234f74.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g2.c8b40ab4.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g3.3669f7f2.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g4.88ebcd8f.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g5.f5e120c6.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g6.dea45011.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g7.0a7f27b4.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g8.c97f56db.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway--g9.27d2fae7.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-ends--g1.236372f1.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-ends--g2.d64d1f97.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-ends--g3.6ae2c6c2.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-ends--g4.3c3eab12.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-on-left--g1.b83e1490.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-on-left--g2.a464ead0.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-on-right--g1.38f23cbf.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-on-right--g2.67b00901.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-to-left--g1.789096ef.png\";","export default __webpack_public_path__ + \"static/media/warning--divided-highway-to-right--g1.b48c54ce.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g1.b5ee6b47.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g2.1c50b229.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g3.ff1fdd4d.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g4.b8240120.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g5.59bfd681.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g6.d8382f60.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g7.e8a76726.png\";","export default __webpack_public_path__ + \"static/media/warning--domestic-animals--g8.3a90a31b.png\";","export default __webpack_public_path__ + \"static/media/warning--double-curve-first-left--g1.6eb7ea5d.png\";","export default __webpack_public_path__ + \"static/media/warning--double-curve-first-left--g2.f33a8be0.png\";","export default __webpack_public_path__ + \"static/media/warning--double-curve-first-right--g1.a3423d11.png\";","export default __webpack_public_path__ + \"static/media/warning--double-curve-first-right--g2.0c1c9b73.png\";","export default __webpack_public_path__ + \"static/media/warning--double-descent--g1.4470eef4.png\";","export default __webpack_public_path__ + \"static/media/warning--double-reverse-curve-left--g1.404c39b1.png\";","export default __webpack_public_path__ + \"static/media/warning--double-reverse-curve-left--g2.9913da77.png\";","export default __webpack_public_path__ + \"static/media/warning--double-reverse-curve-right--g1.ce6cc21b.png\";","export default __webpack_public_path__ + \"static/media/warning--double-reverse-curve-right--g2.220ae800.png\";","export default __webpack_public_path__ + \"static/media/warning--double-side-roads-left--g1.25faddb2.png\";","export default __webpack_public_path__ + \"static/media/warning--double-side-roads-left--g3.90e3a23d.png\";","export default __webpack_public_path__ + \"static/media/warning--double-side-roads-right--g1.d5e87954.png\";","export default __webpack_public_path__ + \"static/media/warning--double-side-roads-right--g3.f828d2c5.png\";","export default __webpack_public_path__ + \"static/media/warning--double-turn-first-left--g1.be7aa3be.png\";","export default __webpack_public_path__ + \"static/media/warning--double-turn-first-right--g1.98471837.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-all-directions-on-left--g1.c3148502.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-all-directions-on-right--g1.e1524300.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-go-straight-or-turn-left--g1.72412f1e.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-go-straight-or-turn-right--g1.2b80e972.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-left-turn--g1.a0868b18.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-left-turn-or-go-straight--g1.35661ca4.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-right-turn--g1.6eb106ff.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-right-turn-or-go-straight--g1.d9341e1a.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-turn-left--g1.bf236e41.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-turn-left-or-right--g1.920cce95.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-turn-left-or-right--g2.f9d846fa.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-turn-left-or-right--g3.bf437251.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-turn-left-or-right--g4.15fdd3ad.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-lanes-turn-right--g1.24e2dfad.png\";","export default __webpack_public_path__ + \"static/media/warning--dual-path-cyclists-and-pedestrians--g1.c641917c.png\";","export default __webpack_public_path__ + \"static/media/warning--electricity--g1.e43834b5.png\";","export default __webpack_public_path__ + \"static/media/warning--electricity--g2.f309d9d6.png\";","export default __webpack_public_path__ + \"static/media/warning--elephant-crossing--g1.1d0a5289.png\";","export default __webpack_public_path__ + \"static/media/warning--emergency-vehicles--g1.11cfb237.png\";","export default __webpack_public_path__ + \"static/media/warning--emu-crossing--g1.52d9cf04.png\";","export default __webpack_public_path__ + \"static/media/warning--emu-crossing--g2.fee7dc08.png\";","export default __webpack_public_path__ + \"static/media/warning--entering-roadway-merge--g1.332dc1ff.png\";","export default __webpack_public_path__ + \"static/media/warning--entering-roadway-merge--g2.86b6aca3.png\";","export default __webpack_public_path__ + \"static/media/warning--equestrians-crossing--g1.19b9300d.png\";","export default __webpack_public_path__ + \"static/media/warning--equestrians-crossing--g2.d8fe8c9d.png\";","export default __webpack_public_path__ + \"static/media/warning--expressway--g1.5cdf1e31.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-left--g1.ba33de2a.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-left--g2.3de84b6f.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-left--g3.092e6480.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-left--g4.21007872.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-right--g1.e3a61a97.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-right--g2.d134cc6d.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-right--g3.159ce905.png\";","export default __webpack_public_path__ + \"static/media/warning--falling-rocks-or-debris-right--g4.84a6e30d.png\";","export default __webpack_public_path__ + \"static/media/warning--ferry--g1.0879199d.png\";","export default __webpack_public_path__ + \"static/media/warning--flaggers-in-road--g1.46677e39.png\";","export default __webpack_public_path__ + \"static/media/warning--flaggers-in-road--g2.4b786672.png\";","export default __webpack_public_path__ + \"static/media/warning--foggy-road--g1.b2ea0888.png\";","export default __webpack_public_path__ + \"static/media/warning--foggy-road--g2.4e58a69c.png\";","export default __webpack_public_path__ + \"static/media/warning--ford--g1.a4e7c139.png\";","export default __webpack_public_path__ + \"static/media/warning--forest--g1.e558de15.png\";","export default __webpack_public_path__ + \"static/media/warning--fresh-oil--g1.2aa89129.png\";","export default __webpack_public_path__ + \"static/media/warning--frog-crossing--g1.cc552a98.png\";","export default __webpack_public_path__ + \"static/media/warning--gate--g1.ef474cd4.png\";","export default __webpack_public_path__ + \"static/media/warning--gate--g2.7393d775.png\";","export default __webpack_public_path__ + \"static/media/warning--gate-left--g1.060d16fa.png\";","export default __webpack_public_path__ + \"static/media/warning--gate-right--g1.a3c3be2f.png\";","export default __webpack_public_path__ + \"static/media/warning--go-left--g1.f419ee5e.png\";","export default __webpack_public_path__ + \"static/media/warning--go-right--g1.39eb9a50.png\";","export default __webpack_public_path__ + \"static/media/warning--golf-carts-crossing--g1.6d3a5336.png\";","export default __webpack_public_path__ + \"static/media/warning--gravel-road-surface--g1.53217d4e.png\";","export default __webpack_public_path__ + \"static/media/warning--hairpin-curve-left--g1.edb73aef.png\";","export default __webpack_public_path__ + \"static/media/warning--hairpin-curve-left--g2.afaea372.png\";","export default __webpack_public_path__ + \"static/media/warning--hairpin-curve-left--g3.6f0b4e07.png\";","export default __webpack_public_path__ + \"static/media/warning--hairpin-curve-right--g1.7379cbcd.png\";","export default __webpack_public_path__ + \"static/media/warning--hairpin-curve-right--g3.193a361e.png\";","export default __webpack_public_path__ + \"static/media/warning--height-restriction--g2.338e63be.png\";","export default __webpack_public_path__ + \"static/media/warning--height-restriction--g3.71fa9500.png\";","export default __webpack_public_path__ + \"static/media/warning--height-restriction--g4.32ae1bcd.png\";","export default __webpack_public_path__ + \"static/media/warning--height-restriction--g5.079c301b.png\";","export default __webpack_public_path__ + \"static/media/warning--horizontal-alignment-left--g1.5f4578ae.png\";","export default __webpack_public_path__ + \"static/media/warning--horizontal-alignment-left--g3.fa116178.png\";","export default __webpack_public_path__ + \"static/media/warning--horizontal-alignment-right--g1.e52240f3.png\";","export default __webpack_public_path__ + \"static/media/warning--horizontal-alignment-right--g3.4a7db298.png\";","export default __webpack_public_path__ + \"static/media/warning--horse-crossing--g1.d3216891.png\";","export default __webpack_public_path__ + \"static/media/warning--icy-road--g1.c497dd9c.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-acute-left--g1.701ef67e.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-acute-left--g2.aed0430a.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-acute-right--g1.97f3099c.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-acute-right--g2.868e5834.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-left--g1.9d8f0946.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-left--g2.4142c0b3.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-left--g3.ac6cedd7.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-left--g4.64bbd277.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-right--g1.c806e5b6.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-right--g2.42f22c1e.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-right--g3.928aa62d.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-a-side-road-perpendicular-right--g4.956d6e55.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-merge-from-left--g1.bf9a8c4e.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-merge-from-right--g1.9d27fd5a.png\";","export default __webpack_public_path__ + \"static/media/warning--junction-with-side-roads--g1.266339ad.png\";","export default __webpack_public_path__ + \"static/media/warning--kangaloo-crossing--g1.f937c5b4.png\";","export default __webpack_public_path__ + \"static/media/warning--keep-distance--g1.18012af6.png\";","export default __webpack_public_path__ + \"static/media/warning--keep-left--g1.b5f34133.png\";","export default __webpack_public_path__ + \"static/media/warning--keep-right--g1.9eb6188b.png\";","export default __webpack_public_path__ + \"static/media/warning--kiwi-crossing--g1.1d1fffc2.png\";","export default __webpack_public_path__ + \"static/media/warning--kiwi-crossing--g2.31b4982f.png\";","export default __webpack_public_path__ + \"static/media/warning--koala-crossing--g1.c49ced4a.png\";","export default __webpack_public_path__ + \"static/media/warning--koala-crossing--g2.89b90763.png\";","export default __webpack_public_path__ + \"static/media/warning--koala-crossing--g3.31ba34fb.png\";","export default __webpack_public_path__ + \"static/media/warning--koala-crossing--g4.f4a67cc8.png\";","export default __webpack_public_path__ + \"static/media/warning--lane-closed-in-dual-lanes-left--g1.7624de03.png\";","export default __webpack_public_path__ + \"static/media/warning--lane-closed-in-dual-lanes-left--g2.3509b0fc.png\";","export default __webpack_public_path__ + \"static/media/warning--lane-closed-in-dual-lanes-right--g1.2df26f89.png\";","export default __webpack_public_path__ + \"static/media/warning--lane-closed-in-dual-lanes-right--g2.7bbfbdf6.png\";","export default __webpack_public_path__ + \"static/media/warning--length-restriction--g1.883f897f.png\";","export default __webpack_public_path__ + \"static/media/warning--length-restriction--g2.82aa1857.png\";","export default __webpack_public_path__ + \"static/media/warning--light-rail-transit-vehicles--g1.18a56f76.png\";","export default __webpack_public_path__ + \"static/media/warning--limited-lighting-under-trees--g1.12866256.png\";","export default __webpack_public_path__ + \"static/media/warning--logging-vehicles--g1.78031a98.png\";","export default __webpack_public_path__ + \"static/media/warning--loop-270-degree--g1.2e953561.png\";","export default __webpack_public_path__ + \"static/media/warning--loop-pretzel--g1.ec181bb6.png\";","export default __webpack_public_path__ + \"static/media/warning--loose-road-surface--g1.9cae8688.png\";","export default __webpack_public_path__ + \"static/media/warning--loose-road-surface--g2.1f8298ec.png\";","export default __webpack_public_path__ + \"static/media/warning--loose-road-surface--g3.aa246e46.png\";","export default __webpack_public_path__ + \"static/media/warning--loose-road-surface--g4.5d211f2c.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g1.28089b2a.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g2.5cf5bdc9.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g3.dd69f808.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g4.fc3dd88f.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g5.1f6f2725.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g6.7aba7310.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g7.0ae82c4d.png\";","export default __webpack_public_path__ + \"static/media/warning--low-flying-aircraft--g8.15694dc5.png\";","export default __webpack_public_path__ + \"static/media/warning--low-ground-clearance--g1.ffa6da01.png\";","export default __webpack_public_path__ + \"static/media/warning--low-ground-clearance--g2.3e54bb51.png\";","export default __webpack_public_path__ + \"static/media/warning--low-ground-clearance--g3.ce30c364.png\";","export default __webpack_public_path__ + \"static/media/warning--monkey-crossing--g1.f226862a.png\";","export default __webpack_public_path__ + \"static/media/warning--motorcycles-crossing--g1.afd3f593.png\";","export default __webpack_public_path__ + \"static/media/warning--narrow-bridge--g1.e80d13e1.png\";","export default __webpack_public_path__ + \"static/media/warning--narrow-bridge--g2.eb66e49c.png\";","export default __webpack_public_path__ + \"static/media/warning--narrow-bridge--g3.2ba8e460.png\";","export default __webpack_public_path__ + \"static/media/warning--no-passing-zone--g1.4c1a1d05.png\";","export default __webpack_public_path__ + \"static/media/warning--no-passing-zone--g2.d2c6f7ce.png\";","export default __webpack_public_path__ + \"static/media/warning--occupied-lanes--g1.a3fb4526.png\";","export default __webpack_public_path__ + \"static/media/warning--offset-roads--g1.b417a496.png\";","export default __webpack_public_path__ + \"static/media/warning--offset-roads--g2.935e20ba.png\";","export default __webpack_public_path__ + \"static/media/warning--offset-roads--g3.faa03178.png\";","export default __webpack_public_path__ + \"static/media/warning--offset-roads--g4.353ab25e.png\";","export default __webpack_public_path__ + \"static/media/warning--opening-or-swing-bridge--g1.1fb27ae9.png\";","export default __webpack_public_path__ + \"static/media/warning--opening-or-swing-bridge--g2.1a1a0f21.png\";","export default __webpack_public_path__ + \"static/media/warning--other-danger--g1.3188ed01.png\";","export default __webpack_public_path__ + \"static/media/warning--other-danger--g2.7e8cac18.png\";","export default __webpack_public_path__ + \"static/media/warning--other-danger--g3.1ee8a971.png\";","export default __webpack_public_path__ + \"static/media/warning--panda-crossing--g1.e2bdb7b5.png\";","export default __webpack_public_path__ + \"static/media/warning--pass-left-or-right--g1.7d7f601f.png\";","export default __webpack_public_path__ + \"static/media/warning--pass-left-or-right--g2.b55dff44.png\";","export default __webpack_public_path__ + \"static/media/warning--pass-left-or-right--g3.f01eab62.png\";","export default __webpack_public_path__ + \"static/media/warning--pavement-ahead--g1.7a325168.png\";","export default __webpack_public_path__ + \"static/media/warning--pavement-ends--g1.150a9eb6.png\";","export default __webpack_public_path__ + \"static/media/warning--pavement-ends--g2.4aa4c794.png\";","export default __webpack_public_path__ + \"static/media/warning--pavement-ends--g3.95da7c5c.png\";","export default __webpack_public_path__ + \"static/media/warning--pavement-ends--g4.2a4100fb.png\";","export default __webpack_public_path__ + \"static/media/warning--pavement-ends--g5.3aa58447.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g1.3b874634.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g4.5c84a724.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g5.b0b6f57d.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g6.116c592a.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g7.9ef22005.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g8.04317383.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g9.8def020a.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g10.f15c17b4.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g11.d4d8802a.png\";","export default __webpack_public_path__ + \"static/media/warning--pedestrians-crossing--g12.d6a9a05d.png\";","export default __webpack_public_path__ + \"static/media/warning--playground--g1.d27fa8a1.png\";","export default __webpack_public_path__ + \"static/media/warning--playground--g3.030a0910.png\";","export default __webpack_public_path__ + \"static/media/warning--polar-bear-crossing--g1.83f48f13.png\";","export default __webpack_public_path__ + \"static/media/warning--quay-or-river-bank--g1.06042e51.png\";","export default __webpack_public_path__ + \"static/media/warning--quay-or-river-bank--g2.f72ff26e.png\";","export default __webpack_public_path__ + \"static/media/warning--quay-or-river-bank--g3.115341dd.png\";","export default __webpack_public_path__ + \"static/media/warning--quay-or-river-bank--g4.ddcd4717.png\";","export default __webpack_public_path__ + \"static/media/warning--rabbit-crossing--g1.078f403a.png\";","export default __webpack_public_path__ + \"static/media/warning--raccoon-crossing--g1.1668b542.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing--g1.e669ea31.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing--g2.02fde72b.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing--g3.8750f7fe.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing--g4.7ca3c9a3.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g1.10b1d9f7.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g2.1e0850d8.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g3.6e3df1bf.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g4.ee65577f.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g5.489d5280.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g6.692ef82e.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-with-barriers--g7.a1fba766.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-without-barriers--g1.56e6bc9c.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-without-barriers--g2.4806262d.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-without-barriers--g3.0a195b24.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-without-barriers--g4.2ef1f5ca.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-without-barriers--g5.26a5cfe8.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-crossing-without-barriers--g6.cc1a10b5.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g1.e91d23c6.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g2.4e7c41ae.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g3.025e4551.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g4.7f8bcdfd.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g5.ff21b221.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g6.3e6b2b59.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g7.0191ef0a.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g8.0b49d7a0.png\";","export default __webpack_public_path__ + \"static/media/warning--railroad-intersection--g9.e91cfdd5.png\";","export default __webpack_public_path__ + \"static/media/warning--ramp-closed--g1.b7091862.png\";","export default __webpack_public_path__ + \"static/media/warning--reduced-maximum-speed-limit--g1.e37bae32.png\";","export default __webpack_public_path__ + \"static/media/warning--reserved-lane--g1.8d676894.png\";","export default __webpack_public_path__ + \"static/media/warning--restricted-zone--g1.4c3bdaf7.png\";","export default __webpack_public_path__ + \"static/media/warning--reversible-lanes--g1.1aa1f3d9.png\";","export default __webpack_public_path__ + \"static/media/warning--reversible-lanes--g2.8e1063e0.png\";","export default __webpack_public_path__ + \"static/media/warning--rickshaws-crossing--g1.57f86968.png\";","export default __webpack_public_path__ + \"static/media/warning--road-blocks--g1.b88715e8.png\";","export default __webpack_public_path__ + \"static/media/warning--road-bump--g1.33610537.png\";","export default __webpack_public_path__ + \"static/media/warning--road-bump--g2.82cf40b3.png\";","export default __webpack_public_path__ + \"static/media/warning--road-bump--g3.a44b2601.png\";","export default __webpack_public_path__ + \"static/media/warning--road-bump-with-speed-limit--g1.7be1fee6.png\";","export default __webpack_public_path__ + \"static/media/warning--road-closed--g3.c3c7cc6d.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows--g1.77f6e5cb.png\";","import basicPins from './basic-pins';\r\nimport trafficSigns from './traffic-signs';\r\nimport UKRoadSigns from './uk-road-signs';\r\nimport packageObjects from './package_objects';\r\nimport packageSigns from './package_signs';\r\nimport allterra from './allterra';\r\n\r\nconst tagTextures = {\r\n ...basicPins,\r\n ...trafficSigns,\r\n ...UKRoadSigns,\r\n ...packageObjects,\r\n ...packageSigns,\r\n ...allterra\r\n};\r\n\r\nexport const defaultTagTexture = Object.keys(tagTextures)[0];\r\n\r\nexport const getTagTexturePath = (key) => {\r\n return tagTextures[key];\r\n};\r\n\r\nexport default tagTextures;\r\n","import icon0 from './complementary--accident-area--g1.png';\r\nimport icon1 from './complementary--accident-area--g2.png';\r\nimport icon2 from './complementary--accident-area--g3.png';\r\nimport icon3 from './complementary--accident-area--g4.png';\r\nimport icon4 from './complementary--advisory-exit-or-ramp-speed--g1.png';\r\nimport icon5 from './complementary--bicycles--g1.png';\r\nimport icon6 from './complementary--bicycles-and-pedestrians-detour--g1.png';\r\nimport icon7 from './complementary--bicycles-or-pedestrians-detour--g1.png';\r\nimport icon8 from './complementary--bicycles-turn-right--g1.png';\r\nimport icon9 from './complementary--bike-route--g1.png';\r\nimport icon10 from './complementary--bike-route--g3.png';\r\nimport icon11 from './complementary--both-directions--g1.png';\r\nimport icon12 from './complementary--both-directions--g2.png';\r\nimport icon13 from './complementary--buses--g1.png';\r\nimport icon14 from './complementary--buses-and-trucks--g1.png';\r\nimport icon15 from './complementary--camera--g1.png';\r\nimport icon16 from './complementary--camera--g2.png';\r\nimport icon17 from './complementary--camera--g3.png';\r\nimport icon18 from './complementary--camera--g4.png';\r\nimport icon19 from './complementary--camera--g5.png';\r\nimport icon20 from './complementary--caravan-trailers--g2.png';\r\nimport icon21 from './complementary--caravan-trailers--g3.png';\r\nimport icon22 from './complementary--caravans--g2.png';\r\nimport icon23 from './complementary--carts--g1.png';\r\nimport icon24 from './complementary--chevron-left--g1.png';\r\nimport icon25 from './complementary--chevron-left--g2.png';\r\nimport icon26 from './complementary--chevron-left--g3.png';\r\nimport icon27 from './complementary--chevron-left--g4.png';\r\nimport icon28 from './complementary--chevron-left--g5.png';\r\nimport icon29 from './complementary--chevron-right--g1.png';\r\nimport icon30 from './complementary--chevron-right--g2.png';\r\nimport icon31 from './complementary--chevron-right--g3.png';\r\nimport icon32 from './complementary--chevron-right--g4.png';\r\nimport icon33 from './complementary--chevron-right--g5.png';\r\nimport icon34 from './complementary--dangerous-or-pollutant-good--g1.png';\r\nimport icon35 from './complementary--dead-end--g1.png';\r\nimport icon36 from './complementary--detour--g1.png';\r\nimport icon37 from './complementary--disabled-persons--g1.png';\r\nimport icon38 from './complementary--distance--g1.png';\r\nimport icon39 from './complementary--distance--g2.png';\r\nimport icon40 from './complementary--distance--g3.png';\r\nimport icon41 from './complementary--end-of-road-works--g1.png';\r\nimport icon42 from './complementary--except-bicycles--g1.png';\r\nimport icon43 from './complementary--except-bicycles--g2.png';\r\nimport icon44 from './complementary--except-buses--g1.png';\r\nimport icon45 from './complementary--except-carts--g1.png';\r\nimport icon46 from './complementary--except-motorcycles--g1.png';\r\nimport icon47 from './complementary--except-motorcycles--g2.png';\r\nimport icon48 from './complementary--except-polluting-level-green--g1.png';\r\nimport icon49 from './complementary--except-polluting-level-green-yellow--g1.png';\r\nimport icon50 from './complementary--except-polluting-level-green-yellow-red--g1.png';\r\nimport icon51 from './complementary--except-tractors--g1.png';\r\nimport icon52 from './complementary--except-tractors--g2.png';\r\nimport icon53 from './complementary--except-trailers--g1.png';\r\nimport icon54 from './complementary--except-trailers--g2.png';\r\nimport icon55 from './complementary--except-trains--g1.png';\r\nimport icon56 from './complementary--except-trams--g1.png';\r\nimport icon57 from './complementary--except-trucks--g1.png';\r\nimport icon58 from './complementary--except-vehicles--g1.png';\r\nimport icon59 from './complementary--except-vehicles--g2.png';\r\nimport icon60 from './complementary--go-left--g1.png';\r\nimport icon61 from './complementary--go-right--g1.png';\r\nimport icon62 from './complementary--go-straight-or-turn-left--g1.png';\r\nimport icon63 from './complementary--go-straight-or-turn-right--g1.png';\r\nimport icon64 from './complementary--height-limit--g1.png';\r\nimport icon65 from './complementary--height-limit--g2.png';\r\nimport icon66 from './complementary--including-bicycles-and-motorcycles--g1.png';\r\nimport icon67 from './complementary--including-buses-vehicles--g1.png';\r\nimport icon68 from './complementary--keep-left--g1.png';\r\nimport icon69 from './complementary--keep-right--g1.png';\r\nimport icon70 from './complementary--lane-control--g1.png';\r\nimport icon71 from './complementary--lane-control--g2.png';\r\nimport icon72 from './complementary--lane-control--g3.png';\r\nimport icon73 from './complementary--maximum-speed-limit-10--g1.png';\r\nimport icon74 from './complementary--maximum-speed-limit-15--g1.png';\r\nimport icon75 from './complementary--maximum-speed-limit-20--g1.png';\r\nimport icon76 from './complementary--maximum-speed-limit-25--g1.png';\r\nimport icon77 from './complementary--maximum-speed-limit-30--g1.png';\r\nimport icon78 from './complementary--maximum-speed-limit-35--g1.png';\r\nimport icon79 from './complementary--maximum-speed-limit-40--g1.png';\r\nimport icon80 from './complementary--maximum-speed-limit-45--g1.png';\r\nimport icon81 from './complementary--maximum-speed-limit-50--g1.png';\r\nimport icon82 from './complementary--maximum-speed-limit-55--g1.png';\r\nimport icon83 from './complementary--maximum-speed-limit-60--g1.png';\r\nimport icon84 from './complementary--maximum-speed-limit-65--g1.png';\r\nimport icon85 from './complementary--maximum-speed-limit-70--g1.png';\r\nimport icon86 from './complementary--maximum-speed-limit-75--g1.png';\r\nimport icon87 from './complementary--maximum-speed-limit-80--g1.png';\r\nimport icon88 from './complementary--maximum-speed-limit-85--g1.png';\r\nimport icon89 from './complementary--maximum-speed-limit-90--g1.png';\r\nimport icon90 from './complementary--maximum-speed-limit-95--g1.png';\r\nimport icon91 from './complementary--motorcycles--g1.png';\r\nimport icon92 from './complementary--motorcycles--g2.png';\r\nimport icon93 from './complementary--motorcycles--g3.png';\r\nimport icon94 from './complementary--motorcycles--g4.png';\r\nimport icon95 from './complementary--obstacle-delineator--g1.png';\r\nimport icon96 from './complementary--obstacle-delineator--g2.png';\r\nimport icon97 from './complementary--obstacle-delineator--g3.png';\r\nimport icon98 from './complementary--one-direction-left--g1.png';\r\nimport icon99 from './complementary--one-direction-right--g1.png';\r\nimport icon100 from './complementary--pass-left--g1.png';\r\nimport icon101 from './complementary--pass-right--g1.png';\r\nimport icon102 from './complementary--pedestrians-and-bicycles--g1.png';\r\nimport icon103 from './complementary--pedestrians-left--g1.png';\r\nimport icon104 from './complementary--pedestrians-right--g1.png';\r\nimport icon105 from './complementary--photo-enforced--g1.png';\r\nimport icon106 from './complementary--playground--g1.png';\r\nimport icon107 from './complementary--priority-route-at-intersection--g1.png';\r\nimport icon108 from './complementary--priority-route-at-intersection--g2.png';\r\nimport icon109 from './complementary--priority-route-at-intersection--g3.png';\r\nimport icon110 from './complementary--priority-route-at-intersection--g4.png';\r\nimport icon111 from './complementary--priority-route-at-intersection--g5.png';\r\nimport icon112 from './complementary--priority-route-at-intersection--g6.png';\r\nimport icon113 from './complementary--railroad--g1.png';\r\nimport icon114 from './complementary--railroad--g2.png';\r\nimport icon115 from './complementary--railroad--g3.png';\r\nimport icon116 from './complementary--restriction-in-both-directions--g1.png';\r\nimport icon117 from './complementary--roundabout-go-left--g1.png';\r\nimport icon118 from './complementary--roundabout-go-right--g1.png';\r\nimport icon119 from './complementary--roundabout-go-straight--g1.png';\r\nimport icon120 from './complementary--slippery-for-caravan-trailers--g1.png';\r\nimport icon121 from './complementary--snow--g2.png';\r\nimport icon122 from './complementary--snow--g4.png';\r\nimport icon123 from './complementary--snow--g5.png';\r\nimport icon124 from './complementary--snowmobiles--g1.png';\r\nimport icon125 from './complementary--soft-shoulder--g1.png';\r\nimport icon126 from './complementary--soft-shoulder--g2.png';\r\nimport icon127 from './complementary--steep-ascent--g1.png';\r\nimport icon128 from './complementary--steep-descent--g1.png';\r\nimport icon129 from './complementary--time-restrictions--g1.png';\r\nimport icon130 from './complementary--time-restrictions--g3.png';\r\nimport icon131 from './complementary--tow-away-zone--g1.png';\r\nimport icon132 from './complementary--tow-away-zone--g3.png';\r\nimport icon133 from './complementary--tractors--g1.png';\r\nimport icon134 from './complementary--traffic-queues--g1.png';\r\nimport icon135 from './complementary--trailers--g1.png';\r\nimport icon136 from './complementary--trailers--g2.png';\r\nimport icon137 from './complementary--trailers--g3.png';\r\nimport icon138 from './complementary--trailers--g4.png';\r\nimport icon139 from './complementary--trains--g1.png';\r\nimport icon140 from './complementary--trams--g1.png';\r\nimport icon141 from './complementary--trees--g1.png';\r\nimport icon142 from './complementary--trucks--g1.png';\r\nimport icon143 from './complementary--trucks--g2.png';\r\nimport icon144 from './complementary--trucks--g3.png';\r\nimport icon145 from './complementary--trucks-and-trailers--g1.png';\r\nimport icon146 from './complementary--trucks-buses-trailers--g1.png';\r\nimport icon147 from './complementary--trucks-go-left--g1.png';\r\nimport icon148 from './complementary--trucks-go-left-ahead--g1.png';\r\nimport icon149 from './complementary--trucks-go-right--g1.png';\r\nimport icon150 from './complementary--trucks-go-right-ahead--g1.png';\r\nimport icon151 from './complementary--trucks-go-straight--g1.png';\r\nimport icon152 from './complementary--trucks-turn-left--g1.png';\r\nimport icon153 from './complementary--trucks-turn-right--g1.png';\r\nimport icon154 from './complementary--turn-left--g1.png';\r\nimport icon155 from './complementary--turn-left--g2.png';\r\nimport icon156 from './complementary--turn-right--g1.png';\r\nimport icon157 from './complementary--turn-right--g2.png';\r\nimport icon158 from './complementary--two-way-traffic--g1.png';\r\nimport icon159 from './complementary--two-way-traffic--g2.png';\r\nimport icon160 from './complementary--two-way-traffic--g3.png';\r\nimport icon161 from './complementary--two-way-traffic--g4.png';\r\nimport icon162 from './complementary--two-way-traffic--g5.png';\r\nimport icon163 from './complementary--vehicles--g1.png';\r\nimport icon164 from './complementary--vehicles--g2.png';\r\nimport icon165 from './complementary--vehicles-or-buses--g1.png';\r\nimport icon166 from './complementary--weekends-or-holidays--g1.png';\r\nimport icon167 from './complementary--weight-limit--g1.png';\r\nimport icon168 from './complementary--when-foggy--g1.png';\r\nimport icon169 from './complementary--when-rainy--g1.png';\r\nimport icon170 from './complementary--when-rainy--g2.png';\r\nimport icon171 from './complementary--when-rainy--g3.png';\r\nimport icon172 from './complementary--when-snowy--g1.png';\r\nimport icon173 from './complementary--when-snowy--g2.png';\r\nimport icon174 from './complementary--when-snowy-or-rainy--g1.png';\r\nimport icon175 from './complementary--when-snowy-or-rainy--g2.png';\r\nimport icon176 from './complementary--when-wet--g1.png';\r\nimport icon177 from './complementary--width-limit--g1.png';\r\nimport icon178 from './complementary--working-days--g1.png';\r\nimport icon179 from './information--airport--g1.png';\r\nimport icon180 from './information--airport--g2.png';\r\nimport icon181 from './information--bicycle-lane--g1.png';\r\nimport icon182 from './information--bicycles-both-ways--g1.png';\r\nimport icon183 from './information--bicycles-crossing--g1.png';\r\nimport icon184 from './information--bicycles-crossing--g2.png';\r\nimport icon185 from './information--bicycles-crossing--g3.png';\r\nimport icon186 from './information--bike-route--g1.png';\r\nimport icon187 from './information--bike-route--g2.png';\r\nimport icon188 from './information--built-up-area--g1.png';\r\nimport icon189 from './information--built-up-area--g2.png';\r\nimport icon190 from './information--bus-lane-straight--g1.png';\r\nimport icon191 from './information--bus-stop--g1.png';\r\nimport icon192 from './information--bus-stop--g2.png';\r\nimport icon193 from './information--camera--g1.png';\r\nimport icon194 from './information--camera--g2.png';\r\nimport icon195 from './information--camera--g3.png';\r\nimport icon196 from './information--camp--g1.png';\r\nimport icon197 from './information--camp--g2.png';\r\nimport icon198 from './information--car-pool-lane--g1.png';\r\nimport icon199 from './information--caravan-parking--g1.png';\r\nimport icon200 from './information--caravan-trailer-parking--g1.png';\r\nimport icon201 from './information--cargo-loading-zone--g1.png';\r\nimport icon202 from './information--central-lane--g1.png';\r\nimport icon203 from './information--charging-station--g1.png';\r\nimport icon204 from './information--children--g1.png';\r\nimport icon205 from './information--children--g2.png';\r\nimport icon206 from './information--children-crossing--g5.png';\r\nimport icon207 from './information--cycling-two-abreast-permitted--g1.png';\r\nimport icon208 from './information--dead-end--g1.png';\r\nimport icon209 from './information--dead-end--g2.png';\r\nimport icon210 from './information--dead-end--g3.png';\r\nimport icon211 from './information--dead-end--g4.png';\r\nimport icon212 from './information--dead-end-except-bicycles--g1.png';\r\nimport icon213 from './information--dead-end-except-bicycles-and-pedestrians--g1.png';\r\nimport icon214 from './information--dead-end-except-bicycles-and-pedestrians--g2.png';\r\nimport icon215 from './information--dead-end-left--g1.png';\r\nimport icon216 from './information--dead-end-left--g2.png';\r\nimport icon217 from './information--dead-end-right--g1.png';\r\nimport icon218 from './information--dead-end-right--g2.png';\r\nimport icon219 from './information--dead-end-right--g3.png';\r\nimport icon220 from './information--directions--g1.png';\r\nimport icon221 from './information--disabled-persons--g1.png';\r\nimport icon222 from './information--disabled-persons--g2.png';\r\nimport icon223 from './information--disabled-persons--g3.png';\r\nimport icon224 from './information--emergency-facility--g1.png';\r\nimport icon225 from './information--end-of-advisory-maximum-speed-limit-20--g1.png';\r\nimport icon226 from './information--end-of-advisory-maximum-speed-limit-40--g1.png';\r\nimport icon227 from './information--end-of-advisory-maximum-speed-limit-60--g1.png';\r\nimport icon228 from './information--end-of-advisory-maximum-speed-limit-70--g1.png';\r\nimport icon229 from './information--end-of-advisory-maximum-speed-limit-80--g1.png';\r\nimport icon230 from './information--end-of-advisory-maximum-speed-limit-90--g1.png';\r\nimport icon231 from './information--end-of-bicycle-lane--g1.png';\r\nimport icon232 from './information--end-of-built-up-area--g1.png';\r\nimport icon233 from './information--end-of-built-up-area--g2.png';\r\nimport icon234 from './information--end-of-built-up-area--g3.png';\r\nimport icon235 from './information--end-of-built-up-area--g4.png';\r\nimport icon236 from './information--end-of-car-pool-lane--g1.png';\r\nimport icon237 from './information--end-of-limited-access-road--g1.png';\r\nimport icon238 from './information--end-of-living-street--g1.png';\r\nimport icon239 from './information--end-of-living-street--g2.png';\r\nimport icon240 from './information--end-of-minimum-speed-10--g1.png';\r\nimport icon241 from './information--end-of-minimum-speed-20--g1.png';\r\nimport icon242 from './information--end-of-minimum-speed-25--g1.png';\r\nimport icon243 from './information--end-of-minimum-speed-30--g1.png';\r\nimport icon244 from './information--end-of-minimum-speed-35--g1.png';\r\nimport icon245 from './information--end-of-minimum-speed-40--g1.png';\r\nimport icon246 from './information--end-of-minimum-speed-50--g1.png';\r\nimport icon247 from './information--end-of-minimum-speed-60--g1.png';\r\nimport icon248 from './information--end-of-minimum-speed-70--g1.png';\r\nimport icon249 from './information--end-of-minimum-speed-75--g1.png';\r\nimport icon250 from './information--end-of-minimum-speed-80--g1.png';\r\nimport icon251 from './information--end-of-minimum-speed-90--g1.png';\r\nimport icon252 from './information--end-of-minimum-speed-100--g1.png';\r\nimport icon253 from './information--end-of-minimum-speed-110--g1.png';\r\nimport icon254 from './information--end-of-minimum-speed-120--g1.png';\r\nimport icon255 from './information--end-of-minimum-speed-130--g1.png';\r\nimport icon256 from './information--end-of-motorway--g1.png';\r\nimport icon257 from './information--end-of-overtaking-permitted-heavy-good-vehicles--g1.png';\r\nimport icon258 from './information--end-of-road-works--g1.png';\r\nimport icon259 from './information--end-of-tunnel--g1.png';\r\nimport icon260 from './information--end-of-tunnel--g2.png';\r\nimport icon261 from './information--end-of-two-way-traffic--g1.png';\r\nimport icon262 from './information--equestrians-permitted--g1.png';\r\nimport icon263 from './information--exit-ahead--g1.png';\r\nimport icon264 from './information--exit-ahead--g2.png';\r\nimport icon265 from './information--exit-ahead--g3.png';\r\nimport icon266 from './information--flight-port--g1.png';\r\nimport icon267 from './information--food--g1.png';\r\nimport icon268 from './information--food--g2.png';\r\nimport icon269 from './information--gas-station--g1.png';\r\nimport icon270 from './information--gas-station--g2.png';\r\nimport icon271 from './information--gas-station--g3.png';\r\nimport icon272 from './information--general-speed-limit-at-city-border--g1.png';\r\nimport icon273 from './information--go-left--g1.png';\r\nimport icon274 from './information--go-right--g1.png';\r\nimport icon275 from './information--go-straight--g1.png';\r\nimport icon276 from './information--go-straight-or-left--g1.png';\r\nimport icon277 from './information--go-straight-or-right--g1.png';\r\nimport icon278 from './information--go-straight-or-turn-left--g1.png';\r\nimport icon279 from './information--go-straight-or-turn-right--g1.png';\r\nimport icon280 from './information--hazardous-goods-vehicles-lane--g1.png';\r\nimport icon281 from './information--height-limit--g1.png';\r\nimport icon282 from './information--height-limit--g2.png';\r\nimport icon283 from './information--highway-directions--g1.png';\r\nimport icon284 from './information--highway-exit--g1.png';\r\nimport icon285 from './information--highway-interchange--g1.png';\r\nimport icon286 from './information--highway-interstate-route--g1.png';\r\nimport icon287 from './information--highway-interstate-route--g2.png';\r\nimport icon288 from './information--highway-preferential-lane--g1.png';\r\nimport icon289 from './information--highway-preferential-lane--g2.png';\r\nimport icon290 from './information--highway-reference-location--g1.png';\r\nimport icon291 from './information--highway-reference-location--g2.png';\r\nimport icon292 from './information--hiking--g1.png';\r\nimport icon293 from './information--hospital--g1.png';\r\nimport icon294 from './information--hurricane-evacuation-route--g1.png';\r\nimport icon295 from './information--interstate-route--g1.png';\r\nimport icon296 from './information--lane-control-intersections--g1.png';\r\nimport icon297 from './information--lane-control-left-turn--g1.png';\r\nimport icon298 from './information--lane-control-multiple-lanes--g1.png';\r\nimport icon299 from './information--lane-control-multiple-lanes--g2.png';\r\nimport icon300 from './information--lane-control-right-turn--g1.png';\r\nimport icon301 from './information--limited-access-road--g1.png';\r\nimport icon302 from './information--litter-container--g1.png';\r\nimport icon303 from './information--living-street--g1.png';\r\nimport icon304 from './information--living-street--g2.png';\r\nimport icon305 from './information--living-street--g3.png';\r\nimport icon306 from './information--lodging--g1.png';\r\nimport icon307 from './information--lodging--g2.png';\r\nimport icon308 from './information--minimum-speed-10--g1.png';\r\nimport icon309 from './information--minimum-speed-20--g1.png';\r\nimport icon310 from './information--minimum-speed-25--g1.png';\r\nimport icon311 from './information--minimum-speed-30--g1.png';\r\nimport icon312 from './information--minimum-speed-35--g1.png';\r\nimport icon313 from './information--minimum-speed-40--g1.png';\r\nimport icon314 from './information--minimum-speed-50--g1.png';\r\nimport icon315 from './information--minimum-speed-60--g1.png';\r\nimport icon316 from './information--minimum-speed-70--g1.png';\r\nimport icon317 from './information--minimum-speed-75--g1.png';\r\nimport icon318 from './information--minimum-speed-80--g1.png';\r\nimport icon319 from './information--minimum-speed-90--g1.png';\r\nimport icon320 from './information--minimum-speed-100--g1.png';\r\nimport icon321 from './information--minimum-speed-110--g1.png';\r\nimport icon322 from './information--minimum-speed-120--g1.png';\r\nimport icon323 from './information--minimum-speed-130--g1.png';\r\nimport icon324 from './information--motorway--g1.png';\r\nimport icon325 from './information--motorway-exit-ahead--g1.png';\r\nimport icon326 from './information--motorway-exit-ahead--g2.png';\r\nimport icon327 from './information--motorway-exit-ahead--g3.png';\r\nimport icon328 from './information--overtaking-allowed-heavy-good-vehicles--g1.png';\r\nimport icon329 from './information--parallel-parking--g1.png';\r\nimport icon330 from './information--park-and-ride--g1.png';\r\nimport icon331 from './information--park-and-ride--g2.png';\r\nimport icon332 from './information--parking--g1.png';\r\nimport icon333 from './information--parking--g2.png';\r\nimport icon334 from './information--parking--g3.png';\r\nimport icon335 from './information--parking--g4.png';\r\nimport icon336 from './information--parking--g5.png';\r\nimport icon337 from './information--parking--g6.png';\r\nimport icon338 from './information--parking-area--g1.png';\r\nimport icon339 from './information--parking-with-restrictions--g1.png';\r\nimport icon340 from './information--pass-on-either-side--g1.png';\r\nimport icon341 from './information--passenger-loading-zone--g1.png';\r\nimport icon342 from './information--pedestrians-crossing--g1.png';\r\nimport icon343 from './information--pedestrians-crossing--g2.png';\r\nimport icon344 from './information--pedestrians-crossing--g3.png';\r\nimport icon345 from './information--pedestrians-only--g4.png';\r\nimport icon346 from './information--pedestrians-permitted--g1.png';\r\nimport icon347 from './information--perpendicular-parking--g1.png';\r\nimport icon348 from './information--picnic-site--g1.png';\r\nimport icon349 from './information--playground--g1.png';\r\nimport icon350 from './information--recreational-vehicle-sanitary-station--g1.png';\r\nimport icon351 from './information--recycle-collection-center--g1.png';\r\nimport icon352 from './information--rest-area--g1.png';\r\nimport icon353 from './information--road-bump--g1.png';\r\nimport icon354 from './information--road-skating--g1.png';\r\nimport icon355 from './information--safety-zone--g1.png';\r\nimport icon356 from './information--safety-zone--g2.png';\r\nimport icon357 from './information--safety-zone--g3.png';\r\nimport icon358 from './information--shared-path-vehicles-and-motorcycles--g1.png';\r\nimport icon359 from './information--stairs--g1.png';\r\nimport icon360 from './information--stairs--g2.png';\r\nimport icon361 from './information--stairs--g3.png';\r\nimport icon362 from './information--stairs--g4.png';\r\nimport icon363 from './information--stop-line--g1.png';\r\nimport icon364 from './information--stop-permitted--g1.png';\r\nimport icon365 from './information--street-name-one-line--g1.png';\r\nimport icon366 from './information--street-name-three-lines--g1.png';\r\nimport icon367 from './information--street-name-two-lines--g1.png';\r\nimport icon368 from './information--subway--g1.png';\r\nimport icon369 from './information--telephone--g1.png';\r\nimport icon370 from './information--telephone--g2.png';\r\nimport icon371 from './information--telephone-device-for-the-deaf--g1.png';\r\nimport icon372 from './information--toll-station--g1.png';\r\nimport icon373 from './information--tourism-information--g1.png';\r\nimport icon374 from './information--tourist-attraction--g1.png';\r\nimport icon375 from './information--traffic-merges-left--g1.png';\r\nimport icon376 from './information--traffic-merges-right--g1.png';\r\nimport icon377 from './information--trail-crossing--g1.png';\r\nimport icon378 from './information--trail-crossing--g2.png';\r\nimport icon379 from './information--trail-crossing--g3.png';\r\nimport icon380 from './information--trailer-camping--g1.png';\r\nimport icon381 from './information--train-or-light-rail-station--g1.png';\r\nimport icon382 from './information--tram-bus-stop--g1.png';\r\nimport icon383 from './information--tram-bus-stop--g2.png';\r\nimport icon384 from './information--trams-crossing--g1.png';\r\nimport icon385 from './information--truck-lane-left--g1.png';\r\nimport icon386 from './information--truck-parking--g1.png';\r\nimport icon387 from './information--truck-trailer-lane-right--g1.png';\r\nimport icon388 from './information--truck-trailer-lane-straight--g1.png';\r\nimport icon389 from './information--trucks-both-ways--g1.png';\r\nimport icon390 from './information--trucks-only--g1.png';\r\nimport icon391 from './information--tsunami-evacuation_route--g1.png';\r\nimport icon392 from './information--tunnel--g1.png';\r\nimport icon393 from './information--tunnel--g2.png';\r\nimport icon394 from './information--tunnel--g3.png';\r\nimport icon395 from './information--tunnel-ahead--g1.png';\r\nimport icon396 from './information--turn-left--g1.png';\r\nimport icon397 from './information--turn-left-ahead--g1.png';\r\nimport icon398 from './information--turn-right--g1.png';\r\nimport icon399 from './information--turn-right-ahead--g1.png';\r\nimport icon400 from './information--urban-area--g1.png';\r\nimport icon401 from './information--vehicles-on-rails--g1.png';\r\nimport icon402 from './information--water-protection-zone--g1.png';\r\nimport icon403 from './information--weight-and-height-limit--g1.png';\r\nimport icon404 from './information--weight-limit--g1.png';\r\nimport icon405 from './information--wireless-internet--g1.png';\r\nimport icon406 from './regulatory--advisory-maximum-speed-limit--g1.png';\r\nimport icon407 from './regulatory--all-directions-permitted--g1.png';\r\nimport icon408 from './regulatory--all-way--g1.png';\r\nimport icon409 from './regulatory--atvs-permitted--g1.png';\r\nimport icon410 from './regulatory--axle-limit--g1.png';\r\nimport icon411 from './regulatory--axle-limit--g2.png';\r\nimport icon412 from './regulatory--bicycle-lane-left--g1.png';\r\nimport icon413 from './regulatory--bicycle-parking--g1.png';\r\nimport icon414 from './regulatory--bicycles-and-buses-only--g1.png';\r\nimport icon415 from './regulatory--bicycles-only--g1.png';\r\nimport icon416 from './regulatory--bicycles-only--g2.png';\r\nimport icon417 from './regulatory--bicycles-only--g3.png';\r\nimport icon418 from './regulatory--bicycles-only--g4.png';\r\nimport icon419 from './regulatory--bicycles-push-button--g1.png';\r\nimport icon420 from './regulatory--bicycles-push-button--g2.png';\r\nimport icon421 from './regulatory--bicycles-stop-on-red--g1.png';\r\nimport icon422 from './regulatory--bicycles-wrong-way--g1.png';\r\nimport icon423 from './regulatory--bicycles-yield-or-use-signal--g1.png';\r\nimport icon424 from './regulatory--bike-route--g1.png';\r\nimport icon425 from './regulatory--building-direction--g1.png';\r\nimport icon426 from './regulatory--bus-priority-lane--g1.png';\r\nimport icon427 from './regulatory--buses-and-taxi-only--g1.png';\r\nimport icon428 from './regulatory--buses-only--g1.png';\r\nimport icon429 from './regulatory--buses-only--g2.png';\r\nimport icon430 from './regulatory--circular-intersection--g1.png';\r\nimport icon431 from './regulatory--circular-intersection--g2.png';\r\nimport icon432 from './regulatory--circular-intersection--g3.png';\r\nimport icon433 from './regulatory--circular-intersection--g4.png';\r\nimport icon434 from './regulatory--cross-only-on-green--g1.png';\r\nimport icon435 from './regulatory--cross-only-on-pedestrian-signal--g1.png';\r\nimport icon436 from './regulatory--crosswalk-stop-on-red--g1.png';\r\nimport icon437 from './regulatory--cycling-restriction--g1.png';\r\nimport icon438 from './regulatory--cyclists-dismount-and-walk--g1.png';\r\nimport icon439 from './regulatory--detour-left--g1.png';\r\nimport icon440 from './regulatory--detour-right--g1.png';\r\nimport icon441 from './regulatory--divided-highway-crossing--g1.png';\r\nimport icon442 from './regulatory--divided-highway-ends--g1.png';\r\nimport icon443 from './regulatory--divided-highway-starts--g1.png';\r\nimport icon444 from './regulatory--do-not-block-intersection--g1.png';\r\nimport icon445 from './regulatory--do-not-pass--g1.png';\r\nimport icon446 from './regulatory--do-not-stop-on-tracks--g1.png';\r\nimport icon447 from './regulatory--dual-lanes-all-directions-on-left--g1.png';\r\nimport icon448 from './regulatory--dual-lanes-all-directions-on-right--g1.png';\r\nimport icon449 from './regulatory--dual-lanes-bicyclists-and-pedestrians--g1.png';\r\nimport icon450 from './regulatory--dual-lanes-go-left-or-right--g1.png';\r\nimport icon451 from './regulatory--dual-lanes-go-straight-on-left--g1.png';\r\nimport icon452 from './regulatory--dual-lanes-go-straight-on-right--g1.png';\r\nimport icon453 from './regulatory--dual-lanes-turn-left--g1.png';\r\nimport icon454 from './regulatory--dual-lanes-turn-left-no-u-turn--g1.png';\r\nimport icon455 from './regulatory--dual-lanes-turn-left-or-straight--g1.png';\r\nimport icon456 from './regulatory--dual-lanes-turn-right-or-straight--g1.png';\r\nimport icon457 from './regulatory--dual-path-bicycles-and-pedestrians--g1.png';\r\nimport icon458 from './regulatory--dual-path-bicycles-and-pedestrians--g2.png';\r\nimport icon459 from './regulatory--dual-path-bicycles-and-pedestrians--g3.png';\r\nimport icon460 from './regulatory--dual-path-equestrians-and-pedestrians--g1.png';\r\nimport icon461 from './regulatory--dual-path-equestrians-and-pedestrians-bicycles--g1.png';\r\nimport icon462 from './regulatory--dual-path-pedestrians-and-bicycles--g1.png';\r\nimport icon463 from './regulatory--dual-path-pedestrians-and-bicycles--g2.png';\r\nimport icon464 from './regulatory--dual-path-pedestrians-and-equestrians--g1.png';\r\nimport icon465 from './regulatory--dual-path-pedestrians-bicycles-and-equestrians--g1.png';\r\nimport icon466 from './regulatory--dual-speed-limits--g1.png';\r\nimport icon467 from './regulatory--dual-speed-limits--g2.png';\r\nimport icon468 from './regulatory--end-of-bicycles-only--g1.png';\r\nimport icon469 from './regulatory--end-of-bicycles-only--g2.png';\r\nimport icon470 from './regulatory--end-of-bus-and-taxi-only--g1.png';\r\nimport icon471 from './regulatory--end-of-buses-only--g1.png';\r\nimport icon472 from './regulatory--end-of-buses-only--g2.png';\r\nimport icon473 from './regulatory--end-of-cycling-restriction--g1.png';\r\nimport icon474 from './regulatory--end-of-dual-path-bicycles-and-pedestrians--g1.png';\r\nimport icon475 from './regulatory--end-of-dual-path-pedestrians-and-bicycles--g1.png';\r\nimport icon476 from './regulatory--end-of-equestrians-only--g1.png';\r\nimport icon477 from './regulatory--end-of-low-beam-headlights--g1.png';\r\nimport icon478 from './regulatory--end-of-maximum-speed-limit-10--g1.png';\r\nimport icon479 from './regulatory--end-of-maximum-speed-limit-10--g2.png';\r\nimport icon480 from './regulatory--end-of-maximum-speed-limit-20--g1.png';\r\nimport icon481 from './regulatory--end-of-maximum-speed-limit-20--g2.png';\r\nimport icon482 from './regulatory--end-of-maximum-speed-limit-25--g1.png';\r\nimport icon483 from './regulatory--end-of-maximum-speed-limit-25--g2.png';\r\nimport icon484 from './regulatory--end-of-maximum-speed-limit-30--g1.png';\r\nimport icon485 from './regulatory--end-of-maximum-speed-limit-30--g2.png';\r\nimport icon486 from './regulatory--end-of-maximum-speed-limit-35--g1.png';\r\nimport icon487 from './regulatory--end-of-maximum-speed-limit-35--g2.png';\r\nimport icon488 from './regulatory--end-of-maximum-speed-limit-40--g1.png';\r\nimport icon489 from './regulatory--end-of-maximum-speed-limit-40--g2.png';\r\nimport icon490 from './regulatory--end-of-maximum-speed-limit-50--g1.png';\r\nimport icon491 from './regulatory--end-of-maximum-speed-limit-50--g2.png';\r\nimport icon492 from './regulatory--end-of-maximum-speed-limit-60--g1.png';\r\nimport icon493 from './regulatory--end-of-maximum-speed-limit-60--g2.png';\r\nimport icon494 from './regulatory--end-of-maximum-speed-limit-65--g1.png';\r\nimport icon495 from './regulatory--end-of-maximum-speed-limit-65--g2.png';\r\nimport icon496 from './regulatory--end-of-maximum-speed-limit-70--g1.png';\r\nimport icon497 from './regulatory--end-of-maximum-speed-limit-70--g2.png';\r\nimport icon498 from './regulatory--end-of-maximum-speed-limit-75--g1.png';\r\nimport icon499 from './regulatory--end-of-maximum-speed-limit-75--g2.png';\r\nimport icon500 from './regulatory--end-of-maximum-speed-limit-80--g1.png';\r\nimport icon501 from './regulatory--end-of-maximum-speed-limit-80--g2.png';\r\nimport icon502 from './regulatory--end-of-maximum-speed-limit-90--g1.png';\r\nimport icon503 from './regulatory--end-of-maximum-speed-limit-90--g2.png';\r\nimport icon504 from './regulatory--end-of-maximum-speed-limit-100--g1.png';\r\nimport icon505 from './regulatory--end-of-maximum-speed-limit-100--g2.png';\r\nimport icon506 from './regulatory--end-of-maximum-speed-limit-110--g1.png';\r\nimport icon507 from './regulatory--end-of-maximum-speed-limit-110--g2.png';\r\nimport icon508 from './regulatory--end-of-maximum-speed-limit-120--g1.png';\r\nimport icon509 from './regulatory--end-of-maximum-speed-limit-120--g2.png';\r\nimport icon510 from './regulatory--end-of-maximum-speed-limit-130--g1.png';\r\nimport icon511 from './regulatory--end-of-maximum-speed-limit-130--g2.png';\r\nimport icon512 from './regulatory--end-of-maximum-speed-limit--g1.png';\r\nimport icon513 from './regulatory--end-of-mopeds-and-bicycles-only--g1.png';\r\nimport icon514 from './regulatory--end-of-no-heavy-goods-vehicles--g1.png';\r\nimport icon515 from './regulatory--end-of-no-horn--g1.png';\r\nimport icon516 from './regulatory--end-of-no-overtaking--g1.png';\r\nimport icon517 from './regulatory--end-of-no-overtaking--g2.png';\r\nimport icon518 from './regulatory--end-of-no-overtaking--g3.png';\r\nimport icon519 from './regulatory--end-of-no-overtaking--g4.png';\r\nimport icon520 from './regulatory--end-of-no-overtaking--g5.png';\r\nimport icon521 from './regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g1.png';\r\nimport icon522 from './regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g2.png';\r\nimport icon523 from './regulatory--end-of-no-overtaking-by-motorcycles--g1.png';\r\nimport icon524 from './regulatory--end-of-no-parking--g1.png';\r\nimport icon525 from './regulatory--end-of-no-parking--g2.png';\r\nimport icon526 from './regulatory--end-of-no-parking-or-stopping--g1.png';\r\nimport icon527 from './regulatory--end-of-one-way-straight--g1.png';\r\nimport icon528 from './regulatory--end-of-parking-zone--g1.png';\r\nimport icon529 from './regulatory--end-of-parking-zone--g2.png';\r\nimport icon530 from './regulatory--end-of-pedestrians-only--g1.png';\r\nimport icon531 from './regulatory--end-of-pedestrians-only--g2.png';\r\nimport icon532 from './regulatory--end-of-pedestrians-only--g3.png';\r\nimport icon533 from './regulatory--end-of-pedestrians-only--g4.png';\r\nimport icon534 from './regulatory--end-of-priority-road--g1.png';\r\nimport icon535 from './regulatory--end-of-prohibition--g1.png';\r\nimport icon536 from './regulatory--end-of-school-zone--g1.png';\r\nimport icon537 from './regulatory--end-of-shared-path-bicycles-and-pedestrians--g1.png';\r\nimport icon538 from './regulatory--end-of-shared-path-pedestrians-and-bicycles--g1.png';\r\nimport icon539 from './regulatory--end-of-snow-chains--g1.png';\r\nimport icon540 from './regulatory--end-of-snow-chains--g2.png';\r\nimport icon541 from './regulatory--end-of-snowmobiles-only--g1.png';\r\nimport icon542 from './regulatory--end-of-speed-limit-zone--g1.png';\r\nimport icon543 from './regulatory--end-of-speed-limit-zone--g2.png';\r\nimport icon544 from './regulatory--end-of-speed-limit-zone--g3.png';\r\nimport icon545 from './regulatory--end-of-tractors-only--g1.png';\r\nimport icon546 from './regulatory--end-of-trams-and-buses-only--g1.png';\r\nimport icon547 from './regulatory--end-of-trams-only--g1.png';\r\nimport icon548 from './regulatory--end-of-trucks-and-buses-only--g1.png';\r\nimport icon549 from './regulatory--end-of-trucks-only--g1.png';\r\nimport icon550 from './regulatory--end-of-trucks-only--g2.png';\r\nimport icon551 from './regulatory--equestrians-only--g1.png';\r\nimport icon552 from './regulatory--except-railroad-crossing--g1.png';\r\nimport icon553 from './regulatory--fine-for-littering--g1.png';\r\nimport icon554 from './regulatory--give-way-to-bicycles--g1.png';\r\nimport icon555 from './regulatory--give-way-to-oncoming-traffic--g1.png';\r\nimport icon556 from './regulatory--give-way-to-oncoming-traffic--g2.png';\r\nimport icon557 from './regulatory--go-left-bicycles--g1.png';\r\nimport icon558 from './regulatory--go-right-bicycles--g1.png';\r\nimport icon559 from './regulatory--go-straight--g1.png';\r\nimport icon560 from './regulatory--go-straight--g3.png';\r\nimport icon561 from './regulatory--go-straight-bicycles--g1.png';\r\nimport icon562 from './regulatory--go-straight-or-turn-left--g1.png';\r\nimport icon563 from './regulatory--go-straight-or-turn-left--g2.png';\r\nimport icon564 from './regulatory--go-straight-or-turn-left--g3.png';\r\nimport icon565 from './regulatory--go-straight-or-turn-right--g1.png';\r\nimport icon566 from './regulatory--go-straight-or-turn-right--g2.png';\r\nimport icon567 from './regulatory--go-straight-or-turn-right--g3.png';\r\nimport icon568 from './regulatory--heavy-goods-vehicles-permitted--g1.png';\r\nimport icon569 from './regulatory--height-limit--g1.png';\r\nimport icon570 from './regulatory--high-beam-headlights--g1.png';\r\nimport icon571 from './regulatory--horn--g1.png';\r\nimport icon572 from './regulatory--in-street-pedestrian-crossing--g1.png';\r\nimport icon573 from './regulatory--keep-left--g1.png';\r\nimport icon574 from './regulatory--keep-left--g2.png';\r\nimport icon575 from './regulatory--keep-left--g3.png';\r\nimport icon576 from './regulatory--keep-left--g4.png';\r\nimport icon577 from './regulatory--keep-left--g5.png';\r\nimport icon578 from './regulatory--keep-left--g6.png';\r\nimport icon579 from './regulatory--keep-left--g7.png';\r\nimport icon580 from './regulatory--keep-right--g1.png';\r\nimport icon581 from './regulatory--keep-right--g2.png';\r\nimport icon582 from './regulatory--keep-right--g3.png';\r\nimport icon583 from './regulatory--keep-right--g4.png';\r\nimport icon584 from './regulatory--keep-right--g5.png';\r\nimport icon585 from './regulatory--keep-right--g6.png';\r\nimport icon586 from './regulatory--keep-right--g7.png';\r\nimport icon587 from './regulatory--keep-right--g8.png';\r\nimport icon588 from './regulatory--keep-right--g9.png';\r\nimport icon589 from './regulatory--lane-control--g1.png';\r\nimport icon590 from './regulatory--left-turn-yield-on-green--g1.png';\r\nimport icon591 from './regulatory--length-limit--g1.png';\r\nimport icon592 from './regulatory--length-limit--g2.png';\r\nimport icon593 from './regulatory--light-rail-divided-highway--g1.png';\r\nimport icon594 from './regulatory--light-rail-do-not-pass--g1.png';\r\nimport icon595 from './regulatory--light-rail-only--g1.png';\r\nimport icon596 from './regulatory--look--g1.png';\r\nimport icon597 from './regulatory--low-beam-headlights--g1.png';\r\nimport icon598 from './regulatory--low-beam-headlights--g2.png';\r\nimport icon599 from './regulatory--low-beam-headlights--g3.png';\r\nimport icon600 from './regulatory--low-speed-vehicle-permitted--g1.png';\r\nimport icon601 from './regulatory--maximum-speed-limit-5--g1.png';\r\nimport icon602 from './regulatory--maximum-speed-limit-5--g3.png';\r\nimport icon603 from './regulatory--maximum-speed-limit-10--g1.png';\r\nimport icon604 from './regulatory--maximum-speed-limit-10--g3.png';\r\nimport icon605 from './regulatory--maximum-speed-limit-15--g1.png';\r\nimport icon606 from './regulatory--maximum-speed-limit-15--g3.png';\r\nimport icon607 from './regulatory--maximum-speed-limit-20--g1.png';\r\nimport icon608 from './regulatory--maximum-speed-limit-20--g3.png';\r\nimport icon609 from './regulatory--maximum-speed-limit-25--g1.png';\r\nimport icon610 from './regulatory--maximum-speed-limit-25--g2.png';\r\nimport icon611 from './regulatory--maximum-speed-limit-30--g1.png';\r\nimport icon612 from './regulatory--maximum-speed-limit-30--g3.png';\r\nimport icon613 from './regulatory--maximum-speed-limit-35--g1.png';\r\nimport icon614 from './regulatory--maximum-speed-limit-35--g2.png';\r\nimport icon615 from './regulatory--maximum-speed-limit-40--g1.png';\r\nimport icon616 from './regulatory--maximum-speed-limit-40--g3.png';\r\nimport icon617 from './regulatory--maximum-speed-limit-45--g1.png';\r\nimport icon618 from './regulatory--maximum-speed-limit-45--g3.png';\r\nimport icon619 from './regulatory--maximum-speed-limit-50--g1.png';\r\nimport icon620 from './regulatory--maximum-speed-limit-50--g3.png';\r\nimport icon621 from './regulatory--maximum-speed-limit-55--g2.png';\r\nimport icon622 from './regulatory--maximum-speed-limit-60--g1.png';\r\nimport icon623 from './regulatory--maximum-speed-limit-60--g3.png';\r\nimport icon624 from './regulatory--maximum-speed-limit-65--g1.png';\r\nimport icon625 from './regulatory--maximum-speed-limit-65--g2.png';\r\nimport icon626 from './regulatory--maximum-speed-limit-70--g1.png';\r\nimport icon627 from './regulatory--maximum-speed-limit-70--g3.png';\r\nimport icon628 from './regulatory--maximum-speed-limit-75--g2.png';\r\nimport icon629 from './regulatory--maximum-speed-limit-80--g1.png';\r\nimport icon630 from './regulatory--maximum-speed-limit-80--g3.png';\r\nimport icon631 from './regulatory--maximum-speed-limit-85--g2.png';\r\nimport icon632 from './regulatory--maximum-speed-limit-90--g1.png';\r\nimport icon633 from './regulatory--maximum-speed-limit-90--g3.png';\r\nimport icon634 from './regulatory--maximum-speed-limit-100--g1.png';\r\nimport icon635 from './regulatory--maximum-speed-limit-100--g3.png';\r\nimport icon636 from './regulatory--maximum-speed-limit-110--g1.png';\r\nimport icon637 from './regulatory--maximum-speed-limit-110--g3.png';\r\nimport icon638 from './regulatory--maximum-speed-limit-120--g1.png';\r\nimport icon639 from './regulatory--maximum-speed-limit-120--g3.png';\r\nimport icon640 from './regulatory--maximum-speed-limit-130--g1.png';\r\nimport icon641 from './regulatory--maximum-speed-limit-130--g3.png';\r\nimport icon642 from './regulatory--maximum-speed-limit-led-5--g2.png';\r\nimport icon643 from './regulatory--maximum-speed-limit-led-5--g3.png';\r\nimport icon644 from './regulatory--maximum-speed-limit-led-10--g1.png';\r\nimport icon645 from './regulatory--maximum-speed-limit-led-10--g2.png';\r\nimport icon646 from './regulatory--maximum-speed-limit-led-10--g3.png';\r\nimport icon647 from './regulatory--maximum-speed-limit-led-15--g2.png';\r\nimport icon648 from './regulatory--maximum-speed-limit-led-15--g3.png';\r\nimport icon649 from './regulatory--maximum-speed-limit-led-20--g1.png';\r\nimport icon650 from './regulatory--maximum-speed-limit-led-20--g2.png';\r\nimport icon651 from './regulatory--maximum-speed-limit-led-20--g3.png';\r\nimport icon652 from './regulatory--maximum-speed-limit-led-25--g1.png';\r\nimport icon653 from './regulatory--maximum-speed-limit-led-25--g2.png';\r\nimport icon654 from './regulatory--maximum-speed-limit-led-25--g3.png';\r\nimport icon655 from './regulatory--maximum-speed-limit-led-30--g1.png';\r\nimport icon656 from './regulatory--maximum-speed-limit-led-30--g2.png';\r\nimport icon657 from './regulatory--maximum-speed-limit-led-30--g3.png';\r\nimport icon658 from './regulatory--maximum-speed-limit-led-35--g1.png';\r\nimport icon659 from './regulatory--maximum-speed-limit-led-35--g2.png';\r\nimport icon660 from './regulatory--maximum-speed-limit-led-35--g3.png';\r\nimport icon661 from './regulatory--maximum-speed-limit-led-40--g1.png';\r\nimport icon662 from './regulatory--maximum-speed-limit-led-40--g2.png';\r\nimport icon663 from './regulatory--maximum-speed-limit-led-40--g3.png';\r\nimport icon664 from './regulatory--maximum-speed-limit-led-45--g2.png';\r\nimport icon665 from './regulatory--maximum-speed-limit-led-45--g3.png';\r\nimport icon666 from './regulatory--maximum-speed-limit-led-50--g1.png';\r\nimport icon667 from './regulatory--maximum-speed-limit-led-50--g2.png';\r\nimport icon668 from './regulatory--maximum-speed-limit-led-50--g3.png';\r\nimport icon669 from './regulatory--maximum-speed-limit-led-55--g2.png';\r\nimport icon670 from './regulatory--maximum-speed-limit-led-55--g3.png';\r\nimport icon671 from './regulatory--maximum-speed-limit-led-60--g1.png';\r\nimport icon672 from './regulatory--maximum-speed-limit-led-60--g2.png';\r\nimport icon673 from './regulatory--maximum-speed-limit-led-60--g3.png';\r\nimport icon674 from './regulatory--maximum-speed-limit-led-65--g2.png';\r\nimport icon675 from './regulatory--maximum-speed-limit-led-65--g3.png';\r\nimport icon676 from './regulatory--maximum-speed-limit-led-70--g1.png';\r\nimport icon677 from './regulatory--maximum-speed-limit-led-70--g2.png';\r\nimport icon678 from './regulatory--maximum-speed-limit-led-70--g3.png';\r\nimport icon679 from './regulatory--maximum-speed-limit-led-75--g1.png';\r\nimport icon680 from './regulatory--maximum-speed-limit-led-75--g2.png';\r\nimport icon681 from './regulatory--maximum-speed-limit-led-75--g3.png';\r\nimport icon682 from './regulatory--maximum-speed-limit-led-80--g1.png';\r\nimport icon683 from './regulatory--maximum-speed-limit-led-80--g2.png';\r\nimport icon684 from './regulatory--maximum-speed-limit-led-80--g3.png';\r\nimport icon685 from './regulatory--maximum-speed-limit-led-85--g2.png';\r\nimport icon686 from './regulatory--maximum-speed-limit-led-85--g3.png';\r\nimport icon687 from './regulatory--maximum-speed-limit-led-90--g1.png';\r\nimport icon688 from './regulatory--maximum-speed-limit-led-100--g1.png';\r\nimport icon689 from './regulatory--maximum-speed-limit-led-110--g1.png';\r\nimport icon690 from './regulatory--maximum-speed-limit-led-120--g1.png';\r\nimport icon691 from './regulatory--maximum-speed-limit-led-130--g1.png';\r\nimport icon692 from './regulatory--minimum-safe-distance--g1.png';\r\nimport icon693 from './regulatory--minimum-safe-distance--g2.png';\r\nimport icon694 from './regulatory--mopeds-and-bicycles-only--g1.png';\r\nimport icon695 from './regulatory--motorcycles-and-bicycles-only--g1.png';\r\nimport icon696 from './regulatory--motorcycles-only--g1.png';\r\nimport icon697 from './regulatory--motorcycles-only--g2.png';\r\nimport icon698 from './regulatory--night-speed-limit-5--g1.png';\r\nimport icon699 from './regulatory--night-speed-limit-10--g1.png';\r\nimport icon700 from './regulatory--night-speed-limit-15--g1.png';\r\nimport icon701 from './regulatory--night-speed-limit-20--g1.png';\r\nimport icon702 from './regulatory--night-speed-limit-25--g1.png';\r\nimport icon703 from './regulatory--night-speed-limit-30--g1.png';\r\nimport icon704 from './regulatory--night-speed-limit-35--g1.png';\r\nimport icon705 from './regulatory--night-speed-limit-40--g1.png';\r\nimport icon706 from './regulatory--night-speed-limit-45--g1.png';\r\nimport icon707 from './regulatory--night-speed-limit-50--g1.png';\r\nimport icon708 from './regulatory--night-speed-limit-55--g1.png';\r\nimport icon709 from './regulatory--night-speed-limit-60--g1.png';\r\nimport icon710 from './regulatory--night-speed-limit-65--g1.png';\r\nimport icon711 from './regulatory--night-speed-limit-70--g1.png';\r\nimport icon712 from './regulatory--night-speed-limit-75--g1.png';\r\nimport icon713 from './regulatory--night-speed-limit-80--g1.png';\r\nimport icon714 from './regulatory--night-speed-limit-85--g1.png';\r\nimport icon715 from './regulatory--no-abnormal-vehicles--g1.png';\r\nimport icon716 from './regulatory--no-atvs--g1.png';\r\nimport icon717 from './regulatory--no-bicycles--g1.png';\r\nimport icon718 from './regulatory--no-bicycles--g2.png';\r\nimport icon719 from './regulatory--no-bicycles--g3.png';\r\nimport icon720 from './regulatory--no-bicycles-carts-or-hand-carts--g1.png';\r\nimport icon721 from './regulatory--no-bicycles-mopeds-or-motorcycles--g1.png';\r\nimport icon722 from './regulatory--no-bicycles-mopeds-or-motorcycles--g2.png';\r\nimport icon723 from './regulatory--no-bicycles-or-hand-carts--g1.png';\r\nimport icon724 from './regulatory--no-bicycles-or-motorcycles--g1.png';\r\nimport icon725 from './regulatory--no-bicycles-tractors-or-carts--g1.png';\r\nimport icon726 from './regulatory--no-buses--g1.png';\r\nimport icon727 from './regulatory--no-buses--g2.png';\r\nimport icon728 from './regulatory--no-buses--g3.png';\r\nimport icon729 from './regulatory--no-caravan-trailers--g1.png';\r\nimport icon730 from './regulatory--no-caravans--g1.png';\r\nimport icon731 from './regulatory--no-caravans-or-caravan-trailers--g1.png';\r\nimport icon732 from './regulatory--no-cargo-loading--g1.png';\r\nimport icon733 from './regulatory--no-carts--g1.png';\r\nimport icon734 from './regulatory--no-carts--g2.png';\r\nimport icon735 from './regulatory--no-carts--g3.png';\r\nimport icon736 from './regulatory--no-carts-or-tractors--g1.png';\r\nimport icon737 from './regulatory--no-construction-vehicles--g1.png';\r\nimport icon738 from './regulatory--no-entry--g1.png';\r\nimport icon739 from './regulatory--no-equestrians--g1.png';\r\nimport icon740 from './regulatory--no-go-straight-or-turn-left--g1.png';\r\nimport icon741 from './regulatory--no-go-straight-or-turn-right--g1.png';\r\nimport icon742 from './regulatory--no-good-trailers--g2.png';\r\nimport icon743 from './regulatory--no-goods-vehicle-trailers--g1.png';\r\nimport icon744 from './regulatory--no-hand-carts--g1.png';\r\nimport icon745 from './regulatory--no-hand-carts--g2.png';\r\nimport icon746 from './regulatory--no-hand-carts-or-bicycles--g1.png';\r\nimport icon747 from './regulatory--no-hawkers--g1.png';\r\nimport icon748 from './regulatory--no-heavy-goods-vehicles--g1.png';\r\nimport icon749 from './regulatory--no-heavy-goods-vehicles--g2.png';\r\nimport icon750 from './regulatory--no-heavy-goods-vehicles--g3.png';\r\nimport icon751 from './regulatory--no-heavy-goods-vehicles--g4.png';\r\nimport icon752 from './regulatory--no-heavy-goods-vehicles--g5.png';\r\nimport icon753 from './regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g1.png';\r\nimport icon754 from './regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g2.png';\r\nimport icon755 from './regulatory--no-heavy-goods-vehicles-or-buses--g1.png';\r\nimport icon756 from './regulatory--no-heavy-goods-vehicles-or-tractors--g1.png';\r\nimport icon757 from './regulatory--no-heavy-goods-vehicles-or-trailers--g1.png';\r\nimport icon758 from './regulatory--no-horizontal-turn--g1.png';\r\nimport icon759 from './regulatory--no-horn--g1.png';\r\nimport icon760 from './regulatory--no-horn--g2.png';\r\nimport icon761 from './regulatory--no-lane-change-to-left--g1.png';\r\nimport icon762 from './regulatory--no-lane-change-to-right--g1.png';\r\nimport icon763 from './regulatory--no-learner-drivers--g1.png';\r\nimport icon764 from './regulatory--no-left-or-u-turn--g1.png';\r\nimport icon765 from './regulatory--no-left-turn--g1.png';\r\nimport icon766 from './regulatory--no-left-turn--g2.png';\r\nimport icon767 from './regulatory--no-left-turn--g3.png';\r\nimport icon768 from './regulatory--no-left-turn--g4.png';\r\nimport icon769 from './regulatory--no-left-turn--g5.png';\r\nimport icon770 from './regulatory--no-low-speed-vehicles--g1.png';\r\nimport icon771 from './regulatory--no-mopeds-or-bicycles--g1.png';\r\nimport icon772 from './regulatory--no-motor-vehicle-trailers--g1.png';\r\nimport icon773 from './regulatory--no-motor-vehicles--g1.png';\r\nimport icon774 from './regulatory--no-motor-vehicles--g3.png';\r\nimport icon775 from './regulatory--no-motor-vehicles--g4.png';\r\nimport icon776 from './regulatory--no-motor-vehicles--g5.png';\r\nimport icon777 from './regulatory--no-motor-vehicles--g6.png';\r\nimport icon778 from './regulatory--no-motor-vehicles--g7.png';\r\nimport icon779 from './regulatory--no-motor-vehicles-except-motorcycles--g1.png';\r\nimport icon780 from './regulatory--no-motor-vehicles-except-motorcycles--g2.png';\r\nimport icon781 from './regulatory--no-motor-vehicles-except-motorcycles--g3.png';\r\nimport icon782 from './regulatory--no-motor-vehicles-or-bicycles--g1.png';\r\nimport icon783 from './regulatory--no-motor-vehicles-or-buses--g1.png';\r\nimport icon784 from './regulatory--no-motor-vehicles-or-carts--g1.png';\r\nimport icon785 from './regulatory--no-motorcycles--g1.png';\r\nimport icon786 from './regulatory--no-motorcycles--g2.png';\r\nimport icon787 from './regulatory--no-overtaking--g1.png';\r\nimport icon788 from './regulatory--no-overtaking--g2.png';\r\nimport icon789 from './regulatory--no-overtaking--g4.png';\r\nimport icon790 from './regulatory--no-overtaking--g5.png';\r\nimport icon791 from './regulatory--no-overtaking--g6.png';\r\nimport icon792 from './regulatory--no-overtaking--g7.png';\r\nimport icon793 from './regulatory--no-overtaking-atvs--g1.png';\r\nimport icon794 from './regulatory--no-overtaking-by-heavy-goods-vehicles--g1.png';\r\nimport icon795 from './regulatory--no-parking--g1.png';\r\nimport icon796 from './regulatory--no-parking--g2.png';\r\nimport icon797 from './regulatory--no-parking--g3.png';\r\nimport icon798 from './regulatory--no-parking--g4.png';\r\nimport icon799 from './regulatory--no-parking--g5.png';\r\nimport icon800 from './regulatory--no-parking--g6.png';\r\nimport icon801 from './regulatory--no-parking--g7.png';\r\nimport icon802 from './regulatory--no-parking--g8.png';\r\nimport icon803 from './regulatory--no-parking--g9.png';\r\nimport icon804 from './regulatory--no-parking-bicycles-or-motorcycles--g1.png';\r\nimport icon805 from './regulatory--no-parking-bus-stop--g1.png';\r\nimport icon806 from './regulatory--no-parking-or-no-stopping--g1.png';\r\nimport icon807 from './regulatory--no-parking-or-no-stopping--g2.png';\r\nimport icon808 from './regulatory--no-parking-or-no-stopping--g3.png';\r\nimport icon809 from './regulatory--no-parking-or-no-stopping--g4.png';\r\nimport icon810 from './regulatory--no-parking-or-no-stopping--g5.png';\r\nimport icon811 from './regulatory--no-passenger-loading--g1.png';\r\nimport icon812 from './regulatory--no-pedestrians--g1.png';\r\nimport icon813 from './regulatory--no-pedestrians--g2.png';\r\nimport icon814 from './regulatory--no-pedestrians--g3.png';\r\nimport icon815 from './regulatory--no-pedestrians--g4.png';\r\nimport icon816 from './regulatory--no-pedestrians--g5.png';\r\nimport icon817 from './regulatory--no-pedestrians--g6.png';\r\nimport icon818 from './regulatory--no-pedestrians-bicycles-animals-or-hand-carts--g1.png';\r\nimport icon819 from './regulatory--no-pedestrians-or-bicycles--g1.png';\r\nimport icon820 from './regulatory--no-pedestrians-or-bicycles--g2.png';\r\nimport icon821 from './regulatory--no-pedestrians-or-bicycles--g3.png';\r\nimport icon822 from './regulatory--no-rickshaws--g1.png';\r\nimport icon823 from './regulatory--no-rickshaws--g2.png';\r\nimport icon824 from './regulatory--no-rickshaws--g3.png';\r\nimport icon825 from './regulatory--no-right-turn--g1.png';\r\nimport icon826 from './regulatory--no-right-turn--g2.png';\r\nimport icon827 from './regulatory--no-right-turn--g3.png';\r\nimport icon828 from './regulatory--no-right-turn-on-red--g1.png';\r\nimport icon829 from './regulatory--no-skiing--g1.png';\r\nimport icon830 from './regulatory--no-snowmobiles--g1.png';\r\nimport icon831 from './regulatory--no-snowmobiles--g2.png';\r\nimport icon832 from './regulatory--no-snowmobiles-or-atvs--g1.png';\r\nimport icon833 from './regulatory--no-stopping--g1.png';\r\nimport icon834 from './regulatory--no-stopping--g2.png';\r\nimport icon835 from './regulatory--no-stopping--g3.png';\r\nimport icon836 from './regulatory--no-stopping--g5.png';\r\nimport icon837 from './regulatory--no-stopping--g6.png';\r\nimport icon838 from './regulatory--no-stopping--g7.png';\r\nimport icon839 from './regulatory--no-stopping-on-pavement--g1.png';\r\nimport icon840 from './regulatory--no-straight-through--g1.png';\r\nimport icon841 from './regulatory--no-straight-through--g2.png';\r\nimport icon842 from './regulatory--no-studded-snow-chains--g1.png';\r\nimport icon843 from './regulatory--no-through-trucks--g1.png';\r\nimport icon844 from './regulatory--no-tour-buses--g1.png';\r\nimport icon845 from './regulatory--no-tractors--g1.png';\r\nimport icon846 from './regulatory--no-tractors-mopeds-or-bicycles--g1.png';\r\nimport icon847 from './regulatory--no-tractors-or-carts--g1.png';\r\nimport icon848 from './regulatory--no-trailers--g1.png';\r\nimport icon849 from './regulatory--no-tricycles--g1.png';\r\nimport icon850 from './regulatory--no-tricycles-or-hand-carts--g1.png';\r\nimport icon851 from './regulatory--no-turn-on-red--g1.png';\r\nimport icon852 from './regulatory--no-turn-on-red--g2.png';\r\nimport icon853 from './regulatory--no-turn-on-red--g3.png';\r\nimport icon854 from './regulatory--no-turns--g1.png';\r\nimport icon855 from './regulatory--no-turns--g2.png';\r\nimport icon856 from './regulatory--no-two-stage-right-turn-for-mopeds--g1.png';\r\nimport icon857 from './regulatory--no-u-turn--g1.png';\r\nimport icon858 from './regulatory--no-u-turn--g2.png';\r\nimport icon859 from './regulatory--no-u-turn--g3.png';\r\nimport icon860 from './regulatory--no-vehicles-carrying-dangerous-goods--g1.png';\r\nimport icon861 from './regulatory--no-vehicles-carrying-dangerous-goods--g2.png';\r\nimport icon862 from './regulatory--no-vehicles-carrying-dangerous-goods--g3.png';\r\nimport icon863 from './regulatory--no-vehicles-carrying-dangerous-goods--g4.png';\r\nimport icon864 from './regulatory--no-vehicles-carrying-dangerous-water-pollutants--g1.png';\r\nimport icon865 from './regulatory--no-vehicles-carrying-dangerous-water-pollutants--g2.png';\r\nimport icon866 from './regulatory--no-vehicles-carrying-explosives--g1.png';\r\nimport icon867 from './regulatory--no-vehicles-carrying-explosives-or-dangerous-water-pollutants--g1.png';\r\nimport icon868 from './regulatory--one-way-left--g1.png';\r\nimport icon869 from './regulatory--one-way-left--g2.png';\r\nimport icon870 from './regulatory--one-way-left--g3.png';\r\nimport icon871 from './regulatory--one-way-right--g1.png';\r\nimport icon872 from './regulatory--one-way-right--g2.png';\r\nimport icon873 from './regulatory--one-way-right--g3.png';\r\nimport icon874 from './regulatory--one-way-straight--g1.png';\r\nimport icon875 from './regulatory--one-way-straight--g3.png';\r\nimport icon876 from './regulatory--parking-fee-station--g1.png';\r\nimport icon877 from './regulatory--parking-restrictions--g1.png';\r\nimport icon878 from './regulatory--parking-restrictions--g2.png';\r\nimport icon879 from './regulatory--parking-restrictions--g3.png';\r\nimport icon880 from './regulatory--pass-on-either-side--g1.png';\r\nimport icon881 from './regulatory--pass-on-either-side--g2.png';\r\nimport icon882 from './regulatory--pass-on-either-side--g3.png';\r\nimport icon883 from './regulatory--pass-with-care--g1.png';\r\nimport icon884 from './regulatory--passing-lane-ahead--g1.png';\r\nimport icon885 from './regulatory--pedestrians-bicycles-permitted--g1.png';\r\nimport icon886 from './regulatory--pedestrians-keep-left--g1.png';\r\nimport icon887 from './regulatory--pedestrians-only--g1.png';\r\nimport icon888 from './regulatory--pedestrians-only--g2.png';\r\nimport icon889 from './regulatory--pedestrians-only--g3.png';\r\nimport icon890 from './regulatory--pedestrians-priority-zone--g1.png';\r\nimport icon891 from './regulatory--pedestrians-push-button--g1.png';\r\nimport icon892 from './regulatory--pedestrians-push-button--g2.png';\r\nimport icon893 from './regulatory--priority-over-oncoming-vehicles--g1.png';\r\nimport icon894 from './regulatory--priority-over-oncoming-vehicles--g2.png';\r\nimport icon895 from './regulatory--priority-road--g1.png';\r\nimport icon896 from './regulatory--priority-road--g2.png';\r\nimport icon897 from './regulatory--radar-enforced--g1.png';\r\nimport icon898 from './regulatory--reserved-parking--g1.png';\r\nimport icon899 from './regulatory--reversible-lanes--g1.png';\r\nimport icon900 from './regulatory--reversible-lanes--g2.png';\r\nimport icon901 from './regulatory--road-closed--g1.png';\r\nimport icon902 from './regulatory--road-closed--g2.png';\r\nimport icon903 from './regulatory--road-closed-to-vehicles--g1.png';\r\nimport icon904 from './regulatory--road-closed-to-vehicles--g3.png';\r\nimport icon905 from './regulatory--roundabout--g1.png';\r\nimport icon906 from './regulatory--roundabout--g2.png';\r\nimport icon907 from './regulatory--roundabout--g3.png';\r\nimport icon908 from './regulatory--shared-path-bicycles-and-pedestrians--g1.png';\r\nimport icon909 from './regulatory--shared-path-pedestrians-and-bicycles--g1.png';\r\nimport icon910 from './regulatory--sidewalk-closed--g1.png';\r\nimport icon911 from './regulatory--slanted-parking--g1.png';\r\nimport icon912 from './regulatory--snow-chains--g1.png';\r\nimport icon913 from './regulatory--snow-chains--g2.png';\r\nimport icon914 from './regulatory--snow-chains--g3.png';\r\nimport icon915 from './regulatory--snowmobiles-only--g1.png';\r\nimport icon916 from './regulatory--snowmobiles-permitted--g1.png';\r\nimport icon917 from './regulatory--speed-limit-zone--g1.png';\r\nimport icon918 from './regulatory--speeding-fines-increased--g1.png';\r\nimport icon919 from './regulatory--state-route--g1.png';\r\nimport icon920 from './regulatory--stay-in-lane--g1.png';\r\nimport icon921 from './regulatory--stop--g1.png';\r\nimport icon922 from './regulatory--stop--g2.png';\r\nimport icon923 from './regulatory--stop--g3.png';\r\nimport icon924 from './regulatory--stop--g4.png';\r\nimport icon925 from './regulatory--stop--g5.png';\r\nimport icon926 from './regulatory--stop--g6.png';\r\nimport icon927 from './regulatory--stop--g7.png';\r\nimport icon928 from './regulatory--stop--g8.png';\r\nimport icon929 from './regulatory--stop--g9.png';\r\nimport icon930 from './regulatory--stop--g10.png';\r\nimport icon931 from './regulatory--stop-here-on-red-or-flashing-light--g1.png';\r\nimport icon932 from './regulatory--stop-here-on-red-or-flashing-light--g2.png';\r\nimport icon933 from './regulatory--stop-signals--g1.png';\r\nimport icon934 from './regulatory--stop-signals--g2.png';\r\nimport icon935 from './regulatory--tanks-only--g1.png';\r\nimport icon936 from './regulatory--taxi-only--g1.png';\r\nimport icon937 from './regulatory--text--g1.png';\r\nimport icon938 from './regulatory--text--g2.png';\r\nimport icon939 from './regulatory--toll-pass-only--g1.png';\r\nimport icon940 from './regulatory--tractors-only--g1.png';\r\nimport icon941 from './regulatory--traffic-signal-photo-enforced--g1.png';\r\nimport icon942 from './regulatory--trams-and-buses-only--g1.png';\r\nimport icon943 from './regulatory--trams-only--g1.png';\r\nimport icon944 from './regulatory--triple-lanes--g1.png';\r\nimport icon945 from './regulatory--triple-lanes-go-straight-center-lane--g1.png';\r\nimport icon946 from './regulatory--triple-lanes-turn-left-center-lane--g1.png';\r\nimport icon947 from './regulatory--triple-lanes-turn-right-center-lane--g1.png';\r\nimport icon948 from './regulatory--truck-route--g1.png';\r\nimport icon949 from './regulatory--truck-speed-limit-5--g1.png';\r\nimport icon950 from './regulatory--truck-speed-limit-10--g1.png';\r\nimport icon951 from './regulatory--truck-speed-limit-15--g1.png';\r\nimport icon952 from './regulatory--truck-speed-limit-20--g1.png';\r\nimport icon953 from './regulatory--truck-speed-limit-25--g1.png';\r\nimport icon954 from './regulatory--truck-speed-limit-30--g1.png';\r\nimport icon955 from './regulatory--truck-speed-limit-35--g1.png';\r\nimport icon956 from './regulatory--truck-speed-limit-40--g1.png';\r\nimport icon957 from './regulatory--truck-speed-limit-45--g1.png';\r\nimport icon958 from './regulatory--truck-speed-limit-50--g1.png';\r\nimport icon959 from './regulatory--truck-speed-limit-55--g1.png';\r\nimport icon960 from './regulatory--truck-speed-limit-60--g1.png';\r\nimport icon961 from './regulatory--truck-speed-limit-65--g1.png';\r\nimport icon962 from './regulatory--truck-speed-limit-70--g1.png';\r\nimport icon963 from './regulatory--truck-speed-limit-75--g1.png';\r\nimport icon964 from './regulatory--truck-speed-limit-80--g1.png';\r\nimport icon965 from './regulatory--truck-speed-limit-85--g1.png';\r\nimport icon966 from './regulatory--trucks-and-buses-only--g1.png';\r\nimport icon967 from './regulatory--trucks-on-right--g1.png';\r\nimport icon968 from './regulatory--trucks-only--g1.png';\r\nimport icon969 from './regulatory--turn-left--g1.png';\r\nimport icon970 from './regulatory--turn-left--g2.png';\r\nimport icon971 from './regulatory--turn-left--g3.png';\r\nimport icon972 from './regulatory--turn-left-ahead--g1.png';\r\nimport icon973 from './regulatory--turn-left-ahead--g2.png';\r\nimport icon974 from './regulatory--turn-left-or-right--g1.png';\r\nimport icon975 from './regulatory--turn-left-or-right--g2.png';\r\nimport icon976 from './regulatory--turn-left-or-right--g3.png';\r\nimport icon977 from './regulatory--turn-left-or-u-turn--g1.png';\r\nimport icon978 from './regulatory--turn-right--g1.png';\r\nimport icon979 from './regulatory--turn-right--g2.png';\r\nimport icon980 from './regulatory--turn-right--g3.png';\r\nimport icon981 from './regulatory--turn-right-ahead--g1.png';\r\nimport icon982 from './regulatory--turn-right-ahead--g2.png';\r\nimport icon983 from './regulatory--turning-vehicles-yield-to-pedestrians--g1.png';\r\nimport icon984 from './regulatory--two-stage-right-turn-for-mopeds--g1.png';\r\nimport icon985 from './regulatory--two-way--g1.png';\r\nimport icon986 from './regulatory--u-turn--g1.png';\r\nimport icon987 from './regulatory--u-turn--g2.png';\r\nimport icon988 from './regulatory--u-turn--g3.png';\r\nimport icon989 from './regulatory--use-crosswalk--g1.png';\r\nimport icon990 from './regulatory--vehicles-carrying-dangerous-goods-only--g1.png';\r\nimport icon991 from './regulatory--vehicles-carrying-dangerous-goods-permitted--g1.png';\r\nimport icon992 from './regulatory--vehicles-carrying-explosives-only--g1.png';\r\nimport icon993 from './regulatory--vehicles-carrying-hazardous-goods-permitted--g1.png';\r\nimport icon994 from './regulatory--vehicles-only--g1.png';\r\nimport icon995 from './regulatory--wear-seat-belt--g1.png';\r\nimport icon996 from './regulatory--wear-seat-belt--g2.png';\r\nimport icon997 from './regulatory--wear-seat-belt--g3.png';\r\nimport icon998 from './regulatory--weight-limit--g1.png';\r\nimport icon999 from './regulatory--weight-limit--g2.png';\r\nimport icon1000 from './regulatory--weight-limit--g3.png';\r\nimport icon1001 from './regulatory--weight-limit--g4.png';\r\nimport icon1002 from './regulatory--weight-limit--g5.png';\r\nimport icon1003 from './regulatory--weight-limit--g6.png';\r\nimport icon1004 from './regulatory--weight-limit--g7.png';\r\nimport icon1005 from './regulatory--weight-limit-per-axle--g1.png';\r\nimport icon1006 from './regulatory--weight-limit-per-tandem-axle--g1.png';\r\nimport icon1007 from './regulatory--weight-limit-with-trucks--g1.png';\r\nimport icon1008 from './regulatory--width-limit--g1.png';\r\nimport icon1009 from './regulatory--wrong-way--g1.png';\r\nimport icon1010 from './regulatory--yield--g1.png';\r\nimport icon1011 from './regulatory--yield-or-stop-for-pedestrians--g1.png';\r\nimport icon1012 from './regulatory--your-speed--g1.png';\r\nimport icon1013 from './warning--accident-area--g1.png';\r\nimport icon1014 from './warning--accident-area--g2.png';\r\nimport icon1015 from './warning--accident-area--g3.png';\r\nimport icon1016 from './warning--accident-area--g4.png';\r\nimport icon1017 from './warning--accident-area--g5.png';\r\nimport icon1018 from './warning--accident-area--g6.png';\r\nimport icon1019 from './warning--accident-area--g7.png';\r\nimport icon1020 from './warning--accident-area--g8.png';\r\nimport icon1021 from './warning--added-lane-from-entering-roadway--g1.png';\r\nimport icon1022 from './warning--added-lane-from-entering-roadway--g2.png';\r\nimport icon1023 from './warning--added-lane-left--g1.png';\r\nimport icon1024 from './warning--added-lane-right--g1.png';\r\nimport icon1025 from './warning--animal-drawn-vehicles--g1.png';\r\nimport icon1026 from './warning--arch-bridge--g1.png';\r\nimport icon1027 from './warning--atv-and-snowmobiles--g1.png';\r\nimport icon1028 from './warning--atv-crossing--g1.png';\r\nimport icon1029 from './warning--atv-crossing--g2.png';\r\nimport icon1030 from './warning--axle-restriction--g1.png';\r\nimport icon1031 from './warning--bear-crossing--g1.png';\r\nimport icon1032 from './warning--bear-crossing--g2.png';\r\nimport icon1033 from './warning--bicycles-and-others--g1.png';\r\nimport icon1034 from './warning--bicycles-caution-on-rail-tracks--g1.png';\r\nimport icon1035 from './warning--bicycles-crossing--g1.png';\r\nimport icon1036 from './warning--bicycles-crossing--g2.png';\r\nimport icon1037 from './warning--bicycles-crossing--g3.png';\r\nimport icon1038 from './warning--bicycles-crossing--g4.png';\r\nimport icon1039 from './warning--bollard--g1.png';\r\nimport icon1040 from './warning--bridge--g1.png';\r\nimport icon1041 from './warning--bridge--g2.png';\r\nimport icon1042 from './warning--bus-stop-ahead--g1.png';\r\nimport icon1043 from './warning--bus-stop-ahead--g2.png';\r\nimport icon1044 from './warning--bus-stop-ahead--g3.png';\r\nimport icon1045 from './warning--camel-crossing--g1.png';\r\nimport icon1046 from './warning--camel-crossing--g2.png';\r\nimport icon1047 from './warning--camera--g1.png';\r\nimport icon1048 from './warning--camera--g2.png';\r\nimport icon1049 from './warning--carts--g1.png';\r\nimport icon1050 from './warning--carts--g2.png';\r\nimport icon1051 from './warning--checkpoint--g1.png';\r\nimport icon1052 from './warning--children--g1.png';\r\nimport icon1053 from './warning--children--g2.png';\r\nimport icon1054 from './warning--children--g3.png';\r\nimport icon1055 from './warning--children--g4.png';\r\nimport icon1056 from './warning--children--g6.png';\r\nimport icon1057 from './warning--cliff--g1.png';\r\nimport icon1058 from './warning--cliff--g2.png';\r\nimport icon1059 from './warning--closed-lane-in-triple-lanes--g1.png';\r\nimport icon1060 from './warning--closed-lane-in-triple-lanes--g2.png';\r\nimport icon1061 from './warning--construction-ahead--g1.png';\r\nimport icon1062 from './warning--crossroads--g1.png';\r\nimport icon1063 from './warning--crossroads--g2.png';\r\nimport icon1064 from './warning--crossroads--g3.png';\r\nimport icon1065 from './warning--crossroads--g4.png';\r\nimport icon1066 from './warning--crossroads--g5.png';\r\nimport icon1067 from './warning--crossroads--g6.png';\r\nimport icon1068 from './warning--crossroads-with-priority-to-the-right--g1.png';\r\nimport icon1069 from './warning--curve-left--g1.png';\r\nimport icon1070 from './warning--curve-left--g2.png';\r\nimport icon1071 from './warning--curve-left--g3.png';\r\nimport icon1072 from './warning--curve-left-with-junction--g1.png';\r\nimport icon1073 from './warning--curve-out-intersection-left--g1.png';\r\nimport icon1074 from './warning--curve-out-intersection-right--g1.png';\r\nimport icon1075 from './warning--curve-right--g1.png';\r\nimport icon1076 from './warning--curve-right--g2.png';\r\nimport icon1077 from './warning--curve-right--g3.png';\r\nimport icon1078 from './warning--curve-right-with-junction--g1.png';\r\nimport icon1079 from './warning--dangerous-crosswinds-left--g1.png';\r\nimport icon1080 from './warning--dangerous-crosswinds-left--g2.png';\r\nimport icon1081 from './warning--dangerous-crosswinds-left--g4.png';\r\nimport icon1082 from './warning--dangerous-crosswinds-right--g1.png';\r\nimport icon1083 from './warning--dangerous-crosswinds-right--g2.png';\r\nimport icon1084 from './warning--dangerous-crosswinds-right--g3.png';\r\nimport icon1085 from './warning--dangerous-crosswinds-right--g4.png';\r\nimport icon1086 from './warning--dead-end--g1.png';\r\nimport icon1087 from './warning--dead-end--g2.png';\r\nimport icon1088 from './warning--dead-end--g3.png';\r\nimport icon1089 from './warning--dead-end-go-left--g1.png';\r\nimport icon1090 from './warning--dead-end-go-right--g1.png';\r\nimport icon1091 from './warning--descent-or-climbing-lanes-in-triple-lanes--g1.png';\r\nimport icon1092 from './warning--detour-ahead--g1.png';\r\nimport icon1093 from './warning--detour-or-construction-ahead--g1.png';\r\nimport icon1094 from './warning--dip--g1.png';\r\nimport icon1095 from './warning--dip--g2.png';\r\nimport icon1096 from './warning--disabled-persons-crossing--g1.png';\r\nimport icon1097 from './warning--disabled-persons-crossing--g2.png';\r\nimport icon1098 from './warning--divided-highway--g1.png';\r\nimport icon1099 from './warning--divided-highway--g2.png';\r\nimport icon1100 from './warning--divided-highway--g3.png';\r\nimport icon1101 from './warning--divided-highway--g4.png';\r\nimport icon1102 from './warning--divided-highway--g5.png';\r\nimport icon1103 from './warning--divided-highway--g6.png';\r\nimport icon1104 from './warning--divided-highway--g7.png';\r\nimport icon1105 from './warning--divided-highway--g8.png';\r\nimport icon1106 from './warning--divided-highway--g9.png';\r\nimport icon1107 from './warning--divided-highway-ends--g1.png';\r\nimport icon1108 from './warning--divided-highway-ends--g2.png';\r\nimport icon1109 from './warning--divided-highway-ends--g3.png';\r\nimport icon1110 from './warning--divided-highway-ends--g4.png';\r\nimport icon1111 from './warning--divided-highway-on-left--g1.png';\r\nimport icon1112 from './warning--divided-highway-on-left--g2.png';\r\nimport icon1113 from './warning--divided-highway-on-right--g1.png';\r\nimport icon1114 from './warning--divided-highway-on-right--g2.png';\r\nimport icon1115 from './warning--divided-highway-to-left--g1.png';\r\nimport icon1116 from './warning--divided-highway-to-right--g1.png';\r\nimport icon1117 from './warning--domestic-animals--g1.png';\r\nimport icon1118 from './warning--domestic-animals--g2.png';\r\nimport icon1119 from './warning--domestic-animals--g3.png';\r\nimport icon1120 from './warning--domestic-animals--g4.png';\r\nimport icon1121 from './warning--domestic-animals--g5.png';\r\nimport icon1122 from './warning--domestic-animals--g6.png';\r\nimport icon1123 from './warning--domestic-animals--g7.png';\r\nimport icon1124 from './warning--domestic-animals--g8.png';\r\nimport icon1125 from './warning--double-curve-first-left--g1.png';\r\nimport icon1126 from './warning--double-curve-first-left--g2.png';\r\nimport icon1127 from './warning--double-curve-first-right--g1.png';\r\nimport icon1128 from './warning--double-curve-first-right--g2.png';\r\nimport icon1129 from './warning--double-descent--g1.png';\r\nimport icon1130 from './warning--double-reverse-curve-left--g1.png';\r\nimport icon1131 from './warning--double-reverse-curve-left--g2.png';\r\nimport icon1132 from './warning--double-reverse-curve-right--g1.png';\r\nimport icon1133 from './warning--double-reverse-curve-right--g2.png';\r\nimport icon1134 from './warning--double-side-roads-left--g1.png';\r\nimport icon1135 from './warning--double-side-roads-left--g3.png';\r\nimport icon1136 from './warning--double-side-roads-right--g1.png';\r\nimport icon1137 from './warning--double-side-roads-right--g3.png';\r\nimport icon1138 from './warning--double-turn-first-left--g1.png';\r\nimport icon1139 from './warning--double-turn-first-right--g1.png';\r\nimport icon1140 from './warning--dual-lanes-all-directions-on-left--g1.png';\r\nimport icon1141 from './warning--dual-lanes-all-directions-on-right--g1.png';\r\nimport icon1142 from './warning--dual-lanes-go-straight-or-turn-left--g1.png';\r\nimport icon1143 from './warning--dual-lanes-go-straight-or-turn-right--g1.png';\r\nimport icon1144 from './warning--dual-lanes-left-turn--g1.png';\r\nimport icon1145 from './warning--dual-lanes-left-turn-or-go-straight--g1.png';\r\nimport icon1146 from './warning--dual-lanes-right-turn--g1.png';\r\nimport icon1147 from './warning--dual-lanes-right-turn-or-go-straight--g1.png';\r\nimport icon1148 from './warning--dual-lanes-turn-left--g1.png';\r\nimport icon1149 from './warning--dual-lanes-turn-left-or-right--g1.png';\r\nimport icon1150 from './warning--dual-lanes-turn-left-or-right--g2.png';\r\nimport icon1151 from './warning--dual-lanes-turn-left-or-right--g3.png';\r\nimport icon1152 from './warning--dual-lanes-turn-left-or-right--g4.png';\r\nimport icon1153 from './warning--dual-lanes-turn-right--g1.png';\r\nimport icon1154 from './warning--dual-path-cyclists-and-pedestrians--g1.png';\r\nimport icon1155 from './warning--electricity--g1.png';\r\nimport icon1156 from './warning--electricity--g2.png';\r\nimport icon1157 from './warning--elephant-crossing--g1.png';\r\nimport icon1158 from './warning--emergency-vehicles--g1.png';\r\nimport icon1159 from './warning--emu-crossing--g1.png';\r\nimport icon1160 from './warning--emu-crossing--g2.png';\r\nimport icon1161 from './warning--entering-roadway-merge--g1.png';\r\nimport icon1162 from './warning--entering-roadway-merge--g2.png';\r\nimport icon1163 from './warning--equestrians-crossing--g1.png';\r\nimport icon1164 from './warning--equestrians-crossing--g2.png';\r\nimport icon1165 from './warning--expressway--g1.png';\r\nimport icon1166 from './warning--falling-rocks-or-debris-left--g1.png';\r\nimport icon1167 from './warning--falling-rocks-or-debris-left--g2.png';\r\nimport icon1168 from './warning--falling-rocks-or-debris-left--g3.png';\r\nimport icon1169 from './warning--falling-rocks-or-debris-left--g4.png';\r\nimport icon1170 from './warning--falling-rocks-or-debris-right--g1.png';\r\nimport icon1171 from './warning--falling-rocks-or-debris-right--g2.png';\r\nimport icon1172 from './warning--falling-rocks-or-debris-right--g3.png';\r\nimport icon1173 from './warning--falling-rocks-or-debris-right--g4.png';\r\nimport icon1174 from './warning--ferry--g1.png';\r\nimport icon1175 from './warning--flaggers-in-road--g1.png';\r\nimport icon1176 from './warning--flaggers-in-road--g2.png';\r\nimport icon1177 from './warning--foggy-road--g1.png';\r\nimport icon1178 from './warning--foggy-road--g2.png';\r\nimport icon1179 from './warning--ford--g1.png';\r\nimport icon1180 from './warning--forest--g1.png';\r\nimport icon1181 from './warning--fresh-oil--g1.png';\r\nimport icon1182 from './warning--frog-crossing--g1.png';\r\nimport icon1183 from './warning--gate--g1.png';\r\nimport icon1184 from './warning--gate--g2.png';\r\nimport icon1185 from './warning--gate-left--g1.png';\r\nimport icon1186 from './warning--gate-right--g1.png';\r\nimport icon1187 from './warning--go-left--g1.png';\r\nimport icon1188 from './warning--go-right--g1.png';\r\nimport icon1189 from './warning--golf-carts-crossing--g1.png';\r\nimport icon1190 from './warning--gravel-road-surface--g1.png';\r\nimport icon1191 from './warning--hairpin-curve-left--g1.png';\r\nimport icon1192 from './warning--hairpin-curve-left--g2.png';\r\nimport icon1193 from './warning--hairpin-curve-left--g3.png';\r\nimport icon1194 from './warning--hairpin-curve-right--g1.png';\r\nimport icon1195 from './warning--hairpin-curve-right--g3.png';\r\nimport icon1196 from './warning--height-restriction--g2.png';\r\nimport icon1197 from './warning--height-restriction--g3.png';\r\nimport icon1198 from './warning--height-restriction--g4.png';\r\nimport icon1199 from './warning--height-restriction--g5.png';\r\nimport icon1200 from './warning--horizontal-alignment-left--g1.png';\r\nimport icon1201 from './warning--horizontal-alignment-left--g3.png';\r\nimport icon1202 from './warning--horizontal-alignment-right--g1.png';\r\nimport icon1203 from './warning--horizontal-alignment-right--g3.png';\r\nimport icon1204 from './warning--horse-crossing--g1.png';\r\nimport icon1205 from './warning--icy-road--g1.png';\r\nimport icon1206 from './warning--junction-with-a-side-road-acute-left--g1.png';\r\nimport icon1207 from './warning--junction-with-a-side-road-acute-left--g2.png';\r\nimport icon1208 from './warning--junction-with-a-side-road-acute-right--g1.png';\r\nimport icon1209 from './warning--junction-with-a-side-road-acute-right--g2.png';\r\nimport icon1210 from './warning--junction-with-a-side-road-perpendicular-left--g1.png';\r\nimport icon1211 from './warning--junction-with-a-side-road-perpendicular-left--g2.png';\r\nimport icon1212 from './warning--junction-with-a-side-road-perpendicular-left--g3.png';\r\nimport icon1213 from './warning--junction-with-a-side-road-perpendicular-left--g4.png';\r\nimport icon1214 from './warning--junction-with-a-side-road-perpendicular-right--g1.png';\r\nimport icon1215 from './warning--junction-with-a-side-road-perpendicular-right--g2.png';\r\nimport icon1216 from './warning--junction-with-a-side-road-perpendicular-right--g3.png';\r\nimport icon1217 from './warning--junction-with-a-side-road-perpendicular-right--g4.png';\r\nimport icon1218 from './warning--junction-with-merge-from-left--g1.png';\r\nimport icon1219 from './warning--junction-with-merge-from-right--g1.png';\r\nimport icon1220 from './warning--junction-with-side-roads--g1.png';\r\nimport icon1221 from './warning--kangaloo-crossing--g1.png';\r\nimport icon1222 from './warning--keep-distance--g1.png';\r\nimport icon1223 from './warning--keep-left--g1.png';\r\nimport icon1224 from './warning--keep-right--g1.png';\r\nimport icon1225 from './warning--kiwi-crossing--g1.png';\r\nimport icon1226 from './warning--kiwi-crossing--g2.png';\r\nimport icon1227 from './warning--koala-crossing--g1.png';\r\nimport icon1228 from './warning--koala-crossing--g2.png';\r\nimport icon1229 from './warning--koala-crossing--g3.png';\r\nimport icon1230 from './warning--koala-crossing--g4.png';\r\nimport icon1231 from './warning--lane-closed-in-dual-lanes-left--g1.png';\r\nimport icon1232 from './warning--lane-closed-in-dual-lanes-left--g2.png';\r\nimport icon1233 from './warning--lane-closed-in-dual-lanes-right--g1.png';\r\nimport icon1234 from './warning--lane-closed-in-dual-lanes-right--g2.png';\r\nimport icon1235 from './warning--length-restriction--g1.png';\r\nimport icon1236 from './warning--length-restriction--g2.png';\r\nimport icon1237 from './warning--light-rail-transit-vehicles--g1.png';\r\nimport icon1238 from './warning--limited-lighting-under-trees--g1.png';\r\nimport icon1239 from './warning--logging-vehicles--g1.png';\r\nimport icon1240 from './warning--loop-270-degree--g1.png';\r\nimport icon1241 from './warning--loop-pretzel--g1.png';\r\nimport icon1242 from './warning--loose-road-surface--g1.png';\r\nimport icon1243 from './warning--loose-road-surface--g2.png';\r\nimport icon1244 from './warning--loose-road-surface--g3.png';\r\nimport icon1245 from './warning--loose-road-surface--g4.png';\r\nimport icon1246 from './warning--low-flying-aircraft--g1.png';\r\nimport icon1247 from './warning--low-flying-aircraft--g2.png';\r\nimport icon1248 from './warning--low-flying-aircraft--g3.png';\r\nimport icon1249 from './warning--low-flying-aircraft--g4.png';\r\nimport icon1250 from './warning--low-flying-aircraft--g5.png';\r\nimport icon1251 from './warning--low-flying-aircraft--g6.png';\r\nimport icon1252 from './warning--low-flying-aircraft--g7.png';\r\nimport icon1253 from './warning--low-flying-aircraft--g8.png';\r\nimport icon1254 from './warning--low-ground-clearance--g1.png';\r\nimport icon1255 from './warning--low-ground-clearance--g2.png';\r\nimport icon1256 from './warning--low-ground-clearance--g3.png';\r\nimport icon1257 from './warning--monkey-crossing--g1.png';\r\nimport icon1258 from './warning--motorcycles-crossing--g1.png';\r\nimport icon1259 from './warning--narrow-bridge--g1.png';\r\nimport icon1260 from './warning--narrow-bridge--g2.png';\r\nimport icon1261 from './warning--narrow-bridge--g3.png';\r\nimport icon1262 from './warning--no-passing-zone--g1.png';\r\nimport icon1263 from './warning--no-passing-zone--g2.png';\r\nimport icon1264 from './warning--occupied-lanes--g1.png';\r\nimport icon1265 from './warning--offset-roads--g1.png';\r\nimport icon1266 from './warning--offset-roads--g2.png';\r\nimport icon1267 from './warning--offset-roads--g3.png';\r\nimport icon1268 from './warning--offset-roads--g4.png';\r\nimport icon1269 from './warning--opening-or-swing-bridge--g1.png';\r\nimport icon1270 from './warning--opening-or-swing-bridge--g2.png';\r\nimport icon1271 from './warning--other-danger--g1.png';\r\nimport icon1272 from './warning--other-danger--g2.png';\r\nimport icon1273 from './warning--other-danger--g3.png';\r\nimport icon1274 from './warning--panda-crossing--g1.png';\r\nimport icon1275 from './warning--pass-left-or-right--g1.png';\r\nimport icon1276 from './warning--pass-left-or-right--g2.png';\r\nimport icon1277 from './warning--pass-left-or-right--g3.png';\r\nimport icon1278 from './warning--pavement-ahead--g1.png';\r\nimport icon1279 from './warning--pavement-ends--g1.png';\r\nimport icon1280 from './warning--pavement-ends--g2.png';\r\nimport icon1281 from './warning--pavement-ends--g3.png';\r\nimport icon1282 from './warning--pavement-ends--g4.png';\r\nimport icon1283 from './warning--pavement-ends--g5.png';\r\nimport icon1284 from './warning--pedestrians-crossing--g1.png';\r\nimport icon1285 from './warning--pedestrians-crossing--g4.png';\r\nimport icon1286 from './warning--pedestrians-crossing--g5.png';\r\nimport icon1287 from './warning--pedestrians-crossing--g6.png';\r\nimport icon1288 from './warning--pedestrians-crossing--g7.png';\r\nimport icon1289 from './warning--pedestrians-crossing--g8.png';\r\nimport icon1290 from './warning--pedestrians-crossing--g9.png';\r\nimport icon1291 from './warning--pedestrians-crossing--g10.png';\r\nimport icon1292 from './warning--pedestrians-crossing--g11.png';\r\nimport icon1293 from './warning--pedestrians-crossing--g12.png';\r\nimport icon1294 from './warning--playground--g1.png';\r\nimport icon1295 from './warning--playground--g3.png';\r\nimport icon1296 from './warning--polar-bear-crossing--g1.png';\r\nimport icon1297 from './warning--quay-or-river-bank--g1.png';\r\nimport icon1298 from './warning--quay-or-river-bank--g2.png';\r\nimport icon1299 from './warning--quay-or-river-bank--g3.png';\r\nimport icon1300 from './warning--quay-or-river-bank--g4.png';\r\nimport icon1301 from './warning--rabbit-crossing--g1.png';\r\nimport icon1302 from './warning--raccoon-crossing--g1.png';\r\nimport icon1303 from './warning--railroad-crossing--g1.png';\r\nimport icon1304 from './warning--railroad-crossing--g2.png';\r\nimport icon1305 from './warning--railroad-crossing--g3.png';\r\nimport icon1306 from './warning--railroad-crossing--g4.png';\r\nimport icon1307 from './warning--railroad-crossing-with-barriers--g1.png';\r\nimport icon1308 from './warning--railroad-crossing-with-barriers--g2.png';\r\nimport icon1309 from './warning--railroad-crossing-with-barriers--g3.png';\r\nimport icon1310 from './warning--railroad-crossing-with-barriers--g4.png';\r\nimport icon1311 from './warning--railroad-crossing-with-barriers--g5.png';\r\nimport icon1312 from './warning--railroad-crossing-with-barriers--g6.png';\r\nimport icon1313 from './warning--railroad-crossing-with-barriers--g7.png';\r\nimport icon1314 from './warning--railroad-crossing-without-barriers--g1.png';\r\nimport icon1315 from './warning--railroad-crossing-without-barriers--g2.png';\r\nimport icon1316 from './warning--railroad-crossing-without-barriers--g3.png';\r\nimport icon1317 from './warning--railroad-crossing-without-barriers--g4.png';\r\nimport icon1318 from './warning--railroad-crossing-without-barriers--g5.png';\r\nimport icon1319 from './warning--railroad-crossing-without-barriers--g6.png';\r\nimport icon1320 from './warning--railroad-intersection--g1.png';\r\nimport icon1321 from './warning--railroad-intersection--g2.png';\r\nimport icon1322 from './warning--railroad-intersection--g3.png';\r\nimport icon1323 from './warning--railroad-intersection--g4.png';\r\nimport icon1324 from './warning--railroad-intersection--g5.png';\r\nimport icon1325 from './warning--railroad-intersection--g6.png';\r\nimport icon1326 from './warning--railroad-intersection--g7.png';\r\nimport icon1327 from './warning--railroad-intersection--g8.png';\r\nimport icon1328 from './warning--railroad-intersection--g9.png';\r\nimport icon1329 from './warning--ramp-closed--g1.png';\r\nimport icon1330 from './warning--reduced-maximum-speed-limit--g1.png';\r\nimport icon1331 from './warning--reserved-lane--g1.png';\r\nimport icon1332 from './warning--restricted-zone--g1.png';\r\nimport icon1333 from './warning--reversible-lanes--g1.png';\r\nimport icon1334 from './warning--reversible-lanes--g2.png';\r\nimport icon1335 from './warning--rickshaws-crossing--g1.png';\r\nimport icon1336 from './warning--road-blocks--g1.png';\r\nimport icon1337 from './warning--road-bump--g1.png';\r\nimport icon1338 from './warning--road-bump--g2.png';\r\nimport icon1339 from './warning--road-bump--g3.png';\r\nimport icon1340 from './warning--road-bump-with-speed-limit--g1.png';\r\nimport icon1341 from './warning--road-closed--g3.png';\r\nimport icon1342 from './warning--road-narrows--g1.png';\r\nimport icon1343 from './warning--road-narrows--g2.png';\r\nimport icon1344 from './warning--road-narrows-left--g1.png';\r\nimport icon1345 from './warning--road-narrows-left--g2.png';\r\nimport icon1346 from './warning--road-narrows-left-ahead--g1.png';\r\nimport icon1347 from './warning--road-narrows-right--g1.png';\r\nimport icon1348 from './warning--road-narrows-right--g2.png';\r\nimport icon1349 from './warning--road-narrows-right-ahead--g1.png';\r\nimport icon1350 from './warning--road-toll-ahead--g1.png';\r\nimport icon1351 from './warning--road-widens--g1.png';\r\nimport icon1352 from './warning--road-widens-left--g1.png';\r\nimport icon1353 from './warning--road-widens-right--g1.png';\r\nimport icon1354 from './warning--roadworks--g1.png';\r\nimport icon1355 from './warning--roadworks--g2.png';\r\nimport icon1356 from './warning--roadworks--g3.png';\r\nimport icon1357 from './warning--roadworks--g5.png';\r\nimport icon1358 from './warning--roadworks--g6.png';\r\nimport icon1359 from './warning--roadworks--g8.png';\r\nimport icon1360 from './warning--roadworks--g9.png';\r\nimport icon1361 from './warning--roadworks--g10.png';\r\nimport icon1362 from './warning--roadworks--g11.png';\r\nimport icon1363 from './warning--roadworks-go-left-or-straight--g1.png';\r\nimport icon1364 from './warning--roadworks-go-right-or-straight--g1.png';\r\nimport icon1365 from './warning--roundabout--g1.png';\r\nimport icon1366 from './warning--roundabout--g2.png';\r\nimport icon1367 from './warning--roundabout--g3.png';\r\nimport icon1368 from './warning--roundabout--g4.png';\r\nimport icon1369 from './warning--roundabout--g5.png';\r\nimport icon1370 from './warning--roundabout--g6.png';\r\nimport icon1371 from './warning--roundabout--g7.png';\r\nimport icon1372 from './warning--ruts--g1.png';\r\nimport icon1373 from './warning--sand--g1.png';\r\nimport icon1374 from './warning--sand-drift--g1.png';\r\nimport icon1375 from './warning--school-zone--g2.png';\r\nimport icon1376 from './warning--severe-weather--g1.png';\r\nimport icon1377 from './warning--shared-lane-motorcycles-bicycles--g1.png';\r\nimport icon1378 from './warning--sharp-turn--g1.png';\r\nimport icon1379 from './warning--single-reverse-curve--g1.png';\r\nimport icon1380 from './warning--skewed-t-roads-left--g1.png';\r\nimport icon1381 from './warning--skewed-t-roads-left--g2.png';\r\nimport icon1382 from './warning--skewed-t-roads-left--g3.png';\r\nimport icon1383 from './warning--skewed-t-roads-right--g1.png';\r\nimport icon1384 from './warning--skewed-t-roads-right--g2.png';\r\nimport icon1385 from './warning--skewed-t-roads-right--g3.png';\r\nimport icon1386 from './warning--skiers--g1.png';\r\nimport icon1387 from './warning--skiers--g2.png';\r\nimport icon1388 from './warning--skiers--g3.png';\r\nimport icon1389 from './warning--slippery-bicycles--g1.png';\r\nimport icon1390 from './warning--slippery-motorcycles--g1.png';\r\nimport icon1391 from './warning--slippery-motorcycles--g2.png';\r\nimport icon1392 from './warning--slippery-road-surface--g1.png';\r\nimport icon1393 from './warning--slippery-road-surface--g2.png';\r\nimport icon1394 from './warning--slow--g1.png';\r\nimport icon1395 from './warning--snow-tractors--g1.png';\r\nimport icon1396 from './warning--snowmobiles--g1.png';\r\nimport icon1397 from './warning--snowmobiles--g2.png';\r\nimport icon1398 from './warning--snowmobiles--g3.png';\r\nimport icon1399 from './warning--snowmobiles-and-others--g1.png';\r\nimport icon1400 from './warning--soft-road-surface--g1.png';\r\nimport icon1401 from './warning--soft-road-surface--g2.png';\r\nimport icon1402 from './warning--soft-shoulder--g1.png';\r\nimport icon1403 from './warning--soft-shoulder--g2.png';\r\nimport icon1404 from './warning--soft-shoulder--g3.png';\r\nimport icon1405 from './warning--soft-shoulder--g4.png';\r\nimport icon1406 from './warning--speed-camera--g1.png';\r\nimport icon1407 from './warning--steep-ascent--g1.png';\r\nimport icon1408 from './warning--steep-ascent--g2.png';\r\nimport icon1409 from './warning--steep-ascent--g3.png';\r\nimport icon1410 from './warning--steep-ascent--g4.png';\r\nimport icon1411 from './warning--steep-ascent-and-descent--g1.png';\r\nimport icon1412 from './warning--steep-descent--g1.png';\r\nimport icon1413 from './warning--steep-descent--g2.png';\r\nimport icon1414 from './warning--steep-descent--g3.png';\r\nimport icon1415 from './warning--steep-descent--g4.png';\r\nimport icon1416 from './warning--steep-descent--g5.png';\r\nimport icon1417 from './warning--steep-descent--g6.png';\r\nimport icon1418 from './warning--stop-ahead--g1.png';\r\nimport icon1419 from './warning--stop-ahead--g3.png';\r\nimport icon1420 from './warning--stop-ahead--g4.png';\r\nimport icon1421 from './warning--stop-ahead--g5.png';\r\nimport icon1422 from './warning--stop-ahead--g6.png';\r\nimport icon1423 from './warning--t-roads--g1.png';\r\nimport icon1424 from './warning--t-roads--g2.png';\r\nimport icon1425 from './warning--tanks-crossing--g1.png';\r\nimport icon1426 from './warning--tanks-crossing--g2.png';\r\nimport icon1427 from './warning--texts--g1.png';\r\nimport icon1428 from './warning--texts--g2.png';\r\nimport icon1429 from './warning--texts--g3.png';\r\nimport icon1430 from './warning--towing--g1.png';\r\nimport icon1431 from './warning--tractors--g1.png';\r\nimport icon1432 from './warning--tractors--g2.png';\r\nimport icon1433 from './warning--tractors--g3.png';\r\nimport icon1434 from './warning--tractors--g4.png';\r\nimport icon1435 from './warning--tractors--g5.png';\r\nimport icon1436 from './warning--tractors--g6.png';\r\nimport icon1437 from './warning--tractors--g7.png';\r\nimport icon1438 from './warning--traffic-merges-at-signalized-intersections--g1.png';\r\nimport icon1439 from './warning--traffic-merges-left--g1.png';\r\nimport icon1440 from './warning--traffic-merges-left--g2.png';\r\nimport icon1441 from './warning--traffic-merges-left--g3.png';\r\nimport icon1442 from './warning--traffic-merges-left--g4.png';\r\nimport icon1443 from './warning--traffic-merges-left-and-right--g1.png';\r\nimport icon1444 from './warning--traffic-merges-left-buses--g1.png';\r\nimport icon1445 from './warning--traffic-merges-right--g1.png';\r\nimport icon1446 from './warning--traffic-merges-right--g2.png';\r\nimport icon1447 from './warning--traffic-merges-right--g3.png';\r\nimport icon1448 from './warning--traffic-merges-right-buses--g1.png';\r\nimport icon1449 from './warning--traffic-queues-likely--g1.png';\r\nimport icon1450 from './warning--traffic-queues-likely--g2.png';\r\nimport icon1451 from './warning--traffic-queues-likely--g3.png';\r\nimport icon1452 from './warning--traffic-queues-likely--g4.png';\r\nimport icon1453 from './warning--traffic-queues-likely--g5.png';\r\nimport icon1454 from './warning--traffic-signals--g1.png';\r\nimport icon1455 from './warning--traffic-signals--g2.png';\r\nimport icon1456 from './warning--traffic-signals--g3.png';\r\nimport icon1457 from './warning--traffic-signals--g4.png';\r\nimport icon1458 from './warning--traffic-signals--g5.png';\r\nimport icon1459 from './warning--traffic-signals--g6.png';\r\nimport icon1460 from './warning--traffic-slow--g1.png';\r\nimport icon1461 from './warning--trail-crossing--g1.png';\r\nimport icon1462 from './warning--trail-crossing--g2.png';\r\nimport icon1463 from './warning--trail-crossing--g3.png';\r\nimport icon1464 from './warning--trail-crossing--g4.png';\r\nimport icon1465 from './warning--trail-crossing--g5.png';\r\nimport icon1466 from './warning--trail-crossing--g6.png';\r\nimport icon1467 from './warning--trams-crossing--g1.png';\r\nimport icon1468 from './warning--trams-crossing--g2.png';\r\nimport icon1469 from './warning--triple-curve-left--g1.png';\r\nimport icon1470 from './warning--triple-curve-right--g1.png';\r\nimport icon1471 from './warning--triple-lanes-left-turn--g1.png';\r\nimport icon1472 from './warning--triple-lanes-left-turn-or-go-straight--g1.png';\r\nimport icon1473 from './warning--triple-lanes-right-turn--g1.png';\r\nimport icon1474 from './warning--triple-lanes-right-turn-or-go-straight--g1.png';\r\nimport icon1475 from './warning--triple-lanes-with-directions--g1.png';\r\nimport icon1476 from './warning--triple-reverse-curve-left--g1.png';\r\nimport icon1477 from './warning--triple-reverse-curve-right--g1.png';\r\nimport icon1478 from './warning--trucks-crossing--g1.png';\r\nimport icon1479 from './warning--trucks-crossing--g2.png';\r\nimport icon1480 from './warning--trucks-rollover--g1.png';\r\nimport icon1481 from './warning--trucks-rollover--g2.png';\r\nimport icon1482 from './warning--trucks-rollover--g3.png';\r\nimport icon1483 from './warning--trucks-rollover--g4.png';\r\nimport icon1484 from './warning--trucks-rollover--g5.png';\r\nimport icon1485 from './warning--tunnel--g1.png';\r\nimport icon1486 from './warning--tunnel--g2.png';\r\nimport icon1487 from './warning--tunnel--g3.png';\r\nimport icon1488 from './warning--tunnel--g4.png';\r\nimport icon1489 from './warning--tunnel--g5.png';\r\nimport icon1490 from './warning--tunnel--g6.png';\r\nimport icon1491 from './warning--tunnel--g7.png';\r\nimport icon1492 from './warning--turn-left--g1.png';\r\nimport icon1493 from './warning--turn-left--g2.png';\r\nimport icon1494 from './warning--turn-left--g3.png';\r\nimport icon1495 from './warning--turn-left-or-right--g1.png';\r\nimport icon1496 from './warning--turn-right--g1.png';\r\nimport icon1497 from './warning--turn-right--g2.png';\r\nimport icon1498 from './warning--turn-right--g3.png';\r\nimport icon1499 from './warning--two-way-traffic--g1.png';\r\nimport icon1500 from './warning--two-way-traffic--g2.png';\r\nimport icon1501 from './warning--two-way-traffic--g3.png';\r\nimport icon1502 from './warning--two-way-traffic--g4.png';\r\nimport icon1503 from './warning--two-way-traffic--g5.png';\r\nimport icon1504 from './warning--two-way-traffic--g6.png';\r\nimport icon1505 from './warning--u-turn--g1.png';\r\nimport icon1506 from './warning--u-turn--g2.png';\r\nimport icon1507 from './warning--uneven-road--g1.png';\r\nimport icon1508 from './warning--uneven-road--g2.png';\r\nimport icon1509 from './warning--uneven-roads-ahead--g1.png';\r\nimport icon1510 from './warning--vehicles-and-others--g1.png';\r\nimport icon1511 from './warning--vehicles-crossing--g1.png';\r\nimport icon1512 from './warning--village--g1.png';\r\nimport icon1513 from './warning--weight-limit--g5.png';\r\nimport icon1514 from './warning--weight-limit-per-tandem-axle--g1.png';\r\nimport icon1515 from './warning--width-restriction--g1.png';\r\nimport icon1516 from './warning--width-restriction--g2.png';\r\nimport icon1517 from './warning--width-restriction--g3.png';\r\nimport icon1518 from './warning--width-restriction--g4.png';\r\nimport icon1519 from './warning--wild-animals--g1.png';\r\nimport icon1520 from './warning--wild-animals--g2.png';\r\nimport icon1521 from './warning--wild-animals--g3.png';\r\nimport icon1522 from './warning--wild-animals--g4.png';\r\nimport icon1523 from './warning--wild-animals--g5.png';\r\nimport icon1524 from './warning--wild-animals--g6.png';\r\nimport icon1525 from './warning--wild-animals--g7.png';\r\nimport icon1526 from './warning--wild-animals--g8.png';\r\nimport icon1527 from './warning--wind--g1.png';\r\nimport icon1528 from './warning--winding-road--g1.png';\r\nimport icon1529 from './warning--winding-road-first-left--g1.png';\r\nimport icon1530 from './warning--winding-road-first-left--g2.png';\r\nimport icon1531 from './warning--winding-road-first-left--g3.png';\r\nimport icon1532 from './warning--winding-road-first-right--g1.png';\r\nimport icon1533 from './warning--winding-road-first-right--g2.png';\r\nimport icon1534 from './warning--winding-road-first-right--g3.png';\r\nimport icon1535 from './warning--winding-road-first-right--g4.png';\r\nimport icon1536 from './warning--winding-road-to-left--g1.png';\r\nimport icon1537 from './warning--winding-road-to-right--g1.png';\r\nimport icon1538 from './warning--wombat-crossing--g1.png';\r\nimport icon1539 from './warning--y-roads--g1.png';\r\nimport icon1540 from './warning--y-roads--g2.png';\r\nimport icon1541 from './warning--yield-ahead--g1.png';\r\nimport icon1542 from './warning--yield-ahead--g3.png';\r\n\r\nconst textures = {\r\n 'complementary--accident-area--g1': icon0,\r\n 'complementary--accident-area--g2': icon1,\r\n 'complementary--accident-area--g3': icon2,\r\n 'complementary--accident-area--g4': icon3,\r\n 'complementary--advisory-exit-or-ramp-speed--g1': icon4,\r\n 'complementary--bicycles--g1': icon5,\r\n 'complementary--bicycles-and-pedestrians-detour--g1': icon6,\r\n 'complementary--bicycles-or-pedestrians-detour--g1': icon7,\r\n 'complementary--bicycles-turn-right--g1': icon8,\r\n 'complementary--bike-route--g1': icon9,\r\n 'complementary--bike-route--g3': icon10,\r\n 'complementary--both-directions--g1': icon11,\r\n 'complementary--both-directions--g2': icon12,\r\n 'complementary--buses--g1': icon13,\r\n 'complementary--buses-and-trucks--g1': icon14,\r\n 'complementary--camera--g1': icon15,\r\n 'complementary--camera--g2': icon16,\r\n 'complementary--camera--g3': icon17,\r\n 'complementary--camera--g4': icon18,\r\n 'complementary--camera--g5': icon19,\r\n 'complementary--caravan-trailers--g2': icon20,\r\n 'complementary--caravan-trailers--g3': icon21,\r\n 'complementary--caravans--g2': icon22,\r\n 'complementary--carts--g1': icon23,\r\n 'complementary--chevron-left--g1': icon24,\r\n 'complementary--chevron-left--g2': icon25,\r\n 'complementary--chevron-left--g3': icon26,\r\n 'complementary--chevron-left--g4': icon27,\r\n 'complementary--chevron-left--g5': icon28,\r\n 'complementary--chevron-right--g1': icon29,\r\n 'complementary--chevron-right--g2': icon30,\r\n 'complementary--chevron-right--g3': icon31,\r\n 'complementary--chevron-right--g4': icon32,\r\n 'complementary--chevron-right--g5': icon33,\r\n 'complementary--dangerous-or-pollutant-good--g1': icon34,\r\n 'complementary--dead-end--g1': icon35,\r\n 'complementary--detour--g1': icon36,\r\n 'complementary--disabled-persons--g1': icon37,\r\n 'complementary--distance--g1': icon38,\r\n 'complementary--distance--g2': icon39,\r\n 'complementary--distance--g3': icon40,\r\n 'complementary--end-of-road-works--g1': icon41,\r\n 'complementary--except-bicycles--g1': icon42,\r\n 'complementary--except-bicycles--g2': icon43,\r\n 'complementary--except-buses--g1': icon44,\r\n 'complementary--except-carts--g1': icon45,\r\n 'complementary--except-motorcycles--g1': icon46,\r\n 'complementary--except-motorcycles--g2': icon47,\r\n 'complementary--except-polluting-level-green--g1': icon48,\r\n 'complementary--except-polluting-level-green-yellow--g1': icon49,\r\n 'complementary--except-polluting-level-green-yellow-red--g1': icon50,\r\n 'complementary--except-tractors--g1': icon51,\r\n 'complementary--except-tractors--g2': icon52,\r\n 'complementary--except-trailers--g1': icon53,\r\n 'complementary--except-trailers--g2': icon54,\r\n 'complementary--except-trains--g1': icon55,\r\n 'complementary--except-trams--g1': icon56,\r\n 'complementary--except-trucks--g1': icon57,\r\n 'complementary--except-vehicles--g1': icon58,\r\n 'complementary--except-vehicles--g2': icon59,\r\n 'complementary--go-left--g1': icon60,\r\n 'complementary--go-right--g1': icon61,\r\n 'complementary--go-straight-or-turn-left--g1': icon62,\r\n 'complementary--go-straight-or-turn-right--g1': icon63,\r\n 'complementary--height-limit--g1': icon64,\r\n 'complementary--height-limit--g2': icon65,\r\n 'complementary--including-bicycles-and-motorcycles--g1': icon66,\r\n 'complementary--including-buses-vehicles--g1': icon67,\r\n 'complementary--keep-left--g1': icon68,\r\n 'complementary--keep-right--g1': icon69,\r\n 'complementary--lane-control--g1': icon70,\r\n 'complementary--lane-control--g2': icon71,\r\n 'complementary--lane-control--g3': icon72,\r\n 'complementary--maximum-speed-limit-10--g1': icon73,\r\n 'complementary--maximum-speed-limit-15--g1': icon74,\r\n 'complementary--maximum-speed-limit-20--g1': icon75,\r\n 'complementary--maximum-speed-limit-25--g1': icon76,\r\n 'complementary--maximum-speed-limit-30--g1': icon77,\r\n 'complementary--maximum-speed-limit-35--g1': icon78,\r\n 'complementary--maximum-speed-limit-40--g1': icon79,\r\n 'complementary--maximum-speed-limit-45--g1': icon80,\r\n 'complementary--maximum-speed-limit-50--g1': icon81,\r\n 'complementary--maximum-speed-limit-55--g1': icon82,\r\n 'complementary--maximum-speed-limit-60--g1': icon83,\r\n 'complementary--maximum-speed-limit-65--g1': icon84,\r\n 'complementary--maximum-speed-limit-70--g1': icon85,\r\n 'complementary--maximum-speed-limit-75--g1': icon86,\r\n 'complementary--maximum-speed-limit-80--g1': icon87,\r\n 'complementary--maximum-speed-limit-85--g1': icon88,\r\n 'complementary--maximum-speed-limit-90--g1': icon89,\r\n 'complementary--maximum-speed-limit-95--g1': icon90,\r\n 'complementary--motorcycles--g1': icon91,\r\n 'complementary--motorcycles--g2': icon92,\r\n 'complementary--motorcycles--g3': icon93,\r\n 'complementary--motorcycles--g4': icon94,\r\n 'complementary--obstacle-delineator--g1': icon95,\r\n 'complementary--obstacle-delineator--g2': icon96,\r\n 'complementary--obstacle-delineator--g3': icon97,\r\n 'complementary--one-direction-left--g1': icon98,\r\n 'complementary--one-direction-right--g1': icon99,\r\n 'complementary--pass-left--g1': icon100,\r\n 'complementary--pass-right--g1': icon101,\r\n 'complementary--pedestrians-and-bicycles--g1': icon102,\r\n 'complementary--pedestrians-left--g1': icon103,\r\n 'complementary--pedestrians-right--g1': icon104,\r\n 'complementary--photo-enforced--g1': icon105,\r\n 'complementary--playground--g1': icon106,\r\n 'complementary--priority-route-at-intersection--g1': icon107,\r\n 'complementary--priority-route-at-intersection--g2': icon108,\r\n 'complementary--priority-route-at-intersection--g3': icon109,\r\n 'complementary--priority-route-at-intersection--g4': icon110,\r\n 'complementary--priority-route-at-intersection--g5': icon111,\r\n 'complementary--priority-route-at-intersection--g6': icon112,\r\n 'complementary--railroad--g1': icon113,\r\n 'complementary--railroad--g2': icon114,\r\n 'complementary--railroad--g3': icon115,\r\n 'complementary--restriction-in-both-directions--g1': icon116,\r\n 'complementary--roundabout-go-left--g1': icon117,\r\n 'complementary--roundabout-go-right--g1': icon118,\r\n 'complementary--roundabout-go-straight--g1': icon119,\r\n 'complementary--slippery-for-caravan-trailers--g1': icon120,\r\n 'complementary--snow--g2': icon121,\r\n 'complementary--snow--g4': icon122,\r\n 'complementary--snow--g5': icon123,\r\n 'complementary--snowmobiles--g1': icon124,\r\n 'complementary--soft-shoulder--g1': icon125,\r\n 'complementary--soft-shoulder--g2': icon126,\r\n 'complementary--steep-ascent--g1': icon127,\r\n 'complementary--steep-descent--g1': icon128,\r\n 'complementary--time-restrictions--g1': icon129,\r\n 'complementary--time-restrictions--g3': icon130,\r\n 'complementary--tow-away-zone--g1': icon131,\r\n 'complementary--tow-away-zone--g3': icon132,\r\n 'complementary--tractors--g1': icon133,\r\n 'complementary--traffic-queues--g1': icon134,\r\n 'complementary--trailers--g1': icon135,\r\n 'complementary--trailers--g2': icon136,\r\n 'complementary--trailers--g3': icon137,\r\n 'complementary--trailers--g4': icon138,\r\n 'complementary--trains--g1': icon139,\r\n 'complementary--trams--g1': icon140,\r\n 'complementary--trees--g1': icon141,\r\n 'complementary--trucks--g1': icon142,\r\n 'complementary--trucks--g2': icon143,\r\n 'complementary--trucks--g3': icon144,\r\n 'complementary--trucks-and-trailers--g1': icon145,\r\n 'complementary--trucks-buses-trailers--g1': icon146,\r\n 'complementary--trucks-go-left--g1': icon147,\r\n 'complementary--trucks-go-left-ahead--g1': icon148,\r\n 'complementary--trucks-go-right--g1': icon149,\r\n 'complementary--trucks-go-right-ahead--g1': icon150,\r\n 'complementary--trucks-go-straight--g1': icon151,\r\n 'complementary--trucks-turn-left--g1': icon152,\r\n 'complementary--trucks-turn-right--g1': icon153,\r\n 'complementary--turn-left--g1': icon154,\r\n 'complementary--turn-left--g2': icon155,\r\n 'complementary--turn-right--g1': icon156,\r\n 'complementary--turn-right--g2': icon157,\r\n 'complementary--two-way-traffic--g1': icon158,\r\n 'complementary--two-way-traffic--g2': icon159,\r\n 'complementary--two-way-traffic--g3': icon160,\r\n 'complementary--two-way-traffic--g4': icon161,\r\n 'complementary--two-way-traffic--g5': icon162,\r\n 'complementary--vehicles--g1': icon163,\r\n 'complementary--vehicles--g2': icon164,\r\n 'complementary--vehicles-or-buses--g1': icon165,\r\n 'complementary--weekends-or-holidays--g1': icon166,\r\n 'complementary--weight-limit--g1': icon167,\r\n 'complementary--when-foggy--g1': icon168,\r\n 'complementary--when-rainy--g1': icon169,\r\n 'complementary--when-rainy--g2': icon170,\r\n 'complementary--when-rainy--g3': icon171,\r\n 'complementary--when-snowy--g1': icon172,\r\n 'complementary--when-snowy--g2': icon173,\r\n 'complementary--when-snowy-or-rainy--g1': icon174,\r\n 'complementary--when-snowy-or-rainy--g2': icon175,\r\n 'complementary--when-wet--g1': icon176,\r\n 'complementary--width-limit--g1': icon177,\r\n 'complementary--working-days--g1': icon178,\r\n 'information--airport--g1': icon179,\r\n 'information--airport--g2': icon180,\r\n 'information--bicycle-lane--g1': icon181,\r\n 'information--bicycles-both-ways--g1': icon182,\r\n 'information--bicycles-crossing--g1': icon183,\r\n 'information--bicycles-crossing--g2': icon184,\r\n 'information--bicycles-crossing--g3': icon185,\r\n 'information--bike-route--g1': icon186,\r\n 'information--bike-route--g2': icon187,\r\n 'information--built-up-area--g1': icon188,\r\n 'information--built-up-area--g2': icon189,\r\n 'information--bus-lane-straight--g1': icon190,\r\n 'information--bus-stop--g1': icon191,\r\n 'information--bus-stop--g2': icon192,\r\n 'information--camera--g1': icon193,\r\n 'information--camera--g2': icon194,\r\n 'information--camera--g3': icon195,\r\n 'information--camp--g1': icon196,\r\n 'information--camp--g2': icon197,\r\n 'information--car-pool-lane--g1': icon198,\r\n 'information--caravan-parking--g1': icon199,\r\n 'information--caravan-trailer-parking--g1': icon200,\r\n 'information--cargo-loading-zone--g1': icon201,\r\n 'information--central-lane--g1': icon202,\r\n 'information--charging-station--g1': icon203,\r\n 'information--children--g1': icon204,\r\n 'information--children--g2': icon205,\r\n 'information--children-crossing--g5': icon206,\r\n 'information--cycling-two-abreast-permitted--g1': icon207,\r\n 'information--dead-end--g1': icon208,\r\n 'information--dead-end--g2': icon209,\r\n 'information--dead-end--g3': icon210,\r\n 'information--dead-end--g4': icon211,\r\n 'information--dead-end-except-bicycles--g1': icon212,\r\n 'information--dead-end-except-bicycles-and-pedestrians--g1': icon213,\r\n 'information--dead-end-except-bicycles-and-pedestrians--g2': icon214,\r\n 'information--dead-end-left--g1': icon215,\r\n 'information--dead-end-left--g2': icon216,\r\n 'information--dead-end-right--g1': icon217,\r\n 'information--dead-end-right--g2': icon218,\r\n 'information--dead-end-right--g3': icon219,\r\n 'information--directions--g1': icon220,\r\n 'information--disabled-persons--g1': icon221,\r\n 'information--disabled-persons--g2': icon222,\r\n 'information--disabled-persons--g3': icon223,\r\n 'information--emergency-facility--g1': icon224,\r\n 'information--end-of-advisory-maximum-speed-limit-20--g1': icon225,\r\n 'information--end-of-advisory-maximum-speed-limit-40--g1': icon226,\r\n 'information--end-of-advisory-maximum-speed-limit-60--g1': icon227,\r\n 'information--end-of-advisory-maximum-speed-limit-70--g1': icon228,\r\n 'information--end-of-advisory-maximum-speed-limit-80--g1': icon229,\r\n 'information--end-of-advisory-maximum-speed-limit-90--g1': icon230,\r\n 'information--end-of-bicycle-lane--g1': icon231,\r\n 'information--end-of-built-up-area--g1': icon232,\r\n 'information--end-of-built-up-area--g2': icon233,\r\n 'information--end-of-built-up-area--g3': icon234,\r\n 'information--end-of-built-up-area--g4': icon235,\r\n 'information--end-of-car-pool-lane--g1': icon236,\r\n 'information--end-of-limited-access-road--g1': icon237,\r\n 'information--end-of-living-street--g1': icon238,\r\n 'information--end-of-living-street--g2': icon239,\r\n 'information--end-of-minimum-speed-10--g1': icon240,\r\n 'information--end-of-minimum-speed-20--g1': icon241,\r\n 'information--end-of-minimum-speed-25--g1': icon242,\r\n 'information--end-of-minimum-speed-30--g1': icon243,\r\n 'information--end-of-minimum-speed-35--g1': icon244,\r\n 'information--end-of-minimum-speed-40--g1': icon245,\r\n 'information--end-of-minimum-speed-50--g1': icon246,\r\n 'information--end-of-minimum-speed-60--g1': icon247,\r\n 'information--end-of-minimum-speed-70--g1': icon248,\r\n 'information--end-of-minimum-speed-75--g1': icon249,\r\n 'information--end-of-minimum-speed-80--g1': icon250,\r\n 'information--end-of-minimum-speed-90--g1': icon251,\r\n 'information--end-of-minimum-speed-100--g1': icon252,\r\n 'information--end-of-minimum-speed-110--g1': icon253,\r\n 'information--end-of-minimum-speed-120--g1': icon254,\r\n 'information--end-of-minimum-speed-130--g1': icon255,\r\n 'information--end-of-motorway--g1': icon256,\r\n 'information--end-of-overtaking-permitted-heavy-good-vehicles--g1': icon257,\r\n 'information--end-of-road-works--g1': icon258,\r\n 'information--end-of-tunnel--g1': icon259,\r\n 'information--end-of-tunnel--g2': icon260,\r\n 'information--end-of-two-way-traffic--g1': icon261,\r\n 'information--equestrians-permitted--g1': icon262,\r\n 'information--exit-ahead--g1': icon263,\r\n 'information--exit-ahead--g2': icon264,\r\n 'information--exit-ahead--g3': icon265,\r\n 'information--flight-port--g1': icon266,\r\n 'information--food--g1': icon267,\r\n 'information--food--g2': icon268,\r\n 'information--gas-station--g1': icon269,\r\n 'information--gas-station--g2': icon270,\r\n 'information--gas-station--g3': icon271,\r\n 'information--general-speed-limit-at-city-border--g1': icon272,\r\n 'information--go-left--g1': icon273,\r\n 'information--go-right--g1': icon274,\r\n 'information--go-straight--g1': icon275,\r\n 'information--go-straight-or-left--g1': icon276,\r\n 'information--go-straight-or-right--g1': icon277,\r\n 'information--go-straight-or-turn-left--g1': icon278,\r\n 'information--go-straight-or-turn-right--g1': icon279,\r\n 'information--hazardous-goods-vehicles-lane--g1': icon280,\r\n 'information--height-limit--g1': icon281,\r\n 'information--height-limit--g2': icon282,\r\n 'information--highway-directions--g1': icon283,\r\n 'information--highway-exit--g1': icon284,\r\n 'information--highway-interchange--g1': icon285,\r\n 'information--highway-interstate-route--g1': icon286,\r\n 'information--highway-interstate-route--g2': icon287,\r\n 'information--highway-preferential-lane--g1': icon288,\r\n 'information--highway-preferential-lane--g2': icon289,\r\n 'information--highway-reference-location--g1': icon290,\r\n 'information--highway-reference-location--g2': icon291,\r\n 'information--hiking--g1': icon292,\r\n 'information--hospital--g1': icon293,\r\n 'information--hurricane-evacuation-route--g1': icon294,\r\n 'information--interstate-route--g1': icon295,\r\n 'information--lane-control-intersections--g1': icon296,\r\n 'information--lane-control-left-turn--g1': icon297,\r\n 'information--lane-control-multiple-lanes--g1': icon298,\r\n 'information--lane-control-multiple-lanes--g2': icon299,\r\n 'information--lane-control-right-turn--g1': icon300,\r\n 'information--limited-access-road--g1': icon301,\r\n 'information--litter-container--g1': icon302,\r\n 'information--living-street--g1': icon303,\r\n 'information--living-street--g2': icon304,\r\n 'information--living-street--g3': icon305,\r\n 'information--lodging--g1': icon306,\r\n 'information--lodging--g2': icon307,\r\n 'information--minimum-speed-10--g1': icon308,\r\n 'information--minimum-speed-20--g1': icon309,\r\n 'information--minimum-speed-25--g1': icon310,\r\n 'information--minimum-speed-30--g1': icon311,\r\n 'information--minimum-speed-35--g1': icon312,\r\n 'information--minimum-speed-40--g1': icon313,\r\n 'information--minimum-speed-50--g1': icon314,\r\n 'information--minimum-speed-60--g1': icon315,\r\n 'information--minimum-speed-70--g1': icon316,\r\n 'information--minimum-speed-75--g1': icon317,\r\n 'information--minimum-speed-80--g1': icon318,\r\n 'information--minimum-speed-90--g1': icon319,\r\n 'information--minimum-speed-100--g1': icon320,\r\n 'information--minimum-speed-110--g1': icon321,\r\n 'information--minimum-speed-120--g1': icon322,\r\n 'information--minimum-speed-130--g1': icon323,\r\n 'information--motorway--g1': icon324,\r\n 'information--motorway-exit-ahead--g1': icon325,\r\n 'information--motorway-exit-ahead--g2': icon326,\r\n 'information--motorway-exit-ahead--g3': icon327,\r\n 'information--overtaking-allowed-heavy-good-vehicles--g1': icon328,\r\n 'information--parallel-parking--g1': icon329,\r\n 'information--park-and-ride--g1': icon330,\r\n 'information--park-and-ride--g2': icon331,\r\n 'information--parking--g1': icon332,\r\n 'information--parking--g2': icon333,\r\n 'information--parking--g3': icon334,\r\n 'information--parking--g4': icon335,\r\n 'information--parking--g5': icon336,\r\n 'information--parking--g6': icon337,\r\n 'information--parking-area--g1': icon338,\r\n 'information--parking-with-restrictions--g1': icon339,\r\n 'information--pass-on-either-side--g1': icon340,\r\n 'information--passenger-loading-zone--g1': icon341,\r\n 'information--pedestrians-crossing--g1': icon342,\r\n 'information--pedestrians-crossing--g2': icon343,\r\n 'information--pedestrians-crossing--g3': icon344,\r\n 'information--pedestrians-only--g4': icon345,\r\n 'information--pedestrians-permitted--g1': icon346,\r\n 'information--perpendicular-parking--g1': icon347,\r\n 'information--picnic-site--g1': icon348,\r\n 'information--playground--g1': icon349,\r\n 'information--recreational-vehicle-sanitary-station--g1': icon350,\r\n 'information--recycle-collection-center--g1': icon351,\r\n 'information--rest-area--g1': icon352,\r\n 'information--road-bump--g1': icon353,\r\n 'information--road-skating--g1': icon354,\r\n 'information--safety-zone--g1': icon355,\r\n 'information--safety-zone--g2': icon356,\r\n 'information--safety-zone--g3': icon357,\r\n 'information--shared-path-vehicles-and-motorcycles--g1': icon358,\r\n 'information--stairs--g1': icon359,\r\n 'information--stairs--g2': icon360,\r\n 'information--stairs--g3': icon361,\r\n 'information--stairs--g4': icon362,\r\n 'information--stop-line--g1': icon363,\r\n 'information--stop-permitted--g1': icon364,\r\n 'information--street-name-one-line--g1': icon365,\r\n 'information--street-name-three-lines--g1': icon366,\r\n 'information--street-name-two-lines--g1': icon367,\r\n 'information--subway--g1': icon368,\r\n 'information--telephone--g1': icon369,\r\n 'information--telephone--g2': icon370,\r\n 'information--telephone-device-for-the-deaf--g1': icon371,\r\n 'information--toll-station--g1': icon372,\r\n 'information--tourism-information--g1': icon373,\r\n 'information--tourist-attraction--g1': icon374,\r\n 'information--traffic-merges-left--g1': icon375,\r\n 'information--traffic-merges-right--g1': icon376,\r\n 'information--trail-crossing--g1': icon377,\r\n 'information--trail-crossing--g2': icon378,\r\n 'information--trail-crossing--g3': icon379,\r\n 'information--trailer-camping--g1': icon380,\r\n 'information--train-or-light-rail-station--g1': icon381,\r\n 'information--tram-bus-stop--g1': icon382,\r\n 'information--tram-bus-stop--g2': icon383,\r\n 'information--trams-crossing--g1': icon384,\r\n 'information--truck-lane-left--g1': icon385,\r\n 'information--truck-parking--g1': icon386,\r\n 'information--truck-trailer-lane-right--g1': icon387,\r\n 'information--truck-trailer-lane-straight--g1': icon388,\r\n 'information--trucks-both-ways--g1': icon389,\r\n 'information--trucks-only--g1': icon390,\r\n 'information--tsunami-evacuation_route--g1': icon391,\r\n 'information--tunnel--g1': icon392,\r\n 'information--tunnel--g2': icon393,\r\n 'information--tunnel--g3': icon394,\r\n 'information--tunnel-ahead--g1': icon395,\r\n 'information--turn-left--g1': icon396,\r\n 'information--turn-left-ahead--g1': icon397,\r\n 'information--turn-right--g1': icon398,\r\n 'information--turn-right-ahead--g1': icon399,\r\n 'information--urban-area--g1': icon400,\r\n 'information--vehicles-on-rails--g1': icon401,\r\n 'information--water-protection-zone--g1': icon402,\r\n 'information--weight-and-height-limit--g1': icon403,\r\n 'information--weight-limit--g1': icon404,\r\n 'information--wireless-internet--g1': icon405,\r\n 'regulatory--advisory-maximum-speed-limit--g1': icon406,\r\n 'regulatory--all-directions-permitted--g1': icon407,\r\n 'regulatory--all-way--g1': icon408,\r\n 'regulatory--atvs-permitted--g1': icon409,\r\n 'regulatory--axle-limit--g1': icon410,\r\n 'regulatory--axle-limit--g2': icon411,\r\n 'regulatory--bicycle-lane-left--g1': icon412,\r\n 'regulatory--bicycle-parking--g1': icon413,\r\n 'regulatory--bicycles-and-buses-only--g1': icon414,\r\n 'regulatory--bicycles-only--g1': icon415,\r\n 'regulatory--bicycles-only--g2': icon416,\r\n 'regulatory--bicycles-only--g3': icon417,\r\n 'regulatory--bicycles-only--g4': icon418,\r\n 'regulatory--bicycles-push-button--g1': icon419,\r\n 'regulatory--bicycles-push-button--g2': icon420,\r\n 'regulatory--bicycles-stop-on-red--g1': icon421,\r\n 'regulatory--bicycles-wrong-way--g1': icon422,\r\n 'regulatory--bicycles-yield-or-use-signal--g1': icon423,\r\n 'regulatory--bike-route--g1': icon424,\r\n 'regulatory--building-direction--g1': icon425,\r\n 'regulatory--bus-priority-lane--g1': icon426,\r\n 'regulatory--buses-and-taxi-only--g1': icon427,\r\n 'regulatory--buses-only--g1': icon428,\r\n 'regulatory--buses-only--g2': icon429,\r\n 'regulatory--circular-intersection--g1': icon430,\r\n 'regulatory--circular-intersection--g2': icon431,\r\n 'regulatory--circular-intersection--g3': icon432,\r\n 'regulatory--circular-intersection--g4': icon433,\r\n 'regulatory--cross-only-on-green--g1': icon434,\r\n 'regulatory--cross-only-on-pedestrian-signal--g1': icon435,\r\n 'regulatory--crosswalk-stop-on-red--g1': icon436,\r\n 'regulatory--cycling-restriction--g1': icon437,\r\n 'regulatory--cyclists-dismount-and-walk--g1': icon438,\r\n 'regulatory--detour-left--g1': icon439,\r\n 'regulatory--detour-right--g1': icon440,\r\n 'regulatory--divided-highway-crossing--g1': icon441,\r\n 'regulatory--divided-highway-ends--g1': icon442,\r\n 'regulatory--divided-highway-starts--g1': icon443,\r\n 'regulatory--do-not-block-intersection--g1': icon444,\r\n 'regulatory--do-not-pass--g1': icon445,\r\n 'regulatory--do-not-stop-on-tracks--g1': icon446,\r\n 'regulatory--dual-lanes-all-directions-on-left--g1': icon447,\r\n 'regulatory--dual-lanes-all-directions-on-right--g1': icon448,\r\n 'regulatory--dual-lanes-bicyclists-and-pedestrians--g1': icon449,\r\n 'regulatory--dual-lanes-go-left-or-right--g1': icon450,\r\n 'regulatory--dual-lanes-go-straight-on-left--g1': icon451,\r\n 'regulatory--dual-lanes-go-straight-on-right--g1': icon452,\r\n 'regulatory--dual-lanes-turn-left--g1': icon453,\r\n 'regulatory--dual-lanes-turn-left-no-u-turn--g1': icon454,\r\n 'regulatory--dual-lanes-turn-left-or-straight--g1': icon455,\r\n 'regulatory--dual-lanes-turn-right-or-straight--g1': icon456,\r\n 'regulatory--dual-path-bicycles-and-pedestrians--g1': icon457,\r\n 'regulatory--dual-path-bicycles-and-pedestrians--g2': icon458,\r\n 'regulatory--dual-path-bicycles-and-pedestrians--g3': icon459,\r\n 'regulatory--dual-path-equestrians-and-pedestrians--g1': icon460,\r\n 'regulatory--dual-path-equestrians-and-pedestrians-bicycles--g1': icon461,\r\n 'regulatory--dual-path-pedestrians-and-bicycles--g1': icon462,\r\n 'regulatory--dual-path-pedestrians-and-bicycles--g2': icon463,\r\n 'regulatory--dual-path-pedestrians-and-equestrians--g1': icon464,\r\n 'regulatory--dual-path-pedestrians-bicycles-and-equestrians--g1': icon465,\r\n 'regulatory--dual-speed-limits--g1': icon466,\r\n 'regulatory--dual-speed-limits--g2': icon467,\r\n 'regulatory--end-of-bicycles-only--g1': icon468,\r\n 'regulatory--end-of-bicycles-only--g2': icon469,\r\n 'regulatory--end-of-bus-and-taxi-only--g1': icon470,\r\n 'regulatory--end-of-buses-only--g1': icon471,\r\n 'regulatory--end-of-buses-only--g2': icon472,\r\n 'regulatory--end-of-cycling-restriction--g1': icon473,\r\n 'regulatory--end-of-dual-path-bicycles-and-pedestrians--g1': icon474,\r\n 'regulatory--end-of-dual-path-pedestrians-and-bicycles--g1': icon475,\r\n 'regulatory--end-of-equestrians-only--g1': icon476,\r\n 'regulatory--end-of-low-beam-headlights--g1': icon477,\r\n 'regulatory--end-of-maximum-speed-limit-10--g1': icon478,\r\n 'regulatory--end-of-maximum-speed-limit-10--g2': icon479,\r\n 'regulatory--end-of-maximum-speed-limit-20--g1': icon480,\r\n 'regulatory--end-of-maximum-speed-limit-20--g2': icon481,\r\n 'regulatory--end-of-maximum-speed-limit-25--g1': icon482,\r\n 'regulatory--end-of-maximum-speed-limit-25--g2': icon483,\r\n 'regulatory--end-of-maximum-speed-limit-30--g1': icon484,\r\n 'regulatory--end-of-maximum-speed-limit-30--g2': icon485,\r\n 'regulatory--end-of-maximum-speed-limit-35--g1': icon486,\r\n 'regulatory--end-of-maximum-speed-limit-35--g2': icon487,\r\n 'regulatory--end-of-maximum-speed-limit-40--g1': icon488,\r\n 'regulatory--end-of-maximum-speed-limit-40--g2': icon489,\r\n 'regulatory--end-of-maximum-speed-limit-50--g1': icon490,\r\n 'regulatory--end-of-maximum-speed-limit-50--g2': icon491,\r\n 'regulatory--end-of-maximum-speed-limit-60--g1': icon492,\r\n 'regulatory--end-of-maximum-speed-limit-60--g2': icon493,\r\n 'regulatory--end-of-maximum-speed-limit-65--g1': icon494,\r\n 'regulatory--end-of-maximum-speed-limit-65--g2': icon495,\r\n 'regulatory--end-of-maximum-speed-limit-70--g1': icon496,\r\n 'regulatory--end-of-maximum-speed-limit-70--g2': icon497,\r\n 'regulatory--end-of-maximum-speed-limit-75--g1': icon498,\r\n 'regulatory--end-of-maximum-speed-limit-75--g2': icon499,\r\n 'regulatory--end-of-maximum-speed-limit-80--g1': icon500,\r\n 'regulatory--end-of-maximum-speed-limit-80--g2': icon501,\r\n 'regulatory--end-of-maximum-speed-limit-90--g1': icon502,\r\n 'regulatory--end-of-maximum-speed-limit-90--g2': icon503,\r\n 'regulatory--end-of-maximum-speed-limit-100--g1': icon504,\r\n 'regulatory--end-of-maximum-speed-limit-100--g2': icon505,\r\n 'regulatory--end-of-maximum-speed-limit-110--g1': icon506,\r\n 'regulatory--end-of-maximum-speed-limit-110--g2': icon507,\r\n 'regulatory--end-of-maximum-speed-limit-120--g1': icon508,\r\n 'regulatory--end-of-maximum-speed-limit-120--g2': icon509,\r\n 'regulatory--end-of-maximum-speed-limit-130--g1': icon510,\r\n 'regulatory--end-of-maximum-speed-limit-130--g2': icon511,\r\n 'regulatory--end-of-maximum-speed-limit--g1': icon512,\r\n 'regulatory--end-of-mopeds-and-bicycles-only--g1': icon513,\r\n 'regulatory--end-of-no-heavy-goods-vehicles--g1': icon514,\r\n 'regulatory--end-of-no-horn--g1': icon515,\r\n 'regulatory--end-of-no-overtaking--g1': icon516,\r\n 'regulatory--end-of-no-overtaking--g2': icon517,\r\n 'regulatory--end-of-no-overtaking--g3': icon518,\r\n 'regulatory--end-of-no-overtaking--g4': icon519,\r\n 'regulatory--end-of-no-overtaking--g5': icon520,\r\n 'regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g1': icon521,\r\n 'regulatory--end-of-no-overtaking-by-heavy-goods-vehicles--g2': icon522,\r\n 'regulatory--end-of-no-overtaking-by-motorcycles--g1': icon523,\r\n 'regulatory--end-of-no-parking--g1': icon524,\r\n 'regulatory--end-of-no-parking--g2': icon525,\r\n 'regulatory--end-of-no-parking-or-stopping--g1': icon526,\r\n 'regulatory--end-of-one-way-straight--g1': icon527,\r\n 'regulatory--end-of-parking-zone--g1': icon528,\r\n 'regulatory--end-of-parking-zone--g2': icon529,\r\n 'regulatory--end-of-pedestrians-only--g1': icon530,\r\n 'regulatory--end-of-pedestrians-only--g2': icon531,\r\n 'regulatory--end-of-pedestrians-only--g3': icon532,\r\n 'regulatory--end-of-pedestrians-only--g4': icon533,\r\n 'regulatory--end-of-priority-road--g1': icon534,\r\n 'regulatory--end-of-prohibition--g1': icon535,\r\n 'regulatory--end-of-school-zone--g1': icon536,\r\n 'regulatory--end-of-shared-path-bicycles-and-pedestrians--g1': icon537,\r\n 'regulatory--end-of-shared-path-pedestrians-and-bicycles--g1': icon538,\r\n 'regulatory--end-of-snow-chains--g1': icon539,\r\n 'regulatory--end-of-snow-chains--g2': icon540,\r\n 'regulatory--end-of-snowmobiles-only--g1': icon541,\r\n 'regulatory--end-of-speed-limit-zone--g1': icon542,\r\n 'regulatory--end-of-speed-limit-zone--g2': icon543,\r\n 'regulatory--end-of-speed-limit-zone--g3': icon544,\r\n 'regulatory--end-of-tractors-only--g1': icon545,\r\n 'regulatory--end-of-trams-and-buses-only--g1': icon546,\r\n 'regulatory--end-of-trams-only--g1': icon547,\r\n 'regulatory--end-of-trucks-and-buses-only--g1': icon548,\r\n 'regulatory--end-of-trucks-only--g1': icon549,\r\n 'regulatory--end-of-trucks-only--g2': icon550,\r\n 'regulatory--equestrians-only--g1': icon551,\r\n 'regulatory--except-railroad-crossing--g1': icon552,\r\n 'regulatory--fine-for-littering--g1': icon553,\r\n 'regulatory--give-way-to-bicycles--g1': icon554,\r\n 'regulatory--give-way-to-oncoming-traffic--g1': icon555,\r\n 'regulatory--give-way-to-oncoming-traffic--g2': icon556,\r\n 'regulatory--go-left-bicycles--g1': icon557,\r\n 'regulatory--go-right-bicycles--g1': icon558,\r\n 'regulatory--go-straight--g1': icon559,\r\n 'regulatory--go-straight--g3': icon560,\r\n 'regulatory--go-straight-bicycles--g1': icon561,\r\n 'regulatory--go-straight-or-turn-left--g1': icon562,\r\n 'regulatory--go-straight-or-turn-left--g2': icon563,\r\n 'regulatory--go-straight-or-turn-left--g3': icon564,\r\n 'regulatory--go-straight-or-turn-right--g1': icon565,\r\n 'regulatory--go-straight-or-turn-right--g2': icon566,\r\n 'regulatory--go-straight-or-turn-right--g3': icon567,\r\n 'regulatory--heavy-goods-vehicles-permitted--g1': icon568,\r\n 'regulatory--height-limit--g1': icon569,\r\n 'regulatory--high-beam-headlights--g1': icon570,\r\n 'regulatory--horn--g1': icon571,\r\n 'regulatory--in-street-pedestrian-crossing--g1': icon572,\r\n 'regulatory--keep-left--g1': icon573,\r\n 'regulatory--keep-left--g2': icon574,\r\n 'regulatory--keep-left--g3': icon575,\r\n 'regulatory--keep-left--g4': icon576,\r\n 'regulatory--keep-left--g5': icon577,\r\n 'regulatory--keep-left--g6': icon578,\r\n 'regulatory--keep-left--g7': icon579,\r\n 'regulatory--keep-right--g1': icon580,\r\n 'regulatory--keep-right--g2': icon581,\r\n 'regulatory--keep-right--g3': icon582,\r\n 'regulatory--keep-right--g4': icon583,\r\n 'regulatory--keep-right--g5': icon584,\r\n 'regulatory--keep-right--g6': icon585,\r\n 'regulatory--keep-right--g7': icon586,\r\n 'regulatory--keep-right--g8': icon587,\r\n 'regulatory--keep-right--g9': icon588,\r\n 'regulatory--lane-control--g1': icon589,\r\n 'regulatory--left-turn-yield-on-green--g1': icon590,\r\n 'regulatory--length-limit--g1': icon591,\r\n 'regulatory--length-limit--g2': icon592,\r\n 'regulatory--light-rail-divided-highway--g1': icon593,\r\n 'regulatory--light-rail-do-not-pass--g1': icon594,\r\n 'regulatory--light-rail-only--g1': icon595,\r\n 'regulatory--look--g1': icon596,\r\n 'regulatory--low-beam-headlights--g1': icon597,\r\n 'regulatory--low-beam-headlights--g2': icon598,\r\n 'regulatory--low-beam-headlights--g3': icon599,\r\n 'regulatory--low-speed-vehicle-permitted--g1': icon600,\r\n 'regulatory--maximum-speed-limit-5--g1': icon601,\r\n 'regulatory--maximum-speed-limit-5--g3': icon602,\r\n 'regulatory--maximum-speed-limit-10--g1': icon603,\r\n 'regulatory--maximum-speed-limit-10--g3': icon604,\r\n 'regulatory--maximum-speed-limit-15--g1': icon605,\r\n 'regulatory--maximum-speed-limit-15--g3': icon606,\r\n 'regulatory--maximum-speed-limit-20--g1': icon607,\r\n 'regulatory--maximum-speed-limit-20--g3': icon608,\r\n 'regulatory--maximum-speed-limit-25--g1': icon609,\r\n 'regulatory--maximum-speed-limit-25--g2': icon610,\r\n 'regulatory--maximum-speed-limit-30--g1': icon611,\r\n 'regulatory--maximum-speed-limit-30--g3': icon612,\r\n 'regulatory--maximum-speed-limit-35--g1': icon613,\r\n 'regulatory--maximum-speed-limit-35--g2': icon614,\r\n 'regulatory--maximum-speed-limit-40--g1': icon615,\r\n 'regulatory--maximum-speed-limit-40--g3': icon616,\r\n 'regulatory--maximum-speed-limit-45--g1': icon617,\r\n 'regulatory--maximum-speed-limit-45--g3': icon618,\r\n 'regulatory--maximum-speed-limit-50--g1': icon619,\r\n 'regulatory--maximum-speed-limit-50--g3': icon620,\r\n 'regulatory--maximum-speed-limit-55--g2': icon621,\r\n 'regulatory--maximum-speed-limit-60--g1': icon622,\r\n 'regulatory--maximum-speed-limit-60--g3': icon623,\r\n 'regulatory--maximum-speed-limit-65--g1': icon624,\r\n 'regulatory--maximum-speed-limit-65--g2': icon625,\r\n 'regulatory--maximum-speed-limit-70--g1': icon626,\r\n 'regulatory--maximum-speed-limit-70--g3': icon627,\r\n 'regulatory--maximum-speed-limit-75--g2': icon628,\r\n 'regulatory--maximum-speed-limit-80--g1': icon629,\r\n 'regulatory--maximum-speed-limit-80--g3': icon630,\r\n 'regulatory--maximum-speed-limit-85--g2': icon631,\r\n 'regulatory--maximum-speed-limit-90--g1': icon632,\r\n 'regulatory--maximum-speed-limit-90--g3': icon633,\r\n 'regulatory--maximum-speed-limit-100--g1': icon634,\r\n 'regulatory--maximum-speed-limit-100--g3': icon635,\r\n 'regulatory--maximum-speed-limit-110--g1': icon636,\r\n 'regulatory--maximum-speed-limit-110--g3': icon637,\r\n 'regulatory--maximum-speed-limit-120--g1': icon638,\r\n 'regulatory--maximum-speed-limit-120--g3': icon639,\r\n 'regulatory--maximum-speed-limit-130--g1': icon640,\r\n 'regulatory--maximum-speed-limit-130--g3': icon641,\r\n 'regulatory--maximum-speed-limit-led-5--g2': icon642,\r\n 'regulatory--maximum-speed-limit-led-5--g3': icon643,\r\n 'regulatory--maximum-speed-limit-led-10--g1': icon644,\r\n 'regulatory--maximum-speed-limit-led-10--g2': icon645,\r\n 'regulatory--maximum-speed-limit-led-10--g3': icon646,\r\n 'regulatory--maximum-speed-limit-led-15--g2': icon647,\r\n 'regulatory--maximum-speed-limit-led-15--g3': icon648,\r\n 'regulatory--maximum-speed-limit-led-20--g1': icon649,\r\n 'regulatory--maximum-speed-limit-led-20--g2': icon650,\r\n 'regulatory--maximum-speed-limit-led-20--g3': icon651,\r\n 'regulatory--maximum-speed-limit-led-25--g1': icon652,\r\n 'regulatory--maximum-speed-limit-led-25--g2': icon653,\r\n 'regulatory--maximum-speed-limit-led-25--g3': icon654,\r\n 'regulatory--maximum-speed-limit-led-30--g1': icon655,\r\n 'regulatory--maximum-speed-limit-led-30--g2': icon656,\r\n 'regulatory--maximum-speed-limit-led-30--g3': icon657,\r\n 'regulatory--maximum-speed-limit-led-35--g1': icon658,\r\n 'regulatory--maximum-speed-limit-led-35--g2': icon659,\r\n 'regulatory--maximum-speed-limit-led-35--g3': icon660,\r\n 'regulatory--maximum-speed-limit-led-40--g1': icon661,\r\n 'regulatory--maximum-speed-limit-led-40--g2': icon662,\r\n 'regulatory--maximum-speed-limit-led-40--g3': icon663,\r\n 'regulatory--maximum-speed-limit-led-45--g2': icon664,\r\n 'regulatory--maximum-speed-limit-led-45--g3': icon665,\r\n 'regulatory--maximum-speed-limit-led-50--g1': icon666,\r\n 'regulatory--maximum-speed-limit-led-50--g2': icon667,\r\n 'regulatory--maximum-speed-limit-led-50--g3': icon668,\r\n 'regulatory--maximum-speed-limit-led-55--g2': icon669,\r\n 'regulatory--maximum-speed-limit-led-55--g3': icon670,\r\n 'regulatory--maximum-speed-limit-led-60--g1': icon671,\r\n 'regulatory--maximum-speed-limit-led-60--g2': icon672,\r\n 'regulatory--maximum-speed-limit-led-60--g3': icon673,\r\n 'regulatory--maximum-speed-limit-led-65--g2': icon674,\r\n 'regulatory--maximum-speed-limit-led-65--g3': icon675,\r\n 'regulatory--maximum-speed-limit-led-70--g1': icon676,\r\n 'regulatory--maximum-speed-limit-led-70--g2': icon677,\r\n 'regulatory--maximum-speed-limit-led-70--g3': icon678,\r\n 'regulatory--maximum-speed-limit-led-75--g1': icon679,\r\n 'regulatory--maximum-speed-limit-led-75--g2': icon680,\r\n 'regulatory--maximum-speed-limit-led-75--g3': icon681,\r\n 'regulatory--maximum-speed-limit-led-80--g1': icon682,\r\n 'regulatory--maximum-speed-limit-led-80--g2': icon683,\r\n 'regulatory--maximum-speed-limit-led-80--g3': icon684,\r\n 'regulatory--maximum-speed-limit-led-85--g2': icon685,\r\n 'regulatory--maximum-speed-limit-led-85--g3': icon686,\r\n 'regulatory--maximum-speed-limit-led-90--g1': icon687,\r\n 'regulatory--maximum-speed-limit-led-100--g1': icon688,\r\n 'regulatory--maximum-speed-limit-led-110--g1': icon689,\r\n 'regulatory--maximum-speed-limit-led-120--g1': icon690,\r\n 'regulatory--maximum-speed-limit-led-130--g1': icon691,\r\n 'regulatory--minimum-safe-distance--g1': icon692,\r\n 'regulatory--minimum-safe-distance--g2': icon693,\r\n 'regulatory--mopeds-and-bicycles-only--g1': icon694,\r\n 'regulatory--motorcycles-and-bicycles-only--g1': icon695,\r\n 'regulatory--motorcycles-only--g1': icon696,\r\n 'regulatory--motorcycles-only--g2': icon697,\r\n 'regulatory--night-speed-limit-5--g1': icon698,\r\n 'regulatory--night-speed-limit-10--g1': icon699,\r\n 'regulatory--night-speed-limit-15--g1': icon700,\r\n 'regulatory--night-speed-limit-20--g1': icon701,\r\n 'regulatory--night-speed-limit-25--g1': icon702,\r\n 'regulatory--night-speed-limit-30--g1': icon703,\r\n 'regulatory--night-speed-limit-35--g1': icon704,\r\n 'regulatory--night-speed-limit-40--g1': icon705,\r\n 'regulatory--night-speed-limit-45--g1': icon706,\r\n 'regulatory--night-speed-limit-50--g1': icon707,\r\n 'regulatory--night-speed-limit-55--g1': icon708,\r\n 'regulatory--night-speed-limit-60--g1': icon709,\r\n 'regulatory--night-speed-limit-65--g1': icon710,\r\n 'regulatory--night-speed-limit-70--g1': icon711,\r\n 'regulatory--night-speed-limit-75--g1': icon712,\r\n 'regulatory--night-speed-limit-80--g1': icon713,\r\n 'regulatory--night-speed-limit-85--g1': icon714,\r\n 'regulatory--no-abnormal-vehicles--g1': icon715,\r\n 'regulatory--no-atvs--g1': icon716,\r\n 'regulatory--no-bicycles--g1': icon717,\r\n 'regulatory--no-bicycles--g2': icon718,\r\n 'regulatory--no-bicycles--g3': icon719,\r\n 'regulatory--no-bicycles-carts-or-hand-carts--g1': icon720,\r\n 'regulatory--no-bicycles-mopeds-or-motorcycles--g1': icon721,\r\n 'regulatory--no-bicycles-mopeds-or-motorcycles--g2': icon722,\r\n 'regulatory--no-bicycles-or-hand-carts--g1': icon723,\r\n 'regulatory--no-bicycles-or-motorcycles--g1': icon724,\r\n 'regulatory--no-bicycles-tractors-or-carts--g1': icon725,\r\n 'regulatory--no-buses--g1': icon726,\r\n 'regulatory--no-buses--g2': icon727,\r\n 'regulatory--no-buses--g3': icon728,\r\n 'regulatory--no-caravan-trailers--g1': icon729,\r\n 'regulatory--no-caravans--g1': icon730,\r\n 'regulatory--no-caravans-or-caravan-trailers--g1': icon731,\r\n 'regulatory--no-cargo-loading--g1': icon732,\r\n 'regulatory--no-carts--g1': icon733,\r\n 'regulatory--no-carts--g2': icon734,\r\n 'regulatory--no-carts--g3': icon735,\r\n 'regulatory--no-carts-or-tractors--g1': icon736,\r\n 'regulatory--no-construction-vehicles--g1': icon737,\r\n 'regulatory--no-entry--g1': icon738,\r\n 'regulatory--no-equestrians--g1': icon739,\r\n 'regulatory--no-go-straight-or-turn-left--g1': icon740,\r\n 'regulatory--no-go-straight-or-turn-right--g1': icon741,\r\n 'regulatory--no-good-trailers--g2': icon742,\r\n 'regulatory--no-goods-vehicle-trailers--g1': icon743,\r\n 'regulatory--no-hand-carts--g1': icon744,\r\n 'regulatory--no-hand-carts--g2': icon745,\r\n 'regulatory--no-hand-carts-or-bicycles--g1': icon746,\r\n 'regulatory--no-hawkers--g1': icon747,\r\n 'regulatory--no-heavy-goods-vehicles--g1': icon748,\r\n 'regulatory--no-heavy-goods-vehicles--g2': icon749,\r\n 'regulatory--no-heavy-goods-vehicles--g3': icon750,\r\n 'regulatory--no-heavy-goods-vehicles--g4': icon751,\r\n 'regulatory--no-heavy-goods-vehicles--g5': icon752,\r\n 'regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g1': icon753,\r\n 'regulatory--no-heavy-goods-vehicles-motorcycles-or-bicycles--g2': icon754,\r\n 'regulatory--no-heavy-goods-vehicles-or-buses--g1': icon755,\r\n 'regulatory--no-heavy-goods-vehicles-or-tractors--g1': icon756,\r\n 'regulatory--no-heavy-goods-vehicles-or-trailers--g1': icon757,\r\n 'regulatory--no-horizontal-turn--g1': icon758,\r\n 'regulatory--no-horn--g1': icon759,\r\n 'regulatory--no-horn--g2': icon760,\r\n 'regulatory--no-lane-change-to-left--g1': icon761,\r\n 'regulatory--no-lane-change-to-right--g1': icon762,\r\n 'regulatory--no-learner-drivers--g1': icon763,\r\n 'regulatory--no-left-or-u-turn--g1': icon764,\r\n 'regulatory--no-left-turn--g1': icon765,\r\n 'regulatory--no-left-turn--g2': icon766,\r\n 'regulatory--no-left-turn--g3': icon767,\r\n 'regulatory--no-left-turn--g4': icon768,\r\n 'regulatory--no-left-turn--g5': icon769,\r\n 'regulatory--no-low-speed-vehicles--g1': icon770,\r\n 'regulatory--no-mopeds-or-bicycles--g1': icon771,\r\n 'regulatory--no-motor-vehicle-trailers--g1': icon772,\r\n 'regulatory--no-motor-vehicles--g1': icon773,\r\n 'regulatory--no-motor-vehicles--g3': icon774,\r\n 'regulatory--no-motor-vehicles--g4': icon775,\r\n 'regulatory--no-motor-vehicles--g5': icon776,\r\n 'regulatory--no-motor-vehicles--g6': icon777,\r\n 'regulatory--no-motor-vehicles--g7': icon778,\r\n 'regulatory--no-motor-vehicles-except-motorcycles--g1': icon779,\r\n 'regulatory--no-motor-vehicles-except-motorcycles--g2': icon780,\r\n 'regulatory--no-motor-vehicles-except-motorcycles--g3': icon781,\r\n 'regulatory--no-motor-vehicles-or-bicycles--g1': icon782,\r\n 'regulatory--no-motor-vehicles-or-buses--g1': icon783,\r\n 'regulatory--no-motor-vehicles-or-carts--g1': icon784,\r\n 'regulatory--no-motorcycles--g1': icon785,\r\n 'regulatory--no-motorcycles--g2': icon786,\r\n 'regulatory--no-overtaking--g1': icon787,\r\n 'regulatory--no-overtaking--g2': icon788,\r\n 'regulatory--no-overtaking--g4': icon789,\r\n 'regulatory--no-overtaking--g5': icon790,\r\n 'regulatory--no-overtaking--g6': icon791,\r\n 'regulatory--no-overtaking--g7': icon792,\r\n 'regulatory--no-overtaking-atvs--g1': icon793,\r\n 'regulatory--no-overtaking-by-heavy-goods-vehicles--g1': icon794,\r\n 'regulatory--no-parking--g1': icon795,\r\n 'regulatory--no-parking--g2': icon796,\r\n 'regulatory--no-parking--g3': icon797,\r\n 'regulatory--no-parking--g4': icon798,\r\n 'regulatory--no-parking--g5': icon799,\r\n 'regulatory--no-parking--g6': icon800,\r\n 'regulatory--no-parking--g7': icon801,\r\n 'regulatory--no-parking--g8': icon802,\r\n 'regulatory--no-parking--g9': icon803,\r\n 'regulatory--no-parking-bicycles-or-motorcycles--g1': icon804,\r\n 'regulatory--no-parking-bus-stop--g1': icon805,\r\n 'regulatory--no-parking-or-no-stopping--g1': icon806,\r\n 'regulatory--no-parking-or-no-stopping--g2': icon807,\r\n 'regulatory--no-parking-or-no-stopping--g3': icon808,\r\n 'regulatory--no-parking-or-no-stopping--g4': icon809,\r\n 'regulatory--no-parking-or-no-stopping--g5': icon810,\r\n 'regulatory--no-passenger-loading--g1': icon811,\r\n 'regulatory--no-pedestrians--g1': icon812,\r\n 'regulatory--no-pedestrians--g2': icon813,\r\n 'regulatory--no-pedestrians--g3': icon814,\r\n 'regulatory--no-pedestrians--g4': icon815,\r\n 'regulatory--no-pedestrians--g5': icon816,\r\n 'regulatory--no-pedestrians--g6': icon817,\r\n 'regulatory--no-pedestrians-bicycles-animals-or-hand-carts--g1': icon818,\r\n 'regulatory--no-pedestrians-or-bicycles--g1': icon819,\r\n 'regulatory--no-pedestrians-or-bicycles--g2': icon820,\r\n 'regulatory--no-pedestrians-or-bicycles--g3': icon821,\r\n 'regulatory--no-rickshaws--g1': icon822,\r\n 'regulatory--no-rickshaws--g2': icon823,\r\n 'regulatory--no-rickshaws--g3': icon824,\r\n 'regulatory--no-right-turn--g1': icon825,\r\n 'regulatory--no-right-turn--g2': icon826,\r\n 'regulatory--no-right-turn--g3': icon827,\r\n 'regulatory--no-right-turn-on-red--g1': icon828,\r\n 'regulatory--no-skiing--g1': icon829,\r\n 'regulatory--no-snowmobiles--g1': icon830,\r\n 'regulatory--no-snowmobiles--g2': icon831,\r\n 'regulatory--no-snowmobiles-or-atvs--g1': icon832,\r\n 'regulatory--no-stopping--g1': icon833,\r\n 'regulatory--no-stopping--g2': icon834,\r\n 'regulatory--no-stopping--g3': icon835,\r\n 'regulatory--no-stopping--g5': icon836,\r\n 'regulatory--no-stopping--g6': icon837,\r\n 'regulatory--no-stopping--g7': icon838,\r\n 'regulatory--no-stopping-on-pavement--g1': icon839,\r\n 'regulatory--no-straight-through--g1': icon840,\r\n 'regulatory--no-straight-through--g2': icon841,\r\n 'regulatory--no-studded-snow-chains--g1': icon842,\r\n 'regulatory--no-through-trucks--g1': icon843,\r\n 'regulatory--no-tour-buses--g1': icon844,\r\n 'regulatory--no-tractors--g1': icon845,\r\n 'regulatory--no-tractors-mopeds-or-bicycles--g1': icon846,\r\n 'regulatory--no-tractors-or-carts--g1': icon847,\r\n 'regulatory--no-trailers--g1': icon848,\r\n 'regulatory--no-tricycles--g1': icon849,\r\n 'regulatory--no-tricycles-or-hand-carts--g1': icon850,\r\n 'regulatory--no-turn-on-red--g1': icon851,\r\n 'regulatory--no-turn-on-red--g2': icon852,\r\n 'regulatory--no-turn-on-red--g3': icon853,\r\n 'regulatory--no-turns--g1': icon854,\r\n 'regulatory--no-turns--g2': icon855,\r\n 'regulatory--no-two-stage-right-turn-for-mopeds--g1': icon856,\r\n 'regulatory--no-u-turn--g1': icon857,\r\n 'regulatory--no-u-turn--g2': icon858,\r\n 'regulatory--no-u-turn--g3': icon859,\r\n 'regulatory--no-vehicles-carrying-dangerous-goods--g1': icon860,\r\n 'regulatory--no-vehicles-carrying-dangerous-goods--g2': icon861,\r\n 'regulatory--no-vehicles-carrying-dangerous-goods--g3': icon862,\r\n 'regulatory--no-vehicles-carrying-dangerous-goods--g4': icon863,\r\n 'regulatory--no-vehicles-carrying-dangerous-water-pollutants--g1': icon864,\r\n 'regulatory--no-vehicles-carrying-dangerous-water-pollutants--g2': icon865,\r\n 'regulatory--no-vehicles-carrying-explosives--g1': icon866,\r\n 'regulatory--no-vehicles-carrying-explosives-or-dangerous-water-pollutants--g1': icon867,\r\n 'regulatory--one-way-left--g1': icon868,\r\n 'regulatory--one-way-left--g2': icon869,\r\n 'regulatory--one-way-left--g3': icon870,\r\n 'regulatory--one-way-right--g1': icon871,\r\n 'regulatory--one-way-right--g2': icon872,\r\n 'regulatory--one-way-right--g3': icon873,\r\n 'regulatory--one-way-straight--g1': icon874,\r\n 'regulatory--one-way-straight--g3': icon875,\r\n 'regulatory--parking-fee-station--g1': icon876,\r\n 'regulatory--parking-restrictions--g1': icon877,\r\n 'regulatory--parking-restrictions--g2': icon878,\r\n 'regulatory--parking-restrictions--g3': icon879,\r\n 'regulatory--pass-on-either-side--g1': icon880,\r\n 'regulatory--pass-on-either-side--g2': icon881,\r\n 'regulatory--pass-on-either-side--g3': icon882,\r\n 'regulatory--pass-with-care--g1': icon883,\r\n 'regulatory--passing-lane-ahead--g1': icon884,\r\n 'regulatory--pedestrians-bicycles-permitted--g1': icon885,\r\n 'regulatory--pedestrians-keep-left--g1': icon886,\r\n 'regulatory--pedestrians-only--g1': icon887,\r\n 'regulatory--pedestrians-only--g2': icon888,\r\n 'regulatory--pedestrians-only--g3': icon889,\r\n 'regulatory--pedestrians-priority-zone--g1': icon890,\r\n 'regulatory--pedestrians-push-button--g1': icon891,\r\n 'regulatory--pedestrians-push-button--g2': icon892,\r\n 'regulatory--priority-over-oncoming-vehicles--g1': icon893,\r\n 'regulatory--priority-over-oncoming-vehicles--g2': icon894,\r\n 'regulatory--priority-road--g1': icon895,\r\n 'regulatory--priority-road--g2': icon896,\r\n 'regulatory--radar-enforced--g1': icon897,\r\n 'regulatory--reserved-parking--g1': icon898,\r\n 'regulatory--reversible-lanes--g1': icon899,\r\n 'regulatory--reversible-lanes--g2': icon900,\r\n 'regulatory--road-closed--g1': icon901,\r\n 'regulatory--road-closed--g2': icon902,\r\n 'regulatory--road-closed-to-vehicles--g1': icon903,\r\n 'regulatory--road-closed-to-vehicles--g3': icon904,\r\n 'regulatory--roundabout--g1': icon905,\r\n 'regulatory--roundabout--g2': icon906,\r\n 'regulatory--roundabout--g3': icon907,\r\n 'regulatory--shared-path-bicycles-and-pedestrians--g1': icon908,\r\n 'regulatory--shared-path-pedestrians-and-bicycles--g1': icon909,\r\n 'regulatory--sidewalk-closed--g1': icon910,\r\n 'regulatory--slanted-parking--g1': icon911,\r\n 'regulatory--snow-chains--g1': icon912,\r\n 'regulatory--snow-chains--g2': icon913,\r\n 'regulatory--snow-chains--g3': icon914,\r\n 'regulatory--snowmobiles-only--g1': icon915,\r\n 'regulatory--snowmobiles-permitted--g1': icon916,\r\n 'regulatory--speed-limit-zone--g1': icon917,\r\n 'regulatory--speeding-fines-increased--g1': icon918,\r\n 'regulatory--state-route--g1': icon919,\r\n 'regulatory--stay-in-lane--g1': icon920,\r\n 'regulatory--stop--g1': icon921,\r\n 'regulatory--stop--g2': icon922,\r\n 'regulatory--stop--g3': icon923,\r\n 'regulatory--stop--g4': icon924,\r\n 'regulatory--stop--g5': icon925,\r\n 'regulatory--stop--g6': icon926,\r\n 'regulatory--stop--g7': icon927,\r\n 'regulatory--stop--g8': icon928,\r\n 'regulatory--stop--g9': icon929,\r\n 'regulatory--stop--g10': icon930,\r\n 'regulatory--stop-here-on-red-or-flashing-light--g1': icon931,\r\n 'regulatory--stop-here-on-red-or-flashing-light--g2': icon932,\r\n 'regulatory--stop-signals--g1': icon933,\r\n 'regulatory--stop-signals--g2': icon934,\r\n 'regulatory--tanks-only--g1': icon935,\r\n 'regulatory--taxi-only--g1': icon936,\r\n 'regulatory--text--g1': icon937,\r\n 'regulatory--text--g2': icon938,\r\n 'regulatory--toll-pass-only--g1': icon939,\r\n 'regulatory--tractors-only--g1': icon940,\r\n 'regulatory--traffic-signal-photo-enforced--g1': icon941,\r\n 'regulatory--trams-and-buses-only--g1': icon942,\r\n 'regulatory--trams-only--g1': icon943,\r\n 'regulatory--triple-lanes--g1': icon944,\r\n 'regulatory--triple-lanes-go-straight-center-lane--g1': icon945,\r\n 'regulatory--triple-lanes-turn-left-center-lane--g1': icon946,\r\n 'regulatory--triple-lanes-turn-right-center-lane--g1': icon947,\r\n 'regulatory--truck-route--g1': icon948,\r\n 'regulatory--truck-speed-limit-5--g1': icon949,\r\n 'regulatory--truck-speed-limit-10--g1': icon950,\r\n 'regulatory--truck-speed-limit-15--g1': icon951,\r\n 'regulatory--truck-speed-limit-20--g1': icon952,\r\n 'regulatory--truck-speed-limit-25--g1': icon953,\r\n 'regulatory--truck-speed-limit-30--g1': icon954,\r\n 'regulatory--truck-speed-limit-35--g1': icon955,\r\n 'regulatory--truck-speed-limit-40--g1': icon956,\r\n 'regulatory--truck-speed-limit-45--g1': icon957,\r\n 'regulatory--truck-speed-limit-50--g1': icon958,\r\n 'regulatory--truck-speed-limit-55--g1': icon959,\r\n 'regulatory--truck-speed-limit-60--g1': icon960,\r\n 'regulatory--truck-speed-limit-65--g1': icon961,\r\n 'regulatory--truck-speed-limit-70--g1': icon962,\r\n 'regulatory--truck-speed-limit-75--g1': icon963,\r\n 'regulatory--truck-speed-limit-80--g1': icon964,\r\n 'regulatory--truck-speed-limit-85--g1': icon965,\r\n 'regulatory--trucks-and-buses-only--g1': icon966,\r\n 'regulatory--trucks-on-right--g1': icon967,\r\n 'regulatory--trucks-only--g1': icon968,\r\n 'regulatory--turn-left--g1': icon969,\r\n 'regulatory--turn-left--g2': icon970,\r\n 'regulatory--turn-left--g3': icon971,\r\n 'regulatory--turn-left-ahead--g1': icon972,\r\n 'regulatory--turn-left-ahead--g2': icon973,\r\n 'regulatory--turn-left-or-right--g1': icon974,\r\n 'regulatory--turn-left-or-right--g2': icon975,\r\n 'regulatory--turn-left-or-right--g3': icon976,\r\n 'regulatory--turn-left-or-u-turn--g1': icon977,\r\n 'regulatory--turn-right--g1': icon978,\r\n 'regulatory--turn-right--g2': icon979,\r\n 'regulatory--turn-right--g3': icon980,\r\n 'regulatory--turn-right-ahead--g1': icon981,\r\n 'regulatory--turn-right-ahead--g2': icon982,\r\n 'regulatory--turning-vehicles-yield-to-pedestrians--g1': icon983,\r\n 'regulatory--two-stage-right-turn-for-mopeds--g1': icon984,\r\n 'regulatory--two-way--g1': icon985,\r\n 'regulatory--u-turn--g1': icon986,\r\n 'regulatory--u-turn--g2': icon987,\r\n 'regulatory--u-turn--g3': icon988,\r\n 'regulatory--use-crosswalk--g1': icon989,\r\n 'regulatory--vehicles-carrying-dangerous-goods-only--g1': icon990,\r\n 'regulatory--vehicles-carrying-dangerous-goods-permitted--g1': icon991,\r\n 'regulatory--vehicles-carrying-explosives-only--g1': icon992,\r\n 'regulatory--vehicles-carrying-hazardous-goods-permitted--g1': icon993,\r\n 'regulatory--vehicles-only--g1': icon994,\r\n 'regulatory--wear-seat-belt--g1': icon995,\r\n 'regulatory--wear-seat-belt--g2': icon996,\r\n 'regulatory--wear-seat-belt--g3': icon997,\r\n 'regulatory--weight-limit--g1': icon998,\r\n 'regulatory--weight-limit--g2': icon999,\r\n 'regulatory--weight-limit--g3': icon1000,\r\n 'regulatory--weight-limit--g4': icon1001,\r\n 'regulatory--weight-limit--g5': icon1002,\r\n 'regulatory--weight-limit--g6': icon1003,\r\n 'regulatory--weight-limit--g7': icon1004,\r\n 'regulatory--weight-limit-per-axle--g1': icon1005,\r\n 'regulatory--weight-limit-per-tandem-axle--g1': icon1006,\r\n 'regulatory--weight-limit-with-trucks--g1': icon1007,\r\n 'regulatory--width-limit--g1': icon1008,\r\n 'regulatory--wrong-way--g1': icon1009,\r\n 'regulatory--yield--g1': icon1010,\r\n 'regulatory--yield-or-stop-for-pedestrians--g1': icon1011,\r\n 'regulatory--your-speed--g1': icon1012,\r\n 'warning--accident-area--g1': icon1013,\r\n 'warning--accident-area--g2': icon1014,\r\n 'warning--accident-area--g3': icon1015,\r\n 'warning--accident-area--g4': icon1016,\r\n 'warning--accident-area--g5': icon1017,\r\n 'warning--accident-area--g6': icon1018,\r\n 'warning--accident-area--g7': icon1019,\r\n 'warning--accident-area--g8': icon1020,\r\n 'warning--added-lane-from-entering-roadway--g1': icon1021,\r\n 'warning--added-lane-from-entering-roadway--g2': icon1022,\r\n 'warning--added-lane-left--g1': icon1023,\r\n 'warning--added-lane-right--g1': icon1024,\r\n 'warning--animal-drawn-vehicles--g1': icon1025,\r\n 'warning--arch-bridge--g1': icon1026,\r\n 'warning--atv-and-snowmobiles--g1': icon1027,\r\n 'warning--atv-crossing--g1': icon1028,\r\n 'warning--atv-crossing--g2': icon1029,\r\n 'warning--axle-restriction--g1': icon1030,\r\n 'warning--bear-crossing--g1': icon1031,\r\n 'warning--bear-crossing--g2': icon1032,\r\n 'warning--bicycles-and-others--g1': icon1033,\r\n 'warning--bicycles-caution-on-rail-tracks--g1': icon1034,\r\n 'warning--bicycles-crossing--g1': icon1035,\r\n 'warning--bicycles-crossing--g2': icon1036,\r\n 'warning--bicycles-crossing--g3': icon1037,\r\n 'warning--bicycles-crossing--g4': icon1038,\r\n 'warning--bollard--g1': icon1039,\r\n 'warning--bridge--g1': icon1040,\r\n 'warning--bridge--g2': icon1041,\r\n 'warning--bus-stop-ahead--g1': icon1042,\r\n 'warning--bus-stop-ahead--g2': icon1043,\r\n 'warning--bus-stop-ahead--g3': icon1044,\r\n 'warning--camel-crossing--g1': icon1045,\r\n 'warning--camel-crossing--g2': icon1046,\r\n 'warning--camera--g1': icon1047,\r\n 'warning--camera--g2': icon1048,\r\n 'warning--carts--g1': icon1049,\r\n 'warning--carts--g2': icon1050,\r\n 'warning--checkpoint--g1': icon1051,\r\n 'warning--children--g1': icon1052,\r\n 'warning--children--g2': icon1053,\r\n 'warning--children--g3': icon1054,\r\n 'warning--children--g4': icon1055,\r\n 'warning--children--g6': icon1056,\r\n 'warning--cliff--g1': icon1057,\r\n 'warning--cliff--g2': icon1058,\r\n 'warning--closed-lane-in-triple-lanes--g1': icon1059,\r\n 'warning--closed-lane-in-triple-lanes--g2': icon1060,\r\n 'warning--construction-ahead--g1': icon1061,\r\n 'warning--crossroads--g1': icon1062,\r\n 'warning--crossroads--g2': icon1063,\r\n 'warning--crossroads--g3': icon1064,\r\n 'warning--crossroads--g4': icon1065,\r\n 'warning--crossroads--g5': icon1066,\r\n 'warning--crossroads--g6': icon1067,\r\n 'warning--crossroads-with-priority-to-the-right--g1': icon1068,\r\n 'warning--curve-left--g1': icon1069,\r\n 'warning--curve-left--g2': icon1070,\r\n 'warning--curve-left--g3': icon1071,\r\n 'warning--curve-left-with-junction--g1': icon1072,\r\n 'warning--curve-out-intersection-left--g1': icon1073,\r\n 'warning--curve-out-intersection-right--g1': icon1074,\r\n 'warning--curve-right--g1': icon1075,\r\n 'warning--curve-right--g2': icon1076,\r\n 'warning--curve-right--g3': icon1077,\r\n 'warning--curve-right-with-junction--g1': icon1078,\r\n 'warning--dangerous-crosswinds-left--g1': icon1079,\r\n 'warning--dangerous-crosswinds-left--g2': icon1080,\r\n 'warning--dangerous-crosswinds-left--g4': icon1081,\r\n 'warning--dangerous-crosswinds-right--g1': icon1082,\r\n 'warning--dangerous-crosswinds-right--g2': icon1083,\r\n 'warning--dangerous-crosswinds-right--g3': icon1084,\r\n 'warning--dangerous-crosswinds-right--g4': icon1085,\r\n 'warning--dead-end--g1': icon1086,\r\n 'warning--dead-end--g2': icon1087,\r\n 'warning--dead-end--g3': icon1088,\r\n 'warning--dead-end-go-left--g1': icon1089,\r\n 'warning--dead-end-go-right--g1': icon1090,\r\n 'warning--descent-or-climbing-lanes-in-triple-lanes--g1': icon1091,\r\n 'warning--detour-ahead--g1': icon1092,\r\n 'warning--detour-or-construction-ahead--g1': icon1093,\r\n 'warning--dip--g1': icon1094,\r\n 'warning--dip--g2': icon1095,\r\n 'warning--disabled-persons-crossing--g1': icon1096,\r\n 'warning--disabled-persons-crossing--g2': icon1097,\r\n 'warning--divided-highway--g1': icon1098,\r\n 'warning--divided-highway--g2': icon1099,\r\n 'warning--divided-highway--g3': icon1100,\r\n 'warning--divided-highway--g4': icon1101,\r\n 'warning--divided-highway--g5': icon1102,\r\n 'warning--divided-highway--g6': icon1103,\r\n 'warning--divided-highway--g7': icon1104,\r\n 'warning--divided-highway--g8': icon1105,\r\n 'warning--divided-highway--g9': icon1106,\r\n 'warning--divided-highway-ends--g1': icon1107,\r\n 'warning--divided-highway-ends--g2': icon1108,\r\n 'warning--divided-highway-ends--g3': icon1109,\r\n 'warning--divided-highway-ends--g4': icon1110,\r\n 'warning--divided-highway-on-left--g1': icon1111,\r\n 'warning--divided-highway-on-left--g2': icon1112,\r\n 'warning--divided-highway-on-right--g1': icon1113,\r\n 'warning--divided-highway-on-right--g2': icon1114,\r\n 'warning--divided-highway-to-left--g1': icon1115,\r\n 'warning--divided-highway-to-right--g1': icon1116,\r\n 'warning--domestic-animals--g1': icon1117,\r\n 'warning--domestic-animals--g2': icon1118,\r\n 'warning--domestic-animals--g3': icon1119,\r\n 'warning--domestic-animals--g4': icon1120,\r\n 'warning--domestic-animals--g5': icon1121,\r\n 'warning--domestic-animals--g6': icon1122,\r\n 'warning--domestic-animals--g7': icon1123,\r\n 'warning--domestic-animals--g8': icon1124,\r\n 'warning--double-curve-first-left--g1': icon1125,\r\n 'warning--double-curve-first-left--g2': icon1126,\r\n 'warning--double-curve-first-right--g1': icon1127,\r\n 'warning--double-curve-first-right--g2': icon1128,\r\n 'warning--double-descent--g1': icon1129,\r\n 'warning--double-reverse-curve-left--g1': icon1130,\r\n 'warning--double-reverse-curve-left--g2': icon1131,\r\n 'warning--double-reverse-curve-right--g1': icon1132,\r\n 'warning--double-reverse-curve-right--g2': icon1133,\r\n 'warning--double-side-roads-left--g1': icon1134,\r\n 'warning--double-side-roads-left--g3': icon1135,\r\n 'warning--double-side-roads-right--g1': icon1136,\r\n 'warning--double-side-roads-right--g3': icon1137,\r\n 'warning--double-turn-first-left--g1': icon1138,\r\n 'warning--double-turn-first-right--g1': icon1139,\r\n 'warning--dual-lanes-all-directions-on-left--g1': icon1140,\r\n 'warning--dual-lanes-all-directions-on-right--g1': icon1141,\r\n 'warning--dual-lanes-go-straight-or-turn-left--g1': icon1142,\r\n 'warning--dual-lanes-go-straight-or-turn-right--g1': icon1143,\r\n 'warning--dual-lanes-left-turn--g1': icon1144,\r\n 'warning--dual-lanes-left-turn-or-go-straight--g1': icon1145,\r\n 'warning--dual-lanes-right-turn--g1': icon1146,\r\n 'warning--dual-lanes-right-turn-or-go-straight--g1': icon1147,\r\n 'warning--dual-lanes-turn-left--g1': icon1148,\r\n 'warning--dual-lanes-turn-left-or-right--g1': icon1149,\r\n 'warning--dual-lanes-turn-left-or-right--g2': icon1150,\r\n 'warning--dual-lanes-turn-left-or-right--g3': icon1151,\r\n 'warning--dual-lanes-turn-left-or-right--g4': icon1152,\r\n 'warning--dual-lanes-turn-right--g1': icon1153,\r\n 'warning--dual-path-cyclists-and-pedestrians--g1': icon1154,\r\n 'warning--electricity--g1': icon1155,\r\n 'warning--electricity--g2': icon1156,\r\n 'warning--elephant-crossing--g1': icon1157,\r\n 'warning--emergency-vehicles--g1': icon1158,\r\n 'warning--emu-crossing--g1': icon1159,\r\n 'warning--emu-crossing--g2': icon1160,\r\n 'warning--entering-roadway-merge--g1': icon1161,\r\n 'warning--entering-roadway-merge--g2': icon1162,\r\n 'warning--equestrians-crossing--g1': icon1163,\r\n 'warning--equestrians-crossing--g2': icon1164,\r\n 'warning--expressway--g1': icon1165,\r\n 'warning--falling-rocks-or-debris-left--g1': icon1166,\r\n 'warning--falling-rocks-or-debris-left--g2': icon1167,\r\n 'warning--falling-rocks-or-debris-left--g3': icon1168,\r\n 'warning--falling-rocks-or-debris-left--g4': icon1169,\r\n 'warning--falling-rocks-or-debris-right--g1': icon1170,\r\n 'warning--falling-rocks-or-debris-right--g2': icon1171,\r\n 'warning--falling-rocks-or-debris-right--g3': icon1172,\r\n 'warning--falling-rocks-or-debris-right--g4': icon1173,\r\n 'warning--ferry--g1': icon1174,\r\n 'warning--flaggers-in-road--g1': icon1175,\r\n 'warning--flaggers-in-road--g2': icon1176,\r\n 'warning--foggy-road--g1': icon1177,\r\n 'warning--foggy-road--g2': icon1178,\r\n 'warning--ford--g1': icon1179,\r\n 'warning--forest--g1': icon1180,\r\n 'warning--fresh-oil--g1': icon1181,\r\n 'warning--frog-crossing--g1': icon1182,\r\n 'warning--gate--g1': icon1183,\r\n 'warning--gate--g2': icon1184,\r\n 'warning--gate-left--g1': icon1185,\r\n 'warning--gate-right--g1': icon1186,\r\n 'warning--go-left--g1': icon1187,\r\n 'warning--go-right--g1': icon1188,\r\n 'warning--golf-carts-crossing--g1': icon1189,\r\n 'warning--gravel-road-surface--g1': icon1190,\r\n 'warning--hairpin-curve-left--g1': icon1191,\r\n 'warning--hairpin-curve-left--g2': icon1192,\r\n 'warning--hairpin-curve-left--g3': icon1193,\r\n 'warning--hairpin-curve-right--g1': icon1194,\r\n 'warning--hairpin-curve-right--g3': icon1195,\r\n 'warning--height-restriction--g2': icon1196,\r\n 'warning--height-restriction--g3': icon1197,\r\n 'warning--height-restriction--g4': icon1198,\r\n 'warning--height-restriction--g5': icon1199,\r\n 'warning--horizontal-alignment-left--g1': icon1200,\r\n 'warning--horizontal-alignment-left--g3': icon1201,\r\n 'warning--horizontal-alignment-right--g1': icon1202,\r\n 'warning--horizontal-alignment-right--g3': icon1203,\r\n 'warning--horse-crossing--g1': icon1204,\r\n 'warning--icy-road--g1': icon1205,\r\n 'warning--junction-with-a-side-road-acute-left--g1': icon1206,\r\n 'warning--junction-with-a-side-road-acute-left--g2': icon1207,\r\n 'warning--junction-with-a-side-road-acute-right--g1': icon1208,\r\n 'warning--junction-with-a-side-road-acute-right--g2': icon1209,\r\n 'warning--junction-with-a-side-road-perpendicular-left--g1': icon1210,\r\n 'warning--junction-with-a-side-road-perpendicular-left--g2': icon1211,\r\n 'warning--junction-with-a-side-road-perpendicular-left--g3': icon1212,\r\n 'warning--junction-with-a-side-road-perpendicular-left--g4': icon1213,\r\n 'warning--junction-with-a-side-road-perpendicular-right--g1': icon1214,\r\n 'warning--junction-with-a-side-road-perpendicular-right--g2': icon1215,\r\n 'warning--junction-with-a-side-road-perpendicular-right--g3': icon1216,\r\n 'warning--junction-with-a-side-road-perpendicular-right--g4': icon1217,\r\n 'warning--junction-with-merge-from-left--g1': icon1218,\r\n 'warning--junction-with-merge-from-right--g1': icon1219,\r\n 'warning--junction-with-side-roads--g1': icon1220,\r\n 'warning--kangaloo-crossing--g1': icon1221,\r\n 'warning--keep-distance--g1': icon1222,\r\n 'warning--keep-left--g1': icon1223,\r\n 'warning--keep-right--g1': icon1224,\r\n 'warning--kiwi-crossing--g1': icon1225,\r\n 'warning--kiwi-crossing--g2': icon1226,\r\n 'warning--koala-crossing--g1': icon1227,\r\n 'warning--koala-crossing--g2': icon1228,\r\n 'warning--koala-crossing--g3': icon1229,\r\n 'warning--koala-crossing--g4': icon1230,\r\n 'warning--lane-closed-in-dual-lanes-left--g1': icon1231,\r\n 'warning--lane-closed-in-dual-lanes-left--g2': icon1232,\r\n 'warning--lane-closed-in-dual-lanes-right--g1': icon1233,\r\n 'warning--lane-closed-in-dual-lanes-right--g2': icon1234,\r\n 'warning--length-restriction--g1': icon1235,\r\n 'warning--length-restriction--g2': icon1236,\r\n 'warning--light-rail-transit-vehicles--g1': icon1237,\r\n 'warning--limited-lighting-under-trees--g1': icon1238,\r\n 'warning--logging-vehicles--g1': icon1239,\r\n 'warning--loop-270-degree--g1': icon1240,\r\n 'warning--loop-pretzel--g1': icon1241,\r\n 'warning--loose-road-surface--g1': icon1242,\r\n 'warning--loose-road-surface--g2': icon1243,\r\n 'warning--loose-road-surface--g3': icon1244,\r\n 'warning--loose-road-surface--g4': icon1245,\r\n 'warning--low-flying-aircraft--g1': icon1246,\r\n 'warning--low-flying-aircraft--g2': icon1247,\r\n 'warning--low-flying-aircraft--g3': icon1248,\r\n 'warning--low-flying-aircraft--g4': icon1249,\r\n 'warning--low-flying-aircraft--g5': icon1250,\r\n 'warning--low-flying-aircraft--g6': icon1251,\r\n 'warning--low-flying-aircraft--g7': icon1252,\r\n 'warning--low-flying-aircraft--g8': icon1253,\r\n 'warning--low-ground-clearance--g1': icon1254,\r\n 'warning--low-ground-clearance--g2': icon1255,\r\n 'warning--low-ground-clearance--g3': icon1256,\r\n 'warning--monkey-crossing--g1': icon1257,\r\n 'warning--motorcycles-crossing--g1': icon1258,\r\n 'warning--narrow-bridge--g1': icon1259,\r\n 'warning--narrow-bridge--g2': icon1260,\r\n 'warning--narrow-bridge--g3': icon1261,\r\n 'warning--no-passing-zone--g1': icon1262,\r\n 'warning--no-passing-zone--g2': icon1263,\r\n 'warning--occupied-lanes--g1': icon1264,\r\n 'warning--offset-roads--g1': icon1265,\r\n 'warning--offset-roads--g2': icon1266,\r\n 'warning--offset-roads--g3': icon1267,\r\n 'warning--offset-roads--g4': icon1268,\r\n 'warning--opening-or-swing-bridge--g1': icon1269,\r\n 'warning--opening-or-swing-bridge--g2': icon1270,\r\n 'warning--other-danger--g1': icon1271,\r\n 'warning--other-danger--g2': icon1272,\r\n 'warning--other-danger--g3': icon1273,\r\n 'warning--panda-crossing--g1': icon1274,\r\n 'warning--pass-left-or-right--g1': icon1275,\r\n 'warning--pass-left-or-right--g2': icon1276,\r\n 'warning--pass-left-or-right--g3': icon1277,\r\n 'warning--pavement-ahead--g1': icon1278,\r\n 'warning--pavement-ends--g1': icon1279,\r\n 'warning--pavement-ends--g2': icon1280,\r\n 'warning--pavement-ends--g3': icon1281,\r\n 'warning--pavement-ends--g4': icon1282,\r\n 'warning--pavement-ends--g5': icon1283,\r\n 'warning--pedestrians-crossing--g1': icon1284,\r\n 'warning--pedestrians-crossing--g4': icon1285,\r\n 'warning--pedestrians-crossing--g5': icon1286,\r\n 'warning--pedestrians-crossing--g6': icon1287,\r\n 'warning--pedestrians-crossing--g7': icon1288,\r\n 'warning--pedestrians-crossing--g8': icon1289,\r\n 'warning--pedestrians-crossing--g9': icon1290,\r\n 'warning--pedestrians-crossing--g10': icon1291,\r\n 'warning--pedestrians-crossing--g11': icon1292,\r\n 'warning--pedestrians-crossing--g12': icon1293,\r\n 'warning--playground--g1': icon1294,\r\n 'warning--playground--g3': icon1295,\r\n 'warning--polar-bear-crossing--g1': icon1296,\r\n 'warning--quay-or-river-bank--g1': icon1297,\r\n 'warning--quay-or-river-bank--g2': icon1298,\r\n 'warning--quay-or-river-bank--g3': icon1299,\r\n 'warning--quay-or-river-bank--g4': icon1300,\r\n 'warning--rabbit-crossing--g1': icon1301,\r\n 'warning--raccoon-crossing--g1': icon1302,\r\n 'warning--railroad-crossing--g1': icon1303,\r\n 'warning--railroad-crossing--g2': icon1304,\r\n 'warning--railroad-crossing--g3': icon1305,\r\n 'warning--railroad-crossing--g4': icon1306,\r\n 'warning--railroad-crossing-with-barriers--g1': icon1307,\r\n 'warning--railroad-crossing-with-barriers--g2': icon1308,\r\n 'warning--railroad-crossing-with-barriers--g3': icon1309,\r\n 'warning--railroad-crossing-with-barriers--g4': icon1310,\r\n 'warning--railroad-crossing-with-barriers--g5': icon1311,\r\n 'warning--railroad-crossing-with-barriers--g6': icon1312,\r\n 'warning--railroad-crossing-with-barriers--g7': icon1313,\r\n 'warning--railroad-crossing-without-barriers--g1': icon1314,\r\n 'warning--railroad-crossing-without-barriers--g2': icon1315,\r\n 'warning--railroad-crossing-without-barriers--g3': icon1316,\r\n 'warning--railroad-crossing-without-barriers--g4': icon1317,\r\n 'warning--railroad-crossing-without-barriers--g5': icon1318,\r\n 'warning--railroad-crossing-without-barriers--g6': icon1319,\r\n 'warning--railroad-intersection--g1': icon1320,\r\n 'warning--railroad-intersection--g2': icon1321,\r\n 'warning--railroad-intersection--g3': icon1322,\r\n 'warning--railroad-intersection--g4': icon1323,\r\n 'warning--railroad-intersection--g5': icon1324,\r\n 'warning--railroad-intersection--g6': icon1325,\r\n 'warning--railroad-intersection--g7': icon1326,\r\n 'warning--railroad-intersection--g8': icon1327,\r\n 'warning--railroad-intersection--g9': icon1328,\r\n 'warning--ramp-closed--g1': icon1329,\r\n 'warning--reduced-maximum-speed-limit--g1': icon1330,\r\n 'warning--reserved-lane--g1': icon1331,\r\n 'warning--restricted-zone--g1': icon1332,\r\n 'warning--reversible-lanes--g1': icon1333,\r\n 'warning--reversible-lanes--g2': icon1334,\r\n 'warning--rickshaws-crossing--g1': icon1335,\r\n 'warning--road-blocks--g1': icon1336,\r\n 'warning--road-bump--g1': icon1337,\r\n 'warning--road-bump--g2': icon1338,\r\n 'warning--road-bump--g3': icon1339,\r\n 'warning--road-bump-with-speed-limit--g1': icon1340,\r\n 'warning--road-closed--g3': icon1341,\r\n 'warning--road-narrows--g1': icon1342,\r\n 'warning--road-narrows--g2': icon1343,\r\n 'warning--road-narrows-left--g1': icon1344,\r\n 'warning--road-narrows-left--g2': icon1345,\r\n 'warning--road-narrows-left-ahead--g1': icon1346,\r\n 'warning--road-narrows-right--g1': icon1347,\r\n 'warning--road-narrows-right--g2': icon1348,\r\n 'warning--road-narrows-right-ahead--g1': icon1349,\r\n 'warning--road-toll-ahead--g1': icon1350,\r\n 'warning--road-widens--g1': icon1351,\r\n 'warning--road-widens-left--g1': icon1352,\r\n 'warning--road-widens-right--g1': icon1353,\r\n 'warning--roadworks--g1': icon1354,\r\n 'warning--roadworks--g2': icon1355,\r\n 'warning--roadworks--g3': icon1356,\r\n 'warning--roadworks--g5': icon1357,\r\n 'warning--roadworks--g6': icon1358,\r\n 'warning--roadworks--g8': icon1359,\r\n 'warning--roadworks--g9': icon1360,\r\n 'warning--roadworks--g10': icon1361,\r\n 'warning--roadworks--g11': icon1362,\r\n 'warning--roadworks-go-left-or-straight--g1': icon1363,\r\n 'warning--roadworks-go-right-or-straight--g1': icon1364,\r\n 'warning--roundabout--g1': icon1365,\r\n 'warning--roundabout--g2': icon1366,\r\n 'warning--roundabout--g3': icon1367,\r\n 'warning--roundabout--g4': icon1368,\r\n 'warning--roundabout--g5': icon1369,\r\n 'warning--roundabout--g6': icon1370,\r\n 'warning--roundabout--g7': icon1371,\r\n 'warning--ruts--g1': icon1372,\r\n 'warning--sand--g1': icon1373,\r\n 'warning--sand-drift--g1': icon1374,\r\n 'warning--school-zone--g2': icon1375,\r\n 'warning--severe-weather--g1': icon1376,\r\n 'warning--shared-lane-motorcycles-bicycles--g1': icon1377,\r\n 'warning--sharp-turn--g1': icon1378,\r\n 'warning--single-reverse-curve--g1': icon1379,\r\n 'warning--skewed-t-roads-left--g1': icon1380,\r\n 'warning--skewed-t-roads-left--g2': icon1381,\r\n 'warning--skewed-t-roads-left--g3': icon1382,\r\n 'warning--skewed-t-roads-right--g1': icon1383,\r\n 'warning--skewed-t-roads-right--g2': icon1384,\r\n 'warning--skewed-t-roads-right--g3': icon1385,\r\n 'warning--skiers--g1': icon1386,\r\n 'warning--skiers--g2': icon1387,\r\n 'warning--skiers--g3': icon1388,\r\n 'warning--slippery-bicycles--g1': icon1389,\r\n 'warning--slippery-motorcycles--g1': icon1390,\r\n 'warning--slippery-motorcycles--g2': icon1391,\r\n 'warning--slippery-road-surface--g1': icon1392,\r\n 'warning--slippery-road-surface--g2': icon1393,\r\n 'warning--slow--g1': icon1394,\r\n 'warning--snow-tractors--g1': icon1395,\r\n 'warning--snowmobiles--g1': icon1396,\r\n 'warning--snowmobiles--g2': icon1397,\r\n 'warning--snowmobiles--g3': icon1398,\r\n 'warning--snowmobiles-and-others--g1': icon1399,\r\n 'warning--soft-road-surface--g1': icon1400,\r\n 'warning--soft-road-surface--g2': icon1401,\r\n 'warning--soft-shoulder--g1': icon1402,\r\n 'warning--soft-shoulder--g2': icon1403,\r\n 'warning--soft-shoulder--g3': icon1404,\r\n 'warning--soft-shoulder--g4': icon1405,\r\n 'warning--speed-camera--g1': icon1406,\r\n 'warning--steep-ascent--g1': icon1407,\r\n 'warning--steep-ascent--g2': icon1408,\r\n 'warning--steep-ascent--g3': icon1409,\r\n 'warning--steep-ascent--g4': icon1410,\r\n 'warning--steep-ascent-and-descent--g1': icon1411,\r\n 'warning--steep-descent--g1': icon1412,\r\n 'warning--steep-descent--g2': icon1413,\r\n 'warning--steep-descent--g3': icon1414,\r\n 'warning--steep-descent--g4': icon1415,\r\n 'warning--steep-descent--g5': icon1416,\r\n 'warning--steep-descent--g6': icon1417,\r\n 'warning--stop-ahead--g1': icon1418,\r\n 'warning--stop-ahead--g3': icon1419,\r\n 'warning--stop-ahead--g4': icon1420,\r\n 'warning--stop-ahead--g5': icon1421,\r\n 'warning--stop-ahead--g6': icon1422,\r\n 'warning--t-roads--g1': icon1423,\r\n 'warning--t-roads--g2': icon1424,\r\n 'warning--tanks-crossing--g1': icon1425,\r\n 'warning--tanks-crossing--g2': icon1426,\r\n 'warning--texts--g1': icon1427,\r\n 'warning--texts--g2': icon1428,\r\n 'warning--texts--g3': icon1429,\r\n 'warning--towing--g1': icon1430,\r\n 'warning--tractors--g1': icon1431,\r\n 'warning--tractors--g2': icon1432,\r\n 'warning--tractors--g3': icon1433,\r\n 'warning--tractors--g4': icon1434,\r\n 'warning--tractors--g5': icon1435,\r\n 'warning--tractors--g6': icon1436,\r\n 'warning--tractors--g7': icon1437,\r\n 'warning--traffic-merges-at-signalized-intersections--g1': icon1438,\r\n 'warning--traffic-merges-left--g1': icon1439,\r\n 'warning--traffic-merges-left--g2': icon1440,\r\n 'warning--traffic-merges-left--g3': icon1441,\r\n 'warning--traffic-merges-left--g4': icon1442,\r\n 'warning--traffic-merges-left-and-right--g1': icon1443,\r\n 'warning--traffic-merges-left-buses--g1': icon1444,\r\n 'warning--traffic-merges-right--g1': icon1445,\r\n 'warning--traffic-merges-right--g2': icon1446,\r\n 'warning--traffic-merges-right--g3': icon1447,\r\n 'warning--traffic-merges-right-buses--g1': icon1448,\r\n 'warning--traffic-queues-likely--g1': icon1449,\r\n 'warning--traffic-queues-likely--g2': icon1450,\r\n 'warning--traffic-queues-likely--g3': icon1451,\r\n 'warning--traffic-queues-likely--g4': icon1452,\r\n 'warning--traffic-queues-likely--g5': icon1453,\r\n 'warning--traffic-signals--g1': icon1454,\r\n 'warning--traffic-signals--g2': icon1455,\r\n 'warning--traffic-signals--g3': icon1456,\r\n 'warning--traffic-signals--g4': icon1457,\r\n 'warning--traffic-signals--g5': icon1458,\r\n 'warning--traffic-signals--g6': icon1459,\r\n 'warning--traffic-slow--g1': icon1460,\r\n 'warning--trail-crossing--g1': icon1461,\r\n 'warning--trail-crossing--g2': icon1462,\r\n 'warning--trail-crossing--g3': icon1463,\r\n 'warning--trail-crossing--g4': icon1464,\r\n 'warning--trail-crossing--g5': icon1465,\r\n 'warning--trail-crossing--g6': icon1466,\r\n 'warning--trams-crossing--g1': icon1467,\r\n 'warning--trams-crossing--g2': icon1468,\r\n 'warning--triple-curve-left--g1': icon1469,\r\n 'warning--triple-curve-right--g1': icon1470,\r\n 'warning--triple-lanes-left-turn--g1': icon1471,\r\n 'warning--triple-lanes-left-turn-or-go-straight--g1': icon1472,\r\n 'warning--triple-lanes-right-turn--g1': icon1473,\r\n 'warning--triple-lanes-right-turn-or-go-straight--g1': icon1474,\r\n 'warning--triple-lanes-with-directions--g1': icon1475,\r\n 'warning--triple-reverse-curve-left--g1': icon1476,\r\n 'warning--triple-reverse-curve-right--g1': icon1477,\r\n 'warning--trucks-crossing--g1': icon1478,\r\n 'warning--trucks-crossing--g2': icon1479,\r\n 'warning--trucks-rollover--g1': icon1480,\r\n 'warning--trucks-rollover--g2': icon1481,\r\n 'warning--trucks-rollover--g3': icon1482,\r\n 'warning--trucks-rollover--g4': icon1483,\r\n 'warning--trucks-rollover--g5': icon1484,\r\n 'warning--tunnel--g1': icon1485,\r\n 'warning--tunnel--g2': icon1486,\r\n 'warning--tunnel--g3': icon1487,\r\n 'warning--tunnel--g4': icon1488,\r\n 'warning--tunnel--g5': icon1489,\r\n 'warning--tunnel--g6': icon1490,\r\n 'warning--tunnel--g7': icon1491,\r\n 'warning--turn-left--g1': icon1492,\r\n 'warning--turn-left--g2': icon1493,\r\n 'warning--turn-left--g3': icon1494,\r\n 'warning--turn-left-or-right--g1': icon1495,\r\n 'warning--turn-right--g1': icon1496,\r\n 'warning--turn-right--g2': icon1497,\r\n 'warning--turn-right--g3': icon1498,\r\n 'warning--two-way-traffic--g1': icon1499,\r\n 'warning--two-way-traffic--g2': icon1500,\r\n 'warning--two-way-traffic--g3': icon1501,\r\n 'warning--two-way-traffic--g4': icon1502,\r\n 'warning--two-way-traffic--g5': icon1503,\r\n 'warning--two-way-traffic--g6': icon1504,\r\n 'warning--u-turn--g1': icon1505,\r\n 'warning--u-turn--g2': icon1506,\r\n 'warning--uneven-road--g1': icon1507,\r\n 'warning--uneven-road--g2': icon1508,\r\n 'warning--uneven-roads-ahead--g1': icon1509,\r\n 'warning--vehicles-and-others--g1': icon1510,\r\n 'warning--vehicles-crossing--g1': icon1511,\r\n 'warning--village--g1': icon1512,\r\n 'warning--weight-limit--g5': icon1513,\r\n 'warning--weight-limit-per-tandem-axle--g1': icon1514,\r\n 'warning--width-restriction--g1': icon1515,\r\n 'warning--width-restriction--g2': icon1516,\r\n 'warning--width-restriction--g3': icon1517,\r\n 'warning--width-restriction--g4': icon1518,\r\n 'warning--wild-animals--g1': icon1519,\r\n 'warning--wild-animals--g2': icon1520,\r\n 'warning--wild-animals--g3': icon1521,\r\n 'warning--wild-animals--g4': icon1522,\r\n 'warning--wild-animals--g5': icon1523,\r\n 'warning--wild-animals--g6': icon1524,\r\n 'warning--wild-animals--g7': icon1525,\r\n 'warning--wild-animals--g8': icon1526,\r\n 'warning--wind--g1': icon1527,\r\n 'warning--winding-road--g1': icon1528,\r\n 'warning--winding-road-first-left--g1': icon1529,\r\n 'warning--winding-road-first-left--g2': icon1530,\r\n 'warning--winding-road-first-left--g3': icon1531,\r\n 'warning--winding-road-first-right--g1': icon1532,\r\n 'warning--winding-road-first-right--g2': icon1533,\r\n 'warning--winding-road-first-right--g3': icon1534,\r\n 'warning--winding-road-first-right--g4': icon1535,\r\n 'warning--winding-road-to-left--g1': icon1536,\r\n 'warning--winding-road-to-right--g1': icon1537,\r\n 'warning--wombat-crossing--g1': icon1538,\r\n 'warning--y-roads--g1': icon1539,\r\n 'warning--y-roads--g2': icon1540,\r\n 'warning--yield-ahead--g1': icon1541,\r\n 'warning--yield-ahead--g3': icon1542,\r\n};\r\n\r\nexport default textures;","export default __webpack_public_path__ + \"static/media/warning--road-narrows--g2.401c3994.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows-left--g1.95c7edf0.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows-left--g2.44b45332.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows-left-ahead--g1.fd5aa709.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows-right--g1.65ee547e.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows-right--g2.87bc2427.png\";","export default __webpack_public_path__ + \"static/media/warning--road-narrows-right-ahead--g1.400397d6.png\";","export default __webpack_public_path__ + \"static/media/warning--road-toll-ahead--g1.6d55961a.png\";","export default __webpack_public_path__ + \"static/media/warning--road-widens--g1.c796ef79.png\";","export default __webpack_public_path__ + \"static/media/warning--road-widens-left--g1.ad78bfd0.png\";","export default __webpack_public_path__ + \"static/media/warning--road-widens-right--g1.0c6d1992.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g1.547c259b.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g2.1be718e9.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g3.2add7320.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g5.e61ab484.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g6.a04ce9d6.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g8.eb9766c2.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g9.f504fc37.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g10.1e4a14ca.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks--g11.65f561a7.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks-go-left-or-straight--g1.2206c5f2.png\";","export default __webpack_public_path__ + \"static/media/warning--roadworks-go-right-or-straight--g1.f4293c9a.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g1.363f83bb.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g2.c8ee3ec5.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g3.596a7a10.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g4.2102530e.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g5.ac2266ff.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g6.73900945.png\";","export default __webpack_public_path__ + \"static/media/warning--roundabout--g7.5c72c830.png\";","export default __webpack_public_path__ + \"static/media/warning--ruts--g1.01bce4e7.png\";","export default __webpack_public_path__ + \"static/media/warning--sand--g1.93715f38.png\";","export default __webpack_public_path__ + \"static/media/warning--sand-drift--g1.aaccd3fd.png\";","export default __webpack_public_path__ + \"static/media/warning--school-zone--g2.3c1c4bdf.png\";","export default __webpack_public_path__ + \"static/media/warning--severe-weather--g1.84f2d524.png\";","export default __webpack_public_path__ + \"static/media/warning--shared-lane-motorcycles-bicycles--g1.969c6687.png\";","export default __webpack_public_path__ + \"static/media/warning--sharp-turn--g1.9911721d.png\";","export default __webpack_public_path__ + \"static/media/warning--single-reverse-curve--g1.8219bd1a.png\";","export default __webpack_public_path__ + \"static/media/warning--skewed-t-roads-left--g1.b3a5ef81.png\";","export default __webpack_public_path__ + \"static/media/warning--skewed-t-roads-left--g2.57907e78.png\";","export default __webpack_public_path__ + \"static/media/warning--skewed-t-roads-left--g3.8810e2d3.png\";","export default __webpack_public_path__ + \"static/media/warning--skewed-t-roads-right--g1.48a80ba7.png\";","export default __webpack_public_path__ + \"static/media/warning--skewed-t-roads-right--g2.733f022e.png\";","export default __webpack_public_path__ + \"static/media/warning--skewed-t-roads-right--g3.544ec832.png\";","export default __webpack_public_path__ + \"static/media/warning--skiers--g1.e4cb5a02.png\";","export default __webpack_public_path__ + \"static/media/warning--skiers--g2.e0e46119.png\";","export default __webpack_public_path__ + \"static/media/warning--skiers--g3.7c53d442.png\";","export default __webpack_public_path__ + \"static/media/warning--slippery-bicycles--g1.44fe2519.png\";","export default __webpack_public_path__ + \"static/media/warning--slippery-motorcycles--g1.55df543d.png\";","export default __webpack_public_path__ + \"static/media/warning--slippery-motorcycles--g2.d5a4c642.png\";","export default __webpack_public_path__ + \"static/media/warning--slippery-road-surface--g1.be37c309.png\";","export default __webpack_public_path__ + \"static/media/warning--slippery-road-surface--g2.cc75b2dd.png\";","export default __webpack_public_path__ + \"static/media/warning--slow--g1.5f3c1df0.png\";","export default __webpack_public_path__ + \"static/media/warning--snow-tractors--g1.bb82eff0.png\";","export default __webpack_public_path__ + \"static/media/warning--snowmobiles--g1.d6ea0469.png\";","export default __webpack_public_path__ + \"static/media/warning--snowmobiles--g2.0f139051.png\";","export default __webpack_public_path__ + \"static/media/warning--snowmobiles--g3.7abe7cc6.png\";","export default __webpack_public_path__ + \"static/media/warning--snowmobiles-and-others--g1.8d956ed3.png\";","export default __webpack_public_path__ + \"static/media/warning--soft-road-surface--g1.85e53a3f.png\";","export default __webpack_public_path__ + \"static/media/warning--soft-road-surface--g2.31a8fbb4.png\";","export default __webpack_public_path__ + \"static/media/warning--soft-shoulder--g1.048f3f53.png\";","export default __webpack_public_path__ + \"static/media/warning--soft-shoulder--g2.f70869d1.png\";","export default __webpack_public_path__ + \"static/media/warning--soft-shoulder--g3.993109d1.png\";","export default __webpack_public_path__ + \"static/media/warning--soft-shoulder--g4.6b309255.png\";","export default __webpack_public_path__ + \"static/media/warning--speed-camera--g1.c247454b.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-ascent--g1.69baab13.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-ascent--g2.f04136e9.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-ascent--g3.ac4d27d9.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-ascent--g4.ab1d5bee.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-ascent-and-descent--g1.127e8fa0.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-descent--g1.1af3c7de.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-descent--g2.84c43533.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-descent--g3.dbc8ed30.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-descent--g4.fe8bc6de.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-descent--g5.53695588.png\";","export default __webpack_public_path__ + \"static/media/warning--steep-descent--g6.124238e6.png\";","export default __webpack_public_path__ + \"static/media/warning--stop-ahead--g1.19311854.png\";","export default __webpack_public_path__ + \"static/media/warning--stop-ahead--g3.f1875ba8.png\";","export default __webpack_public_path__ + \"static/media/warning--stop-ahead--g4.5c3b7c40.png\";","export default __webpack_public_path__ + \"static/media/warning--stop-ahead--g5.9f5a1393.png\";","export default __webpack_public_path__ + \"static/media/warning--stop-ahead--g6.78751205.png\";","export default __webpack_public_path__ + \"static/media/warning--t-roads--g1.02138011.png\";","export default __webpack_public_path__ + \"static/media/warning--t-roads--g2.056984e6.png\";","export default __webpack_public_path__ + \"static/media/warning--tanks-crossing--g1.ff076d31.png\";","export default __webpack_public_path__ + \"static/media/warning--tanks-crossing--g2.7f43e52c.png\";","export default __webpack_public_path__ + \"static/media/warning--texts--g1.f8515b5d.png\";","export default __webpack_public_path__ + \"static/media/warning--texts--g2.d6d56c78.png\";","export default __webpack_public_path__ + \"static/media/warning--texts--g3.14da2898.png\";","export default __webpack_public_path__ + \"static/media/warning--towing--g1.e4f069b4.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g1.6ebffbec.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g2.12c05fcc.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g3.bc827995.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g4.ca6b9ca8.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g5.c35fe753.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g6.80093d62.png\";","export default __webpack_public_path__ + \"static/media/warning--tractors--g7.c9d9396b.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-at-signalized-intersections--g1.15593cdb.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-left--g1.ad031968.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-left--g2.35d525d5.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-left--g3.aa5ed805.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-left--g4.b2ac0c8b.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-left-and-right--g1.b5ae91c4.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-left-buses--g1.bafa36cd.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-right--g1.09a3ead4.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-right--g2.3201b3fd.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-right--g3.c7ea5315.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-merges-right-buses--g1.dd325625.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-queues-likely--g1.2c06f6f5.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-queues-likely--g2.67e4ca2f.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-queues-likely--g3.85ad3584.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-queues-likely--g4.341dcd8c.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-queues-likely--g5.67bac08b.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-signals--g1.0847859b.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-signals--g2.da23a41a.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-signals--g3.675ee0a1.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-signals--g4.9b34ae82.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-signals--g5.3b152c9a.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-signals--g6.89426955.png\";","export default __webpack_public_path__ + \"static/media/warning--traffic-slow--g1.169e23bf.png\";","export default __webpack_public_path__ + \"static/media/warning--trail-crossing--g1.e429d378.png\";","export default __webpack_public_path__ + \"static/media/warning--trail-crossing--g2.8a7ddab9.png\";","export default __webpack_public_path__ + \"static/media/warning--trail-crossing--g3.67219fd7.png\";","export default __webpack_public_path__ + \"static/media/warning--trail-crossing--g4.07b92d0e.png\";","export default __webpack_public_path__ + \"static/media/warning--trail-crossing--g5.10b83374.png\";","export default __webpack_public_path__ + \"static/media/warning--trail-crossing--g6.5ae959ad.png\";","export default __webpack_public_path__ + \"static/media/warning--trams-crossing--g1.c211e5c2.png\";","export default __webpack_public_path__ + \"static/media/warning--trams-crossing--g2.10027951.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-curve-left--g1.2b1378be.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-curve-right--g1.2d533c31.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-lanes-left-turn--g1.8bf1c712.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-lanes-left-turn-or-go-straight--g1.f5c35777.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-lanes-right-turn--g1.c58a09f1.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-lanes-right-turn-or-go-straight--g1.4eea8ba7.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-lanes-with-directions--g1.586f9802.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-reverse-curve-left--g1.4cbc4d04.png\";","export default __webpack_public_path__ + \"static/media/warning--triple-reverse-curve-right--g1.0a1464ca.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-crossing--g1.14771128.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-crossing--g2.8ba4f009.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-rollover--g1.9615c47b.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-rollover--g2.a08fc624.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-rollover--g3.c0f762d7.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-rollover--g4.b6d137b4.png\";","export default __webpack_public_path__ + \"static/media/warning--trucks-rollover--g5.44727700.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g1.e271c799.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g2.1ac74efb.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g3.0d46880c.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g4.55d1ddf2.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g5.598ceb68.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g6.db4d3d0f.png\";","export default __webpack_public_path__ + \"static/media/warning--tunnel--g7.cdca6a34.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-left--g1.1d607064.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-left--g2.2a658ee0.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-left--g3.f55b92bb.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-left-or-right--g1.386986eb.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-right--g1.acd9d2dc.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-right--g2.71999a1f.png\";","export default __webpack_public_path__ + \"static/media/warning--turn-right--g3.df561544.png\";","export default __webpack_public_path__ + \"static/media/warning--two-way-traffic--g1.f6b90cf6.png\";","export default __webpack_public_path__ + \"static/media/warning--two-way-traffic--g2.d18e37c9.png\";","export default __webpack_public_path__ + \"static/media/warning--two-way-traffic--g3.04d6746c.png\";","export default __webpack_public_path__ + \"static/media/warning--two-way-traffic--g4.57cdc063.png\";","export default __webpack_public_path__ + \"static/media/warning--two-way-traffic--g5.1d4d5701.png\";","export default __webpack_public_path__ + \"static/media/warning--two-way-traffic--g6.444c4349.png\";","export default __webpack_public_path__ + \"static/media/warning--u-turn--g1.c962ec41.png\";","export default __webpack_public_path__ + \"static/media/warning--u-turn--g2.997231ed.png\";","export default __webpack_public_path__ + \"static/media/warning--uneven-road--g1.7ee9ceaa.png\";","export default __webpack_public_path__ + \"static/media/warning--uneven-road--g2.2107fedc.png\";","export default __webpack_public_path__ + \"static/media/warning--uneven-roads-ahead--g1.4444a9a8.png\";","export default __webpack_public_path__ + \"static/media/warning--vehicles-and-others--g1.5639870f.png\";","export default __webpack_public_path__ + \"static/media/warning--vehicles-crossing--g1.9f54b48e.png\";","export default __webpack_public_path__ + \"static/media/warning--village--g1.186803fe.png\";","export default __webpack_public_path__ + \"static/media/warning--weight-limit--g5.07efdfea.png\";","export default __webpack_public_path__ + \"static/media/warning--weight-limit-per-tandem-axle--g1.bce254f9.png\";","export default __webpack_public_path__ + \"static/media/warning--width-restriction--g1.4ce617a5.png\";","export default __webpack_public_path__ + \"static/media/warning--width-restriction--g2.3c708099.png\";","export default __webpack_public_path__ + \"static/media/warning--width-restriction--g3.8a82e40c.png\";","export default __webpack_public_path__ + \"static/media/warning--width-restriction--g4.88608eb2.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g1.c0f70fcd.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g2.76bbe024.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g3.ed95b4b7.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g4.85a2983f.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g5.5e9cdace.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g6.cdc986a1.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g7.e116de1f.png\";","export default __webpack_public_path__ + \"static/media/warning--wild-animals--g8.c9822743.png\";","export default __webpack_public_path__ + \"static/media/warning--wind--g1.cbfbcd99.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road--g1.f80521c5.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-left--g1.ece0736d.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-left--g2.3b2df358.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-left--g3.6e45aecc.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-right--g1.39cf401f.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-right--g2.53376994.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-right--g3.2a1fde3f.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-first-right--g4.0c7093c2.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-to-left--g1.896aa6f8.png\";","export default __webpack_public_path__ + \"static/media/warning--winding-road-to-right--g1.6a71c0d8.png\";","export default __webpack_public_path__ + \"static/media/warning--wombat-crossing--g1.633523a4.png\";","export default __webpack_public_path__ + \"static/media/warning--y-roads--g1.1dc031ba.png\";","export default __webpack_public_path__ + \"static/media/warning--y-roads--g2.8994d575.png\";","export default __webpack_public_path__ + \"static/media/warning--yield-ahead--g1.798e142c.png\";","export default __webpack_public_path__ + \"static/media/warning--yield-ahead--g3.1cad1ee2.png\";","import icon0 from './beginn schiessuebungsraum.png';\r\nimport icon1 from './beginn schiessuebungsstrecke.png';\r\nimport icon2 from './doppelrhombus.png';\r\nimport icon3 from './doppelwinkel.png';\r\nimport icon4 from './ende schiessuebungsraum.png';\r\nimport icon5 from './ende schiessuebungsstrecke.png';\r\nimport icon6 from './rhombus.png';\r\nimport icon7 from './stellung feuerhalt.png';\r\nimport icon8 from './winkel.png';\r\n\r\nconst textures = {\r\n 'beginn schiessuebungsraum': icon0,\r\n 'beginn schiessuebungsstrecke': icon1,\r\n 'doppelrhombus': icon2,\r\n 'doppelwinkel': icon3,\r\n 'ende schiessuebungsraum': icon4,\r\n 'ende schiessuebungsstrecke': icon5,\r\n 'rhombus': icon6,\r\n 'stellung feuerhalt': icon7,\r\n 'winkel': icon8,\r\n};\r\n\r\nexport default textures;","export default __webpack_public_path__ + \"static/media/beginn schiessuebungsraum.461cbd1c.png\";","export default __webpack_public_path__ + \"static/media/beginn schiessuebungsstrecke.b0de6080.png\";","export default __webpack_public_path__ + \"static/media/doppelrhombus.0d62fd3b.png\";","export default __webpack_public_path__ + \"static/media/doppelwinkel.1256e63e.png\";","export default __webpack_public_path__ + \"static/media/ende schiessuebungsraum.1209f377.png\";","export default __webpack_public_path__ + \"static/media/ende schiessuebungsstrecke.27c37067.png\";","export default __webpack_public_path__ + \"static/media/rhombus.05d7f59c.png\";","export default __webpack_public_path__ + \"static/media/stellung feuerhalt.10b48150.png\";","export default __webpack_public_path__ + \"static/media/winkel.943a1586.png\";","export enum TagSize {\r\n XSmall = 0.25,\r\n Small = 0.5,\r\n Medium = 1,\r\n Large = 2,\r\n XLarge = 4,\r\n}\r\n\r\nexport enum AnnotationSize {\r\n Small = 1,\r\n Medium = 2,\r\n Large = 4,\r\n XLarge = 8\r\n}\r\n\r\nexport enum AnnotationDrawType {\r\n Eraser = 0,\r\n Polygon = 1,\r\n PolygonFreeHand = 2,\r\n LineString = 3,\r\n LineStringFreeHand = 4,\r\n Rectangle = 5,\r\n Circle = 6,\r\n Star = 7\r\n}","import {\r\n addAsset,\r\n addAssets,\r\n AssetInfo,\r\n AssetType,\r\n pointCloudType,\r\n CameraData,\r\n OrthoData,\r\n LineworkLayerData,\r\n XMLData,\r\n TagItemData,\r\n WebMapData,\r\n createAsset,\r\n createTags,\r\n TagAnnotation\r\n} from \"../redux/assets-slice\";\r\nimport {Parser} from 'xml2js';\r\nimport {dialog, fse, isStaticSite} from \"../electron-modules\";\r\nimport path from 'path';\r\nimport slash from 'slash';\r\nimport {hideBackdrop, showBackdrop, toast} from \"../app\";\r\nimport {PythonExecutable} from \"../executable\";\r\nimport LocalScene, { isValidProjection } from \"../viewer/projections\";\r\nimport { loadProjectFile } from \".\";\r\nimport {\r\n IFCFileFormat,\r\n imageOrthoFormat,\r\n imagePlanarFormat,\r\n pointCloudFileFormats,\r\n configFileType,\r\n SHPFileFormat,\r\n DXFFileFormat,\r\n xmlFileFormat,\r\n projFileFormat,\r\n lasFileFormat\r\n} from \"../file-extensions\";\r\nimport { t } from \"../localization\";\r\nimport { readFileBuffer, readFileText } from \"../viewer/file-system-loader\";\r\nimport { Dispatch, nanoid } from \"@reduxjs/toolkit\";\r\nimport {curveDist, lineDist} from \"../viewer/measurements/land-xml-calculation\";\r\nimport { defaultTagTexture } from \"../viewer/textures/tag-icons\";\r\nimport { TagSize } from \"../types/tags\";\r\nimport { useDispatch } from \"react-redux\";\r\nimport { useGlobalSettings } from \"../hooks\";\r\nimport { openExternalLink } from \"../urls\";\r\nimport { updateDataProjection, updateViewProjection} from \"../redux/projections-slice\";\r\nimport * as CSV from 'csv-string';\r\nimport { checkLASProjections } from \"../projections\";\r\n\r\nconst DEFAULT_LAYER_COLOR = \"#FF0000\";\r\nconst MAX_STRING_LENGTH = 0x1FFFFFE8;\r\n\r\n/** Remove paths from existing array */\r\nconst removeFromArray = (objects, toRemove) => {\r\n return objects.filter(object => !toRemove.includes(object));\r\n};\r\n\r\nexport const useAssetTools = () => {\r\n const dispatch = useDispatch();\r\n const {orthoQuality} = useGlobalSettings();\r\n\r\n const addAssetPaths = async (assetPaths: string[], folderID: string) => {\r\n let totalAssetsAdded = 0;\r\n\r\n const tagPaths = assetPaths.filter(isTagFile);\r\n const tagPathsAdded = await addTagCSVs(tagPaths, folderID, false);\r\n assetPaths = removeFromArray(assetPaths, tagPathsAdded);\r\n totalAssetsAdded += tagPathsAdded.length;\r\n\r\n const planarPaths = assetPaths.filter(isPlanarFile);\r\n totalAssetsAdded += await addPlanarFiles(planarPaths, folderID);\r\n\r\n const panoramicPaths = assetPaths.filter(isPanoramicFile);\r\n totalAssetsAdded += await addPanoramicFiles(panoramicPaths, folderID, false);\r\n\r\n const pointCloudPaths = assetPaths.filter(isPointCloudFile);\r\n totalAssetsAdded += await addPointCloudFiles(pointCloudPaths, folderID);\r\n\r\n const orthoPaths = assetPaths.filter(isOrthomosaicFile);\r\n totalAssetsAdded += await addOrthoFiles(orthoPaths, folderID);\r\n\r\n const modelPaths = assetPaths.filter(isModelFile);\r\n totalAssetsAdded += await addModelFiles(modelPaths, folderID);\r\n\r\n const xmlPaths = assetPaths.filter(isXmlFile);\r\n totalAssetsAdded += await addXMLFiles(xmlPaths, folderID);\r\n\r\n if (totalAssetsAdded === 0) return;\r\n\r\n toast.success(t(\"toast.added-project-files\", {\r\n count: totalAssetsAdded\r\n }));\r\n };\r\n\r\n const addFilePaths = (filePaths: string[], folderID: string) => {\r\n if (!filePaths || filePaths.length === 0) return;\r\n\r\n const configs = filePaths.filter(isConfigFile);\r\n const assetPaths = filePaths.filter(isAssetFile);\r\n const projections = filePaths.filter(isProjectionFile);\r\n\r\n if (configs.length > 0) {\r\n // Load first config file (ignore other files)\r\n const success = loadProjectFile(configs[0]);\r\n if (success) {\r\n toast.success(t(\"toast.load-config-file\"));\r\n }\r\n return;\r\n }\r\n\r\n if (projections.length > 0) {\r\n // Read projection from solv3d projection file\r\n const projectionPath = projections[0];\r\n const text = fse.readFileSync(projectionPath);\r\n const projection = JSON.parse(text);\r\n\r\n if (isValidProjection(projection.string)) {\r\n dispatch(updateDataProjection(projection));\r\n dispatch(updateViewProjection(projection));\r\n } else {\r\n toast.error(\"Invalid projection file\");\r\n }\r\n }\r\n\r\n if (assetPaths.length > 0) {\r\n // Add new assets\r\n addAssetPaths(assetPaths, folderID);\r\n }\r\n };\r\n\r\n const addWebSource = (name: string, data: WebMapData, folderID: string) => {\r\n dispatch(addAsset({\r\n folderID,\r\n name,\r\n path: null,\r\n type: AssetType.Webmap,\r\n data\r\n }));\r\n };\r\n\r\n const addModelFiles = async (assetPaths: string[], folderID: string) => {\r\n const ifcPaths = assetPaths.filter(isIFCFile);\r\n const shpPaths = assetPaths.filter(isSHPFile);\r\n const dxfPaths = assetPaths.filter(isDXFFile);\r\n\r\n let modelsAdded = 0;\r\n modelsAdded += await addIFCFiles(dispatch, ifcPaths, folderID);\r\n modelsAdded += await addSHPFiles(dispatch, shpPaths, folderID);\r\n modelsAdded += await addDXFFiles(dispatch, dxfPaths, folderID);\r\n\r\n return modelsAdded;\r\n };\r\n\r\n const addPointCloudFiles = async (assetPaths: string[], folderID: string) => {\r\n let assetsList = [] as AssetInfo[];\r\n\r\n const LASPaths = assetPaths.filter(asset => isLASFile(asset));\r\n\r\n if (LASPaths.length > 0) {\r\n // Check for projection inside LAS files\r\n await checkLASProjections(LASPaths);\r\n\r\n // Convert to streamable format, and return new assetPaths format\r\n // assetPaths = await convertLASFiles(LASPaths)\r\n }\r\n\r\n for (let assetPath of assetPaths) {\r\n const extension = path.extname(assetPath).slice(1);\r\n const type = pointCloudType(extension);\r\n const fileName = path.basename(assetPath);\r\n\r\n if (type === AssetType.Encompass) {\r\n assetPath = path.dirname(assetPath);\r\n if (fileName !== \"r.idx\") {\r\n toast.error(t('assets.error_loading_points_r_idx'));\r\n return;\r\n }\r\n } else if (type === AssetType.Potree) {\r\n assetPath = path.dirname(assetPath);\r\n if (fileName !== \"octree.bin\") {\r\n toast.error(t('assets.error_loading_points_octree'));\r\n return;\r\n }\r\n }\r\n\r\n assetsList.push({\r\n folderID,\r\n name: fileName,\r\n path: assetPath,\r\n type\r\n });\r\n };\r\n\r\n dispatch(addAssets(assetsList));\r\n\r\n return assetPaths.length;\r\n };\r\n\r\n const addOrthoFiles = async (assetPaths: string[], folderID: string) => {\r\n showBackdrop();\r\n\r\n let numAdded = await addOrthoBatch(dispatch,\r\n assetPaths, folderID, orthoQuality);\r\n\r\n hideBackdrop();\r\n\r\n return numAdded;\r\n };\r\n\r\n const addTagCSVs = async (assetPaths: string[], folderID: string, catchErrors = true): Promise => {\r\n showBackdrop();\r\n\r\n let pathsAdded = [] as string[];\r\n\r\n for (const assetPath of assetPaths) {\r\n try {\r\n const numberOfTags = await addTagCSV(dispatch, assetPath, folderID);\r\n pathsAdded.push(assetPath);\r\n\r\n toast.success(t(\"toast.added-new-tags\", {\r\n count: numberOfTags\r\n }));\r\n } catch {\r\n if (!catchErrors) continue;\r\n const filename = path.basename(assetPath);\r\n\r\n toast.error(t(\"toast.tag-failed-parse\", {\r\n filename\r\n }));\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n return pathsAdded;\r\n };\r\n\r\n const addPanoramicFiles = async (assetPaths: string[], folderID: string, catchErrors = true) => {\r\n showBackdrop();\r\n\r\n let numFilesAdded = 0;\r\n\r\n for (const assetPath of assetPaths) {\r\n const fileName = path.basename(assetPath);\r\n\r\n try {\r\n const {numAdded, numMissing} = await addPanoramicFile(\r\n dispatch, assetPath, folderID);\r\n\r\n if (numMissing > 0) {\r\n toast.warning(t('assets.added_panoramic_images_missing', {\r\n numAdded,\r\n numMissing\r\n }));\r\n } else {\r\n toast.success(t('assets.added_panoramic_images', {\r\n numAdded\r\n }));\r\n }\r\n\r\n numFilesAdded += 1;\r\n } catch (event) {\r\n if (!catchErrors) continue;\r\n\r\n if (event.pathError) {\r\n toast.error(t(\"toast.import-csv-path-error\", {\r\n path: fileName\r\n }));\r\n } else {\r\n toast.error(t(\"toast.import-csv-parse-error\", {\r\n path: fileName\r\n }));\r\n }\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n return numFilesAdded;\r\n };\r\n\r\n const addPlanarFiles = async (assetPaths: string[], folderID: string) => {\r\n showBackdrop();\r\n\r\n let numFilesAdded = 0;\r\n for (const assetPath of assetPaths) {\r\n const fileName = path.basename(assetPath);\r\n\r\n try {\r\n const {numAdded, numMissing} = await addPlanarFile(\r\n dispatch, assetPath, folderID);\r\n\r\n if (numMissing > 0) {\r\n toast.warning(t('assets.added_planar_images_missing', {\r\n numAdded,\r\n numMissing\r\n }));\r\n } else {\r\n toast.success(t('assets.added_planar_images', {\r\n numAdded\r\n }));\r\n }\r\n\r\n numFilesAdded += 1;\r\n } catch {\r\n toast.error(t(\"toast.import-planar-error\", {\r\n path: fileName\r\n }));\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n return numFilesAdded;\r\n };\r\n\r\n const addXMLFiles = async (assetPaths: string[], folderID: string) => {\r\n showBackdrop();\r\n\r\n let numAdded = 0;\r\n\r\n for (const assetPath of assetPaths) {\r\n const added = await addXMLFile(dispatch, assetPath, folderID);\r\n if (added) {\r\n numAdded++;\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n return numAdded;\r\n };\r\n\r\n return {\r\n addAssetPaths,\r\n addFilePaths,\r\n addModelFiles,\r\n addPointCloudFiles,\r\n addOrthoFiles,\r\n addTagCSVs,\r\n addPanoramicFiles,\r\n addPlanarFiles,\r\n addXMLFiles,\r\n addWebSource\r\n };\r\n};\r\n\r\n/** Save a file based on name. Works for website and compiled exe */\r\nexport const downloadFile = async (name: string, data, fileType: string, fileFilter) => {\r\n if (isStaticSite) {\r\n const contentType = `data:text/${fileType};charset=utf-8`;\r\n const content = `${contentType},${encodeURIComponent(data)}`;\r\n openExternalLink(content, {name});\r\n } else {\r\n try {\r\n const savePath = await getPathFromDialog(name, fileFilter);\r\n if (!savePath) return false;\r\n\r\n await fse.writeFile(savePath, data);\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\nconst getPathFromDialog = async (name, filter) => {\r\n const result = await dialog.showSaveDialog({\r\n defaultPath: name,\r\n filters: filter,\r\n });\r\n\r\n const {filePath, canceled} = result;\r\n if (canceled || !filePath) return;\r\n\r\n const savePath = slash(filePath);\r\n return savePath;\r\n};\r\n\r\nexport const pathWithExtension = (filename, extension) => {\r\n const basename = filename.replace(/\\.[^.$]+$/, '');\r\n return `${basename}.${extension}`;\r\n};\r\n\r\nexport const isAssetFile = (filename) => {\r\n return isPanoramicFile(filename)\r\n || isTagFile(filename)\r\n || isPlanarFile(filename)\r\n || isPointCloudFile(filename)\r\n || isOrthomosaicFile(filename)\r\n || isModelFile(filename)\r\n || isXmlFile(filename);\r\n};\r\n\r\nexport const isModelFile = (filename) => {\r\n return isIFCFile(filename)\r\n || isSHPFile(filename)\r\n || isDXFFile(filename);\r\n};\r\n\r\nexport const isPanoramicFile = (filename) => {\r\n return isCSVFile(filename)\r\n || isTXTFile(filename)\r\n || isRZMLFile(filename)\r\n || isODMFile(filename);\r\n};\r\n\r\nconst isTagFile = filename => {\r\n return isCSVFile(filename);\r\n};\r\n\r\nexport const isCSVFile = filename => {\r\n return path.extname(filename) === '.csv';\r\n};\r\n\r\nexport const isTXTFile = filename => {\r\n return path.extname(filename) === '.txt';\r\n};\r\n\r\nexport const isRZMLFile = filename => {\r\n return path.extname(filename) === '.rzml';\r\n};\r\n\r\nexport const isODMFile = filename => {\r\n return path.basename(filename) === \"shots.geojson\";\r\n};\r\n\r\nexport const isIFCFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return extension === IFCFileFormat;\r\n};\r\n\r\nexport const isSHPFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return extension === SHPFileFormat;\r\n};\r\n\r\nexport const isDXFFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return extension === DXFFileFormat;\r\n};\r\n\r\nexport const isConfigFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return extension === configFileType;\r\n};\r\n\r\nexport const isProjectionFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return projFileFormat.indexOf(extension) !== -1;\r\n};\r\n\r\nexport const isPlanarFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return imagePlanarFormat.indexOf(extension) !== -1;\r\n};\r\n\r\nexport const isPointCloudFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return pointCloudFileFormats.indexOf(extension) !== -1;\r\n};\r\n\r\nexport const isLASFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return extension === lasFileFormat;\r\n};\r\n\r\nexport const isOrthomosaicFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return imageOrthoFormat.indexOf(extension) !== -1;\r\n};\r\n\r\nexport const isXmlFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return extension === xmlFileFormat;\r\n};\r\n\r\nconst getDXFLayerNames = (text): Promise<{name: string, color: string}[]> => {\r\n return new Promise((resolve, reject) => {\r\n const workerURL = \"workers/dxf-reader.js\";\r\n let worker = new Worker(`${process.env.PUBLIC_URL}/${workerURL}`);\r\n\r\n worker.onmessage = event => {\r\n const {success, response} = event.data;\r\n\r\n if (success) {\r\n resolve(response);\r\n } else {\r\n console.error(response);\r\n reject(response);\r\n }\r\n };\r\n\r\n const data = {text, type: \"layers\"};\r\n worker.postMessage(data);\r\n });\r\n};\r\n\r\nconst getSHPLayerNames = (buffer) : Promise => {\r\n return new Promise((resolve, reject) => {\r\n const workerURL = \"workers/shp-reader.js\";\r\n let worker = new Worker(`${process.env.PUBLIC_URL}/${workerURL}`);\r\n\r\n worker.onmessage = event => {\r\n const {success, response} = event.data;\r\n\r\n if (success) {\r\n resolve(response);\r\n } else {\r\n console.error(response);\r\n reject(response);\r\n }\r\n };\r\n\r\n const data = {dbf: buffer, type: \"layers\"};\r\n worker.postMessage(data, [data.dbf]);\r\n });\r\n};\r\n\r\nconst addIFCFiles = async (dispatch: Dispatch, assetPaths: string[], folderID: string) => {\r\n let assetsList = [] as AssetInfo[];\r\n\r\n assetPaths.forEach(assetPath => {\r\n assetsList.push({\r\n folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: AssetType.IFC\r\n });\r\n });\r\n\r\n dispatch(addAssets(assetsList));\r\n return assetPaths.length;\r\n};\r\n\r\nconst addDXFFiles = async (dispatch: Dispatch, assetPaths: string[], folderID: string) => {\r\n let assetsList = [] as AssetInfo[];\r\n\r\n showBackdrop();\r\n\r\n for (let assetPath of assetPaths) {\r\n const fileName = path.basename(assetPath);\r\n\r\n const stats = await fse.stat(assetPath);\r\n const fileSize = stats.size;\r\n\r\n if (fileSize >= MAX_STRING_LENGTH) {\r\n toast.error(t(\"toast.import-size-error\", {path: fileName}));\r\n continue;\r\n }\r\n\r\n try {\r\n const text = await readFileText(assetPath);\r\n const layers = await getDXFLayerNames(text);\r\n\r\n const layerData = layers.map(layer => {\r\n return {\r\n id: nanoid(),\r\n name: layer.name,\r\n visible: true,\r\n color: layer.color\r\n };\r\n }) as LineworkLayerData[];\r\n\r\n assetsList.push({\r\n folderID,\r\n name: fileName,\r\n path: assetPath,\r\n data: layerData,\r\n type: AssetType.DXF\r\n });\r\n } catch(err) {\r\n console.log(err);\r\n\r\n toast.error(t(\"toast.import-dxf-error\", {\r\n path: fileName\r\n }));\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n dispatch(addAssets(assetsList));\r\n return assetsList.length;\r\n};\r\n\r\nconst addSHPFiles = async (dispatch: Dispatch, assetPaths: string[], folderID: string) => {\r\n let assetsList = [] as AssetInfo[];\r\n\r\n showBackdrop();\r\n\r\n for (let assetPath of assetPaths) {\r\n const fileName = path.basename(assetPath);\r\n\r\n try {\r\n const dbfPath = pathWithExtension(assetPath, \"dbf\");\r\n const buffer = await readFileBuffer(dbfPath);\r\n const layers = await getSHPLayerNames(buffer);\r\n\r\n const layerData = layers.map(layer => {\r\n return {\r\n id: nanoid(),\r\n name: layer,\r\n visible: true,\r\n color: DEFAULT_LAYER_COLOR\r\n };\r\n }) as LineworkLayerData[];\r\n\r\n assetsList.push({\r\n folderID,\r\n name: fileName,\r\n path: assetPath,\r\n data: layerData,\r\n type: AssetType.SHP\r\n });\r\n } catch(err) {\r\n console.log(err);\r\n\r\n toast.error(t(\"toast.import-shp-error\", {\r\n path: fileName\r\n }));\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n dispatch(addAssets(assetsList));\r\n return assetsList.length;\r\n};\r\n\r\nconst addOrthoBatch = async (dispatch: Dispatch, assetPaths: string[], folderID: string, orthoQuality: number): Promise => {\r\n if (assetPaths.length === 0) {\r\n return 0;\r\n }\r\n\r\n return new Promise(async resolve => {\r\n const exe = new PythonExecutable();\r\n\r\n let response;\r\n let commands = [\r\n \"-p\", \"convert_geotiff\",\r\n \"--image_paths\", assetPaths,\r\n \"--output_scale\", orthoQuality\r\n ];\r\n\r\n let numAdded = 0;\r\n\r\n exe.run({\r\n commands,\r\n onLine: jsonData => {\r\n if (jsonData) {\r\n response = jsonData;\r\n }\r\n },\r\n onClose: () => {\r\n if (!response) {\r\n response = [];\r\n }\r\n\r\n let assetsList = [] as AssetInfo[];\r\n\r\n response.forEach(geotiff => {\r\n const assetPath = slash(geotiff.file_path);\r\n const fileName = path.basename(assetPath);\r\n\r\n if (geotiff.error) {\r\n toast.error(t(`toast.${geotiff.error}`, {\r\n path: fileName\r\n }));\r\n return;\r\n }\r\n\r\n const {corners, base64, width, height, base64_split,\r\n scale_x, scale_y, width_original, height_original} = geotiff;\r\n\r\n const orthoData = {\r\n imageBounds: corners,\r\n imageDataSplit: base64_split,\r\n imageData: base64,\r\n imageSize: [width, height],\r\n imageSizeOriginal: [width_original, height_original],\r\n imagePath: assetPath,\r\n scaleX: scale_x,\r\n scaleY: scale_y,\r\n } as OrthoData;\r\n\r\n assetsList.push({\r\n folderID,\r\n name: fileName,\r\n path: assetPath,\r\n type: AssetType.OrthoMosaic,\r\n data: orthoData\r\n });\r\n\r\n numAdded += 1;\r\n });\r\n\r\n dispatch(addAssets(assetsList));\r\n resolve(numAdded);\r\n }\r\n });\r\n });\r\n};\r\n\r\nconst addPlanarFile = (dispatch: Dispatch, assetPath: string, folderID: string):\r\n Promise<{numAdded: number, numMissing: number}> => {\r\n return new Promise((resolve, reject) => {\r\n const exe = new PythonExecutable();\r\n\r\n let cameras;\r\n let commands = [\r\n \"-p\", \"convert_engine_planars\",\r\n \"--input_path\", assetPath\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n onLine: jsonData => {\r\n if (jsonData) {\r\n cameras = jsonData;\r\n }\r\n },\r\n onClose: () => {\r\n if (!cameras) {\r\n reject();\r\n return;\r\n }\r\n\r\n const numCameras = cameras.length;\r\n const numMissing = cameras.filter(camera => !camera.path).length;\r\n const numAdded = numCameras - numMissing;\r\n\r\n if (numCameras === 0) {\r\n reject();\r\n return;\r\n }\r\n\r\n let cameraData: CameraData[] = [];\r\n\r\n for (let camera of cameras) {\r\n let name = camera.path\r\n ? path.basename(camera.path)\r\n : camera.name;\r\n\r\n const rowData = {\r\n id: nanoid(),\r\n path: camera.path,\r\n name: name,\r\n x: camera.x,\r\n y: camera.y,\r\n z: camera.z,\r\n roll: camera.roll,\r\n pitch: camera.pitch,\r\n yaw: camera.yaw,\r\n config: camera.config\r\n } as CameraData;\r\n\r\n cameraData.push(rowData);\r\n }\r\n\r\n dispatch(addAsset({\r\n folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: AssetType.Planar,\r\n data: cameraData\r\n }));\r\n\r\n resolve({numAdded, numMissing});\r\n }\r\n });\r\n });\r\n};\r\n\r\nconst addPanoramicFile = (dispatch: Dispatch, assetPath: string, folderID: string):\r\n Promise<{numAdded: number, numMissing: number}> => {\r\n return new Promise((resolve, reject) => {\r\n const exe = new PythonExecutable();\r\n\r\n let cameras;\r\n const inputPath = assetPath;\r\n const projection = LocalScene.engineStyleProjection(LocalScene.dataProjection);\r\n\r\n let commands = [\r\n \"-p\", \"convert_engine_panoramics\",\r\n \"--input_path\", inputPath,\r\n \"--projection\", projection\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n onLine: jsonData => {\r\n cameras = jsonData;\r\n },\r\n onClose: async () => {\r\n if (!cameras) {\r\n reject({pathError: false});\r\n return;\r\n }\r\n\r\n const numCameras = cameras.length;\r\n const numMissing = cameras.filter(camera => !camera.path).length;\r\n const numAdded = numCameras - numMissing;\r\n\r\n if (numCameras === 0) {\r\n reject({pathError: false});\r\n return;\r\n }\r\n\r\n let cameraData = [] as CameraData[];\r\n\r\n for (let camera of cameras) {\r\n let name = camera.path\r\n ? path.basename(camera.path)\r\n : camera.name;\r\n\r\n cameraData.push({\r\n id: nanoid(),\r\n path: camera.path,\r\n name: name,\r\n x: camera.x,\r\n y: camera.y,\r\n z: camera.z,\r\n roll: camera.roll,\r\n pitch: camera.pitch,\r\n yaw: camera.yaw\r\n });\r\n }\r\n\r\n dispatch(addAsset({\r\n folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: AssetType.Panoramic,\r\n data: cameraData\r\n }));\r\n\r\n resolve({numAdded, numMissing});\r\n }\r\n });\r\n });\r\n};\r\n\r\nconst addXMLFile = async (dispatch: Dispatch, assetPath: string, folderID: string) => {\r\n const parser = new Parser({\r\n explicitChildren:true,\r\n preserveChildrenOrder: true\r\n });\r\n\r\n let text = await fse.readFile(assetPath, {encoding: 'utf8'});\r\n let textAll = String(text);\r\n let encoding = textAll.split('?>')[0].split('encoding=\"')[1].split('\"')[0];\r\n\r\n if (encoding !== 'utf-8') {\r\n if (encoding === 'iso-8859-1') {\r\n text = await fse.readFile(assetPath, {encoding: 'latin1'});\r\n } else {\r\n toast.error(t(\"dialog.xml-file-encoding-error\"));\r\n return false;\r\n }\r\n }\r\n\r\n try {\r\n let xmlJSON = await parser.parseStringPromise(text);\r\n if (!(\"LandXML\" in xmlJSON)) {\r\n toast.error(t(\"dialog.xml-file-load-error\"));\r\n return false;\r\n }\r\n\r\n xmlJSON = xmlJSON.LandXML;\r\n\r\n let xmlData = {\r\n info: xmlJSON.$,\r\n units: xmlJSON.Units[0].$$[0].$,\r\n alignments: [],\r\n enu: false\r\n } as XMLData;\r\n\r\n xmlJSON.Alignments[0].Alignment.forEach(alignment => {\r\n let alignObject = {\r\n id: nanoid(),\r\n name: alignment.$.name,\r\n length: parseFloat(alignment.$.length),\r\n staStart: parseFloat(alignment.$.staStart),\r\n about: alignment.$.desc,\r\n geometry: []\r\n };\r\n\r\n let geometry = alignment.CoordGeom[0].$$;\r\n\r\n if (Array.isArray(geometry)) {\r\n geometry.forEach(geom => {\r\n let geometryElement = {shapeType: geom['#name']};\r\n let dollarSignKeys = Object.keys(geom.$);\r\n let featureKeys = Object.keys(geom).filter(\r\n key=> ((key !== '$') && (key !== '$$') && (key !== '#name')));\r\n dollarSignKeys.forEach(key$ => {\r\n let aboutValue = geom.$[key$];\r\n aboutValue = !isNaN(parseFloat(aboutValue))\r\n ? parseFloat(aboutValue)\r\n : aboutValue;\r\n\r\n geometryElement[key$] = aboutValue;\r\n });\r\n\r\n featureKeys.forEach(fKey => {\r\n let coordValue = geom[fKey];\r\n let splitCoordValue;\r\n let tempValue;\r\n if (Object.keys(coordValue[0]).includes('$')) {\r\n tempValue = String(coordValue[0]['_']);\r\n } else {\r\n tempValue = String(coordValue[0]);\r\n }\r\n\r\n let newLineSep = tempValue.split('\\n');\r\n let recombine = newLineSep.join(' ');\r\n splitCoordValue = recombine.split(' ');\r\n let coordValueCorrected = [];\r\n splitCoordValue.forEach(scv=> {\r\n if (!isNaN(parseFloat(scv))) {\r\n coordValueCorrected.push(parseFloat(scv));\r\n }\r\n });\r\n if (coordValueCorrected.length > 0) {\r\n geometryElement[fKey] = coordValueCorrected;\r\n }\r\n });\r\n alignObject.geometry.push(geometryElement);\r\n });\r\n }\r\n\r\n xmlData.alignments.push(alignObject);\r\n });\r\n\r\n // Checks to see if length and staStart attributes were correctly added in\r\n // xml file, and if not, manually calculates them.\r\n\r\n let overwriteLength = false;\r\n let overwriteStaStart = false;\r\n\r\n xmlData.alignments.forEach(alignment => {\r\n let staStart = alignment.staStart;\r\n alignment.geometry.forEach(geom => {\r\n let keys = Object.keys(geom);\r\n if (!keys.includes(\"staStart\") || overwriteStaStart) {\r\n geom['staStart'] = staStart;\r\n overwriteStaStart = true;\r\n let length = 0;\r\n if (!keys.includes(\"length\") || overwriteLength) {\r\n overwriteLength = true;\r\n if (geom['shapeType'] === \"Line\") {\r\n length = lineDist(geom);\r\n } else if (geom['shapeType'] === \"Curve\") {\r\n length = curveDist(geom);\r\n }\r\n }\r\n if (overwriteLength) {\r\n geom['length'] = length;\r\n }\r\n if (overwriteStaStart) {\r\n staStart += length;\r\n }\r\n }\r\n geom['checked'] = 1;\r\n });\r\n });\r\n\r\n dispatch(addAsset({\r\n folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: AssetType.LandXML,\r\n data: xmlData\r\n }));\r\n\r\n return true;\r\n } catch {\r\n toast.error(t(\"dialog.xml-file-load-error\"));\r\n return false;\r\n }\r\n};\r\n\r\nconst getHeaderIndex = (headers: string[], values: string | string[]) => {\r\n return typeof(values) === 'string'\r\n ? headers.indexOf(values)\r\n : Math.max(...values.map(value => headers.indexOf(value)));\r\n};\r\n\r\nconst addTagCSV = async (dispatch, assetPath: string, folderID: string): Promise => {\r\n const text = await readFileText(assetPath);\r\n const data = CSV.parse(text);\r\n\r\n const headers = data[0].map(x => x.toLowerCase());\r\n const lines = data.slice(1);\r\n\r\n const xIndex = getHeaderIndex(headers, \"easting\");\r\n const yIndex = getHeaderIndex(headers, \"northing\");\r\n const zIndex = getHeaderIndex(headers, \"elevation\");\r\n const nameIndex = getHeaderIndex(headers, \"name\");\r\n const annotationIndex = getHeaderIndex(headers, \"annotations\");\r\n const commentIndex = getHeaderIndex(headers, [\"comment\", \"comments\", \"comment1_value\"]);\r\n\r\n const validHeader = (xIndex !== -1) && (yIndex !== -1);\r\n if (!validHeader) {\r\n throw new Error(\"Invalid headers\");\r\n }\r\n\r\n const hasHeight = zIndex !== -1;\r\n\r\n const tags = lines.map((line, index) => {\r\n let easting = parseFloat(line[xIndex]);\r\n let northing = parseFloat(line[yIndex]);\r\n\r\n let name = (nameIndex !== -1)\r\n ? line[nameIndex]\r\n : `Item ${index}`;\r\n\r\n let comment = (commentIndex !== -1)\r\n ? line[commentIndex]\r\n : \"\";\r\n\r\n let annotations = [];\r\n if (annotationIndex !== -1) {\r\n try {\r\n let text = line[annotationIndex];\r\n let data = JSON.parse(text);\r\n\r\n annotations = data.map(definition => {\r\n let id;\r\n\r\n if (definition.properties.id) {\r\n // Unique id already exists\r\n id = definition.properties.id;\r\n } else {\r\n // Generate a new unique id\r\n id = nanoid();\r\n definition.properties.id = id;\r\n }\r\n\r\n return {\r\n id,\r\n definition\r\n } as TagAnnotation;\r\n });\r\n } catch {\r\n // Nothing\r\n }\r\n }\r\n\r\n const tag = {\r\n id: nanoid(),\r\n name,\r\n comment,\r\n x: easting,\r\n y: northing,\r\n date: new Date().toISOString(),\r\n sceneState: null,\r\n annotations\r\n } as TagItemData;\r\n\r\n if (hasHeight) {\r\n const elevation = parseFloat(line[zIndex]);\r\n if (elevation && (elevation !== -9999)) {\r\n tag.z = elevation;\r\n }\r\n }\r\n\r\n return tag;\r\n });\r\n\r\n // Create new tag collection\r\n const asset = await dispatch(createAsset({\r\n folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: AssetType.Tag,\r\n size: TagSize.Medium,\r\n texture: defaultTagTexture\r\n }));\r\n\r\n // Add new tags to collection\r\n await dispatch(createTags({\r\n assetID: asset.id,\r\n tags\r\n }));\r\n\r\n return tags.length;\r\n};\r\n\r\nexport const openDialogMulti = (filter): Promise => {\r\n return dialog.showOpenDialog( {\r\n filters: filter,\r\n properties: ['openFile', 'multiSelections']\r\n }).then(result => {\r\n if (result.canceled) {\r\n return [];\r\n }\r\n\r\n const filePaths = result.filePaths.map(path => slash(path));\r\n return filePaths;\r\n }).catch(() => {\r\n dialog.showErrorBox(t(\"dialog.general-error-title\"), t(\"dialog.file-load-error\"));\r\n return [];\r\n });\r\n};\r\n\r\nexport const openDialogFile = (filter): Promise => {\r\n return dialog.showOpenDialog( {\r\n filters: filter,\r\n properties: ['openFile']\r\n }).then(result => {\r\n if (result.canceled) {\r\n return null;\r\n }\r\n\r\n const filePath = slash(result.filePaths[0]);\r\n return filePath;\r\n }).catch(() => {\r\n dialog.showErrorBox(t(\"dialog.general-error-title\"), t(\"dialog.file-load-error\"));\r\n return null;\r\n });\r\n};\r\n\r\nexport const openDialogFolder = (): Promise<{directoryPath: string, filePaths: string[]}> => {\r\n return new Promise((resolve) => {\r\n\r\n dialog.showOpenDialog({\r\n properties: ['openDirectory']\r\n }).then(async result => {\r\n if (result.canceled) {\r\n resolve({\r\n directoryPath: '',\r\n filePaths: []\r\n });\r\n\r\n return;\r\n }\r\n\r\n const filePath = slash(result.filePaths[0]);\r\n const filePaths = await parseDirectory(filePath);\r\n\r\n resolve({\r\n directoryPath: filePath,\r\n filePaths: filePaths\r\n });\r\n }).catch(() => {\r\n dialog.showErrorBox(t(\"dialog.general-error-title\"), t(\"dialog.file-load-error\"));\r\n return null;\r\n });\r\n });\r\n};\r\n\r\nexport const openDirectory = (): Promise => {\r\n return dialog.showOpenDialog({\r\n properties: [\"openDirectory\"]\r\n }).then(result => {\r\n if (result.canceled) {\r\n return null;\r\n }\r\n if (result.filePaths) {\r\n const outputFolder = slash(result.filePaths[0]);\r\n return outputFolder;\r\n }\r\n\r\n return null;\r\n });\r\n};\r\n\r\nconst parseDirectory = async (directoryPath: string): Promise => {\r\n const entries = await fse.readdir(directoryPath, {withFileTypes: true});\r\n\r\n const files = entries\r\n .filter(entry => entry.isFile())\r\n .map(file => path.join(directoryPath, file.name));\r\n\r\n const directories = entries\r\n .filter(entry => entry.isDirectory())\r\n .map(directory => path.join(directoryPath, directory.name));\r\n\r\n for (let folder of directories) {\r\n files.push(...(await parseDirectory(folder)));\r\n }\r\n\r\n return files;\r\n};\r\n","import {\r\n dialog,\r\n fs,\r\n} from \"../electron-modules\";\r\nimport slash from 'slash';\r\nimport { toast } from \"../app\";\r\nimport { cameraMatrixFilter } from \"../file-extensions\";\r\nimport { t } from \"../localization\";\r\nimport { Euler, Matrix4, Vector3 } from \"three\";\r\nimport { readFileText } from \"../viewer/file-system-loader\";\r\n\r\ninterface TransformResponse {\r\n success: Boolean,\r\n content: number[]\r\n}\r\n\r\nexport const saveMatrixFile = (cameraTransformPath) => {\r\n dialog.showSaveDialog({\r\n filters: cameraMatrixFilter,\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n if (result.filePath) {\r\n const savePath = slash(result.filePath);\r\n fs.copyFile(cameraTransformPath, savePath, (err) => {\r\n if (err) {\r\n toast.error(t(\"toast.correction-matrix-failed\"));\r\n } else {\r\n toast.success(t(\"toast.correction-matrix-saved\"));\r\n }\r\n });\r\n }\r\n });\r\n};\r\n\r\nexport const readTransformFile = (path: string): Promise => {\r\n return new Promise(async resolve => {\r\n const errorResponse = {\r\n success: false,\r\n content: null\r\n };\r\n\r\n if (!path) {\r\n resolve(errorResponse);\r\n return;\r\n }\r\n\r\n try {\r\n const data = await readFileText(path);\r\n\r\n let arr = [];\r\n let valid = true;\r\n\r\n const rows = data.split(\"\\n\");\r\n rows.forEach(row => {\r\n row = row.trim();\r\n if (row.length === 0) {\r\n return;\r\n }\r\n\r\n let cols = row.split(\" \");\r\n if (cols.length !== 4) {\r\n valid = false;\r\n }\r\n\r\n cols.forEach((col: any) => {\r\n if (isNaN(col)) {\r\n valid = false;\r\n }\r\n arr.push(parseFloat(col));\r\n });\r\n });\r\n\r\n if (arr.length !== 16) {\r\n valid = false;\r\n }\r\n\r\n if (!valid) {\r\n resolve(errorResponse);\r\n return;\r\n }\r\n\r\n const successResponse = {\r\n success: true,\r\n content: arr\r\n };\r\n\r\n resolve(successResponse);\r\n return;\r\n } catch {\r\n resolve(errorResponse);\r\n return;\r\n }\r\n });\r\n};\r\n\r\nexport const getMatrixValues = async (path: string) => {\r\n const {success, content} = await readTransformFile(path);\r\n\r\n if (!success) {\r\n return {success, rotation: null, offset: null};\r\n }\r\n\r\n const matrix = new Matrix4().fromArray(content);\r\n\r\n const transpose = new Matrix4().copy(matrix).transpose();\r\n const offset = new Vector3().setFromMatrixPosition(transpose);\r\n\r\n matrix.setPosition(0,0,0);\r\n const rotation = new Euler()\r\n .setFromRotationMatrix(matrix)\r\n .toVector3()\r\n .multiplyScalar(180 / Math.PI)\r\n .multiplyScalar(-1);\r\n\r\n return {success, rotation, offset};\r\n};\r\n","import { getConfigVersion } from \"../utilities\";\r\nimport { defaultTagTexture } from \"../viewer/textures/tag-icons\";\r\nimport { AssetType, CameraData } from \"./assets-slice\";\r\nimport { initialAerialState, initialSceneState } from \"./camera-slice\";\r\nimport { currentConfigVersion } from \"./project-slice\";\r\nimport semver from \"semver\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { ProjectType } from \"../types/project\";\r\nimport { TagSize } from \"../types/tags\";\r\n\r\nconst isCameraOrTag = (type) => {\r\n return (type === AssetType.Tag)\r\n || (type === AssetType.Planar)\r\n || (type === AssetType.Panoramic);\r\n};\r\n\r\nexport const upgradeConfig = (config) => {\r\n config = upgradeVersion34(config);\r\n config = upgradeVersion35(config);\r\n config = upgradeVersion36(config);\r\n config = upgradeVersion37(config);\r\n config = upgradeVersion38(config);\r\n config = upgradeVersion39(config);\r\n config = upgradeVersion310(config);\r\n config = upgradeVersion311(config);\r\n config = upgradeVersion312(config);\r\n config = upgradeVersion313(config);\r\n config = upgradeVersion314(config);\r\n config = upgradeVersion315(config);\r\n config = upgradeVersion316(config);\r\n config = upgradeVersion317(config);\r\n config = upgradeVersion318(config);\r\n config = upgradeVersion319(config);\r\n config = upgradeVersion320(config);\r\n config = upgradeVersion321(config);\r\n config = upgradeVersion322(config);\r\n config = upgradeVersion323(config);\r\n config = upgradeVersion324(config);\r\n\r\n /** Additional upgrades go here */\r\n\r\n // Project config should now be at the latest version\r\n config.project.configVersion = currentConfigVersion;\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion324 = (config) => {\r\n const oldVersion = \"3.24.0\";\r\n const newVersion = \"3.25.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add anon access to folders\r\n config.folders = config.folders.map(folder => {\r\n return {\r\n ...folder,\r\n allowAnonViewers: true\r\n };\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion323 = (config) => {\r\n const oldVersion = \"3.23.0\";\r\n const newVersion = \"3.24.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add model draw distance\r\n config.settings.modelDistance = 1000;\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion322 = (config) => {\r\n const oldVersion = \"3.22.0\";\r\n const newVersion = \"3.23.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add annotations state and date to each tag item\r\n config.assets = config.assets.map(asset => {\r\n if (asset.type === AssetType.Tag) {\r\n const items = asset.data.items.map(item => {\r\n delete item.camera;\r\n\r\n return {\r\n ...item,\r\n annotations: []\r\n };\r\n });\r\n\r\n asset.data = {\r\n ...asset.data,\r\n items\r\n };\r\n }\r\n\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion321 = (config) => {\r\n const oldVersion = \"3.21.0\";\r\n const newVersion = \"3.22.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add \"#\" to colors in dxf/shp layer data\r\n config.assets = config.assets.map(asset => {\r\n if ((asset.type === AssetType.DXF) || (asset.type === AssetType.SHP)) {\r\n asset.data = asset.data.map(layer => {\r\n if (layer.color[0] !== \"#\") {\r\n layer.color = `#${layer.color}`;\r\n }\r\n\r\n return layer;\r\n });\r\n }\r\n\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion320 = (config) => {\r\n const oldVersion = \"3.20.0\";\r\n const newVersion = \"3.21.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add scene state and date to each tag item\r\n config.assets = config.assets.map(asset => {\r\n if (asset.type === AssetType.Tag) {\r\n const items = asset.data.items.map(item => {\r\n delete item.camera;\r\n\r\n return {\r\n ...item,\r\n date: new Date().toISOString(),\r\n sceneState: null\r\n };\r\n });\r\n\r\n asset.data = {\r\n ...asset.data,\r\n items\r\n };\r\n }\r\n\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion319 = (config) => {\r\n const oldVersion = \"3.19.0\";\r\n const newVersion = \"3.20.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n config.custom_links = config.links;\r\n delete config.links;\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion318 = (config) => {\r\n const oldVersion = \"3.18.0\";\r\n const newVersion = \"3.19.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add tag draw distance\r\n config.settings.tagDistance = 1000;\r\n\r\n // Update old style camera ids\r\n const mappedCamerasIDs = {};\r\n config.assets.forEach(asset => {\r\n if ((asset.type === AssetType.Panoramic) || (asset.type === AssetType.Planar)) {\r\n const cameras = asset.data as CameraData[];\r\n cameras.forEach(camera => {\r\n const oldCameraID = `${asset.id}-${camera.name}`;\r\n mappedCamerasIDs[oldCameraID] = camera.id;\r\n });\r\n }\r\n });\r\n\r\n if (config.camera.sceneState.camera) {\r\n try {\r\n let newCameraID = mappedCamerasIDs[config.camera.sceneState.camera];\r\n if (newCameraID) {\r\n config.camera.sceneState.camera = newCameraID;\r\n }\r\n } catch {\r\n console.log(\"Error updating camera id (camera state)\");\r\n }\r\n }\r\n\r\n config.bookmarks = config.bookmarks.map(bookmark => {\r\n bookmark.settings.tagDistance = 1000;\r\n\r\n if (bookmark.sceneState.camera) {\r\n try {\r\n let newCameraID = mappedCamerasIDs[bookmark.sceneState.camera];\r\n if (newCameraID) {\r\n bookmark.sceneState.camera = newCameraID;\r\n }\r\n } catch {\r\n console.log(\"Error updating camera id (bookmark)\");\r\n }\r\n }\r\n\r\n return bookmark;\r\n });\r\n\r\n // Add size and camera id field for tags\r\n config.assets = config.assets.map(asset => {\r\n if (asset.type === AssetType.Tag) {\r\n const items = asset.data.items.map(item => {\r\n return {\r\n ...item,\r\n camera: null\r\n };\r\n });\r\n\r\n asset.data = {\r\n ...asset.data,\r\n size: TagSize.Medium,\r\n items\r\n };\r\n }\r\n\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion317 = (config) => {\r\n const oldVersion = \"3.17.0\";\r\n const newVersion = \"3.18.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n if (\"overrideSettings\" in config.settings) {\r\n delete config.settings.overrideSettings;\r\n }\r\n\r\n config.assets = config.assets.map(asset => {\r\n asset.saved = asset.fromJSON;\r\n asset.cloud = false;\r\n delete asset.fromJSON;\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion316 = (config) => {\r\n const oldVersion = \"3.16.0\";\r\n const newVersion = \"3.17.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n config.project.type = ProjectType.Standard;\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion315 = (config) => {\r\n const oldVersion = \"3.15.0\";\r\n const newVersion = \"3.16.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n if (\"newProject\" in config.project) {\r\n delete config.project.newProject;\r\n }\r\n\r\n if (\"modified\" in config.project) {\r\n delete config.project.modified;\r\n }\r\n\r\n config.project.uniqueSession = nanoid();\r\n config.project.id = nanoid();\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion314 = (config) => {\r\n const oldVersion = \"3.14.0\";\r\n const newVersion = \"3.15.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Change from folder.isDefault to folder.default\r\n config.folders = config.folders.map(folder => {\r\n if (folder.hasOwnProperty('isDefault')) {\r\n folder.default = folder.isDefault;\r\n delete folder.isDefault;\r\n }\r\n\r\n return folder;\r\n });\r\n\r\n // Move tag texture string from asset.texture to asset.data.texture\r\n config.assets = config.assets.map(asset => {\r\n if (asset.type !== AssetType.Tag) return asset;\r\n\r\n asset.data = {\r\n texture: asset.texture,\r\n items: asset.data\r\n };\r\n\r\n delete asset['texture'];\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion313 = (config) => {\r\n const oldVersion = \"3.13.0\";\r\n const newVersion = \"3.14.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n config.assets = config.assets.map(asset => {\r\n let filePath = asset.data.path;\r\n\r\n if (filePath) {\r\n asset.path = filePath;\r\n delete asset.data;\r\n } else {\r\n asset.path = null;\r\n }\r\n\r\n return asset;\r\n });\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion312 = (config) => {\r\n const oldVersion = \"3.12.0\";\r\n const newVersion = \"3.13.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n config.settings.overrideSettings = true;\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion311 = (config) => {\r\n const oldVersion = \"3.11.0\";\r\n const newVersion = \"3.12.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Convert from cloudSize to cloudScale + cloudMinimum\r\n const cloudSize = config.settings.cloudSize;\r\n config.settings.cloudScale = Math.min(3.0, cloudSize);\r\n config.settings.cloudMinimum = 2.0;\r\n delete config.settings.cloudSize;\r\n\r\n return config;\r\n};\r\n\r\nconst upgradeVersion310 = (config) => {\r\n const oldVersion = \"3.10.0\";\r\n const newVersion = \"3.11.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n config.assets = config.assets.map(asset => {\r\n // Add unique ID to cameras and tags\r\n if (isCameraOrTag(asset.type)) {\r\n asset.data = asset.data.map(tag => {\r\n return {\r\n id: nanoid(),\r\n ...tag\r\n };\r\n });\r\n }\r\n\r\n // Add comments field for tags\r\n if (asset.type === AssetType.Tag) {\r\n asset.data = asset.data.map(tag => {\r\n return {\r\n ...tag,\r\n comment: \"\"\r\n };\r\n });\r\n }\r\n\r\n return asset;\r\n });\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\nconst upgradeVersion39 = (config) => {\r\n const oldVersion = \"3.9.0\";\r\n const newVersion = \"3.10.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n const extent = config.camera.aerialState.extent;\r\n const resolution = config.camera.aerialState.resolution;\r\n\r\n // Update camera state\r\n config.camera.sceneState = {\r\n ...initialSceneState,\r\n ...config.camera.sceneState\r\n };\r\n\r\n // Update aerial state\r\n config.camera.aerialState = {\r\n ...initialAerialState,\r\n ...config.camera.aerialState\r\n };\r\n\r\n // Convert resolution to zoom\r\n if (resolution) {\r\n const zoom = Math.log2(156543.03390625) - Math.log2(resolution);\r\n config.camera.aerialState.zoom = zoom;\r\n }\r\n\r\n // Convert extent to center\r\n if (extent) {\r\n config.camera.aerialState.center = [\r\n (extent[0] + extent[2]) / 2,\r\n (extent[1] + extent[3]) / 2\r\n ];\r\n }\r\n\r\n delete config.camera.aerialState.resolution;\r\n delete config.camera.aerialState.extent;\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\nconst upgradeVersion38 = (config) => {\r\n const oldVersion = \"3.8.0\";\r\n const newVersion = \"3.9.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Add default texture for tags\r\n config.assets = config.assets.map(asset => {\r\n asset.texture = (asset.type === AssetType.Tag) ? defaultTagTexture : undefined;\r\n return asset;\r\n });\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\nconst upgradeVersion37 = (config) => {\r\n const oldVersion = \"3.7.0\";\r\n const newVersion = \"3.8.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Apply upgrades\r\n delete config.settings.orthoOpacity;\r\n delete config.settings.orthoQuality;\r\n delete config.settings.controlType;\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\nconst upgradeVersion36 = (config) => {\r\n const oldVersion = \"3.6.0\";\r\n const newVersion = \"3.7.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // NOTE: Upgrades removed because of refactoring\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\nconst upgradeVersion35 = (config) => {\r\n const oldVersion = \"3.5.0\";\r\n const newVersion = \"3.6.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // Apply upgrades\r\n config.settings.cloudMaxPoints = config.settings.cloudMaxPoints/1000000;\r\n config.settings.cloudDistance = config.settings.cloudDistance * 10;\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\nconst upgradeVersion34 = (config) => {\r\n const oldVersion = \"3.4.0\";\r\n const newVersion = \"3.5.0\";\r\n\r\n if (semver.gt(getConfigVersion(config), oldVersion)) {\r\n return config;\r\n }\r\n\r\n console.log(`Upgrade configuration file: ${oldVersion} --> ${newVersion}`);\r\n\r\n // NOTE: Upgrades removed because of refactoring\r\n\r\n config.project.configVersion = newVersion;\r\n return config;\r\n};\r\n\r\n","import {store} from '../redux/store';\r\nimport {\r\n defaultProjectTitle,\r\n updateProjectName,\r\n changePath,\r\n currentConfigVersion,\r\n minimumConfigVersion\r\n} from '../redux/project-slice';\r\nimport {\r\n dialog,\r\n fs,\r\n registerEvent,\r\n isElectronApp,\r\n exitFromApp\r\n} from '../electron-modules';\r\nimport slash from 'slash';\r\nimport path from 'path';\r\nimport {isEqual} from 'lodash';\r\nimport { upgradeConfig } from '../redux/config-upgrade';\r\nimport { configFilter } from '../file-extensions';\r\nimport semver from \"semver\";\r\nimport { t } from '../localization';\r\nimport { Projection } from '../redux/projections-slice';\r\nimport { defaultFolderTitle } from '../redux/folders-slice';\r\nimport { ProjectType } from '../types/project';\r\n\r\n/** Return the localized folder name for default project names,\r\n * and the saved name for everything else */\r\nexport const getLocalizedProjectName = (name: string) => {\r\n return name === defaultProjectTitle ? t(name) : name;\r\n};\r\n\r\n/** Return the localized projection name for default projections,\r\n * and the saved name for everything else */\r\nexport const getLocalizedProjectionName = (projection: Projection, units: string) => {\r\n return projection.default\r\n ? t(`projections.default-projection`, {units})\r\n : projection.name;\r\n};\r\n\r\n/** Return the localized folder name for default folders,\r\n * and the saved name for everything else */\r\nexport const getLocalizedFolderName = (name: string) => {\r\n return name === defaultFolderTitle ? t(name) : name;\r\n};\r\n\r\nexport const saveProjectAs = () => {\r\n const projectName = store.getState().project.name;\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n const defaultPath = `${localizedProjectName}.json`;\r\n\r\n return dialog.showSaveDialog({\r\n title: t(\"dialog.save-project\"),\r\n defaultPath,\r\n filters: configFilter,\r\n }).then((result) => {\r\n if (result.canceled) {\r\n return false;\r\n }\r\n\r\n const savePath = slash(result.filePath);\r\n store.dispatch(changePath(savePath));\r\n\r\n // Update the title of the project to be the filename\r\n if (projectName === defaultProjectTitle) {\r\n const fileName = path.basename(savePath);\r\n const extension = path.extname(savePath);\r\n const nameWithoutExt = path.basename(fileName, extension);\r\n store.dispatch(updateProjectName(nameWithoutExt));\r\n }\r\n\r\n writeProject(store);\r\n return true;\r\n }).catch(() => {\r\n dialog.showErrorBox(t(\"dialog.project-save-title\"),\r\n t(\"dialog.project-save-message\"));\r\n return false;\r\n });\r\n};\r\n\r\nexport const saveProject = (allowSaveAs = true) => {\r\n return new Promise(resolve => {\r\n let state = store.getState();\r\n\r\n if (state.project.path === '') {\r\n if (allowSaveAs) {\r\n saveProjectAs().then(result => {\r\n resolve(result);\r\n });\r\n }\r\n return;\r\n } else {\r\n writeProject(store);\r\n resolve(true);\r\n }\r\n });\r\n};\r\n\r\nexport const loadProjectJSON = (projectJSON, parameters = {}) => {\r\n store.dispatch({\r\n type: 'LOAD',\r\n payload: {projectJSON, parameters}\r\n });\r\n};\r\n\r\nexport const getConfigVersion = (config) => {\r\n let version = config.project.configVersion;\r\n if (typeof version === \"number\") {\r\n version = `${String(version)}.0`;\r\n }\r\n\r\n return version;\r\n};\r\n\r\nexport const setWindowHash = (hash) => {\r\n window.history.pushState({}, '', \"#\" + hash);\r\n};\r\n\r\nexport const clearWindowHash = () => {\r\n window.location.hash = \"\";\r\n};\r\n\r\nexport const loadProjectFile = (filePath) => {\r\n try {\r\n const data = fs.readFileSync(filePath, 'utf8');\r\n\r\n // Update json path based on where the json was loaded from\r\n let projectJSON = JSON.parse(data);\r\n projectJSON.project.path = filePath;\r\n\r\n let configVersion = getConfigVersion(projectJSON);\r\n\r\n // Very old versions can't be upgraded\r\n if (semver.lt(configVersion, minimumConfigVersion)) {\r\n dialog.showErrorBox(t(\"dialog.general-error-title\"),\r\n t(\"dialog.legacy-version-error\", {version: configVersion}));\r\n return false;\r\n }\r\n\r\n // Upgrade project configuration to the most recent version\r\n if (semver.lt(configVersion, currentConfigVersion)) {\r\n projectJSON = upgradeConfig(projectJSON);\r\n }\r\n\r\n clearWindowHash();\r\n loadProjectJSON(projectJSON);\r\n return true;\r\n } catch (err) {\r\n dialog.showErrorBox(t(\"dialog.general-error-title\"),\r\n t(\"dialog.project-load-message\"));\r\n return false;\r\n }\r\n};\r\n\r\nexport const loadProject = () => {\r\n dialog.showOpenDialog({\r\n properties: ['openFile'],\r\n filters: configFilter\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n const filePath = slash(result.filePaths[0]);\r\n loadProjectFile(filePath);\r\n }).catch(error => {\r\n console.log(error);\r\n });\r\n};\r\n\r\nexport const newProject = async () => {\r\n const result = await dialog.showMessageBox({\r\n type: 'question',\r\n title: t(\"dialog.new-project-title\"),\r\n message: t(\"dialog.new-project-unsaved\"),\r\n buttons: [\r\n t(\"buttons.cancel\"),\r\n t(\"buttons.new-project\")\r\n ],\r\n noLink: true\r\n });\r\n\r\n if (result.response === 0) return;\r\n store.dispatch({type: 'NEW'});\r\n};\r\n\r\nconst writeProject = (store) => {\r\n // Update saved state for all assets\r\n store.dispatch({\r\n type: \"assets/setSavedState\",\r\n payload: null\r\n });\r\n\r\n const state = store.getState();\r\n const name = state.project.path;\r\n const string = JSON.stringify(state, null, 2);\r\n\r\n fs.writeFile(name, string, (err) => {\r\n if (err) {\r\n throw Error('an error occurred while saving the project');\r\n }\r\n });\r\n};\r\n\r\nconst exitWithChanges = async () => {\r\n const state = store.getState();\r\n\r\n // Cloud projects always exit immediately\r\n if (state.project.type === ProjectType.Cloud) {\r\n exitFromApp();\r\n return;\r\n }\r\n\r\n let hasChanged;\r\n if (state.project.path !== \"\") {\r\n // Compare current state to saved json state\r\n const data = fs.readFileSync(state.project.path, \"utf8\");\r\n let projectJSON = JSON.parse(data);\r\n\r\n const originalState = {...projectJSON};\r\n const modifiedState = JSON.parse(JSON.stringify(state));\r\n\r\n // Our session ID changes every time we load the file,\r\n // so it needs to be removed before we can compare states\r\n delete originalState.project.uniqueSession;\r\n delete modifiedState.project.uniqueSession;\r\n\r\n hasChanged = !isEqual(originalState, modifiedState);\r\n } else {\r\n // Dont prompt user unless assets are loaded\r\n hasChanged = state.assets.length !== 0;\r\n }\r\n\r\n if (!hasChanged) {\r\n exitFromApp();\r\n return;\r\n }\r\n\r\n const result = await dialog.showMessageBox({\r\n type: \"question\",\r\n message: t(\"dialog.exit-save-changes\"),\r\n buttons: [\r\n t(\"buttons.save\"),\r\n t(\"buttons.dont-save\")\r\n ],\r\n defaultId: 2,\r\n noLink: true\r\n });\r\n\r\n if (result.response === 1) {\r\n exitFromApp();\r\n } else if (result.response === 0) {\r\n await saveProject();\r\n exitFromApp();\r\n }\r\n};\r\n\r\nif (isElectronApp) {\r\n registerEvent(\"new-project\", newProject);\r\n registerEvent(\"load-project\", loadProject);\r\n registerEvent(\"save-project\", saveProject);\r\n registerEvent(\"save-project-as\", saveProjectAs);\r\n registerEvent(\"exit-with-changes\", exitWithChanges);\r\n}","import React, { useState, useEffect } from \"react\";\r\nimport { Theme, Grid, Typography } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { useDispatch } from \"react-redux\";\r\nimport { toast } from \"../../app\";\r\nimport {\r\n CheckboxWithLabel,\r\n DropdownWithLabel,\r\n FolderWithLabel,\r\n SimpleDialog,\r\n memoWithOpen\r\n} from \"../../components\";\r\nimport { fse, getTemporaryFile } from \"../../electron-modules\";\r\nimport { deleteAsset } from \"../../redux/assets-slice\";\r\nimport path from \"path\";\r\nimport { useTaskQueue, useViewer } from \"../../hooks\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAssetTools } from \"../../utilities\";\r\nimport { FunctionProps } from \"./props\";\r\nimport * as CSV from 'csv-string';\r\n\r\nenum DetectionType {\r\n VehiclesAndPeople=\"vehicles_and_people\",\r\n Vehicles=\"vehicles\",\r\n People=\"people\"\r\n}\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n mixedDataWarning: {\r\n padding: theme.spacing(1.0),\r\n color: theme.palette.warning.main,\r\n textAlign: \"center\"\r\n }\r\n }),\r\n);\r\n\r\nexport const BlurVehiclesPeople = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [detectionType, setDetectionType] = useState(DetectionType.VehiclesAndPeople);\r\n const [blurStrength, setBlurStrength] = useState(10);\r\n const [accuracy, setAccuracy] = useState(0.5);\r\n const [checkEdges, setCheckEdges] = useState(false);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n };\r\n\r\n const handleSubmit = async () => {\r\n const pythonName = \"blur_vehicles_people\";\r\n\r\n const tempImagePath = getTemporaryFile(\"json\");\r\n const imagesCSVPath = path.join(outputPath, \"blurred-images.csv\");\r\n\r\n try {\r\n const cameras = viewer.getCamerasByCSV(asset.id);\r\n const cameraData = cameras.map(x => x.path);\r\n const pathsJSON = JSON.stringify(cameraData, null, 4);\r\n await fse.writeFile(tempImagePath, pathsJSON);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t('functions.error_running_function'));\r\n return;\r\n }\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--input_path\", tempImagePath,\r\n \"--output_path\", outputPath,\r\n \"--blur_options\", detectionType,\r\n \"--blur_level\", blurStrength,\r\n \"--detection-accuracy\", accuracy,\r\n \"--check_edges\", checkEdges ? 1 : 0\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n try {\r\n // Generate camera csv in output folder\r\n const cameras = viewer.getCamerasByCSV(asset.id);\r\n const rows = viewer.getCameraRowsCSV(cameras);\r\n const content = CSV.stringify(rows);\r\n await fse.writeFile(imagesCSVPath, content);\r\n } catch {\r\n return;\r\n }\r\n\r\n // Remove old camera csv\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new camera csv\r\n await addAssetPaths([imagesCSVPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const cameras = asset ? viewer.getCamerasByCSV(asset.id) : [];\r\n const folders = asset ? viewer.getCameraFolders(cameras) : [];\r\n const inputFolders = new Set([...folders]);\r\n const pathOverlap = inputFolders.has(outputPath);\r\n const canSubmit = !pathOverlap && (outputPath !== null);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {pathOverlap && (\r\n \r\n {t('point-markup.output-folder-must-be-different')}\r\n \r\n )}\r\n\r\n {/** Detection Type */}\r\n \r\n \r\n \r\n\r\n {/** Detection Accuracy */}\r\n \r\n {\r\n const value = (index+1)/10;\r\n const text = `${(index+1)*10}%`;\r\n return [value, text];\r\n })\r\n }\r\n />\r\n \r\n\r\n {/** Blur Level */}\r\n \r\n {\r\n const value = index+1;\r\n const text = `${index+1}`;\r\n return [value, text];\r\n })\r\n }\r\n />\r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n {/** Check Edges */}\r\n \r\n \r\n \r\n\r\n {/** Output folder */}\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n});\r\n","import {\r\n CheckboxWithLabel, DropdownWithLabel,\r\n memoWithOpen,\r\n FileWithLabel,\r\n SimpleDialog\r\n} from \"../../components\";\r\nimport React, {useEffect, useMemo, useState} from \"react\";\r\nimport {useDispatch} from \"react-redux\";\r\nimport {useTaskQueue, useViewer} from \"../../hooks\";\r\nimport {\r\n Checkbox,\r\n Grid,\r\n InputLabel,\r\n ListItemText,\r\n MenuItem,\r\n Select,\r\n Theme,\r\n Typography,\r\n} from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {lasFileFilter} from \"../../file-extensions\";\r\nimport {deleteAsset} from \"../../redux/assets-slice\";\r\nimport clsx from \"clsx\";\r\nimport {classifications} from \"../../classifications\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAssetTools } from \"../../utilities\";\r\nimport { FunctionProps } from \"./props\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n flexibleHeight: {\r\n height: \"100%\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n justifyContent: \"space-between\",\r\n \"& span\": {\r\n flex: 1\r\n }\r\n },\r\n multipleSelectWithLabel: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n justifyContent: \"space-between\",\r\n \"& span\": {\r\n flex: 1\r\n }\r\n },\r\n paddingBottom: {\r\n paddingBottom: `${theme.spacing(1)} !important`,\r\n },\r\n inputParent: {\r\n width: \"100%\",\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n minHeight: theme.spacing(3),\r\n paddingBottom: theme.spacing(0.5)\r\n }\r\n })\r\n);\r\n\r\nenum OperationTypes {\r\n Include = \"include\",\r\n Exclude = \"exclude\"\r\n}\r\n\r\nexport const ClassifyExport = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const {viewer} = useViewer();\r\n const dispatch = useDispatch();\r\n const classes = useStyles();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [operationType, setOperationType] = useState(OperationTypes.Include);\r\n const [classValues, setClassValues] = useState([]);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const classList = useMemo(() => {\r\n if (!open || !asset) return new Set();\r\n const pointCloud = viewer.pointclouds.getByID(asset.id);\r\n return pointCloud.uniqueClassifications;\r\n }, [open, asset]);\r\n\r\n const canSubmit = (outputPath !== null)\r\n && (operationType !== null)\r\n && (classValues.length > 0);\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"classify_export\";\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--inputlas\", asset.path,\r\n \"--outputlas\", outputPath,\r\n \"--operation\", operationType,\r\n \"--classes\", classValues.toString()\r\n ];\r\n\r\n const afterClose = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old LAS\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new thinned LAS\r\n await addAssetPaths([outputPath], asset.folderID);\r\n };\r\n onClose();\r\n addRunningTask(commands, afterClose);\r\n };\r\n\r\n const handleClassChange = (event) => {\r\n setClassValues(event.target.value);\r\n };\r\n\r\n // Function of how the classes vals are rendered and shown in dropdown\r\n const renderClasses = (selected) => {\r\n const renderedClasses = [];\r\n selected.forEach((classVal) => {\r\n renderedClasses.push(formatClassValue(classVal));\r\n });\r\n return renderedClasses.join(\" ,\");\r\n };\r\n\r\n const formatClassValue = (classValue) => {\r\n return classifications[classValue].name + ` (${classValue})`;\r\n };\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n setOperationType(OperationTypes.Include);\r\n setClassValues([]);\r\n setImportResult(true);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Operation Type */}\r\n \r\n \r\n \r\n\r\n {/** Classes */}\r\n \r\n
\r\n
\r\n \r\n {t('functions.classify_export.classes')}\r\n \r\n
\r\n\r\n \r\n {t('functions.classify_export.classes_description')}\r\n \r\n\r\n \r\n {Array.from(classList.values()).map((classValue) => {\r\n return (\r\n \r\n -1} />\r\n \r\n \r\n );\r\n })}\r\n \r\n
\r\n
\r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n {/** Output LAS */}\r\n \r\n \r\n \r\n\r\n
\r\n \r\n
\r\n );\r\n});\r\n","import {\r\n CheckboxWithLabel, DropdownWithLabel,\r\n memoWithOpen,\r\n SimpleDialog,\r\n TextWithLabel\r\n} from \"../../components\";\r\nimport React, {useEffect, useState} from \"react\";\r\nimport {useDispatch} from \"react-redux\";\r\nimport {useTaskQueue} from \"../../hooks\";\r\nimport { FormHelperText, Grid, Theme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {deleteAsset} from \"../../redux/assets-slice\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAssetTools } from \"../../utilities\";\r\nimport { FunctionProps } from \"./props\";\r\nimport { Units } from \"../../types/project\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n helperText: {\r\n textAlign: \"center\",\r\n paddingTop: theme.spacing(2)\r\n },\r\n savedLocation: {\r\n wordWrap: \"break-word\"\r\n }\r\n }),\r\n);\r\n\r\nexport const ConvertUnits = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {addRunningTask} = useTaskQueue();\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n const {addAssetPaths} = useAssetTools();\r\n\r\n const [inputUnits, setInputUnits] = useState(Units.Meters);\r\n const [outputUnits, setOutputUnits] = useState(Units.Feet);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n const nullUnits = inputUnits == null || outputUnits == null;\r\n const sameUnits = (inputUnits === outputUnits && !nullUnits);\r\n const canSubmit = (!sameUnits && !nullUnits);\r\n\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n // Get name of saved file for display\r\n const basename = asset.name.replace(/\\.[^/.]+$/, \"\");\r\n const pathNameNoExt = asset.path.replace(/\\.[^/.]+$/, \"\");\r\n const outputName = `${basename}_${inputUnits}_to_${outputUnits}.las`;\r\n const outputPath = `${pathNameNoExt}_${inputUnits}_to_${outputUnits}.las`;\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"convert_units\";\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--inputlas\", asset.path,\r\n \"--input_units\", inputUnits,\r\n \"--output_units\", outputUnits\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old LAS\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new thinned LAS\r\n await addAssetPaths([outputPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setInputUnits(Units.Meters);\r\n setOutputUnits(Units.Feet);\r\n setImportResult(true);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Input Units */}\r\n \r\n \r\n \r\n\r\n {/** Output Units */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n {/** Output Path Display */}\r\n {canSubmit && \r\n \r\n }\r\n\r\n \r\n {sameUnits && \r\n {t('functions.convert_units.same_units_error')}\r\n }\r\n \r\n \r\n );\r\n});\r\n","import React, { useState, useEffect } from \"react\";\r\nimport { FormHelperText, Grid, Theme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n CheckboxWithLabel,\r\n DropdownWithLabel,\r\n FolderWithLabel,\r\n NumberFieldWithLabel,\r\n SimpleDialog,\r\n memoWithOpen,\r\n} from \"../../components\";\r\nimport { pathWithExtension, useAssetTools } from \"../../utilities\";\r\nimport path from \"path\";\r\nimport LocalScene from \"../../viewer/projections\";\r\nimport { useTaskQueue } from \"../../hooks\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { FunctionProps } from \"./props\";\r\n\r\nenum ChannelType {\r\n Empty=\"empty\",\r\n Red=\"red\",\r\n Green=\"green\",\r\n Blue=\"blue\",\r\n Linearity=\"linearity\",\r\n Planarity=\"planarity\",\r\n Scattering=\"scattering\",\r\n Normal=\"normal\",\r\n Intensity=\"intensity\",\r\n NumReturns=\"num_returns\",\r\n ReturnNumber=\"return_number\",\r\n Classification=\"classification\"\r\n}\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n helperText: {\r\n textAlign: \"center\",\r\n paddingTop: theme.spacing(2)\r\n }\r\n }),\r\n);\r\n\r\ninterface ChannelSelectorProps {\r\n title: string;\r\n value: string | number;\r\n onChange: React.Dispatch;\r\n}\r\n\r\nconst ChannelSelector = (props: ChannelSelectorProps) => {\r\n const {title, value, onChange} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport const LasToOrthomosaic = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const classes = useStyles();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const defaultPixelSize = {value: 0.1, error: false};\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [channelOne, setChannelOne] = useState(ChannelType.Empty);\r\n const [channelTwo, setChannelTwo] = useState(ChannelType.Empty);\r\n const [channelThree, setChannelThree] = useState(ChannelType.Empty);\r\n const [pixelSize, setPixelSize] = useState(defaultPixelSize);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n };\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"las_to_orthomosaic\";\r\n const tifPath = pathWithExtension(\r\n path.join(outputPath, asset.name), \"tif\");\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--input_path\", asset.path,\r\n \"--output_path\", outputPath,\r\n \"--channel_1\", channelOne,\r\n \"--channel_2\", channelTwo,\r\n \"--channel_3\", channelThree,\r\n \"--pixel_size\", pixelSize.value,\r\n \"--units\", LocalScene.dataProjectionUnits\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Add new orthmosaic\r\n await addAssetPaths([tifPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const emptyChannels = (channelOne === ChannelType.Empty)\r\n && (channelTwo === ChannelType.Empty)\r\n && (channelThree === ChannelType.Empty);\r\n\r\n const canSubmit = (outputPath !== null)\r\n && !pixelSize.error\r\n && !emptyChannels;\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Channel 1 color */}\r\n \r\n \r\n \r\n\r\n {/** Channel 2 color */}\r\n \r\n \r\n \r\n\r\n {/** Channel 3 color */}\r\n \r\n \r\n \r\n\r\n {/** Pixel size */}\r\n \r\n \r\n \r\n\r\n {/** Output folder */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n \r\n\r\n {emptyChannels && \r\n {t('functions.las_to_orthomosaic.at_least_one_channel_must_be')}\r\n }\r\n \r\n \r\n );\r\n});\r\n","import React, {useEffect, useState} from \"react\";\r\nimport {\r\n Grid\r\n} from \"@mui/material\";\r\nimport { useDispatch } from \"react-redux\";\r\nimport {\r\n CheckboxWithLabel,\r\n FolderWithLabel,\r\n SimpleDialog,\r\n memoWithOpen,\r\n} from \"../../components\";\r\nimport {pathWithExtension, useAssetTools} from \"../../utilities\";\r\nimport path from \"path\";\r\nimport {useTaskQueue} from \"../../hooks\";\r\nimport {deleteAsset} from \"../../redux/assets-slice\";\r\nimport LocalScene from \"../../viewer/projections\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { FunctionProps } from \"./props\";\r\n\r\nexport const LasToSolv3dStreamable = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [isSingleFile, setSingleFile] = useState(true);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n const canSubmit = (outputPath !== null);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"process_las\";\r\n const binPath = pathWithExtension(\r\n path.join(outputPath, \"octree\"), \"bin\");\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--input_path\", asset.path,\r\n \"--output_folder\", outputPath,\r\n \"--single_file\", isSingleFile,\r\n \"--units\", LocalScene.dataProjectionUnits\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old LAS\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new streamable point cloud\r\n await addAssetPaths([binPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n setImportResult(true);\r\n setSingleFile(true);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Single File */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n {/** Output folder */}\r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n});\r\n\r\n\r\n","import {\r\n CheckboxWithLabel,\r\n FileWithLabel,\r\n memoWithOpen,\r\n NumberFieldWithLabel,\r\n SimpleDialog\r\n} from \"../../components\";\r\nimport React, {useEffect, useState} from \"react\";\r\nimport {useDispatch} from \"react-redux\";\r\nimport {useTaskQueue} from \"../../hooks\";\r\nimport {Grid} from \"@mui/material\";\r\nimport {lasFileFilter} from \"../../file-extensions\";\r\nimport {deleteAsset} from \"../../redux/assets-slice\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAssetTools } from \"../../utilities\";\r\nimport { FunctionProps } from \"./props\";\r\n\r\nexport const Sampling = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const defaultSamplingRateOptions = {\r\n value: 40,\r\n error: false\r\n };\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [samplingRate, setSamplingRate] = useState(defaultSamplingRateOptions);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n const validSampling = samplingRate.error === false && samplingRate.value !== null;\r\n const canSubmit = (outputPath !== null && validSampling);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"sampling\";\r\n const decimalSamplingRate = samplingRate.value/100;\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--inputlas\", asset.path,\r\n \"--outputlas\", outputPath,\r\n \"--rate\", decimalSamplingRate\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old LAS\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new sampled LAS\r\n await addAssetPaths([outputPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n setSamplingRate(defaultSamplingRateOptions);\r\n setImportResult(true);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Sampling Rate */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n {/** Output LAS */}\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n});\r\n","import React, {useEffect, useState} from \"react\";\r\nimport { FormHelperText, Grid, Theme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { useDispatch } from \"react-redux\";\r\nimport {\r\n CheckboxWithLabel,\r\n DropdownWithLabel,\r\n FileWithLabel,\r\n NumberFieldWithLabel,\r\n SimpleDialog,\r\n memoWithOpen,\r\n} from \"../../components\";\r\nimport {useTaskQueue} from \"../../hooks\";\r\nimport {deleteAsset} from \"../../redux/assets-slice\";\r\nimport {lasFileFilter} from \"../../file-extensions\";\r\nimport {tempDirectoryPath} from \"../../electron-modules\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAssetTools } from \"../../utilities\";\r\nimport { FunctionProps } from \"./props\";\r\n\r\nenum ThinTechniques {\r\n Highest = \"highest\",\r\n Lowest = \"lowest\",\r\n Average = \"average\"\r\n}\r\n\r\nenum ThinDimensions {\r\n Two = 2,\r\n Three = 3,\r\n}\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n invalidThinningError: {\r\n padding: theme.spacing(1.0),\r\n color: theme.palette.warning.main,\r\n textAlign: \"center\"\r\n }\r\n }),\r\n);\r\n\r\nexport const ThinLas = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {addRunningTask} = useTaskQueue();\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const {addAssetPaths} = useAssetTools();\r\n\r\n const defaultThinningOptions = {\r\n value: 0.1,\r\n error: false\r\n };\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [thinTechnique, setThinTechnique] = useState(ThinTechniques.Lowest);\r\n const [thinDimension, setThinDimension] = useState(ThinDimensions.Two);\r\n const [thinning, setThinning] = useState(defaultThinningOptions);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n const inValidThinningValue = thinning.value <= 0;\r\n const canSubmit = (outputPath !== null && !thinning.error && thinDimension && thinTechnique && !inValidThinningValue);\r\n\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"thin\";\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--inputlas\", asset.path,\r\n \"--outputlas\", outputPath,\r\n \"--precision\", thinning.value,\r\n \"--keepvalue\", thinTechnique,\r\n \"--temp\", tempDirectoryPath,\r\n \"--dim\", thinDimension\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old LAS\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new thinned LAS\r\n await addAssetPaths([outputPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n setThinTechnique(ThinTechniques.Lowest);\r\n setThinDimension(ThinDimensions.Two);\r\n setThinning(defaultThinningOptions);\r\n setImportResult(true);\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Output thinning */}\r\n \r\n \r\n \r\n\r\n {/** Thin Technique */}\r\n \r\n \r\n \r\n\r\n {/** Thin Dimension */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n {/** Output LAS */}\r\n \r\n \r\n \r\n \r\n\r\n {inValidThinningValue && \r\n {t('functions.thin_las.invalid_thinning_value')}\r\n }\r\n\r\n \r\n \r\n );\r\n});\r\n\r\n\r\n","import React, { useState } from \"react\";\r\nimport {\r\n CheckboxWithLabel,\r\n FileWithLabel,\r\n SimpleDialog,\r\n memoWithOpen\r\n} from \"../../components\";\r\nimport { FunctionProps } from \"./props\";\r\nimport { Grid } from \"@mui/material\";\r\nimport { DXFModelFilter, lasFileFilter } from \"../../file-extensions\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useDispatch } from \"react-redux\";\r\nimport { deleteAsset } from \"../../redux/assets-slice\";\r\nimport { useTaskQueue } from \"../../hooks\";\r\nimport { useAssetTools } from \"../../utilities\";\r\n\r\nexport const InterpolateDXF = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [demPath, setDemPath] = useState(null);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"interpolate_dxf\";\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--input_path\", asset.path,\r\n \"--output_path\", outputPath,\r\n \"--dem_path\", demPath\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old dxf\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new interpolated dxf\r\n await addAssetPaths([outputPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n const canSubmit = outputPath && demPath;\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Input DEM */}\r\n \r\n \r\n \r\n\r\n {/** Output DXF */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n});\r\n","import React, { useState } from \"react\";\r\nimport {\r\n CheckboxWithLabel,\r\n FileWithLabel,\r\n SimpleDialog,\r\n memoWithOpen\r\n} from \"../../components\";\r\nimport { FunctionProps } from \"./props\";\r\nimport { Grid } from \"@mui/material\";\r\nimport { SHPModelFilter, lasFileFilter } from \"../../file-extensions\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useDispatch } from \"react-redux\";\r\nimport { deleteAsset } from \"../../redux/assets-slice\";\r\nimport { useTaskQueue } from \"../../hooks\";\r\nimport { useAssetTools } from \"../../utilities\";\r\n\r\nexport const InterpolateSHP = memoWithOpen((props: FunctionProps) => {\r\n const {assets, open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {addRunningTask} = useTaskQueue();\r\n const {addAssetPaths} = useAssetTools();\r\n const {t} = useTranslation();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [demPath, setDemPath] = useState(null);\r\n const [importResult, setImportResult] = useState(true);\r\n\r\n // TODO: actually handle multiple inputs (sent multiple exe commands to processing queue)\r\n const asset = assets ? assets[0] : undefined;\r\n\r\n const handleSubmit = () => {\r\n const pythonName = \"interpolate_shp\";\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--input_path\", asset.path,\r\n \"--output_path\", outputPath,\r\n \"--dem_path\", demPath\r\n ];\r\n\r\n const onFinish = async () => {\r\n if (!importResult) return;\r\n\r\n // Remove old shapefile\r\n dispatch(deleteAsset(asset.id));\r\n\r\n // Add new interpolated shapefile\r\n await addAssetPaths([outputPath], asset.folderID);\r\n };\r\n\r\n onClose();\r\n addRunningTask(commands, onFinish);\r\n };\r\n\r\n const canSubmit = outputPath && demPath;\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Input DEM */}\r\n \r\n \r\n \r\n\r\n {/** Output SHP */}\r\n \r\n \r\n \r\n\r\n {/** Import results */}\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n});\r\n","import React from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { MenuItem, Typography } from \"@mui/material\";\r\nimport FunctionsIcon from '@mui/icons-material/Functions';\r\nimport { NestedMenu } from \"../components\";\r\nimport {\r\n BlurVehiclesPeople,\r\n ClassifyExport,\r\n ConvertUnits,\r\n InterpolateDXF,\r\n InterpolateSHP,\r\n LasToOrthomosaic,\r\n LasToSolv3dStreamable,\r\n Sampling,\r\n ThinLas\r\n} from \"./definitions\";\r\nimport { Asset, AssetType } from \"../redux/assets-slice\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { useDialog } from \"../hooks\";\r\n\r\nconst generateFunctionData = (title, condition, onClick) => {\r\n return {\r\n name: title,\r\n condition: condition,\r\n component: (\r\n \r\n {title}\r\n \r\n )\r\n };\r\n};\r\n\r\ninterface FunctionsMenuProps {\r\n assets: Asset[];\r\n contextOpen: boolean;\r\n closeContextMenu: () => void;\r\n}\r\n\r\nexport const FunctionsMenu = React.forwardRef((props: FunctionsMenuProps, ref) => {\r\n const {assets, contextOpen, closeContextMenu} = props;\r\n\r\n const {t} = useTranslation();\r\n const blurVehiclesPeopleDialog = useDialog();\r\n const lasToOrthomosaicDialog = useDialog();\r\n const lasToSolv3dStreamableDialog = useDialog();\r\n const thinLasDialog = useDialog();\r\n const samplingDialog = useDialog();\r\n const classifyExportDialog = useDialog();\r\n const convertUnitsDialog = useDialog();\r\n const interpolateSHPDialog = useDialog();\r\n const interpolateDXFDialog = useDialog();\r\n\r\n const LASFiles = assets.filter(asset => asset.type === AssetType.LAS);\r\n const cameraFiles = assets.filter(asset => asset.type === AssetType.Panoramic);\r\n const SHPFiles = assets.filter(asset => asset.type === AssetType.SHP);\r\n const DXFFiles = assets.filter(asset => asset.type === AssetType.DXF);\r\n\r\n const hasLASFiles = LASFiles.length > 0;\r\n const hasCameraFiles = cameraFiles.length > 0;\r\n const hasSHPFiles = SHPFiles.length > 0;\r\n const hasDXFFiles = DXFFiles.length > 0;\r\n\r\n const handleBlurVehiclesPeople = () => {\r\n closeContextMenu();\r\n blurVehiclesPeopleDialog.handleOpen();\r\n };\r\n\r\n const handleLasToOrthomosaic = () => {\r\n closeContextMenu();\r\n lasToOrthomosaicDialog.handleOpen();\r\n };\r\n\r\n const handleLasToSolv3dStreamable = () => {\r\n closeContextMenu();\r\n lasToSolv3dStreamableDialog.handleOpen();\r\n };\r\n\r\n const handleThinLas = () => {\r\n closeContextMenu();\r\n thinLasDialog.handleOpen();\r\n };\r\n\r\n const handleSampling = () => {\r\n closeContextMenu();\r\n samplingDialog.handleOpen();\r\n };\r\n\r\n const handleClassifyExport = () => {\r\n closeContextMenu();\r\n classifyExportDialog.handleOpen();\r\n };\r\n\r\n const handleConvertUnits = () => {\r\n closeContextMenu();\r\n convertUnitsDialog.handleOpen();\r\n };\r\n\r\n const handleInterpolateSHP = () => {\r\n closeContextMenu();\r\n interpolateSHPDialog.handleOpen();\r\n };\r\n\r\n const handleInterpolateDXF = () => {\r\n closeContextMenu();\r\n interpolateDXFDialog.handleOpen();\r\n };\r\n\r\n const getMenuItems = () => {\r\n if (!contextOpen) return [];\r\n\r\n const data = [\r\n generateFunctionData(\r\n t('functions.blur_vehicles_people.title'),\r\n hasCameraFiles,\r\n handleBlurVehiclesPeople\r\n ),\r\n generateFunctionData(\r\n t('functions.las_to_orthomosaic.title'),\r\n hasLASFiles,\r\n handleLasToOrthomosaic\r\n ),\r\n generateFunctionData(\r\n t('functions.las_to_solv3d_streamable.title'),\r\n hasLASFiles,\r\n handleLasToSolv3dStreamable\r\n ),\r\n generateFunctionData(\r\n t('functions.thin_las.title'),\r\n hasLASFiles,\r\n handleThinLas\r\n ),\r\n generateFunctionData(\r\n t('functions.sampling.title'),\r\n hasLASFiles,\r\n handleSampling\r\n ),\r\n generateFunctionData(\r\n t('functions.classify_export.title'),\r\n hasLASFiles,\r\n handleClassifyExport\r\n ),\r\n generateFunctionData(\r\n t('functions.convert_units.title'),\r\n hasLASFiles,\r\n handleConvertUnits\r\n ),\r\n generateFunctionData(\r\n \"Interpolate Height\",\r\n hasDXFFiles,\r\n handleInterpolateDXF\r\n ),\r\n generateFunctionData(\r\n \"Interpolate Height\",\r\n hasSHPFiles,\r\n handleInterpolateSHP\r\n )\r\n ];\r\n\r\n let filtered = data\r\n .filter(x => x.condition)\r\n .sort((a, b) => a.name.localeCompare(b.name))\r\n .map(x => x.component);\r\n\r\n if (filtered.length === 0) {\r\n return (\r\n \r\n \r\n {t('functions.no_functions_available')}\r\n \r\n \r\n );\r\n }\r\n\r\n return filtered;\r\n };\r\n\r\n return (\r\n \r\n }\r\n parentMenuOpen={contextOpen}\r\n >\r\n {getMenuItems()}\r\n \r\n\r\n {hasCameraFiles && \r\n\r\n {/** Blur vehicles and people */}\r\n \r\n\r\n }\r\n\r\n {hasLASFiles && \r\n\r\n {/** LAS to Orthomosaic */}\r\n \r\n\r\n {/** LAS to Solv3D Streamable Point Cloud */}\r\n \r\n\r\n {/** Thin Las */}\r\n \r\n\r\n {/** Sampling */}\r\n \r\n\r\n {/** Sampling */}\r\n \r\n\r\n {/** Convert Units */}\r\n \r\n\r\n }\r\n\r\n {hasSHPFiles && \r\n \r\n }\r\n\r\n {hasDXFFiles && \r\n \r\n }\r\n\r\n \r\n );\r\n});\r\n","export enum ServerType {\r\n ArcGISMapServer = 0,\r\n ArcGISFeatureServer = 1,\r\n ArcGISImageServer = 2,\r\n ArcGISOnline = 3,\r\n OGCWMS = 4,\r\n OGCWMTS = 5,\r\n OGCWFS = 6,\r\n TileServer = 7\r\n}","import React, {useEffect, useState, memo, useCallback, useMemo} from \"react\";\r\nimport {isCloudSite, isElectronApp} from '../electron-modules';\r\nimport CloudIcon from \"@mui/icons-material/Cloud\";\r\nimport InfoIcon from \"@mui/icons-material/Info\";\r\nimport PanoramaIcon from '@mui/icons-material/Panorama';\r\nimport PanoramaOutlinedIcon from '@mui/icons-material/PanoramaOutlined';\r\nimport ListItemText from \"@mui/material/ListItemText\";\r\nimport PublicIcon from '@mui/icons-material/Public';\r\nimport {\r\n Avatar,\r\n Checkbox,\r\n DialogContent,\r\n ListItemButton,\r\n ListItemSecondaryAction,\r\n MenuItem,\r\n Typography\r\n} from \"@mui/material\";\r\nimport EditIcon from \"@mui/icons-material/Edit\";\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport ErrorIcon from '@mui/icons-material/Error';\r\nimport PhotoLibraryIcon from '@mui/icons-material/PhotoLibrary';\r\nimport SwapHorizIcon from '@mui/icons-material/SwapHoriz';\r\nimport WarningIcon from '@mui/icons-material/Warning';\r\nimport ImportExportIcon from '@mui/icons-material/ImportExport';\r\nimport Satellite from '@mui/icons-material/Satellite';\r\nimport {\r\n DenseMenu,\r\n DraggableDialog,\r\n DropDownDialog,\r\n LinearProgressWithLabel,\r\n MenuDivider,\r\n PromptDialog,\r\n TextDialog\r\n} from \"../components\";\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n AssetType,\r\n updateAsset,\r\n deleteAsset,\r\n Asset,\r\n CameraData,\r\n TagData,\r\n XMLData,\r\n WebMapData,\r\n LineworkLayerData\r\n} from \"../redux/assets-slice\";\r\nimport {useDispatch} from 'react-redux';\r\nimport { downloadFile } from '../utilities';\r\nimport {\r\n DenseIcon,\r\n FontAwesomeIcon,\r\n ArrowTooltip\r\n} from '../components';\r\nimport clsx from 'clsx';\r\nimport {toast} from \"../app\";\r\nimport {\r\n TagItemsDialog,\r\n TagIconDialog,\r\n ModelLayerDialog,\r\n WebSourceLayerDialog\r\n} from \".\";\r\nimport { getTagTexturePath } from \"../viewer/textures/tag-icons\";\r\nimport { isEqual } from 'lodash';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { FunctionsMenu } from \"../functions\";\r\nimport { useAuth, useContextMenu, useDialog, useViewer } from \"../hooks\";\r\nimport { ServerType } from \"../types/web-sources\";\r\nimport { csvExportFilter } from \"../file-extensions\";\r\nimport * as CSV from 'csv-string';\r\n\r\nconst updateInterval = 200;\r\n\r\ninterface AssetState {\r\n assetPercent: number\r\n assetError: boolean\r\n assetIsLarge: boolean\r\n}\r\n\r\nconst initialAssetState = {\r\n assetPercent: 0,\r\n assetError: false,\r\n assetIsLarge: false,\r\n};\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n floatRight: {\r\n float: \"right\"\r\n },\r\n itemText: {\r\n wordBreak: \"break-all\",\r\n overflow: \"hidden\"\r\n },\r\n assetMargins: {\r\n margin: '0px 12px 0px 0px'\r\n },\r\n assetError: {\r\n color: theme.palette.error.main,\r\n fontWeight: \"bold\"\r\n },\r\n assetWarning: {\r\n color: theme.palette.warning.main,\r\n fontWeight: \"bold\"\r\n },\r\n assetInfo: {\r\n display: 'flex',\r\n margin: '0px'\r\n },\r\n assetCheckbox: {\r\n position: \"relative\",\r\n transform: \"translateY(0%)\",\r\n alignItems: \"center\",\r\n display: \"flex\",\r\n right: \"8px\"\r\n },\r\n checkboxParent: {\r\n padding: \"6px\"\r\n },\r\n percentLabel: {\r\n textAlign: \"right\"\r\n },\r\n fileInfoHeading: {\r\n paddingTop: theme.spacing(2.0)\r\n },\r\n fileInfoText: {\r\n display: \"block\"\r\n },\r\n tagAvatar: {\r\n width: \"20px\",\r\n height: \"20px\",\r\n borderRadius: theme.spacing(0)\r\n },\r\n titleClose: {\r\n position: 'absolute',\r\n right: theme.spacing(0),\r\n color: theme.palette.grey[500],\r\n },\r\n remoteAssetIcon: {\r\n fontSize: \"0.8rem\",\r\n marginRight: \"-0.8rem\", // must match font size\r\n position: \"relative\",\r\n left: \"-8px\",\r\n bottom: \"-5px\",\r\n opacity: \"1.0\",\r\n color: \"lightgray\",\r\n filter: \"drop-shadow(2px 2px 1px darkgray)\"\r\n }\r\n }),\r\n);\r\n\r\ninterface LasFileInfoDialogProps {\r\n asset: Asset;\r\n open: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nconst LasFileInfoDialog = (props: LasFileInfoDialogProps) => {\r\n const {open, onClose, asset} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [data, setData] = useState(null);\r\n\r\n const hasVLRSData = data ? data.vlrs_data : false;\r\n\r\n let vlrsKeys = null;\r\n if (hasVLRSData) {\r\n vlrsKeys = Object.keys(data.vlrs_data);\r\n vlrsKeys.sort();\r\n }\r\n\r\n useEffect(() => {\r\n if (!viewer || !open) return;\r\n const info = viewer.getLasFileInfo(asset.id);\r\n\r\n if (info) {\r\n setData(info);\r\n return;\r\n }\r\n\r\n toast.warning(t(\"toast.file-info-missing\"));\r\n onClose();\r\n }, [viewer, open]);\r\n\r\n return (\r\n \r\n {data && \r\n \r\n {t('asset.general-attributes')}\r\n \r\n\r\n \r\n {t('asset.file-name')}: {asset.name}\r\n \r\n\r\n \r\n {t('asset.point-information')}\r\n \r\n \r\n {t('asset.point-count')}: {data.points.count}\r\n \r\n \r\n {t('asset.x-range')}: [{data.points.x_min.toFixed(2)}, {data.points.x_max.toFixed(2)}]\r\n \r\n \r\n {t('asset.y-range')}: [{data.points.y_min.toFixed(2)}, {data.points.y_max.toFixed(2)}]\r\n \r\n \r\n {t('asset.z-range')}: [{data.points.z_min.toFixed(2)}, {data.points.z_max.toFixed(2)}]\r\n \r\n\r\n \r\n {t('asset.data-format')}\r\n \r\n \r\n {t('asset.las-version')}: {data.attributes.version}\r\n \r\n \r\n {t('asset.record-id')}: {data.attributes.record_id}\r\n \r\n \r\n {t('asset.contains-timestamp')}: {data.attributes.has_time_stamp ? t('general.yes') : t('general.no')}\r\n \r\n \r\n {t('asset.contains-rgb')}: {data.attributes.has_rgb ? t('general.yes') : t('general.no')}\r\n \r\n \r\n {t('asset.contains-intensity')}: {data.attributes.has_intensity ? t('general.yes') : t('general.no')}\r\n \r\n\r\n \r\n {t('asset.vlrs-metadata')}\r\n \r\n\r\n {hasVLRSData && (\r\n {vlrsKeys.map((key, index) => {\r\n return (\r\n \r\n {key}: {data.vlrs_data[key]}\r\n \r\n );\r\n })}\r\n )}\r\n\r\n {/* Nothing found in VLRS */}\r\n {!hasVLRSData && (\r\n \r\n {t('asset.no-data-found')}\r\n \r\n )}\r\n\r\n }\r\n \r\n );\r\n};\r\n\r\ninterface AssetItemProps {\r\n asset: Asset;\r\n setDraggingAsset: React.Dispatch;\r\n}\r\n\r\nexport const AssetItem = memo((props: AssetItemProps) => {\r\n const {asset, setDraggingAsset} = props;\r\n\r\n const dispatch = useDispatch();\r\n const theme = useTheme();\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const contextMenu = useContextMenu();\r\n const fileInfoDialog = useDialog();\r\n const detailsDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const renameDialog = useDialog();\r\n const iconUpdateDialog = useDialog();\r\n const modelLayersDialog = useDialog();\r\n const webmapLayersDialog = useDialog();\r\n const landXMLDialog = useDialog();\r\n const {permissions} = useAuth();\r\n\r\n const [assetState, setAssetState] = useState({\r\n ...initialAssetState\r\n });\r\n\r\n\r\n const isPanoramic = asset.type === AssetType.Panoramic;\r\n const isPlanar = asset.type === AssetType.Planar;\r\n const isEncompassCloud = asset.type === AssetType.Encompass;\r\n const isPotreeCloud = asset.type === AssetType.Potree;\r\n const isLASFile = asset.type === AssetType.LAS;\r\n const isE57File = asset.type === AssetType.E57Points;\r\n const isOrtho = asset.type === AssetType.OrthoMosaic;\r\n const isTag = asset.type === AssetType.Tag;\r\n const isIFC = asset.type === AssetType.IFC;\r\n const isSHP = asset.type === AssetType.SHP;\r\n const isDXF = asset.type === AssetType.DXF;\r\n const isLandXML = asset.type === AssetType.LandXML;\r\n const isWebMap = asset.type === AssetType.Webmap;\r\n\r\n const isModelFile = isIFC || isSHP || isDXF;\r\n const isCamera = isPanoramic || isPlanar;\r\n const isPointCloud = isLASFile || isEncompassCloud || isE57File || isPotreeCloud;\r\n\r\n const canEditLayers = useMemo(() => {\r\n if (isSHP || isDXF) {\r\n return true;\r\n }\r\n\r\n if (isWebMap) {\r\n const type = (asset.data as WebMapData).type;\r\n return (type !== ServerType.ArcGISImageServer)\r\n && (type !== ServerType.TileServer);\r\n }\r\n\r\n return false;\r\n }, [asset.type]);\r\n\r\n /** Handle asset percentage / state changes */\r\n useEffect(() => {\r\n // Create interval to update state\r\n const interval = setInterval(() => {\r\n updateAssetState();\r\n }, updateInterval);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [viewer, assetState]);\r\n\r\n useEffect(() => {\r\n // Update initial state\r\n updateAssetState();\r\n }, []);\r\n\r\n const updateAssetState = () => {\r\n if (!viewer) return;\r\n\r\n let newAssetState = {} as AssetState;\r\n\r\n if (isPointCloud) {\r\n newAssetState = viewer.getCloudStatus(asset.id);\r\n } else if (isModelFile) {\r\n newAssetState = viewer.getModelStatus(asset.id);\r\n }\r\n\r\n if (isEqual(assetState, newAssetState)) return;\r\n setAssetState(newAssetState);\r\n };\r\n\r\n const handleRenameSubmit = (name: string) => {\r\n dispatch(updateAsset({\r\n assetID: asset.id,\r\n name: name\r\n }));\r\n\r\n renameDialog.handleClose();\r\n };\r\n\r\n const handleRenameClick = () => {\r\n contextMenu.handleClose();\r\n renameDialog.handleOpen();\r\n };\r\n\r\n const handleDeleteClick = () => {\r\n contextMenu.handleClose();\r\n deleteDialog.handleOpen();\r\n };\r\n\r\n const handleIconChangeClick = () => {\r\n contextMenu.handleClose();\r\n iconUpdateDialog.handleOpen();\r\n };\r\n\r\n const handleOrderingClick = () => {\r\n contextMenu.handleClose();\r\n landXMLDialog.handleOpen();\r\n };\r\n\r\n const handleOrderingClose = (state: boolean) => {\r\n contextMenu.handleClose();\r\n landXMLDialog.handleClose();\r\n\r\n dispatch(updateAsset({\r\n assetID: asset.id,\r\n enu: state\r\n }));\r\n };\r\n\r\n const handleTagCSVExport = (asset) => {\r\n contextMenu.handleClose();\r\n const tags = viewer.getTagsByCSV(asset.id);\r\n const rows = viewer.getTagRowsCSV(tags);\r\n const content = CSV.stringify(rows);\r\n downloadFile(asset.name, content, \"csv\", csvExportFilter);\r\n };\r\n\r\n const handleImageCSVExport = (asset) => {\r\n contextMenu.handleClose();\r\n const cameras = viewer.getCamerasByCSV(asset.id);\r\n const rows = viewer.getCameraRowsCSV(cameras);\r\n const content = CSV.stringify(rows);\r\n downloadFile(asset.name, content, \"csv\", csvExportFilter);\r\n };\r\n\r\n const handleModelLayersClick = () => {\r\n contextMenu.handleClose();\r\n modelLayersDialog.handleOpen();\r\n };\r\n\r\n const handleWebmapLayersClick = () => {\r\n contextMenu.handleClose();\r\n webmapLayersDialog.handleOpen();\r\n };\r\n\r\n const onAssetDelete = () => {\r\n dispatch(deleteAsset(asset.id));\r\n };\r\n\r\n const handleAssetClick = (event) => {\r\n const isCheckBox = (event.target.type === \"checkbox\");\r\n if (isCheckBox) return;\r\n\r\n if (isOrtho) {\r\n viewer?.snapToOrtho(asset.id);\r\n } else if (isPointCloud) {\r\n viewer?.snapToPointCloud(asset.id);\r\n } else if (isCamera) {\r\n viewer?.snapToImages(asset.id);\r\n } else if (isTag) {\r\n detailsDialog.handleOpen();\r\n } else if (isModelFile) {\r\n viewer?.snapToModel(asset.id);\r\n }\r\n };\r\n\r\n const handleDragStart = () => {\r\n setDraggingAsset(asset.id);\r\n };\r\n\r\n const handleDragEnd = () => {\r\n setDraggingAsset(null);\r\n };\r\n\r\n const handleVisibilityClick = () => {\r\n dispatch(updateAsset({\r\n assetID: asset.id,\r\n visible: !asset.visible\r\n }));\r\n };\r\n\r\n const handleFileInfoClick = () => {\r\n contextMenu.handleClose();\r\n fileInfoDialog.handleOpen();\r\n };\r\n\r\n const getAssetCount = () => {\r\n if (isPanoramic) {\r\n const items = asset.data as CameraData[];\r\n return t(\"asset.panoramic-count\", {\r\n count: items.length\r\n });\r\n } else if (isPlanar) {\r\n const items = asset.data as CameraData[];\r\n return t(\"asset.planar-count\", {\r\n count: items.length\r\n });\r\n } else if (isTag) {\r\n const {items} = asset.data as TagData;\r\n return t(\"asset.tags-count\", {\r\n count: items.length\r\n });\r\n } else if (isSHP || isDXF) {\r\n const items = asset.data as LineworkLayerData[];\r\n return t(\"asset.layers-count\", {\r\n count: items.length\r\n });\r\n }\r\n\r\n return;\r\n };\r\n\r\n const getTagAttributes = () => {\r\n if (!isTag) return {\r\n tagTexture: undefined,\r\n tagSize: undefined\r\n };\r\n\r\n const {texture, size} = (asset.data as TagData);\r\n\r\n return {\r\n tagTexture: texture,\r\n tagSize: size\r\n };\r\n };\r\n\r\n const submitTagIcon = useCallback((texture: string, size: number) => {\r\n dispatch(updateAsset({\r\n assetID: asset.id,\r\n texture: texture,\r\n size: size\r\n }));\r\n\r\n iconUpdateDialog.handleClose();\r\n }, [asset]);\r\n\r\n const {assetPercent, assetError, assetIsLarge} = assetState;\r\n\r\n const isLargeCloud = isPointCloud\r\n && assetIsLarge\r\n && (assetPercent < 100)\r\n && !assetError;\r\n\r\n const showPercent = (isLASFile || isE57File || isModelFile)\r\n && asset.visible\r\n && (assetPercent < 100);\r\n\r\n const assetCount = getAssetCount();\r\n const {tagTexture, tagSize} = getTagAttributes();\r\n const isRemoteAsset = asset.cloud && !isCloudSite;\r\n\r\n // Right now we only officially support editing/deleting\r\n // tag collections for the cloud site\r\n const canDeleteAsset = isElectronApp || (permissions.delete && isTag);\r\n const canEditAsset = isElectronApp || (permissions.edit && isTag);\r\n\r\n return (\r\n
\r\n \r\n
\r\n \r\n \r\n {/* Panoramic File */}\r\n {(isPanoramic) && ()}\r\n\r\n {/* Planar File */}\r\n {(isPlanar) && ()}\r\n\r\n {/* Tag File */}\r\n {isTag && ()}\r\n\r\n {/* Orthomosaic File */}\r\n {(isOrtho) && ()}\r\n\r\n {/* LandXML File */}\r\n {(isLandXML) && }\r\n\r\n {/* Webmap */}\r\n {(isWebMap) && }\r\n\r\n {/* Model File */}\r\n {isModelFile && \r\n {!assetError && (\r\n \r\n )}\r\n\r\n {assetError && (\r\n \r\n \r\n \r\n )}\r\n }\r\n\r\n {/* Pointcloud File */}\r\n {isPointCloud && \r\n {(!assetError && !isLargeCloud) && (\r\n \r\n )}\r\n\r\n {assetError && (\r\n \r\n \r\n \r\n )}\r\n\r\n {(isLargeCloud) && (\r\n \r\n \r\n \r\n )}\r\n }\r\n\r\n {isRemoteAsset && \r\n \r\n \r\n \r\n }\r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n
\r\n\r\n {/* File load percent */}\r\n {showPercent && (
\r\n \r\n
)}\r\n\r\n \r\n\r\n \r\n {/** Functions submenu */}\r\n {isElectronApp && }\r\n\r\n {isElectronApp && }\r\n\r\n {/** Export image csv */}\r\n {isPanoramic && {\r\n handleImageCSVExport(asset);\r\n }}>\r\n \r\n \r\n \r\n \r\n {t('asset.export-corrected-csv')}\r\n \r\n }\r\n\r\n {/** Export tag csv */}\r\n {isTag && {\r\n handleTagCSVExport(asset);\r\n }}>\r\n \r\n \r\n \r\n \r\n {t('asset.export-tag-csv')}\r\n \r\n }\r\n\r\n {/** Get LAS information */}\r\n {isLASFile && (\r\n \r\n \r\n \r\n \r\n {t('asset.file-info')}\r\n \r\n )}\r\n\r\n {/** Update tag icon */}\r\n {isTag && permissions.edit &&\r\n \r\n \r\n \r\n \r\n \r\n {t('asset.update-tag-icon')}\r\n \r\n \r\n }\r\n\r\n {/** Manage webmap layers */}\r\n {isWebMap && canEditLayers && (\r\n \r\n \r\n \r\n \r\n \r\n {t('asset.manage_layers')}\r\n \r\n \r\n )}\r\n\r\n {/** Manage model layers */}\r\n {isModelFile && canEditLayers && (\r\n \r\n \r\n \r\n \r\n \r\n {\"Manage Layers\"}\r\n \r\n \r\n )}\r\n\r\n {/** LandXML ordering */}\r\n {isLandXML && isElectronApp && (\r\n \r\n \r\n \r\n \r\n \r\n {t('asset.landxml-ordering')}\r\n \r\n \r\n )}\r\n\r\n {/** Rename asset */}\r\n \r\n \r\n \r\n \r\n \r\n {t('asset.rename')}\r\n \r\n \r\n\r\n {/** Delete asset */}\r\n \r\n \r\n \r\n \r\n \r\n {t('asset.delete')}\r\n \r\n \r\n \r\n\r\n {isTag && ()}\r\n\r\n {isWebMap && canEditLayers && ()}\r\n\r\n {isModelFile && canEditLayers && ()}\r\n\r\n {/* Discard measurements dialog */}\r\n {\r\n onAssetDelete();\r\n }}\r\n title={t('asset.delete-title')}\r\n prompt={t('asset.delete-prompt', {\r\n name: asset.name\r\n })}\r\n button={t(\"buttons.delete\")}\r\n />\r\n\r\n {/* Rename Dialog */}\r\n \r\n\r\n {/* LAS file info Dialog */}\r\n \r\n\r\n {/* Tag info dialog */}\r\n {isTag && }\r\n\r\n\r\n {isLandXML && }\r\n\r\n
\r\n );\r\n});\r\n","import React, {memo, useCallback, useEffect, useMemo, useState} from \"react\";\r\nimport {useSelector, useDispatch} from 'react-redux';\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport tagTextures, { defaultTagTexture, getTagTexturePath } from \"../viewer/textures/tag-icons\";\r\nimport Pagination from \"@mui/lab/Pagination/Pagination\";\r\nimport LinkIcon from '@mui/icons-material/Link';\r\nimport ZoomInIcon from '@mui/icons-material/ZoomIn';\r\nimport CheckCircleIcon from '@mui/icons-material/CheckCircle';\r\nimport FileCopyIcon from '@mui/icons-material/FileCopy';\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport {\r\n createTags,\r\n updateTag,\r\n deleteTag,\r\n getTagAssets,\r\n selectAllAssets,\r\n TagData,\r\n TagItemData,\r\n Asset,\r\n createAsset,\r\n AssetType\r\n} from \"../redux/assets-slice\";\r\nimport {createFolder, selectAllFolders} from '../redux/folders-slice';\r\nimport {\r\n DialogContent,\r\n InputLabel,\r\n TextField,\r\n Avatar,\r\n Grid,\r\n Collapse,\r\n Button,\r\n DialogActions,\r\n Select,\r\n FormHelperText\r\n} from \"@mui/material\";\r\nimport clsx from 'clsx';\r\nimport {\r\n DraggableDialog,\r\n PromptDialog,\r\n EnhancedTable,\r\n SimpleDialog,\r\n InputWithLabel,\r\n DropdownWithLabel,\r\n DenseDivider,\r\n DividerWithText,\r\n EditableTextField,\r\n EditableDropdown,\r\n TextWithLabel,\r\n ColorPicker,\r\n optionsToDropdown,\r\n EditButtonGroup,\r\n DropdownOption\r\n} from \"../components\";\r\nimport { headerHeight, toast } from \"../app\";\r\nimport { getLocalizedFolderName, toLocaleString } from \"../utilities\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { isStaticSite } from \"../electron-modules\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { useAuth, useDialog, useUniqueProjectID, useViewer } from \"../hooks\";\r\nimport { AnnotationDrawType, AnnotationSize, TagSize } from \"../types/tags\";\r\nimport { sendCustomEvent } from \"../events\";\r\nimport { useTableState } from \"../hooks/use-table-state\";\r\nimport { useAppDispatch } from \"../redux/store\";\r\nimport copyTextToClipboard from \"copy-to-clipboard\";\r\nimport { selectViewerSwitched } from \"../redux/settings-slice\";\r\n\r\nexport const tagIconsPerRow = 8;\r\nexport const tagRowsPerPage = 3;\r\n\r\nconst NEW_CSV_ID = \"__new_csv__\";\r\nconst NEW_FOLDER_ID = \"__new_folder__\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n textField: {\r\n marginBottom: theme.spacing(3)\r\n },\r\n selectDivider: {\r\n margin: theme.spacing(0.5),\r\n opacity: 0.2\r\n },\r\n asterisk: {\r\n \"&:after\": {\r\n content:'\"*\"',\r\n color: \"red\",\r\n paddingLeft: theme.spacing(0.5)\r\n }\r\n },\r\n avatarParent: {\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n paddingTop: theme.spacing(2)\r\n },\r\n tagAvatar: {\r\n width: \"24px\",\r\n height: \"24px\",\r\n cursor: \"pointer\",\r\n \"&:hover\": {\r\n width: \"26px\",\r\n height: \"26px\",\r\n margin: \"-1px\"\r\n }\r\n },\r\n tagIconPagination: {\r\n paddingBottom: theme.spacing(2)\r\n },\r\n tagIconSearchParent: {\r\n textAlign: \"right\",\r\n paddingRight: theme.spacing(2),\r\n paddingBottom: theme.spacing(1)\r\n },\r\n tagIconPageParent: {\r\n width: \"100%\",\r\n display: \"flex\",\r\n flexDirection: \"row-reverse\"\r\n },\r\n tagIconParent: {\r\n position: \"relative\",\r\n display: \"inline-block\",\r\n width: `calc(${100/tagIconsPerRow}% - ${theme.spacing(2)})`,\r\n padding: theme.spacing(1)\r\n },\r\n tagIconCheck: {\r\n userSelect: \"none\",\r\n bottom: theme.spacing(1),\r\n right: theme.spacing(1),\r\n position: \"absolute\",\r\n color: \"green\",\r\n backgroundColor: \"white\",\r\n borderRadius: \"50%\"\r\n },\r\n tagIconImage: {\r\n width: `calc(100% - ${theme.spacing(1)})`,\r\n height: `calc(100% - ${theme.spacing(1)})`,\r\n margin: theme.spacing(0.5),\r\n cursor: \"pointer\",\r\n \"&:hover\": {\r\n width: \"100%\",\r\n height: \"100%\",\r\n margin: \"0px\",\r\n }\r\n },\r\n content: {\r\n padding: theme.spacing(0),\r\n paddingTop: \"0px !important\"\r\n }\r\n }),\r\n);\r\n\r\ninterface TagIconDialogProps {\r\n open: boolean\r\n onSubmit(texture: string, size: number): void\r\n onClose(): void\r\n currentTexture: string\r\n currentSize: number\r\n}\r\n\r\nexport const TagIconDialog = memo((props: TagIconDialogProps) => {\r\n const {open, onSubmit, onClose, currentTexture, currentSize} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const [page, setPage] = useState(1);\r\n const [search, setSearch] = useState(\"\");\r\n const [tagTexture, setTagTexture] = useState(\"\");\r\n const [tagSize, setTagSize] = useState(0);\r\n\r\n const handleIconClick = (texture) => {\r\n setTagTexture(texture);\r\n };\r\n\r\n const onSearch = (event) => {\r\n setPage(1);\r\n setSearch(event.target.value as string);\r\n };\r\n\r\n const onPageChange = (event, page: number) => {\r\n setPage(page);\r\n };\r\n\r\n const resetDefaults = () => {\r\n let selectedPage = Math.floor(\r\n textures.indexOf(currentTexture) / tagsPerPage) + 1;\r\n\r\n setSearch(\"\");\r\n setTagTexture(currentTexture);\r\n setTagSize(currentSize);\r\n setPage(selectedPage);\r\n };\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const textures = useMemo(() => {\r\n const searchText = search.toLowerCase().trim();\r\n const searchTerms = searchText.split(\" \");\r\n\r\n if (searchText === \"\") {\r\n return Object.keys(tagTextures);\r\n }\r\n\r\n return Object.keys(tagTextures)\r\n .map(key => {\r\n const itemText = key.toLowerCase();\r\n const matches = searchTerms.filter(x => itemText.includes(x)).length;\r\n return {key, matches};\r\n })\r\n .filter(x => x.matches >= searchTerms.length)\r\n .map(x => x.key);\r\n }, [search]);\r\n\r\n const iconChanged = (tagTexture !== currentTexture);\r\n const sizeChanged = (tagSize !== currentSize);\r\n\r\n const tagsPerPage = tagIconsPerRow * tagRowsPerPage;\r\n const numPages = Math.ceil(textures.length / tagsPerPage);\r\n\r\n const texturesForPage = textures.slice(\r\n (page-1) * tagsPerPage,\r\n page * tagsPerPage\r\n );\r\n\r\n return (\r\n {\r\n onSubmit(tagTexture, tagSize);\r\n }}\r\n button={t(\"buttons.save-changes\")}\r\n >\r\n
\r\n \r\n
\r\n\r\n
\r\n {texturesForPage.map(texture => (\r\n
\r\n {\r\n handleIconClick(texture);\r\n }}\r\n />\r\n\r\n {(texture === tagTexture) && ()}\r\n
\r\n ))}\r\n
\r\n\r\n
\r\n \r\n
\r\n\r\n \r\n\r\n
\r\n \r\n\r\n {/** Icon Size */}\r\n \r\n \r\n \r\n
\r\n\r\n \r\n );\r\n});\r\n\r\ninterface TagItemsDialogProps {\r\n asset: Asset\r\n open: boolean;\r\n title: string;\r\n onClose(): void;\r\n}\r\n\r\nexport const TagItemsDialog = (props: TagItemsDialogProps) => {\r\n const {asset, open, title, onClose} = props;\r\n\r\n const {viewer} = useViewer();\r\n const {i18n, t} = useTranslation();\r\n\r\n const deleteDialog = useDialog();\r\n const {permissions} = useAuth();\r\n const tableState = useTableState({defaultSort: \"name\"});\r\n\r\n const formatter = viewer.getMeasurementFormatter();\r\n const projection = viewer.getViewProjection();\r\n const precision = formatter.getVectorPrecision(projection);\r\n\r\n const onRowClick = (row, index) => {\r\n if (index > 2) return;\r\n viewer.jumpToTag(row.tagID, true);\r\n };\r\n\r\n const getRows = (items) => {\r\n return items.map((tag, index) => {\r\n const isAerialTag = !(\"z\" in tag);\r\n const x = tag.x.toFixed(precision.x);\r\n const y = tag.y.toFixed(precision.y);\r\n const z = isAerialTag ? \"N/A\" : tag.z.toFixed(precision.z);\r\n\r\n const coordinate = isAerialTag\r\n ? `(${x}, ${y})`\r\n : `(${x}, ${y}, ${z})`;\r\n\r\n const position = isAerialTag\r\n ? [tag.x, tag.y]\r\n : [tag.x, tag.y, tag.z];\r\n\r\n let rowData = {\r\n id: `TagTableRow_${tag.id}`,\r\n tagID: tag.id,\r\n tag: index + 1,\r\n modified: tag.date,\r\n name: tag.name,\r\n comment: tag.comment,\r\n coordinate,\r\n position\r\n };\r\n\r\n return rowData;\r\n });\r\n };\r\n\r\n const tagItems = (asset.data as TagData).items;\r\n\r\n const actions = useMemo(() => {\r\n const zoomToTag = {\r\n title: t('tags.move_to_tag'),\r\n icon: ,\r\n onClick: (row) => {\r\n viewer.jumpToTag(row.tagID);\r\n }\r\n };\r\n\r\n const copyPosition = {\r\n title: t(\"tags.copy-to-clipboard\"),\r\n icon: ,\r\n onClick: (row) => {\r\n // Copy position to clipboard\r\n copyTextToClipboard(row.coordinate);\r\n toast.success(t(\"toast.copied-to-clipboard\"));\r\n }\r\n };\r\n\r\n const copyURL = {\r\n title: t('tags.copy_tag_url'),\r\n icon: ,\r\n onClick: (row) => {\r\n // Copy url to clipboard\r\n const url = new URL(window.location as any);\r\n url.hash = `tag=${row.tagID}`;\r\n copyTextToClipboard(url.href);\r\n toast.success(t(\"toast.copied-to-clipboard\"));\r\n }\r\n };\r\n\r\n const deleteRow = {\r\n title: t(\"buttons.delete\"),\r\n icon: ,\r\n onClick: (row) => {\r\n const tagToDelete = row.tagID;\r\n deleteDialog.handleOpen([tagToDelete]);\r\n }\r\n };\r\n\r\n let actions = [];\r\n actions.push(zoomToTag);\r\n actions.push(copyPosition);\r\n\r\n if (isStaticSite) {\r\n actions.push(copyURL);\r\n }\r\n\r\n if (permissions.delete) {\r\n actions.push(deleteRow);\r\n }\r\n\r\n return actions;\r\n }, [i18n.language, permissions, isStaticSite]);\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t(\"tags.name\"),\r\n wordBreak: true,\r\n searchable: true\r\n },\r\n {\r\n id: 'comment',\r\n label: t(\"tags.comments\"),\r\n wordBreak: true,\r\n searchable: true\r\n },\r\n {\r\n id: 'modified',\r\n label: t(\"tags.date\"),\r\n date: true\r\n },\r\n ];\r\n\r\n const rows = useMemo(() => {\r\n return getRows(tagItems);\r\n }, [tagItems]);\r\n\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n {/* Delete Dialog */}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface TagDeleteDialogProps {\r\n open: boolean;\r\n onClose(): void;\r\n onDelete?(): void;\r\n toDelete: string[];\r\n}\r\n\r\nexport const TagDeleteDialog = (props: TagDeleteDialogProps) => {\r\n const {open, onClose, onDelete, toDelete = []} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n\r\n const onSubmit = () => {\r\n for (const tagID of toDelete) {\r\n dispatch(deleteTag(tagID));\r\n };\r\n\r\n onClose();\r\n onDelete?.();\r\n\r\n toast.success(t(\"toast.tag-removed\", {\r\n count: numTagsToDelete\r\n }));\r\n };\r\n\r\n const numTagsToDelete = toDelete ? toDelete.length : 0;\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nconst getTagDetails = (assets: Asset[], tagID: string) => {\r\n const tagFiles = getTagAssets(assets);\r\n\r\n for (let file of tagFiles) {\r\n const tags = (file.data as TagData).items;\r\n const selected = tags.find(tag => tag.id === tagID);\r\n\r\n if (selected) {\r\n return {\r\n tag: selected,\r\n asset: file\r\n };\r\n };\r\n }\r\n\r\n return {\r\n tag: null,\r\n asset: null\r\n };\r\n};\r\n\r\nexport const TagDetailsDialog = () => {\r\n const assets = useSelector(selectAllAssets);\r\n const uniqueProjectID = useUniqueProjectID();\r\n const detailsDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const {t} = useTranslation();\r\n const {permissions} = useAuth();\r\n\r\n const [tagID, setTagID] = useState(null);\r\n\r\n const onClose = () => {\r\n detailsDialog.handleClose();\r\n setTagID(null);\r\n };\r\n\r\n const onDelete = () => {\r\n deleteDialog.handleOpen([tagID]);\r\n };\r\n\r\n const {tag, asset} = useMemo(() => {\r\n return getTagDetails(assets, tagID);\r\n }, [assets, tagID]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n onClose();\r\n }, [uniqueProjectID]);\r\n\r\n /** Event listener */\r\n useEffect(() => {\r\n const callback = (event) => {\r\n setTagID(event.detail);\r\n detailsDialog.handleOpen();\r\n };\r\n\r\n document.addEventListener(\"tag-details\", callback);\r\n\r\n return () => {\r\n document.removeEventListener(\"tag-details\", callback);\r\n };\r\n }, []);\r\n\r\n return (\r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n {permissions.delete && \r\n {t('buttons.delete')}\r\n }\r\n\r\n \r\n {t('buttons.close')}\r\n \r\n \r\n\r\n \r\n\r\n {/* Delete Dialog */}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface AnnotationsToolbarProps {\r\n tag: TagItemData;\r\n}\r\n\r\nconst AnnotationsToolbar = (props: AnnotationsToolbarProps) => {\r\n const {tag} = props;\r\n\r\n const theme = useTheme();\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n const {viewer} = useViewer();\r\n const {permissions} = useAuth();\r\n\r\n const viewerSwitched = useSelector(selectViewerSwitched);\r\n\r\n const [editing, setEditing] = useState(false);\r\n const [size, setSize] = useState(AnnotationSize.Medium);\r\n const [type, setType] = useState(AnnotationDrawType.Polygon);\r\n const [color, setColor] = useState(\"#FF0000\");\r\n\r\n const savedAnnotations = tag\r\n ? tag.annotations ? [...tag.annotations] : []\r\n : [];\r\n\r\n const savedTagID = tag ? tag.id : null;\r\n\r\n const handleSave = () => {\r\n const annotations = viewer.getTagAnnotations();\r\n toast.success(t(\"toast.tag-details-update\"));\r\n dispatch(updateTag({tagID: tag.id, annotations}));\r\n };\r\n\r\n const handleCancel = () => {\r\n // Discard any changes and load saved annotations\r\n viewer.loadTagAnnotations(savedAnnotations);\r\n };\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setTagAnnotationType(type);\r\n }, [viewer, type]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setTagAnnotationColor(color);\r\n }, [viewer, color]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setTagAnnotationSize(size);\r\n }, [viewer, size]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n if (savedTagID) {\r\n viewer.toggleTagAnnotations(true);\r\n viewer.loadTagAnnotations(savedAnnotations);\r\n viewer.setTagSelected(savedTagID);\r\n } else {\r\n viewer.toggleTagAnnotations(false);\r\n viewer.setTagSelected(null);\r\n setEditing(false);\r\n }\r\n }, [viewer, savedTagID]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setTagAnnotationDrawing(editing);\r\n }, [viewer, editing]);\r\n\r\n useEffect(() => {\r\n // Disable editing if we minimize the aerial view\r\n if (viewerSwitched) return;\r\n setEditing(false);\r\n }, [viewerSwitched]);\r\n\r\n const typeOptions = optionsToDropdown([\r\n [AnnotationDrawType.Polygon, t('tags.polygon')],\r\n [AnnotationDrawType.PolygonFreeHand, t('tags.polygon_freehand')],\r\n [AnnotationDrawType.LineString, t('tags.linestring')],\r\n [AnnotationDrawType.LineStringFreeHand, t('tags.linestring_freehand')],\r\n [AnnotationDrawType.Rectangle, t('tags.rectangle')],\r\n [AnnotationDrawType.Circle, t('tags.circle')],\r\n [AnnotationDrawType.Star, t('tags.star')],\r\n [AnnotationDrawType.Eraser, t('tags.eraser')],\r\n ]);\r\n\r\n const sizeOptions = optionsToDropdown([\r\n [AnnotationSize.Small, t('sizes.small')],\r\n [AnnotationSize.Medium, t('sizes.medium')],\r\n [AnnotationSize.Large, t('sizes.large')],\r\n [AnnotationSize.XLarge, t('sizes.extra_large')]\r\n ]);\r\n\r\n const showToolbar = tag\r\n && permissions.edit\r\n && viewerSwitched;\r\n\r\n return (\r\n \r\n {showToolbar &&
\r\n
\r\n \r\n {t('tags.tag_annotations_toolbar')}\r\n \r\n\r\n
\r\n {/** Annotation Type */}\r\n {\r\n setType(event.target.value as AnnotationDrawType);\r\n }}\r\n >\r\n {typeOptions}\r\n \r\n\r\n {/** Annotation Size */}\r\n {\r\n setSize(event.target.value as AnnotationSize);\r\n }}\r\n >\r\n {sizeOptions}\r\n \r\n\r\n {/** Annotation Color */}\r\n \r\n\r\n {/** Save/Edit Buttons */}\r\n \r\n
\r\n\r\n
\r\n
}\r\n
\r\n );\r\n};\r\n\r\ninterface TagDetailsContentProps {\r\n tag: TagItemData;\r\n asset: Asset;\r\n}\r\n\r\nconst TagDetailsContent = (props: TagDetailsContentProps) => {\r\n const {tag, asset} = props;\r\n\r\n const dispatch = useDispatch();\r\n const assets = useSelector(selectAllAssets);\r\n const {i18n, t} = useTranslation();\r\n\r\n const onChangeName = (value: string) => {\r\n toast.success(t(\"toast.tag-details-update\"));\r\n dispatch(updateTag({tagID: tag.id, name: value}));\r\n };\r\n\r\n const onChangeComment = (value: string) => {\r\n toast.success(t(\"toast.tag-details-update\"));\r\n dispatch(updateTag({tagID: tag.id, comment: value}));\r\n };\r\n\r\n const onChangeAsset = (value: string) => {\r\n toast.success(t(\"toast.tag-details-update\"));\r\n dispatch(updateTag({tagID: tag.id, assetID: value}));\r\n };\r\n\r\n const options = useMemo(() => {\r\n return getTagAssets(assets).map(file => {\r\n return [file.id, file.name];\r\n }) as [string, string][];\r\n }, [assets]);\r\n\r\n const dateString = tag\r\n ? toLocaleString(tag.date, i18n.language)\r\n : \"\";\r\n\r\n return (\r\n \r\n {tag && \r\n \r\n {/** Title */}\r\n \r\n \r\n \r\n\r\n {/** Comments */}\r\n \r\n \r\n \r\n\r\n {/** Modified date */}\r\n {\r\n \r\n }\r\n\r\n {/** Tag Collection */}\r\n {\r\n \r\n }\r\n \r\n }\r\n \r\n );\r\n};\r\n\r\ninterface TagCreateDialogProps {\r\n open: boolean;\r\n onClose(): void;\r\n coordinate: number[];\r\n}\r\n\r\nexport const TagCreateDialog = memo((props: TagCreateDialogProps) => {\r\n const {open, onClose, coordinate} = props;\r\n\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n const dispatch = useAppDispatch();\r\n const {t} = useTranslation();\r\n const iconUpdateDialog = useDialog();\r\n const {viewer} = useViewer();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const tagFiles = getTagAssets(assets);\r\n const folders = useSelector(selectAllFolders);\r\n\r\n const [title, setTitle] = useState(\"\");\r\n const [comment, setComment] = useState(\"\");\r\n const [collectionID, setCollectionID] = useState(\"\");\r\n const [collectionName, setCollectionName] = useState(\"\");\r\n const [folderID, setFolderID] = useState(NEW_FOLDER_ID);\r\n const [tagTexture, setTagTexture] = useState(defaultTagTexture);\r\n const [tagSize, setTagSize] = useState(TagSize.Medium);\r\n\r\n const onSubmit = async () => {\r\n onClose();\r\n\r\n const newTag = {\r\n id: nanoid(),\r\n name: title,\r\n comment: comment,\r\n date: new Date().toISOString(),\r\n x: coordinate[0],\r\n y: coordinate[1],\r\n annotations: []\r\n } as TagItemData;\r\n\r\n if (coordinate.length === 3) {\r\n newTag.z = coordinate[2];\r\n newTag.sceneState = viewer.sceneState;\r\n }\r\n\r\n let tagFolderID;\r\n\r\n if (createNewFolder) {\r\n // Create new folder\r\n const folder = await dispatch(createFolder());\r\n tagFolderID = folder.id;\r\n } else {\r\n tagFolderID = folderID;\r\n }\r\n\r\n let tagCollectionID;\r\n\r\n if (createNewFile) {\r\n // Create new tag collection\r\n const asset = await dispatch(createAsset({\r\n folderID: tagFolderID,\r\n name: collectionName,\r\n type: AssetType.Tag,\r\n texture: tagTexture,\r\n size: tagSize\r\n }));\r\n\r\n tagCollectionID = asset.id;\r\n } else {\r\n tagCollectionID = collectionID;\r\n }\r\n\r\n // Add new tag to collection\r\n await dispatch(createTags({\r\n assetID: tagCollectionID,\r\n tags: [newTag]\r\n }));\r\n\r\n toast.success(t(\"toast.tag-added\"));\r\n };\r\n\r\n const resetDefaultValues = () => {\r\n setTitle(\"\");\r\n setComment(\"\");\r\n setCollectionName(\"\");\r\n setTagTexture(defaultTagTexture);\r\n\r\n iconUpdateDialog.handleClose();\r\n\r\n if (hasExistingFolders) {\r\n setFolderID(folders[0].id);\r\n } else {\r\n setFolderID(NEW_FOLDER_ID);\r\n }\r\n\r\n if (hasExistingCSVs) {\r\n setCollectionID(tagFiles[0].id);\r\n } else {\r\n setCollectionID(\"\");\r\n }\r\n };\r\n\r\n const submitTagIcon = useCallback((texture: string, size: number) => {\r\n setTagTexture(texture);\r\n setTagSize(size);\r\n iconUpdateDialog.handleClose();\r\n }, []);\r\n\r\n const getMenuItems = () => {\r\n // Folder is used if it is user made or if it contains assets\r\n const folderOptions = folders.filter(folder => {\r\n const items = assets.filter(x => x.folderID === folder.id);\r\n return folder.default ? items.length > 0 : true;\r\n });\r\n\r\n const options = folderOptions.map(folder => {\r\n const localizedFolderName = getLocalizedFolderName(folder.name);\r\n return [folder.id, localizedFolderName];\r\n }) as DropdownOption[];\r\n\r\n const newFolder = [NEW_FOLDER_ID, t(\"tags.new-folder\")] as DropdownOption;\r\n\r\n return [newFolder, ...options];\r\n };\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n resetDefaultValues();\r\n }, [open]);\r\n\r\n const hasExistingCSVs = tagFiles.length > 0;\r\n const hasExistingFolders = folders.length > 0;\r\n const createNewFile = collectionID === NEW_CSV_ID;\r\n const createNewFolder = folderID === NEW_FOLDER_ID;\r\n\r\n /* Determine valid state for new tag */\r\n let canSubmit = true;\r\n const titleMissing = title.trim() === \"\";\r\n const nameMissing = collectionName.trim() === \"\";\r\n canSubmit = canSubmit && !titleMissing;\r\n canSubmit = canSubmit && !(nameMissing && createNewFile);\r\n\r\n const options = getMenuItems();\r\n\r\n return (\r\n \r\n {/* New tag dialog */}\r\n \r\n \r\n\r\n {/** Title */}\r\n \r\n \r\n \r\n\r\n {/** Comments */}\r\n \r\n \r\n \r\n\r\n \r\n [tagCSV.id, tagCSV.name])\r\n ] as any}\r\n />\r\n \r\n\r\n
\r\n \r\n \r\n\r\n {/** Tag collection name */}\r\n \r\n \r\n \r\n\r\n {/** Tag collection folder */}\r\n \r\n \r\n \r\n\r\n {/** Default Icon */}\r\n \r\n
\r\n \r\n {t('tags.collection_icon')}\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n\r\n
\r\n \r\n\r\n {/* Tag Icon */}\r\n \r\n
\r\n );\r\n});\r\n\r\nexport const showTagDetails = (tagID: string) => {\r\n sendCustomEvent(\"tag-details\", tagID);\r\n};\r\n","import React, {useState, memo, useEffect} from \"react\";\r\nimport FolderIcon from \"@mui/icons-material/Folder\";\r\nimport ListItemText from \"@mui/material/ListItemText\";\r\nimport {Checkbox, Grid, ListItemButton} from \"@mui/material\";\r\nimport {\r\n Asset,\r\n deleteAsset,\r\n toggleFolderVisibility,\r\n updateAsset\r\n} from \"../redux/assets-slice\";\r\nimport ExpandLess from \"@mui/icons-material/ExpandLess\";\r\nimport ExpandMore from \"@mui/icons-material/ExpandMore\";\r\nimport List from \"@mui/material/List\";\r\nimport {AddAssetList, AssetItem} from \".\";\r\nimport {useDispatch} from 'react-redux';\r\nimport {\r\n CheckboxWithLabel,\r\n DenseIcon,\r\n DenseMenu,\r\n InputWithLabel,\r\n MenuDivider,\r\n NestedMenu,\r\n PromptDialog,\r\n SimpleDialog\r\n} from '../components';\r\nimport {MenuItem, Typography} from \"@mui/material\";\r\nimport EditIcon from \"@mui/icons-material/Edit\";\r\nimport PublicOffIcon from '@mui/icons-material/PublicOff';\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport AddIcon from '@mui/icons-material/Add';\r\nimport {createFolder, deleteFolder, Folder, updateFolder} from '../redux/folders-slice';\r\nimport { isElectronApp, isStaticSite } from \"../electron-modules\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { getLocalizedFolderName, isAssetFile, useAssetTools } from \"../utilities\";\r\nimport slash from \"slash\";\r\nimport { useContextMenu, useDialog } from \"../hooks\";\r\n\r\nexport const assetFolderClass = \"asset-folder\";\r\n\r\ninterface NewFolderDialogProps {\r\n open: boolean;\r\n onClose: () => void;\r\n folder?: Folder;\r\n}\r\n\r\n/** Dialog for creating and editing folder properties */\r\nexport const FolderDialog = (props: NewFolderDialogProps) => {\r\n const {open, onClose, folder} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n\r\n const [name, setName] = useState(\"\");\r\n const [allowAnonViewers, setAllowAnonViewers] = useState(true);\r\n\r\n const handleSubmit = () => {\r\n if (folder) {\r\n // Update existing folder\r\n dispatch(updateFolder({\r\n folderID: folder.id,\r\n name,\r\n allowAnonViewers\r\n }));\r\n } else {\r\n // Create a new folder\r\n dispatch(createFolder(name, allowAnonViewers));\r\n }\r\n onClose();\r\n };\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n if (folder) {\r\n const localizedFolderName = getLocalizedFolderName(folder.name);\r\n setName(localizedFolderName);\r\n setAllowAnonViewers(folder.allowAnonViewers);\r\n } else {\r\n setName(\"\");\r\n setAllowAnonViewers(true);\r\n }\r\n }, [open]);\r\n\r\n const canSubmit = !!name;\r\n\r\n const title = folder\r\n ? t('folder.edit-title')\r\n : t(\"folder.create-title\");\r\n\r\n return (\r\n \r\n \r\n\r\n {/** Title */}\r\n \r\n \r\n \r\n\r\n {/** Anonymous access */}\r\n \r\n \r\n \r\n\r\n \r\n \r\n );\r\n};\r\n\r\n\r\ninterface AssetFolderProps {\r\n folder: Folder;\r\n assets: Asset[];\r\n draggingAsset: boolean;\r\n setDraggingAsset: React.Dispatch\r\n}\r\n\r\nexport const AssetFolder = memo((props: AssetFolderProps) => {\r\n const {folder, assets, draggingAsset, setDraggingAsset} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n const {addAssetPaths} = useAssetTools();\r\n const contextMenu = useContextMenu();\r\n const deleteDialog = useDialog();\r\n const editDialog = useDialog();\r\n\r\n const [expanded, setExpanded] = useState(true);\r\n const [dragDropHover, setDragDropHover] = useState(false);\r\n\r\n const updateAssetFolder = (assetID) => {\r\n dispatch(updateAsset({\r\n assetID,\r\n folderID: folder.id\r\n }));\r\n };\r\n\r\n const addAssetsToFolder = (event) => {\r\n const assetPaths = [...event.dataTransfer.files]\r\n .map(file => slash(file.path))\r\n .filter(isAssetFile);\r\n\r\n addAssetPaths(assetPaths, folder.id);\r\n };\r\n\r\n const handleClick = (event) => {\r\n const isCheckBox = (event.target.type === \"checkbox\");\r\n if (isCheckBox) return;\r\n\r\n setExpanded(!expanded);\r\n };\r\n\r\n const handleDragOver = (event) => {\r\n event.preventDefault();\r\n setDragDropHover(true);\r\n };\r\n\r\n const handleDragLeave = (event) => {\r\n setDragDropHover(false);\r\n };\r\n\r\n const handleDrop = (event) => {\r\n if (isStaticSite) return;\r\n\r\n setDragDropHover(false);\r\n\r\n if (draggingAsset) {\r\n updateAssetFolder(draggingAsset);\r\n } else {\r\n addAssetsToFolder(event);\r\n }\r\n };\r\n\r\n const handleDeleteSubmit = () => {\r\n deleteDialog.handleClose();\r\n\r\n for (let asset of assets) {\r\n dispatch(deleteAsset(asset.id));\r\n }\r\n\r\n dispatch(deleteFolder(folder.id));\r\n };\r\n\r\n const handleDeleteClick = () => {\r\n contextMenu.handleClose();\r\n deleteDialog.handleOpen();\r\n };\r\n\r\n const handleEditClick = () => {\r\n contextMenu.handleClose();\r\n editDialog.handleOpen();\r\n };\r\n\r\n const toggleCheckboxes = () => {\r\n let newVisibility;\r\n if (numVisible > 0 && numHidden > 0) {\r\n newVisibility = true;\r\n } else if (numVisible > 0) {\r\n newVisibility = false;\r\n } else {\r\n newVisibility = true;\r\n }\r\n\r\n dispatch(toggleFolderVisibility({\r\n folderID: folder.id,\r\n visible: newVisibility\r\n }));\r\n };\r\n\r\n const numVisible = assets.filter(x => x.visible).length;\r\n const numHidden = assets.filter(x => !x.visible).length;\r\n\r\n // Folder is visible if it is user made or if it contains assets\r\n const visible = folder.default ? assets.length > 0 : true;\r\n\r\n const localizedFolderName = getLocalizedFolderName(folder.name);\r\n\r\n return (\r\n \r\n {visible && (\r\n \r\n \r\n \r\n \r\n\r\n {!folder.allowAnonViewers && \r\n \r\n }\r\n\r\n \r\n\r\n {(assets.length > 0) && (\r\n {/* Show / hide contents */}\r\n {expanded ? : }\r\n\r\n {/* Toggle all folder assets */}\r\n 0}\r\n onChange={toggleCheckboxes}\r\n indeterminate={numVisible > 0 && numHidden > 0}\r\n />\r\n )}\r\n\r\n \r\n )}\r\n\r\n {visible && expanded && (\r\n \r\n {assets.map(asset => )}\r\n \r\n )}\r\n\r\n \r\n {/** New asset submenu */}\r\n }\r\n parentMenuOpen={contextMenu.open}\r\n >\r\n \r\n \r\n\r\n {/** Functions submenu */}\r\n {/*\r\n {}\r\n */}\r\n\r\n {isElectronApp && }\r\n\r\n {/** Edit folder */}\r\n \r\n \r\n \r\n \r\n \r\n {t(\"folder.edit\")}\r\n \r\n \r\n\r\n {/** Delete folder */}\r\n \r\n \r\n \r\n \r\n \r\n {t(\"folder.delete\")}\r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n\r\n \r\n );\r\n});\r\n","import { useTheme, Grid, Typography, DialogContent, Checkbox } from \"@mui/material\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport React, { useState, useMemo, useEffect } from \"react\";\r\nimport toast from \"react-hot-toast\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { SimpleDialog, DropdownWithLabel, InputWithLabel, DraggableDialog, EnhancedTable, EnhancedTableCheckboxHead } from \"../components\";\r\nimport { Asset, updateWebMapLayer, WebMapData, WebMapLayerData } from \"../redux/assets-slice\";\r\nimport { ServerType } from \"../types/web-sources\";\r\nimport { useAssetTools } from \"../utilities\";\r\nimport {Parser as XMLParser} from 'xml2js';\r\nimport WMTSCapabilities from 'ol/format/WMTSCapabilities.js';\r\nimport WMSCapabilities from 'ol/format/WMSCapabilities.js';\r\nimport { useTableState } from \"../hooks/use-table-state\";\r\nimport { useDispatch } from \"react-redux\";\r\n\r\ninterface WebSourceDialogProps {\r\n open: boolean;\r\n onClose(): void;\r\n folderID: string;\r\n}\r\n\r\nexport const WebSourceDialog = (props: WebSourceDialogProps) => {\r\n const {open, onClose, folderID} = props;\r\n\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n const {addWebSource} = useAssetTools();\r\n\r\n const [serverURL, setServerURL] = useState(\"\");\r\n const [serverName, setServerName] = useState(\"\");\r\n const [serverType, setServerType] = useState(ServerType.ArcGISMapServer);\r\n const [submitting, setSubmitting] = useState(false);\r\n\r\n const onSubmit = async () => {\r\n setSubmitting(true);\r\n\r\n try {\r\n const webmapData = {\r\n url: serverURL,\r\n type: serverType,\r\n public: true,\r\n layers: await getMapLayers(serverURL, serverType)\r\n };\r\n\r\n await addWebSource(serverName, webmapData, folderID);\r\n\r\n setSubmitting(false);\r\n onClose();\r\n } catch {\r\n toast.error(\"Error grabbing layers from URL\");\r\n setSubmitting(false);\r\n }\r\n };\r\n\r\n const getMapServerLayers = async (baseURL: string) => {\r\n const url = new URL(baseURL);\r\n url.searchParams.set('f', \"json\");\r\n url.searchParams.set('pretty', \"true\");\r\n\r\n const response = await fetch(url.href);\r\n const data = await response.json();\r\n const layers = data.layers as any[];\r\n\r\n return layers.map(layer => {\r\n return {\r\n id: nanoid(),\r\n visible: true,\r\n identifier: layer.id,\r\n name: layer.name,\r\n };\r\n });\r\n };\r\n\r\n const getFeatureServerLayers = async (baseURL: string) => {\r\n const url = new URL(baseURL);\r\n url.searchParams.set('f', \"json\");\r\n url.searchParams.set('pretty', \"true\");\r\n\r\n const response = await fetch(url.href);\r\n const data = await response.json();\r\n const layers = data.layers as any[];\r\n\r\n return layers.map(layer => {\r\n return {\r\n id: nanoid(),\r\n visible: true,\r\n identifier: layer.id,\r\n name: layer.name,\r\n };\r\n });\r\n };\r\n\r\n const getImageServerLayers = async (baseURL: string) => {\r\n const url = new URL(baseURL);\r\n url.searchParams.set('f', \"json\");\r\n url.searchParams.set('pretty', \"true\");\r\n\r\n const response = await fetch(url.href);\r\n if (!response.ok) {\r\n throw new Error(\"Error verifying image server URL\");\r\n }\r\n\r\n // No layers for this server type\r\n return [];\r\n };\r\n\r\n const getWMSLayers = async (baseURL: string) => {\r\n const url = new URL(baseURL);\r\n url.searchParams.set('SERVICE', \"WMS\");\r\n url.searchParams.set('REQUEST', \"GetCapabilities\");\r\n\r\n const response = await fetch(url.href);\r\n const text = await response.text();\r\n\r\n const parser = new WMSCapabilities();\r\n const capabilities = parser.read(text);\r\n const layers = capabilities.Capability.Layer.Layer as any[];\r\n\r\n return layers.map(layer => {\r\n return {\r\n id: nanoid(),\r\n visible: true,\r\n identifier: layer.Name,\r\n name: layer.Title\r\n };\r\n });\r\n };\r\n\r\n const getWFSLayers = async (baseURL: string) => {\r\n const url = new URL(baseURL);\r\n url.searchParams.set('SERVICE', \"WFS\");\r\n url.searchParams.set('REQUEST', \"GetCapabilities\");\r\n\r\n const response = await fetch(url.href);\r\n const text = await response.text();\r\n\r\n const parser = new XMLParser({\r\n explicitChildren:true,\r\n preserveChildrenOrder: true\r\n });\r\n\r\n const xmlJSON = await parser.parseStringPromise(text);\r\n const capabilities = xmlJSON['wfs:WFS_Capabilities'];\r\n const featureTypeList = capabilities.FeatureTypeList[0];\r\n const features = featureTypeList.FeatureType as any[];\r\n\r\n return features.map(layer => {\r\n return {\r\n id: nanoid(),\r\n visible: true,\r\n identifier: layer.Name[0],\r\n name: layer.Title[0]\r\n };\r\n });\r\n };\r\n\r\n const getWMTSLayers = async (baseURL: string) => {\r\n const url = new URL(baseURL);\r\n url.pathname = `${url.pathname}/1.0.0/WMTSCapabilities.xml`;\r\n\r\n const response = await fetch(url.href);\r\n const text = await response.text();\r\n\r\n const parser = new WMTSCapabilities();\r\n const capabilities = parser.read(text);\r\n const layers = capabilities.Contents.Layer as any[];\r\n\r\n return layers.map(layer => {\r\n return {\r\n id: nanoid(),\r\n visible: true,\r\n identifier: layer.Identifier,\r\n name: layer.Title\r\n };\r\n });\r\n };\r\n\r\n const getTileServerLayers = async (baseURL: string) => {\r\n // No layers for this server type\r\n return [];\r\n };\r\n\r\n const getMapLayers = (url, type) : Promise => {\r\n switch (type) {\r\n case ServerType.ArcGISMapServer:\r\n return getMapServerLayers(url);\r\n case ServerType.ArcGISImageServer:\r\n return getImageServerLayers(url);\r\n case ServerType.ArcGISFeatureServer:\r\n return getFeatureServerLayers(url);\r\n case ServerType.OGCWMS:\r\n return getWMSLayers(url);\r\n case ServerType.OGCWFS:\r\n return getWFSLayers(url);\r\n case ServerType.OGCWMTS:\r\n return getWMTSLayers(url);\r\n case ServerType.TileServer:\r\n return getTileServerLayers(url);\r\n default:\r\n throw new Error(\"Error grabbing map layers\");\r\n }\r\n };\r\n\r\n const resetDefaults = () => {\r\n setServerURL(\"\");\r\n setServerName(\"\");\r\n setSubmitting(false);\r\n setServerType(ServerType.ArcGISMapServer);\r\n };\r\n\r\n const isSecureURL = useMemo(() => {\r\n try {\r\n const url = new URL(serverURL);\r\n return url.protocol === \"https:\";\r\n } catch {\r\n return false;\r\n }\r\n }, [serverURL]);\r\n\r\n /** Check url to make sure it matches the required syntax */\r\n const isValidURL = useMemo(() => {\r\n const isArcGISServer = (serverType === ServerType.ArcGISMapServer)\r\n || (serverType === ServerType.ArcGISImageServer)\r\n || (serverType === ServerType.ArcGISFeatureServer);\r\n\r\n if (isArcGISServer) {\r\n try {\r\n const testURL = new URL(serverURL);\r\n const mapType = testURL.pathname\r\n .split(\"/\")\r\n .pop()\r\n .toLowerCase();\r\n\r\n if (serverType === ServerType.ArcGISMapServer) {\r\n return mapType === \"mapserver\";\r\n } else if (serverType === ServerType.ArcGISImageServer) {\r\n return mapType === \"imageserver\";\r\n } else if (serverType === ServerType.ArcGISFeatureServer) {\r\n return mapType === \"featureserver\";\r\n }\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n if (serverType === ServerType.TileServer) {\r\n const hasX = serverURL.includes(\"{x}\")\r\n || serverURL.includes(\"{col}\");\r\n\r\n const hasY = serverURL.includes(\"{y}\")\r\n || serverURL.includes(\"{-y}\")\r\n || serverURL.includes(\"{row}\");\r\n\r\n const hasZ = serverURL.includes(\"{z}\")\r\n || serverURL.includes(\"{level}\")\r\n || serverURL.includes(\"{zoom}\");\r\n\r\n return hasX && hasY && hasZ;\r\n }\r\n\r\n return true;\r\n }, [serverURL, serverType]);\r\n\r\n const placeholder = useMemo(() => {\r\n switch (serverType) {\r\n case ServerType.ArcGISMapServer:\r\n return \"https://server.arcgisonline.com/..../MapServer\";\r\n case ServerType.ArcGISFeatureServer:\r\n return \"https://server.arcgisonline.com/..../FeatureServer/\";\r\n case ServerType.ArcGISImageServer:\r\n return \"https://server.arcgisonline.com/..../ImageServer/\";\r\n case ServerType.ArcGISOnline:\r\n return \"https://arcgis.com/home/webmap/viewer.html?webmap=MAPID\";\r\n case ServerType.OGCWMS:\r\n return \"https://example.server.com/wms\";\r\n case ServerType.OGCWMTS:\r\n return \"https://example.server.com/wmts\";\r\n case ServerType.OGCWFS:\r\n return \"https://example.server.com/wfs\";\r\n case ServerType.TileServer:\r\n return \"https://custom.server.com/tiles/{z}/{x}/{y}.png\";\r\n default:\r\n return;\r\n }\r\n }, [serverType]);\r\n\r\n const label = useMemo(() => {\r\n const warnings = [];\r\n\r\n if (!isSecureURL) {\r\n warnings.push(t('websources.only_secure_urls_https_are_supported'));\r\n }\r\n\r\n if (!isValidURL) {\r\n warnings.push(t('websources.invalid_url_for_this_server_type'));\r\n }\r\n\r\n return warnings.join(\" \");\r\n }, [isSecureURL, isValidURL]);\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const showEsriWarning = (serverType === ServerType.ArcGISFeatureServer)\r\n || (serverType === ServerType.ArcGISImageServer)\r\n || (serverType === ServerType.ArcGISMapServer)\r\n || (serverType === ServerType.ArcGISOnline);\r\n\r\n const error = !isSecureURL\r\n || !isValidURL;\r\n\r\n const canSubmit = isSecureURL\r\n && isValidURL\r\n && !!serverName\r\n && !submitting;\r\n\r\n return (\r\n \r\n \r\n {/** Icon Size */}\r\n \r\n \r\n \r\n\r\n {/** Name */}\r\n \r\n \r\n \r\n\r\n {/** URL */}\r\n \r\n \r\n \r\n\r\n {showEsriWarning && (\r\n {t('websources.all_arcgis_maps_must_be_public')}\r\n )}\r\n\r\n \r\n \r\n );\r\n};\r\n\r\ninterface WebSourceLayerCheckboxProps {\r\n layerID: string;\r\n visible: boolean;\r\n}\r\n\r\nconst WebSourceLayerCheckbox = (props: WebSourceLayerCheckboxProps) => {\r\n const {layerID, visible} = props;\r\n\r\n const dispatch = useDispatch();\r\n\r\n const onVisibilityChange = (visible: boolean) => {\r\n dispatch(updateWebMapLayer({\r\n layerID,\r\n visible\r\n }));\r\n };\r\n\r\n return (\r\n {\r\n const checked = event.target.checked;\r\n onVisibilityChange(checked);\r\n }}\r\n />\r\n );\r\n};\r\n\r\ninterface WebSourceLayerDialogProps {\r\n open: boolean;\r\n onClose(): void;\r\n asset: Asset;\r\n}\r\n\r\nexport const WebSourceLayerDialog = (props: WebSourceLayerDialogProps) => {\r\n const {open, onClose, asset} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n\r\n const tableState = useTableState({defaultSort: \"name\"});\r\n\r\n const layers = useMemo(() => {\r\n return (asset.data as WebMapData).layers;\r\n }, [asset.data]);\r\n\r\n const getRows = (layers: WebMapLayerData[]) => {\r\n return layers.map(layer => {\r\n return {\r\n id: `WebSourceLayerTableRow_${layer.id}`,\r\n name: layer.name,\r\n visible_sortable: layer.visible ? 1 : 0,\r\n visible_checkbox: \r\n };\r\n });\r\n };\r\n\r\n const rows = useMemo(() => {\r\n return getRows(layers);\r\n }, [layers]);\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t('websources.layer_name'),\r\n wordBreak: true,\r\n searchable: true\r\n },\r\n {\r\n id: 'visible_checkbox',\r\n label: x.visible)}\r\n onChange={(checked) => {\r\n layers.forEach(layer => {\r\n dispatch(updateWebMapLayer({\r\n layerID: layer.id,\r\n visible: checked\r\n }));\r\n });\r\n }}\r\n />,\r\n sortBy: \"visible_sortable\",\r\n center: true\r\n }\r\n ];\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {t('asset.file-name')}: {asset.name}\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","import React, {useState, memo, useCallback} from 'react';\r\nimport List from '@mui/material/List';\r\nimport ListItemText from '@mui/material/ListItemText';\r\nimport {ListItemButton, MenuItem, Typography} from \"@mui/material\";\r\nimport AddIcon from '@mui/icons-material/Add';\r\nimport CreateNewFolderIcon from '@mui/icons-material/CreateNewFolder';\r\nimport PanoramaIcon from '@mui/icons-material/Panorama';\r\nimport PermMediaIcon from '@mui/icons-material/PermMedia';\r\nimport PublicIcon from '@mui/icons-material/Public';\r\nimport {\r\n openDialogFile,\r\n openDialogFolder,\r\n openDialogMulti,\r\n useAssetTools\r\n} from '../utilities';\r\nimport {\r\n modelFileFilter,\r\n imageCSVFilter,\r\n imageOrthoFilter,\r\n imagePlanarFilter,\r\n pointCloudFilter,\r\n tagCSVFilter,\r\n xmlFileFilter\r\n} from '../file-extensions';\r\nimport {AssetFolder, FolderDialog} from \".\";\r\nimport {createFolder, selectDefaultFolder, selectAllFolders} from '../redux/folders-slice';\r\nimport {selectAllAssets} from '../redux/assets-slice';\r\nimport {useSelector} from 'react-redux';\r\nimport {\r\n DenseIcon,\r\n DenseDivider,\r\n SlimScrollbar,\r\n FontAwesomeIcon,\r\n DenseMenu\r\n} from '../components';\r\nimport path from 'path';\r\nimport { isElectronApp } from '../electron-modules';\r\nimport {toast} from '../app';\r\nimport { useTranslation } from 'react-i18next';\r\nimport CloudIcon from \"@mui/icons-material/Cloud\";\r\nimport RoomIcon from \"@mui/icons-material/Room\";\r\nimport PanoramaOutlinedIcon from \"@mui/icons-material/PanoramaOutlined\";\r\nimport SatelliteIcon from \"@mui/icons-material/Satellite\";\r\nimport { useContextMenu, useDialog } from '../hooks';\r\nimport { WebSourceDialog } from './web-sources';\r\nimport { useAppDispatch } from '../redux/store';\r\n\r\n\r\ninterface AddAssetListProps {\r\n folderID: string;\r\n closeContextMenu(): void;\r\n}\r\n\r\nexport const AddAssetList = (props: AddAssetListProps) => {\r\n const {folderID, closeContextMenu} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n const webmapDialog = useDialog();\r\n\r\n const {\r\n addModelFiles, addPointCloudFiles, addOrthoFiles,\r\n addPanoramicFiles, addPlanarFiles, addXMLFiles,\r\n addTagCSVs\r\n } = useAssetTools();\r\n\r\n const handleAddModels = async () => {\r\n closeContextMenu();\r\n\r\n const assetPaths = await openDialogMulti(modelFileFilter);\r\n if (assetPaths.length === 0) return;\r\n\r\n addModelFiles(assetPaths, folderID);\r\n };\r\n\r\n const handleAddPoints = async () => {\r\n closeContextMenu();\r\n\r\n const assetPaths = await openDialogMulti(pointCloudFilter);\r\n if (assetPaths.length === 0) return;\r\n\r\n await addPointCloudFiles(assetPaths, folderID);\r\n };\r\n\r\n const handleAddOrtho = async () => {\r\n closeContextMenu();\r\n\r\n const assetPaths = await openDialogMulti(imageOrthoFilter);\r\n if (assetPaths.length === 0) return;\r\n\r\n addOrthoFiles(assetPaths, folderID);\r\n };\r\n\r\n const handleAddPanoramics = async () => {\r\n closeContextMenu();\r\n\r\n const assetPaths = await openDialogMulti(imageCSVFilter);\r\n if (assetPaths.length === 0) return;\r\n\r\n addPanoramicFiles(assetPaths, folderID);\r\n };\r\n\r\n const handleAddTags = async () => {\r\n closeContextMenu();\r\n\r\n const assetPaths = await openDialogMulti(tagCSVFilter);\r\n if (assetPaths.length === 0) return;\r\n\r\n addTagCSVs(assetPaths, folderID);\r\n };\r\n\r\n const handleAddPlanars = async () => {\r\n closeContextMenu();\r\n\r\n const assetPath = await openDialogFile(imagePlanarFilter);\r\n if (!assetPath) return;\r\n\r\n addPlanarFiles([assetPath], folderID);\r\n };\r\n\r\n const handleAddXML = async () => {\r\n closeContextMenu();\r\n\r\n const assetPath = await openDialogFile(xmlFileFilter);\r\n if (!assetPath) return;\r\n\r\n try {\r\n await addXMLFiles([assetPath], folderID);\r\n toast.success(t(\"toast.added-new-xml\"));\r\n } catch {\r\n const fileName = path.basename(assetPath);\r\n toast.error(t(\"toast.import-xml-error\", {\r\n path: fileName\r\n }));\r\n }\r\n };\r\n\r\n const handleAddWebMap = useCallback(() => {\r\n closeContextMenu();\r\n webmapDialog.handleOpen();\r\n }, []);\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-point-cloud\")}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-panoramic-csv\")}\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-tag-csv\")}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-planar-images\")}\r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-orthomosaic\")}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-model-file\")}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t('folder-list.add-landxml-file')}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t('folder-list.add-web-source')}\r\n \r\n\r\n \r\n \r\n );\r\n};\r\n\r\nexport const FolderList = memo(() => {\r\n const dispatch = useAppDispatch();\r\n const {t} = useTranslation();\r\n const contextMenu = useContextMenu();\r\n const newFolderDialog = useDialog();\r\n const {addFilePaths} = useAssetTools();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const defaultFolder = useSelector(selectDefaultFolder);\r\n const folders = useSelector(selectAllFolders);\r\n\r\n const [draggingAsset, setDraggingAsset] = useState(null);\r\n\r\n const handleAddFolder = async () => {\r\n contextMenu.handleClose();\r\n\r\n const {directoryPath, filePaths} = await openDialogFolder();\r\n if (filePaths.length === 0) return;\r\n\r\n const name = path.basename(directoryPath);\r\n const folder = await dispatch(createFolder(name));\r\n addFilePaths(filePaths, folder.id);\r\n };\r\n\r\n const handleNewFolder = () => {\r\n contextMenu.handleClose();\r\n newFolderDialog.handleOpen();\r\n };\r\n\r\n return (\r\n \r\n {/* Add item button */}\r\n {isElectronApp && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n )}\r\n\r\n \r\n \r\n {folders.map(folder =>\r\n x.folderID === folder.id)}\r\n draggingAsset={draggingAsset}\r\n setDraggingAsset={setDraggingAsset}\r\n />)}\r\n \r\n \r\n\r\n {/** New Folder */}\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n {t(\"folder-list.create-new-folder\")}\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"folder-list.add-folder-contents\")}\r\n \r\n \r\n \r\n );\r\n});\r\n","import { Checkbox, DialogContent, Typography } from \"@mui/material\";\r\nimport React, { useMemo } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useDispatch } from \"react-redux\";\r\nimport { ColorPicker, DraggableDialog, EnhancedTable, EnhancedTableCheckboxHead } from \"../components\";\r\nimport { useTableState } from \"../hooks/use-table-state\";\r\nimport { Asset, LineworkLayerData, updateModelLayer } from \"../redux/assets-slice\";\r\n\r\ninterface ModelLayerCheckboxProps {\r\n layerID: string;\r\n visible: boolean;\r\n}\r\n\r\nconst ModelLayerCheckbox = (props: ModelLayerCheckboxProps) => {\r\n const {layerID, visible} = props;\r\n\r\n const dispatch = useDispatch();\r\n\r\n const onVisibilityChange = (visible: boolean) => {\r\n dispatch(updateModelLayer({\r\n layerID,\r\n visible\r\n }));\r\n };\r\n\r\n return (\r\n {\r\n const checked = event.target.checked;\r\n onVisibilityChange(checked);\r\n }}\r\n />\r\n );\r\n};\r\n\r\ninterface ModelLayerColorProps {\r\n layerID: string;\r\n color: string;\r\n}\r\n\r\nconst ModelLayerColor = (props: ModelLayerColorProps) => {\r\n const {layerID, color} = props;\r\n\r\n const dispatch = useDispatch();\r\n\r\n const onColorChange = (color: string) => {\r\n dispatch(updateModelLayer({\r\n layerID,\r\n color\r\n }));\r\n };\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface ModelLayerDialogProps {\r\n open: boolean;\r\n onClose(): void;\r\n asset: Asset;\r\n}\r\n\r\nexport const ModelLayerDialog = (props: ModelLayerDialogProps) => {\r\n const {open, onClose, asset} = props;\r\n\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const tableState = useTableState({defaultSort: \"name\"});\r\n\r\n const layers = useMemo(() => {\r\n return asset.data as LineworkLayerData[];\r\n }, [asset.data]);\r\n\r\n const getRows = (layers: LineworkLayerData[]) => {\r\n return layers.map(layer => {\r\n return {\r\n id: `WebSourceLayerTableRow_${layer.id}`,\r\n name: layer.name,\r\n visible_sortable: layer.visible ? 1 : 0,\r\n visible_checkbox: ,\r\n color_picker: \r\n };\r\n });\r\n };\r\n\r\n const rows = useMemo(() => {\r\n return getRows(layers);\r\n }, [layers]);\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t('models.layer_name'),\r\n wordBreak: true,\r\n searchable: true\r\n },\r\n {\r\n id: 'color_picker',\r\n label: t('models.layer_color'),\r\n center: true,\r\n sortable: false\r\n },\r\n {\r\n id: 'visible_checkbox',\r\n label: x.visible)}\r\n onChange={(checked) => {\r\n layers.forEach(layer => {\r\n dispatch(updateModelLayer({\r\n layerID: layer.id,\r\n visible: checked\r\n }));\r\n });\r\n }}\r\n />,\r\n sortBy: \"visible_sortable\",\r\n center: true\r\n }\r\n ];\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {t('asset.file-name')}: {asset.name}\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n );\r\n};\r\n","import React, { useMemo, useState } from \"react\";\r\nimport { Theme } from '@mui/material/styles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n Checkbox,\r\n List,\r\n ListItemButton,\r\n ListItemText,\r\n MenuItem,\r\n Typography,\r\n} from \"@mui/material\";\r\nimport {\r\n DenseDivider,\r\n DenseIcon,\r\n DenseMenu,\r\n PromptDialog,\r\n SlimScrollbar,\r\n TextDialog\r\n} from \"../components\";\r\nimport AddIcon from '@mui/icons-material/Add';\r\nimport { useDispatch, useSelector } from 'react-redux';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { BookmarkItem } from \".\";\r\nimport BookmarksIcon from '@mui/icons-material/Bookmarks';\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport ExpandLess from \"@mui/icons-material/ExpandLess\";\r\nimport ExpandMore from \"@mui/icons-material/ExpandMore\";\r\nimport {\r\n createBookmark,\r\n updateBookmark,\r\n deleteBookmark\r\n} from \"../redux/bookmarks-slice\";\r\nimport { store } from \"../redux/store\";\r\nimport { toast } from \"../app\";\r\nimport LocalScene from \"../viewer/projections\";\r\nimport { useAuth, useBookmarks, useContextMenu, useDialog, useViewer } from \"../hooks\";\r\nimport { AerialViewState, SceneCameraState } from \"../redux/camera-slice\";\r\nimport { SettingsState } from \"../redux/settings-slice\";\r\nimport { getVisibleAssets, selectAllAssets } from \"../redux/assets-slice\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n addItem: {\r\n paddingTop: \"0px\",\r\n paddingBottom: \"0px\"\r\n },\r\n footerDiv: {\r\n width: \"100%\",\r\n boxShadow: \"0px 10px 10px 2px\",\r\n zIndex: 1,\r\n textAlign: \"center\"\r\n },\r\n footerCheckbox: {\r\n padding: theme.spacing(0.5),\r\n marginRight: theme.spacing(0.5)\r\n }\r\n })\r\n);\r\n\r\nexport const getStoredState = () => {\r\n const state = store.getState();\r\n\r\n const settings = {...state.settings} as SettingsState;\r\n const aerialState = state.camera.aerialState as AerialViewState;\r\n const sceneState = state.camera.sceneState as SceneCameraState;\r\n\r\n return {settings, aerialState, sceneState};\r\n};\r\n\r\nexport const BookmarkList = () => {\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {permissions} = useAuth();\r\n const {t} = useTranslation();\r\n const contextMenu = useContextMenu();\r\n const bookmarkDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const {bookmarks} = useBookmarks();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n\r\n const visibleAssets = useMemo(() => {\r\n return getVisibleAssets(assets);\r\n }, [assets]);\r\n\r\n const [expanded, setExpanded] = useState(true);\r\n\r\n const handleSubmit = (name: string) => {\r\n bookmarkDialog.handleClose();\r\n\r\n if (!LocalScene.initialized) {\r\n toast.warning(t('bookmarks.invalid_position'));\r\n return;\r\n }\r\n\r\n const position = viewer.getCameraPosition().toArray();\r\n const {settings, aerialState, sceneState} = getStoredState();\r\n const visibleAssetIDs = visibleAssets.map(asset => asset.id);\r\n\r\n dispatch(createBookmark({\r\n name,\r\n position,\r\n settings,\r\n visibleAssets: visibleAssetIDs,\r\n aerialState,\r\n sceneState\r\n }));\r\n };\r\n\r\n const handleClick = (event) => {\r\n const isCheckBox = (event.target.type === \"checkbox\");\r\n if (isCheckBox) return;\r\n\r\n setExpanded(!expanded);\r\n };\r\n\r\n const toggleCheckboxes = () => {\r\n let newVisibility;\r\n if (numVisible > 0 && numHidden > 0) {\r\n newVisibility = true;\r\n } else if (numVisible > 0) {\r\n newVisibility = false;\r\n } else {\r\n newVisibility = true;\r\n }\r\n\r\n for (let bookmark of bookmarks) {\r\n dispatch(updateBookmark({\r\n bookmarkID: bookmark.id,\r\n visible: newVisibility\r\n }));\r\n }\r\n };\r\n\r\n const handleDeleteSubmit = () => {\r\n for (let bookmark of bookmarks) {\r\n dispatch(deleteBookmark(bookmark.id));\r\n }\r\n deleteDialog.handleClose();\r\n };\r\n\r\n const handleDeleteClick = () => {\r\n deleteDialog.handleOpen();\r\n contextMenu.handleClose();\r\n };\r\n\r\n const numVisible = bookmarks.filter(x => x.visible).length;\r\n const numHidden = bookmarks.filter(x => !x.visible).length;\r\n\r\n return (\r\n \r\n\r\n {/* Add item button */}\r\n {permissions.create && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n )}\r\n\r\n {/* Bookmarks list */}\r\n \r\n {(bookmarks.length > 0) && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n {(bookmarks.length > 0) && (\r\n {/* Show / hide contents */}\r\n {expanded ? : }\r\n\r\n {/* Toggle all folder assets */}\r\n 0}\r\n onChange={toggleCheckboxes}\r\n indeterminate={numVisible > 0 && numHidden > 0}\r\n />\r\n )}\r\n\r\n \r\n\r\n {expanded && (\r\n \r\n {bookmarks.map(bookmark =>\r\n \r\n )}\r\n \r\n )}\r\n\r\n \r\n )}\r\n \r\n\r\n \r\n \r\n \r\n \r\n \r\n {t('buttons.delete')}\r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n );\r\n};\r\n","import React, { useMemo } from \"react\";\r\nimport { Theme, useTheme } from '@mui/material/styles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {useDispatch, useSelector} from 'react-redux';\r\nimport {\r\n Checkbox,\r\n ListItemButton,\r\n ListItemSecondaryAction,\r\n ListItemText,\r\n MenuItem,\r\n Typography\r\n} from \"@mui/material\";\r\nimport {\r\n DenseIcon,\r\n DenseMenu,\r\n PromptDialog,\r\n TextDialog\r\n} from \"../components\";\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport EditIcon from \"@mui/icons-material/Edit\";\r\nimport BookmarkIcon from '@mui/icons-material/Bookmark';\r\nimport SyncIcon from '@mui/icons-material/Sync';\r\nimport LinkIcon from '@mui/icons-material/Link';\r\nimport {\r\n deleteBookmark,\r\n updateBookmark,\r\n Bookmark\r\n} from \"../redux/bookmarks-slice\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { toast } from \"../app\";\r\nimport { getStoredState } from \".\";\r\nimport LocalScene from \"../viewer/projections\";\r\nimport { useAuth, useBookmarks, useContextMenu, useDialog, useViewer } from \"../hooks\";\r\nimport copyTextToClipboard from \"copy-to-clipboard\";\r\nimport { isStaticSite } from \"../electron-modules\";\r\nimport { getVisibleAssets, selectAllAssets } from \"../redux/assets-slice\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n assetInfo: {\r\n display: 'flex',\r\n margin: '0px'\r\n },\r\n itemText: {\r\n wordBreak: \"break-word\",\r\n overflow: \"hidden\"\r\n },\r\n checkboxParent: {\r\n padding: \"0px\",\r\n height: \"100%\"\r\n },\r\n assetCheckbox: {\r\n position: \"relative\",\r\n transform: \"translateY(0%)\",\r\n }\r\n })\r\n);\r\n\r\ninterface BookmarkItemProps {\r\n bookmark: Bookmark;\r\n}\r\n\r\nexport const BookmarkItem = (props: BookmarkItemProps) => {\r\n const {bookmark} = props;\r\n\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {permissions} = useAuth();\r\n const {t} = useTranslation();\r\n const contextMenu = useContextMenu();\r\n const renameDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const updateDialog = useDialog();\r\n const {loadBookmark} = useBookmarks();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n\r\n const visibleAssets = useMemo(() => {\r\n return getVisibleAssets(assets);\r\n }, [assets]);\r\n\r\n const handleBookmarkClick = (event) => {\r\n const isCheckBox = (event.target.type === \"checkbox\");\r\n if (isCheckBox) return;\r\n\r\n loadBookmark(bookmark.id);\r\n };\r\n\r\n const handleVisibilityClick = () => {\r\n dispatch(updateBookmark({\r\n bookmarkID: bookmark.id,\r\n visible: !bookmark.visible\r\n }));\r\n };\r\n\r\n const handleDeleteSubmit = () => {\r\n dispatch(deleteBookmark(bookmark.id));\r\n deleteDialog.handleClose();\r\n };\r\n\r\n const handleDeleteClick = () => {\r\n contextMenu.handleClose();\r\n deleteDialog.handleOpen();\r\n };\r\n\r\n const handleRenameSubmit = name => {\r\n dispatch(updateBookmark({\r\n bookmarkID: bookmark.id,\r\n name\r\n }));\r\n\r\n renameDialog.handleClose();\r\n };\r\n\r\n const handleRenameClick = () => {\r\n contextMenu.handleClose();\r\n renameDialog.handleOpen();\r\n };\r\n\r\n const handleUpdateSubmit = () => {\r\n updateDialog.handleClose();\r\n\r\n if (!LocalScene.initialized) {\r\n toast.warning(t('bookmarks.invalid_position'));\r\n return;\r\n }\r\n\r\n const position = viewer.getCameraPosition().toArray();\r\n const {settings, aerialState, sceneState} = getStoredState();\r\n const visibleAssetIDs = visibleAssets.map(asset => asset.id);\r\n\r\n dispatch(updateBookmark({\r\n bookmarkID: bookmark.id,\r\n position,\r\n settings,\r\n visibleAssets: visibleAssetIDs,\r\n aerialState,\r\n sceneState\r\n }));\r\n\r\n toast.success(t('bookmarks.updated_bookmark'));\r\n };\r\n\r\n const handleUpdateClick = () => {\r\n contextMenu.handleClose();\r\n updateDialog.handleOpen();\r\n };\r\n\r\n const handleCopyClick = () => {\r\n contextMenu.handleClose();\r\n\r\n // Copy url to clipboard\r\n const url = new URL(window.location as any);\r\n url.hash = `bookmark=${bookmark.id}`;\r\n copyTextToClipboard(url.href);\r\n toast.success(t(\"toast.copied-to-clipboard\"));\r\n };\r\n\r\n return (\r\n \r\n \r\n
\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n\r\n
\r\n \r\n\r\n \r\n {isStaticSite && \r\n \r\n \r\n \r\n {t('bookmarks.copy_bookmark_url')}\r\n }\r\n\r\n \r\n \r\n \r\n \r\n {t('buttons.rename')}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t('buttons.update')}\r\n \r\n\r\n \r\n \r\n \r\n \r\n {t('buttons.delete')}\r\n \r\n\r\n \r\n\r\n {/* Rename Dialog */}\r\n \r\n\r\n {/* Update Dialog */}\r\n \r\n\r\n {/* Delete Dialog */}\r\n \r\n
\r\n );\r\n};","import IconButton from \"@mui/material/IconButton\";\r\nimport ChevronLeftIcon from \"@mui/icons-material/ChevronLeft\";\r\nimport ChevronRightIcon from \"@mui/icons-material/ChevronRight\";\r\nimport {FolderList} from \"./folder\";\r\nimport Drawer from \"@mui/material/Drawer\";\r\nimport React, {useEffect, useState, memo} from \"react\";\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { AppBar, Box, Tab } from \"@mui/material\";\r\nimport {\r\n TabPanel,\r\n TabProps,\r\n} from \"./components\";\r\nimport {\r\n changeAssetDrawerState,\r\n changeSelectedTab,\r\n selectAssetDrawerState,\r\n selectSelectedTab,\r\n} from \"./redux/settings-slice\";\r\nimport Tabs from \"@mui/material/Tabs/Tabs\";\r\nimport { useTranslation } from 'react-i18next';\r\nimport { BookmarkList } from \"./bookmarks\";\r\nimport { useDispatch, useSelector } from 'react-redux';\r\nimport { Bookmark } from \"./redux/bookmarks-slice\";\r\nimport { useBookmarks, useViewer } from \"./hooks\";\r\nimport { useBranding } from \"./hooks/use-branding\";\r\n\r\nexport const assetDrawerWidth = 280;\r\nexport const assetDrawerHeight = 75;\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n backdrop: {\r\n display: \"none\"\r\n },\r\n inside: {\r\n height: `${assetDrawerHeight}%`,\r\n display: \"flex\",\r\n overflow: \"hidden\",\r\n flexDirection: \"column\"\r\n },\r\n drawer: {\r\n width: 0,\r\n },\r\n drawerPaper: {\r\n width: assetDrawerWidth,\r\n },\r\n root: {\r\n \"z-index\": `${theme.zIndex.modal - 1} !important`\r\n },\r\n tab: {\r\n minWidth: \"0px !important\",\r\n flexBasis: \"unset\",\r\n flexShrink: \"unset\"\r\n },\r\n tabGrow: {\r\n \"flex-grow\": 1\r\n },\r\n toggleDrawer: {\r\n color: \"white\"\r\n }\r\n }),\r\n);\r\n\r\ninterface StyledPanelProps {\r\n value: number;\r\n index: number;\r\n children: React.ReactNode;\r\n}\r\n\r\nconst StyledPanel = (props: StyledPanelProps) => {\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nconst CompanyLogo = () => {\r\n const theme = useTheme();\r\n const branding = useBranding();\r\n\r\n return (\r\n \r\n {branding.iconPath &&
\r\n \r\n
}\r\n
\r\n );\r\n};\r\n\r\nexport const AssetDrawer = memo(() => {\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const {bookmarks, loadBookmark} = useBookmarks();\r\n\r\n const assetDrawerState = useSelector(selectAssetDrawerState);\r\n const projectActiveTab = useSelector(selectSelectedTab);\r\n\r\n const [activeTab, setSelectedTab] = useState(0);\r\n\r\n const setActiveTab = (event, value) => {\r\n dispatch(changeSelectedTab(value));\r\n };\r\n\r\n const handleDrawerClose = () => {\r\n dispatch(changeAssetDrawerState(false));\r\n };\r\n\r\n useEffect(() => {\r\n setSelectedTab(projectActiveTab);\r\n }, [projectActiveTab]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n const labels = [];\r\n\r\n bookmarks.forEach((bookmark: Bookmark) => {\r\n if (!bookmark.visible) return;\r\n\r\n const onClick = () => {\r\n loadBookmark(bookmark.id);\r\n };\r\n\r\n const {name, position} = bookmark;\r\n const label = viewer.addSceneLabel(name, position, onClick);\r\n labels.push(label);\r\n });\r\n\r\n viewer.updateSceneLabels();\r\n\r\n return () => {\r\n labels.forEach(label => {\r\n viewer.removeSceneLabel(label);\r\n });\r\n\r\n viewer.updateSceneLabels();\r\n };\r\n }, [viewer, bookmarks, loadBookmark]);\r\n\r\n return (\r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {theme.direction === 'ltr' ? : }\r\n \r\n \r\n \r\n\r\n {/* Assets */}\r\n \r\n \r\n \r\n\r\n {/* Bookmarks */}\r\n \r\n \r\n \r\n\r\n \r\n
\r\n \r\n );\r\n});\r\n","import React, {memo, useEffect, useState} from 'react';\r\nimport { Theme, useTheme } from '@mui/material/styles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport AppBar from '@mui/material/AppBar';\r\nimport Toolbar from '@mui/material/Toolbar';\r\nimport Typography from '@mui/material/Typography';\r\nimport IconButton from '@mui/material/IconButton';\r\nimport MenuIcon from '@mui/icons-material/Menu';\r\nimport MeasureIcon from '@mui/icons-material/SquareFoot';\r\nimport LinkIcon from '@mui/icons-material/Link';\r\nimport SettingsIcon from '@mui/icons-material/Settings';\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport HomeIcon from '@mui/icons-material/Home';\r\nimport {\r\n updateProjectName,\r\n selectProjectName\r\n} from \"./redux/project-slice\";\r\nimport {useSelector, useDispatch} from 'react-redux';\r\nimport {\r\n Projection,\r\n updateDataProjection,\r\n updateViewProjection,\r\n selectDataProjection\r\n} from './redux/projections-slice';\r\nimport {\r\n userProjections,\r\n uniqueProjectionID,\r\n unknownProjectionFeet,\r\n unknownProjectionMeters\r\n} from './projections';\r\nimport {\r\n Button,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n FormControl,\r\n FormHelperText,\r\n InputAdornment,\r\n InputLabel,\r\n ListSubheader,\r\n MenuItem,\r\n TextField\r\n} from '@mui/material';\r\nimport {assetDrawerWidth} from './asset-drawer';\r\nimport LocalScene, {\r\n projectionToMeters,\r\n projectionToUnits,\r\n SceneCoordinate\r\n} from './viewer/projections';\r\nimport {isCloudSite, isElectronApp} from \"./electron-modules\";\r\nimport {\r\n changeBasicAdjustments,\r\n changeCameraHeight,\r\n changeCameraTransform,\r\n resetAerialState,\r\n resetCameraState,\r\n selectBasicAdjustments,\r\n selectCameraHeight,\r\n selectCameraTransform\r\n} from './redux/camera-slice';\r\nimport {\r\n asyncTimeout,\r\n getLocalizedProjectionName,\r\n getLocalizedProjectName,\r\n getMatrixValues,\r\n openDialogFile,\r\n saveMatrixFile\r\n} from \"./utilities\";\r\nimport {cameraMatrixFilter} from \"./file-extensions\";\r\nimport clsx from 'clsx';\r\nimport { ArrowTooltip, LanguageSwitch, AccountButton } from './components';\r\nimport {headerHeight, toast} from './app';\r\nimport { sendCustomEvent } from './events';\r\nimport { Vector3 } from 'three';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { getLocalizedURL } from './localization';\r\nimport { changeAssetDrawerState, changeSelectedTab, selectAssetDrawerState } from './redux/settings-slice';\r\nimport { UnitConverter } from './viewer/utilities';\r\nimport {isEqual} from 'lodash';\r\nimport {\r\n useDialog,\r\n useViewer,\r\n useActiveTool,\r\n useAuth,\r\n useBookmarks\r\n} from './hooks';\r\nimport manifest from \"../package.json\";\r\nimport { Units } from './types/project';\r\n\r\nconst converter = new UnitConverter();\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n disabled: {\r\n opacity: 0.3\r\n },\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n menuButton: {\r\n marginRight: theme.spacing(2),\r\n },\r\n title: {\r\n flexGrow: 1,\r\n },\r\n projectName: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n padding: theme.spacing(0, 1),\r\n // necessary for content to be below app bar\r\n ...theme.mixins.toolbar,\r\n justifyContent: 'flex-start',\r\n flexGrow: 1\r\n },\r\n projectionText: {\r\n paddingTop: theme.spacing(0),\r\n margin: theme.spacing(0),\r\n marginTop: \"-5px\",\r\n color: \"inherit\"\r\n },\r\n marginTop: {\r\n marginTop: theme.spacing(2),\r\n marginBottom: theme.spacing(1)\r\n },\r\n buttonDiv: {\r\n textAlign: \"right\"\r\n },\r\n coordinates: {\r\n width: \"100%\",\r\n display: \"flex\",\r\n justifyContent: \"flex-end\"\r\n },\r\n button: {\r\n marginTop: theme.spacing(2),\r\n marginLeft: theme.spacing(1)\r\n },\r\n slimButton: {\r\n marginTop: theme.spacing(1)\r\n },\r\n dropdown: {\r\n minWidth: 200,\r\n },\r\n offset: {\r\n marginLeft: assetDrawerWidth - 60\r\n },\r\n textField: {\r\n paddingBottom: theme.spacing(3)\r\n },\r\n matrixValuesParent: {\r\n display: \"flex\",\r\n paddingTop: theme.spacing(2),\r\n justifyContent: \"space-evenly\"\r\n },\r\n matrixValues: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n textAlign: \"center\"\r\n },\r\n matrixButtons: {\r\n display: \"flex\",\r\n justifyContent: \"center\"\r\n }\r\n }),\r\n);\r\n\r\nconst ProjectDetails = () => {\r\n const {viewer} = useViewer();\r\n\r\n const dispatch = useDispatch();\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n const projectDialog = useDialog();\r\n const warnDialog = useDialog();\r\n\r\n const [name, setName] = useState(\"\");\r\n const [height, setHeight] = useState(0);\r\n const [changed, setChanged] = useState(false);\r\n const [projectionID, setProjectionID] = useState(\"\");\r\n const [matchedProjection, setMatchedProjection] = useState(null);\r\n const [imported, setImported] = useState(null);\r\n const [projections, setProjections] = useState([]);\r\n const {deleteBookmarks} = useBookmarks();\r\n\r\n const [cameraTransform, setCameraTransform] = useState({\r\n path: null,\r\n rotation: null,\r\n offset: null\r\n });\r\n\r\n const projectName = useSelector(selectProjectName);\r\n const projectHeight = useSelector(selectCameraHeight);\r\n const cameraTransformPath = useSelector(selectCameraTransform);\r\n const dataProjection = useSelector(selectDataProjection);\r\n const basicAdjustments = useSelector(selectBasicAdjustments);\r\n const assetDrawerState = useSelector(selectAssetDrawerState);\r\n\r\n const unknownTextMeters = unknownProjectionMeters.name;\r\n const unknownTextFeet = unknownProjectionFeet.name;\r\n\r\n const getProjection = (key: string) => {\r\n let newProjection = null;\r\n\r\n if (key === unknownTextMeters) {\r\n newProjection = unknownProjectionMeters;\r\n } else if (key === unknownTextFeet) {\r\n newProjection = unknownProjectionFeet;\r\n } else if (imported && (key === imported.name)) {\r\n newProjection = imported;\r\n } else {\r\n const results = projections.filter(x => x.name === key);\r\n if (results.length !== 1) {\r\n return;\r\n }\r\n newProjection = results[0];\r\n }\r\n\r\n return newProjection;\r\n };\r\n\r\n const updateName = (event) => {\r\n const value = event.target.value;\r\n setName(value);\r\n };\r\n\r\n const updateHeight = (event) => {\r\n const value = event.target.value;\r\n\r\n setChanged(true);\r\n\r\n if (value) {\r\n setHeight(parseFloat(value));\r\n } else {\r\n setHeight(null);\r\n }\r\n };\r\n\r\n const updateProj = (event) => {\r\n const newProjectionID = event.target.value;\r\n if (!newProjectionID) return;\r\n\r\n if (height && !changed) {\r\n // Convert height to new units\r\n const oldProjection = getProjection(projectionID);\r\n const newProjection = getProjection(newProjectionID);\r\n\r\n const toMetersOld = projectionToMeters(oldProjection);\r\n const toMetersNew = projectionToMeters(newProjection);\r\n\r\n const conversion = toMetersOld / toMetersNew;\r\n const newHeight = height * conversion;\r\n\r\n setHeight(newHeight);\r\n }\r\n\r\n setProjectionID(newProjectionID);\r\n };\r\n\r\n const onSubmit = async () => {\r\n const trimmedName = name.trim();\r\n const heightInMeters = height * toMeters;\r\n\r\n projectDialog.handleClose();\r\n toast.success(t(\"toast.project-details-updated\"));\r\n\r\n await asyncTimeout(100);\r\n\r\n dispatch(updateProjectName(trimmedName));\r\n dispatch(changeCameraHeight(heightInMeters));\r\n dispatch(changeCameraTransform(cameraTransform.path));\r\n\r\n // Projection change requires a more strict check before dispatch\r\n const projectionName = selectedProjection.name;\r\n const projectionChanged = !LocalScene.isDataProjection(projectionName);\r\n\r\n if (!projectionChanged) return;\r\n\r\n dispatch(changeSelectedTab(0));\r\n\r\n // Clear all bookmarks. TODO: update values instead of clearing(?)\r\n deleteBookmarks();\r\n\r\n dispatch(resetCameraState(null));\r\n dispatch(resetAerialState(null));\r\n dispatch(updateDataProjection(selectedProjection));\r\n dispatch(updateViewProjection(selectedProjection));\r\n };\r\n\r\n const handleImported = () => {\r\n const name = dataProjection.name;\r\n\r\n // Special case for default projections\r\n if ((name === unknownTextFeet) || (name === unknownTextMeters)) {\r\n setImported(null);\r\n return;\r\n }\r\n\r\n // Check to see if this projection existed in the users defined projections\r\n const matchedProjection = userProjections.data\r\n .find(x => x.name === name);\r\n\r\n if (matchedProjection) {\r\n const importedProjection = JSON.parse(JSON.stringify(dataProjection));\r\n const userProjection = JSON.parse(JSON.stringify(matchedProjection));\r\n\r\n if (isEqual(importedProjection, userProjection)) {\r\n // Projections match, so we use the locally defined one\r\n setImported(null);\r\n } else {\r\n // Projections are different, so we warn\r\n // the user and use the imported one\r\n setImported({...dataProjection});\r\n warnDialog.handleOpen();\r\n }\r\n } else {\r\n // Projection is not found in the users defined\r\n // projections so we mark it as imported\r\n setImported({...dataProjection});\r\n }\r\n };\r\n\r\n const onCorrectionSelect = async () => {\r\n const filePath = await openDialogFile(cameraMatrixFilter);\r\n if (!filePath) return;\r\n\r\n const {success, rotation, offset} = await getMatrixValues(filePath);\r\n\r\n if (!success) {\r\n toast.error(t(\"toast.correction-matrix-error\"));\r\n return;\r\n }\r\n\r\n setCameraTransform({path: filePath, rotation, offset});\r\n };\r\n\r\n const onMatrixChange = async (filePath: string) => {\r\n const {success, rotation, offset} = await getMatrixValues(filePath);\r\n\r\n if (success) {\r\n setCameraTransform({path: filePath, rotation, offset});\r\n } else {\r\n onCorrectionRemove();\r\n }\r\n };\r\n\r\n const onCorrectionRemove = () => {\r\n setCameraTransform({\r\n path: null,\r\n rotation: null,\r\n offset: null\r\n });\r\n };\r\n\r\n const updateTitle = (title) => {\r\n document.title = `${manifest.productName}: ${title}`;\r\n };\r\n\r\n const clearBasicAlignment = () => {\r\n dispatch(changeBasicAdjustments({}));\r\n viewer?.resetBasicAlignerCamera();\r\n };\r\n\r\n const getTransformValues = () => {\r\n let rotation = [0,0,0];\r\n let offset = [0,0,0];\r\n\r\n if (cameraTransform.offset) {\r\n offset = [\r\n converter.convert(cameraTransform.offset.x, Units.Meters, units, 2),\r\n converter.convert(cameraTransform.offset.y, Units.Meters, units, 2),\r\n converter.convert(cameraTransform.offset.z, Units.Meters, units, 2)\r\n ];\r\n }\r\n\r\n if (cameraTransform.rotation) {\r\n rotation = [\r\n cameraTransform.rotation.x.toFixed(2),\r\n cameraTransform.rotation.y.toFixed(2),\r\n cameraTransform.rotation.z.toFixed(2)\r\n ];\r\n }\r\n\r\n return {rotation, offset};\r\n };\r\n\r\n const resetDefaults = () => {\r\n const height = projectHeight / projectionToMeters(dataProjection);\r\n setHeight(height);\r\n setChanged(false);\r\n\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n setName(localizedProjectName);\r\n\r\n setProjectionID(dataProjection.name);\r\n };\r\n\r\n useEffect(() => {\r\n onMatrixChange(cameraTransformPath);\r\n }, [cameraTransformPath]);\r\n\r\n useEffect(() => {\r\n if (!projectDialog.open) return;\r\n\r\n resetDefaults();\r\n handleImported();\r\n userProjections.load();\r\n\r\n // Get a sorted list of projections\r\n const sortedProjections = userProjections.data.sort((a, b) => {\r\n const name1 = a.name.toLowerCase();\r\n const name2 = b.name.toLowerCase();\r\n return (name1 < name2) ? -1 : ((name2 > name1) ? 1 : 0);\r\n });\r\n\r\n // Find the current projection\r\n const matchedProjection = sortedProjections.filter(\r\n x => x.name === dataProjection.name)[0];\r\n\r\n setProjections(sortedProjections);\r\n setMatchedProjection(matchedProjection);\r\n }, [projectDialog.open, dataProjection]);\r\n\r\n const selectedProjection = getProjection(projectionID);\r\n const units = projectionToUnits(selectedProjection);\r\n const toMeters = projectionToMeters(selectedProjection);\r\n const hasBasicAlignment = Object.keys(basicAdjustments).length !== 0;\r\n\r\n const localizedProjectionName = getLocalizedProjectionName(dataProjection, units);\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n\r\n const roundedHeight = (height !== null)\r\n ? parseFloat(height.toFixed(2))\r\n : \"\";\r\n\r\n const {rotation, offset} = getTransformValues();\r\n const hasUserProjections = projections.length > 0;\r\n updateTitle(localizedProjectName);\r\n\r\n const emptyName = name.trim() === \"\";\r\n const emptyHeight = height === null;\r\n const emptyProjection = projectionID === null;\r\n\r\n const hasErrors = emptyName\r\n || emptyHeight\r\n || emptyProjection;\r\n\r\n return (\r\n
\r\n \r\n\r\n {/** Project Name */}\r\n \r\n {localizedProjectName}\r\n \r\n\r\n {/** Projection */}\r\n \r\n {localizedProjectionName}\r\n \r\n\r\n \r\n\r\n {isElectronApp && (\r\n \r\n \r\n \r\n )}\r\n\r\n \r\n \r\n {t('project-settings.project-information')}\r\n \r\n \r\n\r\n {/* Project display title */}\r\n \r\n {t('project-settings.project-title')}\r\n \r\n\r\n \r\n {t('project-settings.project-title-description')}\r\n \r\n \r\n\r\n {/* Camera height */}\r\n \r\n {t('project-settings.camera-height')}\r\n \r\n \r\n {t('project-settings.camera-height-description')}\r\n \r\n {units},\r\n }}\r\n />\r\n\r\n {/* Projection dropdown */}\r\n \r\n {t('project-settings.data-projection')}\r\n \r\n \r\n {t('project-settings.data-projection-description')}\r\n \r\n \r\n {imported && (\r\n {t('project-settings.imported-projections')}\r\n )}\r\n\r\n {imported && ({imported.name})}\r\n\r\n \r\n {t('project-settings.generic-projections')}\r\n \r\n\r\n {t(\"projections.default-projection\", {units: Units.Meters})}\r\n\r\n {t(\"projections.default-projection\", {units: Units.Feet})}\r\n\r\n {hasUserProjections && \r\n {t('project-settings.user-projections')}\r\n }\r\n\r\n {projections.map(row => {\r\n const conflict = imported\r\n ? imported.name === row.name\r\n : false;\r\n\r\n const suffix = conflict\r\n ? \"__conflict\"\r\n : \"\";\r\n\r\n return ({row.name});\r\n })}\r\n \r\n\r\n {/* Camera Correction Matrix */}\r\n
\r\n \r\n {t('project-settings.camera-correction')}\r\n \r\n\r\n {(!hasBasicAlignment) && (\r\n {t('project-settings.camera-correction-description')}\r\n )}\r\n\r\n {(hasBasicAlignment) && (
\r\n \r\n {t('project-settings.camera-correction-warning')}\r\n \r\n
)}\r\n\r\n
\r\n {cameraTransform.path &&
\r\n \r\n {t('project-settings.matrix_offset_units', {units})}: [{offset[0]}, {offset[1]}, {offset[2]}]\r\n \r\n\r\n \r\n {t('project-settings.matrix_rotation')}: [{rotation[0]}, {rotation[1]}, {rotation[2]}]\r\n \r\n
}\r\n\r\n
\r\n {/* Save matrix file */}\r\n {(cameraTransform.path) && (saveMatrixFile(cameraTransform.path)}\r\n className={clsx(classes.button, classes.slimButton)}\r\n color=\"primary\"\r\n >\r\n {t('buttons.save-file')}\r\n )}\r\n\r\n {/* Remove matrix file */}\r\n {cameraTransform.path && (\r\n {t('buttons.remove-file')}\r\n )}\r\n\r\n {/* Upload matrix file */}\r\n {(!hasBasicAlignment) && (\r\n {t('buttons.upload-file')}\r\n )}\r\n\r\n {/* Cancel basic alignment */}\r\n {(hasBasicAlignment) && (\r\n {t('buttons.clear-file')}\r\n )}\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n \r\n {t('buttons.cancel')}\r\n \r\n\r\n \r\n {t('buttons.update-project')}\r\n \r\n
\r\n
\r\n \r\n\r\n {/* Warning message for projection mismatch */}\r\n \r\n \r\n {t('project-settings.projection-mismatch')}\r\n \r\n \r\n \r\n {t('project-settings.projection-mismatch-description', {name: dataProjection.name})}\r\n \r\n\r\n \r\n {t('project-settings.imported-projection')}\r\n

\r\n \"{dataProjection.string}\"\r\n
\r\n\r\n \r\n {t('project-settings.existing-projection')}\r\n

\r\n \"{matchedProjection?.string}\"\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n\r\ninterface MainAppHeaderProps {\r\n settingsDrawerState: boolean;\r\n setSettingsDrawerState: React.Dispatch;\r\n customURLDialogOpen: boolean;\r\n setCustomURLDialogOpen: () => void;\r\n measurementsDialogOpen: boolean;\r\n setMeasurementsDialogOpen: () => void;\r\n}\r\n\r\nexport const MainAppHeader = memo((props: MainAppHeaderProps) => {\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n const dispatch = useDispatch();\r\n const {t, i18n} = useTranslation();\r\n\r\n const {settingsDrawerState, setSettingsDrawerState,\r\n customURLDialogOpen, setCustomURLDialogOpen,\r\n measurementsDialogOpen, setMeasurementsDialogOpen} = props;\r\n\r\n const { activeToolOpen } = useActiveTool();\r\n const { loggedIn } = useAuth();\r\n\r\n const handleDrawerOpen = () => {\r\n dispatch(changeAssetDrawerState(true));\r\n };\r\n\r\n return (\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n {/** Language selector */}\r\n \r\n\r\n {/** Custom Links */}\r\n {isElectronApp && \r\n \r\n \r\n \r\n }\r\n\r\n {/** Measurements */}\r\n \r\n {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n setMeasurementsDialogOpen();\r\n }}\r\n size=\"large\">\r\n \r\n \r\n \r\n\r\n {/** Home Icon */}\r\n {isCloudSite && loggedIn && \r\n \r\n \r\n \r\n }\r\n\r\n {/** User profile */}\r\n {(isCloudSite || isElectronApp) && }\r\n\r\n {/** Project Settings */}\r\n \r\n {\r\n setSettingsDrawerState(true);\r\n }}\r\n size=\"large\">\r\n \r\n \r\n \r\n\r\n \r\n \r\n );\r\n});\r\n\r\nexport const MainAppFooter = memo(() => {\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [mouseCoords, setMouseCoords] = useState(null);\r\n const [coordinate, setCoordinate] = useState(null);\r\n const formatter = viewer?.getMeasurementFormatter();\r\n\r\n useEffect(() => {\r\n setCoordinates();\r\n }, [mouseCoords]);\r\n\r\n /** Mouse coordinate event listener */\r\n useEffect(() => {\r\n const callback = (event) => {\r\n const {coords} = event.detail;\r\n setMouseCoords(coords);\r\n };\r\n\r\n document.addEventListener(\"update-mouse-coords\", callback);\r\n\r\n return () => {\r\n document.removeEventListener(\"update-mouse-coords\", callback);\r\n };\r\n }, []);\r\n\r\n const setCoordinates = () => {\r\n if (!mouseCoords || !LocalScene.initialized) {\r\n setCoordinate(null);\r\n return;\r\n }\r\n\r\n const precision = formatter.getVectorPrecision(LocalScene.viewProjection);\r\n const coordinate = new SceneCoordinate(mouseCoords)\r\n .toViewProjection();\r\n\r\n const x = coordinate.x.toFixed(precision.x);\r\n const y = coordinate.y.toFixed(precision.y);\r\n const z = coordinate.z.toFixed(precision.z);\r\n\r\n setCoordinate([x, y, z]);\r\n };\r\n\r\n return (\r\n \r\n
\r\n {coordinate && \r\n {`(${coordinate[0]}, ${coordinate[1]}, ${coordinate[2]})`}\r\n }\r\n\r\n {!coordinate && \r\n {t('footer.powered_by_solv3d')}\r\n }\r\n
\r\n\r\n
\r\n );\r\n});\r\n\r\nexport const updateMouseCoords = (coords: Vector3) => {\r\n sendCustomEvent(\"update-mouse-coords\", {coords});\r\n};","import React, { useCallback, useEffect, useState } from \"react\";\r\nimport { KeyboardArrowDown, KeyboardArrowUp } from '@mui/icons-material';\r\nimport { throttle, debounce } from 'throttle-debounce';\r\nimport {\r\n Box,\r\n Typography,\r\n Slider,\r\n IconButton,\r\n Input,\r\n InputLabel,\r\n InputAdornment,\r\n useTheme,\r\n Theme\r\n} from \"@mui/material\";\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { UnitConverter } from \"../viewer/utilities\";\r\nimport { isEqual } from 'lodash';\r\nimport { Clamp } from \"../redux/settings-slice\";\r\nimport { Units } from \"../types/project\";\r\n\r\nconst updateValueInterval = 50;\r\nconst saveDispatchInterval = 1000;\r\n\r\nconst converter = new UnitConverter();\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n listItem: {\r\n width: '100%',\r\n marginBottom: theme.spacing(0.5)\r\n },\r\n inputPropParent: {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: theme.spacing(1),\r\n zoom: \"0.85\",\r\n marginRight: `calc(36px + ${theme.spacing(1.5)})`,\r\n },\r\n inputPropTitle: {\r\n height: \"fit-content\"\r\n }\r\n }),\r\n);\r\n\r\ninterface GenericSliderProps {\r\n value: number | Clamp;\r\n min: number;\r\n max: number;\r\n step: number;\r\n onChange: (value) => void;\r\n onFinish?: (value) => void;\r\n labelFunction?: (value) => string;\r\n magnitude?: number;\r\n units?: Units;\r\n endAdornment?: string;\r\n}\r\n\r\ninterface InputSliderProps extends GenericSliderProps {\r\n type: \"single\" | \"range\";\r\n}\r\n\r\nconst InputSlider = (props: InputSliderProps) => {\r\n const {value, type, onChange, onFinish, labelFunction,\r\n magnitude=1.0, units=Units.Meters, endAdornment=\"\"} = props;\r\n\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n\r\n const min = converter.convert(props.min * magnitude, Units.Meters, units);\r\n const max = converter.convert(props.max * magnitude, Units.Meters, units);\r\n const step = props.step * magnitude;\r\n const isRangeType = type === \"range\";\r\n const inputProps = {min, max, step};\r\n\r\n const defaultLabel = value => {\r\n return `${+Number(value).toFixed(2)}${endAdornment}`;\r\n };\r\n\r\n const labelFormat = labelFunction ? labelFunction : defaultLabel;\r\n\r\n const [openState, setOpen] = useState(false);\r\n const [sliderValue, setSliderValue] = useState(null);\r\n\r\n const roundToStep = (value) => {\r\n return +Number((Math.round(value/step) * step).toFixed(2));\r\n };\r\n\r\n const toInput = (value) => {\r\n if (isRangeType) {\r\n const min = converter.convert(value.min * magnitude, Units.Meters, units);\r\n const max = converter.convert(value.max * magnitude, Units.Meters, units);\r\n\r\n return [roundToStep(min), roundToStep(max)];\r\n }\r\n\r\n const out = converter.convert(value * magnitude, Units.Meters, units);\r\n return roundToStep(out);\r\n };\r\n\r\n const fromInput = (value) => {\r\n if (isRangeType) {\r\n return {\r\n min: converter.convert(value[0], units, Units.Meters) / magnitude,\r\n max: converter.convert(value[1], units, Units.Meters) / magnitude\r\n };\r\n }\r\n\r\n return converter.convert(value, units, Units.Meters) / magnitude;\r\n };\r\n\r\n // Throttle update function\r\n const changeCallback = useCallback(\r\n throttle(updateValueInterval, (value) => {\r\n onChange(value);\r\n }), []);\r\n\r\n // Debounce save function\r\n const finishCallback = useCallback(\r\n debounce(saveDispatchInterval, (value) => {\r\n if (!onFinish) return;\r\n onFinish(value);\r\n }), []);\r\n\r\n useEffect(() => {\r\n let scaledValue = toInput(value);\r\n\r\n /** NOTE: react will never return equal for arrays, so lodash is used */\r\n if (isEqual(sliderValue, scaledValue)) return;\r\n setSliderValue(scaledValue);\r\n }, [value, units]);\r\n\r\n useEffect(() => {\r\n if (sliderValue === null) return;\r\n\r\n // Trigger update and change callbacks\r\n const saveValue = fromInput(sliderValue);\r\n changeCallback(saveValue);\r\n finishCallback(saveValue);\r\n }, [sliderValue]);\r\n\r\n const handleClick = () => {\r\n setOpen(!openState);\r\n };\r\n\r\n return (\r\n \r\n
\r\n
\r\n \r\n {labelFormat(min)}\r\n {labelFormat(max)}\r\n \r\n\r\n {\r\n setSliderValue(value);\r\n }}\r\n aria-labelledby=\"input-slider\"\r\n />\r\n
\r\n\r\n {\r\n event.stopPropagation();\r\n handleClick();\r\n }}\r\n >\r\n {openState ? : }\r\n \r\n
\r\n\r\n {openState && (
\r\n {isRangeType && ()}\r\n\r\n {!isRangeType && ()}\r\n
)}\r\n
\r\n );\r\n};\r\n\r\ninterface InputProp {\r\n min: number;\r\n max: number;\r\n step: number;\r\n}\r\n\r\ninterface SingleInputPropProps {\r\n value: number;\r\n setValue: React.Dispatch;\r\n inputProps: InputProp;\r\n adornment: string;\r\n}\r\n\r\nconst SingleInputProp = (props: SingleInputPropProps) => {\r\n const {value, setValue, inputProps, adornment} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const [inputValue, setInputValue] = useState(0);\r\n const [inputError, setInputError] = useState(false);\r\n\r\n useEffect(() => {\r\n setInputValue(+Number(value).toFixed(2));\r\n setInputError(false);\r\n }, [value]);\r\n\r\n const hasError = (value) => {\r\n return (value === \"\")\r\n || isNaN(value)\r\n || (parseFloat(value) < inputProps.min)\r\n || (parseFloat(value) > inputProps.max);\r\n };\r\n\r\n return (\r\n
\r\n \r\n {t(\"user-settings.slider-value\")}:\r\n \r\n\r\n {\r\n // Check for general error\r\n let error = hasError(value);\r\n setInputValue(value);\r\n setInputError(error);\r\n if (error) return;\r\n\r\n // Update slider value\r\n value = parseFloat(value);\r\n setValue(value);\r\n }}\r\n />\r\n
\r\n );\r\n};\r\n\r\ninterface RangeInputPropProps {\r\n values: number[];\r\n setValues: React.Dispatch;\r\n inputProps: InputProp;\r\n adornment: string;\r\n}\r\n\r\nconst RangeInputProp = (props: RangeInputPropProps) => {\r\n const {values, setValues, inputProps, adornment} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const [minValue, setMinValue] = useState(0);\r\n const [maxValue, setMaxValue] = useState(0);\r\n\r\n const [minError, setMinError] = useState(false);\r\n const [maxError, setMaxError] = useState(false);\r\n\r\n useEffect(() => {\r\n setMinValue(+Number(values[0]).toFixed(2));\r\n setMaxValue(+Number(values[1]).toFixed(2));\r\n\r\n setMinError(false);\r\n setMaxError(false);\r\n }, [values]);\r\n\r\n const hasError = (value) => {\r\n return (value === \"\")\r\n || isNaN(value)\r\n || (parseFloat(value) < inputProps.min)\r\n || (parseFloat(value) > inputProps.max);\r\n };\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.slider-minimum-value\")}:\r\n \r\n\r\n {\r\n // Check for general error\r\n let error = hasError(value);\r\n setMinValue(value);\r\n setMinError(error);\r\n if (error) return;\r\n\r\n value = parseFloat(value);\r\n\r\n // Make sure min is less than max\r\n if (value > maxValue) {\r\n setMinError(true);\r\n return;\r\n }\r\n\r\n // Update slider values\r\n setValues([value, maxValue]);\r\n }}\r\n />\r\n
\r\n\r\n
\r\n \r\n {t(\"user-settings.slider-maximum-value\")}:\r\n \r\n\r\n {\r\n // Check for general error\r\n let error = hasError(value);\r\n setMaxValue(value);\r\n setMaxError(error);\r\n if (error) return;\r\n\r\n value = parseFloat(value);\r\n\r\n // Make sure max is more than min\r\n if (value < minValue) {\r\n setMaxError(true);\r\n return;\r\n }\r\n\r\n // Update slider values\r\n setValues([minValue, value]);\r\n }}\r\n />\r\n\r\n
\r\n
\r\n );\r\n};\r\n\r\ninterface InputFieldProps {\r\n value: number;\r\n inputProps: InputProp;\r\n onChange: (value) => void;\r\n adornment: string;\r\n error: boolean;\r\n}\r\n\r\nconst InputField = (props: InputFieldProps) => {\r\n const {value, inputProps, onChange, adornment, error} = props;\r\n\r\n return (\r\n {adornment}}\r\n onChange={(event) => {\r\n onChange(event.target.value);\r\n }}\r\n />\r\n );\r\n};\r\n\r\nexport const SingleSlider = (props: GenericSliderProps) => {\r\n return ;\r\n};\r\n\r\nexport const RangeSlider = (props: GenericSliderProps) => {\r\n return ;\r\n};\r\n","import React from \"react\";\r\nimport { useTheme } from \"@mui/styles\";\r\nimport {\r\n ListItem,\r\n Typography\r\n} from \"@mui/material\";\r\nimport {\r\n ColorPickerWithLabelInline,\r\n DropdownWithLabelInline,\r\n SwitchWithLabelInline,\r\n TextFieldWithLabelInline\r\n} from \"../../components\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { ControlType } from \"../../types/controls\";\r\nimport { AerialMeasureType, SamplingRate, VolumeType } from \"../../types/measurements\";\r\nimport { SingleSlider } from \"../sliders\";\r\n\r\n\r\ninterface SectionTitleProps {\r\n text: string;\r\n}\r\n\r\nexport const SectionTitle = (props: SectionTitleProps) => {\r\n const theme = useTheme();\r\n\r\n return (\r\n \r\n \r\n {props.text}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface ViewerBackgroundProps {\r\n value: string;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const ViewerBackground = (props: ViewerBackgroundProps) => {\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface AerialBackgroundProps {\r\n value: string;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const AerialBackground = (props: AerialBackgroundProps) => {\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface MouseControlTypeProps {\r\n value: ControlType;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const MouseControlType = (props: MouseControlTypeProps) => {\r\n const {value, setValue} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface QuickNavigationToggleProps {\r\n value: boolean;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const QuickNavigationToggle = (props: QuickNavigationToggleProps) => {\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface AerialTypeDropdownProps {\r\n value: AerialMeasureType;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const AerialTypeDropdown = (props: AerialTypeDropdownProps) => {\r\n const {value, setValue} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface VolumeCalculationProps {\r\n value: VolumeType;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const VolumeCalculation = (props: VolumeCalculationProps) => {\r\n const {value, setValue} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface VolumeSamplingProps {\r\n value: SamplingRate;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const VolumeSampling = (props: VolumeSamplingProps) => {\r\n const {value, setValue} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface EngineCloudURLProps {\r\n value: string;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const EngineCloudURL = (props: EngineCloudURLProps) => {\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface OrthomosaicOpacityProps {\r\n value: number;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const OrthomosaicOpacity = (props: OrthomosaicOpacityProps) => {\r\n const {value, setValue} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"global-settings.orthomosaic-opacity\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\ninterface OrthomosaicQualityProps {\r\n value: number;\r\n setValue: React.Dispatch\r\n}\r\n\r\nexport const OrthomosaicQuality = (props: OrthomosaicQualityProps) => {\r\n const {value, setValue} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"global-settings.orthomosaic-quality\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};","import React, {useEffect, useState} from \"react\";\r\nimport {dialog, isElectronApp, registerEvent} from \"../../electron-modules\";\r\nimport {\r\n List} from \"@mui/material\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { SimpleDialog } from \"../../components\";\r\nimport {useAuth, useDialog, useGlobalSettings} from \"../../hooks\";\r\nimport {\r\n engineCloudURL as globalEngineCloudURL,\r\n setEngineCloudURL as setGlobalEngineCloudURL\r\n} from \"../../urls\";\r\nimport {\r\n AerialBackground,\r\n AerialTypeDropdown,\r\n EngineCloudURL,\r\n MouseControlType,\r\n OrthomosaicOpacity,\r\n OrthomosaicQuality,\r\n QuickNavigationToggle,\r\n SectionTitle,\r\n ViewerBackground,\r\n VolumeCalculation,\r\n VolumeSampling\r\n} from \"./components\";\r\nimport { ControlType } from \"../../types/controls\";\r\nimport { AerialMeasureType, SamplingRate, VolumeType } from \"../../types/measurements\";\r\n\r\nexport const GlobalSettings = () => {\r\n const {signOut} = useAuth();\r\n const {t} = useTranslation();\r\n\r\n const settingsDialog = useDialog();\r\n const globalSettings = useGlobalSettings();\r\n\r\n const [openQuickNav, setOpenQuickNav] = useState(false);\r\n const [orthoQuality, setOrthoQuality] = useState(null);\r\n const [orthoOpacity, setOrthoOpacity] = useState(null);\r\n const [controlType, setControlType] = useState(null);\r\n const [aerialMeasureType, setAerialMeasureType] = useState(null);\r\n const [volumeType, setVolumeType] = useState(null);\r\n const [volumeSampleRate, setVolumeSampleRate] = useState(null);\r\n const [viewerBackground, setViewerBackground] = useState(\"#00000\");\r\n const [aerialBackground, setAerialBackground] = useState(\"#00000\");\r\n const [engineCloudURL, setEngineCloudURL] = useState(\"\");\r\n\r\n const onSubmit = () => {\r\n globalSettings.update({\r\n orthoQuality,\r\n orthoOpacity,\r\n controlType,\r\n openQuickNav,\r\n aerialMeasureType,\r\n volumeType,\r\n volumeSampleRate,\r\n viewerBackground,\r\n aerialBackground\r\n });\r\n\r\n if (isElectronApp) {\r\n const modified = setGlobalEngineCloudURL(engineCloudURL, true);\r\n\r\n if (modified) {\r\n signOut();\r\n }\r\n }\r\n\r\n settingsDialog.handleClose();\r\n };\r\n\r\n const onClose = async () => {\r\n if (!modified) {\r\n settingsDialog.handleClose();\r\n return;\r\n }\r\n\r\n const result = await dialog.showMessageBox({\r\n type: 'question',\r\n title: t('global-settings.discard_changes'),\r\n message: t('global-settings.any_unsaved_changes_will_be_lost'),\r\n buttons: [\r\n t(\"buttons.cancel\"),\r\n t('buttons.discard_changes')\r\n ],\r\n noLink: true\r\n });\r\n\r\n if (!result.response) return;\r\n settingsDialog.handleClose();\r\n };\r\n\r\n useEffect(() => {\r\n if (!settingsDialog.open) {\r\n return;\r\n }\r\n\r\n // Load current state from global settings context\r\n setOrthoQuality(globalSettings.orthoQuality);\r\n setOrthoOpacity(globalSettings.orthoOpacity);\r\n setControlType(globalSettings.controlType);\r\n setAerialMeasureType(globalSettings.aerialMeasureType);\r\n setVolumeType(globalSettings.volumeType);\r\n setVolumeSampleRate(globalSettings.volumeSampleRate);\r\n setViewerBackground(globalSettings.viewerBackground);\r\n setAerialBackground(globalSettings.aerialBackground);\r\n setOpenQuickNav(globalSettings.openQuickNav);\r\n\r\n if (isElectronApp) {\r\n setEngineCloudURL(globalEngineCloudURL);\r\n }\r\n }, [settingsDialog.open]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-global-settings\", () => {\r\n settingsDialog.handleOpen();\r\n });\r\n }, []);\r\n\r\n const modified = (engineCloudURL !== globalEngineCloudURL)\r\n || (orthoQuality !== globalSettings.orthoQuality)\r\n || (orthoOpacity !== globalSettings.orthoOpacity)\r\n || (controlType !== globalSettings.controlType)\r\n || (openQuickNav !== globalSettings.openQuickNav)\r\n || (aerialMeasureType !== globalSettings.aerialMeasureType)\r\n || (volumeType !== globalSettings.volumeType)\r\n || (volumeSampleRate !== globalSettings.volumeSampleRate)\r\n || (viewerBackground !== globalSettings.viewerBackground)\r\n || (aerialBackground !== globalSettings.aerialBackground);\r\n\r\n return (\r\n \r\n {/* Global Settings */}\r\n \r\n {/** General settings */}\r\n \r\n \r\n \r\n \r\n \r\n\r\n {/** Measurement settings */}\r\n \r\n \r\n \r\n \r\n\r\n {/** Orthomosaic settings */}\r\n \r\n \r\n \r\n\r\n {/** Engine cloud settings */}\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n","export default __webpack_public_path__ + \"static/media/awesome-green.32dfeafe.png\";","export default __webpack_public_path__ + \"static/media/black-orange.62f427fb.png\";","export default __webpack_public_path__ + \"static/media/blue-hue.15284809.png\";","export default __webpack_public_path__ + \"static/media/blue-orange.19c7779d.png\";","export default __webpack_public_path__ + \"static/media/blue-red.d938a92d.png\";","export default __webpack_public_path__ + \"static/media/grayscale.416ab034.png\";","export default __webpack_public_path__ + \"static/media/heat-map.100d3bd6.png\";","export default __webpack_public_path__ + \"static/media/jet.e5269d83.png\";","export default __webpack_public_path__ + \"static/media/pastel-shades.1cd9b941.png\";","import awesomeGreen from './awesome-green.png';\r\nimport blackOrange from './black-orange.png';\r\nimport blueHue from './blue-hue.png';\r\nimport blueOrange from './blue-orange.png';\r\nimport blueRed from './blue-red.png';\r\nimport grayScale from './grayscale.png';\r\nimport heatMap from './heat-map.png';\r\nimport jet from './jet.png';\r\nimport pastelShades from './pastel-shades.png';\r\nimport {ColorMapKey} from \"../../../redux/settings-slice\";\r\nimport {t} from '../../../localization';\r\n\r\nclass ColorMap {\r\n public id: ColorMapKey;\r\n public image: string;\r\n\r\n constructor(id, image) {\r\n this.id = id;\r\n this.image = image;\r\n }\r\n\r\n get name() {\r\n return t(`color-map.${this.id}`);\r\n }\r\n}\r\n\r\nexport const colorMaps: ColorMap[] = [\r\n new ColorMap(\"heat-map\", heatMap),\r\n new ColorMap(\"awesome-green\", awesomeGreen),\r\n new ColorMap(\"pastel-shades\", pastelShades),\r\n new ColorMap(\"blue-orange\", blueOrange),\r\n new ColorMap(\"black-orange\", blackOrange),\r\n new ColorMap(\"blue-hue\", blueHue),\r\n new ColorMap(\"blue-red\", blueRed),\r\n new ColorMap(\"jet\", jet),\r\n new ColorMap(\"grayscale\", grayScale)\r\n];\r\n\r\nexport const getColorMap = (id) => {\r\n return colorMaps.find(colorMap => colorMap.id === id);\r\n};\r\n","import openStreetMaps from './open-street-maps.png';\r\nimport arcgisWorld from './arcgis-world.png';\r\nimport arcgisStreet from './arcgis-street.png';\r\nimport noBasemap from './no-basemap.png';\r\n\r\nconst textures = {\r\n 'open-street-maps': openStreetMaps,\r\n 'arcgis-world': arcgisWorld,\r\n 'arcgis-street': arcgisStreet,\r\n 'no-basemap': noBasemap\r\n};\r\n\r\nexport default textures;\r\n","export default __webpack_public_path__ + \"static/media/open-street-maps.45e253e7.png\";","export default __webpack_public_path__ + \"static/media/arcgis-world.f700fb3f.png\";","export default __webpack_public_path__ + \"static/media/arcgis-street.d6a677f8.png\";","export default __webpack_public_path__ + \"static/media/no-basemap.32912dc6.png\";","import textures from \"../viewer/textures/map-preview\";\r\n\r\nexport const emptyBasemapID = \"no-basemap\";\r\n\r\nexport const aerialBasemaps = [\r\n {\r\n id: emptyBasemapID,\r\n text: \"user-settings.no_base_map\",\r\n src: textures[\"no-basemap\"]\r\n },\r\n {\r\n id: \"open-street-maps\",\r\n text: \"OpenStreetMaps\",\r\n src: textures[\"open-street-maps\"]\r\n },\r\n {\r\n id: \"arcgis-world\",\r\n text: \"ArcGIS World\",\r\n src: textures[\"arcgis-world\"]\r\n },\r\n {\r\n id: \"arcgis-street\",\r\n text: \"ArcGIS Street\",\r\n src: textures[\"arcgis-street\"]\r\n }\r\n];","import React, { useCallback, useEffect, useMemo, useState } from 'react';\r\nimport { Theme, useTheme } from '@mui/material/styles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n Avatar,\r\n FormControl,\r\n List,\r\n ListItem,\r\n MenuItem,\r\n Select,\r\n Switch,\r\n Typography\r\n} from '@mui/material';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { RangeSlider, SingleSlider } from '../sliders';\r\nimport { useGlobalSettings, useViewer } from '../../hooks';\r\nimport LocalScene from '../../viewer/projections';\r\nimport { useDispatch, useSelector } from 'react-redux';\r\nimport { UnitConverter } from '../../viewer/utilities';\r\nimport {\r\n ColorMapKey,\r\n ColorType,\r\n MarkerNavType,\r\n changeAllClassificationVisibility,\r\n changeArrowMarkers,\r\n changeAvailableClassifications,\r\n changeCircularPoints,\r\n changeClassificationVisibility,\r\n changeCloudDistance,\r\n changeCloudMaxPoints,\r\n changeCloudMinimum,\r\n changeCloudScale,\r\n changeColorMap,\r\n changeColorType,\r\n changeDynamicSize,\r\n changeHeightClip,\r\n changeIntensityClip,\r\n changeModelDistance,\r\n changeOpacity,\r\n changeTagDistance,\r\n getAvailableClassifications,\r\n getClassificationVisibilities,\r\n selectArrowMarkers,\r\n selectCircularPoints,\r\n selectClassifications,\r\n selectCloudDistance,\r\n selectCloudMaxPoints,\r\n selectCloudMinimum,\r\n selectCloudScale,\r\n selectColorMap,\r\n selectColorType,\r\n selectDynamicSize,\r\n selectHeightClip,\r\n selectIntensityClip,\r\n selectModelDistance,\r\n selectOpacity,\r\n selectTagDistance\r\n} from '../../redux/settings-slice';\r\nimport { getClassificationColors } from '../../classifications';\r\nimport { ArrowTooltip, SwitchWithLabel } from '../../components';\r\nimport {isEqual} from 'lodash';\r\nimport { colorMaps, getColorMap } from '../../viewer/textures/colormaps';\r\nimport { Units } from '../../types/project';\r\nimport { changeSavedAerialState, selectSavedAerialState } from '../../redux/camera-slice';\r\nimport { aerialBasemaps, emptyBasemapID } from '../../types/basemaps';\r\n\r\nconst converter = new UnitConverter();\r\n\r\nconst classificationInterval = 200;\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n colorPreview: {\r\n height: theme.spacing(3),\r\n width: theme.spacing(3),\r\n marginRight: theme.spacing(1),\r\n },\r\n colorMapImage: {\r\n objectFit: 'fill',\r\n transform: 'rotate(-90deg)'\r\n },\r\n listItem: {\r\n width: '100%',\r\n marginBottom: theme.spacing(0.5)\r\n },\r\n formControl: {\r\n width: '100%',\r\n marginBottom: theme.spacing(1)\r\n }\r\n })\r\n);\r\n\r\ninterface SectionTitleProps {\r\n text: string;\r\n}\r\n\r\nexport const SectionTitle = (props: SectionTitleProps) => {\r\n return (\r\n \r\n \r\n {props.text}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface SectionDescriptionProps {\r\n text: string;\r\n}\r\n\r\nexport const SectionDescription = (props: SectionDescriptionProps) => {\r\n return (\r\n \r\n \r\n {props.text}\r\n \r\n \r\n );\r\n};\r\n\r\n/** Debug tools */\r\nexport const GPUPickerDebug = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [pickerDebug, setPickerDebug] = useState(false);\r\n\r\n const onChange = useCallback((_, checked) => {\r\n setPickerDebug(checked);\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.togglePickerDebug(pickerDebug);\r\n }, [viewer, pickerDebug]);\r\n\r\n return (\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const PointsRenderDebug = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [renderPaused, setRenderPaused] = useState(false);\r\n\r\n const onChange = useCallback((_, checked) => {\r\n setRenderPaused(checked);\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointsRenderPaused(renderPaused);\r\n }, [viewer, renderPaused]);\r\n\r\n return (\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const BoudingBoxDebug = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [boundsVisible, setBoundsVisible] = useState(false);\r\n\r\n const onChange = useCallback((_, checked) => {\r\n setBoundsVisible(checked);\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointBoundsVisible(boundsVisible);\r\n }, [viewer, boundsVisible]);\r\n\r\n return (\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\n/** Classifications */\r\nexport const ClassificationList = () => {\r\n const dispatch = useDispatch();\r\n const classes = useStyles();\r\n const theme = useTheme();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const classifications = useSelector(selectClassifications);\r\n\r\n const [classificationColors, setClassificationColors]\r\n = useState(Array(256).fill('#ffffff'));\r\n\r\n const savedAvailableClassifications = useMemo(() => {\r\n return getAvailableClassifications(classifications);\r\n }, [classifications]);\r\n\r\n const savedClassificationVisibilities = useMemo(() => {\r\n return getClassificationVisibilities(classifications);\r\n }, [classifications]);\r\n\r\n useEffect(() => {\r\n const updateColorsList = async () => {\r\n const colors = await getClassificationColors();\r\n setClassificationColors(colors);\r\n };\r\n\r\n updateColorsList();\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setVisibleClassifications(savedClassificationVisibilities);\r\n }, [viewer, savedClassificationVisibilities]);\r\n\r\n /** Handle classification updates */\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (!viewer) return;\r\n\r\n const newClasses = viewer.getAvailableClassifications();\r\n newClasses.sort();\r\n\r\n const oldClasses = savedAvailableClassifications.map(x => x.id);\r\n oldClasses.sort();\r\n\r\n if (isEqual(newClasses, oldClasses)) return;\r\n dispatch(changeAvailableClassifications(newClasses));\r\n }, classificationInterval);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [viewer, classifications]);\r\n\r\n const hasClassifications = savedAvailableClassifications.length > 0;\r\n\r\n return (\r\n \r\n \r\n
\r\n \r\n {t(\"user-settings.classifications\")}\r\n \r\n\r\n {savedAvailableClassifications.length > 0 && (\r\n \r\n classification.visible\r\n )}\r\n onChange={(_, checked) => {\r\n dispatch(changeAllClassificationVisibility(checked));\r\n }}\r\n />\r\n \r\n )}\r\n
\r\n
\r\n\r\n\r\n {!hasClassifications && (\r\n
\r\n \r\n \r\n {t(\"user-settings.no-points-loaded\")}\r\n \r\n \r\n
\r\n )}\r\n\r\n {hasClassifications && (\r\n savedAvailableClassifications.map(classification => (\r\n \r\n
\r\n \r\n }\r\n checked={classification.visible}\r\n onChange={(_, checked) => {\r\n dispatch(changeClassificationVisibility(classification.id));\r\n }}\r\n />\r\n
\r\n
\r\n ))\r\n )}\r\n\r\n
\r\n );\r\n};\r\n\r\n/** Model components */\r\nexport const ModelDistance = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedModelDistance = useSelector(selectModelDistance);\r\n const units = LocalScene.viewProjectionUnits;\r\n\r\n const onChange = useCallback((value) => {\r\n viewer.setModelDistance(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeModelDistance(value));\r\n }, []);\r\n\r\n const labelFunction = useCallback((value) => {\r\n const maxValue = converter.convert(999, Units.Meters, units);\r\n return (value > maxValue) ? \"∞\" : `${value}${units}`;\r\n }, [units]);\r\n\r\n useEffect(() => {\r\n viewer?.setModelDistance(savedModelDistance);\r\n }, [viewer, savedModelDistance]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.model_distance\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\n/** Tag components */\r\nexport const TagDrawDistance = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedTagDistance = useSelector(selectTagDistance);\r\n const units = LocalScene.viewProjectionUnits;\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setTagDistance(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeTagDistance(value));\r\n }, []);\r\n\r\n const labelFunction = useCallback((value) => {\r\n const maxValue = converter.convert(999, Units.Meters, units);\r\n return (value > maxValue) ? \"∞\" : `${value}${units}`;\r\n }, [units]);\r\n\r\n useEffect(() => {\r\n viewer?.setTagDistance(savedTagDistance);\r\n }, [viewer, savedTagDistance]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.tag-distance\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\n/** Point cloud components */\r\nexport const PointCloudDistance = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedCloudDistance = useSelector(selectCloudDistance);\r\n const units = LocalScene.viewProjectionUnits;\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudDistance(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeCloudDistance(value));\r\n }, []);\r\n\r\n const labelFunction = useCallback((value) => {\r\n const maxValue = converter.convert(999, Units.Meters, units);\r\n return (value > maxValue) ? \"∞\" : `${value}${units}`;\r\n }, [units]);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudDistance(savedCloudDistance);\r\n }, [viewer, savedCloudDistance]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.point-distance\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const PointCloudScale = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedCloudScale = useSelector(selectCloudScale);\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudScale(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeCloudScale(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudScale(savedCloudScale);\r\n }, [viewer, savedCloudScale]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.point-size\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const PointCloudSize = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedCloudMinimum = useSelector(selectCloudMinimum);\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudMinimum(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeCloudMinimum(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudMinimum(savedCloudMinimum);\r\n }, [viewer, savedCloudMinimum]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t('user-settings.minimum-point-size')}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const AdaptivePointSize = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedDynamicSize = useSelector(selectDynamicSize);\r\n\r\n const onChange = useCallback((_, checked) => {\r\n dispatch(changeDynamicSize(checked));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudDynamicSize(savedDynamicSize);\r\n }, [viewer, savedDynamicSize]);\r\n\r\n return (\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const PointCloudShape = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedCircularPoints = useSelector(selectCircularPoints);\r\n\r\n const onChange = useCallback((_, checked) => {\r\n dispatch(changeCircularPoints(checked));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudCircularPoints(savedCircularPoints);\r\n }, [viewer, savedCircularPoints]);\r\n\r\n return (\r\n \r\n
\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const IntensityRange = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedIntensityClip = useSelector(selectIntensityClip);\r\n const savedColorType = useSelector(selectColorType);\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudIntensityClip(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeIntensityClip(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudIntensityClip(savedIntensityClip);\r\n }, [viewer, savedIntensityClip]);\r\n\r\n const visible = savedColorType === ColorType.Intensity;\r\n\r\n return (\r\n \r\n {visible && \r\n
\r\n \r\n {t(\"user-settings.intensity-range\")}\r\n \r\n\r\n \r\n
\r\n
\r\n }\r\n
\r\n );\r\n};\r\n\r\nexport const HeightRange = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedHeightClip = useSelector(selectHeightClip);\r\n const savedColorType = useSelector(selectColorType);\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudHeightClip(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeHeightClip(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudHeightClip(savedHeightClip);\r\n }, [viewer, savedHeightClip]);\r\n\r\n const visible = savedColorType === ColorType.Height;\r\n\r\n return (\r\n \r\n {visible && \r\n
\r\n \r\n {t(\"user-settings.height-range\")}\r\n \r\n\r\n \r\n
\r\n
}\r\n
\r\n );\r\n};\r\n\r\nexport const ColorMapPicker = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedColorMap = useSelector(selectColorMap);\r\n const savedColorType = useSelector(selectColorType);\r\n\r\n const onRender = useCallback((value) => {\r\n return getColorMap(value).name;\r\n }, []);\r\n\r\n const onChange = useCallback((event) => {\r\n const value = event.target.value as ColorMapKey;\r\n dispatch(changeColorMap(value));\r\n }, []);\r\n\r\n const getMenuItems = () => {\r\n return colorMaps.map((colorMap) => (\r\n \r\n \r\n {colorMap.name}\r\n \r\n ));\r\n };\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudColorMap(savedColorMap);\r\n }, [viewer, savedColorMap]);\r\n\r\n const visible = (savedColorType === ColorType.Intensity)\r\n || (savedColorType === ColorType.Height);\r\n\r\n const options = getMenuItems();\r\n\r\n return (\r\n \r\n {visible && \r\n
\r\n \r\n {t(\"user-settings.color-map\")}\r\n \r\n\r\n \r\n \r\n {options}\r\n \r\n \r\n
\r\n
}\r\n
\r\n );\r\n};\r\n\r\nexport const PointCloudOpacity = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedOpacity = useSelector(selectOpacity);\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudOpacity(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeOpacity(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudOpacity(savedOpacity);\r\n }, [viewer, savedOpacity]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.point-visibility\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const PointCloudCount = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedMaxPoints = useSelector(selectCloudMaxPoints);\r\n\r\n const onChange = useCallback((value) => {\r\n viewer?.setPointCloudMaxPoints(value);\r\n }, [viewer]);\r\n\r\n const onFinish = useCallback((value) => {\r\n dispatch(changeCloudMaxPoints(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudMaxPoints(savedMaxPoints);\r\n }, [viewer, savedMaxPoints]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.max-visible-points\")}\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const PointCloudColor = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedColorType = useSelector(selectColorType);\r\n\r\n const onChange = useCallback((event) => {\r\n const value = event.target.value as ColorType;\r\n dispatch(changeColorType(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudColorType(savedColorType);\r\n }, [viewer, savedColorType]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.color-type\")}\r\n \r\n\r\n \r\n \r\n \r\n {t(\"color-type.intensity\")}\r\n \r\n \r\n {t(\"color-type.color\")}\r\n \r\n \r\n {t(\"color-type.height\")}\r\n \r\n \r\n {t(\"color-type.classification\")}\r\n \r\n \r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const NavigationType = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const savedArrowMarkers = useSelector(selectArrowMarkers);\r\n\r\n const onChange = useCallback((event) => {\r\n let value = event.target.value as MarkerNavType;\r\n dispatch(changeArrowMarkers(value));\r\n }, []);\r\n\r\n useEffect(() => {\r\n viewer?.setNavigationType(savedArrowMarkers);\r\n }, [viewer, savedArrowMarkers]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t(\"user-settings.navigation-type\")}\r\n \r\n\r\n \r\n \r\n \r\n {t(\"navigation-type.arrows\")}\r\n \r\n \r\n {t(\"navigation-type.markers\")}\r\n \r\n \r\n {t(\"navigation-type.none\")}\r\n \r\n \r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const AerialBasemapPicker = () => {\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const {aerialBackground} = useGlobalSettings();\r\n const aerialState = useSelector(selectSavedAerialState);\r\n const savedBaseMap = aerialState.basemap || emptyBasemapID;\r\n\r\n const onRender = useCallback((value) => {\r\n const basemap = aerialBasemaps.find(basemap => basemap.id === value);\r\n return t(basemap.text);\r\n }, []);\r\n\r\n const onChange = useCallback((event) => {\r\n const basemap = event.target.value as string;\r\n const newState = {...aerialState, basemap};\r\n dispatch(changeSavedAerialState(newState));\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setAerialBasemap(savedBaseMap);\r\n }, [viewer, savedBaseMap]);\r\n\r\n const getMenuItems = () => {\r\n if (!viewer) return [];\r\n\r\n return aerialBasemaps.map((basemap) => {\r\n const isEmpty = basemap.id === emptyBasemapID;\r\n\r\n return (\r\n \r\n \r\n {t(basemap.text)}\r\n \r\n );\r\n });\r\n };\r\n\r\n const options = getMenuItems();\r\n\r\n return (\r\n \r\n \r\n
\r\n \r\n {t('user-settings.base_map')}\r\n \r\n\r\n \r\n \r\n {options}\r\n \r\n \r\n
\r\n
\r\n
\r\n );\r\n};","import React from 'react';\r\nimport { Theme, } from '@mui/material/styles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport Drawer from '@mui/material/Drawer';\r\nimport {\r\n List,\r\n ListItem,\r\n} from \"@mui/material\";\r\nimport IconButton from \"@mui/material/IconButton\";\r\nimport CloseIcon from \"@mui/icons-material/Close\";\r\nimport Divider from \"@mui/material/Divider\";\r\nimport Typography from \"@mui/material/Typography\";\r\nimport { isDevMode } from '../../electron-modules';\r\nimport { SlimScrollbar } from '../../components';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { headerHeight } from '../../app';\r\nimport clsx from 'clsx';\r\nimport {\r\n BoudingBoxDebug,\r\n ClassificationList,\r\n ModelDistance,\r\n GPUPickerDebug,\r\n PointCloudDistance,\r\n PointsRenderDebug,\r\n TagDrawDistance,\r\n PointCloudShape,\r\n AdaptivePointSize,\r\n PointCloudScale,\r\n PointCloudSize,\r\n IntensityRange,\r\n HeightRange,\r\n ColorMapPicker,\r\n PointCloudCount,\r\n PointCloudOpacity,\r\n NavigationType,\r\n PointCloudColor,\r\n SectionTitle,\r\n SectionDescription,\r\n AerialBasemapPicker\r\n} from './components';\r\nimport { useSelector } from 'react-redux';\r\nimport { selectOrbitMode } from '../../redux/camera-slice';\r\n\r\nexport const settingsDrawerWidth = 280;\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n backdrop: {\r\n display: \"none\"\r\n },\r\n drawer: {\r\n width: 0,\r\n \"z-index\": `${theme.zIndex.appBar - 1} !important`,\r\n },\r\n drawerPaper: {\r\n width: settingsDrawerWidth,\r\n paddingTop: `${headerHeight}px`,\r\n height: `calc(100% - ${headerHeight}px)`,\r\n },\r\n list: {\r\n width: '100%',\r\n maxWidth: 360,\r\n backgroundColor: theme.palette.background.paper,\r\n },\r\n title: {\r\n flex: 1,\r\n margin: theme.spacing(0)\r\n },\r\n boldTitleTypography: {\r\n fontWeight: 'bold',\r\n fontSize: '1em'\r\n }\r\n }),\r\n);\r\n\r\ninterface SettingsDrawerProps {\r\n open: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nexport const SettingsDrawer = (props: SettingsDrawerProps) => {\r\n const {open, onClose} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const isOrbitMode = useSelector(selectOrbitMode);\r\n\r\n return (\r\n \r\n \r\n\r\n \r\n \r\n \r\n {t('user-settings.project_settings')}\r\n \r\n\r\n {/* Close button */}\r\n \r\n \r\n \r\n \r\n \r\n\r\n {/* Developer Controls */}\r\n {isDevMode && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n )}\r\n\r\n {/* Point Cloud Controls */}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n {/* Point Cloud Size */}\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n {/* Aerial Map Controls */}\r\n \r\n \r\n \r\n \r\n\r\n \r\n\r\n {/* Draw distances */}\r\n \r\n \r\n\r\n {isOrbitMode && }\r\n\r\n {!isOrbitMode && \r\n \r\n \r\n \r\n }\r\n \r\n\r\n \r\n\r\n {/* Classifications */}\r\n \r\n\r\n \r\n \r\n );\r\n};","import { NearestFilter, TextureLoader } from 'three';\r\nimport classifications from './textures/colormaps/classifications.png';\r\n\r\n// Load classification texture\r\nconst loader = new TextureLoader();\r\n\r\nexport const classificationTexture =\r\n loader.load(classifications, texture => {\r\n texture.minFilter = NearestFilter;\r\n texture.magFilter = NearestFilter;\r\n });\r\n","export default \"uniform sampler2D tImage;\\r\\nuniform float opacity;\\r\\nvarying vec2 vUv;\\r\\n\\r\\nvoid main() {\\r\\n vec4 color = texture2D(tImage, vUv);\\r\\n float alpha = color.a * opacity;\\r\\n gl_FragColor = vec4(color.rgb, alpha);\\r\\n}\\r\\n\";","export default \"varying vec2 vUv;\\r\\n\\r\\nvoid main() {\\r\\n\\tvUv = uv;\\r\\n\\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\r\\n}\\r\\n\";","/* eslint-disable import/no-webpack-loader-syntax */\r\n\r\nimport basicRenderFragmentShader from \"!!raw-loader!./render_basic.frag\";\r\nimport edlRenderFragmentShader from \"!!raw-loader!./render_edl.frag\";\r\nimport outputRenderFragmentShader from \"!!raw-loader!./render_output.frag\";\r\nimport commonRenderVertexShader from \"!!raw-loader!./render_common.vert\";\r\nimport pointCloudFragmentShader from \"!!raw-loader!./pointcloud.frag\";\r\nimport pointCloudVertexShader from \"!!raw-loader!./pointcloud.vert\";\r\nimport panoramicFragmentShader from \"!!raw-loader!./panoramic.frag\";\r\nimport panoramicVertexShader from \"!!raw-loader!./panoramic.vert\";\r\nimport planarFragmentShader from \"!!raw-loader!./planar.frag\";\r\nimport planarVertexShader from \"!!raw-loader!./planar.vert\";\r\nimport markersFragmentShader from \"!!raw-loader!./markers.frag\";\r\nimport markersVertexShader from \"!!raw-loader!./markers.vert\";\r\nimport utilitiesShader from \"!!raw-loader!./utilities.glsl\";\r\nimport gpuPickerFragmentShader from \"!!raw-loader!./gpu_picker.frag\";\r\nimport gpuPickerVertexShader from \"!!raw-loader!./gpu_picker.vert\";\r\nimport texturePackVertexShader from \"!!raw-loader!./texture_pack.vert\";\r\nimport tagsFragmentShader from \"!!raw-loader!./tags.frag\";\r\nimport tagsVertexShader from \"!!raw-loader!./tags.vert\";\r\nimport basicPickerFragmentShader from \"!!raw-loader!./picker_basic.frag\";\r\nimport basicPickerVertexShader from \"!!raw-loader!./picker_basic.vert\";\r\nimport lineworkSpriteFragmentShader from \"!!raw-loader!./linework_sprite.frag\";\r\nimport lineworkSpriteVertexShader from \"!!raw-loader!./linework_sprite.vert\";\r\nimport lineworkBasicFragmentShader from \"!!raw-loader!./linework_basic.frag\";\r\nimport lineworkBasicVertexShader from \"!!raw-loader!./linework_basic.vert\";\r\nimport IFCFragmentShader from \"!!raw-loader!./ifc.frag\";\r\nimport IFCVertexShader from \"!!raw-loader!./ifc.vert\";\r\n\r\nconst shaders = {\r\n ifc: {\r\n vert: IFCVertexShader,\r\n frag: IFCFragmentShader\r\n },\r\n pointcloud: {\r\n vert: pointCloudVertexShader,\r\n frag: pointCloudFragmentShader\r\n },\r\n panoramic: {\r\n vert: panoramicVertexShader,\r\n frag: panoramicFragmentShader\r\n },\r\n planar: {\r\n vert: planarVertexShader,\r\n frag: planarFragmentShader\r\n },\r\n linework_basic: {\r\n vert: lineworkBasicVertexShader,\r\n frag: lineworkBasicFragmentShader\r\n },\r\n linework_sprite: {\r\n vert: lineworkSpriteVertexShader,\r\n frag: lineworkSpriteFragmentShader\r\n },\r\n render_edl: {\r\n vert: commonRenderVertexShader,\r\n frag: edlRenderFragmentShader\r\n },\r\n render_basic: {\r\n vert: commonRenderVertexShader,\r\n frag: basicRenderFragmentShader\r\n },\r\n render_transition: {\r\n vert: commonRenderVertexShader,\r\n frag: outputRenderFragmentShader\r\n },\r\n markers: {\r\n vert: markersVertexShader,\r\n frag: markersFragmentShader\r\n },\r\n utilities: utilitiesShader,\r\n basic_picker: {\r\n vert: basicPickerVertexShader,\r\n frag: basicPickerFragmentShader\r\n },\r\n gpu_picker: {\r\n vert: gpuPickerVertexShader,\r\n frag: gpuPickerFragmentShader\r\n },\r\n texture_packer: {\r\n vert: texturePackVertexShader\r\n },\r\n tags: {\r\n vert: tagsVertexShader,\r\n frag: tagsFragmentShader\r\n }\r\n};\r\n\r\nexport default shaders;","export default \"#define LAMBERT\\r\\n\\r\\nvarying vec3 vLightFront;\\r\\nvarying vec3 vIndirectFront;\\r\\n\\r\\n#ifdef DOUBLE_SIDED\\r\\n\\tvarying vec3 vLightBack;\\r\\n\\tvarying vec3 vIndirectBack;\\r\\n#endif\\r\\n\\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n\\r\\nvarying vec3 vWorldPosition;\\r\\n\\r\\nvoid main() {\\r\\n\\t// Update colors for GPU picker\\r\\n\\tupdateGPUPickerColors();\\r\\n\\r\\n \\tvWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\\r\\n\\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n\\t#include \\r\\n}\";","export default \"uniform vec3 diffuse;\\r\\nuniform vec3 emissive;\\r\\nuniform float opacity;\\r\\n\\r\\nvarying vec3 vLightFront;\\r\\nvarying vec3 vIndirectFront;\\r\\n\\r\\n#ifdef DOUBLE_SIDED\\r\\n\\tvarying vec3 vLightBack;\\r\\n\\tvarying vec3 vIndirectBack;\\r\\n#endif\\r\\n\\r\\n\\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n#include \\r\\n\\r\\nuniform bool gpuPicker;\\r\\nuniform float drawDistance;\\r\\n\\r\\nvarying vec3 vWorldPosition;\\r\\n\\r\\nvoid main() {\\r\\n // Hide based on draw distance\\r\\n if (outsideBounds(vWorldPosition, drawDistance)) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n if (gpuPicker) {\\r\\n gl_FragColor = vGPUColor;\\r\\n return;\\r\\n }\\r\\n\\r\\n #include \\r\\n\\r\\n vec4 diffuseColor = vec4( diffuse, opacity );\\r\\n ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\\r\\n vec3 totalEmissiveRadiance = emissive;\\r\\n\\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n\\r\\n // accumulation\\r\\n\\r\\n #ifdef DOUBLE_SIDED\\r\\n\\r\\n reflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\\r\\n\\r\\n #else\\r\\n\\r\\n reflectedLight.indirectDiffuse += vIndirectFront;\\r\\n\\r\\n #endif\\r\\n\\r\\n #include \\r\\n\\r\\n reflectedLight.indirectDiffuse *= BRDF_Lambert( diffuseColor.rgb );\\r\\n\\r\\n #ifdef DOUBLE_SIDED\\r\\n\\r\\n reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\\r\\n\\r\\n #else\\r\\n\\r\\n reflectedLight.directDiffuse = vLightFront;\\r\\n\\r\\n #endif\\r\\n\\r\\n reflectedLight.directDiffuse *= BRDF_Lambert( diffuseColor.rgb ) * getShadowMask();\\r\\n\\r\\n // modulation\\r\\n\\r\\n #include \\r\\n\\r\\n vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\\r\\n\\r\\n #include \\r\\n\\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n #include \\r\\n}\";","export default \"\\r\\n#define DISTANCE_FROM_PLANE 0.5\\r\\n\\r\\nattribute float intensity;\\r\\nattribute float classification;\\r\\nattribute vec3 rgb;\\r\\n\\r\\nuniform bool gpuPicker;\\r\\nuniform float pratio;\\r\\nuniform float size;\\r\\nuniform float alpha;\\r\\nuniform float screenHeight;\\r\\nuniform float fov;\\r\\nuniform float minSize;\\r\\nuniform float maxSize;\\r\\nuniform float octreeSize;\\r\\nuniform vec3 octreeCorner;\\r\\nuniform float octreeSpacing;\\r\\nuniform float drawDistance;\\r\\n\\r\\nuniform sampler2D colorMap;\\r\\nuniform float colorType;\\r\\nuniform bool adaptiveSize;\\r\\nuniform bool isOctreeCloud;\\r\\nuniform bool isPotreeCloud;\\r\\nuniform vec2 heightRange;\\r\\nuniform vec2 heightClamp;\\r\\nuniform vec2 intensityRange;\\r\\nuniform vec2 intensityClamp;\\r\\nuniform float rgbMax;\\r\\n\\r\\nuniform float crossSectionWidth;\\r\\nuniform vec3 crossSectionStart;\\r\\nuniform vec3 crossSectionEnd;\\r\\n\\r\\nuniform sampler2D clipPolygonData;\\r\\n\\r\\nuniform sampler2D visibleNodes;\\r\\nuniform sampler2D classificationData;\\r\\nuniform sampler2D classificationVisible;\\r\\nuniform sampler2D areaTriangleData;\\r\\n\\r\\nflat varying vec3 vColor;\\r\\nflat varying float vHidden;\\r\\n\\r\\nvec3 pointOnPlane(vec3 origin, vec3 point, vec3 normal) {\\r\\n return point - dot(point - origin, normal) * normal;\\r\\n}\\r\\n\\r\\nfloat distanceFromPlane(vec3 origin, vec3 point, vec3 normal) {\\r\\n return abs(dot(origin - point, normal));\\r\\n}\\r\\n\\r\\nbool classificationIsHidden(float classification) {\\r\\n float x = (classification + 0.1) / float(NUMBER_OF_CLASSIFICATIONS);\\r\\n vec4 value = texture2D(classificationVisible, vec2(x, 0.5));\\r\\n return value.a < 0.5;\\r\\n}\\r\\n\\r\\nvec3 classificationColor(float classification) {\\r\\n float x = (classification + 0.1) / float(NUMBER_OF_CLASSIFICATIONS);\\r\\n vec4 value = texture2D(classificationData, vec2(x, 0.5));\\r\\n return value.rgb;\\r\\n}\\r\\n\\r\\nfloat clampedValue(float data, vec2 dataRange, vec2 dataClamp) {\\r\\n float scaled = (data - dataRange.x) / (dataRange.y - dataRange.x);\\r\\n float clamped = (scaled - dataClamp.x) / (dataClamp.y - dataClamp.x);\\r\\n return clamped;\\r\\n}\\r\\n\\r\\nvec3 calculateOppositeColor(float colorType, vec3 colorValue){\\r\\n vec3 result;\\r\\n vec3 opp = vec3(1.0, 1.0, 1.0);\\r\\n opp = opp - colorValue;\\r\\n\\r\\n bool isIntensity = compareFloat(colorType, 0.0);\\r\\n bool isRGB = compareFloat(colorType, 1.0);\\r\\n bool isHeight = compareFloat(colorType, 2.0);\\r\\n bool isClassification = compareFloat(colorType, 3.0);\\r\\n\\r\\n if (isHeight) {\\r\\n result = opp;\\r\\n } else if (isIntensity) {\\r\\n result = vec3(1.0, 0.0, 0.0);\\r\\n } else if (isClassification) {\\r\\n result = vec3(1.0, 0.0, 0.0);\\r\\n } else if (isRGB) {\\r\\n result = vec3(1.0, 0.0, 0.0);\\r\\n } else {\\r\\n result = opp;\\r\\n }\\r\\n\\r\\n return result;\\r\\n}\\r\\n\\r\\nvec3 getCloudColor(float colorType, vec3 posWorld) {\\r\\n // Default color for invalid color types\\r\\n vec3 color = vec3(0.0, 0.0, 0.0);\\r\\n\\r\\n bool isIntensity = compareFloat(colorType, 0.0);\\r\\n bool isRGB = compareFloat(colorType, 1.0);\\r\\n bool isHeight = compareFloat(colorType, 2.0);\\r\\n bool isClassification = compareFloat(colorType, 3.0);\\r\\n\\r\\n if (isRGB) {\\r\\n // Color by RGB values\\r\\n color = rgb / rgbMax;\\r\\n } else if (isIntensity) {\\r\\n // Intensity colors with clamping\\r\\n float cloudIntensity = clampedValue(intensity, intensityRange, intensityClamp);\\r\\n color = texture2D(colorMap, vec2(cloudIntensity, 0.5)).rgb;\\r\\n } else if (isHeight) {\\r\\n // Height based coloring with clamping\\r\\n float cloudHeight = clampedValue(posWorld.z, heightRange, heightClamp);\\r\\n color = texture2D(colorMap, vec2(cloudHeight, 0.5)).rgb;\\r\\n } else if (isClassification) {\\r\\n color = classificationColor(classification);\\r\\n }\\r\\n\\r\\n return color;\\r\\n}\\r\\n\\r\\nint roundFloat(float number){\\r\\n\\treturn int(floor(number + 0.5));\\r\\n}\\r\\n\\r\\nbool isBitSet(int number, int index){\\r\\n int powi = roundFloat(pow(2.0, float(index)));\\r\\n\\tint ndp = number / powi;\\r\\n float remainder = mod(float(ndp), 2.0);\\r\\n\\treturn !compareFloat(remainder, 0.0);\\r\\n}\\r\\n\\r\\nint numberOfOnes(int number, int index){\\r\\n\\tint numOnes = 0;\\r\\n\\tint tmp = 128;\\r\\n\\tfor(int i = 7; i >= 0; i--){\\r\\n\\t\\tif(number >= tmp){\\r\\n\\t\\t\\tnumber = number - tmp;\\r\\n\\t\\t\\tif(i <= index){\\r\\n\\t\\t\\t\\tnumOnes++;\\r\\n\\t\\t\\t}\\r\\n\\t\\t}\\r\\n\\t\\ttmp = tmp / 2;\\r\\n\\t}\\r\\n\\treturn numOnes;\\r\\n}\\r\\n\\r\\nint getChildIndexPotree(vec3 index3d) {\\r\\n return roundFloat((4.0 * index3d.x) + (2.0 * index3d.y) + index3d.z);\\r\\n}\\r\\n\\r\\nint getChildIndexEncompass(vec3 index3d) {\\r\\n return roundFloat(index3d.x + (2.0 * index3d.y) + (4.0 * index3d.z));\\r\\n}\\r\\n\\r\\nfloat getLocalTreeDepth(vec3 positionOctree){\\r\\n int iOffset = 0;\\r\\n\\tfloat depth = 0.0;\\r\\n vec3 offset = vec3(0.0, 0.0, 0.0);\\r\\n\\r\\n\\tfor(float i = 0.0; i <= 30.0; i++) {\\r\\n\\t\\tfloat nodeSizeAtLevel = octreeSize / pow(2.0, i);\\r\\n\\r\\n vec3 index3d = (positionOctree - offset) / nodeSizeAtLevel;\\r\\n\\t\\tindex3d = floor(index3d + 0.5);\\r\\n int index = isPotreeCloud\\r\\n ? getChildIndexPotree(index3d)\\r\\n : getChildIndexEncompass(index3d);\\r\\n\\r\\n float x = float(iOffset) / float(VISIBLE_NODES_WIDTH);\\r\\n\\t\\tvec4 value = texture2D(visibleNodes, vec2(x, 0.0));\\r\\n int mask = int(round(value.r * 255.0));\\r\\n bool childExists = isBitSet(mask, index);\\r\\n\\r\\n if(childExists){\\r\\n\\t\\t\\t// There are more visible child nodes at this position\\r\\n\\t\\t\\tint advanceG = int(round(value.g * 255.0)) * 256;\\r\\n\\t\\t\\tint advanceB = int(round(value.b * 255.0));\\r\\n\\t\\t\\tint advanceChild = numberOfOnes(mask, index - 1);\\r\\n\\t\\t\\tint advance = advanceG + advanceB + advanceChild;\\r\\n\\t\\t\\tiOffset = iOffset + advance;\\r\\n\\t\\t\\tdepth++;\\r\\n\\t\\t} else {\\r\\n\\t\\t\\t// No more visible child nodes at this position\\r\\n\\t\\t\\tfloat lodOffset = (255.0 * value.a) / 10.0 - 10.0;\\r\\n\\t\\t\\treturn depth + lodOffset;\\r\\n\\t\\t}\\r\\n\\r\\n\\t\\toffset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;\\r\\n\\t}\\r\\n\\r\\n\\treturn depth;\\r\\n}\\r\\n\\r\\nfloat getPointSizeAttenuation(vec3 posWorld) {\\r\\n vec3 positionOctree = posWorld - octreeCorner;\\r\\n\\treturn pow(2.0, getLocalTreeDepth(positionOctree));\\r\\n}\\r\\n\\r\\nfloat getClipBoxData(int xIndex, int yIndex) {\\r\\n return unpackTextureData(\\r\\n clipPolygonData,\\r\\n xIndex,\\r\\n yIndex,\\r\\n CLIP_TEXTURE_WIDTH,\\r\\n CLIP_TEXTURE_HEIGHT\\r\\n );\\r\\n}\\r\\n\\r\\nfloat getAreaTriangleData(int xIndex, int yIndex) {\\r\\n return unpackTextureData(\\r\\n areaTriangleData,\\r\\n xIndex,\\r\\n yIndex,\\r\\n AREA_TEXTURE_WIDTH,\\r\\n AREA_TEXTURE_HEIGHT\\r\\n );\\r\\n}\\r\\n\\r\\n// Point in 2d triangle: https://stackoverflow.com/a/2049593\\r\\nfloat triangleSign(vec3 p1, vec3 p2, vec3 p3) {\\r\\n return (p1.x - p3.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p3.y);\\r\\n}\\r\\n\\r\\n// Point in 2d triangle: https://stackoverflow.com/a/2049593\\r\\nbool pointInTriangle(vec3 p1, vec3 p2, vec3 p3, vec3 p4) {\\r\\n float d1 = triangleSign(p4, p1, p2);\\r\\n float d2 = triangleSign(p4, p2, p3);\\r\\n float d3 = triangleSign(p4, p3, p1);\\r\\n\\r\\n bool isNegative = (d1 < 0.0) || (d2 < 0.0) || (d3 < 0.0);\\r\\n bool isPositive = (d1 > 0.0) || (d2 > 0.0) || (d3 > 0.0);\\r\\n bool insideTriangle = !(isNegative && isPositive);\\r\\n\\r\\n return insideTriangle;\\r\\n}\\r\\n\\r\\nvec2 checkPointInArea(vec3 point) {\\r\\n // return vec2(\\r\\n // float insidePolygon,\\r\\n // float volumeEnabled\\r\\n // )\\r\\n\\r\\n #if defined NUM_AREA_TRIANGLES\\r\\n for (int i=0; i 0.5;\\r\\n bool volumeCalculated = compareFloat(volumeStatus, 2.0);\\r\\n\\r\\n // vertex #1\\r\\n vec3 v1 = vec3(\\r\\n getAreaTriangleData(i, 1),\\r\\n getAreaTriangleData(i, 2),\\r\\n getAreaTriangleData(i, 3)\\r\\n );\\r\\n\\r\\n // vertex #2\\r\\n vec3 v2 = vec3(\\r\\n getAreaTriangleData(i, 4),\\r\\n getAreaTriangleData(i, 5),\\r\\n getAreaTriangleData(i, 6)\\r\\n );\\r\\n\\r\\n // vertex #3\\r\\n vec3 v3 = vec3(\\r\\n getAreaTriangleData(i, 7),\\r\\n getAreaTriangleData(i, 8),\\r\\n getAreaTriangleData(i, 9)\\r\\n );\\r\\n\\r\\n vec3 N = cross(v2 - v1, v3 - v1);\\r\\n N = N / length(N);\\r\\n\\r\\n vec3 v1p = v1;\\r\\n vec3 v2p = v2;\\r\\n vec3 v3p = v3;\\r\\n vec3 pointP = point;\\r\\n\\r\\n if (isVolumeType == false) {\\r\\n // Check distance from plane\\r\\n float pointHeight = distanceFromPlane(v1, point, N);\\r\\n if (pointHeight > DISTANCE_FROM_PLANE) {\\r\\n continue;\\r\\n }\\r\\n\\r\\n // Project point to plane\\r\\n v1p = pointOnPlane(v1, v1, N);\\r\\n v2p = pointOnPlane(v1, v2, N);\\r\\n v3p = pointOnPlane(v1, v3, N);\\r\\n pointP = pointOnPlane(v1, point, N);\\r\\n }\\r\\n\\r\\n bool insideTriangle = pointInTriangle(v1p, v2p, v3p, pointP);\\r\\n if (insideTriangle == false) {\\r\\n continue;\\r\\n }\\r\\n\\r\\n if (volumeCalculated) {\\r\\n return vec2(1.0, 1.0);\\r\\n } else {\\r\\n return vec2(1.0, 0.0);\\r\\n }\\r\\n }\\r\\n #endif\\r\\n\\r\\n return vec2(0.0, 0.0);\\r\\n}\\r\\n\\r\\nvec4 checkPointInBox(vec3 point, float classification) {\\r\\n bool insideBox = false;\\r\\n bool newVisibility = true;\\r\\n bool reclassifyPoints = false;\\r\\n float finalClassification = -1.0;\\r\\n\\r\\n #if defined NUM_CLIP_BOXES\\r\\n for (int i=0; i 0.0);\\r\\n}\\r\\n\\r\\nbool pointInCrossSection(vec3 point) {\\r\\n vec3 p1 = crossSectionStart;\\r\\n vec3 p2 = crossSectionEnd;\\r\\n vec3 p3 = point;\\r\\n\\r\\n // force everything to 2d\\r\\n p1.z = 0.0;\\r\\n p2.z = 0.0;\\r\\n p3.z = 0.0;\\r\\n\\r\\n float lineLength = length(p1 - p2);\\r\\n if (compareFloat(lineLength, 0.0)) {\\r\\n return false;\\r\\n }\\r\\n\\r\\n // calculate distance from line\\r\\n float p1p3x = p1.x - p3.x;\\r\\n float p1p3y = p1.y - p3.y;\\r\\n float p2p1x = p2.x - p1.x;\\r\\n float p2p1y = p2.y - p1.y;\\r\\n float dAcrossAxis = abs(p2p1x*p1p3y - p1p3x*p2p1y) / lineLength;\\r\\n\\r\\n // calculate signed distance along line\\r\\n float dHypotenuse = length(p1 - p3);\\r\\n float dAlongAxis = sqrt(dHypotenuse*dHypotenuse - dAcrossAxis*dAcrossAxis);\\r\\n bool infront = isInFront(p1, p2, p3);\\r\\n if (infront == false) {\\r\\n dAlongAxis = -1.0 * dAlongAxis;\\r\\n }\\r\\n\\r\\n return (dAlongAxis >= 0.0)\\r\\n && (dAlongAxis <= lineLength)\\r\\n && (dAcrossAxis < (crossSectionWidth/2.0));\\r\\n}\\r\\n\\r\\nvoid main() {\\r\\n // Update colors for GPU picker\\r\\n updateGPUPickerColors();\\r\\n\\r\\n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\\r\\n vec3 viewPosition = -mvPosition.xyz;\\r\\n gl_Position = projectionMatrix * mvPosition;\\r\\n\\r\\n // Position in viewer coordinates (including offset)\\r\\n\\tvec3 posWorld = (modelMatrix * vec4( position, 1.0 )).xyz;\\r\\n\\r\\n // Hide based on draw distance\\r\\n if (outsideBounds(posWorld, drawDistance)) {\\r\\n vHidden = boolToFloat(true);\\r\\n return;\\r\\n }\\r\\n\\r\\n // Check if classification is hidden\\r\\n if (classificationIsHidden(classification)) {\\r\\n vHidden = boolToFloat(true);\\r\\n return;\\r\\n }\\r\\n\\r\\n // ---------------------\\r\\n\\t// POINT SIZE\\r\\n\\t// ---------------------\\r\\n float pointSize = 1.0;\\r\\n float projFactor = getProjFactor(fov, screenHeight, viewPosition.z);\\r\\n float r = octreeSpacing * sqrt(3.0);\\r\\n\\r\\n if (isOctreeCloud && adaptiveSize) {\\r\\n // Adaptive point sizing\\r\\n float pointAttenuation = getPointSizeAttenuation(posWorld);\\r\\n float worldSpaceSize = size * (r / pointAttenuation);\\r\\n pointSize = 1.0 * worldSpaceSize * projFactor;\\r\\n } else {\\r\\n // Attenuated point size\\r\\n pointSize = 0.15 * size * projFactor;\\r\\n }\\r\\n\\r\\n pointSize = max(minSize, pointSize);\\r\\n pointSize = min(maxSize, pointSize);\\r\\n\\r\\n // ---------------------\\r\\n\\t// POINT COLOR\\r\\n\\t// ---------------------\\r\\n vColor = getCloudColor(colorType, posWorld);\\r\\n\\r\\n // ---------------------\\r\\n // CROSS SECTION\\r\\n // ---------------------\\r\\n bool inCrossSection = pointInCrossSection(posWorld.xyz);\\r\\n\\r\\n // ---------------------\\r\\n // MEASUREMENT AREA/VOLUME\\r\\n // ---------------------\\r\\n vec2 areaReturnValue = checkPointInArea(posWorld.xyz);\\r\\n bool insidePolygon = floatToBool(areaReturnValue.x);\\r\\n bool volumeEnabled = floatToBool(areaReturnValue.y);\\r\\n\\r\\n // ---------------------\\r\\n // CLIPPING BOXES\\r\\n // ---------------------\\r\\n vec4 clipReturnValue = checkPointInBox(posWorld.xyz, classification);\\r\\n bool insideClip = floatToBool(clipReturnValue.x);\\r\\n bool clipVisible = floatToBool(clipReturnValue.y);\\r\\n bool reclassify = floatToBool(clipReturnValue.z);\\r\\n float newClassification = clipReturnValue.w;\\r\\n\\r\\n if (inCrossSection || insidePolygon || insideClip) {\\r\\n vColor = calculateOppositeColor(colorType, vColor);\\r\\n }\\r\\n\\r\\n // Delete points\\r\\n if (!clipVisible) {\\r\\n vHidden = boolToFloat(true);\\r\\n return;\\r\\n }\\r\\n\\r\\n // Reclassify points\\r\\n if (insideClip && reclassify) {\\r\\n vColor = classificationColor(newClassification);\\r\\n }\\r\\n\\r\\n // Reduce point size if volume is calculated\\r\\n if (volumeEnabled) {\\r\\n pointSize = pointSize * 0.5;\\r\\n }\\r\\n\\r\\n if (gpuPicker) {\\r\\n // gpu picker points are 10% larger than normal\\r\\n pointSize = pointSize * 1.10;\\r\\n }\\r\\n\\r\\n // Set OpenGL parameters\\r\\n vHidden = boolToFloat(false);\\r\\n gl_PointSize = pointSize;\\r\\n}\";","export default \"#define PRECISION 0.0001\\r\\n\\r\\nuniform bool gpuPicker;\\r\\nuniform bool circularPoints;\\r\\n\\r\\nflat varying vec3 vColor;\\r\\nflat varying float vHidden;\\r\\n\\r\\nvoid main(void) {\\r\\n bool isHidden = floatToBool(vHidden);\\r\\n if (isHidden) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n // Circular points\\r\\n if (circularPoints) {\\r\\n float u = 2.0 * gl_PointCoord.x - 1.0;\\r\\n float v = 2.0 * gl_PointCoord.y - 1.0;\\r\\n float cc = u*u + v*v;\\r\\n if(cc > 1.0){\\r\\n discard;\\r\\n }\\r\\n }\\r\\n\\r\\n vec4 final;\\r\\n if (gpuPicker) {\\r\\n final = vGPUColor;\\r\\n } else {\\r\\n final = vec4(vColor, 1.0);\\r\\n }\\r\\n\\r\\n gl_FragColor = final;\\r\\n}\";","export default \"varying vec3 vPosition;\\r\\n\\r\\nvoid main() {\\r\\n vPosition = position;\\r\\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\r\\n}\\r\\n\";","export default \"#define RECIPROCAL_PI 0.3183098861837907\\r\\n#define RECIPROCAL_PI2 0.15915494309189535\\r\\n\\r\\nuniform sampler2D tImage;\\r\\nvarying vec3 vPosition;\\r\\n\\r\\nvec2 getPixelCoords( in vec3 dir ) {\\r\\n\\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\\r\\n\\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\\r\\n\\treturn vec2( u, v );\\r\\n}\\r\\n\\r\\nvoid main() {\\r\\n\\tvec3 direction = vec3(vPosition.x, vPosition.z, -vPosition.y);\\r\\n direction = normalize(direction);\\r\\n\\r\\n vec2 sampleUV = getPixelCoords( direction );\\r\\n gl_FragColor = texture2D( tImage, sampleUV );\\r\\n}\\r\\n\";","export default \"varying vec3 vPosition;\\r\\n\\r\\nvoid main() {\\r\\n vPosition = position;\\r\\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\r\\n}\\r\\n\";","export default \"uniform sampler2D tImage;\\r\\nuniform float imageHeight;\\r\\nuniform float imageWidth;\\r\\nuniform float fx;\\r\\nuniform float fy;\\r\\nuniform float cx;\\r\\nuniform float cy;\\r\\n\\r\\nvarying vec3 vPosition;\\r\\n\\r\\nvec2 getPixelCoords( vec3 direction, float dist ) {\\r\\n vec3 vec = direction / dist;\\r\\n float u = ((vec.x * fx) + cx) / imageWidth;\\r\\n float v = ((-vec.y * fy) + cy) / imageHeight;\\r\\n return vec2(u, 1.0 - v);\\r\\n}\\r\\n\\r\\nvoid main() {\\r\\n vec3 direction = normalize(vPosition);\\r\\n float dist = -direction.z;\\r\\n\\r\\n // Image is behind us\\r\\n if (dist <= 0.0) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n vec2 sampleUV = getPixelCoords( direction, dist );\\r\\n\\r\\n bool outOfBounds = (sampleUV.x < 0.0)\\r\\n || (sampleUV.x >= 1.0)\\r\\n || (sampleUV.y <= 0.0)\\r\\n || (sampleUV.y > 1.0);\\r\\n\\r\\n if (outOfBounds) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n gl_FragColor = texture2D(tImage, sampleUV);\\r\\n}\\r\\n\";","export default \"uniform float drawDistance;\\r\\n\\r\\nvarying vec3 vWorldPosition;\\r\\n\\r\\nvoid main() {\\r\\n // Update colors for GPU picker\\r\\n updateGPUPickerColors();\\r\\n\\r\\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\r\\n vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\\r\\n}\\r\\n\";","export default \"uniform bool gpuPicker;\\r\\nuniform vec3 color;\\r\\nuniform float drawDistance;\\r\\n\\r\\nvarying vec3 vWorldPosition;\\r\\n\\r\\nvoid main() {\\r\\n // Hide based on draw distance\\r\\n if (outsideBounds(vWorldPosition, drawDistance)) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n if (gpuPicker) {\\r\\n gl_FragColor = vGPUColor;\\r\\n } else {\\r\\n gl_FragColor = vec4(color, 1.0);\\r\\n }\\r\\n}\\r\\n\";","export default \"uniform float screenHeight;\\r\\nuniform float fov;\\r\\nuniform float size;\\r\\nuniform bool gpuPicker;\\r\\nuniform float drawDistance;\\r\\n\\r\\nvarying float vHidden;\\r\\n\\r\\nvoid main() {\\r\\n // Update colors for GPU picker\\r\\n updateGPUPickerColors();\\r\\n\\r\\n vHidden = boolToFloat(false);\\r\\n\\r\\n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\\r\\n vec3 viewPosition = -mvPosition.xyz;\\r\\n gl_Position = projectionMatrix * mvPosition;\\r\\n\\r\\n // Hide based on draw distance\\r\\n vec3 worldPosition = (modelMatrix * vec4(position, 1.0)).xyz;\\r\\n if (outsideBounds(worldPosition, drawDistance)) {\\r\\n vHidden = boolToFloat(true);\\r\\n return;\\r\\n }\\r\\n\\r\\n float projFactor = getProjFactor(fov, screenHeight, viewPosition.z);\\r\\n float spriteSize = size * projFactor;\\r\\n gl_PointSize = spriteSize;\\r\\n}\\r\\n\";","export default \"uniform sampler2D imageTexture;\\r\\nuniform bool gpuPicker;\\r\\nuniform vec3 color;\\r\\n\\r\\nvarying float vHidden;\\r\\n\\r\\nvoid main() {\\r\\n bool isHidden = floatToBool(vHidden);\\r\\n if (isHidden) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n vec2 uv = vec2(gl_PointCoord.x, 1.0 - gl_PointCoord.y);\\r\\n vec4 textureColor = texture2D(imageTexture, uv);\\r\\n if (textureColor.a < ALPHA_PRECISION) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n if (gpuPicker) {\\r\\n gl_FragColor = vGPUColor;\\r\\n } else {\\r\\n vec3 finalColor = textureColor.xyz * color;\\r\\n gl_FragColor = vec4(finalColor, 1.0);\\r\\n }\\r\\n}\\r\\n\";","export default \"#include \\r\\n#define PRECISION 0.0001\\r\\n\\r\\nuniform sampler2D tImage;\\r\\nuniform sampler2D tDepth;\\r\\n\\r\\nuniform float opacity;\\r\\nuniform float screenWidth;\\r\\nuniform float screenHeight;\\r\\nuniform float near;\\r\\nuniform float far;\\r\\nuniform vec2 neighbours[NEIGHBOUR_COUNT];\\r\\nuniform vec3 lightDir;\\r\\nuniform float edlStrength;\\r\\nuniform float radius;\\r\\n\\r\\nvarying vec2 vUv;\\r\\n\\r\\nfloat linearDepth(sampler2D depthSampler, vec2 coord) {\\r\\n float z_b = texture2D(depthSampler, coord).x;\\r\\n float z_n = 2.0 * z_b - 1.0;\\r\\n float z_e = 2.0 * near * far / (far + near - z_n * (far - near));\\r\\n return z_e;\\r\\n}\\r\\n\\r\\nfloat readDepth(sampler2D depthSampler, vec2 coord) {\\r\\n float depth = log2(linearDepth(depthSampler, coord));\\r\\n return (depth == 1.0) ? 0.0 : depth;\\r\\n}\\r\\n\\r\\nfloat response(float depth){\\r\\n\\tvec2 uvRadius = radius / vec2(screenWidth, screenHeight);\\r\\n\\r\\n\\tfloat sum = 0.0;\\r\\n\\tfor(int i = 0; i < NEIGHBOUR_COUNT; i++){\\r\\n\\t\\tvec2 uvNeighbor = vUv + uvRadius * neighbours[i];\\r\\n\\t\\tfloat neighbourDepth = readDepth(tDepth, uvNeighbor);\\r\\n\\r\\n\\t\\tif(neighbourDepth != 0.0){\\r\\n if (depth == 0.0) {\\r\\n sum += 100.0;\\r\\n } else{\\r\\n sum += max(0.0, depth - neighbourDepth);\\r\\n }\\r\\n\\t\\t}\\r\\n\\t}\\r\\n\\r\\n\\treturn sum / float(NEIGHBOUR_COUNT);\\r\\n}\\r\\n\\r\\nvoid main() {\\r\\n vec4 color = texture2D(tImage, vUv);\\r\\n float alpha = color.a * opacity;\\r\\n\\r\\n float depth = readDepth(tDepth, vUv);\\r\\n float res = response(depth);\\r\\n\\tfloat shade = exp(-res * 10.0 * edlStrength);\\r\\n\\r\\n if (color.a <= PRECISION) {\\r\\n if (res <= PRECISION) discard;\\r\\n alpha = opacity;\\r\\n }\\r\\n\\r\\n gl_FragColor = vec4(color.rgb*shade, alpha);\\r\\n}\\r\\n\";","export default \"#define BORDER_SIZE 3.0\\r\\n\\r\\nuniform sampler2D tCurrent;\\r\\nuniform sampler2D tPrevious;\\r\\nuniform bool zooming;\\r\\nuniform float zoomRadius;\\r\\nuniform float progress;\\r\\nuniform float screenWidth;\\r\\nuniform float screenHeight;\\r\\nuniform int transition;\\r\\nuniform vec2 mousePosition;\\r\\n\\r\\nvarying vec2 vUv;\\r\\n\\r\\nvec4 getToColor(vec2 uv) {\\r\\n return texture2D(tCurrent, uv);\\r\\n}\\r\\n\\r\\nvec4 getFromColor(vec2 uv) {\\r\\n return texture2D(tPrevious, uv);\\r\\n}\\r\\n\\r\\n/** https://gl-transitions.com/editor/circleopen **/\\r\\nvec4 transitionCircleOpen(vec2 uv) {\\r\\n float smoothness = 0.75;\\r\\n bool opening = true;\\r\\n vec2 center = vec2(0.5, 0.5);\\r\\n float SQRT_2 = 1.414213562373;\\r\\n\\r\\n float x = opening ? progress : 1.-progress;\\r\\n float m = smoothstep(-smoothness, 0.0, SQRT_2*distance(center, uv) - x*(1.+smoothness));\\r\\n return mix(getFromColor(uv), getToColor(uv), opening ? 1.-m : m);\\r\\n}\\r\\n\\r\\n/** https://gl-transitions.com/editor/LinearBlur **/\\r\\nvec4 transitionLinearBlur(vec2 uv) {\\r\\n float intensity = 0.01;\\r\\n int passes = 6;\\r\\n\\r\\n vec4 c1 = vec4(0.0);\\r\\n vec4 c2 = vec4(0.0);\\r\\n\\r\\n float disp = intensity*(0.5-distance(0.5, progress));\\r\\n for (int xi=0; xi circle_bounds){\\r\\n discard;\\r\\n }\\r\\n\\r\\n if (!gpuPicker) {\\r\\n // Black outline\\r\\n float edge = circle_bounds - border_thickness;\\r\\n if ((circle <= circle_bounds) && (circle > edge)){\\r\\n final.rgb = vec3(0.0, 0.0, 0.0);\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n // Square with rounded corners\\r\\n if (isSquare) {\\r\\n float circle = sqrt(uv.x * uv.x + uv.y * uv.y);\\r\\n float circle_bounds = sqrt(2.0) * 0.95;\\r\\n if (circle > circle_bounds){\\r\\n discard;\\r\\n }\\r\\n\\r\\n if (!gpuPicker) {\\r\\n // Black outline\\r\\n float edge1 = circle_bounds - border_thickness;\\r\\n float edge2 = 1.0 - border_thickness;\\r\\n if ((circle > edge1) || (abs(uv.x) > edge2) || (abs(uv.y) > edge2)) {\\r\\n final.rgb = vec3(0.0, 0.0, 0.0);\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n if (!gpuPicker) {\\r\\n if (final.a < PRECISION) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n final.a = 1.0;\\r\\n }\\r\\n\\r\\n gl_FragColor = final;\\r\\n}\\r\\n\";","export default \"#define PRECISION 0.0001\\r\\n#define ALPHA_PRECISION 0.5\\r\\n\\r\\n/** https://github.com/Experience-Monks/glsl-fast-gaussian-blur/blob/master/5.glsl */\\r\\nvec4 blur5(sampler2D image, vec2 uv, vec2 resolution, vec2 direction) {\\r\\n vec4 color = vec4(0.0);\\r\\n vec2 off1 = vec2(1.3333333333333333) * direction;\\r\\n color += texture2D(image, uv) * 0.29411764705882354;\\r\\n color += texture2D(image, uv + (off1 / resolution)) * 0.35294117647058826;\\r\\n color += texture2D(image, uv - (off1 / resolution)) * 0.35294117647058826;\\r\\n return color;\\r\\n}\\r\\n\\r\\nfloat getProjFactor(float fov, float screenHeight, float distance) {\\r\\n float projFactor = 1.0 / tan(fov / 2.0);\\r\\n projFactor /= distance;\\r\\n projFactor *= screenHeight / 2.0;\\r\\n return projFactor;\\r\\n}\\r\\n\\r\\nbool compareFloat(float floatOne, float floatTwo) {\\r\\n return abs(floatOne - floatTwo) < PRECISION;\\r\\n}\\r\\n\\r\\nbool floatToBool(float value) {\\r\\n return value > 0.5;\\r\\n}\\r\\n\\r\\nfloat boolToFloat(bool value) {\\r\\n if (value) {\\r\\n return 1.0;\\r\\n } else {\\r\\n return 0.0;\\r\\n }\\r\\n}\\r\\n\\r\\nmat3 rotateX(float theta) {\\r\\n float c = cos(theta);\\r\\n float s = sin(theta);\\r\\n return mat3(\\r\\n vec3(1, 0, 0),\\r\\n vec3(0, c, -s),\\r\\n vec3(0, s, c)\\r\\n );\\r\\n}\\r\\n\\r\\nmat3 rotateY(float theta) {\\r\\n float c = cos(theta);\\r\\n float s = sin(theta);\\r\\n return mat3(\\r\\n vec3(c, 0, s),\\r\\n vec3(0, 1, 0),\\r\\n vec3(-s, 0, c)\\r\\n );\\r\\n}\\r\\n\\r\\nmat3 rotateZ(float theta) {\\r\\n float c = cos(theta);\\r\\n float s = sin(theta);\\r\\n return mat3(\\r\\n vec3(c, -s, 0),\\r\\n vec3(s, c, 0),\\r\\n vec3(0, 0, 1)\\r\\n );\\r\\n}\\r\\n\\r\\nmat3 eulerMatrix(vec3 rotation) {\\r\\n mat3 rotX = rotateX(rotation.x);\\r\\n mat3 rotY = rotateY(rotation.y);\\r\\n mat3 rotZ = rotateZ(rotation.z);\\r\\n\\r\\n return rotZ * rotY * rotX;\\r\\n}\\r\\n\\r\\nmat3 scaleMatrix(float scale) {\\r\\n return mat3(\\r\\n vec3(scale, 0.0, 0.0),\\r\\n vec3(0.0, scale, 0.0),\\r\\n vec3(0.0, 0.0, scale)\\r\\n );\\r\\n}\\r\\n\\r\\nfloat getDistance2D(vec3 positionA, vec3 positionB) {\\r\\n float dX = positionA.x - positionB.x;\\r\\n float dY = positionA.y - positionB.y;\\r\\n return sqrt(dX*dX + dY*dY);\\r\\n}\\r\\n\\r\\nfloat getDistance3D(vec3 positionA, vec3 positionB) {\\r\\n float dX = positionA.x - positionB.x;\\r\\n float dY = positionA.y - positionB.y;\\r\\n float dZ = positionA.z - positionB.z;\\r\\n return sqrt(dX*dX + dY*dY + dZ*dZ);\\r\\n}\\r\\n\\r\\nbool outsideBounds(vec3 offset, float drawDistance) {\\r\\n float dist = getDistance2D(offset, cameraPosition);\\r\\n return dist > drawDistance;\\r\\n}\";","export default \"void main() {\\r\\n updateGPUPickerColors();\\r\\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\r\\n}\\r\\n\";","export default \"void main() {\\r\\n gl_FragColor = vGPUColor;\\r\\n}\\r\\n\";","export default \"#define COLOR_PRECISION 0.05\\r\\n\\r\\nattribute int gpu_index;\\r\\n\\r\\nflat varying vec4 vGPUColor;\\r\\n\\r\\nvoid updateGPUPickerColors() {\\r\\n vec4 encoded_index = vec4(\\r\\n float(gpu_index >> 24 & 255),\\r\\n float(gpu_index >> 16 & 255),\\r\\n float(gpu_index >> 8 & 255),\\r\\n float(gpu_index & 255)\\r\\n );\\r\\n\\r\\n vGPUColor = (encoded_index + COLOR_PRECISION) / 255.0;\\r\\n}\\r\\n\";","export default \"flat varying vec4 vGPUColor;\";","export default \"float unpackTextureData(sampler2D data_texture, int xIndex, int yIndex, int width, int height) {\\r\\n float u = (float(xIndex) + 0.5) /float(width);\\r\\n float v = (float(yIndex) + 0.5) /float(height);\\r\\n\\r\\n vec4 data = texture2D(data_texture, vec2(u, v));\\r\\n\\r\\n int unpacked = (int(data.r*255.0) << 24)\\r\\n + (int(data.g*255.0) << 16)\\r\\n + (int(data.b*255.0) << 8)\\r\\n + int(data.a*255.0);\\r\\n\\r\\n return float(unpacked) * PACKED_TEXTURE_SCALE;\\r\\n}\\r\\n\";","export default \"#define MIN_CAMERA_DIST 0.5\\r\\n\\r\\nattribute float selected;\\r\\nattribute float hovering;\\r\\n\\r\\nuniform float scale;\\r\\nuniform float drawDistance;\\r\\nuniform vec3 cameraRotation;\\r\\nuniform float timeStamp;\\r\\nuniform float windowHeight;\\r\\nuniform float fov;\\r\\nuniform float distance;\\r\\nuniform bool gpuPicker;\\r\\n\\r\\nvarying vec2 vUv;\\r\\nvarying float vHidden;\\r\\n\\r\\nvoid main() {\\r\\n updateGPUPickerColors();\\r\\n vUv = uv;\\r\\n\\r\\n float hoverScale = 0.8;\\r\\n bool isHovering = compareFloat(hovering, 1.0);\\r\\n bool isSelected = compareFloat(selected, 1.0);\\r\\n\\r\\n if (isHovering) {\\r\\n hoverScale = 1.0;\\r\\n }\\r\\n\\r\\n float x = position.x - (uv.x - 0.5);\\r\\n float y = position.y - (uv.y - 0.5);\\r\\n float z = position.z;\\r\\n vec3 posWorld = vec3(x, y, z);\\r\\n\\r\\n // Hide based on draw distance\\r\\n if (outsideBounds(posWorld, drawDistance)) {\\r\\n vHidden = boolToFloat(true);\\r\\n return;\\r\\n }\\r\\n\\r\\n // Resize based on distance (3D)\\r\\n float distance3D = getDistance3D(posWorld, cameraPosition);\\r\\n float projFactor = getProjFactor(fov, windowHeight, distance3D);\\r\\n float tagSize = 30.0 / projFactor;\\r\\n\\r\\n tagSize = clamp(tagSize, 1.0, 10.0);\\r\\n tagSize *= scale;\\r\\n\\r\\n // Move position to center of marker\\r\\n vec3 posOffset = position - posWorld;\\r\\n\\r\\n // Rotate using camera rotation\\r\\n mat3 rot = eulerMatrix(cameraRotation);\\r\\n vec3 posRotated = posOffset * rot;\\r\\n\\r\\n mat3 scaleMatrix = scaleMatrix(tagSize * hoverScale);\\r\\n vec3 posScaled = posRotated * scaleMatrix;\\r\\n\\r\\n // Add back our offset values\\r\\n vec3 posFinal = posScaled + posWorld;\\r\\n\\r\\n // Add height based on tag size\\r\\n posFinal.z += (0.5 * tagSize);\\r\\n\\r\\n if (!gpuPicker && isSelected) {\\r\\n if (timeStamp > 500.0) {\\r\\n vHidden = boolToFloat(true);\\r\\n return;\\r\\n }\\r\\n }\\r\\n\\r\\n vHidden = boolToFloat(false);\\r\\n gl_Position = projectionMatrix * modelViewMatrix * vec4(posFinal, 1.0);\\r\\n}\";","export default \"uniform sampler2D imageTexture;\\r\\nuniform bool gpuPicker;\\r\\n\\r\\nvarying vec2 vUv;\\r\\nvarying float vHidden;\\r\\nvarying float vVisible;\\r\\n\\r\\nvoid main() {\\r\\n bool isHidden = floatToBool(vHidden);\\r\\n if (isHidden) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n vec4 color = texture2D(imageTexture, vUv);\\r\\n if (color.a < ALPHA_PRECISION) {\\r\\n discard;\\r\\n }\\r\\n\\r\\n if (gpuPicker) {\\r\\n gl_FragColor = vGPUColor;\\r\\n } else {\\r\\n gl_FragColor = vec4(color.rgb, 1.0);\\r\\n }\\r\\n}\";","import {classificationTexture} from '../classifications';\r\nimport shaders from '../shaders';\r\nimport { getColorMap } from '../textures/colormaps';\r\nimport {Viewer} from \"../main\";\r\nimport {numberOfClassifications} from \"../../classifications\";\r\nimport {\r\n Color,\r\n DataTexture,\r\n NearestFilter,\r\n DoubleSide,\r\n RGBAFormat,\r\n RGBFormat,\r\n ShaderMaterial,\r\n Uniform,\r\n Vector2,\r\n Vector3,\r\n TextureLoader,\r\n Texture,\r\n MeshLambertMaterial,\r\n MeshLambertMaterialParameters,\r\n} from \"three\";\r\nimport { getTagTexturePath } from '../textures/tag-icons';\r\nimport { PlanarConfig } from '../../redux/assets-slice';\r\n\r\nconst packedTextureScale = 0.00025;\r\n\r\nexport const assignPackedData = (texture, xIndex, yIndex, value) => {\r\n if (typeof value == \"boolean\") {\r\n value = value ? 1.0 : 0.0;\r\n }\r\n\r\n const valueInt = Math.floor(value / packedTextureScale);\r\n let data = texture.image.data;\r\n let height = texture.image.height;\r\n let width = texture.image.width;\r\n let channels = texture.image.data.length / (width*height);\r\n let index = channels*(xIndex + yIndex*width);\r\n\r\n data[index + 0] = (valueInt >> 24) & 255;\r\n data[index + 1] = (valueInt >> 16) & 255;\r\n data[index + 2] = (valueInt >> 8) & 255;\r\n data[index + 3] = (valueInt) & 255;\r\n};\r\n\r\nconst generateDataTexture = (width: number, height: number, channels, color: Color = new Color(0xffffff)) => {\r\n let size = width * height;\r\n let data = new Uint8Array(channels * width * height);\r\n\r\n let r = Math.floor(color.r * 255);\r\n let g = Math.floor(color.g * 255);\r\n let b = Math.floor(color.b * 255);\r\n\r\n for (let i = 0; i < size; i++) {\r\n data[i * channels] = r;\r\n data[i * channels + 1] = g;\r\n data[i * channels + 2] = b;\r\n\r\n if (channels === 4) {\r\n data[i * channels + 3] = 255;\r\n }\r\n }\r\n\r\n let format = channels === 3 ? RGBFormat : RGBAFormat;\r\n let texture = new DataTexture(data, width, height, format);\r\n texture.minFilter = NearestFilter;\r\n texture.magFilter = NearestFilter;\r\n texture.needsUpdate = true;\r\n\r\n return texture;\r\n};\r\n\r\nexport interface PointCloudMaterialParams {\r\n minSize: number\r\n maxSize: number\r\n heightClamp: Vector2\r\n intensityClamp: Vector2\r\n dynamicSize: boolean\r\n circularPoints: boolean\r\n colorType: number\r\n size: number\r\n colorMap: string\r\n classifications: {[id: string]: boolean}\r\n}\r\n\r\nexport interface LineworkSpriteParams {\r\n map: Texture;\r\n size: number;\r\n color: Color;\r\n}\r\n\r\n/** Shader Materials */\r\n\r\nexport class BaseMaterial extends ShaderMaterial {\r\n constructor() {\r\n super();\r\n }\r\n\r\n updateValues(parameters) {\r\n for (const key in parameters) {\r\n this[key] = parameters[key];\r\n }\r\n }\r\n\r\n initProperties() {\r\n let keys = Object.keys(this.uniforms);\r\n keys.forEach(key => {\r\n this.defineProperty(key);\r\n });\r\n }\r\n\r\n defineProperty(key) {\r\n Object.defineProperty(this, key, {\r\n get: () => {\r\n return (this.uniforms[key].value);\r\n },\r\n set: value => {\r\n this.uniforms[key].value = value;\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport class PointCloudMaterial extends BaseMaterial {\r\n public gpuPicker;\r\n public size;\r\n public minSize;\r\n public distance;\r\n public colorMap;\r\n public colorType;\r\n public adaptiveSize;\r\n public circularPoints;\r\n public isOctreeCloud: boolean;\r\n public isPotreeCloud: boolean;\r\n public drawDistance: number;\r\n public screenHeight: number;\r\n public screenwidth: number;\r\n public fov: number;\r\n public octreeSpacing;\r\n public octreeSize: number;\r\n public octreeCorner: Vector3;\r\n public intensityRange: Vector2;\r\n public rgbMax: number;\r\n public heightRange: Vector2;\r\n public classificationVisible;\r\n\r\n private visibleClassTexture: DataTexture;\r\n\r\n public crossSectionWidth: number;\r\n public crossSectionStart: Vector3;\r\n public crossSectionEnd: Vector3;\r\n\r\n public clipBoxTexture: DataTexture;\r\n public areaTriangleTexture: DataTexture;\r\n public visibleNodesTexture: DataTexture;\r\n\r\n public numClippingBoxes = 0;\r\n public numAreaTriangles = 0;\r\n\r\n constructor(viewer: Viewer, parameters: PointCloudMaterialParams, gpuPicker: boolean) {\r\n super();\r\n\r\n this.gpuPicker = gpuPicker;\r\n\r\n // Node depth texture for dynamic sizing\r\n const visibleNodesWidth = 2048;\r\n const visibleNodesHeight = 1;\r\n this.visibleNodesTexture = generateDataTexture(\r\n visibleNodesWidth, visibleNodesHeight, 4);\r\n\r\n // Clip polygon texture (4 attribute + 3x3 coordinates)\r\n const clipTextureWidth = 1024;\r\n const clipTextureHeight = 4 + 9;\r\n this.clipBoxTexture = generateDataTexture(\r\n clipTextureWidth, clipTextureHeight, 4);\r\n\r\n // Area/volume texture (1 attribute + 3x3 coordinates)\r\n const areaTextureWidth = 1024;\r\n const areaTextureHeight = 1 + 9;\r\n this.areaTriangleTexture = generateDataTexture(\r\n areaTextureWidth, areaTextureHeight, 4);\r\n\r\n // Load initial colormap texture\r\n const loader = new TextureLoader();\r\n const image = getColorMap(parameters.colorMap).image;\r\n const colorMapTexture = loader.load(image);\r\n\r\n // Generate classification visibility array\r\n this.visibleClassTexture = generateDataTexture(\r\n numberOfClassifications, 1, 4);\r\n\r\n this.updateVisibleClassifications(parameters);\r\n\r\n let uniforms = {\r\n gpuPicker: new Uniform(gpuPicker),\r\n circularPoints: new Uniform(parameters.circularPoints),\r\n depth: new Uniform(1.0),\r\n size: new Uniform(parameters.size),\r\n minSize: new Uniform(parameters.minSize),\r\n maxSize: new Uniform(parameters.maxSize),\r\n fov: new Uniform(viewer.camera.fov * Math.PI / 180.0),\r\n screenHeight: new Uniform(viewer.height),\r\n screenwidth: new Uniform(viewer.width),\r\n octreeSize: new Uniform(0.0),\r\n octreeSpacing: new Uniform(0.0),\r\n octreeCorner: new Uniform(new Vector3()),\r\n colorType: new Uniform(parameters.colorType),\r\n heightRange: new Uniform(new Vector2(0, 1)),\r\n heightClamp: new Uniform(parameters.heightClamp),\r\n intensityRange: new Uniform(new Vector2(0, 1)),\r\n intensityClamp: new Uniform(parameters.intensityClamp),\r\n rgbMax: new Uniform(0),\r\n colorMap: new Uniform(colorMapTexture),\r\n adaptiveSize: new Uniform(parameters.dynamicSize),\r\n isOctreeCloud: new Uniform(false),\r\n isPotreeCloud: new Uniform(false),\r\n drawDistance: new Uniform(0),\r\n classificationData: new Uniform(classificationTexture),\r\n classificationVisible: new Uniform(this.visibleClassTexture),\r\n visibleNodes: new Uniform(this.visibleNodesTexture),\r\n areaTriangleData: new Uniform(this.areaTriangleTexture),\r\n clipPolygonData: new Uniform(this.clipBoxTexture),\r\n crossSectionWidth: new Uniform(0),\r\n crossSectionStart: new Uniform(new Vector3(0, 0, 0)),\r\n crossSectionEnd: new Uniform(new Vector3(0, 0, 0))\r\n };\r\n\r\n let defines = {\r\n NUMBER_OF_CLASSIFICATIONS: numberOfClassifications,\r\n CLIP_TEXTURE_WIDTH: clipTextureWidth,\r\n CLIP_TEXTURE_HEIGHT: clipTextureHeight,\r\n AREA_TEXTURE_WIDTH: areaTextureWidth,\r\n AREA_TEXTURE_HEIGHT: areaTextureHeight,\r\n VISIBLE_NODES_WIDTH: visibleNodesWidth,\r\n PACKED_TEXTURE_SCALE: packedTextureScale\r\n };\r\n\r\n let fragmentShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.frag,\r\n shaders.pointcloud.frag\r\n ].join(\"\\n\");\r\n\r\n let vertexShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.vert,\r\n shaders.texture_packer.vert,\r\n shaders.pointcloud.vert\r\n ].join(\"\\n\");\r\n\r\n this.setValues({\r\n defines,\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n vertexColors: true,\r\n transparent: true,\r\n depthWrite: true\r\n });\r\n\r\n this.initProperties();\r\n }\r\n\r\n updateVisibleClassifications(parameters: PointCloudMaterialParams) {\r\n let classifications = parameters.classifications;\r\n let texture = this.visibleClassTexture;\r\n let data = texture.image.data;\r\n\r\n Object.keys(classifications).forEach(id => {\r\n const visible = classifications[id];\r\n const index = parseInt(id) * 4 + 3;\r\n data[index] = visible ? 255 : 0;\r\n });\r\n\r\n texture.needsUpdate = true;\r\n }\r\n\r\n updateNumClippingBoxes(value) {\r\n if (value === this.numClippingBoxes) {\r\n return;\r\n }\r\n\r\n this.numClippingBoxes = value;\r\n\r\n if (value === 0) {\r\n delete this.defines.NUM_CLIP_BOXES;\r\n } else {\r\n this.defines.NUM_CLIP_BOXES = value;\r\n }\r\n\r\n this.needsUpdate = true;\r\n }\r\n\r\n updateNumAreaTriangles(value) {\r\n if (value === this.numAreaTriangles) {\r\n return;\r\n }\r\n\r\n this.numAreaTriangles = value;\r\n\r\n if (value === 0) {\r\n delete this.defines.NUM_AREA_TRIANGLES;\r\n } else {\r\n this.defines.NUM_AREA_TRIANGLES = value;\r\n }\r\n\r\n this.needsUpdate = true;\r\n }\r\n}\r\n\r\nexport class OutputRenderMaterial extends BaseMaterial {\r\n public tCurrent: Texture;\r\n public tPrevious: Texture;\r\n public progress: number;\r\n public transition: number;\r\n public screenWidth: number;\r\n public screenHeight: number;\r\n public zooming: boolean;\r\n public zoomRadius: number;\r\n public mousePosition: Vector2\r\n\r\n constructor(width: number, height: number) {\r\n super();\r\n\r\n const vertexShader = shaders.render_transition.vert;\r\n const fragmentShader = [\r\n shaders.utilities,\r\n shaders.render_transition.frag\r\n ].join(\"\\n\");\r\n\r\n let uniforms = {\r\n tCurrent: new Uniform(null),\r\n tPrevious: new Uniform(null),\r\n progress: new Uniform(1.0),\r\n transition: new Uniform(1),\r\n screenWidth: new Uniform(width),\r\n screenHeight: new Uniform(height),\r\n zooming: new Uniform(false),\r\n zoomRadius: new Uniform(0.3),\r\n mousePosition: new Uniform(new Vector2())\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n transparent: true\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class BasicRenderMaterial extends BaseMaterial {\r\n public tImage: Texture;\r\n public tDepth: Texture;\r\n public opacity = 1.0;\r\n\r\n constructor() {\r\n super();\r\n\r\n let vertexShader = shaders.render_basic.vert;\r\n let fragmentShader = shaders.render_basic.frag;\r\n\r\n let uniforms = {\r\n tImage: new Uniform(null),\r\n opacity: new Uniform(1.0)\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n transparent: true\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class EDLRenderMaterial extends BasicRenderMaterial {\r\n public screenWidth;\r\n public screenHeight;\r\n public edlStrength;\r\n public far;\r\n\r\n constructor(width, height, near, far, pixelRatio = 1.0) {\r\n super();\r\n\r\n let vertexShader = shaders.render_edl.vert;\r\n let fragmentShader = shaders.render_edl.frag;\r\n\r\n let neighbourCount = 8;\r\n let neighbours = new Float32Array(neighbourCount * 2);\r\n for (let i = 0; i < neighbourCount; i++) {\r\n let value = 2 * i * Math.PI / neighbourCount;\r\n neighbours[2 * i] = Math.cos(value);\r\n neighbours[2 * i + 1] = Math.sin(value);\r\n }\r\n\r\n let defines = {\r\n NEIGHBOUR_COUNT: neighbourCount,\r\n };\r\n\r\n let uniforms = {\r\n tImage: new Uniform(null),\r\n tDepth: new Uniform(null),\r\n opacity: new Uniform(1.0),\r\n screenWidth: new Uniform(width),\r\n screenHeight: new Uniform(height),\r\n near: new Uniform(near),\r\n far: new Uniform(far),\r\n edlStrength: new Uniform(1.0),\r\n radius: new Uniform(1.0 / pixelRatio),\r\n neighbours: new Uniform(neighbours),\r\n };\r\n\r\n this.setValues({\r\n defines,\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n transparent: true\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class TagMaterial extends BaseMaterial {\r\n public cameraRotation: Vector3\r\n public drawDistance: number\r\n public timeStamp: number\r\n public windowHeight: number\r\n public fov: number\r\n\r\n constructor(texture: string, scale: number, gpuPicker: boolean) {\r\n super();\r\n\r\n const texturePath = getTagTexturePath(texture);\r\n const textureData = new TextureLoader().load(texturePath);\r\n\r\n const fragmentShader = [\r\n shaders.gpu_picker.frag,\r\n shaders.utilities,\r\n shaders.tags.frag\r\n ].join(\"\\n\");\r\n\r\n const vertexShader = [\r\n shaders.gpu_picker.vert,\r\n shaders.utilities,\r\n shaders.tags.vert\r\n ].join(\"\\n\");\r\n\r\n const uniform = {\r\n scale: new Uniform(scale),\r\n gpuPicker: new Uniform(gpuPicker),\r\n cameraRotation: new Uniform(new Vector3()),\r\n drawDistance: new Uniform(0),\r\n fov: new Uniform(0),\r\n windowHeight: new Uniform(0),\r\n timeStamp: new Uniform(0),\r\n imageTexture: {\r\n type: 't',\r\n value: textureData\r\n }\r\n };\r\n\r\n this.setValues({\r\n uniforms: uniform,\r\n vertexShader: vertexShader,\r\n fragmentShader: fragmentShader,\r\n side: DoubleSide\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class PanoramicImageMaterial extends BaseMaterial {\r\n public tImage: Texture;\r\n\r\n constructor() {\r\n super();\r\n\r\n let vertexShader = shaders.panoramic.vert;\r\n let fragmentShader = shaders.panoramic.frag;\r\n\r\n let uniforms = {\r\n tImage: new Uniform(null)\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n side: DoubleSide\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class PlanarImageMaterial extends BaseMaterial {\r\n public tImage: Texture;\r\n\r\n constructor(config: PlanarConfig) {\r\n super();\r\n\r\n let vertexShader = shaders.planar.vert;\r\n let fragmentShader = shaders.planar.frag;\r\n\r\n let uniforms = {\r\n tImage: new Uniform(null),\r\n imageWidth: new Uniform(config.width),\r\n imageHeight: new Uniform(config.height),\r\n fx: new Uniform(config.fx),\r\n fy: new Uniform(config.fy),\r\n cx: new Uniform(config.cx),\r\n cy: new Uniform(config.cy),\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n side: DoubleSide\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class MarkerMaterial extends BaseMaterial {\r\n public cameraRotation: Vector3;\r\n public windowHeight: number;\r\n public cameraHeight: number;\r\n public currentIndex: number;\r\n public orbitMode: Boolean;\r\n public fov: number;\r\n\r\n constructor(gpuPicker) {\r\n super();\r\n\r\n let fragmentShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.frag,\r\n shaders.markers.frag\r\n ].join(\"\\n\");\r\n\r\n let vertexShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.vert,\r\n shaders.markers.vert\r\n ].join(\"\\n\");\r\n\r\n let uniforms = {\r\n scale: new Uniform(0.5),\r\n gpuPicker: new Uniform(gpuPicker),\r\n orbitMode: new Uniform(false),\r\n cameraRotation: new Uniform(new Vector3()),\r\n fov: new Uniform(0),\r\n cameraHeight: new Uniform(0),\r\n windowHeight: new Uniform(0),\r\n currentIndex: new Uniform(0)\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n side: DoubleSide\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class LineworkSpriteMaterial extends BaseMaterial {\r\n public screenHeight: number;\r\n public fov: number;\r\n public map: Texture;\r\n public size = 1.0;\r\n public gpuPicker = false;\r\n public color = new Color(0xffffff);\r\n public drawDistance: number\r\n\r\n constructor(parameters: LineworkSpriteParams, gpuPicker: boolean) {\r\n super();\r\n\r\n this.updateValues(parameters);\r\n\r\n let fragmentShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.frag,\r\n shaders.linework_sprite.frag\r\n ].join(\"\\n\");\r\n\r\n let vertexShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.vert,\r\n shaders.linework_sprite.vert\r\n ].join(\"\\n\");\r\n\r\n let uniforms = {\r\n color: new Uniform(this.color),\r\n imageTexture: {type: \"t\", value: this.map},\r\n gpuPicker: new Uniform(gpuPicker),\r\n size: new Uniform(this.size),\r\n fov: new Uniform(0),\r\n screenHeight: new Uniform(0),\r\n drawDistance: new Uniform(0)\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n side: DoubleSide\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class LineworkBasicMaterial extends BaseMaterial {\r\n public gpuPicker = false;\r\n public color: Color;\r\n public drawDistance: number\r\n\r\n constructor(color: Color, gpuPicker: boolean) {\r\n super();\r\n\r\n let fragmentShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.frag,\r\n shaders.linework_basic.frag\r\n ].join(\"\\n\");\r\n\r\n let vertexShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.vert,\r\n shaders.linework_basic.vert\r\n ].join(\"\\n\");\r\n\r\n let uniforms = {\r\n color: new Uniform(color),\r\n gpuPicker: new Uniform(gpuPicker),\r\n drawDistance: new Uniform(0)\r\n };\r\n\r\n this.setValues({\r\n uniforms,\r\n vertexShader,\r\n fragmentShader,\r\n side: DoubleSide\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class IFCMaterial extends MeshLambertMaterial {\r\n public drawDistance: number;\r\n\r\n // Required for cameraPosition to be automatically set in the shader.\r\n // https://github.com/mrdoob/three.js/blob/r135/src/renderers/WebGLRenderer.js#L1578\r\n public isShaderMaterial = true;\r\n\r\n constructor(parameters: MeshLambertMaterialParameters, gpuPicker: boolean) {\r\n super(parameters);\r\n\r\n let fragmentShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.frag,\r\n shaders.ifc.frag\r\n ].join(\"\\n\");\r\n\r\n let vertexShader = [\r\n shaders.utilities,\r\n shaders.gpu_picker.vert,\r\n shaders.ifc.vert\r\n ].join(\"\\n\");\r\n\r\n // Shader code is from adapted from the MeshLambertMaterial code.\r\n // https://github.com/mrdoob/three.js/blob/r135/src/renderers/shaders/ShaderLib/meshlambert.glsl.js\r\n this.onBeforeCompile = function(shader) {\r\n shader.vertexShader = vertexShader;\r\n shader.fragmentShader = fragmentShader;\r\n shader.uniforms.drawDistance = new Uniform(0);\r\n shader.uniforms.gpuPicker = new Uniform(gpuPicker);\r\n this.userData.shader = shader;\r\n };\r\n\r\n this.defineProperty(\"drawDistance\");\r\n }\r\n\r\n defineProperty(key) {\r\n Object.defineProperty(this, key, {\r\n get: () => {\r\n if (!this.userData.shader) return undefined;\r\n return this.userData.shader.uniforms[key].value;\r\n },\r\n set: value => {\r\n if (!this.userData.shader) return;\r\n this.userData.shader.uniforms[key].value = value;\r\n }\r\n });\r\n }\r\n}\r\n\r\n/** Generic material for gpu picker objects */\r\nexport class BasicPickerMaterial extends BaseMaterial {\r\n constructor(side = DoubleSide) {\r\n super();\r\n\r\n let vertexShader = [\r\n shaders.gpu_picker.vert,\r\n shaders.basic_picker.vert\r\n ].join(\"\\n\");\r\n\r\n let fragmentShader = [\r\n shaders.gpu_picker.frag,\r\n shaders.basic_picker.frag\r\n ].join(\"\\n\");\r\n\r\n this.setValues({vertexShader, fragmentShader, side});\r\n this.initProperties();\r\n }\r\n}\r\n","import {\r\n NearestFilter,\r\n RGBAFormat,\r\n WebGLRenderTarget,\r\n LinearFilter,\r\n DepthTexture,\r\n UnsignedIntType,\r\n FloatType\r\n} from \"three\";\r\n\r\nexport class BasicRenderTarget extends WebGLRenderTarget {\r\n constructor(width, height) {\r\n super(width, height, {\r\n format: RGBAFormat,\r\n minFilter: LinearFilter,\r\n magFilter: LinearFilter,\r\n stencilBuffer: false\r\n });\r\n }\r\n}\r\n\r\nexport class EDLRenderTarget extends WebGLRenderTarget {\r\n constructor(width, height, isWebGL2) {\r\n super(width, height, {\r\n format: RGBAFormat,\r\n minFilter: NearestFilter,\r\n magFilter: NearestFilter,\r\n generateMipmaps: false,\r\n stencilBuffer: false,\r\n depthBuffer: true\r\n });\r\n\r\n this.depthTexture = new DepthTexture(width, height);\r\n this.depthTexture.type = isWebGL2 ? FloatType : UnsignedIntType;\r\n }\r\n}","import {\r\n EDLRenderMaterial,\r\n BasicRenderMaterial,\r\n EDLRenderTarget,\r\n BasicRenderTarget,\r\n OutputRenderMaterial\r\n} from \".\";\r\nimport {\r\n Camera,\r\n Material,\r\n Mesh,\r\n MeshBasicMaterial,\r\n PerspectiveCamera,\r\n PlaneBufferGeometry,\r\n Scene,\r\n Texture,\r\n Vector2,\r\n Vector3,\r\n WebGLRenderer,\r\n WebGLRenderTarget\r\n} from \"three\";\r\nimport { eventToPixel } from \"../utilities\";\r\n\r\nexport class RenderPass {\r\n private readonly screenScene: Scene;\r\n private readonly screenQuad: Mesh;\r\n private readonly camera: Camera;\r\n\r\n constructor() {\r\n const geometry = new PlaneBufferGeometry(2, 2);\r\n const material = new MeshBasicMaterial({\r\n depthTest: true,\r\n depthWrite: true,\r\n transparent: true\r\n });\r\n\r\n this.screenScene = new Scene();\r\n this.screenQuad = new Mesh(geometry, material);\r\n this.screenScene.add(this.screenQuad);\r\n this.camera = new Camera();\r\n }\r\n\r\n render(renderer, material: Material, target = null) {\r\n this.screenQuad.material = material;\r\n renderer.setRenderTarget(target);\r\n renderer.render(this.screenScene, this.camera);\r\n }\r\n}\r\n\r\nexport class RenderUtils {\r\n private renderer: WebGLRenderer;\r\n private camera: PerspectiveCamera;\r\n private screenPass = new RenderPass()\r\n private targets: WebGLRenderTarget[] = [];\r\n private pixelRatio;\r\n\r\n private EDLEnabled = false;\r\n private animationFrames = 30;\r\n private _zooming = false\r\n private mouseEvent = null;\r\n private mousePosition = new Vector3();\r\n\r\n private basicMaterial: BasicRenderMaterial;\r\n private basicRenderTarget: BasicRenderTarget;\r\n\r\n private EDLMaterial: EDLRenderMaterial;\r\n private EDLRenderTarget: EDLRenderTarget;\r\n\r\n private outputMaterial: OutputRenderMaterial;\r\n private outputRenderTarget: BasicRenderTarget;\r\n\r\n private previousRenderTarget: BasicRenderTarget;\r\n public previousNeedsUpdate = false;\r\n\r\n constructor(renderer: WebGLRenderer, camera: PerspectiveCamera, pixelRatio=1.0) {\r\n this.renderer = renderer;\r\n this.camera = camera;\r\n this.pixelRatio = pixelRatio;\r\n\r\n this.initTargets();\r\n }\r\n\r\n get EDLSupport() : boolean {\r\n let capabilities = this.renderer.capabilities;\r\n let supported = (capabilities.maxVaryings > 8)\r\n && capabilities.floatFragmentTextures;\r\n\r\n return supported;\r\n }\r\n\r\n get renderTarget() {\r\n return this.EDLSupport\r\n ? this.EDLRenderTarget\r\n : this.basicRenderTarget;\r\n }\r\n\r\n get renderMaterial() {\r\n return (this.EDLSupport && this.EDLEnabled)\r\n ? this.EDLMaterial\r\n : this.basicMaterial;\r\n }\r\n\r\n get isWebGL2() {\r\n let capabilities = this.renderer.capabilities;\r\n return capabilities.isWebGL2;\r\n }\r\n\r\n get width() {\r\n let renderSize = new Vector2();\r\n this.renderer.getSize(renderSize);\r\n return renderSize.x;\r\n }\r\n\r\n get height() {\r\n let renderSize = new Vector2();\r\n this.renderer.getSize(renderSize);\r\n return renderSize.y;\r\n }\r\n\r\n get zoomRadius() {\r\n return this.outputMaterial.zoomRadius;\r\n }\r\n\r\n get zooming() {\r\n return this._zooming;\r\n }\r\n\r\n set zoomToCursor(value: boolean) {\r\n const pixels = eventToPixel(this.mouseEvent);\r\n\r\n this.mousePosition.copy(pixels);\r\n this.outputMaterial.mousePosition.x = pixels.x / this.width;\r\n this.outputMaterial.mousePosition.y = 1.0 - (pixels.y / this.height);\r\n this._zooming = value;\r\n }\r\n\r\n insideRadius(position: Vector3) {\r\n if (!this.zooming) return true;\r\n\r\n const radius = this.zoomRadius * this.height;\r\n\r\n const distance = new Vector3()\r\n .copy(position)\r\n .sub(this.mousePosition)\r\n .length();\r\n\r\n return distance < radius;\r\n }\r\n\r\n initTargets() {\r\n this.basicMaterial = new BasicRenderMaterial();\r\n this.basicRenderTarget = new BasicRenderTarget(\r\n this.width, this.height);\r\n this.addTarget(this.basicRenderTarget);\r\n\r\n this.outputMaterial = new OutputRenderMaterial(this.width, this.height);\r\n this.outputRenderTarget = new BasicRenderTarget(\r\n this.width, this.height);\r\n this.addTarget(this.outputRenderTarget);\r\n\r\n if (this.EDLSupport) {\r\n this.EDLMaterial = new EDLRenderMaterial(\r\n this.width,\r\n this.height,\r\n this.camera.near,\r\n this.camera.far,\r\n this.pixelRatio\r\n );\r\n\r\n this.EDLRenderTarget = new EDLRenderTarget(\r\n this.width, this.height, this.isWebGL2);\r\n this.addTarget(this.EDLRenderTarget);\r\n } else {\r\n this.EDLMaterial = null;\r\n this.EDLRenderTarget = null;\r\n\r\n console.log(\"EDL Not Supported\");\r\n }\r\n }\r\n\r\n update() {\r\n this.updateEDLValues();\r\n this.updateZoomValues();\r\n this.updateProgress();\r\n this.resizeTextures();\r\n\r\n this.renderer.setRenderTarget(this.outputRenderTarget);\r\n this.renderer.clear();\r\n\r\n this.renderer.setRenderTarget(this.renderTarget);\r\n this.renderer.clear();\r\n\r\n this.renderer.setRenderTarget(null);\r\n this.renderer.clear();\r\n }\r\n\r\n addTarget(target) {\r\n this.targets.push(target);\r\n }\r\n\r\n setCamera(camera) {\r\n this.camera = camera;\r\n }\r\n\r\n updateProgress() {\r\n const increment = 1.0 / this.animationFrames;\r\n this.outputMaterial.progress += increment;\r\n this.outputMaterial.progress = Math.min(\r\n 1.0, this.outputMaterial.progress);\r\n }\r\n\r\n updateTexture() : Promise {\r\n return new Promise((resolve) => {\r\n this.previousNeedsUpdate = true;\r\n\r\n const interval = setInterval(() => {\r\n if (this.previousNeedsUpdate) return;\r\n clearInterval(interval);\r\n resolve();\r\n }, 10);\r\n });\r\n }\r\n\r\n /** @private */\r\n resizeTextures() {\r\n let width = this.width;\r\n let height = this.height;\r\n\r\n this.targets.forEach(target => {\r\n if (!target) {\r\n return;\r\n }\r\n\r\n let w = target.width;\r\n let h = target.height;\r\n if ((w !== width) || (h !== height)) {\r\n target.dispose();\r\n target.setSize(width, height);\r\n }\r\n });\r\n }\r\n\r\n /** @private */\r\n updateEDLValues() {\r\n if (!this.EDLMaterial) return;\r\n\r\n this.EDLMaterial.far = this.camera.far;\r\n this.EDLMaterial.screenWidth = this.width;\r\n this.EDLMaterial.screenHeight = this.height;\r\n }\r\n\r\n /** @private */\r\n updateZoomValues() {\r\n this.outputMaterial.screenWidth = this.width;\r\n this.outputMaterial.screenHeight = this.height;\r\n this.outputMaterial.zooming = this.zooming;\r\n }\r\n\r\n updateMaterial(material, values) {\r\n let keys = Object.keys(values);\r\n keys.forEach(key => {\r\n material[key] = values[key];\r\n });\r\n }\r\n\r\n textureFromImage(imageData: string): Promise {\r\n return new Promise(resolve => {\r\n const image = new Image();\r\n image.onload = () => {\r\n const texture = new Texture(image);\r\n resolve(texture);\r\n };\r\n image.src = imageData;\r\n });\r\n }\r\n\r\n setRenderTarget(clear: boolean) {\r\n this.renderer.setRenderTarget(this.renderTarget);\r\n if (!clear) return;\r\n\r\n this.renderer.clear();\r\n }\r\n\r\n setEDLState(state: boolean) {\r\n this.EDLEnabled = state;\r\n }\r\n\r\n onMouseMove(event) {\r\n this.mouseEvent = event;\r\n }\r\n\r\n /** Render scene to renderTarget */\r\n renderScene(scene: Scene) {\r\n this.renderer.render(scene, this.camera);\r\n this.renderer.render(scene, this.camera);\r\n }\r\n\r\n /** Render renderTarget texture to outputRenderTarget */\r\n renderToTarget(opacity: number) {\r\n this.renderMaterial.tDepth = this.renderTarget.depthTexture;\r\n this.renderMaterial.tImage = this.renderTarget.texture;\r\n this.renderMaterial.opacity = opacity;\r\n\r\n this.screenPass.render(\r\n this.renderer,\r\n this.renderMaterial,\r\n this.outputRenderTarget\r\n );\r\n }\r\n\r\n /** Update the previous image texture in outputRenderTarget */\r\n renderToPrevious() {\r\n if (!this.previousNeedsUpdate) return;\r\n\r\n if (this.previousRenderTarget) {\r\n this.previousRenderTarget.dispose();\r\n }\r\n\r\n this.outputMaterial.progress = 1.0;\r\n this.outputMaterial.zooming = false;\r\n\r\n this.previousRenderTarget = new BasicRenderTarget(\r\n this.width, this.height);\r\n\r\n this.outputMaterial.tCurrent =\r\n this.outputRenderTarget.texture;\r\n\r\n this.screenPass.render(\r\n this.renderer,\r\n this.outputMaterial,\r\n this.previousRenderTarget\r\n );\r\n\r\n this.outputMaterial.tPrevious =\r\n this.previousRenderTarget.texture;\r\n\r\n this.outputMaterial.progress = 0;\r\n this.outputMaterial.zooming = this.zooming;\r\n\r\n this.previousNeedsUpdate = false;\r\n }\r\n\r\n renderToScreen() {\r\n this.outputMaterial.tCurrent = this.outputRenderTarget.texture;\r\n this.screenPass.render(this.renderer, this.outputMaterial);\r\n }\r\n}\r\n","import {\r\n Box3,\r\n BoxGeometry,\r\n BufferAttribute,\r\n BufferGeometry,\r\n EdgesGeometry,\r\n Frustum,\r\n LineBasicMaterial,\r\n LineSegments,\r\n Points,\r\n Scene,\r\n Vector3\r\n} from 'three';\r\nimport { isDevMode } from '../../electron-modules';\r\nimport { PointCloudMaterial } from '../rendering';\r\nimport { PointCloudManager } from '.';\r\nimport { closestPowerOfTwo, mergeBoundingBoxes, randomHexColor, toVector2 } from '../utilities';\r\nimport GPUPicker from '../gpu-picker';\r\n\r\n/** Base class for all pointcloud nodes */\r\nexport class PointCloudNode {\r\n public cloud: PointCloud\r\n public parent: PointCloudNode\r\n\r\n public pointsScene: Points;\r\n public pointsPicker: Points;\r\n protected boundingBoxMesh: LineSegments;\r\n public geometry: BufferGeometry;\r\n protected _boundingBox: Box3;\r\n\r\n public name: string;\r\n public nodeSize: number;\r\n public edgeSize = new Vector3();\r\n protected data;\r\n protected nodeCenter: Vector3;\r\n public numPoints = 0;\r\n public children: PointCloudNode[] = []\r\n public density: number;\r\n\r\n public visible = false;\r\n public loaded = false;\r\n public loading = false;\r\n\r\n get scene(): Scene {\r\n return this.cloud.scene;\r\n }\r\n\r\n get picker(): GPUPicker {\r\n return this.cloud.picker;\r\n }\r\n\r\n /** Bounding box in viewer coordinates */\r\n get boundingBox(): Box3 {\r\n if (!this._boundingBox) {\r\n const size = new Vector3()\r\n .add(this.edgeSize)\r\n .divideScalar(2);\r\n\r\n const min = new Vector3()\r\n .add(this.center)\r\n .sub(size);\r\n\r\n const max = new Vector3()\r\n .add(this.center)\r\n .add(size);\r\n\r\n this._boundingBox = new Box3(min, max);\r\n }\r\n\r\n return this._boundingBox;\r\n }\r\n\r\n get shift() {\r\n return new Vector3();\r\n }\r\n\r\n /** Node center in viewer coordinates */\r\n get center() {\r\n return new Vector3()\r\n .add(this.nodeCenter)\r\n .add(this.shift);\r\n }\r\n\r\n /** Bounding sphere radius */\r\n get radius() {\r\n return Math.sqrt(3) * (this.nodeSize / 2.0);\r\n }\r\n\r\n get isGeometryNode() {\r\n return !this.pointsScene;\r\n }\r\n\r\n get isTreeNode() {\r\n return !!this.pointsScene;\r\n }\r\n\r\n addChildNode(node) {\r\n this.children.push(node);\r\n }\r\n\r\n clearChildNodes() {\r\n this.children.forEach(child => child = null);\r\n this.children = [];\r\n }\r\n\r\n removeChildNode(node) {\r\n let index = this.children.indexOf(node);\r\n if (index !== -1) {\r\n this.children.splice(index, 1);\r\n }\r\n\r\n node.clearChildNodes();\r\n node = null;\r\n }\r\n\r\n removeFromScene(item) {\r\n if (!item) return;\r\n this.scene.remove(item);\r\n }\r\n\r\n disposeGeometry(item) {\r\n if (!item) {\r\n return;\r\n }\r\n\r\n item.geometry.dispose();\r\n item.material.dispose();\r\n }\r\n\r\n dispose() {\r\n this.removeFromScene(this.pointsScene);\r\n this.disposeGeometry(this.pointsScene);\r\n this.pointsScene = null;\r\n\r\n this.picker.remove(this.pointsPicker);\r\n this.disposeGeometry(this.pointsPicker);\r\n this.pointsPicker = null;\r\n\r\n if (this.boundingBoxMesh) {\r\n this.removeFromScene(this.boundingBoxMesh);\r\n this.disposeGeometry(this.boundingBoxMesh);\r\n this.boundingBoxMesh = null;\r\n }\r\n\r\n if (this.geometry) {\r\n this.geometry.dispose();\r\n }\r\n\r\n this.geometry = null;\r\n this.loaded = false;\r\n this.loading = false;\r\n\r\n // console.log(`Dispose node: ${this.name}`);\r\n }\r\n\r\n setVisibility(visible: boolean, boundsVisible: boolean) {\r\n if (this.pointsPicker) {\r\n this.pointsPicker.visible = visible;\r\n }\r\n\r\n if (this.pointsScene) {\r\n this.pointsScene.visible = visible;\r\n }\r\n\r\n if (this.boundingBoxMesh) {\r\n this.boundingBoxMesh.visible = boundsVisible;\r\n }\r\n\r\n this.visible = visible;\r\n }\r\n\r\n setGeometry(data) {\r\n let geometry = new BufferGeometry();\r\n geometry.setAttribute('position', new BufferAttribute(data.positions, 3));\r\n geometry.setAttribute('intensity', new BufferAttribute(data.intensity, 1));\r\n geometry.setAttribute('classification', new BufferAttribute(data.classification, 1));\r\n geometry.setAttribute('rgb', new BufferAttribute(data.colors, 3));\r\n geometry.setAttribute('gpu_index', new BufferAttribute(data.gpu_index, 1));\r\n //geometry.computeBoundingBox();\r\n\r\n this.geometry = geometry;\r\n }\r\n\r\n addToScene() {\r\n let pointsScene = new Points(this.geometry, this.cloud.materialScene);\r\n pointsScene.visible = false;\r\n\r\n let pointsPicker = new Points(this.geometry, this.cloud.materialPicker);\r\n pointsPicker.visible = false;\r\n\r\n let boundingBox = generateEdgeMesh(this.boundingBox);\r\n\r\n this.addCloudData(pointsPicker, pointsScene, boundingBox);\r\n }\r\n\r\n addCloudData(pointsPicker: Points, pointsScene: Points, boundingBox: LineSegments) {\r\n // Add our global shift to line up with previous data\r\n pointsScene.position.copy(this.shift);\r\n pointsPicker.position.copy(this.shift);\r\n\r\n // Add our new objects\r\n this.pointsPicker = pointsPicker;\r\n this.pointsScene = pointsScene;\r\n\r\n this.scene.add(this.pointsScene);\r\n this.picker.add(this.pointsPicker);\r\n\r\n if (boundingBox) {\r\n // Bounding box is for dev mode only\r\n boundingBox.position.copy(this.center);\r\n this.boundingBoxMesh = boundingBox;\r\n this.scene.add(this.boundingBoxMesh);\r\n }\r\n }\r\n\r\n\r\n isVisible(frustum: Frustum) {\r\n // Ignore nodes based on our view frustrum\r\n if (!frustum.intersectsBox(this.boundingBox)) {\r\n return false;\r\n }\r\n\r\n const handler = this.cloud.pointclouds;\r\n const controls = handler.viewer.controls;\r\n const drawDistance = handler.drawDistance;\r\n const cameraPosition = controls.getCameraTarget();\r\n\r\n // Ignore nodes based on distance slider\r\n const bounds2D = toVector2(this.center);\r\n const camera2D = toVector2(cameraPosition);\r\n const nodeDistance = bounds2D.distanceTo(camera2D);\r\n if (nodeDistance > (this.radius + drawDistance)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n}\r\n\r\n/** Base class for all pointclouds */\r\nexport class PointCloud {\r\n public uniqueClassifications: Set;\r\n private readonly rgbArray = [];\r\n public maxColor = null;\r\n public intensityRange = null;\r\n public identifier = null;\r\n public error = false;\r\n protected enabled = true;\r\n public visible = true;\r\n private name: string;\r\n public materialScene: PointCloudMaterial = null;\r\n public materialPicker: PointCloudMaterial = null;\r\n public materials: PointCloudMaterial[];\r\n public root: PointCloudNode = null;\r\n public pointclouds: PointCloudManager;\r\n protected _tightBoundingBox: Box3 = null;\r\n\r\n constructor(pointclouds: PointCloudManager) {\r\n this.pointclouds = pointclouds;\r\n this.uniqueClassifications = new Set();\r\n\r\n this.materialScene = new PointCloudMaterial(this.viewer,\r\n this.pointclouds.materialDefaults, false);\r\n\r\n this.materialPicker = new PointCloudMaterial(this.viewer,\r\n this.pointclouds.materialDefaults, true);\r\n\r\n this.materials = [\r\n this.materialScene,\r\n this.materialPicker\r\n ];\r\n }\r\n\r\n get shift() {\r\n return new Vector3();\r\n }\r\n\r\n get size() {\r\n return 0;\r\n }\r\n\r\n get viewer() {\r\n return this.pointclouds.viewer;\r\n }\r\n\r\n get scene() {\r\n return this.pointclouds.scene;\r\n }\r\n\r\n get picker() {\r\n return this.viewer.gpuPickers.default;\r\n }\r\n\r\n /** Get bounding box with global shift applied */\r\n get tightBoundingBox(): Box3 {\r\n let bbox = this._tightBoundingBox;\r\n if (!bbox) return null;\r\n\r\n return new Box3(\r\n new Vector3().add(bbox.min).add(this.shift),\r\n new Vector3().add(bbox.max).add(this.shift)\r\n );\r\n }\r\n\r\n setName(name) {\r\n this.name = name;\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n }\r\n\r\n setVisibility(visible) {\r\n const changed = this.visible !== visible;\r\n this.visible = visible;\r\n if (changed) {\r\n this.pointclouds.updateMinimapExtent();\r\n }\r\n }\r\n\r\n setIdentifier(identifier) {\r\n // console.log(`Added pointcloud [id = ${identifier}]`);\r\n identifier = identifier === undefined ? null : identifier;\r\n this.identifier = identifier;\r\n }\r\n\r\n destroy() {\r\n this.setState(false);\r\n this.disposeNodes();\r\n }\r\n\r\n disposeNodes() {\r\n const nodes = this.getVisibleNodes();\r\n nodes.forEach(node => {\r\n node.visible = false;\r\n node.dispose();\r\n });\r\n }\r\n\r\n getVisibleNodes(condition?) : PointCloudNode[] {\r\n console.warn(\"Not implemented\");\r\n return [];\r\n }\r\n\r\n updateBoundingBox(boundingBox: Box3) {\r\n let combined = mergeBoundingBoxes([\r\n this._tightBoundingBox,\r\n boundingBox\r\n ]);\r\n\r\n this._tightBoundingBox = combined;\r\n }\r\n\r\n updateIntensityRange(intensityMin, intensityMax) {\r\n if (this.intensityRange === null) {\r\n this.intensityRange = {\r\n min: intensityMin,\r\n max: intensityMax\r\n };\r\n }\r\n\r\n this.intensityRange.min = Math.min(intensityMin, this.intensityRange.min);\r\n this.intensityRange.max = Math.max(intensityMax, this.intensityRange.max);\r\n }\r\n\r\n updateColorLimits(rgbMax) {\r\n let closestValue = closestPowerOfTwo(rgbMax);\r\n this.rgbArray.push(closestValue);\r\n this.rgbArray.sort();\r\n\r\n let arrMax = Math.max(...this.rgbArray);\r\n let arrMin = Math.min(...this.rgbArray);\r\n let diff = arrMax - arrMin;\r\n if (diff === 0) {\r\n this.maxColor = arrMax;\r\n return;\r\n }\r\n\r\n // Grab the middle value instead\r\n let midpoint = this.rgbArray.length / 2.0;\r\n midpoint = Math.ceil(midpoint);\r\n this.maxColor = this.rgbArray[midpoint];\r\n }\r\n\r\n updateClassificationFromHistogram(histogram) {\r\n let uniqueClassifications = [];\r\n\r\n histogram.forEach((count, index) => {\r\n if (count === 0) return;\r\n uniqueClassifications.push(index);\r\n });\r\n\r\n this.updateClassifications(uniqueClassifications);\r\n }\r\n\r\n updateClassifications(classifications: number[]) {\r\n classifications.forEach(item => {\r\n this.uniqueClassifications.add(item);\r\n });\r\n }\r\n\r\n\r\n}\r\n\r\nconst generateEdgeMesh = (boundingBox: Box3) => {\r\n if (!isDevMode) return null;\r\n\r\n const size = new Vector3()\r\n .add(boundingBox.max)\r\n .sub(boundingBox.min);\r\n\r\n const color = randomHexColor();\r\n const boxGeometry = new BoxGeometry(size.x, size.y, size.z);\r\n const edgeGeometry = new EdgesGeometry(boxGeometry);\r\n const boxMaterial = new LineBasicMaterial({color});\r\n const mesh = new LineSegments(edgeGeometry, boxMaterial);\r\n mesh.visible = false;\r\n\r\n return mesh;\r\n};\r\n\r\nexport const getClassificationHistogram = (classifications: number[]) => {\r\n const histogram = new Array(256).fill(0);\r\n\r\n classifications.forEach(classification => {\r\n histogram[classification] += 1;\r\n });\r\n\r\n return histogram;\r\n};\r\n","// Binary heap implementation from:\r\n// http://eloquentjavascript.net/appendix2.html\r\n\r\nexport class BinaryHeap {\r\n private scoreFunction;\r\n private content = [];\r\n\r\n constructor(scoreFunction) {\r\n this.scoreFunction = scoreFunction;\r\n }\r\n\r\n get size() {\r\n return this.content.length;\r\n }\r\n\r\n push(element) {\r\n // Add the new element to the end of the array.\r\n this.content.push(element);\r\n // Allow it to bubble up.\r\n this.bubbleUp(this.content.length - 1);\r\n }\r\n\r\n pop() {\r\n // Store the first element so we can return it later.\r\n var result = this.content[0];\r\n // Get the element at the end of the array.\r\n var end = this.content.pop();\r\n // If there are any elements left, put the end element at the\r\n // start, and let it sink down.\r\n if (this.content.length > 0) {\r\n this.content[0] = end;\r\n this.sinkDown(0);\r\n }\r\n return result;\r\n }\r\n\r\n peek() {\r\n return this.content[0];\r\n }\r\n\r\n remove(node) {\r\n var length = this.content.length;\r\n // To remove a value, we must search through the array to find\r\n // it.\r\n for (var i = 0; i < length; i++) {\r\n if (this.content[i] !== node) continue;\r\n // When it is found, the process seen in 'pop' is repeated\r\n // to fill up the hole.\r\n var end = this.content.pop();\r\n // If the element we popped was the one we needed to remove,\r\n // we're done.\r\n if (i === length - 1) break;\r\n // Otherwise, we replace the removed element with the popped\r\n // one, and allow it to float up or sink down as appropriate.\r\n this.content[i] = end;\r\n this.bubbleUp(i);\r\n this.sinkDown(i);\r\n break;\r\n }\r\n }\r\n\r\n bubbleUp(n) {\r\n // Fetch the element that has to be moved.\r\n var element = this.content[n];\r\n var score = this.scoreFunction(element);\r\n // When at 0, an element can not go up any further.\r\n while (n > 0) {\r\n // Compute the parent element's index, and fetch it.\r\n var parentN = Math.floor((n + 1) / 2) - 1;\r\n var parent = this.content[parentN];\r\n // If the parent has a lesser score, things are in order and we\r\n // are done.\r\n if (score >= this.scoreFunction(parent)) {\r\n break;\r\n }\r\n\r\n // Otherwise, swap the parent with the current element and\r\n // continue.\r\n this.content[parentN] = element;\r\n this.content[n] = parent;\r\n n = parentN;\r\n }\r\n }\r\n\r\n sinkDown(n) {\r\n // Look up the target element and its score.\r\n var length = this.content.length;\r\n var element = this.content[n];\r\n var elemScore = this.scoreFunction(element);\r\n\r\n while (true) {\r\n // Compute the indices of the child elements.\r\n var child2N = (n + 1) * 2;\r\n var child1N = child2N - 1;\r\n // This is used to store the new position of the element,\r\n // if any.\r\n var swap = null;\r\n // If the first child exists (is inside the array)...\r\n if (child1N < length) {\r\n // Look it up and compute its score.\r\n var child1 = this.content[child1N];\r\n var child1Score = this.scoreFunction(child1);\r\n // If the score is less than our element's, we need to swap.\r\n if (child1Score < elemScore) {\r\n swap = child1N;\r\n }\r\n }\r\n // Do the same checks for the other child.\r\n if (child2N < length) {\r\n var child2 = this.content[child2N];\r\n var child2Score = this.scoreFunction(child2);\r\n if (child2Score < (swap == null ? elemScore : child1Score)) {\r\n swap = child2N;\r\n }\r\n }\r\n\r\n // No need to swap further, we are done.\r\n if (swap == null) break;\r\n\r\n // Otherwise, swap and continue.\r\n this.content[n] = this.content[swap];\r\n this.content[swap] = element;\r\n n = swap;\r\n }\r\n }\r\n}","import {\r\n EncompassPointCloud,\r\n PointCloud,\r\n PotreePointCloud,\r\n GenericPointCloud,\r\n StreamablePointCloud,\r\n StreamablePointCloudNode,\r\n GenericPointCloudNode,\r\n PointCloudNode\r\n} from \".\";\r\nimport {\r\n assignPackedData,\r\n PointCloudMaterial,\r\n PointCloudMaterialParams\r\n} from \"../rendering\";\r\nimport {Viewer} from \"../main\";\r\nimport {\r\n boundsToMapLayer,\r\n closestPowerOfTwo,\r\n getProjFactor,\r\n mergeBoundingBoxes\r\n} from \"../utilities\";\r\nimport { pointInPolygon } from \"../utilities\";\r\nimport {\r\n AmbientLight,\r\n BufferGeometry,\r\n Frustum,\r\n MathUtils,\r\n Points,\r\n Scene,\r\n Vector2,\r\n Vector3\r\n} from \"three\";\r\nimport { Vector as VectorLayer } from \"ol/layer\";\r\nimport { isStaticSite } from \"../../electron-modules\";\r\nimport LocalScene, { getEulerInverse } from \"../projections\";\r\nimport slash from \"slash\";\r\nimport { Asset, AssetType } from \"../../redux/assets-slice\";\r\nimport { BinaryHeap } from \"../binary-heap\";\r\nimport { Clamp } from \"../../redux/settings-slice\";\r\n\r\nexport class PointCloudManager {\r\n public viewer: Viewer;\r\n public scene: Scene;\r\n private mapLayer: VectorLayer;\r\n public materialDefaults: PointCloudMaterialParams;\r\n public clouds: (GenericPointCloud | StreamablePointCloud)[] = [];\r\n public visiblePointsTarget = 0;\r\n private visiblePointsPerCloud = 1000000;\r\n private maxUnloadedNodes = 3;\r\n private numNodesLoading = 0;\r\n private unloadedNodes = [];\r\n private maxUnloadedClouds = 2;\r\n private loadedToGPUThisFrame = false;\r\n private streamableCacheSize = 1000;\r\n private genericCacheSize = 100;\r\n private maxGenericFilesVisible = 10;\r\n private exeLaunchTimeout = 1000;\r\n private lastExeLaunched = performance.now();\r\n public numLoadedPoints = 0;\r\n public numVisiblePoints = 0;\r\n public numSceneNodesVisible = 0;\r\n private minStreamableNodeSize = 50;\r\n public boundsVisible = false;\r\n public transparency = 1.0;\r\n public rawJsonResponse = [];\r\n public shouldUpdate = true;\r\n private _drawDistance = 0;\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n\r\n // Material defaults\r\n this.materialDefaults = {\r\n size: 1.0,\r\n minSize: 2.0,\r\n maxSize: 50.0,\r\n colorMap: \"heat-map\",\r\n colorType: 2,\r\n dynamicSize: true,\r\n circularPoints: true,\r\n classifications: {},\r\n heightClamp: new Vector2(0, 1),\r\n intensityClamp: new Vector2(0, 1),\r\n };\r\n\r\n this.initScene();\r\n }\r\n\r\n get cameraHandler() {\r\n return this.viewer.cameraHandler;\r\n }\r\n\r\n get renderUtils() {\r\n return this.viewer.renderUtils;\r\n }\r\n\r\n get minimap() {\r\n return this.viewer.minimap;\r\n }\r\n\r\n get controls() {\r\n return this.viewer.controls;\r\n }\r\n\r\n get fov() {\r\n return this.viewer.camera.fov;\r\n }\r\n\r\n get uniqueClassifications(): number[] {\r\n let uniqueClassifications = new Set();\r\n this.clouds.forEach(cloud => {\r\n cloud.uniqueClassifications.forEach((item: number) => {\r\n uniqueClassifications.add(item);\r\n });\r\n });\r\n return Array.from(uniqueClassifications) as number[];\r\n }\r\n\r\n get combinedBoundingBox() {\r\n const boundingBoxes = this.clouds.map(cloud => {\r\n if (!cloud.visible) return null;\r\n return cloud.tightBoundingBox;\r\n });\r\n\r\n return mergeBoundingBoxes(boundingBoxes);\r\n }\r\n\r\n get genericPointClouds() {\r\n return this.clouds.filter(cloud => {\r\n return cloud instanceof GenericPointCloud;\r\n }) as GenericPointCloud[];\r\n }\r\n\r\n get streamablePointClouds() {\r\n return this.clouds.filter(cloud => {\r\n return cloud instanceof StreamablePointCloud;\r\n }) as StreamablePointCloud[];\r\n }\r\n\r\n get isEmpty() {\r\n return this.clouds.length === 0;\r\n }\r\n\r\n get screenHeight() {\r\n return this.viewer.height;\r\n }\r\n\r\n get screenWidth() {\r\n return this.viewer.width;\r\n }\r\n\r\n get cameraPosition() {\r\n return this.viewer.camera.position;\r\n }\r\n\r\n get drawDistance() {\r\n if (this.viewer.orbitState) {\r\n return this.viewer.far;\r\n }\r\n\r\n return (this._drawDistance > 999)\r\n ? this.viewer.far\r\n : this._drawDistance;\r\n }\r\n\r\n set drawDistance(distance: number) {\r\n this._drawDistance = distance;\r\n }\r\n\r\n reconcile(pointCloudFiles: Asset[]) {\r\n const currentFiles = new Set(this.clouds.map(cloud => cloud.identifier));\r\n const newFiles = new Set(pointCloudFiles.map(cloud => cloud.id));\r\n const assetsToLoad = pointCloudFiles.filter(cloud => !currentFiles.has(cloud.id));\r\n const filesToDelete = this.clouds.filter(cloud => !newFiles.has(cloud.identifier));\r\n\r\n const pointCloudsAdded = assetsToLoad.length;\r\n const pointCloudsRemoved = filesToDelete.length;\r\n\r\n // Delete old pointclouds\r\n filesToDelete.forEach(file => {\r\n this.deleteFile(file);\r\n });\r\n\r\n // Add new pointclouds\r\n assetsToLoad.forEach(file => {\r\n this.addNewFile(file);\r\n });\r\n\r\n // Toggle proper visibility for each cloud\r\n pointCloudFiles.forEach(pointCloud => {\r\n this.toggleVisibility(pointCloud.id, pointCloud.visible);\r\n });\r\n\r\n return {pointCloudsAdded, pointCloudsRemoved};\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n getByID(id) {\r\n return this.clouds.find(pointCloud => pointCloud.identifier === id);\r\n }\r\n\r\n doesCloudExist(identifier: string): boolean {\r\n return this.clouds.filter(cloud => cloud.identifier === identifier).length > 0;\r\n }\r\n\r\n addPointCloud(cloud: GenericPointCloud | StreamablePointCloud) {\r\n this.clouds.push(cloud);\r\n this.updateMeasureList();\r\n }\r\n\r\n addNewFile(file: Asset) {\r\n const cloudDetails = {\r\n name: file.name,\r\n identifier: file.id,\r\n path: slash(file.path),\r\n visible: file.visible,\r\n saved: file.saved\r\n };\r\n\r\n let newPointCloud;\r\n\r\n if (file.type === AssetType.LAS) {\r\n newPointCloud = new GenericPointCloud(this);\r\n } else if (file.type === AssetType.E57Points) {\r\n newPointCloud = new GenericPointCloud(this);\r\n } else if (file.type === AssetType.Encompass) {\r\n newPointCloud = new EncompassPointCloud(this);\r\n } else if (file.type === AssetType.Potree) {\r\n newPointCloud = new PotreePointCloud(this);\r\n } else {\r\n return;\r\n }\r\n\r\n if (!newPointCloud) return;\r\n newPointCloud.load(cloudDetails);\r\n }\r\n\r\n deleteFile(file: GenericPointCloud | StreamablePointCloud) {\r\n file.destroy();\r\n\r\n if (file instanceof GenericPointCloud) {\r\n file.removeTempFiles();\r\n }\r\n\r\n const index = this.clouds.indexOf(file);\r\n this.clouds.splice(index, 1);\r\n\r\n this.updateMinimapExtent();\r\n this.updateMeasureList();\r\n }\r\n\r\n updateMeasureList() {\r\n const measurements = this.controls.measurements;\r\n measurements.refreshMeasurementList();\r\n }\r\n\r\n toggleVisibility(identifier, state) {\r\n this.clouds\r\n .filter(cloud => cloud.identifier === identifier)\r\n .forEach(cloud => {\r\n cloud.setVisibility(state);\r\n });\r\n }\r\n\r\n updateClamping(key: string, data: Clamp) {\r\n if (data.max <= data.min) return;\r\n\r\n const value = new Vector2(data.min, data.max);\r\n\r\n this.materialDefaults[key] = value;\r\n this.clouds.forEach(cloud => {\r\n cloud.materials.forEach(material => {\r\n material[key] = value;\r\n });\r\n });\r\n }\r\n\r\n setVisibleClassifications(classifications) {\r\n // Update defaults for new clouds\r\n classifications.forEach(classification => {\r\n const {id, visible} = classification;\r\n this.materialDefaults.classifications[id] = visible;\r\n });\r\n\r\n // Update values in existing clouds\r\n this.clouds.forEach(cloud => {\r\n cloud.materials.forEach(material => {\r\n material.updateVisibleClassifications(\r\n this.materialDefaults);\r\n });\r\n\r\n cloud.picker.needsUpdate = true;\r\n });\r\n }\r\n\r\n setPointCloudScale(size) {\r\n this.materialDefaults.size = size;\r\n this.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.size = size;\r\n material.needsUpdate = true;\r\n });\r\n });\r\n }\r\n\r\n setPointCloudMinimum(size) {\r\n this.materialDefaults.minSize = size;\r\n this.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.minSize = size;\r\n material.needsUpdate = true;\r\n });\r\n });\r\n }\r\n\r\n updateMinimapExtent() {\r\n const map = this.minimap.map;\r\n if (this.mapLayer) {\r\n map.removeLayer(this.mapLayer);\r\n }\r\n\r\n if (!LocalScene.initialized) return;\r\n\r\n let boundingBox = this.combinedBoundingBox;\r\n if (!boundingBox) return;\r\n\r\n // Aerial view layer\r\n this.mapLayer = boundsToMapLayer(boundingBox);\r\n map.addLayer(this.mapLayer);\r\n }\r\n\r\n updateUniforms(cloud: PointCloud, material: PointCloudMaterial) {\r\n const camera = this.viewer.camera;\r\n const drawDistance = this.drawDistance;\r\n\r\n material.isOctreeCloud = !(cloud instanceof GenericPointCloud);\r\n material.isPotreeCloud = cloud instanceof PotreePointCloud;\r\n material.drawDistance = drawDistance;\r\n material.screenHeight = this.screenHeight;\r\n material.screenwidth = this.screenWidth;\r\n material.fov = MathUtils.degToRad(camera.fov);\r\n\r\n if (cloud instanceof StreamablePointCloud) {\r\n material.octreeSpacing = cloud.spacing;\r\n material.octreeSize = cloud.root.nodeSize;\r\n material.octreeCorner = new Vector3()\r\n .add(cloud.root.center)\r\n .subScalar(cloud.root.nodeSize / 2.0);\r\n }\r\n\r\n let intensityRange = cloud.intensityRange;\r\n if (intensityRange) {\r\n let intensity = new Vector2(\r\n intensityRange.min,\r\n intensityRange.max\r\n );\r\n material.intensityRange = intensity;\r\n }\r\n\r\n let maxColor = cloud.maxColor;\r\n if (maxColor) {\r\n let maxValue = closestPowerOfTwo(maxColor);\r\n material.rgbMax = maxValue;\r\n }\r\n\r\n let tightBoundingBox = this.combinedBoundingBox;\r\n if (tightBoundingBox) {\r\n let height = new Vector2(\r\n tightBoundingBox.min.z,\r\n tightBoundingBox.max.z\r\n );\r\n material.heightRange = height;\r\n }\r\n }\r\n\r\n updateCloudSampling() {\r\n let percent = this.visiblePointsTarget / this.numLoadedPoints;\r\n percent = Math.min(1.0, percent);\r\n\r\n this.clouds.forEach(cloud => {\r\n if (!(cloud instanceof GenericPointCloud)) return;\r\n if (!cloud.visible || !cloud.root) return;\r\n\r\n cloud.root.children.forEach(child => {\r\n const geometry = child.geometry;\r\n if (!geometry) return;\r\n\r\n const numPoints = child.numPoints;\r\n const numToDraw = Math.floor(numPoints * percent);\r\n if (geometry.drawRange.count === numToDraw) return;\r\n\r\n geometry.setDrawRange(0, numToDraw);\r\n });\r\n });\r\n }\r\n\r\n updateCrossSection(start, end, width) {\r\n this.clouds.forEach(pointcloud => {\r\n let material = pointcloud.materialScene;\r\n material.crossSectionStart = start;\r\n material.crossSectionEnd = end;\r\n material.crossSectionWidth = width;\r\n material.needsUpdate = true;\r\n });\r\n }\r\n\r\n calculatePointsVisible() {\r\n let visibleNodes = this.scene.children\r\n .filter(x => x instanceof Points)\r\n .filter(x => x.visible) as Points[];\r\n\r\n this.numVisiblePoints = 0;\r\n this.numSceneNodesVisible = visibleNodes.length;\r\n\r\n visibleNodes.forEach(node => {\r\n let geometry = node.geometry as BufferGeometry;\r\n let numPoints = geometry.attributes.position.count;\r\n let numVisible = Math.min(numPoints, geometry.drawRange.count);\r\n this.numVisiblePoints += numVisible;\r\n });\r\n }\r\n\r\n updateVisibilityTexture(cloud: StreamablePointCloud, material) {\r\n // Static sizing, exit the function\r\n if (!material.adaptiveSize) return;\r\n\r\n let nodes = cloud.getVisibleNodes();\r\n let texture = material.visibleNodesTexture;\r\n let data = texture.image.data;\r\n\r\n let nodeMap = new Map();\r\n let visibleNodeTextureOffsets = new Map();\r\n let offsetsToChild = new Array(nodes.length).fill(Infinity);\r\n\r\n // Clear previous values\r\n for (let i = 0; i < data.length; i++) {\r\n data[i] = 0;\r\n }\r\n\r\n nodes.forEach((node, nodeIndex) => {\r\n nodeMap.set(node.name, node);\r\n visibleNodeTextureOffsets.set(node, nodeIndex);\r\n\r\n if (nodeIndex > 0) {\r\n let index = parseInt(node.name.slice(-1));\r\n let parentName = node.name.slice(0, -1);\r\n let parent = nodeMap.get(parentName);\r\n let parentOffset = visibleNodeTextureOffsets.get(parent);\r\n\r\n let parentOffsetToChild = (nodeIndex - parentOffset);\r\n\r\n offsetsToChild[parentOffset] = Math.min(offsetsToChild[parentOffset], parentOffsetToChild);\r\n\r\n data[parentOffset * 4 + 0] = data[parentOffset * 4 + 0] | (1 << index);\r\n data[parentOffset * 4 + 1] = (offsetsToChild[parentOffset] >> 8);\r\n data[parentOffset * 4 + 2] = (offsetsToChild[parentOffset] % 256);\r\n }\r\n\r\n let lodOffset = 0.0;\r\n let density = node.density;\r\n\r\n if (typeof density === \"number\" && !Number.isNaN(density)) {\r\n lodOffset = Math.log2(density) / 2 - 1.5;\r\n }\r\n\r\n let offsetUint8 = (lodOffset + 10) * 10;\r\n data[nodeIndex * 4 + 3] = offsetUint8;\r\n });\r\n\r\n texture.needsUpdate = true;\r\n }\r\n\r\n updateClipBoxTexture(material: PointCloudMaterial) {\r\n let pointMarkup = this.controls.pointMarkup;\r\n let texture = material.clipBoxTexture;\r\n\r\n let clippingBoxes = pointMarkup.clippingBoxes;\r\n let numClipBoxes = clippingBoxes.length;\r\n\r\n clippingBoxes.forEach((clippingBox, index) => {\r\n if (index >= texture.image.width) return;\r\n\r\n const position = clippingBox.position;\r\n const scale = clippingBox.scale;\r\n const hidePoints = clippingBox.hidePoints;\r\n const updateClassification = clippingBox.updateClassification;\r\n const newClassification = clippingBox.newClassification;\r\n const ignoredClassification = clippingBox.ignoredClassification;\r\n const inverse = getEulerInverse(clippingBox.rotation);\r\n\r\n // position\r\n assignPackedData(texture, index, 0, position.x);\r\n assignPackedData(texture, index, 1, position.y);\r\n assignPackedData(texture, index, 2, position.z);\r\n\r\n // scale\r\n assignPackedData(texture, index, 3, scale.x);\r\n assignPackedData(texture, index, 4, scale.y);\r\n assignPackedData(texture, index, 5, scale.z);\r\n\r\n // rotation\r\n assignPackedData(texture, index, 6, inverse.x);\r\n assignPackedData(texture, index, 7, inverse.y);\r\n assignPackedData(texture, index, 8, inverse.z);\r\n\r\n assignPackedData(texture, index, 9, hidePoints);\r\n assignPackedData(texture, index, 10, updateClassification);\r\n assignPackedData(texture, index, 11, newClassification);\r\n assignPackedData(texture, index, 12, ignoredClassification);\r\n });\r\n\r\n if (numClipBoxes > 0) {\r\n texture.needsUpdate = true;\r\n }\r\n\r\n material.updateNumClippingBoxes(numClipBoxes);\r\n }\r\n\r\n updateAreaTriangleTexture(material) {\r\n let texture = material.areaTriangleTexture;\r\n\r\n const controller = this.controls.measurements;\r\n let areaGeometry = controller.getAreaGeometry();\r\n\r\n let numAreaTriangles = 0;\r\n areaGeometry.forEach(data => {\r\n data.indices.forEach(triangleIndex => {\r\n let index = numAreaTriangles;\r\n if (index >= texture.image.width) {\r\n return;\r\n }\r\n\r\n // volume status\r\n assignPackedData(texture, index, 0, data.volumeStatus);\r\n\r\n // vertex #1\r\n let vertex1 = data.vertices[triangleIndex[0]];\r\n assignPackedData(texture, index, 1, vertex1.x);\r\n assignPackedData(texture, index, 2, vertex1.y);\r\n assignPackedData(texture, index, 3, vertex1.z);\r\n\r\n // vertex #2\r\n let vertex2 = data.vertices[triangleIndex[1]];\r\n assignPackedData(texture, index, 4, vertex2.x);\r\n assignPackedData(texture, index, 5, vertex2.y);\r\n assignPackedData(texture, index, 6, vertex2.z);\r\n\r\n // vertex #3\r\n let vertex3 = data.vertices[triangleIndex[2]];\r\n assignPackedData(texture, index, 7, vertex3.x);\r\n assignPackedData(texture, index, 8, vertex3.y);\r\n assignPackedData(texture, index, 9, vertex3.z);\r\n\r\n numAreaTriangles += 1;\r\n });\r\n });\r\n\r\n if (numAreaTriangles > 0) {\r\n texture.needsUpdate = true;\r\n }\r\n\r\n material.updateNumAreaTriangles(numAreaTriangles);\r\n }\r\n\r\n pointsInRadius(position, size) {\r\n var points = [];\r\n\r\n this.clouds.forEach(cloud => {\r\n // Grab valid nodes\r\n let nodes = cloud.getVisibleNodes((node: PointCloudNode) => {\r\n let dx = Math.abs(node.center.x - position.x);\r\n let dy = Math.abs(node.center.y - position.y);\r\n\r\n return !((dx > node.nodeSize) || (dy > node.nodeSize));\r\n });\r\n\r\n // Grab valid points\r\n nodes.forEach(node => {\r\n let geometry = node.pointsScene.geometry as BufferGeometry;\r\n let positions = geometry.attributes.position;\r\n\r\n for (var i = 0; i < positions.count; i++) {\r\n let x = positions.getX(i) + node.pointsScene.position.x;\r\n let y = positions.getY(i) + node.pointsScene.position.y;\r\n let z = positions.getZ(i) + node.pointsScene.position.z;\r\n\r\n let dx = Math.abs(x - position.x);\r\n let dy = Math.abs(y - position.y);\r\n\r\n if ((dx > size) || (dy > size)) {\r\n continue;\r\n }\r\n\r\n let point = new Vector3(x, y, z);\r\n points.push(point);\r\n }\r\n });\r\n });\r\n\r\n return points;\r\n }\r\n\r\n pointsInPolygon(points, vertices) {\r\n let pointsInPolygon = [];\r\n\r\n points.forEach(point => {\r\n if (pointInPolygon(point, vertices)) {\r\n pointsInPolygon.push(point);\r\n }\r\n });\r\n\r\n return pointsInPolygon;\r\n }\r\n\r\n getSampledPoints(points, highest, keyfunc) {\r\n let samples = {};\r\n points.forEach(point => {\r\n let key = keyfunc(point);\r\n if (!(key in samples)) {\r\n samples[key] = [];\r\n }\r\n\r\n samples[key].push(point);\r\n });\r\n\r\n let dtmPoints = [];\r\n let keys = Object.keys(samples);\r\n keys.forEach(key => {\r\n let data = samples[key];\r\n data.sort((a, b) => (a.z > b.z) ? 1 : -1);\r\n\r\n let sampled = highest\r\n ? data[data.length - 1]\r\n : data[0];\r\n\r\n dtmPoints.push(sampled);\r\n });\r\n\r\n return dtmPoints;\r\n }\r\n\r\n manageStreamableCache() {\r\n let stack = [];\r\n let unusedNodes = [];\r\n let numVisible = 0;\r\n let numHidden = 0;\r\n\r\n this.streamablePointClouds.forEach(cloud => {\r\n if (!cloud.root) return;\r\n stack.push(cloud.root);\r\n });\r\n\r\n while (stack.length > 0) {\r\n let object = stack.shift();\r\n\r\n if (object.visible) {\r\n numVisible++;\r\n } else if (object.loaded) {\r\n numHidden++;\r\n unusedNodes.push(object);\r\n } else {\r\n continue;\r\n }\r\n\r\n object.children.forEach(child => {\r\n stack.push(child);\r\n });\r\n }\r\n\r\n const numberOfNodes = numVisible + numHidden;\r\n if (numberOfNodes < this.streamableCacheSize) return;\r\n\r\n let numberToDelete = numberOfNodes - this.streamableCacheSize;\r\n numberToDelete = Math.min(numberToDelete, numHidden);\r\n if (numberToDelete === 0) return;\r\n\r\n // Delete unused nodes\r\n unusedNodes.reverse();\r\n unusedNodes = unusedNodes.slice(0, numberToDelete);\r\n unusedNodes.forEach(node => {\r\n node.dispose();\r\n });\r\n }\r\n\r\n manageGenericCache() {\r\n let unusedNodes = [];\r\n let numVisible = 0;\r\n let numHidden = 0;\r\n\r\n const fov = MathUtils.degToRad(this.fov);\r\n\r\n this.genericPointClouds.forEach(cloud => {\r\n if (!cloud.root) return;\r\n\r\n cloud.root.children.forEach(child => {\r\n if (child.visible) {\r\n numVisible++;\r\n } else if (child.loaded) {\r\n numHidden++;\r\n\r\n\r\n const distance = child.center.distanceTo(this.cameraPosition);\r\n const insideSphere = distance < child.radius;\r\n const projFactor = getProjFactor(fov, distance, this.screenHeight);\r\n const nodeScreenSize = child.radius * projFactor;\r\n\r\n const weight = insideSphere\r\n ? Number.MAX_VALUE\r\n : nodeScreenSize;\r\n\r\n unusedNodes.push({\r\n node: child,\r\n weight\r\n });\r\n }\r\n });\r\n });\r\n\r\n const numberOfNodes = numVisible + numHidden;\r\n if (numberOfNodes < this.genericCacheSize) return;\r\n\r\n let numberToDelete = numberOfNodes - this.genericCacheSize;\r\n numberToDelete = Math.min(numberToDelete, numHidden);\r\n if (numberToDelete === 0) return;\r\n\r\n // Delete unused nodes\r\n unusedNodes.sort((a, b) => a.weight - b.weight);\r\n unusedNodes = unusedNodes.slice(0, numberToDelete);\r\n unusedNodes.forEach(({node}) => {\r\n node.dispose();\r\n });\r\n }\r\n\r\n loadGenericPointClouds() {\r\n const loadingClouds = this.genericPointClouds.filter(cloud => {\r\n return cloud.loading\r\n && cloud.visible;\r\n });\r\n\r\n const unloadedClouds = this.genericPointClouds.filter(cloud => {\r\n return !cloud.loaded\r\n && !cloud.loading\r\n && cloud.visible;\r\n });\r\n\r\n let numLoading = loadingClouds.length;\r\n if (numLoading >= this.maxUnloadedClouds) return;\r\n\r\n // Wait between launching exes\r\n let timeSinceLaunch = performance.now() - this.lastExeLaunched;\r\n if (timeSinceLaunch < this.exeLaunchTimeout) {\r\n return;\r\n }\r\n\r\n // Load the next available point cloud\r\n let cloud = unloadedClouds.shift();\r\n if (!cloud) return;\r\n\r\n this.lastExeLaunched = performance.now();\r\n cloud.loadFromExe();\r\n }\r\n\r\n loadStreamablePointClouds() {\r\n const loadingClouds = this.streamablePointClouds.filter(cloud => {\r\n return cloud.loading\r\n && cloud.visible;\r\n });\r\n\r\n const unloadedClouds = this.streamablePointClouds.filter(cloud => {\r\n return !cloud.loaded\r\n && !cloud.loading\r\n && cloud.visible;\r\n });\r\n\r\n let numLoading = loadingClouds.length;\r\n\r\n for (let cloud of unloadedClouds) {\r\n if (numLoading >= this.maxUnloadedClouds) return;\r\n cloud.loadMetadata();\r\n numLoading += 1;\r\n }\r\n }\r\n\r\n loadUnloadedGeometry() {\r\n\r\n const genericPointCloudNodes = this.unloadedNodes\r\n .filter(node => node instanceof GenericPointCloudNode);\r\n\r\n // Load one node at a time for generic point clouds\r\n const maxUnloaded = genericPointCloudNodes.length === 0\r\n ? this.maxUnloadedNodes\r\n : 1;\r\n\r\n for (let node of this.unloadedNodes) {\r\n if (node.loaded || node.loading) continue;\r\n if (this.numNodesLoading >= maxUnloaded) continue;\r\n\r\n this.numNodesLoading += 1;\r\n\r\n node.load().then(() => {\r\n this.numNodesLoading -= 1;\r\n });\r\n };\r\n }\r\n\r\n updateGenericPointClouds(frustum: Frustum) {\r\n if (isStaticSite || !this.shouldUpdate) return;\r\n\r\n this.genericPointClouds.forEach(cloud => {\r\n cloud.hideDescendants();\r\n });\r\n\r\n this.calculateGenericVisibility(frustum);\r\n this.manageGenericCache();\r\n }\r\n\r\n updateStreamablePointClouds(frustum: Frustum) {\r\n if (!this.shouldUpdate) return;\r\n\r\n this.streamablePointClouds.forEach(cloud => {\r\n cloud.hideDescendants();\r\n });\r\n\r\n this.calculateStreamableVisibility(frustum);\r\n this.manageStreamableCache();\r\n }\r\n\r\n /** @private */\r\n calculateGenericVisibility(frustum: Frustum) {\r\n if (this.cameraHandler.waitForCameras) return;\r\n\r\n const fov = MathUtils.degToRad(this.fov);\r\n const priorityQueue = new BinaryHeap(x => 1 / x.weight);\r\n\r\n // Add all possible nodes to queue\r\n this.genericPointClouds.forEach(cloud => {\r\n if (!cloud.visible || !cloud.root) return;\r\n\r\n const node = cloud.root;\r\n const distance = node.center.distanceTo(this.cameraPosition);\r\n const insideSphere = distance < node.radius;\r\n const projFactor = getProjFactor(fov, distance, this.screenHeight);\r\n const nodeScreenSize = node.radius * projFactor;\r\n\r\n const weight = insideSphere\r\n ? Number.MAX_VALUE\r\n : nodeScreenSize;\r\n\r\n priorityQueue.push({node, weight});\r\n });\r\n\r\n let numLoadedPoints = 0;\r\n let loadedPointClouds = new Set();\r\n\r\n while (priorityQueue.size > 0) {\r\n const element = priorityQueue.pop();\r\n const node = element.node as GenericPointCloudNode;\r\n\r\n if (loadedPointClouds.size >= this.maxGenericFilesVisible) break;\r\n\r\n for (let child of node.children) {\r\n // Make sure pointcloud node is visible\r\n if (!child.isVisible(frustum)) continue;\r\n\r\n loadedPointClouds.add(node.cloud.identifier);\r\n\r\n // Add node to scene if data is loaded, or else add to unloaded list\r\n if (child.isGeometryNode) {\r\n if (child.loaded && !this.loadedToGPUThisFrame) {\r\n child.addToScene();\r\n this.loadedToGPUThisFrame = true;\r\n } else {\r\n this.unloadedNodes.push(child);\r\n }\r\n }\r\n\r\n // Update node visibility for loaded nodes\r\n if (child.isTreeNode) {\r\n child.setVisibility(true, this.boundsVisible);\r\n numLoadedPoints += child.numPoints;\r\n }\r\n }\r\n }\r\n\r\n this.numLoadedPoints += numLoadedPoints;\r\n }\r\n\r\n /** @private */\r\n calculateStreamableVisibility(frustum: Frustum) {\r\n if (this.cameraHandler.waitForCameras) return;\r\n\r\n const fov = MathUtils.degToRad(this.fov);\r\n const minNodeSize = this.minStreamableNodeSize;\r\n const totalPointsTarget = this.visiblePointsTarget;\r\n const singleCloudLimit = this.visiblePointsPerCloud;\r\n const priorityQueue = new BinaryHeap(x => 1 / x.weight);\r\n\r\n let totalPointsLoaded = 0;\r\n let cloudPointsLoaded = {};\r\n\r\n this.streamablePointClouds.forEach(cloud => {\r\n if (!cloud.visible || !cloud.root) return;\r\n\r\n // Push root node to queue\r\n priorityQueue.push({\r\n node: cloud.root,\r\n weight: Number.MAX_VALUE\r\n });\r\n\r\n cloudPointsLoaded[cloud.identifier] = 0;\r\n });\r\n\r\n while (priorityQueue.size > 0) {\r\n const element = priorityQueue.pop();\r\n const node = element.node as StreamablePointCloudNode;\r\n const cloudID = node.cloud.identifier;\r\n\r\n // Total number of points loaded must under the user limit\r\n const projectPointsTarget = totalPointsLoaded + node.numPoints;\r\n if (projectPointsTarget >= totalPointsTarget) {\r\n continue;\r\n }\r\n\r\n // Individual number of points must be under the fixed limit\r\n const cloudPointsTarget = cloudPointsLoaded[cloudID] + node.numPoints;\r\n if (cloudPointsTarget >= singleCloudLimit) {\r\n continue;\r\n }\r\n\r\n // Make sure pointcloud node is visible\r\n if (!node.isVisible(frustum)) continue;\r\n\r\n if (node.isGeometryNode && (!node.parent || node.parent.isTreeNode)) {\r\n if (node.loaded && !this.loadedToGPUThisFrame) {\r\n node.addToScene();\r\n this.loadedToGPUThisFrame = true;\r\n } else {\r\n this.unloadedNodes.push(node);\r\n }\r\n }\r\n\r\n if (node.isTreeNode) {\r\n node.setVisibility(true, this.boundsVisible);\r\n totalPointsLoaded += node.numPoints;\r\n cloudPointsLoaded[cloudID] += node.numPoints;\r\n }\r\n\r\n node.children.forEach((child: StreamablePointCloudNode) => {\r\n const childDistance = child.center.distanceTo(this.cameraPosition);\r\n const insideSphere = childDistance < child.radius;\r\n\r\n // Pixel size based filtering\r\n const projFactor = getProjFactor(fov, childDistance, this.screenHeight);\r\n const nodeScreenSize = child.radius * projFactor;\r\n if (nodeScreenSize < minNodeSize) return;\r\n\r\n const weight = insideSphere\r\n ? Number.MAX_VALUE\r\n : nodeScreenSize;\r\n\r\n priorityQueue.push({\r\n node: child,\r\n weight: weight\r\n });\r\n });\r\n }\r\n\r\n this.numLoadedPoints += totalPointsLoaded;\r\n }\r\n\r\n updateMaterials() {\r\n this.clouds.forEach(cloud => {\r\n let numVisibleNodes = cloud.getVisibleNodes().length;\r\n if (numVisibleNodes === 0) return;\r\n\r\n cloud.materials.forEach(material => {\r\n if (!material || !cloud.root) return;\r\n\r\n this.updateUniforms(cloud, material);\r\n\r\n if (!material.gpuPicker) {\r\n this.updateAreaTriangleTexture(material);\r\n this.updateClipBoxTexture(material);\r\n }\r\n\r\n if (cloud instanceof StreamablePointCloud) {\r\n this.updateVisibilityTexture(cloud, material);\r\n }\r\n });\r\n });\r\n }\r\n\r\n update() {\r\n this.numLoadedPoints = 0;\r\n this.loadedToGPUThisFrame = false;\r\n this.unloadedNodes = [];\r\n\r\n const frustum = this.viewer.getCameraFrustum();\r\n\r\n // Update clouds based on current view\r\n this.updateGenericPointClouds(frustum);\r\n this.updateStreamablePointClouds(frustum);\r\n\r\n // Load unloaded geometry data\r\n this.loadUnloadedGeometry();\r\n\r\n // Start loading point clouds\r\n this.loadGenericPointClouds();\r\n this.loadStreamablePointClouds();\r\n\r\n // Update material and texture data\r\n this.updateMaterials();\r\n\r\n // Sample raw pointclouds based on total points loaded\r\n this.updateCloudSampling();\r\n\r\n this.calculatePointsVisible();\r\n }\r\n}","import { PointCloudNode, PointCloud, PointCloudManager } from '.';\r\nimport LocalScene from '../projections';\r\nimport { PythonExecutable } from '../../executable';\r\nimport { Box3, LineSegments, Points, Vector3 } from 'three';\r\nimport { toast } from '../../app';\r\nimport { t } from '../../localization';\r\nimport { readFileBuffer } from '../file-system-loader';\r\nimport { fse, tempDirectoryPath } from '../../electron-modules';\r\nimport { AsyncWorkerPool } from '../worker-pool';\r\n\r\nconst workerPool = new AsyncWorkerPool(\"point-decoder-buffer.js\");\r\n\r\ninterface HeaderResponse {\r\n maxs: [number, number, number];\r\n mins: [number, number, number];\r\n mean: [number, number, number];\r\n size: [number, number, number];\r\n number_of_bytes: number;\r\n points_to_process: number;\r\n version: string;\r\n file_info?: any;\r\n}\r\n\r\ninterface PointsResponse {\r\n xyz_min: [number, number, number];\r\n xyz_max: [number, number, number];\r\n offset: [number, number, number];\r\n unique_classes: number[];\r\n precision: number;\r\n num_points: number;\r\n intensity_min: number;\r\n intensity_max: number;\r\n rgb_max: number;\r\n point_count: number;\r\n bytes_path: string;\r\n}\r\n\r\n\r\n/** Processed pointcloud node */\r\nexport class GenericPointCloudNode extends PointCloudNode {\r\n public cloud: GenericPointCloud;\r\n public parent: GenericPointCloudRootNode;\r\n private path = null;\r\n private precision;\r\n private _shift;\r\n\r\n constructor(cloud, parent) {\r\n super();\r\n\r\n this.cloud = cloud;\r\n this.parent = parent;\r\n }\r\n\r\n get shift() {\r\n return this._shift;\r\n }\r\n\r\n set shift(value) {\r\n this._shift = value;\r\n }\r\n\r\n decodeMetadata(data: PointsResponse) {\r\n this.numPoints = data.num_points;\r\n this.path = data.bytes_path;\r\n this.precision = data.precision;\r\n\r\n // Convert array to vector\r\n const xyzMin = new Vector3(...data.xyz_min);\r\n const xyzMax = new Vector3(...data.xyz_max);\r\n const offset = new Vector3(...data.offset);\r\n\r\n // Calculate bounding box size\r\n let size = new Vector3()\r\n .add(xyzMax)\r\n .sub(xyzMin);\r\n\r\n // Calculate bounding box center\r\n let center = new Vector3()\r\n .add(xyzMin)\r\n .add(xyzMax)\r\n .divideScalar(2.0)\r\n .sub(offset);\r\n\r\n this.nodeSize = Math.max(size.x, size.y, size.z);\r\n this.edgeSize = size;\r\n this.nodeCenter = center;\r\n\r\n // Safe to add to parent's child list now\r\n this.parent.addChildNode(this);\r\n\r\n // Update root node info\r\n this.shift = LocalScene.offsetToScene(offset);\r\n\r\n this.cloud.updateClassifications(data.unique_classes);\r\n this.cloud.updateColorLimits(data.rgb_max);\r\n this.cloud.updateIntensityRange(\r\n data.intensity_min,\r\n data.intensity_max\r\n );\r\n\r\n const boundingBox = new Box3(xyzMin, xyzMax);\r\n this.cloud.updateBoundingBox(boundingBox);\r\n\r\n this.cloud.updateRootNode();\r\n }\r\n\r\n getGeometry(data) {\r\n this.setGeometry(data);\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n\r\n async getBinaryData() {\r\n const buffer = await readFileBuffer(this.path);\r\n\r\n const values = {\r\n buffer: buffer,\r\n precision: this.precision,\r\n numPoints: this.numPoints\r\n };\r\n\r\n const data = await workerPool.postMessage(values, [values.buffer]);\r\n\r\n // Convert raw buffer to float array\r\n data.positions = new Float32Array(data.positions);\r\n data.intensity = new Float32Array(data.intensity);\r\n data.classification = new Float32Array(data.classification);\r\n data.colors = new Float32Array(data.colors);\r\n\r\n return data;\r\n }\r\n\r\n async load() {\r\n if ((this.loaded) || (this.loading)) return;\r\n\r\n this.loading = true;\r\n\r\n const data = await this.getBinaryData();\r\n this.getGeometry(data);\r\n }\r\n}\r\n\r\n/** Simulated processed pointcloud root node */\r\nclass GenericPointCloudRootNode extends GenericPointCloudNode {\r\n constructor(cloud) {\r\n super(cloud, null);\r\n\r\n this.numPoints = 0;\r\n this.boundingBoxMesh = new LineSegments();\r\n this.nodeCenter = new Vector3();\r\n this.nodeSize = 0;\r\n }\r\n\r\n get center() {\r\n return this.nodeCenter;\r\n }\r\n\r\n /** Function override */\r\n dispose() {\r\n this.pointsScene = null;\r\n this.pointsPicker = null;\r\n this.boundingBoxMesh = null;\r\n }\r\n\r\n updateSizeInfo(data) {\r\n // Calculate bounding box size\r\n let size = new Vector3()\r\n .add(data.max)\r\n .sub(data.min);\r\n\r\n // Calculate bounding box center\r\n let center = new Vector3()\r\n .add(data.min)\r\n .add(data.max)\r\n .divideScalar(2.0);\r\n\r\n this.nodeSize = Math.max(size.x, size.y, size.z);\r\n this.edgeSize = size;\r\n this.nodeCenter = center;\r\n\r\n // Reset bounding box\r\n this._boundingBox = null;\r\n }\r\n\r\n async load() {\r\n if ((this.loaded) || (this.loading)) return;\r\n\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n\r\n getGeometry() {\r\n return;\r\n }\r\n\r\n addToScene() {\r\n this.pointsScene = new Points();\r\n this.pointsPicker = new Points();\r\n }\r\n}\r\n\r\n/** Processed pointcloud */\r\nexport class GenericPointCloud extends PointCloud {\r\n private workerExe: PythonExecutable;\r\n public root: GenericPointCloudRootNode = null;\r\n private file = null;\r\n private header: HeaderResponse;\r\n public loaded = false;\r\n public loading = false;\r\n private cancelled = false;\r\n private byteCutoffSize = 10 * 1024**3;\r\n private pointsDataParsed = 0;\r\n private numSampledPoints = 5000000;\r\n private numSampledChunks = 10;\r\n public isLargeFile = false;\r\n private dataPaths = [];\r\n public percent;\r\n\r\n constructor(pointclouds: PointCloudManager) {\r\n super(pointclouds);\r\n this.workerExe = new PythonExecutable();\r\n }\r\n\r\n get shift() {\r\n return LocalScene.sceneOffset;\r\n }\r\n\r\n get size() {\r\n return Math.max.apply(null, this.header.size);\r\n }\r\n\r\n /** Get bounding box with global shift applied */\r\n get tightBoundingBox(): Box3 {\r\n let bbox = this._tightBoundingBox;\r\n if (!bbox) return null;\r\n\r\n return new Box3(\r\n new Vector3().add(bbox.min).sub(this.shift),\r\n new Vector3().add(bbox.max).sub(this.shift)\r\n );\r\n }\r\n\r\n /** Get estimated bounding box using header information */\r\n get estimatedBoundingBox(): Box3 {\r\n return new Box3(\r\n new Vector3(...this.header.mins).sub(this.shift),\r\n new Vector3(...this.header.maxs).sub(this.shift)\r\n );\r\n }\r\n\r\n get headerFileInfo() {\r\n return this.header?.file_info;\r\n }\r\n\r\n get saved() {\r\n return this.file.saved;\r\n }\r\n\r\n removeTempFiles() {\r\n for (let filePath of this.dataPaths) {\r\n fse.removeSync(filePath);\r\n }\r\n\r\n this.dataPaths = [];\r\n }\r\n\r\n dispose() {\r\n this.setState(false);\r\n this.disposeNodes();\r\n\r\n this.cancelled = true;\r\n this.workerExe.destroy();\r\n }\r\n\r\n onFinish() {\r\n this.loading = false;\r\n this.loaded = true;\r\n this.updatePercent(100);\r\n }\r\n\r\n onProgress() {\r\n let points_to_process = this.header.points_to_process;\r\n let percent = this.pointsDataParsed / points_to_process;\r\n this.updatePercent(100 * percent);\r\n }\r\n\r\n updatePercent(percent) {\r\n this.percent = percent;\r\n }\r\n\r\n updateRootNode() {\r\n this.root.updateSizeInfo(this.tightBoundingBox);\r\n }\r\n\r\n load(file) {\r\n this.file = file;\r\n this.pointsDataParsed = 0;\r\n\r\n // Add pointcloud and set parameters\r\n this.pointclouds.addPointCloud(this);\r\n this.setIdentifier(file.identifier);\r\n this.setVisibility(file.visible);\r\n this.updatePercent(0);\r\n }\r\n\r\n loadFromExe() {\r\n this.loading = true;\r\n\r\n const lasFilePath = this.file.path;\r\n const minChunkSize = this.numSampledPoints / this.numSampledChunks;\r\n\r\n let commands = [\r\n \"-p\", \"convert_engine_points\",\r\n \"--input_file\", lasFilePath,\r\n \"--output_folder\", tempDirectoryPath,\r\n \"--units\", LocalScene.dataProjectionUnits,\r\n \"--min_chunk_size\", minChunkSize,\r\n \"--max_points\", this.numSampledPoints\r\n ];\r\n\r\n this.workerExe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (!jsonData) return;\r\n const {type, data} = jsonData;\r\n\r\n if (type === \"header\") {\r\n this.parseHeaderResponse(data);\r\n } else if (type === \"points\") {\r\n this.parsePointsResponse(data);\r\n }\r\n },\r\n onClose: () => {\r\n if (this.cancelled) return;\r\n\r\n const pointsToProcess = this.header?.points_to_process;\r\n const allPointsLoaded = pointsToProcess === this.pointsDataParsed;\r\n\r\n if (!allPointsLoaded) {\r\n this.error = true;\r\n toast.error(t(\"toast.points-load-error\", {\r\n name: this.file.name\r\n }));\r\n }\r\n\r\n this.onFinish();\r\n }\r\n });\r\n }\r\n\r\n checkForLargeFile() {\r\n this.isLargeFile = this.header\r\n ? this.header.number_of_bytes > this.byteCutoffSize\r\n : false;\r\n\r\n if (this.isLargeFile) {;\r\n toast.warning(t(\"toast.large-point-cloud\", {\r\n name: this.file.name\r\n }));\r\n }\r\n }\r\n\r\n parseHeaderResponse(data: HeaderResponse) {\r\n this.header = data;\r\n this.root = new GenericPointCloudRootNode(this);\r\n this.checkForLargeFile();\r\n }\r\n\r\n parsePointsResponse(data: PointsResponse) {\r\n if (this.cancelled) return;\r\n\r\n this.dataPaths.push(data.bytes_path);\r\n\r\n // Update loaded percent\r\n this.pointsDataParsed += data.point_count;\r\n this.onProgress();\r\n\r\n // Add new node to pointcloud\r\n let child = new GenericPointCloudNode(this, this.root);\r\n child.decodeMetadata(data);\r\n\r\n this.pointclouds.updateMinimapExtent();\r\n\r\n if (this.saved) return;\r\n\r\n this.viewer.zoomToSceneExtent(this.estimatedBoundingBox, false);\r\n }\r\n\r\n getVisibleNodes(condition?): PointCloudNode[] {\r\n let visibleNodes = [];\r\n\r\n // All data for raw pointclouds is contained in a single level\r\n this.root?.children.forEach(node => {\r\n if (!node.visible) return;\r\n if (condition && !condition(node)) return;\r\n\r\n visibleNodes.push(node);\r\n });\r\n\r\n return visibleNodes;\r\n }\r\n\r\n hideDescendants() {\r\n if (!this.root) return;\r\n\r\n [this.root, ...this.root.children].forEach(node => {\r\n node.setVisibility(false, false);\r\n });\r\n }\r\n}\r\n","import { Vector3 } from \"three\";\r\nimport { PointCloud, PointCloudManager } from \".\";\r\nimport { toast } from \"../../app\";\r\nimport { t } from \"../../localization\";\r\nimport { readFileJSON } from \"../file-system-loader\";\r\nimport { PointCloudNode } from \"./point-cloud\";\r\n\r\n/** Base class for streamable cloud node */\r\nexport class StreamablePointCloudNode extends PointCloudNode {\r\n public cloud: StreamablePointCloud;\r\n public parent: StreamablePointCloudNode;\r\n protected level: number;\r\n\r\n constructor(name: string, level: number, center: Vector3, size: number) {\r\n super();\r\n\r\n this.name = name;\r\n this.level = level;\r\n this.nodeSize = size;\r\n this.edgeSize = new Vector3().addScalar(size);\r\n this.nodeCenter = center;\r\n }\r\n\r\n get shift() {\r\n return this.cloud.shift;\r\n }\r\n\r\n getChildOffset(index) {\r\n console.warn(\"Not implemented\");\r\n return {x: 0, y: 0, z: 0};\r\n }\r\n\r\n addChildNode(node) {\r\n this.children.push(node);\r\n\r\n // Make sure child nodes are sorted by index\r\n this.children.sort((a,b) => {\r\n let indexA = parseInt(a.name.slice(-1));\r\n let indexB = parseInt(b.name.slice(-1));\r\n return indexA - indexB;\r\n });\r\n }\r\n\r\n getChildNode(index) {\r\n const childName = `${this.name}${index}`;\r\n const childSize = this.nodeSize / 2.0;\r\n const childLevel = this.level + 1;\r\n\r\n const {x,y,z} = this.getChildOffset(index);\r\n\r\n const childCenter = new Vector3(\r\n this.nodeCenter.x + (x - 0.5) * childSize,\r\n this.nodeCenter.y + (y - 0.5) * childSize,\r\n this.nodeCenter.z + (z - 0.5) * childSize\r\n );\r\n\r\n const NodeConstructor = this.constructor as any;\r\n return new NodeConstructor(this.cloud, this, childName,\r\n childLevel, childCenter, childSize);\r\n }\r\n}\r\n\r\n/** Base class for streamable cloud */\r\nexport class StreamablePointCloud extends PointCloud {\r\n public loaded = false;\r\n public loading = false;\r\n public spacing = null;\r\n protected structure = null;\r\n private _shift;\r\n\r\n constructor(pointclouds: PointCloudManager) {\r\n super(pointclouds);\r\n }\r\n\r\n get shift() {\r\n return this._shift;\r\n }\r\n\r\n set shift(value) {\r\n this._shift = value;\r\n }\r\n\r\n get size() {\r\n return this.root.nodeSize;\r\n }\r\n\r\n get dataDir() {\r\n return this.structure.path;\r\n }\r\n\r\n get saved() {\r\n return this.structure.saved;\r\n }\r\n\r\n get metadataPath() {\r\n console.warn(\"Not implemented\");\r\n return \"\";\r\n }\r\n\r\n async load(structure) {\r\n this.structure = structure;\r\n\r\n // Add pointcloud and set parameters\r\n this.pointclouds.addPointCloud(this);\r\n this.setName(structure.name);\r\n this.setVisibility(structure.visible);\r\n this.setIdentifier(structure.identifier);\r\n }\r\n\r\n async loadMetadata() {\r\n this.loading = true;\r\n\r\n try {\r\n // Read index data\r\n const metadata = await readFileJSON(this.metadataPath);\r\n this.decodeMetadata(metadata);\r\n } catch(err) {\r\n this.error = true;\r\n console.error(err);\r\n toast.error(t(\"toast.points-load-error\", {\r\n name: this.structure.name\r\n }));\r\n } finally {\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n }\r\n\r\n decodeMetadata(data) {\r\n console.warn(\"Not implemented\");\r\n }\r\n\r\n getVisibleNodes(condition?): PointCloudNode[] {\r\n let visibleNodes = [];\r\n if (!this.root) return visibleNodes;\r\n\r\n let stack = [this.root];\r\n while (stack.length > 0) {\r\n let node = stack.shift();\r\n\r\n if (!node.visible) continue;\r\n if (condition && !condition(node)) continue;\r\n\r\n visibleNodes.push(node);\r\n node.children.forEach(child => {\r\n stack.push(child);\r\n });\r\n }\r\n\r\n return visibleNodes;\r\n }\r\n\r\n hideDescendants() {\r\n if (!this.root) return;\r\n\r\n let stack = [this.root];\r\n\r\n while (stack.length > 0) {\r\n let object = stack.shift();\r\n if (!object.visible) {\r\n continue;\r\n }\r\n\r\n object.setVisibility(false, false);\r\n object.children.forEach(child => {\r\n stack.push(child);\r\n });\r\n }\r\n }\r\n}\r\n","import { PointCloudManager, StreamablePointCloud, StreamablePointCloudNode, getClassificationHistogram } from '.';\r\nimport { readFileBuffer, readFileJSON} from \"../file-system-loader\";\r\nimport LocalScene from '../projections';\r\nimport { Box3, Vector3 } from 'three';\r\nimport { AsyncWorkerPool } from '../worker-pool';\r\n\r\ntype NodeArguments = ConstructorParameters\r\n\r\nconst workerPool = new AsyncWorkerPool(\"point-decoder-encompass.js\");\r\n\r\n/** Encompass style pointcloud node */\r\nclass EncompassPointCloudNode extends StreamablePointCloudNode {\r\n public cloud: EncompassPointCloud;\r\n public parent: EncompassPointCloudNode;\r\n\r\n constructor(cloud, parent, name, level, center, size,) {\r\n super(name, level, center, size);\r\n\r\n this.cloud = cloud;\r\n this.parent = parent;\r\n }\r\n\r\n get precision() {\r\n return this.cloud.precision;\r\n }\r\n\r\n get hierarchy() {\r\n return this.cloud.hierarchy;\r\n }\r\n\r\n getChildOffset(index) {\r\n return {\r\n x: index & 0b001,\r\n y: (index & 0b010) / 2,\r\n z: (index & 0b100) / 4\r\n };\r\n }\r\n\r\n async readNodeHierarchy() {\r\n console.warn(\"Not implemented\");\r\n }\r\n\r\n async getBinaryData() {\r\n let dataPath = this.cloud.getDataPath(this.name);\r\n let nodePath = `${dataPath}/${this.name}`;\r\n\r\n let minCorner = new Vector3()\r\n .add(this.nodeCenter)\r\n .subScalar(this.nodeSize/2);\r\n\r\n // Read node data\r\n const buffer = await readFileBuffer(nodePath);\r\n\r\n const values = {\r\n buffer: buffer,\r\n name: this.name,\r\n precision: this.precision,\r\n size: this.nodeSize,\r\n corner: minCorner\r\n };\r\n\r\n const data = await workerPool.postMessage(values, [values.buffer]);\r\n\r\n // Convert array to vector\r\n data.xyz_min = new Vector3(...data.xyz_min);\r\n data.xyz_max = new Vector3(...data.xyz_max);\r\n\r\n // Convert raw buffer to float array\r\n data.positions = new Float32Array(data.positions);\r\n data.intensity = new Float32Array(data.intensity);\r\n data.classification = new Float32Array(data.classification);\r\n data.colors = new Float32Array(data.colors);\r\n\r\n return data;\r\n }\r\n\r\n getGeometry(data) {\r\n this.setGeometry(data);\r\n\r\n this.numPoints = data.num_points;\r\n this.density = data.density;\r\n\r\n // Update unique classifications\r\n const histogram = getClassificationHistogram(data.classification);\r\n this.cloud.updateClassificationFromHistogram(histogram);\r\n\r\n // Update unique values and min/max values\r\n this.cloud.updateColorLimits(data.rgb_max);\r\n this.cloud.updateIntensityRange(data.intensity_min, data.intensity_max);\r\n\r\n const boundingBox = new Box3(data.xyz_min, data.xyz_max);\r\n this.cloud.updateBoundingBox(boundingBox);\r\n\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n\r\n async load() {\r\n if ((this.loaded) || (this.loading)) return;\r\n\r\n this.loading = true;\r\n\r\n await this.readNodeHierarchy();\r\n\r\n try {\r\n const data = await this.getBinaryData();\r\n this.getGeometry(data);\r\n } catch(err) {\r\n console.error(err);\r\n if (this.level !== 1) {\r\n this.parent.removeChildNode(this);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/** Encompass cloud node with no hierarchy */\r\nclass EncompassPointCloudNodeV0 extends EncompassPointCloudNode {\r\n constructor (...args: NodeArguments) {\r\n super(...args);\r\n }\r\n\r\n async readNodeHierarchy() {\r\n // No hierarchy is provided so we assume all 8 children exist\r\n // Missing nodes will be deleted later if the data doesnt exist\r\n for (let childIndex = 0; childIndex < 8; childIndex++) {\r\n let child = this.getChildNode(childIndex);\r\n this.addChildNode(child);\r\n }\r\n }\r\n}\r\n\r\n/** Encompass cloud node hierarchy inside r.idx */\r\nclass EncompassPointCloudNodeV1 extends EncompassPointCloudNode {\r\n constructor (...args: NodeArguments) {\r\n super(...args);\r\n }\r\n\r\n async readNodeHierarchy() {\r\n // Read legacy hierarchy\r\n for (let childIndex = 0; childIndex < 8; childIndex++) {\r\n let childName = `${this.name}${childIndex}`;\r\n let childExists = this.hierarchy[childName] !== undefined;\r\n if (!childExists) continue;\r\n let child = this.getChildNode(childIndex);\r\n this.addChildNode(child);\r\n }\r\n }\r\n}\r\n\r\n/** Encompass cloud node with folder based hierarchy */\r\nclass EncompassPointCloudNodeV2 extends EncompassPointCloudNode {\r\n constructor (...args: NodeArguments) {\r\n super(...args);\r\n }\r\n\r\n get isFolderRoot() {\r\n const nodeLength = (this.name.length - 1);\r\n return nodeLength % this.cloud.folderDepth === 0;\r\n }\r\n\r\n async loadHierarchy() {\r\n let dataPath = this.cloud.getDataPath(this.name);\r\n let hrcPath = `${dataPath}/${this.name}.hrc`;\r\n\r\n try {\r\n // Read hierarchy data\r\n const hierarchy = await readFileJSON(hrcPath);\r\n this.cloud.updateHierarchy(hierarchy);\r\n } catch {\r\n console.log(`Error reading hierarchy: ${this.name}`);\r\n }\r\n }\r\n\r\n async readNodeHierarchy() {\r\n if (this.isFolderRoot) {\r\n await this.loadHierarchy();\r\n }\r\n\r\n // Update children with known hierarchy\r\n const indices = this.hierarchy[this.name];\r\n indices?.forEach(childIndex => {\r\n let child = this.getChildNode(childIndex);\r\n this.addChildNode(child);\r\n });\r\n }\r\n}\r\n\r\n/** Encompass style pointcloud */\r\nexport class EncompassPointCloud extends StreamablePointCloud {\r\n public precision;\r\n public folderDepth;\r\n public hierarchy = {};\r\n\r\n constructor(pointclouds: PointCloudManager) {\r\n super(pointclouds);\r\n }\r\n\r\n get metadataPath() {\r\n return `${this.structure.path}/r.idx`;\r\n }\r\n\r\n getDataPath(node) {\r\n let dataDir = this.dataDir;\r\n let folderDepth = this.folderDepth;\r\n\r\n if (node === \"r\") {\r\n return dataDir;\r\n }\r\n\r\n let name = node.slice(1);\r\n if ((folderDepth) && (name.length >= folderDepth)) {\r\n let dirs = name.match(new RegExp('.{' + folderDepth + '}', 'g'));\r\n dataDir = `${dataDir}/${dirs.join(\"/\")}`;\r\n }\r\n\r\n return dataDir;\r\n }\r\n\r\n /** Decode cloud metadata. Cloud is already converted to meters */\r\n decodeMetadata(data) {\r\n this.precision = data.hasOwnProperty('precision')\r\n ? data.precision\r\n : 0.005;\r\n\r\n this.folderDepth = data.hasOwnProperty('hierarchy_step_size')\r\n ? data.hierarchy_step_size\r\n : null;\r\n\r\n this.spacing = data.hasOwnProperty('spacing')\r\n ? data.spacing\r\n : Math.sqrt(2) * data.size / 250.0;\r\n\r\n const offset = new Vector3(...data.point_offset);\r\n\r\n // Get our tight bounding box if available\r\n let tightBoundingBox: Box3 = null;\r\n if (\"tight_bounding_box\" in data) {\r\n let box = data.tight_bounding_box;\r\n tightBoundingBox = new Box3(\r\n new Vector3(...box.min).sub(offset),\r\n new Vector3(...box.max).sub(offset)\r\n );\r\n }\r\n\r\n // Generate cloud root node\r\n let nodeSize = parseFloat(data.size);\r\n let nodeCenter = new Vector3(...data.center)\r\n .sub(offset);\r\n\r\n this.shift = LocalScene.offsetToScene(offset);\r\n\r\n const hasHierarchyV1 = this.checkLegacyHierarchy(data);\r\n const hasHierarchyV2 = data.hasOwnProperty('contains_hierarchy')\r\n ? data.contains_hierarchy\r\n : false;\r\n\r\n let RootNodeConstructor;\r\n if (hasHierarchyV1) {\r\n RootNodeConstructor = EncompassPointCloudNodeV1;\r\n } else if (hasHierarchyV2) {\r\n RootNodeConstructor = EncompassPointCloudNodeV2;\r\n } else {\r\n RootNodeConstructor = EncompassPointCloudNodeV0;\r\n }\r\n\r\n const rootNode = new RootNodeConstructor(\r\n this, null, \"r\", 1, nodeCenter, nodeSize);\r\n\r\n this.root = rootNode;\r\n this.updateBoundingBox(tightBoundingBox);\r\n this.pointclouds.updateMinimapExtent();\r\n\r\n if (this.saved) return;\r\n this.viewer.zoomToSceneExtent(this.tightBoundingBox, false);\r\n }\r\n\r\n updateHierarchy(hierarchy) {\r\n this.hierarchy = {\r\n ...this.hierarchy,\r\n ...hierarchy\r\n };\r\n }\r\n\r\n /** Check for legacy style hierarchy */\r\n checkLegacyHierarchy(data) {\r\n const availableNodes = data.hasOwnProperty('node_structure')\r\n ? data.node_structure\r\n : null;\r\n\r\n if (availableNodes && availableNodes.r) {\r\n console.log(\"Legacy hierarchy detected\");\r\n this.updateHierarchy(availableNodes);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n}\r\n","\r\n/**\r\n * Some types of possible point attribute data formats\r\n *\r\n * @class\r\n */\r\nconst PointAttributeTypes = {\r\n DATA_TYPE_DOUBLE: {ordinal: 0, name: \"double\", size: 8},\r\n DATA_TYPE_FLOAT: {ordinal: 1, name: \"float\", size: 4},\r\n DATA_TYPE_INT8: {ordinal: 2, name: \"int8\", size: 1},\r\n DATA_TYPE_UINT8: {ordinal: 3, name: \"uint8\", size: 1},\r\n DATA_TYPE_INT16: {ordinal: 4, name: \"int16\", size: 2},\r\n DATA_TYPE_UINT16: {ordinal: 5, name: \"uint16\", size: 2},\r\n DATA_TYPE_INT32: {ordinal: 6, name: \"int32\", size: 4},\r\n DATA_TYPE_UINT32: {ordinal: 7, name: \"uint32\", size: 4},\r\n DATA_TYPE_INT64: {ordinal: 8, name: \"int64\", size: 8},\r\n DATA_TYPE_UINT64: {ordinal: 9, name: \"uint64\", size: 8}\r\n};\r\n\r\nconst typenameTypeattributeMap = {\r\n \"double\": PointAttributeTypes.DATA_TYPE_DOUBLE,\r\n \"float\": PointAttributeTypes.DATA_TYPE_FLOAT,\r\n \"int8\": PointAttributeTypes.DATA_TYPE_INT8,\r\n \"uint8\": PointAttributeTypes.DATA_TYPE_UINT8,\r\n \"int16\": PointAttributeTypes.DATA_TYPE_INT16,\r\n \"uint16\": PointAttributeTypes.DATA_TYPE_UINT16,\r\n \"int32\": PointAttributeTypes.DATA_TYPE_INT32,\r\n \"uint32\": PointAttributeTypes.DATA_TYPE_UINT32,\r\n \"int64\": PointAttributeTypes.DATA_TYPE_INT64,\r\n \"uint64\": PointAttributeTypes.DATA_TYPE_UINT64,\r\n};\r\n\r\nlet i = 0;\r\nfor (let obj in PointAttributeTypes) {\r\n PointAttributeTypes[i] = PointAttributeTypes[obj];\r\n i++;\r\n}\r\n\r\nclass PointAttribute{\r\n name: any;\r\n type: any;\r\n numElements: any;\r\n byteSize: number;\r\n description: string;\r\n range: number[];\r\n static POSITION_CARTESIAN: PointAttribute;\r\n static RGBA_PACKED: PointAttribute;\r\n static COLOR_PACKED: any;\r\n static RGB_PACKED: PointAttribute;\r\n static NORMAL_FLOATS: PointAttribute;\r\n static INTENSITY: PointAttribute;\r\n static CLASSIFICATION: PointAttribute;\r\n static NORMAL_SPHEREMAPPED: PointAttribute;\r\n static NORMAL_OCT16: PointAttribute;\r\n static NORMAL: PointAttribute;\r\n static RETURN_NUMBER: PointAttribute;\r\n static NUMBER_OF_RETURNS: PointAttribute;\r\n static SOURCE_ID: PointAttribute;\r\n static INDICES: PointAttribute;\r\n static SPACING: PointAttribute;\r\n static GPS_TIME: PointAttribute;\r\n initialRange: any;\r\n\r\n constructor(name, type, numElements){\r\n this.name = name;\r\n this.type = type;\r\n this.numElements = numElements;\r\n this.byteSize = this.numElements * this.type.size;\r\n this.description = \"\";\r\n this.range = [Infinity, -Infinity];\r\n }\r\n\r\n};\r\n\r\nPointAttribute.POSITION_CARTESIAN = new PointAttribute(\r\n \"POSITION_CARTESIAN\", PointAttributeTypes.DATA_TYPE_FLOAT, 3);\r\n\r\nPointAttribute.RGBA_PACKED = new PointAttribute(\r\n \"COLOR_PACKED\", PointAttributeTypes.DATA_TYPE_INT8, 4);\r\n\r\nPointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED;\r\n\r\nPointAttribute.RGB_PACKED = new PointAttribute(\r\n \"COLOR_PACKED\", PointAttributeTypes.DATA_TYPE_INT8, 3);\r\n\r\nPointAttribute.NORMAL_FLOATS = new PointAttribute(\r\n \"NORMAL_FLOATS\", PointAttributeTypes.DATA_TYPE_FLOAT, 3);\r\n\r\nPointAttribute.INTENSITY = new PointAttribute(\r\n \"INTENSITY\", PointAttributeTypes.DATA_TYPE_UINT16, 1);\r\n\r\nPointAttribute.CLASSIFICATION = new PointAttribute(\r\n \"CLASSIFICATION\", PointAttributeTypes.DATA_TYPE_UINT8, 1);\r\n\r\nPointAttribute.NORMAL_SPHEREMAPPED = new PointAttribute(\r\n \"NORMAL_SPHEREMAPPED\", PointAttributeTypes.DATA_TYPE_UINT8, 2);\r\n\r\nPointAttribute.NORMAL_OCT16 = new PointAttribute(\r\n \"NORMAL_OCT16\", PointAttributeTypes.DATA_TYPE_UINT8, 2);\r\n\r\nPointAttribute.NORMAL = new PointAttribute(\r\n \"NORMAL\", PointAttributeTypes.DATA_TYPE_FLOAT, 3);\r\n\r\nPointAttribute.RETURN_NUMBER = new PointAttribute(\r\n \"RETURN_NUMBER\", PointAttributeTypes.DATA_TYPE_UINT8, 1);\r\n\r\nPointAttribute.NUMBER_OF_RETURNS = new PointAttribute(\r\n \"NUMBER_OF_RETURNS\", PointAttributeTypes.DATA_TYPE_UINT8, 1);\r\n\r\nPointAttribute.SOURCE_ID = new PointAttribute(\r\n \"SOURCE_ID\", PointAttributeTypes.DATA_TYPE_UINT16, 1);\r\n\r\nPointAttribute.INDICES = new PointAttribute(\r\n \"INDICES\", PointAttributeTypes.DATA_TYPE_UINT32, 1);\r\n\r\nPointAttribute.SPACING = new PointAttribute(\r\n \"SPACING\", PointAttributeTypes.DATA_TYPE_FLOAT, 1);\r\n\r\nPointAttribute.GPS_TIME = new PointAttribute(\r\n \"GPS_TIME\", PointAttributeTypes.DATA_TYPE_DOUBLE, 1);\r\n\r\nexport class PointAttributes{\r\n attributes: any[];\r\n byteSize: number;\r\n size: number;\r\n vectors: any[];\r\n\r\n constructor(pointAttributes=null){\r\n this.attributes = [];\r\n this.byteSize = 0;\r\n this.size = 0;\r\n this.vectors = [];\r\n\r\n if (pointAttributes != null) {\r\n for (let i = 0; i < pointAttributes.length; i++) {\r\n let pointAttributeName = pointAttributes[i];\r\n let pointAttribute = PointAttribute[pointAttributeName];\r\n this.attributes.push(pointAttribute);\r\n this.byteSize += pointAttribute.byteSize;\r\n this.size++;\r\n }\r\n }\r\n }\r\n\r\n\r\n add(pointAttribute){\r\n this.attributes.push(pointAttribute);\r\n this.byteSize += pointAttribute.byteSize;\r\n this.size++;\r\n };\r\n\r\n addVector(vector){\r\n this.vectors.push(vector);\r\n }\r\n\r\n hasNormals(){\r\n for (let name in this.attributes) {\r\n let pointAttribute = this.attributes[name];\r\n if (\r\n pointAttribute === PointAttribute.NORMAL_SPHEREMAPPED ||\r\n\t\t\t\tpointAttribute === PointAttribute.NORMAL_FLOATS ||\r\n\t\t\t\tpointAttribute === PointAttribute.NORMAL ||\r\n\t\t\t\tpointAttribute === PointAttribute.NORMAL_OCT16) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n };\r\n\r\n}\r\n\r\nexport const parseAttributes = jsonAttributes => {\r\n let attributes = new PointAttributes();\r\n\r\n let replacements = {\r\n \"rgb\": \"rgba\",\r\n };\r\n\r\n for (const jsonAttribute of jsonAttributes) {\r\n let {name, numElements, min, max} = jsonAttribute;\r\n let type = typenameTypeattributeMap[jsonAttribute.type];\r\n let potreeAttributeName = replacements[name] ? replacements[name] : name;\r\n let attribute = new PointAttribute(potreeAttributeName, type, numElements);\r\n\r\n if(numElements === 1){\r\n attribute.range = [min[0], max[0]];\r\n }else{\r\n attribute.range = [min, max];\r\n }\r\n\r\n if (name === \"gps-time\") {\r\n if (attribute.range[0] === attribute.range[1]) {\r\n attribute.range[1] += 1;\r\n }\r\n }\r\n\r\n attribute.initialRange = attribute.range;\r\n attributes.add(attribute);\r\n }\r\n\r\n // check if it has normals\r\n let hasNormals =\r\n attributes.attributes.find(a => a.name === \"NormalX\") !== undefined &&\r\n attributes.attributes.find(a => a.name === \"NormalY\") !== undefined &&\r\n attributes.attributes.find(a => a.name === \"NormalZ\") !== undefined;\r\n\r\n if(hasNormals){\r\n let vector = {\r\n name: \"NORMAL\",\r\n attributes: [\"NormalX\", \"NormalY\", \"NormalZ\"],\r\n };\r\n attributes.addVector(vector);\r\n }\r\n\r\n return attributes;\r\n};\r\n","import { Box3, Vector3 } from \"three\";\r\nimport { PointCloudManager, StreamablePointCloud, StreamablePointCloudNode, getClassificationHistogram } from \".\";\r\nimport { toast } from \"../../app\";\r\nimport { t } from \"../../localization\";\r\nimport { readFileBuffer } from \"../file-system-loader\";\r\nimport LocalScene from \"../projections\";\r\nimport { AsyncWorkerPool } from \"../worker-pool\";\r\nimport { parseAttributes, PointAttributes } from \"./point-attributes\";\r\n\r\nconst workerPool = new AsyncWorkerPool(\"point-decoder-potree.js\");\r\n\r\nclass DataView64 extends DataView {\r\n constructor(buffer) {\r\n super(buffer);\r\n }\r\n\r\n getUint64(position, littleEndian = false) {\r\n return Number(this.getBigUint64(position, littleEndian));\r\n }\r\n\r\n getInt64(position, littleEndian = false) {\r\n return Number(this.getBigInt64(position, littleEndian));\r\n }\r\n}\r\n\r\n/** Encompass style pointcloud node */\r\nclass PotreePointCloudNode extends StreamablePointCloudNode {\r\n public cloud: PotreePointCloud;\r\n public parent: PotreePointCloudNode;\r\n\r\n public nodeType = 0;\r\n public hierarchyByteOffset = 0;\r\n public hierarchyByteSize = 0;\r\n public byteOffset = 0;\r\n public byteSize = 0;\r\n\r\n private attemptNumber = 0;\r\n private maxAttempts = 3;\r\n\r\n constructor(cloud, parent, name, level, center, size) {\r\n super(name, level, center, size);\r\n\r\n this.cloud = cloud;\r\n this.parent = parent;\r\n }\r\n\r\n get toMeters() {\r\n return LocalScene.dataToMeters;\r\n }\r\n\r\n getChildOffset(index) {\r\n return {\r\n x: (index & 0b100) / 4,\r\n y: (index & 0b010) / 2,\r\n z: index & 0b001\r\n };\r\n }\r\n\r\n async loadHierarchy(){\r\n if (this.nodeType !== 2) return;\r\n\r\n const byteRange = {\r\n first: this.hierarchyByteOffset,\r\n last: this.hierarchyByteOffset + this.hierarchyByteSize\r\n };\r\n\r\n const path = this.cloud.hierarchyPath;\r\n const buffer = await readFileBuffer(path, {byteRange});\r\n\r\n this.parseHierarchy(buffer);\r\n }\r\n\r\n parseHierarchy(buffer) {\r\n const view = new DataView64(buffer);\r\n const bytesPerNode = 22;\r\n const numNodes = buffer.byteLength / bytesPerNode;\r\n\r\n let nodePos = 1;\r\n const nodes = new Array(numNodes);\r\n nodes[0] = this;\r\n\r\n for (let i = 0; i < numNodes; i++) {\r\n const current = nodes[i] as PotreePointCloudNode;\r\n\r\n const type = view.getUint8(i * bytesPerNode + 0);\r\n const childMask = view.getUint8(i * bytesPerNode + 1);\r\n const numPoints = view.getUint32(i * bytesPerNode + 2, true);\r\n const byteOffset = view.getInt64(i * bytesPerNode + 6, true);\r\n const byteSize = view.getInt64(i * bytesPerNode + 14, true);\r\n\r\n if (current.nodeType === 2) {\r\n current.byteOffset = byteOffset;\r\n current.byteSize = byteSize;\r\n current.numPoints = numPoints;\r\n } else if(type === 2) {\r\n current.hierarchyByteOffset = byteOffset;\r\n current.hierarchyByteSize = byteSize;\r\n current.numPoints = numPoints;\r\n } else {\r\n current.byteOffset = byteOffset;\r\n current.byteSize = byteSize;\r\n current.numPoints = numPoints;\r\n }\r\n\r\n if (current.byteSize === 0) {\r\n current.numPoints = 0;\r\n }\r\n\r\n current.nodeType = type;\r\n if (current.nodeType === 2){\r\n continue;\r\n }\r\n\r\n for (let childIndex = 0; childIndex < 8; childIndex++){\r\n let childExists = ((1 << childIndex) & childMask) !== 0;\r\n if (!childExists) continue;\r\n\r\n const child = current.getChildNode(childIndex);\r\n current.addChildNode(child);\r\n\r\n nodes[nodePos] = child;\r\n nodePos++;\r\n }\r\n }\r\n }\r\n\r\n async getBinaryData() {\r\n const byteRange = {\r\n first: this.byteOffset,\r\n last: this.byteOffset + this.byteSize\r\n };\r\n\r\n let minCorner = new Vector3()\r\n .add(this.nodeCenter)\r\n .subScalar(this.nodeSize/2);\r\n\r\n let buffer;\r\n\r\n if (this.byteSize === 0) {\r\n buffer = new ArrayBuffer(0);\r\n // console.warn(`Loaded node with 0 bytes: ${this.name}`);\r\n } else {\r\n const path = this.cloud.octreePath;\r\n buffer = await readFileBuffer(path, {byteRange});\r\n }\r\n\r\n const values = {\r\n buffer: buffer,\r\n name: this.name,\r\n pointAttributes: this.cloud.pointAttributes,\r\n scale: this.cloud.xyzScale,\r\n min: this.cloud.xyzCenter,\r\n offset: this.cloud.xyzOffset,\r\n size: this.nodeSize,\r\n numPoints: this.numPoints,\r\n corner: minCorner,\r\n toMeters: this.toMeters\r\n };\r\n\r\n const data = await workerPool.postMessage(values, [values.buffer]);\r\n\r\n // Convert raw buffer to float array\r\n data.positions = new Float32Array(data.attributeBuffers.positions.buffer);\r\n data.intensity = new Float32Array(data.attributeBuffers.intensity.buffer);\r\n data.classification = new Float32Array(data.attributeBuffers.classification.buffer);\r\n data.colors = new Float32Array(data.attributeBuffers.colors.buffer);\r\n\r\n return data;\r\n }\r\n\r\n getGeometry(data) {\r\n this.setGeometry(data);\r\n\r\n if (!this.cloud.hasClassHistogram) {\r\n // Update unique classifications\r\n const histogram = getClassificationHistogram(data.classification);\r\n this.cloud.updateClassificationFromHistogram(histogram);\r\n }\r\n\r\n this.density = data.density;\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n\r\n async load() {\r\n if ((this.loaded) || (this.loading)) return;\r\n\r\n this.loading = true;\r\n\r\n try {\r\n await this.loadHierarchy();\r\n const data = await this.getBinaryData();\r\n this.getGeometry(data);\r\n } catch(err) {\r\n this.attemptNumber += 1;\r\n\r\n if (this.attemptNumber <= this.maxAttempts) {\r\n console.log(`Reload node ${this.name} (attempt #${this.attemptNumber})`);\r\n this.loaded = false;\r\n this.loading = false;\r\n return;\r\n }\r\n\r\n this.cloud.error = true;\r\n console.error(err);\r\n }\r\n }\r\n}\r\n\r\n/** Potree style pointcloud */\r\nexport class PotreePointCloud extends StreamablePointCloud {\r\n public xyzScale;\r\n public xyzOffset;\r\n public xyzCenter;\r\n public pointAttributes: PointAttributes;\r\n private version = \"2.0\";\r\n private encoding = \"DEFAULT\"\r\n public hasClassHistogram = false;\r\n\r\n constructor(pointclouds: PointCloudManager) {\r\n super(pointclouds);\r\n }\r\n\r\n get metadataPath() {\r\n return `${this.structure.path}/metadata.json`;\r\n }\r\n\r\n get octreePath() {\r\n return `${this.structure.path}/octree.bin`;\r\n }\r\n\r\n get hierarchyPath() {\r\n return `${this.structure.path}/hierarchy.bin`;\r\n }\r\n\r\n get toMeters() {\r\n return LocalScene.dataToMeters;\r\n }\r\n\r\n /** Decode cloud metadata. Cloud is in dataProjection units */\r\n decodeMetadata(data) {\r\n if (data.version !== this.version) {\r\n this.error = true;\r\n toast.error(t(\"toast.point_version_error\", {\r\n version: data.version\r\n }));\r\n\r\n return;\r\n }\r\n\r\n if (data.encoding !== this.encoding) {\r\n this.error = true;\r\n toast.error(t(\"toast.point_encoding_error\", {\r\n encoding: data.encoding\r\n }));\r\n\r\n return;\r\n }\r\n\r\n this.pointAttributes = parseAttributes(data.attributes);\r\n\r\n // Update maximum rgb value\r\n const colors = data.attributes.find(x => x.name === \"rgb\");\r\n const rgbMax = colors ? Math.max(...colors.max) : 0;\r\n this.updateColorLimits(rgbMax);\r\n\r\n const classification = data.attributes.find(x => x.name === \"classification\");\r\n this.hasClassHistogram = !!classification.histogram;\r\n\r\n if (this.hasClassHistogram) {\r\n // Update unique classifications\r\n const histogram = classification.histogram;\r\n this.updateClassificationFromHistogram(histogram);\r\n }\r\n\r\n // Update intensity bounds\r\n const intensity = data.attributes.find(x => x.name === \"intensity\");\r\n this.updateIntensityRange(intensity.min, intensity.max);\r\n\r\n const bboxMin = new Vector3(...data.boundingBox.min)\r\n .multiplyScalar(this.toMeters);\r\n\r\n const bboxMax = new Vector3(...data.boundingBox.max)\r\n .multiplyScalar(this.toMeters);\r\n\r\n const offset = new Vector3()\r\n .add(bboxMin)\r\n .add(bboxMax)\r\n .divideScalar(2.0);\r\n\r\n this.xyzScale = data.scale;\r\n this.xyzOffset = data.offset;\r\n this.xyzCenter = offset;\r\n this.spacing = data.spacing * this.toMeters;\r\n\r\n const position = data.attributes\r\n .find(x => x.name === \"position\");\r\n\r\n const xyzMin = new Vector3(...position.min)\r\n .multiplyScalar(this.toMeters);\r\n\r\n const xyzMax = new Vector3(...position.max)\r\n .multiplyScalar(this.toMeters);\r\n\r\n const boundingBox = new Box3(\r\n new Vector3().add(xyzMin).sub(offset),\r\n new Vector3().add(xyzMax).sub(offset)\r\n );\r\n\r\n const nodeSize = bboxMax.x - bboxMin.x;\r\n const nodeCenter = new Vector3();\r\n\r\n this.shift = LocalScene.offsetToScene(offset);\r\n\r\n const rootNode = new PotreePointCloudNode(\r\n this, null, \"r\", 1, nodeCenter, nodeSize);\r\n\r\n rootNode.nodeType = 2;\r\n rootNode.hierarchyByteSize = data.hierarchy.firstChunkSize;\r\n\r\n this.root = rootNode;\r\n this.updateBoundingBox(boundingBox);\r\n this.pointclouds.updateMinimapExtent();\r\n\r\n if (this.saved) return;\r\n this.viewer.zoomToSceneExtent(this.tightBoundingBox, false);\r\n }\r\n}","/**\r\n * @author qiao / https://github.com/qiao\r\n * @author mrdoob / http://mrdoob.com\r\n * @author alteredq / http://alteredqualia.com/\r\n * @author WestLangley / http://github.com/WestLangley\r\n * @author erich666 / http://erichaines.com\r\n */\r\n\r\nimport {\r\n EventDispatcher,\r\n MathUtils,\r\n MOUSE,\r\n Quaternion,\r\n Spherical,\r\n Vector2,\r\n Vector3\r\n} from \"three\";\r\nimport { toast } from \"../../app\";\r\nimport { t } from \"../../localization\";\r\nimport { ControlModes, ControlType } from \"../../types/controls\";\r\nimport { Viewer } from \"../main\";\r\n\r\nconst screenSpacePanning = 0;\r\nconst horizontalPanning = 1;\r\n\r\nconst CustomOrbitControls = function(viewer: Viewer, object, domElement ) {\r\n this.viewer = viewer as Viewer;\r\n this.object = object;\r\n this.domElement = ( domElement !== undefined ) ? domElement : document;\r\n\r\n this.keyPressed = {};\r\n this.walkMode = false;\r\n this.walkVelocity = new Vector3();\r\n this.walkRotation = new Spherical();\r\n this.maxWalkSpeed = 1.0;\r\n this.walkIncrement = 0.01;\r\n this.walkPercent = 1.0;\r\n this.walkPercentMin = 0.1;\r\n this.walkPercentMax = 5.0;\r\n this.oldRadiusState = 0.0;\r\n\r\n this.zoomToCursor = false;\r\n\r\n // Set to false to disable this control\r\n this.enabled = true;\r\n\r\n this.focused = false;\r\n\r\n // \"target\" sets the location of focus, where the object orbits around\r\n this.target = new Vector3();\r\n\r\n // How far you can dolly in and out ( PerspectiveCamera only )\r\n this.minDistance = 0.05;\r\n this.maxDistance = Infinity;\r\n\r\n // How far you can zoom in and out ( OrthographicCamera only )\r\n this.minZoom = 0;\r\n this.maxZoom = Infinity;\r\n\r\n // How far you can orbit vertically, upper and lower limits.\r\n // Range is 0 to Math.PI radians.\r\n this.minPolarAngle = 0; // radians\r\n this.maxPolarAngle = Math.PI; // radians\r\n\r\n // How far you can orbit horizontally, upper and lower limits.\r\n // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\r\n this.minAzimuthAngle = -Infinity; // radians\r\n this.maxAzimuthAngle = Infinity; // radians\r\n\r\n // Set to true to enable damping (inertia)\r\n // If damping is enabled, you must call controls.update() in your animation loop\r\n this.enableDamping = false;\r\n this.dampingFactor = 0.25;\r\n\r\n // This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\r\n // Set to false to disable zooming\r\n this.enableZoom = true;\r\n this.zoomSpeed = 1.0;\r\n\r\n // Set to false to disable rotating\r\n this.enableRotate = true;\r\n this.rotateSpeed = 1.0;\r\n\r\n // Set to false to disable panning\r\n this.enablePan = true;\r\n this.panSpeed = 1.0;\r\n this.panningMode = screenSpacePanning; // alternate horizontalPanning\r\n this.keyPanSpeed = 7.0;\t// pixels moved per arrow key push\r\n\r\n // Set to true to automatically rotate around the target\r\n // If auto-rotate is enabled, you must call controls.update() in your animation loop\r\n this.autoRotate = false;\r\n this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\r\n\r\n // Set to false to disable use of the keys\r\n this.enableKeys = true;\r\n\r\n // The four arrow keys\r\n this.keys = {\r\n LEFT: 37,\r\n UP: 38,\r\n RIGHT: 39,\r\n BOTTOM: 40,\r\n SPACE: 32,\r\n PLUS: 187,\r\n MINUS: 189,\r\n NUMPAD_PLUS: 107,\r\n NUMPAD_MINUS: 109,\r\n WALK_FORWARD: 87,\r\n WALK_BACK: 83,\r\n WALK_RIGHT: 68,\r\n WALK_LEFT: 65,\r\n WALK_UP: 69,\r\n WALK_DOWN: 81\r\n };\r\n\r\n this.controlType = ControlType.Encompass;\r\n\r\n // Mouse buttons\r\n this.mouseButtons = { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT };\r\n\r\n // for reset\r\n this.target0 = this.target.clone();\r\n this.position0 = this.object.position.clone();\r\n this.zoom0 = this.object.zoom;\r\n\r\n //\r\n // public methods\r\n //\r\n\r\n this.setControls = function (controlType) {\r\n this.controlType = controlType;\r\n this.mouseButtons = ControlModes[controlType];\r\n };\r\n\r\n this.getPolarAngle = function () {\r\n return spherical.phi;\r\n };\r\n\r\n this.getAzimuthalAngle = function () {\r\n return spherical.theta;\r\n };\r\n\r\n this.clearSphericalDelta = function () {\r\n sphericalDelta.set(0, 0, 0);\r\n };\r\n\r\n this.clearPanOffset = function() {\r\n panOffset.set(0, 0, 0);\r\n };\r\n\r\n this.saveState = function () {\r\n scope.target0.copy( scope.target );\r\n scope.position0.copy( scope.object.position );\r\n scope.zoom0 = scope.object.zoom;\r\n };\r\n\r\n this.resetWalkValues = function () {\r\n scope.walkVelocity = new Vector3();\r\n scope.keyPressed = {};\r\n };\r\n\r\n this.incrementWalkSpeed = function () {\r\n if (!scope.walkMode) return;\r\n scope.walkPercent = Math.min(scope.walkPercentMax, scope.walkPercent + 0.1);\r\n const percent = Math.round(scope.walkPercent*100.0);\r\n toast.static(t(\"toast.walk-speed\", {percent}));\r\n };\r\n\r\n this.decreaseWalkSpeed = function () {\r\n if (!scope.walkMode) return;\r\n scope.walkPercent = Math.max(scope.walkPercentMin, scope.walkPercent - 0.1);\r\n const percent = Math.round(scope.walkPercent*100.0);\r\n toast.static(t(\"toast.walk-speed\", {percent}));\r\n };\r\n\r\n this.setWalkMode = function (state) {\r\n if (state === scope.walkMode) {\r\n return;\r\n }\r\n\r\n if (state) {\r\n toast.static(t(\"toast.walk-mode-enabled\"));\r\n } else {\r\n toast.static(t(\"toast.walk-mode-disabled\"));\r\n }\r\n\r\n scope.clearSphericalDelta();\r\n scope.clearPanOffset();\r\n scope.resetWalkValues();\r\n scope.walkMode = state;\r\n\r\n if (state) {\r\n // Calculate initial rotation for walk mode\r\n const offset = new Vector3()\r\n .copy( scope.object.position )\r\n .sub( scope.target );\r\n\r\n const quat = new Quaternion().setFromUnitVectors(\r\n scope.object.up,\r\n new Vector3( 0, 1, 0 )\r\n );\r\n\r\n offset.applyQuaternion( quat );\r\n scope.walkRotation.setFromVector3( offset );\r\n scope.walkRotation.theta += MathUtils.degToRad(90);\r\n } else {\r\n // Restore previous orbit radius and reset\r\n scope.position0 = scope.activePosition();\r\n scope.target0 = scope.activeTarget();\r\n scope.reset();\r\n }\r\n };\r\n\r\n this.activePosition = function () {\r\n return scope.object.position;\r\n };\r\n\r\n this.activeTarget = function () {\r\n const radius = scope.oldRadiusState;\r\n return new Vector3(0, 0, -radius)\r\n .applyQuaternion(scope.object.quaternion)\r\n .add(scope.object.position);\r\n };\r\n\r\n this.applyWalkOffset = function (scaleFactor) {\r\n const offset = new Vector3();\r\n const quaternion = this.object.quaternion;\r\n\r\n // Forward/back logic\r\n if (this.keyPressed[scope.keys.WALK_FORWARD]) {\r\n scope.walkVelocity.x += scope.walkIncrement;\r\n scope.walkVelocity.x = Math.min(scope.maxWalkSpeed, scope.walkVelocity.x);\r\n } else if (this.keyPressed[scope.keys.WALK_BACK]) {\r\n scope.walkVelocity.x -= scope.walkIncrement;\r\n scope.walkVelocity.x = Math.max(-scope.maxWalkSpeed, scope.walkVelocity.x);\r\n } else {\r\n scope.walkVelocity.x *= (1 - scope.dampingFactor);\r\n if (Math.abs(scope.walkVelocity.x) < 1E-3) {\r\n scope.walkVelocity.x = 0.0;\r\n }\r\n }\r\n\r\n // Left/right logic\r\n if (this.keyPressed[scope.keys.WALK_RIGHT]) {\r\n scope.walkVelocity.y += scope.walkIncrement;\r\n scope.walkVelocity.y = Math.min(scope.maxWalkSpeed, scope.walkVelocity.y);\r\n } else if (this.keyPressed[scope.keys.WALK_LEFT]) {\r\n scope.walkVelocity.y -= scope.walkIncrement;\r\n scope.walkVelocity.y = Math.max(-scope.maxWalkSpeed, scope.walkVelocity.y);\r\n } else {\r\n scope.walkVelocity.y *= (1 - scope.dampingFactor);\r\n if (Math.abs(scope.walkVelocity.y) < 1E-3) {\r\n scope.walkVelocity.y = 0.0;\r\n }\r\n }\r\n\r\n // up/down logic\r\n if (this.keyPressed[scope.keys.WALK_UP]) {\r\n scope.walkVelocity.z += scope.walkIncrement;\r\n scope.walkVelocity.z = Math.min(scope.maxWalkSpeed, scope.walkVelocity.z);\r\n } else if (this.keyPressed[scope.keys.WALK_DOWN]) {\r\n scope.walkVelocity.z -= scope.walkIncrement;\r\n scope.walkVelocity.z = Math.max(-scope.maxWalkSpeed, scope.walkVelocity.z);\r\n } else {\r\n scope.walkVelocity.z *= (1 - scope.dampingFactor);\r\n if (Math.abs(scope.walkVelocity.z) < 1E-3) {\r\n scope.walkVelocity.z = 0.0;\r\n }\r\n }\r\n\r\n if (scope.walkVelocity.x !== 0) {\r\n const forward = new Vector3(0, 0, -1)\r\n .applyQuaternion(quaternion)\r\n .multiplyScalar(scope.walkVelocity.x);\r\n offset.add(forward);\r\n }\r\n\r\n if (scope.walkVelocity.y !== 0) {\r\n const right = new Vector3(1, 0, 0)\r\n .applyQuaternion(quaternion)\r\n .multiplyScalar(scope.walkVelocity.y);\r\n offset.add(right);\r\n }\r\n\r\n if (scope.walkVelocity.z !== 0) {\r\n const up = new Vector3(0, 1, 0)\r\n .applyQuaternion(quaternion)\r\n .multiplyScalar(scope.walkVelocity.z);\r\n offset.add(up);\r\n }\r\n\r\n // Apply scale so distance travelled is consistent\r\n // regardless of framerate / update interval speed\r\n offset.multiplyScalar(scaleFactor);\r\n\r\n offset.multiplyScalar(scope.walkPercent);\r\n\r\n scope.object.position.add(offset);\r\n };\r\n\r\n this.reset = function () {\r\n scope.target.copy( scope.target0 );\r\n\r\n scope.object.position.copy( scope.position0 );\r\n scope.object.zoom = scope.zoom0;\r\n scope.object.updateProjectionMatrix();\r\n\r\n scope.dispatchEvent( changeEvent );\r\n scope.update();\r\n\r\n state = STATE.NONE;\r\n };\r\n\r\n function clampDistance(radius) {\r\n return Math.max(scope.minDistance, Math.min(scope.maxDistance, radius));\r\n }\r\n\r\n // this method is exposed, but perhaps it would be better if we can make it private...\r\n this.update = (function () {\r\n var offset = new Vector3();\r\n\r\n // so camera.up is the orbit axis\r\n var quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\r\n var quatInverse = quat.clone().invert();\r\n\r\n var lastPosition = new Vector3();\r\n var lastQuaternion = new Quaternion();\r\n var lastUpdated = performance.now();\r\n var changeDetected = false;\r\n\r\n return function update() {\r\n var position = scope.object.position;\r\n\r\n let timeElapsed = performance.now() - lastUpdated;\r\n let scaleFactor = timeElapsed / (1000/60);\r\n lastUpdated = performance.now();\r\n\r\n offset.copy( position ).sub( scope.target );\r\n\r\n // rotate offset to \"y-axis-is-up\" space\r\n offset.applyQuaternion( quat );\r\n\r\n // angle from z-axis around y-axis\r\n spherical.setFromVector3( offset );\r\n\r\n if ( scope.autoRotate && state === STATE.NONE ) {\r\n rotateLeft( getAutoRotationAngle() );\r\n }\r\n\r\n if (scope.walkMode) {\r\n scope.walkRotation.theta += sphericalDelta.theta;\r\n scope.walkRotation.phi += sphericalDelta.phi;\r\n scope.walkRotation.makeSafe();\r\n\r\n const {phi, theta} = scope.walkRotation;\r\n let x = Math.cos(theta) * Math.sin(phi);\r\n let y = Math.sin(theta) * Math.sin(phi);\r\n let z = -1*Math.cos(phi);\r\n\r\n let lookat = new Vector3(x,y,z)\r\n .add(scope.object.position);\r\n scope.object.lookAt( lookat );\r\n\r\n scope.applyWalkOffset(scaleFactor);\r\n } else {\r\n spherical.theta += sphericalDelta.theta;\r\n spherical.phi += sphericalDelta.phi;\r\n spherical.theta = Math.max( scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta) );\r\n spherical.phi = Math.max( scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));\r\n spherical.makeSafe();\r\n\r\n if ( scope.zoomToCursor ) {\r\n spherical.radius = clampDistance( spherical.radius );\r\n } else {\r\n spherical.radius = clampDistance( spherical.radius * scale );\r\n }\r\n\r\n scope.oldRadiusState = spherical.radius;\r\n\r\n // move target to panned location\r\n scope.target.add( panOffset );\r\n\r\n offset.setFromSpherical( spherical );\r\n\r\n // rotate offset back to \"camera-up-vector-is-up\" space\r\n offset.applyQuaternion( quatInverse );\r\n\r\n position.copy( scope.target ).add( offset );\r\n\r\n scope.object.lookAt( scope.target );\r\n\r\n // adjust camera position\r\n if ( scope.zoomToCursor ) {\r\n // move the camera down the pointer ray\r\n // this method avoids floating point error\r\n let prevRadius = offset.length();\r\n let newRadius = clampDistance( prevRadius * scale );\r\n\r\n let radiusDelta = prevRadius - newRadius;\r\n scope.object.position.addScaledVector( dollyDirection, radiusDelta );\r\n scope.object.updateMatrixWorld();\r\n zoomChanged = !!radiusDelta;\r\n\r\n // update target position\r\n scope.target.set( 0, 0, - 1 )\r\n .transformDirection( scope.object.matrix )\r\n .multiplyScalar( newRadius )\r\n .add( scope.object.position );\r\n }\r\n }\r\n\r\n if ( scope.enableDamping === true ) {\r\n sphericalDelta.theta *= ( 1 - scope.dampingFactor );\r\n sphericalDelta.phi *= ( 1 - scope.dampingFactor );\r\n if ((Math.abs(sphericalDelta.phi) < 1E-3) && (Math.abs(sphericalDelta.theta) < 1E-3)) {\r\n scope.clearSphericalDelta();\r\n }\r\n\r\n panOffset.multiplyScalar( 1 - scope.dampingFactor );\r\n if (panOffset.length() < 1E-3) {\r\n scope.clearPanOffset();\r\n }\r\n } else {\r\n scope.clearSphericalDelta();\r\n scope.clearPanOffset();\r\n }\r\n\r\n scale = 1;\r\n\r\n // update condition is:\r\n // min(camera displacement, camera rotation in radians)^2 > EPS\r\n // using small-angle approximation cos(x/2) = 1 - x^2 / 8\r\n\r\n if ( zoomChanged ||\r\n\t\t\t\tlastPosition.distanceToSquared( scope.object.position ) > EPS ||\r\n\t\t\t\t8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {\r\n scope.dispatchEvent( changeEvent );\r\n\r\n lastPosition.copy( scope.object.position );\r\n lastQuaternion.copy( scope.object.quaternion );\r\n zoomChanged = false;\r\n changeDetected = true;\r\n\r\n return true;\r\n }\r\n\r\n if (changeDetected) {\r\n scope.dispatchEvent( moveStopEvent );\r\n }\r\n\r\n changeDetected = false;\r\n\r\n return false;\r\n };\r\n }());\r\n\r\n this.dispose = function () {\r\n scope.domElement.removeEventListener( 'mousedown', onMouseDown, false );\r\n scope.domElement.removeEventListener( 'wheel', onMouseWheel, false );\r\n scope.domElement.removeEventListener( 'touchstart', onTouchStart, false );\r\n scope.domElement.removeEventListener( 'touchend', onTouchEnd, false );\r\n scope.domElement.removeEventListener( 'touchmove', onTouchMove, false );\r\n scope.domElement.removeEventListener( 'mouseover', onMouseFocus, false );\r\n scope.domElement.removeEventListener( 'mouseout', onMouseFocus, false );\r\n document.removeEventListener( 'mousemove', onMouseMove, false );\r\n document.removeEventListener( 'mouseup', onMouseUp, false );\r\n window.removeEventListener( 'keydown', onKeyDown, false );\r\n window.removeEventListener( 'keyUp', onKeyUp, false );\r\n };\r\n\r\n //\r\n // internals\r\n //\r\n\r\n var scope = this;\r\n\r\n var moveStopEvent = { type: \"stop\" };\r\n var changeEvent = { type: 'change' };\r\n var startEvent = { type: 'start' };\r\n var endEvent = { type: 'end' };\r\n\r\n var STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };\r\n\r\n var state = STATE.NONE;\r\n\r\n var EPS = 0.000001;\r\n\r\n // current position in spherical coordinates\r\n var spherical = new Spherical();\r\n var sphericalDelta = new Spherical();\r\n\r\n var scale = 1;\r\n var panOffset = new Vector3();\r\n var zoomChanged = false;\r\n\r\n var rotateStart = new Vector2();\r\n var rotateEnd = new Vector2();\r\n var rotateDelta = new Vector2();\r\n\r\n var panStart = new Vector2();\r\n var panEnd = new Vector2();\r\n var panDelta = new Vector2();\r\n\r\n var dollyStart = new Vector2();\r\n var dollyEnd = new Vector2();\r\n var dollyDelta = new Vector2();\r\n\r\n var dollyDirection = new Vector3();\r\n var mouse = new Vector2();\r\n\r\n function getAutoRotationAngle() {\r\n return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\r\n }\r\n\r\n function getZoomScale() {\r\n return Math.pow( 0.95, scope.zoomSpeed );\r\n }\r\n\r\n function rotateLeft( angle ) {\r\n sphericalDelta.theta -= angle;\r\n }\r\n\r\n function rotateUp( angle ) {\r\n sphericalDelta.phi -= angle;\r\n }\r\n\r\n function updateZoomParameters( x, y ) {\r\n if ( !scope.zoomToCursor ) return;\r\n\r\n const rect = scope.domElement.getBoundingClientRect();\r\n const dx = x - rect.left;\r\n const dy = y - rect.top;\r\n const w = rect.width;\r\n const h = rect.height;\r\n\r\n mouse.x = ( dx / w ) * 2 - 1;\r\n mouse.y = - ( dy / h ) * 2 + 1;\r\n\r\n dollyDirection\r\n .set( mouse.x, mouse.y, 1 )\r\n .unproject( scope.object )\r\n .sub( scope.object.position )\r\n .normalize();\r\n }\r\n\r\n var panLeft = (function () {\r\n var v = new Vector3();\r\n\r\n return function panLeft( distance, objectMatrix ) {\r\n v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\r\n v.multiplyScalar( -distance );\r\n\r\n panOffset.add( v );\r\n };\r\n }());\r\n\r\n var panUp = (function () {\r\n var v = new Vector3();\r\n\r\n return function panUp( distance, objectMatrix ) {\r\n switch ( scope.panningMode ) {\r\n case screenSpacePanning:\r\n\r\n v.setFromMatrixColumn( objectMatrix, 1 );\r\n break;\r\n\r\n case horizontalPanning:\r\n\r\n v.setFromMatrixColumn( objectMatrix, 0 );\r\n v.crossVectors( scope.object.up, v );\r\n break;\r\n }\r\n\r\n v.multiplyScalar( distance );\r\n\r\n panOffset.add( v );\r\n };\r\n }());\r\n\r\n // deltaX and deltaY are in pixels; right and down are positive\r\n var pan = (function () {\r\n var offset = new Vector3();\r\n\r\n return function pan( deltaX, deltaY ) {\r\n if (scope.walkMode) return;\r\n var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\r\n\r\n var position = scope.object.position;\r\n offset.copy( position ).sub( scope.target );\r\n var targetDistance = offset.length();\r\n\r\n // half of the fov is center to top of screen\r\n targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\r\n\r\n // we actually don't use screenWidth, since perspective camera is fixed to screen height\r\n panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\r\n panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\r\n };\r\n }());\r\n\r\n function dollyIn( dollyScale ) {\r\n scale /= dollyScale;\r\n }\r\n\r\n function dollyOut( dollyScale ) {\r\n scale *= dollyScale;\r\n }\r\n\r\n //\r\n // event callbacks - update the object state\r\n //\r\n\r\n function handleMouseDownRotate( event ) {\r\n // console.log( 'handleMouseDownRotate' );\r\n\r\n rotateStart.set( event.clientX, event.clientY );\r\n }\r\n\r\n function handleMouseDownDolly( event ) {\r\n // console.log( 'handleMouseDownDolly' );\r\n\r\n updateZoomParameters( event.clientX, event.clientY );\r\n dollyStart.set( event.clientX, event.clientY );\r\n }\r\n\r\n function handleMouseDownPan( event ) {\r\n // console.log( 'handleMouseDownPan' );\r\n\r\n panStart.set( event.clientX, event.clientY );\r\n }\r\n\r\n function handleMouseMoveRotate( event ) {\r\n // console.log( 'handleMouseMoveRotate' );\r\n\r\n rotateEnd.set( event.clientX, event.clientY );\r\n\r\n rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\r\n\r\n var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\r\n\r\n // rotating across whole screen goes 360 degrees around\r\n rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth );\r\n\r\n // rotating up and down along whole screen attempts to go 360, but limited to 180\r\n rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\r\n\r\n rotateStart.copy( rotateEnd );\r\n\r\n scope.update();\r\n }\r\n\r\n function handleMouseMoveDolly( event ) {\r\n // console.log( 'handleMouseMoveDolly' );\r\n\r\n dollyEnd.set( event.clientX, event.clientY );\r\n dollyDelta.subVectors( dollyEnd, dollyStart );\r\n\r\n if ( dollyDelta.y > 0 ) {\r\n dollyIn( getZoomScale() );\r\n } else if ( dollyDelta.y < 0 ) {\r\n dollyOut( getZoomScale() );\r\n }\r\n\r\n dollyStart.copy( dollyEnd );\r\n\r\n scope.update();\r\n }\r\n\r\n function handleMouseMovePan( event ) {\r\n // console.log( 'handleMouseMovePan' );\r\n\r\n panEnd.set( event.clientX, event.clientY );\r\n\r\n panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\r\n\r\n pan( panDelta.x, panDelta.y );\r\n\r\n panStart.copy( panEnd );\r\n\r\n scope.update();\r\n }\r\n\r\n function handleMouseUp( event ) {\r\n\r\n // console.log( 'handleMouseUp' );\r\n\r\n }\r\n\r\n this.setRotateRadius = (radius: number) => {\r\n const target = new Vector3()\r\n .copy(scope.target)\r\n .sub(scope.object.position)\r\n .setLength(radius)\r\n .add(scope.object.position);\r\n\r\n scope.target.copy( target );\r\n scope.update();\r\n };\r\n\r\n this.dollyInZoom = (event, zoomPercent) => {\r\n let scale = getZoomScale();\r\n let numIterations = ln(zoomPercent) / ln(scale);\r\n numIterations = Math.ceil(numIterations);\r\n\r\n for (let i=0; i 0 ) {\r\n dollyIn( getZoomScale() );\r\n }\r\n\r\n scope.update();\r\n }\r\n\r\n function handleKeyUp( event ) {\r\n // console.log( 'handleKeyUp' );\r\n\r\n if (scope.walkMode) {\r\n scope.keyPressed[event.keyCode] = false;\r\n return;\r\n }\r\n }\r\n\r\n function handleKeyDown( event ) {\r\n // console.log( 'handleKeyDown' );\r\n\r\n if (scope.walkMode) {\r\n scope.keyPressed[event.keyCode] = true;\r\n }\r\n\r\n switch ( event.keyCode ) {\r\n case scope.keys.UP:\r\n pan( 0, scope.keyPanSpeed );\r\n scope.update();\r\n break;\r\n\r\n case scope.keys.BOTTOM:\r\n pan( 0, -scope.keyPanSpeed );\r\n scope.update();\r\n break;\r\n\r\n case scope.keys.LEFT:\r\n pan( scope.keyPanSpeed, 0 );\r\n scope.update();\r\n break;\r\n\r\n case scope.keys.RIGHT:\r\n pan( -scope.keyPanSpeed, 0 );\r\n scope.update();\r\n break;\r\n\r\n case scope.keys.SPACE:\r\n scope.setWalkMode(!scope.walkMode);\r\n break;\r\n\r\n case scope.keys.PLUS:\r\n scope.incrementWalkSpeed();\r\n break;\r\n\r\n case scope.keys.NUMPAD_PLUS:\r\n scope.incrementWalkSpeed();\r\n break;\r\n\r\n case scope.keys.MINUS:\r\n scope.decreaseWalkSpeed();\r\n break;\r\n\r\n case scope.keys.NUMPAD_MINUS:\r\n scope.decreaseWalkSpeed();\r\n break;\r\n }\r\n }\r\n\r\n function handleTouchStartRotate( event ) {\r\n // console.log( 'handleTouchStartRotate' );\r\n\r\n rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r\n }\r\n\r\n function handleTouchStartDolly( event ) {\r\n // console.log( 'handleTouchStartDolly' );\r\n\r\n var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\r\n var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\r\n\r\n var distance = Math.sqrt( dx * dx + dy * dy );\r\n\r\n dollyStart.set( 0, distance );\r\n }\r\n\r\n function handleTouchStartPan( event ) {\r\n // console.log( 'handleTouchStartPan' );\r\n\r\n panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r\n }\r\n\r\n function handleTouchMoveRotate( event ) {\r\n // console.log( 'handleTouchMoveRotate' );\r\n\r\n rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r\n\r\n rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\r\n\r\n var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\r\n\r\n // rotating across whole screen goes 360 degrees around\r\n rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth );\r\n\r\n // rotating up and down along whole screen attempts to go 360, but limited to 180\r\n rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\r\n\r\n rotateStart.copy( rotateEnd );\r\n\r\n scope.update();\r\n }\r\n\r\n function handleTouchMoveDolly( event ) {\r\n // console.log( 'handleTouchMoveDolly' );\r\n\r\n var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\r\n var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\r\n\r\n var distance = Math.sqrt( dx * dx + dy * dy );\r\n\r\n dollyEnd.set( 0, distance );\r\n\r\n dollyDelta.subVectors( dollyEnd, dollyStart );\r\n\r\n if ( dollyDelta.y > 0 ) {\r\n dollyOut( getZoomScale() );\r\n } else if ( dollyDelta.y < 0 ) {\r\n dollyIn( getZoomScale() );\r\n }\r\n\r\n dollyStart.copy( dollyEnd );\r\n\r\n scope.update();\r\n }\r\n\r\n function handleTouchMovePan( event ) {\r\n // console.log( 'handleTouchMovePan' );\r\n\r\n panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\r\n\r\n panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\r\n\r\n pan( panDelta.x, panDelta.y );\r\n\r\n panStart.copy( panEnd );\r\n\r\n scope.update();\r\n }\r\n\r\n function handleTouchEnd( event ) {\r\n\r\n // console.log( 'handleTouchEnd' );\r\n\r\n }\r\n\r\n //\r\n // event handlers - FSM: listen for events and reset state\r\n //\r\n\r\n function onMouseDown( event ) {\r\n if ( scope.enabled === false ) return;\r\n\r\n event.preventDefault();\r\n\r\n var switchTo = event.button;\r\n if (scope.controlType === ControlType.Autocad) {\r\n if (event.shiftKey && event.button === MOUSE.MIDDLE) {\r\n switchTo = scope.mouseButtons.ORBIT;\r\n }\r\n }\r\n switch ( switchTo ) {\r\n case scope.mouseButtons.ORBIT:\r\n\r\n if ( scope.enableRotate === false ) return;\r\n\r\n handleMouseDownRotate( event );\r\n\r\n state = STATE.ROTATE;\r\n\r\n break;\r\n\r\n case scope.mouseButtons.ZOOM:\r\n\r\n if ( scope.enableZoom === false ) return;\r\n\r\n handleMouseDownDolly( event );\r\n\r\n state = STATE.DOLLY;\r\n\r\n break;\r\n\r\n case scope.mouseButtons.PAN:\r\n\r\n if ( scope.enablePan === false ) return;\r\n\r\n handleMouseDownPan( event );\r\n\r\n state = STATE.PAN;\r\n\r\n break;\r\n }\r\n\r\n if ( state !== STATE.NONE ) {\r\n document.addEventListener( 'mousemove', onMouseMove, false );\r\n document.addEventListener( 'mouseup', onMouseUp, false );\r\n\r\n scope.dispatchEvent( startEvent );\r\n }\r\n }\r\n\r\n function onMouseMove( event ) {\r\n if ( scope.enabled === false ) return;\r\n\r\n event.preventDefault();\r\n\r\n switch ( state ) {\r\n case STATE.ROTATE:\r\n if ( scope.enableRotate === false ) return;\r\n handleMouseMoveRotate( event );\r\n\r\n break;\r\n\r\n case STATE.DOLLY:\r\n if (scope.enableZoom === false) return;\r\n handleMouseMoveDolly( event );\r\n\r\n break;\r\n\r\n case STATE.PAN:\r\n if (scope.enablePan === false) return;\r\n handleMouseMovePan( event );\r\n\r\n break;\r\n }\r\n }\r\n\r\n function onMouseUp( event ) {\r\n if ( scope.enabled === false ) return;\r\n\r\n handleMouseUp( event );\r\n\r\n if (!scope.walkMode) {\r\n document.removeEventListener( 'mousemove', onMouseMove, false );\r\n }\r\n document.removeEventListener( 'mouseup', onMouseUp, false );\r\n\r\n scope.dispatchEvent( endEvent );\r\n\r\n state = STATE.NONE;\r\n }\r\n\r\n function onMouseWheel( event ) {\r\n if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;\r\n\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n scope.dispatchEvent( startEvent );\r\n\r\n handleMouseWheel( event );\r\n\r\n scope.dispatchEvent( endEvent );\r\n }\r\n\r\n function onKeyDown( event ) {\r\n if (!scope.enabled || !scope.focused || !scope.enableKeys || !scope.enablePan) {\r\n return;\r\n }\r\n\r\n handleKeyDown( event );\r\n }\r\n\r\n function onKeyUp( event ) {\r\n if (!scope.enabled || !scope.enableKeys || !scope.enablePan) {\r\n return;\r\n }\r\n\r\n handleKeyUp( event );\r\n }\r\n\r\n function onTouchStart( event ) {\r\n if ( scope.enabled === false ) return;\r\n\r\n switch ( event.touches.length ) {\r\n case 1:\t// one-fingered touch: rotate\r\n\r\n if ( scope.enableRotate === false ) return;\r\n\r\n handleTouchStartRotate( event );\r\n\r\n state = STATE.TOUCH_ROTATE;\r\n\r\n break;\r\n\r\n case 2:\t// two-fingered touch: dolly\r\n\r\n if ( scope.enableZoom === false ) return;\r\n\r\n handleTouchStartDolly( event );\r\n\r\n state = STATE.TOUCH_DOLLY;\r\n\r\n break;\r\n\r\n case 3: // three-fingered touch: pan\r\n\r\n if ( scope.enablePan === false ) return;\r\n\r\n handleTouchStartPan( event );\r\n\r\n state = STATE.TOUCH_PAN;\r\n\r\n break;\r\n\r\n default:\r\n\r\n state = STATE.NONE;\r\n }\r\n\r\n if ( state !== STATE.NONE ) {\r\n scope.dispatchEvent( startEvent );\r\n }\r\n }\r\n\r\n function onTouchMove( event ) {\r\n if ( scope.enabled === false ) return;\r\n\r\n event.preventDefault();\r\n event.stopPropagation();\r\n\r\n switch ( event.touches.length ) {\r\n case 1: // one-fingered touch: rotate\r\n\r\n if ( scope.enableRotate === false ) return;\r\n if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed?...\r\n\r\n handleTouchMoveRotate( event );\r\n\r\n break;\r\n\r\n case 2: // two-fingered touch: dolly\r\n\r\n if ( scope.enableZoom === false ) return;\r\n if ( state !== STATE.TOUCH_DOLLY ) return; // is this needed?...\r\n\r\n handleTouchMoveDolly( event );\r\n\r\n break;\r\n\r\n case 3: // three-fingered touch: pan\r\n\r\n if ( scope.enablePan === false ) return;\r\n if ( state !== STATE.TOUCH_PAN ) return; // is this needed?...\r\n\r\n handleTouchMovePan( event );\r\n\r\n break;\r\n\r\n default:\r\n\r\n state = STATE.NONE;\r\n }\r\n }\r\n\r\n function onTouchEnd( event ) {\r\n if ( scope.enabled === false ) return;\r\n\r\n handleTouchEnd( event );\r\n\r\n scope.dispatchEvent( endEvent );\r\n\r\n state = STATE.NONE;\r\n }\r\n\r\n function onMouseFocus( event ) {\r\n if (event.type === 'mouseover') {\r\n scope.focused = true;\r\n } else if (event.type === 'mouseout') {\r\n scope.focused = false;\r\n }\r\n }\r\n\r\n // Bind all events to dom element\r\n scope.domElement.addEventListener( 'mousedown', onMouseDown, false );\r\n scope.domElement.addEventListener( 'wheel', onMouseWheel, false );\r\n scope.domElement.addEventListener( 'touchstart', onTouchStart, false );\r\n scope.domElement.addEventListener( 'touchend', onTouchEnd, false );\r\n scope.domElement.addEventListener( 'touchmove', onTouchMove, false );\r\n\r\n // Keep track of our canvas focus\r\n scope.domElement.addEventListener( 'mouseover', onMouseFocus, false );\r\n scope.domElement.addEventListener( 'mouseout', onMouseFocus, false );\r\n\r\n // Keydown doesnt work on canvas\r\n window.addEventListener( 'keydown', onKeyDown, false) ;\r\n window.addEventListener( 'keyup', onKeyUp, false) ;\r\n\r\n // Start our update loop\r\n this.update();\r\n};\r\n\r\nCustomOrbitControls.prototype = Object.create( EventDispatcher.prototype );\r\nCustomOrbitControls.prototype.constructor = CustomOrbitControls;\r\n\r\nfunction ln(value: number) {\r\n return Math.log(value) / Math.log(2);\r\n}\r\n\r\nexport default CustomOrbitControls;\r\n","import { createHash } from \"crypto\";\r\nimport { Color } from \"three\";\r\nimport { getClassificationColors, classifications } from \"../../classifications\";\r\n\r\nlet classificationColors = [];\r\ngetClassificationColors().then(result => classificationColors = result);\r\n\r\nconst parseHex = (text, min, max) => {\r\n return parseInt(text.slice(min, max), 16);\r\n};\r\n\r\nconst hexToRGB = (hex) => {\r\n let r = parseInt(hex.slice(1, 3), 16);\r\n let g = parseInt(hex.slice(3, 5), 16);\r\n let b = parseInt(hex.slice(5, 7), 16);\r\n return [r,g,b];\r\n};\r\n\r\nexport const getClassFromAlias = (alias) => {\r\n let classNum = -1;\r\n classifications.forEach(classification => {\r\n if (classification.alias.includes(alias.toLowerCase())) {\r\n classNum = classification.id;\r\n }\r\n });\r\n\r\n return classNum;\r\n};\r\n\r\nexport const getNameFromClass = (classicationCheck) => {\r\n let alias = \"undefined\";\r\n\r\n classifications.forEach(classification => {\r\n if (classification.id === classicationCheck) {\r\n alias = classification.name;\r\n }\r\n });\r\n\r\n return alias;\r\n};\r\n\r\nconst getColorFromClassNum = (classNum) => {\r\n const rgbColor = hexToRGB(classificationColors[classNum]);\r\n return rgbColor;\r\n};\r\n\r\nexport const textToColor = (text, opacity=1.0) => {\r\n let classNum = getClassFromAlias(text);\r\n\r\n // If alias is similar to any of the defined classes (don't want to use 0,1 since white\r\n // and black are used for highlights and training areas)\r\n if (classNum > 1) {\r\n let rgbColor = getColorFromClassNum(classNum);\r\n return `rgba(${Math.ceil(rgbColor[0])}, ${Math.ceil(rgbColor[1])}, ${Math.ceil(rgbColor[2])}, ${opacity})`;\r\n }\r\n let [r,g,b,a] = textToColorArray(text, opacity);\r\n\r\n return `rgba(${Math.ceil(r)}, ${Math.ceil(g)}, ${Math.ceil(b)}, ${a})`;\r\n};\r\n\r\nexport const textToColorArray = (text, opacity=1.0) => {\r\n const colorHash = createHash('md5');\r\n const hash = colorHash.update(text).digest('hex');\r\n const h = (parseHex(hash, 0, 8) + parseHex(hash, 8, 16)) % 360;\r\n const s = 50 + (parseHex(hash, 16, 24) % 50);\r\n const l = 25 + (parseHex(hash, 24, 32) % 50);\r\n\r\n const color = new Color(`hsl(${h}, ${s}%, ${l}%)`);\r\n const {r,g,b} = color.multiplyScalar(255);\r\n\r\n return [Math.ceil(r), Math.ceil(g), Math.ceil(b), opacity];\r\n};\r\n\r\n\r\n\r\n","import { CanvasTexture, LinearFilter } from \"three\";\r\nimport { fetchImage, isMobile, resizeImage } from \"../utilities\";\r\n\r\ninterface CachedResponse {\r\n texture: CanvasTexture;\r\n missing: boolean;\r\n cancelled: boolean;\r\n lastAccess: number;\r\n path: string;\r\n width: number;\r\n height: number;\r\n}\r\n\r\nexport class TextureCache {\r\n private cache : { [path: string]: CachedResponse } = {};\r\n private maxCacheSize = 0;\r\n private maxTextureSize = Infinity;\r\n private maxDeviceSize = isMobile ? 4096 : 8192\r\n private isThumbnailCache: boolean;\r\n\r\n constructor(maxCacheSize: number, isThumbnailCache: boolean) {\r\n this.maxCacheSize = maxCacheSize;\r\n this.isThumbnailCache = isThumbnailCache;\r\n }\r\n\r\n setMaxTextureSize(textureSize: number) {\r\n this.maxTextureSize = Math.min(this.maxDeviceSize, textureSize);\r\n }\r\n\r\n async get(imagePath: string, controller: AbortController): Promise {\r\n this.manage();\r\n\r\n if (this.isThumbnailCache) {\r\n imagePath = `${imagePath}?thumbnail=true`;\r\n }\r\n\r\n if (imagePath in this.cache) {\r\n // Update last used timestamp and return cached values\r\n this.cache[imagePath].lastAccess = performance.now();\r\n return this.cache[imagePath];\r\n }\r\n\r\n const response = await this.load(imagePath, controller);\r\n\r\n // Textures are not cached for mobile devices\r\n if (isMobile) return response;\r\n\r\n this.cache[imagePath] = response;\r\n return this.cache[imagePath];\r\n }\r\n\r\n reset() {\r\n const keys = Object.keys(this.cache);\r\n const toRemove = keys.map(key => this.cache[key]);\r\n this.closeImages(toRemove);\r\n\r\n // Reset cache values\r\n this.cache = {};\r\n }\r\n\r\n /** @private */\r\n closeImages(images: CachedResponse[]) {\r\n // Close all image bitmaps to free up memory\r\n images.forEach(imageData => {\r\n const {texture} = imageData;\r\n if (!texture) return;\r\n\r\n const image = texture.image;\r\n\r\n if (image instanceof ImageBitmap) {\r\n image.close();\r\n } else if (image instanceof HTMLCanvasElement) {\r\n image.remove();\r\n }\r\n });\r\n }\r\n\r\n /** @private */\r\n async load(path: string, controller: AbortController): Promise {\r\n let image = null;\r\n let texture = null;\r\n let missing = false;\r\n let cancelled = false;\r\n let height = null;\r\n let width = null;\r\n\r\n try {\r\n const imageInfo = await this.getImageInfo(path, controller);\r\n\r\n image = imageInfo.image;\r\n texture = new CanvasTexture(image);\r\n texture.minFilter = LinearFilter;\r\n texture.generateMipmaps = false;\r\n width = imageInfo.width;\r\n height = imageInfo.height;\r\n } catch (err) {\r\n // Request was aborted on purpose\r\n cancelled = err.code === DOMException.ABORT_ERR;\r\n\r\n // Image must be missing\r\n missing = true;\r\n }\r\n\r\n const lastAccess = performance.now();\r\n\r\n return {\r\n texture,\r\n missing,\r\n cancelled,\r\n lastAccess,\r\n path,\r\n width,\r\n height\r\n };\r\n }\r\n\r\n /** @private */\r\n manage() {\r\n const keys = Object.keys(this.cache);\r\n let data = keys.map(key => this.cache[key]);\r\n\r\n // Remove cancelled requests\r\n data = data.filter(imageData => !imageData.cancelled);\r\n\r\n // Remove oldest requests\r\n data.sort((a,b) => a.lastAccess - b.lastAccess);\r\n data.reverse();\r\n\r\n const toKeep = data.slice(0, this.maxCacheSize);\r\n const toRemove = data.slice(this.maxCacheSize);\r\n\r\n this.closeImages(toRemove);\r\n\r\n // Rebuild final cache\r\n this.cache = {};\r\n toKeep.forEach(imageData => {\r\n const key = imageData.path;\r\n this.cache[key] = imageData;\r\n });\r\n }\r\n\r\n /** @private */\r\n async getImageInfo(path: string, controller: AbortController) {\r\n const signal = controller.signal;\r\n const image = await fetchImage(path, signal);\r\n const originalWidth = image.width;\r\n const originalHeight = image.height;\r\n\r\n const maxEdgeLength = Math.max(image.width, image.height);\r\n const needsResize = maxEdgeLength > this.maxTextureSize;\r\n\r\n if (needsResize) {\r\n const scale = this.maxTextureSize/maxEdgeLength;\r\n const width = Math.floor(image.width * scale);\r\n const height = Math.floor(image.height * scale);\r\n const resized = await resizeImage(image, width, height);\r\n return {image: resized, width: originalWidth, height: originalHeight};\r\n }\r\n\r\n return {image: image, width: originalWidth, height: originalHeight};\r\n }\r\n}\r\n","import {\r\n DataProjectionCoordinate,\r\n getEulerInverse,\r\n SceneCoordinate,\r\n SphericalPosition\r\n} from '../projections';\r\nimport { Viewer } from '../main';\r\nimport {\r\n Asset,\r\n AssetType,\r\n CameraData\r\n} from '../../redux/assets-slice';\r\nimport {\r\n AmbientLight,\r\n BoxGeometry,\r\n BufferAttribute,\r\n BufferGeometry,\r\n CanvasTexture,\r\n Euler,\r\n MathUtils,\r\n Matrix4,\r\n Mesh,\r\n PerspectiveCamera,\r\n Scene,\r\n Texture,\r\n Vector3\r\n} from 'three';\r\nimport { MarkerMaterial, PanoramicImageMaterial, PlanarImageMaterial } from \"../rendering\";\r\nimport { CustomMouseEvent, MouseControls } from \"../controls\";\r\nimport { toast } from \"../../app\";\r\nimport { SceneCameraState } from \"../../redux/camera-slice\";\r\nimport { t } from \"../../localization\";\r\nimport { TextureCache } from \"./texture-cache\";\r\nimport {\r\n AerialCameras,\r\n PanoramicCameraFile,\r\n PlanarCameraFile,\r\n PlanarImage,\r\n SceneViewCameras\r\n} from '.';\r\nimport {Feature} from \"ol\";\r\nimport { MarkerNavType } from '../../redux/settings-slice';\r\nimport {isEqual} from 'lodash';\r\nimport { Point } from 'ol/geom';\r\nimport path from 'path';\r\n\r\nconst thumbnailCache = new TextureCache(40, true);\r\nconst standardCache = new TextureCache(10, false);\r\n\r\nexport interface ImagePixel {\r\n u: number,\r\n v: number\r\n}\r\n\r\nexport interface CameraLoadOptions {\r\n fov?: number\r\n angles?: number[]\r\n lookat?: DataProjectionCoordinate\r\n centerOnImage?: boolean\r\n}\r\n\r\nexport type CameraArguments = ConstructorParameters\r\n\r\nexport type CameraFileArguments = ConstructorParameters\r\n\r\nclass ImagePosition {\r\n private _scene: SceneCoordinate;\r\n private _aerial: number[];\r\n private _value: Vector3;\r\n\r\n private input: Vector3;\r\n private image: CameraImage;\r\n\r\n constructor(image: CameraImage, position) {\r\n this.image = image;\r\n this.input = new Vector3(...position);\r\n }\r\n\r\n get offset() {\r\n let matrix = new Matrix4()\r\n .copy(this.image.matrix)\r\n .transpose();\r\n\r\n return new Vector3()\r\n .setFromMatrixPosition(matrix);\r\n }\r\n\r\n get value() {\r\n if (!this._value) {\r\n const euler = this.image.rotation.input;\r\n\r\n const offset = new Vector3()\r\n .copy(this.offset)\r\n .applyEuler(euler);\r\n\r\n const position = new Vector3()\r\n .copy(this.input)\r\n .add(offset);\r\n\r\n this._value = position;\r\n }\r\n\r\n return this._value;\r\n }\r\n\r\n get scene() {\r\n if (!this._scene) {\r\n const value = new DataProjectionCoordinate(this.value).toScene();\r\n this._scene = value;\r\n }\r\n\r\n return this._scene;\r\n }\r\n\r\n get aerial() {\r\n if (!this._aerial) {\r\n const value = new DataProjectionCoordinate(this.value).toAerial();\r\n this._aerial = value;\r\n }\r\n\r\n return this._aerial;\r\n }\r\n\r\n reset() {\r\n this._value = null;\r\n this._scene = null;\r\n this._aerial = null;\r\n }\r\n}\r\n\r\nclass ImageRotation {\r\n private _euler: Euler;\r\n\r\n public array = [0,0,0];\r\n public input: THREE.Euler;\r\n private image: CameraImage;\r\n\r\n constructor(image: CameraImage, rotation) {\r\n this.image = image;\r\n this.setRotation(rotation);\r\n }\r\n\r\n get matrix() {\r\n return new Matrix4()\r\n .copy(this.image.matrix)\r\n .setPosition(0,0,0);\r\n }\r\n\r\n get adjustment() {\r\n if (this.image.adjustment) {\r\n const angles = this.image.adjustment;\r\n const x = -1 * MathUtils.degToRad(angles.x);\r\n const y = -1 * MathUtils.degToRad(angles.y);\r\n const z = -1 * MathUtils.degToRad(angles.z);\r\n return new Euler(x, y, z);\r\n }\r\n\r\n return new Euler(0,0,0);\r\n }\r\n\r\n get euler() {\r\n if (!this._euler) {\r\n const rotationWithTransform = multiplyRotations(\r\n this.input, this.matrix);\r\n\r\n const rotationWithAdjustment = multiplyRotations(\r\n rotationWithTransform, this.adjustment);\r\n\r\n const value = new Euler().setFromRotationMatrix(\r\n rotationWithAdjustment);\r\n\r\n this._euler = value;\r\n }\r\n\r\n return this._euler;\r\n }\r\n\r\n get scene() {\r\n return this.euler;\r\n }\r\n\r\n get degrees() {\r\n const x = -1 * MathUtils.radToDeg(this.euler.x);\r\n const y = -1 * MathUtils.radToDeg(this.euler.y);\r\n const z = -1 * MathUtils.radToDeg(this.euler.z);\r\n return new Euler(x,y,z);\r\n }\r\n\r\n get inputInverted() {\r\n return getEulerInverse(this.input);\r\n }\r\n\r\n setRotation(rotation) {\r\n this.array = rotation;\r\n const x = -1 * MathUtils.degToRad(rotation[0]);\r\n const y = -1 * MathUtils.degToRad(rotation[1]);\r\n const z = -1 * MathUtils.degToRad(rotation[2]);\r\n this.input = new Euler(x,y,z);\r\n }\r\n\r\n reset() {\r\n this._euler = null;\r\n }\r\n\r\n clear() {\r\n this.setRotation([0,0,0]);\r\n }\r\n}\r\n\r\nexport class CameraFeature extends Feature {\r\n public camera: CameraImage;\r\n\r\n constructor(opts) {\r\n super(opts);\r\n this.camera = opts.camera;\r\n }\r\n}\r\n\r\nexport class CameraImage {\r\n public id: string;\r\n public name: string;\r\n public root: string;\r\n public path: string;\r\n public adjustment: Vector3\r\n public object: Mesh;\r\n public feature: CameraFeature;\r\n public enabled = false;\r\n public loaded = false;\r\n public loading = false;\r\n public missing = false;\r\n public geometry: BoxGeometry;\r\n public cameraData: CameraData;\r\n public cameraFile: CameraFile;\r\n private controller: AbortController;\r\n public imageWidth = 0;\r\n public imageHeight = 0;\r\n public scene: Scene;\r\n public camera: PerspectiveCamera;\r\n public matrix: Matrix4 = new Matrix4();\r\n public controls: MouseControls;\r\n public position: ImagePosition;\r\n public rotation: ImageRotation;\r\n\r\n protected material: PanoramicImageMaterial | PlanarImageMaterial;\r\n private texture: CanvasTexture;\r\n protected missingTexture: Texture;\r\n\r\n constructor(cameraFile: CameraFile, data: CameraData, scene: Scene, camera: PerspectiveCamera, controls: MouseControls) {\r\n this.cameraData = data;\r\n this.cameraFile = cameraFile;\r\n\r\n this.id = data.id;\r\n this.name = data.name;\r\n this.path = data.path;\r\n\r\n // The root is the name without the extension\r\n const extension = path.extname(this.name);\r\n this.root = path.basename(this.name, extension);\r\n\r\n this.camera = camera;\r\n this.scene = scene;\r\n this.controls = controls;\r\n\r\n const position = [data.x, data.y, data.z];\r\n this.position = new ImagePosition(this, position);\r\n\r\n const rotation = [data.roll, data.pitch, data.yaw];\r\n this.rotation = new ImageRotation(this, rotation);\r\n\r\n this.reset();\r\n }\r\n\r\n setMatrix(matrix: Matrix4) {\r\n this.matrix = matrix;\r\n this.rotation.reset();\r\n this.position.reset();\r\n }\r\n\r\n setAdjustment(adjustments) {\r\n this.adjustment = (this.id in adjustments)\r\n ? new Vector3(...adjustments[this.id])\r\n : null;\r\n\r\n this.rotation.reset();\r\n }\r\n\r\n updateFeature() {\r\n const position = this.position.aerial;\r\n const point = new Point([position[0], position[1]]);\r\n\r\n if (this.feature) {\r\n // Update existing feature\r\n this.feature.setGeometry(point);\r\n } else {\r\n // Create a new feature\r\n this.feature = new CameraFeature({\r\n geometry: point,\r\n camera: this\r\n });\r\n }\r\n }\r\n\r\n pixelToDirection(pixel: ImagePixel) : Vector3 {\r\n console.warn(\"Not implemented\");\r\n return new Vector3();\r\n }\r\n\r\n directionToPixel(direction: Vector3) : ImagePixel {\r\n console.warn(\"Not implemented\");\r\n return null;\r\n }\r\n\r\n /** @private */\r\n setCameraPosition() {\r\n this.camera.position.copy(this.position.scene);\r\n this.object.position.copy(this.position.scene);\r\n this.object.rotation.copy(this.rotation.scene);\r\n }\r\n\r\n /** @private */\r\n setCameraParameters(opts: CameraLoadOptions) {\r\n if (opts.fov) {\r\n this.controls.fov = opts.fov;\r\n }\r\n\r\n if (opts.lookat) {\r\n let position = new DataProjectionCoordinate(opts.lookat).toScene();\r\n this.controls.angles = positionToCameraAngle(\r\n this.object.position, position);\r\n } else if (opts.angles) {\r\n this.controls.angles = opts.angles;\r\n }\r\n }\r\n\r\n /** @private */\r\n async grabImageFromPath(thumbnail: boolean) {\r\n this.controller = new AbortController();\r\n\r\n const textureCache = thumbnail\r\n ? thumbnailCache\r\n : standardCache;\r\n\r\n const response = await textureCache.get(this.path, this.controller);\r\n\r\n this.texture = response.texture;\r\n this.missing = response.missing;\r\n\r\n if (this.texture && !thumbnail) {\r\n this.imageWidth = response.width;\r\n this.imageHeight = response.height;\r\n }\r\n\r\n if (!this.enabled) return;\r\n\r\n this.updateMaterial();\r\n\r\n if (this.missing) {\r\n toast.error(t(\"toast.image-load-error\", {\r\n name: this.name\r\n }));\r\n }\r\n }\r\n\r\n setObjectVisible(state) {\r\n this.object.visible = state;\r\n }\r\n\r\n activate(opts: CameraLoadOptions = {}) {\r\n this.setCameraPosition();\r\n this.setCameraParameters(opts);\r\n this.setObjectVisible(true);\r\n\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n\r\n initialize() {\r\n this.enabled = true;\r\n this.loaded = false;\r\n this.loading = true;\r\n this.generateObject();\r\n }\r\n\r\n async load() {\r\n const loadThumbnail = this.cameraFile.cloud;\r\n\r\n if (!loadThumbnail) {\r\n // Load full image and return\r\n await this.loadFullImage();\r\n return;\r\n }\r\n\r\n // Load preview image\r\n await this.loadThumbnail();\r\n if (this.missing) return;\r\n\r\n // Load full image, but dont await results\r\n this.loadFullImage();\r\n }\r\n\r\n /** @private */\r\n async loadThumbnail() {\r\n await this.grabImageFromPath(true);\r\n }\r\n\r\n /** @private */\r\n async loadFullImage() {\r\n await this.grabImageFromPath(false);\r\n }\r\n\r\n applyTempRotation(angles) {\r\n const angleEuler = new Euler(\r\n -1 * MathUtils.degToRad(angles[0]),\r\n -1 * MathUtils.degToRad(angles[1]),\r\n -1 * MathUtils.degToRad(angles[2])\r\n );\r\n\r\n const tempRotation = multiplyRotations(\r\n this.rotation.input, angleEuler);\r\n const euler = new Euler()\r\n .setFromRotationMatrix(tempRotation);\r\n\r\n if (this.object) {\r\n this.object.rotation.copy(euler);\r\n }\r\n\r\n }\r\n\r\n /** @private */\r\n generateObject() {\r\n const geometry = new BoxGeometry(10, 10, 10);\r\n const mesh = new Mesh(geometry, this.material);\r\n mesh.visible = false;\r\n\r\n this.object = mesh;\r\n this.scene.add(this.object);\r\n }\r\n\r\n /** @private */\r\n updateMaterial() {\r\n this.material.tImage = this.missing\r\n ? this.missingTexture\r\n : this.texture;\r\n }\r\n\r\n destroy() {\r\n if (!this.enabled) return false;\r\n\r\n if (this.controller) {\r\n this.controller.abort();\r\n this.controller = null;\r\n }\r\n\r\n if (this.object) {\r\n this.scene.remove(this.object);\r\n }\r\n\r\n if (this.material) {\r\n this.material.dispose();\r\n }\r\n\r\n if (this.geometry) {\r\n this.geometry.dispose();\r\n }\r\n\r\n if (this.texture) {\r\n this.texture.dispose();\r\n }\r\n\r\n this.reset();\r\n }\r\n\r\n reset() {\r\n this.object = null;\r\n this.enabled = false;\r\n this.geometry = null;\r\n this.texture = null;\r\n\r\n if (this.material) {\r\n this.material.tImage = null;\r\n }\r\n }\r\n}\r\n\r\nexport class CameraFile {\r\n public id: string;\r\n public folderID: string;\r\n public cloud: boolean;\r\n public visible = false;\r\n private needsUpdate = true;\r\n\r\n public cameras: CameraImage[] = [];\r\n private features: CameraFeature[] = [];\r\n protected cameraHandler: CameraHandler;\r\n\r\n private standardMaterial: MarkerMaterial\r\n private standardMesh: Mesh\r\n private pickingMaterial: MarkerMaterial\r\n private pickingMesh: Mesh\r\n private geometry: BufferGeometry;\r\n\r\n private numVertices = 6;\r\n private uvs: number[] = [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1];\r\n private corners: number[] = [0, 2, 1, 2, 3, 1];\r\n private vertices: Vector3[] = [\r\n new Vector3(-0.5, 0.5, 0),\r\n new Vector3(0.5, 0.5, 0),\r\n new Vector3(-0.5, -0.5, 0),\r\n new Vector3(0.5, -0.5, 0)\r\n ]\r\n\r\n constructor(cameraHandler: CameraHandler, asset: Asset) {\r\n this.cameraHandler = cameraHandler;\r\n this.id = asset.id;\r\n this.cloud = asset.cloud;\r\n this.folderID = asset.folderID;\r\n\r\n // Add new camera data\r\n const cameraData = asset.data as CameraData[];\r\n cameraData.forEach(data => {\r\n const camera = this.getNewCamera(data);\r\n camera.setMatrix(cameraHandler.matrix);\r\n camera.setAdjustment(cameraHandler.adjustments);\r\n this.cameras.push(camera);\r\n });\r\n\r\n // NOTE: Special hack for mosaic\r\n if (this.id === \"9xlU4x4onuF02ixxFvyXk\") {\r\n this.cameras.sort((a,b) => {\r\n if (a.name < b.name) return -1;\r\n if (a.name > b.name) return 1;\r\n return 0;\r\n });\r\n }\r\n\r\n this.initSceneView();\r\n }\r\n\r\n get viewer() {\r\n return this.cameraHandler.viewer;\r\n }\r\n\r\n get scene() {\r\n return this.cameraHandler.markerScene;\r\n }\r\n\r\n get picker() {\r\n return this.viewer.gpuPickers.markers;\r\n }\r\n\r\n get map() {\r\n return this.viewer.minimap.map;\r\n }\r\n\r\n get meshes() {\r\n return [this.standardMesh, this.pickingMesh];\r\n }\r\n\r\n get materials() {\r\n return [this.standardMaterial, this.pickingMaterial];\r\n }\r\n\r\n get mapSource() {\r\n return this.cameraHandler.aerialController.mapSource;\r\n }\r\n\r\n getByID(cameraID: string): CameraImage {\r\n return this.cameras.find(camera => camera.id === cameraID);\r\n }\r\n\r\n getByName(name: string): CameraImage {\r\n return this.cameras.find(camera => {\r\n return (camera.name === name) || (camera.root === name);\r\n });\r\n }\r\n\r\n getByPickerID(pickerID: number): CameraImage {\r\n const attributes = this.pickingMesh.geometry.attributes;\r\n const gpuIndex = attributes.gpu_index.array as number[];\r\n const arrIndex = gpuIndex.indexOf(pickerID);\r\n if (arrIndex === -1) return null;\r\n\r\n const cameraIndex = attributes.camera_index.array[arrIndex];\r\n return this.cameras[cameraIndex];\r\n }\r\n\r\n initSceneView() {\r\n const numCameras = this.cameras.length;\r\n const arrayLength = numCameras * this.numVertices;\r\n\r\n const selected = new Float32Array(arrayLength);\r\n const visible = new Float32Array(arrayLength);\r\n const markerShape = new Float32Array(arrayLength);\r\n const positions = new Float32Array(arrayLength * 3);\r\n const uvs = new Float32Array(arrayLength * 2);\r\n const indices = new Int32Array(arrayLength);\r\n const cameraIndices = new Int32Array(arrayLength);\r\n\r\n this.cameras.forEach((camera, cameraIndex) => {\r\n // Set the marker shape. Default is circular\r\n let cameraShape = camera instanceof PlanarImage ? 1.0 : 0.0;\r\n\r\n // Assign our uv values\r\n const numUvs = this.uvs.length;\r\n this.uvs.forEach((uv, uvIndex) => {\r\n let index = (numUvs * cameraIndex) + uvIndex;\r\n uvs[index] = uv;\r\n });\r\n\r\n // Create attribute arrays for each vertex in each cam.\r\n const numVertices = this.numVertices;\r\n for (var i = 0; i < this.numVertices; i++) {\r\n let index = (numVertices * cameraIndex) + i;\r\n selected[index] = 0.0;\r\n visible[index] = 1.0;\r\n indices[index] = 0.0;\r\n markerShape[index] = cameraShape;\r\n cameraIndices[index] = cameraIndex;\r\n }\r\n });\r\n\r\n const geometry = new BufferGeometry();\r\n geometry.setAttribute('selected', new BufferAttribute(selected, 1));\r\n geometry.setAttribute('visible', new BufferAttribute(visible, 1));\r\n geometry.setAttribute('marker_shape', new BufferAttribute(markerShape, 1));\r\n geometry.setAttribute('gpu_index', new BufferAttribute(indices, 1));\r\n geometry.setAttribute('camera_index', new BufferAttribute(cameraIndices, 1));\r\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\r\n geometry.setAttribute('uv', new BufferAttribute(uvs, 2));\r\n\r\n this.standardMaterial = new MarkerMaterial(false);\r\n this.standardMesh = new Mesh(geometry, this.standardMaterial);\r\n this.standardMesh.visible = false;\r\n this.scene.add(this.standardMesh);\r\n\r\n this.pickingMaterial = new MarkerMaterial(true);\r\n this.pickingMesh = new Mesh(geometry, this.pickingMaterial);\r\n this.pickingMesh.visible = false;\r\n this.picker.add(this.pickingMesh);\r\n\r\n this.geometry = geometry;\r\n }\r\n\r\n updateMatrix(matrix: Matrix4) {\r\n this.cameras.forEach(camera => {\r\n camera.setMatrix(matrix);\r\n });\r\n\r\n this.needsUpdate = true;\r\n this.updateCameras();\r\n }\r\n\r\n updateAdjustments(adjustments = {}) {\r\n this.cameras.forEach(camera => {\r\n camera.setAdjustment(adjustments);\r\n });\r\n }\r\n\r\n updateAerialView() {\r\n for (let camera of this.cameras) {\r\n camera.updateFeature();\r\n }\r\n\r\n if (this.features.length > 0) return;\r\n\r\n this.features = this.cameras\r\n .map(camera => camera.feature);\r\n\r\n this.mapSource.addFeatures(this.features);\r\n }\r\n\r\n updateSceneView() {\r\n const positions = this.geometry.attributes.position;\r\n\r\n this.cameras.forEach((camera, cameraIndex) => {\r\n const position = camera.position.scene;\r\n const numCorners = this.corners.length;\r\n this.corners.forEach((corner, cornerIndex) => {\r\n let index = (numCorners * cameraIndex) + cornerIndex;\r\n let vertex = this.vertices[corner];\r\n\r\n let x = vertex.x + position.x;\r\n let y = vertex.y + position.y;\r\n let z = vertex.z + position.z;\r\n\r\n positions.setXYZ(index, x, y, z);\r\n });\r\n });\r\n\r\n this.updateUniforms();\r\n this.updatePicker();\r\n }\r\n\r\n getNewCamera(data: CameraData): CameraImage {\r\n console.warn(\"Not implemented\");\r\n return null;\r\n }\r\n\r\n setSelected(camera: CameraImage) {\r\n this.meshes.forEach(mesh => {\r\n const attributes = mesh.geometry.attributes;\r\n const selected = attributes.selected.array as number[];\r\n selected.fill(0.0);\r\n\r\n if (this.cameras.includes(camera)) {\r\n const index = this.cameras.indexOf(camera);\r\n const baseIndex = this.numVertices * index;\r\n for (let i = 0; i < this.numVertices; i++) {\r\n selected[baseIndex + i] = 1.00;\r\n }\r\n }\r\n\r\n attributes.selected.needsUpdate = true;\r\n });\r\n }\r\n\r\n setVisible(state: boolean) {\r\n if (this.visible === state) return;\r\n\r\n this.visible = state;\r\n\r\n if (this.standardMesh) {\r\n this.standardMesh.visible = state;\r\n }\r\n\r\n if (this.pickingMesh) {\r\n this.pickingMesh.visible = state;\r\n }\r\n\r\n if (!this.visible) {\r\n this.cameras.forEach(camera => {\r\n camera.destroy();\r\n });\r\n }\r\n\r\n this.updateCameras();\r\n this.updatePicker();\r\n }\r\n\r\n /** @private */\r\n updateCameras() {\r\n if (this.needsUpdate && this.visible) {\r\n this.updateAerialView();\r\n this.updateSceneView();\r\n this.needsUpdate = false;\r\n }\r\n\r\n const visible = this.visible ? 1 : 0;\r\n for (let feature of this.features) {\r\n feature.set(\"visible\", visible, true);\r\n }\r\n\r\n if (this.features.length > 0) {\r\n this.mapSource.changed();\r\n }\r\n }\r\n\r\n updatePicker() {\r\n this.picker.needsUpdate = true;\r\n }\r\n\r\n updateUniforms() {\r\n const camera = this.viewer.camera;\r\n const rotation = camera.rotation.toVector3();\r\n const cameraLoading = this.viewer.initialCameraLoading;\r\n\r\n const current = this.cameraHandler.current;\r\n const currentIndex = this.cameras.indexOf(current);\r\n\r\n const visible = this.visible\r\n && this.cameraHandler.markersVisible\r\n && !cameraLoading;\r\n\r\n // Set mesh visibility\r\n this.meshes.forEach(mesh => {\r\n mesh.visible = visible;\r\n });\r\n\r\n // Update shader parameters\r\n this.materials.forEach((material: MarkerMaterial) => {\r\n material.cameraRotation = rotation;\r\n material.windowHeight = window.innerHeight;\r\n material.currentIndex = currentIndex;\r\n material.orbitMode = this.viewer.orbitState;\r\n material.cameraHeight = this.cameraHandler.cameraHeight;\r\n material.fov = MathUtils.degToRad(camera.fov);\r\n material.needsUpdate = true;\r\n });\r\n }\r\n\r\n update() {\r\n this.updateUniforms();\r\n }\r\n\r\n removeFeatures() {\r\n const removedFeatures = [];\r\n\r\n for (let feature of this.features) {\r\n // @ts-ignore\r\n const removedFeature = this.mapSource.removeFeatureInternal(feature);\r\n\r\n if (removedFeature) {\r\n removedFeatures.push(removedFeature);\r\n }\r\n }\r\n\r\n if (removedFeatures.length > 0) {\r\n this.mapSource.changed();\r\n }\r\n\r\n this.features = [];\r\n }\r\n\r\n destroy() {\r\n /**\r\n * VectorSource.removeFeatures() was added in openlayers 9.1.0.\r\n * Currently using a custom solution based on the source code\r\n * */\r\n this.removeFeatures();\r\n this.features = [];\r\n\r\n if (this.standardMesh) {\r\n this.scene.remove(this.standardMesh);\r\n this.standardMaterial.dispose();\r\n }\r\n\r\n if (this.pickingMesh) {\r\n this.picker.remove(this.pickingMesh);\r\n this.pickingMaterial.dispose();\r\n }\r\n\r\n this.cameras.forEach(camera => {\r\n camera.destroy();\r\n });\r\n\r\n this.cameras = [];\r\n }\r\n}\r\n\r\nexport class CameraHandler {\r\n public viewer: Viewer;\r\n public cameraScene: Scene;\r\n public markerScene: Scene;\r\n public sceneViewController: SceneViewCameras;\r\n public aerialController: AerialCameras;\r\n public cameras: CameraImage[] = [];\r\n public files: CameraFile[] = [];\r\n public matrix = new Matrix4();\r\n public adjustments = {};\r\n public cameraHeight = 0;\r\n public aligned = false;\r\n public waitForCameras = false;\r\n public current: CameraImage | null = null;\r\n public newCameraLoading = false\r\n public cameraLoadedOnce = false;\r\n\r\n constructor(viewer: Viewer, maxTextureSize: number) {\r\n this.viewer = viewer;\r\n this.initScenes();\r\n\r\n this.sceneViewController = new SceneViewCameras(this);\r\n this.aerialController = new AerialCameras(this);\r\n\r\n thumbnailCache.setMaxTextureSize(maxTextureSize);\r\n standardCache.setMaxTextureSize(maxTextureSize);\r\n }\r\n\r\n get map() {\r\n return this.viewer.minimap.map;\r\n }\r\n\r\n get numCameras() {\r\n return this.cameras.length;\r\n }\r\n\r\n get camera() {\r\n return this.viewer.camera;\r\n }\r\n\r\n get controls() {\r\n return this.viewer.controls;\r\n }\r\n\r\n get pointclouds() {\r\n return this.viewer.pointclouds;\r\n }\r\n\r\n get minimap() {\r\n return this.viewer.minimap;\r\n }\r\n\r\n get currentIndex() {\r\n return this.cameras.indexOf(this.current);\r\n }\r\n\r\n get cameraLoaded() {\r\n return this.current !== null;\r\n }\r\n\r\n get renderInFront() {\r\n return this.sceneViewController.renderInFront;\r\n }\r\n\r\n get isEmpty() {\r\n return this.cameras.length === 0;\r\n }\r\n\r\n get markersVisible() {\r\n return this.sceneViewController.markersVisible;\r\n }\r\n\r\n addNewFile(asset: Asset) {\r\n if (this.getByID(asset.id)) return;\r\n\r\n let file: CameraFile;\r\n\r\n if (asset.type === AssetType.Panoramic) {\r\n file = new PanoramicCameraFile(this, asset);\r\n } else if (asset.type === AssetType.Planar) {\r\n file = new PlanarCameraFile(this, asset);\r\n } else {\r\n return;\r\n }\r\n\r\n this.files.push(file);\r\n }\r\n\r\n deleteFile(file: CameraFile) {\r\n file.destroy();\r\n\r\n const index = this.files.indexOf(file);\r\n this.files.splice(index, 1);\r\n }\r\n\r\n updateVisibility(asset: Asset) {\r\n let file = this.getByID(asset.id);\r\n if (!file) return;\r\n\r\n file.setVisible(asset.visible);\r\n }\r\n\r\n reconcile(camerasFiles: Asset[]) {\r\n const currentIDs = new Set(this.files.map(x => x.id));\r\n const newAssetIDs = new Set(camerasFiles.map(x => x.id));\r\n const assetsToLoad = camerasFiles.filter(x => !currentIDs.has(x.id));\r\n const filesToDelete = this.files.filter(x => !newAssetIDs.has(x.id));\r\n\r\n let cameraFilesAdded = assetsToLoad.length;\r\n let cameraFilesRemoved = filesToDelete.length;\r\n\r\n // Delete old camera files\r\n filesToDelete.forEach(file => {\r\n this.deleteFile(file);\r\n });\r\n\r\n // Add new camera files\r\n assetsToLoad.forEach(asset => {\r\n this.addNewFile(asset);\r\n });\r\n\r\n // Toggle visibility for each file\r\n camerasFiles.forEach(file => {\r\n this.updateVisibility(file);\r\n });\r\n\r\n // Update combined camera array\r\n this.cameras = this.files\r\n .filter(file => file.visible)\r\n .map(file => file.cameras)\r\n .flat();\r\n\r\n // Current camera has been removed / hidden\r\n if (this.current && !this.cameras.includes(this.current)) {\r\n this.viewer.clearCurrentCamera();\r\n }\r\n\r\n // All camera files have been removed\r\n if (this.files.length === 0) {\r\n this.cameraLoadedOnce = false;\r\n }\r\n\r\n return {cameraFilesAdded, cameraFilesRemoved};\r\n }\r\n\r\n initScenes() {\r\n this.cameraScene = new Scene();\r\n this.cameraScene.add(new AmbientLight(0xFFFFFF));\r\n\r\n this.markerScene = new Scene();\r\n this.markerScene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n getFeatureForEvent(event) {\r\n return this.aerialController.getFeatureForEvent(event);\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n this.sceneViewController.onMouseMove(event);\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n return this.sceneViewController.onMouseUp(event);\r\n }\r\n\r\n onKeyDown(event) {\r\n if (event.key === \"ArrowUp\") {\r\n const index = this.getNextIndex();\r\n const camera = this.cameras[index];\r\n this.viewer.loadImage(camera.id);\r\n }\r\n\r\n if (event.key === \"ArrowDown\") {\r\n const index = this.getPreviousIndex();\r\n const camera = this.cameras[index];\r\n this.viewer.loadImage(camera.id);\r\n }\r\n }\r\n\r\n setWaitForCameras(state) {\r\n this.waitForCameras = state;\r\n }\r\n\r\n /** @private */\r\n setNormalCamera() {\r\n this.controls.setOrbitValues(false);\r\n }\r\n\r\n /** @private */\r\n setOrbitCamera() {\r\n this.controls.setOrbitValues(true);\r\n }\r\n\r\n setNavigationType(type: MarkerNavType) {\r\n this.sceneViewController.setNavigationType(type);\r\n }\r\n\r\n setCameraHeight(height: number) {\r\n this.cameraHeight = height;\r\n }\r\n\r\n /** @private */\r\n setCurrentImage(cameraImage: CameraImage | null) {\r\n this.current = cameraImage;\r\n }\r\n\r\n getByID(assetID: string) {\r\n return this.files.find(file => file.id === assetID);\r\n }\r\n\r\n getCameraByName(cameraName: string): CameraImage {\r\n for (let file of this.files) {\r\n const camera = file.getByName(cameraName);\r\n if (camera) return camera;\r\n }\r\n }\r\n\r\n getCameraByID(cameraID: string): CameraImage {\r\n for (let file of this.files) {\r\n const camera = file.getByID(cameraID);\r\n if (camera) return camera;\r\n }\r\n }\r\n\r\n getCamerasByCSV(assetID: string): CameraImage[] {\r\n const file = this.getByID(assetID);\r\n return file ? file.cameras : [];\r\n }\r\n\r\n getCamerasByFolder(folderID: string): CameraImage[] {\r\n return this.files\r\n .filter(file => file.folderID === folderID)\r\n .map(file => file.cameras)\r\n .flat();\r\n }\r\n\r\n getRowsCSV(cameras: CameraImage[]) {\r\n let csvEncompassOut = [];\r\n csvEncompassOut.push(['Filename', 'X', 'Y', 'Z','Roll', 'Pitch', 'Yaw']);\r\n\r\n cameras.forEach(camera => {\r\n let position = camera.position.value;\r\n let rotation = camera.rotation.degrees;\r\n\r\n csvEncompassOut.push([\r\n camera.name,\r\n position.x, position.y, position.z,\r\n rotation.x, rotation.y, rotation.z\r\n ]);\r\n });\r\n\r\n return csvEncompassOut;\r\n }\r\n\r\n async loadImage(cameraID, opts:CameraLoadOptions = {}) {\r\n if (this.newCameraLoading) return;\r\n\r\n let camera = this.getCameraByID(cameraID);\r\n if (!camera) return;\r\n\r\n const {centerOnImage=true} = opts;\r\n\r\n if (camera.enabled) {\r\n // Reload existing camera\r\n console.log(`Reload camera: ${camera.name}`);\r\n\r\n this.setNormalCamera();\r\n camera.setCameraPosition();\r\n camera.setCameraParameters(opts);\r\n this.minimap.setCurrentCamera(camera, centerOnImage);\r\n\r\n return camera;\r\n }\r\n\r\n // Load new camera\r\n console.log(`Load camera: ${camera.name}`);\r\n\r\n this.newCameraLoading = true;\r\n\r\n if (!this.cameraLoaded) {\r\n this.setWaitForCameras(true);\r\n }\r\n\r\n // Load image data from path\r\n camera.initialize();\r\n await camera.load();\r\n\r\n // Update previous texture\r\n await this.viewer.updatePreviousTexture();\r\n\r\n // Destroy previous cameras and exit orbit mode\r\n this.clearImages(camera);\r\n this.setNormalCamera();\r\n this.minimap.setCurrentCamera(camera, centerOnImage);\r\n\r\n camera.activate(opts);\r\n\r\n this.setCurrentImage(camera);\r\n this.setWaitForCameras(false);\r\n this.updateArrowNavigation();\r\n\r\n this.cameraLoadedOnce = true;\r\n this.newCameraLoading = false;\r\n\r\n return camera;\r\n }\r\n\r\n updateArrowNavigation() {\r\n this.sceneViewController.updateArrowNavigation();\r\n }\r\n\r\n clearArrowNavigation() {\r\n this.sceneViewController.clearArrowNavigation();\r\n }\r\n\r\n clearImages(currentCamera: CameraImage) {\r\n /** Destroy all images except the current one */\r\n this.cameras.forEach(camera => {\r\n if (camera.id === currentCamera.id) {\r\n return;\r\n }\r\n camera.destroy();\r\n });\r\n }\r\n\r\n setMeshVisible(state) {\r\n this.cameras.forEach(camera => {\r\n if (state && !camera.enabled) {\r\n return;\r\n }\r\n\r\n if (camera.object) {\r\n camera.object.visible = state;\r\n }\r\n });\r\n }\r\n\r\n getNextIndex() {\r\n if (!this.current) return;\r\n\r\n let cameraIndex = this.currentIndex;\r\n let index = cameraIndex + 1;\r\n return (index + this.numCameras) % this.numCameras;\r\n }\r\n\r\n getPreviousIndex() {\r\n if (!this.current) return;\r\n\r\n let cameraIndex = this.currentIndex;\r\n let index = cameraIndex - 1;\r\n return (index + this.numCameras) % this.numCameras;\r\n }\r\n\r\n setCameraAdjustments(newAdjustments) {\r\n if (isEqual(this.adjustments, newAdjustments)) return;\r\n\r\n this.adjustments = newAdjustments;\r\n this.updateAdjustments();\r\n }\r\n\r\n setCameraMatrix(elements) {\r\n const newMatrix = new Matrix4().fromArray(elements);\r\n if (this.matrix.equals(newMatrix)) return;\r\n\r\n this.matrix = newMatrix;\r\n this.updateMatrix();\r\n }\r\n\r\n /** Reset to identity matrix */\r\n resetCameraMatrix() {\r\n this.matrix = new Matrix4();\r\n this.updateMatrix();\r\n }\r\n\r\n resetTextureCache() {\r\n thumbnailCache.reset();\r\n standardCache.reset();\r\n }\r\n\r\n /** @private */\r\n updateMatrix() {\r\n this.files.forEach(file => {\r\n file.updateMatrix(this.matrix);\r\n });\r\n\r\n if (this.current) {\r\n this.setNormalCamera();\r\n this.current.setCameraPosition();\r\n }\r\n\r\n this.updateArrowNavigation();\r\n }\r\n\r\n /** @private */\r\n updateAdjustments() {\r\n this.files.forEach(file => {\r\n file.updateAdjustments(this.adjustments);\r\n });\r\n }\r\n\r\n /** @private */\r\n loadSavedCameraState(savedCameraState: SceneCameraState) {\r\n if (this.numCameras === 0) return false;\r\n\r\n let savedcameraID;\r\n const activeCamera = savedCameraState.camera;\r\n const savedLookat = savedCameraState.lookat;\r\n\r\n if (activeCamera) {\r\n // Load saved camera based based on the camera id / camera name\r\n const camera = this.getCameraByID(activeCamera)\r\n || this.getCameraByName(activeCamera);\r\n\r\n if (camera) {\r\n savedcameraID = camera.id;\r\n }\r\n } else if (savedLookat) {\r\n // Load closest camera based on saved position\r\n const lookat = new DataProjectionCoordinate(savedLookat);\r\n const closestCameraID = this.closestCameraToPosition(lookat);\r\n\r\n if (closestCameraID) {\r\n savedcameraID = closestCameraID;\r\n } else {\r\n toast.warning(t(\"toast.camera-error-xyz\"));\r\n }\r\n }\r\n\r\n if (!savedcameraID) return false;\r\n\r\n // Convert from SceneCameraState to CameraLoadOptions\r\n const lookatVector = savedCameraState.lookat\r\n ? new DataProjectionCoordinate(savedCameraState.lookat)\r\n : null;\r\n\r\n const cameraLoadOptions = {\r\n fov: savedCameraState.fov,\r\n angles: savedCameraState.angles,\r\n lookat: lookatVector,\r\n centerOnImage: false\r\n } as CameraLoadOptions;\r\n\r\n this.viewer.loadImage(savedcameraID, cameraLoadOptions);\r\n\r\n return true;\r\n }\r\n\r\n closestCameraToPosition(position: DataProjectionCoordinate) {\r\n const maxViewAngle = MathUtils.degToRad(45);\r\n\r\n let bestDistance = Infinity;\r\n let bestCameraID: string;\r\n\r\n for (const camera of this.cameras) {\r\n const cameraPos = camera.position.value;\r\n const distance = position.distanceTo(cameraPos);\r\n if (distance > bestDistance) continue;\r\n\r\n const angles = positionToCameraAngle(cameraPos, position);\r\n const phiAngle = Math.abs(angles[1]);\r\n if (phiAngle > maxViewAngle) continue;\r\n\r\n bestDistance = distance;\r\n bestCameraID = camera.id;\r\n }\r\n\r\n return bestCameraID;\r\n }\r\n\r\n update() {\r\n this.sceneViewController.update();\r\n }\r\n}\r\n\r\nconst multiplyRotations = (rotationA, rotationB) => {\r\n let matrixA = rotationA instanceof Euler\r\n ? new Matrix4().makeRotationFromEuler(rotationA)\r\n : rotationA;\r\n\r\n let matrixB = rotationB instanceof Euler\r\n ? new Matrix4().makeRotationFromEuler(rotationB)\r\n : rotationB;\r\n\r\n return new Matrix4().multiplyMatrices(matrixA, matrixB);\r\n};\r\n\r\nexport const directionToCameraAngle = (direction: Vector3) : [number, number] => {\r\n return positionToCameraAngle(new Vector3(), direction);\r\n};\r\n\r\nexport const positionToCameraAngle = (cameraPos: Vector3, position: Vector3) : [number, number] => {\r\n const sphere = new SphericalPosition().fromVectors(cameraPos, position);\r\n const theta = MathUtils.degToRad(sphere.theta);\r\n const phi = MathUtils.degToRad(90 - sphere.phi);\r\n\r\n return [theta, phi] as [number, number];\r\n};\r\n","export default __webpack_public_path__ + \"static/media/no-image-panoramic.91b6e7e4.png\";","import { Vector3, MathUtils, Vector2, TextureLoader } from \"three\";\r\nimport {\r\n CameraArguments,\r\n CameraFile,\r\n CameraFileArguments,\r\n CameraImage,\r\n ImagePixel\r\n} from \".\";\r\nimport { CameraData } from \"../../redux/assets-slice\";\r\nimport { getEulerInverse, SphericalPosition } from \"../projections\";\r\nimport { PanoramicImageMaterial } from \"../rendering\";\r\nimport { planeFromVectors, interpolate1D, roundDigit } from \"../utilities\";\r\nimport missingImagePath from \"../textures/misc/no-image-panoramic.png\";\r\n\r\nconst loader = new TextureLoader();\r\nconst missingTexture = loader.load(missingImagePath);\r\n\r\nexport class PanoramicImage extends CameraImage {\r\n constructor(...args: CameraArguments) {\r\n super(...args);\r\n this.missingTexture = missingTexture;\r\n this.material = new PanoramicImageMaterial();\r\n }\r\n\r\n pixelToDirection(pixel: ImagePixel) : Vector3 {\r\n if (!pixel) return null;\r\n\r\n let width = this.imageWidth;\r\n let height = this.imageHeight;\r\n\r\n let theta = -1*MathUtils.degToRad(360 * (pixel.u / width) - 180);\r\n let phi = MathUtils.degToRad(180 * (pixel.v / height));\r\n\r\n let imageDirection = new Vector3(\r\n Math.cos(theta) * Math.sin(phi),\r\n Math.sin(theta) * Math.sin(phi),\r\n Math.cos(phi)\r\n );\r\n\r\n let direction = imageDirection.clone()\r\n .applyEuler(this.rotation.euler);\r\n\r\n return direction;\r\n }\r\n\r\n directionToPixel(direction: Vector3) : ImagePixel {\r\n if (!direction) return null;\r\n\r\n const inverse = getEulerInverse(this.rotation.euler);\r\n const imageDirection = direction.clone()\r\n .applyEuler(inverse);\r\n\r\n let sphere = new SphericalPosition()\r\n .fromVectors(new Vector3(0,0,0), imageDirection);\r\n\r\n let width = this.imageWidth;\r\n let height = this.imageHeight;\r\n\r\n let u = (width*(-sphere.theta + 180)/360);\r\n let v = (height*(sphere.phi)/180);\r\n\r\n u = (u + width) % width;\r\n v = (v + height) % height;\r\n\r\n return {u, v};\r\n }\r\n\r\n directionsToPlanar(directions, planarSize=100) {\r\n // Convert directons to a flat plane based on average normal\r\n const plane = planeFromVectors(directions);\r\n let planar = directions.map(x => {\r\n let target = new Vector3();\r\n plane.projectPoint(x, target);\r\n return target;\r\n });\r\n\r\n let allX = planar.map(x => x.x);\r\n let allY = planar.map(x => x.y);\r\n\r\n let xMin = Math.min(...allX);\r\n let xMax = Math.max(...allX);\r\n let yMin = Math.min(...allY);\r\n let yMax = Math.max(...allY);\r\n\r\n planar = planar.map(point => {\r\n point.x = planarSize * (point.x - xMin) / (xMax-xMin);\r\n point.y = planarSize * (point.y - yMin) / (yMax-yMin);\r\n point.z = 0.0;\r\n return point;\r\n });\r\n\r\n return planar;\r\n }\r\n\r\n interpolatePixels(points, width, height) {\r\n let interpolated = [];\r\n\r\n // Convert pixels to angles\r\n let theta = points.map(x => MathUtils.degToRad((360 * x[0] / width) - 180));\r\n let phi = points.map(x => MathUtils.degToRad(180 * x[1] / height));\r\n\r\n // Convert angles to xyz\r\n let xyz = [];\r\n for (var i=0;i {\r\n let nextIndex = (index+1) % xyz.length;\r\n let xyz2 = xyz[nextIndex];\r\n let distance = new Vector3(...xyz1)\r\n .distanceTo(new Vector3(...xyz2));\r\n\r\n if (distance === 0) {\r\n return;\r\n }\r\n\r\n let steps = Math.ceil(distance/stepSize) + 1;\r\n let _x = interpolate1D(xyz1[0], xyz2[0], steps);\r\n let _y = interpolate1D(xyz1[1], xyz2[1], steps);\r\n let _z = interpolate1D(xyz1[2], xyz2[2], steps);\r\n\r\n let interpTemp = [];\r\n for (var i=0;i {\r\n if (index === 0) {\r\n xyzNoDups.push(current);\r\n return;\r\n }\r\n\r\n let previous = xyz[index - 1];\r\n let distance = new Vector3(...current)\r\n .distanceTo(new Vector3(...previous));\r\n\r\n if (distance !== 0) {\r\n xyzNoDups.push(current);\r\n };\r\n });\r\n xyz = [...xyzNoDups];\r\n\r\n // Convert xyz back to pixels\r\n xyz.forEach(current => {\r\n let r = new Vector2(...current).length();\r\n let _theta = MathUtils.radToDeg(Math.atan2(current[1], current[0]));\r\n let _phi = MathUtils.radToDeg(Math.atan2(r, current[2]));\r\n\r\n interpolated.push([\r\n roundDigit(width * ((_theta + 180) / 360), 4),\r\n roundDigit(height * (_phi / 180), 4)\r\n ]);\r\n });\r\n\r\n return interpolated;\r\n };\r\n}\r\n\r\nexport class PanoramicCameraFile extends CameraFile {\r\n constructor(...args: CameraFileArguments) {\r\n super(...args);\r\n }\r\n\r\n getNewCamera(data: CameraData) {\r\n return new PanoramicImage(\r\n this,\r\n data,\r\n this.cameraHandler.cameraScene,\r\n this.cameraHandler.controls.object,\r\n this.cameraHandler.controls.mouseControls\r\n );\r\n }\r\n}","export default __webpack_public_path__ + \"static/media/no-image-planar.58113df4.png\";","import { TextureLoader, Vector3 } from \"three\";\r\nimport {\r\n CameraArguments,\r\n CameraFile,\r\n CameraFileArguments,\r\n CameraImage,\r\n ImagePixel\r\n} from \".\";\r\nimport { CameraData, PlanarConfig } from \"../../redux/assets-slice\";\r\nimport { getEulerInverse } from \"../projections\";\r\nimport { PlanarImageMaterial } from \"../rendering\";\r\nimport missingImagePath from \"../textures/misc/no-image-planar.png\";\r\n\r\nconst loader = new TextureLoader();\r\nconst missingTexture = loader.load(missingImagePath);\r\n\r\nexport class PlanarImage extends CameraImage {\r\n public config: PlanarConfig;\r\n\r\n constructor(...args: CameraArguments) {\r\n super(...args);\r\n this.config = this.cameraData.config;\r\n this.missingTexture = missingTexture;\r\n this.material = new PlanarImageMaterial(this.config);\r\n }\r\n\r\n pixelToDirection(pixel: ImagePixel) : Vector3 {\r\n if (!pixel) return null;\r\n\r\n let x = -1 * (pixel.u - this.config.cx) / this.config.fx;\r\n let y = (pixel.v - this.config.cy) / this.config.fy;\r\n\r\n let xyz = new Vector3(x, y, 1.0)\r\n .normalize()\r\n .multiplyScalar(-1.0);\r\n\r\n let direction = xyz.clone()\r\n .applyEuler(this.rotation.euler);\r\n\r\n return direction;\r\n }\r\n\r\n directionToPixel(direction: Vector3) : ImagePixel {\r\n if (!direction) return null;\r\n\r\n const inverse = getEulerInverse(this.rotation.euler);\r\n\r\n const imageDirection = direction.clone()\r\n .applyEuler(inverse);\r\n\r\n const xyz = new Vector3()\r\n .copy(imageDirection)\r\n .divideScalar(imageDirection.z);\r\n\r\n const u = -xyz.x * this.config.fx + this.config.cx;\r\n const v = xyz.y * this.config.fy + this.config.cy;\r\n\r\n const padding = 50;\r\n const outOfBounds = (u < -padding)\r\n || (v < -padding)\r\n || (u > (this.config.width + padding))\r\n || (v > (this.config.height + padding));\r\n\r\n if (outOfBounds) return null;\r\n\r\n return {u, v};\r\n }\r\n}\r\n\r\nexport class PlanarCameraFile extends CameraFile {\r\n constructor(...args: CameraFileArguments) {\r\n super(...args);\r\n }\r\n\r\n getNewCamera(data: CameraData) {\r\n return new PlanarImage(\r\n this,\r\n data,\r\n this.cameraHandler.cameraScene,\r\n this.cameraHandler.controls.object,\r\n this.cameraHandler.controls.mouseControls\r\n );\r\n }\r\n}","import { Layer } from \"ol/layer\";\r\nimport { CameraFeature, CameraHandler } from \".\";\r\nimport WebGLPointsLayer from \"ol/layer/WebGLPoints\";\r\nimport VectorSource from \"ol/source/Vector\";\r\n\r\nconst minCameraRadius = 1.5;\r\nconst maxCameraRadius = 6;\r\n\r\nexport class AerialCameras {\r\n private cameraHandler: CameraHandler;\r\n public mapSource: VectorSource;\r\n private mapLayer: WebGLPointsLayer;\r\n\r\n constructor(cameraHandler: CameraHandler) {\r\n this.cameraHandler = cameraHandler;\r\n\r\n this.mapSource = new VectorSource({\r\n wrapX: false\r\n });\r\n\r\n const backgroundLayer = new WebGLPointsLayer({\r\n zIndex: 1,\r\n source: this.mapSource,\r\n style: {\r\n filter: ['>', ['get', 'visible'], 0.5],\r\n \"circle-radius\": [\r\n \"interpolate\",\r\n [\"linear\"],\r\n [\"zoom\"],\r\n 10, minCameraRadius,\r\n 18, maxCameraRadius\r\n ],\r\n \"circle-fill-color\": \"#000000\"\r\n }\r\n });\r\n\r\n const foregroundLayer = new WebGLPointsLayer({\r\n zIndex: 1,\r\n source: this.mapSource,\r\n style: {\r\n filter: ['>', ['get', 'visible'], 0.5],\r\n \"circle-radius\": [\r\n \"interpolate\",\r\n [\"linear\"],\r\n [\"zoom\"],\r\n 10, minCameraRadius - 1,\r\n 18, maxCameraRadius - 1\r\n ],\r\n \"circle-fill-color\": \"#ffffff\"\r\n }\r\n });\r\n\r\n this.mapLayer = backgroundLayer;\r\n this.map.addLayer(backgroundLayer);\r\n this.map.addLayer(foregroundLayer);\r\n }\r\n\r\n get viewer() {\r\n return this.cameraHandler.viewer;\r\n }\r\n\r\n get files() {\r\n return this.cameraHandler.files;\r\n }\r\n\r\n get map() {\r\n return this.cameraHandler.map;\r\n }\r\n\r\n getFeatureForEvent(event) {\r\n try {\r\n const features = this.map.getFeaturesAtPixel(event.pixel, {\r\n layerFilter: (layer: Layer) => layer === this.mapLayer\r\n }) as CameraFeature[];\r\n\r\n // Only return the first feature\r\n return features.slice(0,1);\r\n } catch {\r\n return [];\r\n }\r\n }\r\n}","import { PerspectiveCamera, Plane, Raycaster, Triangle, Vector3 } from \"three\";\r\nimport { eventToPixel } from \"./utilities\";\r\nimport { Viewer } from \"./main\";\r\nimport { MultiImageWindow } from \"./controls\";\r\n\r\nexport class RayCaster {\r\n private initialized = false;\r\n private width: number;\r\n private height: number;\r\n private event;\r\n private camera: PerspectiveCamera;\r\n private raycaster: Raycaster;\r\n\r\n constructor(object: MultiImageWindow | Viewer, event) {\r\n const {width, height, camera} = object;\r\n\r\n this.width = width;\r\n this.height = height;\r\n this.camera = camera;\r\n this.event = event;\r\n\r\n this.init();\r\n }\r\n\r\n get direction() {\r\n return this.ray.direction;\r\n }\r\n\r\n get position() {\r\n return this.ray.origin;\r\n }\r\n\r\n get ray() {\r\n return this.raycaster.ray;\r\n }\r\n\r\n init() {\r\n let direction = this.vectorFromEvent(this.event);\r\n let raycaster = this.defaultRaycaster(direction);\r\n this.raycaster = raycaster;\r\n }\r\n\r\n setPrecision(precision) {\r\n if (!this.initialized) {\r\n return;\r\n }\r\n\r\n this.raycaster.params = {\r\n 'Points': {threshold: precision},\r\n 'Line': {threshold: precision}\r\n };\r\n }\r\n\r\n intersectPlane(plane: Plane) {\r\n return this.ray.intersectPlane(plane, new Vector3());\r\n }\r\n\r\n intersectObject(target) {\r\n return this.raycaster.intersectObject(target);\r\n }\r\n\r\n intersectTriangle(triangle: Triangle) {\r\n return this.ray.intersectTriangle(\r\n triangle.a, triangle.b, triangle.c,\r\n false, new Vector3()\r\n );\r\n }\r\n\r\n intersectObjects(targets, opts={}) {\r\n if (!this.initialized) {\r\n return [];\r\n }\r\n\r\n let defaults = {\r\n minDistance: null,\r\n sortByRay: false,\r\n recursive: true\r\n };\r\n\r\n let options = {...defaults, ...opts};\r\n\r\n let objects = this.raycaster.intersectObjects(\r\n targets, options.recursive);\r\n\r\n if (options.minDistance) {\r\n objects = objects.filter(item => {\r\n return item.distance > options.minDistance;\r\n });\r\n }\r\n\r\n if (options.sortByRay) {\r\n objects.sort(function(a, b) {\r\n return a.distanceToRay - b.distanceToRay;\r\n });\r\n }\r\n\r\n return objects;\r\n }\r\n\r\n /** @private */\r\n vectorFromEvent(event) {\r\n let uv = eventToPixel(event);\r\n uv.x = 2 * (uv.x / this.width) - 1;\r\n uv.y = 1 - 2 * (uv.y / this.height);\r\n uv.z = 0.5;\r\n\r\n let direction = this.raycastDirection(uv);\r\n return direction;\r\n }\r\n\r\n /** @private */\r\n raycastDirection(vector: Vector3) {\r\n vector.unproject(this.camera);\r\n vector.sub(this.camera.position).normalize();\r\n return vector;\r\n }\r\n\r\n /** @private */\r\n defaultRaycaster(direction) {\r\n if (!direction) return;\r\n\r\n let raycaster = new Raycaster();\r\n let origin = this.camera.position;\r\n raycaster.set(origin, direction);\r\n this.initialized = true;\r\n\r\n return raycaster;\r\n }\r\n}\r\n","import {\r\n Line3,\r\n MathUtils,\r\n Mesh,\r\n MeshBasicMaterial,\r\n Path,\r\n Plane,\r\n Shape,\r\n ShapeGeometry,\r\n Sphere,\r\n Vector3\r\n} from \"three\";\r\nimport { CameraHandler, CameraImage } from \".\";\r\nimport { MarkerNavType } from \"../../redux/settings-slice\";\r\nimport { CustomMouseEvent } from \"../controls\";\r\nimport { RayCaster } from \"../ray-caster\";\r\nimport { toVector2 } from \"../utilities\";\r\nimport { calculateEigenVectors } from \"../projections\";\r\n\r\ninterface IntersectResponse {\r\n camera: CameraImage;\r\n intersect: Vector3;\r\n rotation: number;\r\n}\r\n\r\nexport class SceneViewCameras {\r\n public cameraHandler: CameraHandler;\r\n private arrowNavigation: ArrowNavigation;\r\n public markerNavigation: MarkerNavigation;\r\n private modifier = false;\r\n private navigationType: MarkerNavType;\r\n\r\n constructor(cameraHandler: CameraHandler) {\r\n this.cameraHandler = cameraHandler;\r\n this.markerNavigation = new MarkerNavigation(this);\r\n this.arrowNavigation = new ArrowNavigation(this);\r\n\r\n this.initEvents();\r\n }\r\n\r\n get viewer() {\r\n return this.cameraHandler.viewer;\r\n }\r\n\r\n get files() {\r\n return this.cameraHandler.files;\r\n }\r\n\r\n get scene() {\r\n return this.cameraHandler.markerScene;\r\n }\r\n\r\n get renderInFront() {\r\n return this.viewer.orbitState || this.arrowNavigation.visible;\r\n }\r\n\r\n get markersVisible() {\r\n return this.markerNavigation.visible;\r\n }\r\n\r\n initEvents() {\r\n this.onKeyUp = this.onKeyUp.bind(this);\r\n this.onKeyDown = this.onKeyDown.bind(this);\r\n\r\n window.addEventListener( 'keydown', this.onKeyDown, false);\r\n window.addEventListener( 'keyup', this.onKeyUp, false);\r\n }\r\n\r\n removeEvents() {\r\n window.removeEventListener('keydown', this.onKeyDown, false);\r\n window.removeEventListener('keyup', this.onKeyUp, false);\r\n }\r\n\r\n onKeyUp(event) {\r\n if (event.key === \"Control\") {\r\n this.modifier = false;\r\n }\r\n }\r\n\r\n onKeyDown(event) {\r\n if (event.key === \"Control\") {\r\n this.modifier = true;\r\n }\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n if (event.mouseMoved) return false;\r\n if (!event.isLeftClick) return false;\r\n\r\n const camera = this.markerNavigation.onMouseUp(event)\r\n || this.arrowNavigation.onMouseUp(event);\r\n\r\n if (camera) {\r\n this.viewer.loadImage(camera.id);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n if (event.mouseMoved) return;\r\n this.arrowNavigation.onMouseMove(event);\r\n this.markerNavigation.onMouseMove(event);\r\n }\r\n\r\n setNavigationType(type: MarkerNavType) {\r\n this.navigationType = type;\r\n this.markerNavigation.updatePicker();\r\n this.clearArrowNavigation();\r\n }\r\n\r\n updateArrowNavigation() {\r\n this.arrowNavigation.updateNavigation();\r\n }\r\n\r\n clearArrowNavigation() {\r\n this.arrowNavigation.clearNavigation();\r\n }\r\n\r\n updateVisibility() {\r\n const isOrbitMode = this.viewer.orbitState;\r\n const isHidden = this.navigationType === MarkerNavType.None;\r\n const isArrowMode = this.navigationType === MarkerNavType.Arrows;\r\n const isMarkerMode = this.navigationType === MarkerNavType.Markers;\r\n\r\n if (isHidden) {\r\n this.markerNavigation.setVisible(false);\r\n this.arrowNavigation.setVisible(false);\r\n } else if (isMarkerMode || isOrbitMode || this.modifier) {\r\n this.markerNavigation.setVisible(true);\r\n this.arrowNavigation.setVisible(false);\r\n } else if (isArrowMode) {\r\n this.markerNavigation.setVisible(false);\r\n this.arrowNavigation.setVisible(true);\r\n }\r\n\r\n this.markerNavigation.setEnabled(isArrowMode || isMarkerMode);\r\n this.arrowNavigation.setEnabled(isArrowMode);\r\n }\r\n\r\n update() {\r\n this.updateVisibility();\r\n this.files.forEach(file => file.update());\r\n this.arrowNavigation.update();\r\n }\r\n}\r\n\r\nclass MarkerNavigation {\r\n private sceneViewController: SceneViewCameras;\r\n private selected: CameraImage;\r\n public enabled = false;\r\n public visible = false;\r\n\r\n constructor(sceneViewCameras: SceneViewCameras) {\r\n this.sceneViewController = sceneViewCameras;\r\n }\r\n\r\n get files() {\r\n return this.sceneViewController.files;\r\n }\r\n\r\n get viewer() {\r\n return this.sceneViewController.viewer;\r\n }\r\n\r\n get picker() {\r\n return this.viewer.gpuPickers.markers;\r\n }\r\n\r\n get cameraHeight() {\r\n const handler = this.sceneViewController.cameraHandler;\r\n return handler.cameraHeight;\r\n }\r\n\r\n updatePicker() {\r\n this.picker.needsUpdate = true;\r\n }\r\n\r\n getPickerResults(event: CustomMouseEvent): CameraImage {\r\n try {\r\n this.picker.update();\r\n\r\n const pickerID = this.picker.value(event);\r\n if (pickerID === null) return null;\r\n\r\n for (let file of this.files) {\r\n const camera = file.getByPickerID(pickerID);\r\n if (camera) return camera;\r\n }\r\n } catch (e) {\r\n console.log(\"Prevented framebuffer exception: \");\r\n console.log(e);\r\n return null;\r\n }\r\n }\r\n\r\n /** @private */\r\n markCameraSelected(camera: CameraImage) {\r\n for (let file of this.files) {\r\n file.setSelected(camera);\r\n }\r\n\r\n if (this.selected !== camera) {\r\n this.updatePicker();\r\n }\r\n\r\n this.selected = camera;\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): CameraImage {\r\n if (!this.visible) return;\r\n\r\n return this.getPickerResults(event);\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n if (!this.visible) return;\r\n\r\n const camera = this.getPickerResults(event);\r\n this.markCameraSelected(camera);\r\n }\r\n\r\n setEnabled(state: boolean) {\r\n this.enabled = state;\r\n }\r\n\r\n setVisible(state: boolean) {\r\n if (this.visible === state) return;\r\n\r\n this.visible = state;\r\n this.updatePicker();\r\n }\r\n}\r\n\r\nclass ArrowNavigation {\r\n private sceneViewController: SceneViewCameras;\r\n private nearbyCameras: CameraImage[] = [];\r\n private cameraPlane: Plane = null;\r\n\r\n private cameraObject: Mesh;\r\n private cursorObject: Mesh;\r\n\r\n public enabled = false;\r\n public visible = false;\r\n private needsUpdate = false;\r\n private calculating = false;\r\n private minCameraDistance = 1.0;\r\n private maxCameraDistance = 40.0;\r\n\r\n constructor(sceneViewCameras: SceneViewCameras) {\r\n this.sceneViewController = sceneViewCameras;\r\n\r\n this.createCameraObject();\r\n this.createCursorObject();\r\n this.setObjectsVisible(false);\r\n this.clearNavigation();\r\n }\r\n\r\n get files() {\r\n return this.sceneViewController.files;\r\n }\r\n\r\n get viewer() {\r\n return this.sceneViewController.viewer;\r\n }\r\n\r\n get scene() {\r\n return this.sceneViewController.scene;\r\n }\r\n\r\n get cameraHeight() {\r\n return this.sceneViewController.cameraHandler.cameraHeight;\r\n }\r\n\r\n /** @private */\r\n createCameraObject() {\r\n const shape = new Shape();\r\n shape.moveTo( 0.60, 0.60 );\r\n shape.lineTo( 1.00, 0.60 );\r\n shape.lineTo( 1.00, 0.40 );\r\n shape.lineTo( 0.60, 0.40 );\r\n shape.lineTo( 0.60, 0.00 );\r\n shape.lineTo( 0.40, 0.00 );\r\n shape.lineTo( 0.40, 0.40 );\r\n shape.lineTo( 0.00, 0.40 );\r\n shape.lineTo( 0.00, 0.60 );\r\n shape.lineTo( 0.40, 0.60 );\r\n shape.lineTo( 0.40, 1.00 );\r\n shape.lineTo( 0.60, 1.00 );\r\n shape.lineTo( 0.60, 0.60 );\r\n\r\n const geometry = new ShapeGeometry(shape);\r\n const material = new MeshBasicMaterial({\r\n color: 0xFFFFFF,\r\n opacity: 0.8,\r\n transparent: true\r\n });\r\n\r\n this.cameraObject = new Mesh(geometry, material);\r\n this.cameraObject.geometry.center();\r\n this.scene.add(this.cameraObject);\r\n }\r\n\r\n /** @private */\r\n createCursorObject() {\r\n const shape = new Shape();\r\n shape.moveTo( 0.00, 1.00 );\r\n shape.absarc( 0.50, 0.50, 0.50, 0, Math.PI * 2, false );\r\n\r\n const hole = new Path();\r\n hole.moveTo( 0.15, 0.70 );\r\n hole.lineTo( 0.50, 0.70 );\r\n hole.lineTo( 0.50, 0.80 );\r\n hole.lineTo( 0.85, 0.51 );\r\n hole.lineTo( 0.85, 0.49 );\r\n hole.lineTo( 0.50, 0.20 );\r\n hole.lineTo( 0.50, 0.30 );\r\n hole.lineTo( 0.15, 0.30 );\r\n hole.lineTo( 0.15, 0.70 );\r\n\r\n shape.holes.push(hole);\r\n\r\n const geometry = new ShapeGeometry(shape);\r\n const material = new MeshBasicMaterial({\r\n color: 0xEAEAEA\r\n });\r\n\r\n this.cursorObject = new Mesh(geometry, material);\r\n this.cursorObject.geometry.center();\r\n this.scene.add(this.cursorObject);\r\n }\r\n\r\n onMouseMove(event) {\r\n if (!this.visible) return;\r\n\r\n const {camera, intersect, rotation} = this.getBestCamera(event);\r\n if (!camera) {\r\n this.setObjectsVisible(false);\r\n return;\r\n }\r\n\r\n this.setObjectsVisible(true);\r\n\r\n const position = camera.position.scene;\r\n const cameraPosition = new Vector3(\r\n position.x,\r\n position.y,\r\n position.z - this.cameraHeight\r\n );\r\n\r\n if (intersect) {\r\n this.cursorObject.position.copy(intersect);\r\n this.cursorObject.rotation.z = rotation;\r\n } else {\r\n this.cursorObject.visible = false;\r\n }\r\n\r\n this.cameraObject.position.copy(cameraPosition);\r\n this.cameraObject.position.z -= 0.25;\r\n this.cameraObject.rotation.z = rotation + MathUtils.degToRad(45);\r\n }\r\n\r\n onMouseUp(event) {\r\n if (!this.visible) return;\r\n\r\n const {camera} = this.getBestCamera(event);\r\n return camera;\r\n }\r\n\r\n getBestCamera(event: CustomMouseEvent): IntersectResponse {\r\n const defaultResponse = {\r\n camera: null,\r\n intersect: null,\r\n rotation: 0\r\n };\r\n\r\n return this.getCameraFromPlane(event)\r\n || this.getCameraFromDirection(event)\r\n || defaultResponse;\r\n }\r\n\r\n /** @private */\r\n getCameraFromDirection(event: CustomMouseEvent): IntersectResponse {\r\n let closestCamera: CameraImage;\r\n\r\n const raycaster = new RayCaster(this.viewer, event);\r\n\r\n const start = raycaster.position;\r\n const end = new Vector3()\r\n .copy(raycaster.position)\r\n .add(raycaster.direction);\r\n\r\n const line = new Line3(start, end);\r\n const nextCamera = this.viewer.getNextCamera();\r\n const previousCamera = this.viewer.getPreviousCamera();\r\n if (!nextCamera || !previousCamera) return;\r\n\r\n const P0 = line.closestPointToPointParameter(\r\n nextCamera.position.scene);\r\n\r\n const P1 = line.closestPointToPointParameter(\r\n previousCamera.position.scene);\r\n\r\n if (P0 > 0) {\r\n closestCamera = nextCamera;\r\n } else if (P1 > 0) {\r\n closestCamera = previousCamera;\r\n } else {\r\n return;\r\n }\r\n\r\n const rotation = getRotation(closestCamera, raycaster);\r\n\r\n return {\r\n camera: closestCamera,\r\n intersect: null,\r\n rotation: rotation\r\n };\r\n }\r\n\r\n /** @private */\r\n getCameraFromPlane(event: CustomMouseEvent): IntersectResponse {\r\n if (this.nearbyCameras.length === 0) return;\r\n\r\n const raycaster = new RayCaster(this.viewer, event);\r\n const intersection = raycaster.intersectPlane(this.cameraPlane);\r\n const frustum = this.viewer.getCameraFrustum();\r\n if (!intersection) return;\r\n\r\n const intersect2D = toVector2(intersection);\r\n\r\n let closestCamera: CameraImage = null;\r\n let closestDistance: number = Infinity;\r\n\r\n // Determine which cameras are visible in the view frustum\r\n const visibleCameras = this.nearbyCameras.filter(camera => {\r\n const position = camera.position.scene;\r\n const spherePosition = new Vector3(\r\n position.x,\r\n position.y,\r\n position.z - this.cameraHeight\r\n );\r\n\r\n const sphere = new Sphere(spherePosition, 0.5);\r\n return frustum.intersectsSphere(sphere);\r\n });\r\n\r\n if (visibleCameras.length === 0) return;\r\n\r\n // Grab the camera closest to our intersection point\r\n for (let camera of visibleCameras) {\r\n const position = camera.position.scene;\r\n const position2D = toVector2(position);\r\n const distance = position2D.distanceTo(intersect2D);\r\n if (distance >= closestDistance) continue;\r\n\r\n closestDistance = distance;\r\n closestCamera = camera;\r\n }\r\n\r\n const rotation = getRotation(closestCamera, raycaster);\r\n\r\n return {\r\n camera: closestCamera,\r\n intersect: intersection,\r\n rotation: rotation\r\n };\r\n }\r\n\r\n setEnabled(state: boolean) {\r\n this.enabled = state;\r\n }\r\n\r\n setVisible(state:boolean) {\r\n if (this.visible === state) return;\r\n\r\n this.visible = state;\r\n this.clearNavigation();\r\n }\r\n\r\n setObjectsVisible(visible: boolean) {\r\n if (this.cursorObject) {\r\n this.cursorObject.visible = visible;\r\n }\r\n\r\n if (this.cameraObject) {\r\n this.cameraObject.visible = visible;\r\n }\r\n }\r\n\r\n updateNavigation() {\r\n this.needsUpdate = true;\r\n this.clearNavigation();\r\n }\r\n\r\n clearNavigation() {\r\n this.setObjectsVisible(false);\r\n }\r\n\r\n calculateClosestCameras() {\r\n this.calculating = true;\r\n\r\n this.calculateNearbyCameras();\r\n this.calculateCameraPlane();\r\n\r\n this.calculating = false;\r\n this.needsUpdate = false;\r\n }\r\n\r\n /** @private */\r\n calculateNearbyCameras() {\r\n const camera = this.viewer.camera;\r\n const cameraPosition = camera.position;\r\n\r\n this.nearbyCameras = [];\r\n\r\n for (let file of this.files) {\r\n if (!file.visible) continue;\r\n\r\n file.cameras.forEach(camera => {\r\n const position = camera.position.scene;\r\n\r\n const dX = position.x - cameraPosition.x;\r\n if (dX > this.maxCameraDistance) return;\r\n\r\n const dY = position.y - cameraPosition.y;\r\n if (dY > this.maxCameraDistance) return;\r\n\r\n const distance = Math.sqrt(dX*dX + dY*dY);\r\n\r\n // Calculate min and max distance from camera;\r\n let tooClose = distance < this.minCameraDistance;\r\n let tooFar = distance > this.maxCameraDistance;\r\n if (tooClose || tooFar) return;\r\n\r\n this.nearbyCameras.push(camera);\r\n });\r\n }\r\n }\r\n\r\n /** @private */\r\n calculateCameraPlane() {\r\n const camera = this.viewer.camera;\r\n const cameraPosition = camera.position;\r\n\r\n if (this.nearbyCameras.length === 0) return;\r\n\r\n const points = this.nearbyCameras.map(camera => {\r\n // A small offset will create a more consistent plane in certain\r\n // situations (ex: perfectly straight line of points)\r\n const dx = Math.random()*0.5;\r\n const dy = Math.random()*0.5;\r\n const offset = new Vector3(dx, dy, 0);\r\n\r\n return new Vector3()\r\n .copy(camera.position.scene)\r\n .add(offset);\r\n });\r\n\r\n const {eigen} = calculateEigenVectors(points);\r\n\r\n let normal = new Vector3();\r\n let minAngle = Infinity;\r\n\r\n // Use the eigenvector that is closest to [0,0,1]\r\n // (regardless if it is the smallest eigenvalue)\r\n eigen.forEach(values => {\r\n const {vector} = values;\r\n if (vector.z < 0) {\r\n vector.multiplyScalar(-1);\r\n }\r\n\r\n const vertical = new Vector3(0,0,1);\r\n const angle = vector.angleTo(vertical);\r\n if (angle > minAngle) return;\r\n\r\n minAngle = angle;\r\n normal = vector;\r\n });\r\n\r\n const height = Math.max(1.0, this.cameraHeight);\r\n const point = new Vector3()\r\n .copy(cameraPosition)\r\n .sub(new Vector3(0, 0, height));\r\n\r\n this.cameraPlane = new Plane()\r\n .setFromNormalAndCoplanarPoint(normal, point);\r\n }\r\n\r\n update() {\r\n if (this.needsUpdate && !this.calculating) {\r\n this.calculateClosestCameras();\r\n }\r\n }\r\n}\r\n\r\nconst getRotation = (camera: CameraImage, raycaster: RayCaster) => {\r\n const position = new Vector3()\r\n .copy(camera.position.scene)\r\n .sub(raycaster.position);\r\n\r\n const position2D = toVector2(position);\r\n\r\n return position2D.angle();\r\n};\r\n","import React, { useEffect, useState } from \"react\";\r\nimport { sendCustomEvent } from \"../events\";\r\nimport {\r\n TagCreateDialog,\r\n TagDeleteDialog\r\n} from \"../folder\";\r\nimport { isStaticSite } from \"../electron-modules\";\r\nimport { DialogContent, Typography } from \"@mui/material\";\r\nimport {\r\n DenseIcon,\r\n DenseMenu,\r\n DraggableDialog,\r\n LabelCategoryDialog,\r\n EnhancedTable,\r\n MenuDivider\r\n} from \"../components\";\r\nimport MenuItem from '@mui/material/MenuItem';\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useAuth, useContextMenu, useDialog, useViewer } from \"../hooks\";\r\nimport DeleteIcon from '@mui/icons-material/Delete';\r\nimport InfoIcon from '@mui/icons-material/Info';\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport RoomIcon from \"@mui/icons-material/Room\";\r\nimport ClearIcon from '@mui/icons-material/Clear';\r\nimport ZoomInIcon from '@mui/icons-material/ZoomIn';\r\nimport RotateLeftIcon from '@mui/icons-material/RotateLeft';\r\nimport ToggleOnIcon from '@mui/icons-material/ToggleOn';\r\nimport ToggleOffIcon from '@mui/icons-material/ToggleOff';\r\nimport TrendingUpIcon from '@mui/icons-material/TrendingUp';\r\nimport TrendingDownIcon from '@mui/icons-material/TrendingDown';\r\nimport SearchIcon from '@mui/icons-material/Search';\r\nimport SyncIcon from '@mui/icons-material/Sync';\r\nimport AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';\r\nimport LinkIcon from '@mui/icons-material/Link';\r\nimport CompareArrowsIcon from '@mui/icons-material/CompareArrows';\r\nimport { useDispatch, useSelector } from \"react-redux\";\r\nimport { CustomURL, selectAllCustomLinks } from \"../redux/custom-links-slice\";\r\nimport { openExternalLink } from \"../urls\";\r\nimport { toast } from \"../app\";\r\nimport { updateTag } from \"../redux/assets-slice\";\r\nimport { useTableState } from \"../hooks/use-table-state\";\r\nimport copyTextToClipboard from \"copy-to-clipboard\";\r\n\r\nexport interface LabelContextData {\r\n labelID: number;\r\n pointID: number;\r\n coordinate: number[] | object;\r\n}\r\n\r\nexport interface ContextData {\r\n isAerial?: boolean;\r\n sceneCoord?: number[];\r\n aerialCoord?: number[];\r\n labelData?: LabelContextData;\r\n selectedTags?: string[];\r\n modelData?: object[];\r\n}\r\n\r\ninterface ContextMenuItem {\r\n text: string;\r\n icon: React.ReactNode;\r\n seperator?: boolean;\r\n disabled?: boolean;\r\n visible?: boolean;\r\n callback: () => void;\r\n}\r\n\r\ninterface ContextMenuProps {\r\n clearTooltipText: () => void;\r\n}\r\n\r\nexport const ContextMenu = (props: ContextMenuProps) => {\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n\r\n const contextMenu = useContextMenu();\r\n const newTagDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const changeCategoryDialog = useDialog();\r\n const customLinks = useSelector(selectAllCustomLinks);\r\n const {permissions} = useAuth();\r\n\r\n const [modelProperties, setModelProperties] = useState(null);\r\n const [tagCoordinate, setTagCoordinate] = useState([]);\r\n\r\n const {event, contextData={}} = contextMenu.data;\r\n\r\n const {isAerial=false, labelData, selectedTags, modelData,\r\n sceneCoord, aerialCoord} = contextData as ContextData;\r\n\r\n const multipleCategories = ((viewer?.getAllCategories().length) > 1);\r\n\r\n const onClose = () => {\r\n contextMenu.handleClose();\r\n viewer?.clearHighlightedLinework();\r\n };\r\n\r\n const onEnter = () => {\r\n props.clearTooltipText();\r\n };\r\n\r\n const listItemSeperator = (visible) => {\r\n return {\r\n text: \"\",\r\n seperator: true,\r\n visible\r\n };\r\n };\r\n\r\n const constructCustomURL = (customURL: CustomURL, sceneCoord, aerialCoord) => {\r\n let urlString = customURL.url;\r\n\r\n let position = isAerial\r\n ? aerialCoord\r\n : sceneCoord;\r\n\r\n if (position.length === 2) {\r\n // Add placeholder height to aerial coordinates\r\n position.push(0);\r\n }\r\n\r\n urlString = urlString\r\n .replaceAll('{x}', position[0].toFixed(3))\r\n .replaceAll('{y}', position[1].toFixed(3))\r\n .replaceAll('{z}', position[2].toFixed(3));\r\n\r\n const target = customURL.target;\r\n openExternalLink(urlString, {target});\r\n };\r\n\r\n const getMenuItems = () => {\r\n if (!viewer || !contextMenu.open) {\r\n return [] as ContextMenuItem[];\r\n }\r\n\r\n let numLabelsSelected = viewer.numLabelsHighlighted();\r\n let profileActive = viewer.pointProfileActive();\r\n const currentCamera = viewer.getCurrentCamera();\r\n\r\n const labelSelected = labelData\r\n ? labelData.labelID !== null\r\n : false;\r\n\r\n const labelPointSelected = labelData\r\n ? labelData.pointID !== null\r\n : false;\r\n\r\n const hasLabelCoord = labelData\r\n ? labelData.coordinate !== null\r\n : false;\r\n\r\n const numTagsSelected = selectedTags\r\n ? selectedTags.length\r\n : 0;\r\n\r\n const hasModelData = modelData\r\n ? modelData.length > 0\r\n : false;\r\n\r\n const enableChangeCategory = multipleCategories && (numLabelsSelected > 0);\r\n\r\n const hasSceneCoord = !!sceneCoord;\r\n const hasAerialCoord = !!aerialCoord;\r\n\r\n const noTagSelected = numTagsSelected === 0;\r\n const oneTagSelected = numTagsSelected === 1;\r\n\r\n const pointProfileActions = [\r\n {\r\n text: t(\"context-menu.profile\"),\r\n icon: ,\r\n disabled: !hasSceneCoord,\r\n visible: !isAerial && !profileActive,\r\n callback: () => {\r\n viewer.pointProfileStart(sceneCoord);\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.profile-end\"),\r\n icon: ,\r\n disabled: !hasSceneCoord,\r\n visible: !isAerial && profileActive,\r\n callback: () => {\r\n viewer.pointProfileEnd();\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.profile-cancel\"),\r\n icon: ,\r\n visible: !isAerial && profileActive,\r\n callback: () => {\r\n viewer.pointProfileCancel();\r\n }\r\n },\r\n ] as ContextMenuItem[];\r\n\r\n const tagActions = [\r\n {\r\n text: t(\"context-menu.new-tag\"),\r\n icon: ,\r\n visible: permissions.create\r\n && (hasSceneCoord || hasAerialCoord)\r\n && noTagSelected,\r\n callback: () => {\r\n setTagCoordinate(sceneCoord || aerialCoord);\r\n newTagDialog.handleOpen();\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.new-tag\"),\r\n icon: ,\r\n visible: permissions.create\r\n && viewer.isImageOnly\r\n && !hasSceneCoord\r\n && !hasAerialCoord\r\n && noTagSelected,\r\n callback: async () => {\r\n const coordinate = await viewer.getMultiImageCoordinate(event);\r\n if (!coordinate) return;\r\n\r\n const tagCoordinate = coordinate\r\n .toDataProjection()\r\n .toArray();\r\n\r\n setTagCoordinate(tagCoordinate);\r\n newTagDialog.handleOpen();\r\n }\r\n },\r\n {\r\n text: t('tags.move_to_tag'),\r\n icon: ,\r\n visible: isAerial && oneTagSelected,\r\n callback: () => {\r\n // Jump to nearest camera position\r\n viewer.jumpToTag(selectedTags[0]);\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.copy-tag\"),\r\n icon: ,\r\n visible: isStaticSite && oneTagSelected,\r\n callback: () => {\r\n // Copy url to clipboard\r\n const url = new URL(window.location as any);\r\n url.hash = `tag=${selectedTags[0]}`;\r\n copyTextToClipboard(url.href);\r\n toast.success(t(\"toast.copied-to-clipboard\"));\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.update-tag-view\"),\r\n icon: ,\r\n visible: permissions.edit && oneTagSelected,\r\n callback: () => {\r\n dispatch(updateTag({\r\n tagID: selectedTags[0],\r\n sceneState: viewer.sceneState\r\n }));\r\n\r\n toast.success(t(\"toast.updated-tag-view\"));\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.delete-tags\", {\r\n count: numTagsSelected\r\n }),\r\n icon: ,\r\n visible: permissions.delete && !noTagSelected,\r\n callback: () => {\r\n deleteDialog.handleOpen(selectedTags);\r\n }\r\n }\r\n ] as ContextMenuItem[];\r\n\r\n const orbitModeActions = [\r\n {\r\n text: t(\"context-menu.disable-3d-mode\"),\r\n icon: ,\r\n visible: !isAerial && viewer.orbitState,\r\n disabled: !currentCamera,\r\n callback: () => {\r\n viewer.loadImage(currentCamera.id);\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.enable-3d-mode\"),\r\n icon: ,\r\n visible: !isAerial && !viewer.orbitState,\r\n callback: () => {\r\n viewer.setOrbitValues(true);\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.reset-3d-mode\"),\r\n icon: ,\r\n disabled: !viewer.orbitState,\r\n visible: !isAerial,\r\n callback: () => {\r\n viewer.resetCamera();\r\n }\r\n },\r\n ] as ContextMenuItem[];\r\n\r\n const modelActions = [\r\n {\r\n text: t(\"context-menu.model-properties\"),\r\n icon: ,\r\n visible: hasModelData,\r\n callback: () => {\r\n setModelProperties(modelData);\r\n }\r\n }\r\n ] as ContextMenuItem[];\r\n\r\n const labelActions = [\r\n {\r\n text: t(\"context-menu.delete-label\", {\r\n count: numLabelsSelected\r\n }),\r\n icon: ,\r\n disabled: viewer.anyLabelSelected(),\r\n callback: () => {\r\n viewer.deleteHighlighted();\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.delete-point\"),\r\n icon: ,\r\n disabled: !labelPointSelected,\r\n callback: () => {\r\n viewer.deleteLabelPoint(labelData.pointID);\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.unselect-label\", {\r\n count: numLabelsSelected\r\n }),\r\n icon: ,\r\n disabled: viewer.anyLabelSelected(),\r\n callback: () => {\r\n viewer.unHighlightAll();\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.insert-point\"),\r\n icon: ,\r\n disabled: !hasLabelCoord || labelPointSelected,\r\n callback: () => {\r\n viewer.insertLabelPoint(\r\n labelData.labelID,\r\n labelData.coordinate\r\n );\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.edit-point\"),\r\n icon: ,\r\n disabled: !hasLabelCoord || labelPointSelected,\r\n callback: () => {\r\n viewer.editLabel(\r\n labelData.labelID,\r\n labelData.coordinate\r\n );\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.find-in-list\"),\r\n icon: ,\r\n disabled: !labelSelected,\r\n callback: () => {\r\n viewer.moveToLabel(labelData.labelID);\r\n }\r\n },\r\n {\r\n text: t(\"context-menu.change-category\"),\r\n icon: ,\r\n disabled: !enableChangeCategory,\r\n callback: () => {\r\n changeCategoryDialog.handleOpen();\r\n }\r\n },\r\n ] as ContextMenuItem[];\r\n\r\n const customUserActions = customLinks\r\n .filter(values => {\r\n return isAerial\r\n ? values.showInAerial\r\n : values.showInScene;\r\n })\r\n .map(values => {\r\n return {\r\n text: values.name,\r\n icon: ,\r\n disabled: !hasSceneCoord && !hasAerialCoord,\r\n callback: () => {\r\n constructCustomURL(values, sceneCoord, aerialCoord);\r\n }\r\n };\r\n }) as ContextMenuItem[];\r\n\r\n if (numLabelsSelected > 0) {\r\n // Labels are selected\r\n return [...labelActions];\r\n }\r\n\r\n const hasCustom = customUserActions.length > 0;\r\n\r\n return [\r\n ...tagActions,\r\n listItemSeperator(hasModelData),\r\n ...modelActions,\r\n listItemSeperator(!isAerial),\r\n ...orbitModeActions,\r\n listItemSeperator(!isAerial),\r\n ...pointProfileActions,\r\n listItemSeperator(hasCustom),\r\n ...customUserActions\r\n ] as ContextMenuItem[];\r\n };\r\n\r\n /** Context menu event listener */\r\n useEffect(() => {\r\n const callback = (menuEvent) => {\r\n const {event} = menuEvent.detail;\r\n contextMenu.handleOpen(event, menuEvent.detail);\r\n };\r\n\r\n document.addEventListener(\"context-menu\", callback);\r\n\r\n return () => {\r\n document.removeEventListener(\"context-menu\", callback);\r\n };\r\n }, []);\r\n\r\n let options = getMenuItems();\r\n\r\n options = options.filter(item => {\r\n return item.hasOwnProperty(\"visible\")\r\n ? item.visible\r\n : true;\r\n });\r\n\r\n // Make sure a seperator isn't the first element\r\n if ((options.length > 0) && options[0].seperator) {\r\n options = options.slice(1);\r\n }\r\n\r\n return (\r\n \r\n 0}\r\n onClose={onClose}\r\n onEnter={onEnter}\r\n anchorPosition={contextMenu.anchorPosition}\r\n >\r\n {options.map((option) => {\r\n if (option.seperator) {\r\n return ;\r\n }\r\n\r\n return (\r\n {\r\n onClose();\r\n option.callback();\r\n }}\r\n >\r\n {option.icon\r\n ? option.icon\r\n : \r\n }\r\n\r\n \r\n {option.text}\r\n \r\n\r\n \r\n );\r\n })}\r\n \r\n\r\n {/* New Tag Dialog */}\r\n \r\n\r\n {/* Delete Tag Dialog */}\r\n \r\n\r\n \r\n\r\n {/* Change Category Dialog */}\r\n \r\n\r\n \r\n );\r\n};\r\n\r\n\r\n\r\ninterface ModelPropertiesProps {\r\n data: any[]\r\n setData: (data) => void;\r\n}\r\n\r\nconst ModelProperties = (props: ModelPropertiesProps) => {\r\n const {data, setData} = props;\r\n\r\n const {t} = useTranslation();\r\n const tableState = useTableState();\r\n\r\n const open = data ? data.length > 0 : false;\r\n\r\n const onClose = () => {\r\n setData(null);\r\n };\r\n\r\n const getRows = () => {\r\n if (!data) return [];\r\n\r\n return data.map((property, index) => {\r\n return {\r\n id: `PropertyTableRow_${index}`,\r\n ...property\r\n };\r\n });\r\n };\r\n\r\n const columns = [\r\n {\r\n id: 'property',\r\n label: t(\"model-properties.property\")\r\n },\r\n {\r\n id: 'value',\r\n label: t(\"model-properties.value\"),\r\n wordBreak: true\r\n }\r\n ];\r\n\r\n const rows = getRows();\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const showContextMenu = (event, contextData = {} as ContextData) => {\r\n event.preventDefault();\r\n sendCustomEvent(\"context-menu\", {event, contextData});\r\n};","import React, { useEffect, useState } from \"react\";\r\nimport { Card, CardHeader, Grid, IconButton, List, Theme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useDispatch, useSelector } from \"react-redux\";\r\nimport slash from \"slash\";\r\nimport {\r\n ArrowTooltip,\r\n CheckboxWithLabel,\r\n DenseDivider,\r\n DraggableDialog,\r\n IconToolBar,\r\n InputWithLabel,\r\n PromptDialog,\r\n SimpleDialog,\r\n SlimScrollbar,\r\n ToolBarButton\r\n} from \"../components\";\r\nimport { dialog, fs } from \"../electron-modules\";\r\nimport { customURLFilter } from \"../file-extensions\";\r\nimport { useDialog, useUniqueProjectID } from \"../hooks\";\r\nimport {\r\n createCustomLink,\r\n updateCustomLink,\r\n CustomURL,\r\n selectAllCustomLinks,\r\n deleteCustomLink\r\n} from \"../redux/custom-links-slice\";\r\nimport DeleteIcon from '@mui/icons-material/Delete';\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport GetAppIcon from '@mui/icons-material/GetApp';\r\nimport { toast } from \"../app\";\r\nimport CardContent from \"@mui/material/CardContent\";\r\nimport Typography from \"@mui/material/Typography\";\r\nimport { toLocaleString } from \"../utilities\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n card: {\r\n margin: theme.spacing(2),\r\n marginTop: theme.spacing(0),\r\n padding: theme.spacing(1),\r\n userSelect: \"none\"\r\n },\r\n cardHeader: {\r\n padding: theme.spacing(1)\r\n },\r\n cardButtons: {\r\n marginTop: 0,\r\n alignSelf: \"center\"\r\n },\r\n headerTitle: {\r\n fontWeight: \"bold\",\r\n cursor: \"pointer\"\r\n },\r\n cardContent: {\r\n margin: theme.spacing(1,2),\r\n padding: theme.spacing(0),\r\n paddingBottom: \"0px !important\",\r\n wordBreak: \"break-all\"\r\n }\r\n })\r\n);\r\n\r\ninterface EditLinkDialogProps {\r\n open: boolean;\r\n onClose: () => void;\r\n values: CustomURL;\r\n}\r\n\r\nconst EditLinkDialog = (props: EditLinkDialogProps) => {\r\n const {open, onClose, values} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n\r\n const [name, setName] = useState(\"\");\r\n const [url, setUrl] = useState(\"\");\r\n const [target, setTarget] = useState(\"\");\r\n const [showInScene, setShowInScene] = useState(false);\r\n const [showInAerial, setShowInAerial] = useState(false);\r\n\r\n const addNewLink = !values;\r\n\r\n const handleSubmit = () => {\r\n onClose();\r\n\r\n if (addNewLink) {\r\n dispatch(createCustomLink({\r\n name,\r\n url,\r\n target,\r\n showInScene,\r\n showInAerial\r\n }));\r\n } else {\r\n dispatch(updateCustomLink({\r\n linkID: values.id,\r\n name,\r\n url,\r\n target,\r\n showInScene,\r\n showInAerial\r\n }));\r\n\r\n toast.success(t('toast.updated_custom_url'));\r\n }\r\n };\r\n\r\n const resetDefaults = () => {\r\n setName(\"\");\r\n setUrl(\"\");\r\n setTarget(\"\");\r\n setShowInScene(false);\r\n setShowInAerial(false);\r\n };\r\n\r\n const loadCustomValues = () => {\r\n setName(values.name);\r\n setUrl(values.url);\r\n setTarget(values.target);\r\n setShowInScene(values.showInScene);\r\n setShowInAerial(values.showInAerial);\r\n };\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n\r\n if (addNewLink) {\r\n resetDefaults();\r\n } else {\r\n loadCustomValues();\r\n }\r\n }, [open]);\r\n\r\n const canSubmit = (name !== \"\")\r\n && (url !== \"\")\r\n && (target !== \"\");\r\n\r\n return (\r\n \r\n \r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n {t('custom-link.the_url_supports_the_following_special_values')}\r\n
    \r\n
  • {t('custom-link.the_current_x_coordinate')}
  • \r\n
  • {t('custom-link.the_current_y_coordinate')}
  • \r\n
  • {t('custom-link.the_current_z_coordinate')}
  • \r\n
\r\n }\r\n value={url}\r\n onChange={setUrl}\r\n />\r\n
\r\n\r\n \r\n \r\n \r\n\r\n {/** Display in scene view */}\r\n \r\n \r\n \r\n\r\n {/** Display in aerial view */}\r\n \r\n \r\n \r\n\r\n
\r\n \r\n );\r\n};\r\n\r\ninterface CustomLinkProps {\r\n values: CustomURL;\r\n}\r\n\r\nconst CustomLink = (props: CustomLinkProps) => {\r\n const {values} = props;\r\n\r\n const classes = useStyles();\r\n const {i18n, t} = useTranslation();\r\n const dispatch = useDispatch();\r\n const editDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n\r\n const dateString = toLocaleString(values.date, i18n.language);\r\n\r\n const handleEdit = () => {\r\n editDialog.handleOpen(values);\r\n };\r\n\r\n const handleDownload = async () => {\r\n const result = await dialog.showSaveDialog( {\r\n defaultPath: `${values.name}.json`,\r\n filters: customURLFilter,\r\n });\r\n\r\n if (result.canceled) return;\r\n\r\n const jsonData = {\r\n name: values.name,\r\n url: values.url,\r\n target: values.target,\r\n showInScene: values.showInScene,\r\n showInAerial: values.showInAerial\r\n };\r\n\r\n const text = JSON.stringify(jsonData, null, 2);\r\n const savePath = slash(result.filePath);\r\n fs.writeFileSync(savePath, text);\r\n };\r\n\r\n const handleDeleteSubmit = () => {\r\n dispatch(deleteCustomLink(values.id));\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n {/** Download definition */}\r\n \r\n \r\n \r\n \r\n \r\n\r\n {/** Edit values */}\r\n \r\n \r\n \r\n \r\n \r\n\r\n {/** Delete */}\r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n }\r\n title={values.name}\r\n titleTypographyProps={{\r\n variant: \"body2\",\r\n className: classes.headerTitle\r\n }}\r\n subheader={dateString}\r\n subheaderTypographyProps={{\r\n variant: \"caption\"\r\n }}\r\n />\r\n \r\n
\r\n \r\n {t('custom-link.url')}: \r\n \r\n \r\n {values.url}\r\n \r\n
\r\n\r\n
\r\n \r\n {t('custom-link.target')}: \r\n \r\n \r\n {values.target}\r\n \r\n
\r\n
\r\n \r\n\r\n {/* Delete Dialog */}\r\n \r\n\r\n {/* Edit Dialog */}\r\n \r\n \r\n );\r\n};\r\n\r\ninterface CustomContextURLProps {\r\n open: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nexport const CustomContextURL = (props: CustomContextURLProps) => {\r\n const {open, onClose} = props;\r\n\r\n const dispatch = useDispatch();\r\n const {t} = useTranslation();\r\n const newURLDialog = useDialog();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const customLinks = useSelector(selectAllCustomLinks);\r\n\r\n const handleNewLink = () => {\r\n newURLDialog.handleOpen();\r\n };\r\n\r\n const handleImport = async () => {\r\n const result = await dialog.showOpenDialog({\r\n properties: ['openFile'],\r\n filters: customURLFilter\r\n });\r\n\r\n if (result.canceled) return;\r\n\r\n let filePath = slash(result.filePaths[0]);\r\n\r\n try {\r\n const text = fs.readFileSync(filePath, 'utf8');\r\n const data = JSON.parse(text);\r\n importURLData(data);\r\n } catch {\r\n toast.error(t('toast.error_reading_custom_url_definition'));\r\n }\r\n };\r\n\r\n const importURLData = (values) => {\r\n const valid = values.hasOwnProperty(\"name\")\r\n && values.hasOwnProperty(\"url\")\r\n && values.hasOwnProperty(\"target\")\r\n && values.hasOwnProperty(\"showInScene\")\r\n && values.hasOwnProperty(\"showInAerial\");\r\n\r\n if (valid) {\r\n dispatch(createCustomLink(values));\r\n return;\r\n }\r\n\r\n throw new Error(\"Invalid definition\");\r\n };\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n onClose();\r\n }, [uniqueProjectID]);\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/* Add new operation */}\r\n \r\n\r\n {/* Import definition file */}\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n {customLinks.map(data =>\r\n \r\n )}\r\n \r\n \r\n\r\n \r\n\r\n \r\n \r\n );\r\n};\r\n","import 'ol/ol.css';\r\n\r\nimport Map from 'ol/Map';\r\nimport Tile from 'ol/layer/Tile';\r\nimport View from 'ol/View';\r\nimport {Attribution, defaults as defaultControls} from 'ol/control';\r\nimport {DragPan} from 'ol/interaction';\r\nimport {Viewer} from \"../main\";\r\nimport {OSM, XYZ} from \"ol/source\";\r\nimport {transform} from 'ol/proj';\r\nimport {Vector as VectorSource} from \"ol/source\";\r\nimport {Vector as VectorLayer} from \"ol/layer\";\r\nimport { Circle as CircleStyle, Fill, Stroke, Style } from \"ol/style\";\r\nimport {Point, Polygon} from \"ol/geom\";\r\nimport {Feature, MapBrowserEvent} from \"ol\";\r\nimport {boundingExtent} from 'ol/extent';\r\nimport LocalScene, {\r\n DataProjectionCoordinate,\r\n LonLatCoordinate,\r\n SceneCoordinate\r\n} from '../projections';\r\nimport {Vector3} from 'three';\r\nimport { Projection } from '../../redux/projections-slice';\r\nimport { OrthoMosaicList } from '.';\r\nimport { CameraFeature, CameraImage } from '../cameras';\r\nimport { AerialViewState } from '../../redux/camera-slice';\r\nimport onresize from \"resize-event\";\r\nimport { showContextMenu } from '../../context-menu';\r\nimport { clearAerialTooltip, setAerialState } from '../viewer';\r\nimport { ChangeDetector } from '../utilities';\r\nimport { CustomMouseEvent } from '../controls';\r\nimport { emptyBasemapID } from '../../types/basemaps';\r\n\r\nconst CreateBasemapLayer = (id: string, source) => {\r\n return new Tile({\r\n source: source,\r\n properties: {\r\n id: id,\r\n type: 'basemap'\r\n }\r\n });\r\n};\r\n\r\nexport class TagFeature extends Feature {\r\n public tagID: string;\r\n public texture: string;\r\n public size: number;\r\n\r\n constructor(tagID, texture, size, opts) {\r\n super(opts);\r\n this.tagID = tagID;\r\n this.size = size;\r\n this.texture = texture;\r\n }\r\n}\r\n\r\nclass ViewTriangle {\r\n private viewer: Viewer;\r\n private aerialMap: AerialMap;\r\n private feature;\r\n private layer;\r\n\r\n constructor(aerialMap: AerialMap, viewer: Viewer) {\r\n this.viewer = viewer;\r\n this.aerialMap = aerialMap;\r\n\r\n this.generateSource();\r\n }\r\n\r\n get map() {\r\n return this.aerialMap.map;\r\n }\r\n\r\n get camera() {\r\n return this.viewer.camera;\r\n }\r\n\r\n generateSource() {\r\n // Adding our view triangle source\r\n const source = new VectorSource({\r\n wrapX: false\r\n });\r\n\r\n const polygon = new Polygon([[[0,0], [0,0]]]);\r\n const feature = new Feature(polygon);\r\n source.addFeature(feature);\r\n\r\n const layer = new VectorLayer({\r\n zIndex: 2,\r\n visible: false,\r\n source: source,\r\n properties: {\r\n type: \"triangle\"\r\n },\r\n style: new Style({\r\n stroke: new Stroke({\r\n color: \"rgba(0,0,0,0.5)\",\r\n width: 1.0\r\n }),\r\n fill: new Fill({\r\n color: \"rgba(64,244,155,0.5)\"\r\n })\r\n })\r\n });\r\n\r\n this.map.addLayer(layer);\r\n this.feature = feature;\r\n this.layer = layer;\r\n }\r\n\r\n rotateViewMarker(lookat) {\r\n // Updating feature geometry\r\n let ring = this.generateMarkerCoordinates(lookat);\r\n let polygon = new Polygon([ring]);\r\n polygon.transform('EPSG:4326', 'EPSG:3857');\r\n this.feature.setGeometry(polygon);\r\n }\r\n\r\n generateMarkerCoordinates(lookat) {\r\n // Set up additional constants\r\n let height = this.map.getTargetElement().clientHeight;\r\n let coneAngle = 0.8 * 0.5 * (this.camera.fov * Math.PI / 180);\r\n let axis = new Vector3(0, 0, 1);\r\n\r\n // Cone length is measured in meters based on aerial height\r\n let meterPerPixel = this.map.getView().getResolution();\r\n let coneLength = height * 0.10 * meterPerPixel;\r\n let maxConeLength = 1000000;\r\n if (coneLength > maxConeLength) {\r\n coneLength = 0;\r\n }\r\n\r\n // Center position\r\n let v0 = this.camera.position;\r\n\r\n // Set triangle size\r\n let vector = new Vector3(lookat.x, lookat.y, 0);\r\n vector.setLength(coneLength);\r\n\r\n // First triangle corner\r\n let v1 = vector.clone()\r\n .applyAxisAngle(axis, coneAngle)\r\n .add(v0);\r\n\r\n // Second triangle corner\r\n let v2 = vector.clone()\r\n .applyAxisAngle(axis, -coneAngle)\r\n .add(v0);\r\n\r\n v0 = new SceneCoordinate(v0).toLonLat();\r\n v1 = new SceneCoordinate(v1).toLonLat();\r\n v2 = new SceneCoordinate(v2).toLonLat();\r\n\r\n let ring = [\r\n [v1.x, v1.y],\r\n [v2.x, v2.y],\r\n [v0.x, v0.y],\r\n [v1.x, v1.y]\r\n ];\r\n\r\n return ring;\r\n }\r\n\r\n clear() {\r\n this.layer.setVisible(false);\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n if (!LocalScene.initialized || !changeDetector.changed) return;\r\n\r\n // Update view marker geometry\r\n this.rotateViewMarker(this.viewer.lookatVector);\r\n this.layer.setVisible(true);\r\n }\r\n}\r\n\r\nexport class AerialMap {\r\n private viewer: Viewer;\r\n public containerElement;\r\n public map: Map;\r\n public orthoList: OrthoMosaicList;\r\n private viewTriangle: ViewTriangle;\r\n private maxLayerZoom = 20;\r\n private maxMapZoomLevel = 28;\r\n private maxCameraZoomLevel = 23;\r\n private markerRadius = 6;\r\n private observer;\r\n\r\n private currentCameraFeature: Feature;\r\n private currentCameraLayer: VectorLayer;\r\n private selectedCameraFeature: Feature;\r\n private selectedCameraLayer: VectorLayer;\r\n\r\n public mapSystem = {\r\n string: \"EPSG:3857\",\r\n transform: null\r\n } as Projection;\r\n\r\n constructor(viewer: Viewer, container) {\r\n this.viewer = viewer;\r\n this.containerElement = container;\r\n\r\n this.initMap();\r\n this.initEvents();\r\n this.initResize();\r\n\r\n this.addCurrentLayer();\r\n this.addSelectedLayer();\r\n\r\n this.orthoList = new OrthoMosaicList(this);\r\n }\r\n\r\n get defaultLayers() {\r\n const arcGISBase = \"https://services.arcgisonline.com/ArcGIS/rest/services\";\r\n\r\n const layers = [\r\n CreateBasemapLayer(\"open-street-maps\", new OSM({\r\n maxZoom: this.maxLayerZoom\r\n })),\r\n\r\n CreateBasemapLayer(\"arcgis-world\", new XYZ({\r\n url: `${arcGISBase}/World_Imagery/MapServer/tile/{z}/{y}/{x}.png`,\r\n maxZoom: this.maxLayerZoom\r\n })),\r\n\r\n CreateBasemapLayer(\"arcgis-world\", new XYZ({\r\n attributions: 'Powered by Esri',\r\n url: `${arcGISBase}/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}.png`,\r\n maxZoom: this.maxLayerZoom\r\n })),\r\n\r\n CreateBasemapLayer(\"arcgis-street\", new XYZ({\r\n attributions: 'Powered by Esri',\r\n url: `${arcGISBase}/World_Street_Map/MapServer/tile/{z}/{y}/{x}.png`,\r\n maxZoom: this.maxLayerZoom\r\n })),\r\n ];\r\n\r\n return layers;\r\n }\r\n\r\n get cameraHandler() {\r\n return this.viewer.cameraHandler;\r\n }\r\n\r\n get width() {\r\n return this.containerElement.scrollWidth;\r\n }\r\n\r\n get height() {\r\n return this.containerElement.scrollHeight;\r\n }\r\n\r\n get basemapLayers() {\r\n return this.map\r\n .getLayers()\r\n .getArray()\r\n .filter(layer => layer.get(\"type\") === \"basemap\");\r\n }\r\n\r\n get activeBasemap() {\r\n let basemapID = null;\r\n this.basemapLayers.forEach(layer => {\r\n let isVisible = layer.getVisible();\r\n if (isVisible) {\r\n basemapID = layer.get(\"id\");\r\n }\r\n });\r\n\r\n return basemapID;\r\n }\r\n\r\n get aerialState() {\r\n const view = this.map.getView();\r\n\r\n const activeBasemap = this.basemapLayers\r\n .find(x => x.getVisible());\r\n\r\n const basemap = activeBasemap\r\n ? activeBasemap.get(\"id\")\r\n : emptyBasemapID;\r\n\r\n return {\r\n center: view.getCenter(),\r\n zoom: view.getZoom(),\r\n rotation: view.getRotation(),\r\n basemap\r\n } as AerialViewState;\r\n }\r\n\r\n get anyToolEnabled() {\r\n return this.orthoLabels.enabled\r\n || this.measurements.enabled;\r\n }\r\n\r\n get orthoLabels() {\r\n return this.viewer.imageLabels.orthoLabels;\r\n }\r\n\r\n get localAligner() {\r\n return this.viewer.controls.localAligner;\r\n }\r\n\r\n get measurements() {\r\n return this.viewer.measurements;\r\n }\r\n\r\n get tagsHandler() {\r\n return this.viewer.tagsHandler;\r\n }\r\n\r\n get element() {\r\n return this.map.getTargetElement();\r\n }\r\n\r\n resetView(state = {} as AerialViewState) {\r\n const view = this.map.getView();\r\n\r\n const center = state.center\r\n ? state.center\r\n : [0, 0];\r\n\r\n const zoom = state.zoom\r\n ? state.zoom\r\n : 0;\r\n\r\n const rotation = state.rotation\r\n ? state.rotation\r\n : 0;\r\n\r\n const basemap = state.basemap;\r\n\r\n view.setCenter(center);\r\n view.setZoom(zoom);\r\n view.setRotation(rotation);\r\n this.setVisibleBasemap(basemap);\r\n }\r\n\r\n initMap() {\r\n const attribution = new Attribution({\r\n collapsible: true,\r\n });\r\n\r\n this.map = new Map({\r\n layers: this.defaultLayers,\r\n target: this.containerElement,\r\n controls: defaultControls({\r\n zoom: false,\r\n attribution: false,\r\n rotate: true\r\n }).extend([attribution]),\r\n view: new View({\r\n maxZoom: this.maxMapZoomLevel\r\n })\r\n });\r\n\r\n this.viewTriangle = new ViewTriangle(this, this.viewer);\r\n\r\n this.resetView();\r\n this.setCurrentCamera(null, false);\r\n }\r\n\r\n initResize() {\r\n this.observer = onresize(this.containerElement, () => {\r\n this.handleWindowResize();\r\n });\r\n\r\n this.handleWindowResize();\r\n }\r\n\r\n initEvents() {\r\n this.onMapClick = this.onMapClick.bind(this);\r\n this.onMouseUp = this.onMouseUp.bind(this);\r\n this.onDoubleClick = this.onDoubleClick.bind(this);\r\n this.onMouseMove = this.onMouseMove.bind(this);\r\n this.updateSavedState = this.updateSavedState.bind(this);\r\n\r\n this.map.on('click', this.onMapClick);\r\n this.map.on('dblclick', this.onDoubleClick);\r\n this.map.on('pointermove', this.onMouseMove);\r\n this.map.on('moveend', this.updateSavedState);\r\n this.element.addEventListener('mouseup', this.onMouseUp, false);\r\n }\r\n\r\n removeEvents() {\r\n this.map.un('click', this.onMapClick);\r\n this.map.un('dblclick', this.onDoubleClick);\r\n this.map.un('pointermove', this.onMouseMove);\r\n this.map.un('moveend', this.updateSavedState);\r\n this.element.removeEventListener('mouseup', this.onMouseUp, false);\r\n }\r\n\r\n addCurrentLayer() {\r\n const style = new Style({\r\n image: new CircleStyle({\r\n radius: this.markerRadius,\r\n stroke: new Stroke({\r\n color: \"#000000\"\r\n }),\r\n fill: new Fill({\r\n color: \"#DD0C29\"\r\n }),\r\n })\r\n });\r\n\r\n this.currentCameraFeature = new Feature({\r\n geometry: new Point([0,0])\r\n });\r\n\r\n const source = new VectorSource({\r\n wrapX: false,\r\n features: [this.currentCameraFeature]\r\n });\r\n\r\n this.currentCameraLayer = new VectorLayer({\r\n zIndex: 2,\r\n visible: false,\r\n source,\r\n style\r\n });\r\n\r\n this.map.addLayer(this.currentCameraLayer);\r\n }\r\n\r\n addSelectedLayer() {\r\n const style = new Style({\r\n image: new CircleStyle({\r\n radius: this.markerRadius,\r\n stroke: new Stroke({\r\n color: \"#000000\"\r\n }),\r\n fill: new Fill({\r\n color: \"#FFC300\"\r\n }),\r\n })\r\n });\r\n\r\n this.selectedCameraFeature = new Feature({\r\n geometry: new Point([0,0])\r\n });\r\n\r\n const source = new VectorSource({\r\n wrapX: false,\r\n features: [this.selectedCameraFeature]\r\n });\r\n\r\n this.selectedCameraLayer = new VectorLayer({\r\n zIndex: 2,\r\n visible: false,\r\n source,\r\n style\r\n });\r\n\r\n this.map.addLayer(this.selectedCameraLayer);\r\n }\r\n\r\n onDoubleClick(event) {\r\n this.orthoLabels.onDoubleClick(event);\r\n }\r\n\r\n onMapClick(event) {\r\n const mapClicked = this.orthoLabels.onMapClick(event)\r\n || this.localAligner.onMapClick(event)\r\n || this.tagsHandler.onMapClick(event);\r\n\r\n if (mapClicked) return;\r\n\r\n const features = this.tagsHandler.hovering\r\n ? this.tagsHandler.getFeatureForEvent(event)\r\n : this.cameraHandler.getFeatureForEvent(event);\r\n\r\n // No features were found\r\n if (features.length === 0) return;\r\n\r\n const currentView = this.map.getView();\r\n const currentZoom = Math.ceil(currentView.getZoom());\r\n const maxZoomReached = currentZoom >= this.maxCameraZoomLevel;\r\n const singleFeature = features.length === 1;\r\n\r\n if (singleFeature || maxZoomReached) {\r\n const feature = features[0];\r\n\r\n if (feature instanceof TagFeature) {\r\n const selectedTagID = feature.tagID;\r\n this.viewer.showTagDetails(selectedTagID);\r\n } else if (feature instanceof CameraFeature) {\r\n const selectedCameraID = feature.camera.id;\r\n this.viewer.loadImage(selectedCameraID);\r\n }\r\n\r\n return;\r\n }\r\n\r\n // Zoom to cluster with 50% boundary\r\n const coordinates = [...features]\r\n .map((x: Feature) => x.getGeometry().getCoordinates());\r\n const extent = boundingExtent(coordinates);\r\n const mapSize = this.map.getSize();\r\n\r\n this.map.getView().fit(extent, {\r\n size: [mapSize[0] * 0.5, mapSize[1] * 0.5],\r\n nearest: false,\r\n duration: 250,\r\n });\r\n\r\n clearAerialTooltip();\r\n }\r\n\r\n onMouseUp(initialEvent) {\r\n const event = this.getCustomEvent(initialEvent);\r\n\r\n const mouseClicked = this.orthoLabels.onMouseUp(event)\r\n || this.localAligner.onMouseUp(event)\r\n || this.measurements.onMouseUpAerial(event)\r\n || this.tagsHandler.onMouseUpAerial(event);\r\n\r\n if (mouseClicked) return;\r\n\r\n if (event.isRightClick) {\r\n this.openContextMenu(event);\r\n }\r\n }\r\n\r\n onMouseMove(event: MapBrowserEvent) {\r\n if (this.orthoLabels.enabled) {\r\n this.orthoLabels.onMouseMove(event);\r\n } else if (this.measurements.enabled) {\r\n this.measurements.onMouseMoveAerial(event);\r\n } else if (this.localAligner.enabled) {\r\n this.localAligner.onMouseMoveAerial();\r\n } else {\r\n this.tagsHandler.onMouseMoveAerial(event);\r\n }\r\n\r\n if (event.dragging) return;\r\n this.onFeatureHover(event);\r\n }\r\n\r\n onFeatureHover(event) {\r\n const cameras = this.cameraHandler.getFeatureForEvent(event);\r\n const selectedCamera = cameras[0];\r\n\r\n if (selectedCamera) {\r\n const geometry = selectedCamera.getGeometry();\r\n this.selectedCameraFeature.setGeometry(geometry);\r\n this.selectedCameraLayer.setVisible(true);\r\n } else {\r\n this.selectedCameraLayer.setVisible(false);\r\n }\r\n }\r\n\r\n getCustomEvent(event) : CustomMouseEvent {\r\n event.isLeftClick = event.button === 0;\r\n event.isRightClick = event.button === 2;\r\n return event;\r\n }\r\n\r\n updateSavedState() {\r\n setAerialState(this.aerialState);\r\n }\r\n\r\n openContextMenu(event) {\r\n if (this.anyToolEnabled) {\r\n return showContextMenu(event, {\r\n isAerial: true\r\n });\r\n }\r\n\r\n // Tag attributes\r\n const pixel = this.map.getEventPixel(event);\r\n const tags = this.tagsHandler.getFeatureForEvent({pixel});\r\n const tagIDs = tags.map(tag => tag.tagID);\r\n\r\n // New tag coordinate\r\n const mapCoordinate = this.map.getCoordinateFromPixel(pixel);\r\n const lonlat = transform(mapCoordinate, 'EPSG:3857', 'EPSG:4326');\r\n const aerialCoord = new LonLatCoordinate(lonlat)\r\n .toDataProjection()\r\n .toArray()\r\n .slice(0,2);\r\n\r\n // Show default context menu\r\n showContextMenu(event, {\r\n isAerial: true,\r\n selectedTags: tagIDs,\r\n aerialCoord\r\n });\r\n }\r\n\r\n handleWindowResize() {\r\n if (!this.map) return;\r\n this.map.updateSize();\r\n this.map.render();\r\n }\r\n\r\n setDragState(state) {\r\n this.map.getInteractions().forEach(interaction => {\r\n if (interaction instanceof DragPan) {\r\n interaction.setActive(state);\r\n }\r\n });\r\n }\r\n\r\n jumpToPosition(position) {\r\n const view = this.map.getView();\r\n view.setCenter(position);\r\n }\r\n\r\n setVisibleBasemap(basemapID: string) {\r\n basemapID = basemapID || emptyBasemapID;\r\n\r\n this.basemapLayers.forEach(layer => {\r\n let id = layer.get(\"id\");\r\n layer.setVisible(id === basemapID);\r\n });\r\n\r\n this.updateSavedState();\r\n }\r\n\r\n setCurrentCamera(camera: CameraImage, centerOnImage: boolean) {\r\n if (this.currentCameraLayer) {\r\n this.currentCameraLayer.setVisible(false);\r\n }\r\n\r\n if (!camera) return;\r\n\r\n const mapPosition = camera.position.aerial;\r\n const point = new Point([mapPosition[0], mapPosition[1]]);\r\n\r\n this.currentCameraFeature.setGeometry(point);\r\n\r\n // Move aerial map to camera position\r\n if (centerOnImage) {\r\n this.jumpToPosition(mapPosition);\r\n }\r\n\r\n this.currentCameraLayer.setVisible(true);\r\n }\r\n\r\n setMapExtent(extent) {\r\n const view = this.map.getView();\r\n\r\n view.setRotation(0);\r\n view.fit(extent, {\r\n size: this.map.getSize()\r\n });\r\n view.setZoom(view.getZoom() - 1.0);\r\n }\r\n\r\n destroy() {\r\n this.removeEvents();\r\n this.observer.disconnect();\r\n this.map.setTarget(null);\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n if (this.viewer.orbitState) {\r\n this.viewTriangle.clear();\r\n return;\r\n }\r\n\r\n if (this.viewer.hasPoints || this.viewer.cameraSelected) {\r\n this.viewTriangle.update(changeDetector);\r\n }\r\n }\r\n}\r\n\r\nexport const extentFromPoints = (positions, reproject=true) => {\r\n let xPositions = [];\r\n let yPositions = [];\r\n\r\n if (reproject) {\r\n positions = positions.map(position => {\r\n let lonlat = new DataProjectionCoordinate(position).toLonLat();\r\n let mapPos = transform([lonlat.x, lonlat.y], 'EPSG:4326', 'EPSG:3857');\r\n return mapPos;\r\n });\r\n }\r\n\r\n positions.forEach(position => {\r\n xPositions.push(position[0]);\r\n yPositions.push(position[1]);\r\n });\r\n\r\n let extent = [\r\n Math.min(...xPositions),\r\n Math.min(...yPositions),\r\n Math.max(...xPositions),\r\n Math.max(...yPositions)\r\n ];\r\n\r\n return extent;\r\n};","import 'ol/ol.css';\r\nimport Map from 'ol/Map';\r\nimport Static from 'ol/source/ImageStatic';\r\nimport ImageLayer from 'ol/layer/Image';\r\nimport LayerGroup from 'ol/layer/Group';\r\nimport {transformExtent, transform} from 'ol/proj';\r\nimport LocalScene, {\r\n LonLatCoordinate,\r\n ProjectedCoordinate\r\n} from '../projections';\r\nimport { AerialMap } from '.';\r\nimport {polygon as turfPolygon} from '@turf/helpers';\r\nimport {default as turfIntersect} from '@turf/intersect';\r\nimport { Asset, OrthoData } from '../../redux/assets-slice';\r\n\r\ninterface LoadableChunk {\r\n orthomosaic: OrthoMosaic;\r\n element: HTMLImageElement;\r\n src: string;\r\n}\r\n\r\nclass OrthoImageLayer extends ImageLayer {\r\n constructor(opts) {\r\n super(opts);\r\n }\r\n}\r\n\r\nexport class OrthoMosaic {\r\n public id;\r\n public mapLayer: LayerGroup;\r\n private corners = [];\r\n public aerialBounds = [];\r\n private scaleX: number;\r\n private scaleY: number;\r\n private imageBase64: string;\r\n private name: string;\r\n private splitData;\r\n private cropBase64 = [];\r\n private cropCorners = [];\r\n private imageSize: [Number, Number];\r\n private imageSizeOriginal: [Number, Number];\r\n private imagePath: string;\r\n private saved: boolean;\r\n private extent = [];\r\n private orthosList: OrthoMosaicList;\r\n public loading = false;\r\n public loaded = false;\r\n\r\n constructor(orthosList: OrthoMosaicList, data) {\r\n this.orthosList = orthosList;\r\n this.id = data.id;\r\n this.name = data.name;\r\n this.corners = data.corners;\r\n this.imageBase64 = data.base64;\r\n this.imageSize = data.imageSize;\r\n this.splitData = data.splitData;\r\n this.imageSizeOriginal = data.imageSizeOriginal;\r\n this.saved = data.saved;\r\n this.imagePath = data.imagePath;\r\n this.scaleX = data.scaleX;\r\n this.scaleY = data.scaleY;\r\n\r\n this.calculateCroppedData();\r\n this.calculateExtent();\r\n this.calculateAerialPolygon();\r\n this.addMapLayer();\r\n }\r\n\r\n get opacity() {\r\n return this.orthosList.opacity;\r\n }\r\n\r\n get aerialMap() {\r\n return this.orthosList.aerialMap;\r\n }\r\n\r\n get map() {\r\n return this.orthosList.map;\r\n }\r\n\r\n get projection() {\r\n return LocalScene.dataProjectionName;\r\n }\r\n\r\n get proj4Projection() {\r\n return LocalScene.dataProjection;\r\n }\r\n\r\n get visible() {\r\n return this.mapLayer.getVisible();\r\n }\r\n\r\n get path() {\r\n return this.imagePath;\r\n }\r\n\r\n get cornerCoordinates() {\r\n return this.corners;\r\n }\r\n\r\n get scale() {\r\n return [this.scaleX, this.scaleY];\r\n }\r\n\r\n get originalSize() {\r\n return this.imageSizeOriginal;\r\n }\r\n\r\n get orthoName() {\r\n return this.name;\r\n }\r\n\r\n get metadata() {\r\n return {\r\n x_scale: this.scaleX,\r\n y_scale: this.scaleY,\r\n x_offset: this.corners[0],\r\n y_offset: this.corners[3],\r\n x_skew: 0.0,\r\n y_skew: 0.0\r\n };\r\n }\r\n\r\n get cornerPixels() {\r\n return [\r\n [0, 0],\r\n [this.originalSize[0], 0],\r\n [this.originalSize[0], this.originalSize[1]],\r\n [0, this.originalSize[1]],\r\n ] as Array<[number, number]>;\r\n }\r\n\r\n zoomToExtent() {\r\n this.aerialMap.setMapExtent(this.extent);\r\n }\r\n\r\n calculateExtent() {\r\n const extent = transformExtent(this.corners,\r\n this.projection, 'EPSG:3857');\r\n this.extent = extent;\r\n }\r\n\r\n calculateAerialPolygon() {\r\n this.aerialBounds = imagePixelsToAerial(\r\n this.cornerPixels, this, this.proj4Projection);\r\n }\r\n\r\n calculateCroppedData() {\r\n if (this.splitData) {\r\n this.cropBase64 = [];\r\n this.cropCorners = [];\r\n\r\n this.splitData.forEach(data => {\r\n // Cropped base64 data\r\n let {index_start, index_end} = data;\r\n let base64 = this.imageBase64.slice(index_start, index_end);\r\n this.cropBase64.push(base64);\r\n\r\n // Cropped extent\r\n let {width_start, width_end, height_start, height_end} = data;\r\n let extentWidth = this.corners[2] - this.corners[0];\r\n let extentHeight = this.corners[3] - this.corners[1];\r\n\r\n let subtileCorners = [\r\n this.corners[0] + extentWidth * width_start,\r\n this.corners[3] - (extentHeight * height_end),\r\n this.corners[0] + extentWidth * width_end,\r\n this.corners[3] - (extentHeight * height_start),\r\n ];\r\n\r\n this.cropCorners.push(subtileCorners);\r\n });\r\n } else {\r\n // Single value. Convert to array\r\n this.cropBase64 = [this.imageBase64];\r\n this.cropCorners = [this.corners];\r\n }\r\n }\r\n\r\n intersectAerialPoints(aerialPoints) {\r\n return turfIntersect(\r\n turfPolygon([[...aerialPoints, aerialPoints[0]]]),\r\n turfPolygon([[...this.aerialBounds, this.aerialBounds[0]]])\r\n );\r\n }\r\n\r\n aerialToPixels(aerialPoints) {\r\n return aerialToImagePixels(\r\n aerialPoints, this, this.proj4Projection);\r\n }\r\n\r\n transform(coordinates) {\r\n let coordinatesTransformed = [];\r\n coordinates.forEach(coordinate =>{\r\n let coordTransformed = transform(coordinate, 'EPSG:3857', this.projection);\r\n coordinatesTransformed.push(coordTransformed);\r\n });\r\n return coordinatesTransformed;\r\n }\r\n\r\n reverseTransform(coordinates) {\r\n let coordinatesTransformed = [];\r\n coordinates.forEach(coordinate =>{\r\n let coordTransformed = transform(coordinate, this.projection, 'EPSG:3857');\r\n coordinatesTransformed.push(coordTransformed);\r\n });\r\n return coordinatesTransformed;\r\n }\r\n\r\n addMapLayer() {\r\n let allLayers = [];\r\n let numSubtiles = this.cropBase64.length;\r\n\r\n console.log(`Load ortho layer (${numSubtiles} subtiles)`);\r\n\r\n for (var i =0; i {\r\n const imageChunk = {\r\n orthomosaic: this,\r\n element: image.getImage() as HTMLImageElement,\r\n src: imageURL\r\n };\r\n\r\n this.orthosList.addImageChunk(imageChunk);\r\n }\r\n });\r\n\r\n let layer = new OrthoImageLayer({source});\r\n\r\n // Add layer to group\r\n allLayers.push(layer);\r\n }\r\n\r\n // Create layer group that contains all subtiles\r\n this.mapLayer = new LayerGroup({layers: allLayers});\r\n this.setOpacity();\r\n\r\n this.map.addLayer(this.mapLayer);\r\n\r\n if (this.saved) return;\r\n this.zoomToExtent();\r\n }\r\n\r\n setOpacity() {\r\n this.mapLayer.setOpacity(this.opacity);\r\n }\r\n\r\n setVisibility(visible) {\r\n this.mapLayer.setVisible(visible);\r\n }\r\n\r\n destroy() {\r\n if (!this.mapLayer) return;\r\n this.map.removeLayer(this.mapLayer);\r\n this.imageBase64 = null;\r\n this.mapLayer = null;\r\n }\r\n}\r\n\r\nexport class OrthoMosaicList {\r\n public orthos: OrthoMosaic[] = [];\r\n public opacity = 0.8;\r\n public aerialMap: AerialMap;\r\n public chunksLoading = false;\r\n public chunksToLoad = [] as LoadableChunk[];\r\n private enabled = true;\r\n\r\n constructor(aerialMap: AerialMap) {\r\n this.aerialMap = aerialMap;\r\n }\r\n\r\n get map(): Map {\r\n return this.aerialMap.map;\r\n }\r\n\r\n destroy() {\r\n this.enabled = false;\r\n }\r\n\r\n reconcile(orthoFiles: Asset[]) {\r\n const currentIDs = new Set(this.orthos.map(ortho => ortho.id));\r\n const newAssetIDs = new Set(orthoFiles.map(ortho => ortho.id));\r\n const assetsToLoad = orthoFiles.filter(ortho => !currentIDs.has(ortho.id));\r\n const filesToDelete = this.orthos.filter(ortho => !newAssetIDs.has(ortho.id));\r\n\r\n // Delete orthos that need to be removed\r\n filesToDelete.forEach(file => {\r\n this.deleteFile(file);\r\n });\r\n\r\n // Add new orthos\r\n assetsToLoad.forEach(file => {\r\n this.addNewFile(file);\r\n });\r\n\r\n // Toggle proper visibility for each ortho\r\n orthoFiles.forEach(ortho => {\r\n this.toggleVisibility(ortho.id, ortho.visible);\r\n });\r\n }\r\n\r\n addNewFile(file: Asset) {\r\n if (this.getByID(file.id)) return;\r\n\r\n const {\r\n imageBounds, imageData, imageDataSplit, imageSize,\r\n imageSizeOriginal, imagePath, scaleX, scaleY\r\n } = file.data as OrthoData;\r\n\r\n const data = {\r\n id: file.id,\r\n name: file.name,\r\n corners: imageBounds,\r\n base64: imageData,\r\n splitData: imageDataSplit,\r\n imageSize,\r\n imageSizeOriginal,\r\n saved: file.saved,\r\n imagePath,\r\n scaleX,\r\n scaleY\r\n };\r\n\r\n let ortho = new OrthoMosaic(this, data);\r\n this.orthos.push(ortho);\r\n }\r\n\r\n deleteFile(file: OrthoMosaic) {\r\n file.destroy();\r\n\r\n const index = this.orthos.indexOf(file);\r\n this.orthos.splice(index, 1);\r\n }\r\n\r\n getByID(orthoID) {\r\n return this.orthos.find(ortho => ortho.id === orthoID);\r\n }\r\n\r\n addImageChunk(loadable: LoadableChunk) {\r\n this.chunksToLoad.push(loadable);\r\n }\r\n\r\n toggleVisibility = (orthoID, visible) => {\r\n let ortho = this.getByID(orthoID);\r\n if (!ortho) {\r\n return;\r\n }\r\n\r\n ortho.setVisibility(visible);\r\n }\r\n\r\n setOpacity = (value) => {\r\n if ((value < 0.0) || (value > 1.0)) {\r\n return;\r\n }\r\n\r\n this.opacity = value;\r\n this.orthos.forEach(ortho => ortho.setOpacity());\r\n }\r\n\r\n update() {\r\n if (!this.enabled || this.chunksLoading) return;\r\n\r\n if (this.chunksToLoad.length === 0) return;\r\n const toLoad = this.chunksToLoad.pop();\r\n\r\n const {orthomosaic, element, src} = toLoad;\r\n\r\n if (orthomosaic.mapLayer && orthomosaic.visible) {\r\n this.chunksLoading = true;\r\n element.onload = () => {\r\n this.chunksLoading = false;\r\n };\r\n element.src = src;\r\n } else {\r\n // Push ortho chunk back to queue\r\n this.chunksToLoad.push(toLoad);\r\n }\r\n }\r\n}\r\n\r\nexport const imagePixelsToAerial = (points, image: OrthoMosaic, projection): Array<[number, number]> => {\r\n let newPoints = [];\r\n\r\n try {\r\n let metadata = image.metadata;\r\n newPoints = points.map(point => {\r\n let x = point[0]*metadata.x_scale + metadata.x_offset;\r\n let y = point[1]*metadata.y_scale + metadata.y_offset;\r\n let lonlat = new ProjectedCoordinate([x,y,0], projection).toLonLat();\r\n return transform([lonlat.x, lonlat.y], 'EPSG:4326', 'EPSG:3857');\r\n });\r\n } catch {\r\n // Do Nothing\r\n }\r\n\r\n return newPoints;\r\n};\r\n\r\nexport const aerialToImagePixels = (points, image: OrthoMosaic, projection): Array<[number, number]> => {\r\n let newPoints = [];\r\n\r\n\r\n let metadata = image.metadata;\r\n newPoints = points.map(point => {\r\n let lonlat = transform([point[0], point[1], 0], 'EPSG:3857', 'EPSG:4326');\r\n let projected = new LonLatCoordinate(lonlat)\r\n .toProjection(projection);\r\n\r\n let x = (projected.x - metadata.x_offset) / metadata.x_scale;\r\n let y = (projected.y - metadata.y_offset) / metadata.y_scale;\r\n return [x, y];\r\n });\r\n\r\n\r\n return newPoints;\r\n};\r\n\r\n","import { Viewer, ViewerProps } from \"../main\";\r\nimport {\r\n SceneLabelTools,\r\n AerialLabelTools,\r\n textToColorArray\r\n} from \".\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport LocalScene, { isValidProjection } from \"../projections\";\r\nimport {Line3, ShapeUtils, Vector2, Vector3} from \"three\";\r\nimport {\r\n polygon as turfPolygon,\r\n lineString as turfLineString,\r\n point as turfPoint\r\n} from '@turf/helpers';\r\nimport {default as turfSimplify} from '@turf/simplify';\r\nimport {default as turfUnion} from '@turf/union';\r\nimport { PanoramicImage, PlanarImage } from \"../cameras\";\r\nimport GeoJSONReader from 'jsts/org/locationtech/jts/io/GeoJSONReader';\r\nimport {BufferOp} from 'jsts/org/locationtech/jts/operation/buffer';\r\nimport { toast } from \"../../app\";\r\nimport { imagePixelsToAerial } from \"../aerial\";\r\nimport {ChangeDetector, coordinatesToArray} from \"../utilities\";\r\nimport { clearAerialTooltip, clearViewerTooltip } from \"../viewer\";\r\nimport { t } from \"../../localization\";\r\nimport { asyncTimeout } from \"../../utilities\";\r\n\r\nexport interface CocoCategory {\r\n supercategory: string,\r\n id: number,\r\n visible: boolean,\r\n name: string,\r\n color: [number, number, number]\r\n}\r\n\r\nexport interface CocoImage {\r\n height: number,\r\n width: number,\r\n id: number,\r\n file_name: string,\r\n metadata?: {\r\n x_skew: number,\r\n y_skew: number,\r\n x_scale: number,\r\n y_scale: number,\r\n x_offset: number,\r\n y_offset: number\r\n }\r\n}\r\n\r\nexport interface CocoAnnotation {\r\n segmentation: Array<[]>,\r\n iscrowd: number,\r\n image_id: number,\r\n merge_id?: number\r\n bbox: [number, number, number, number],\r\n category_id: number,\r\n id: number,\r\n area: number,\r\n score: number,\r\n text: string,\r\n textScore: number,\r\n findText: number\r\n}\r\n\r\nexport class ImageLabel {\r\n public id;\r\n public category;\r\n public selected = false;\r\n public completed = false;\r\n public editing = false;\r\n public valid = true;\r\n public drawable = true;\r\n public highlighted = false;\r\n public score = 1.0;\r\n public text = '';\r\n public textScore = 1.0;\r\n public isThing = 1;\r\n public findText = false;\r\n private duplicatePixelDistance = 5;\r\n public coordinates = [];\r\n\r\n constructor() {\r\n this.id = nanoid();\r\n }\r\n\r\n get hasEnoughPoints() {\r\n console.warn(\"Not Implemented\");\r\n return false;\r\n }\r\n\r\n get numPoints() {\r\n console.warn(\"Not Implemented\");\r\n return 0;\r\n }\r\n\r\n select() {\r\n const stateChanged = !this.selected;\r\n this.selected = true;\r\n this.highlighted = false;\r\n this.completed = false;\r\n\r\n if (stateChanged) {\r\n this.draw();\r\n }\r\n }\r\n\r\n unSelect() {\r\n this.selected = false;\r\n this.complete();\r\n }\r\n\r\n complete() {\r\n const stateChanged = !this.completed;\r\n this.completed = true;\r\n\r\n if (stateChanged) {\r\n this.draw();\r\n }\r\n }\r\n\r\n setDrawable(state) {\r\n this.drawable = state;\r\n }\r\n\r\n setEditing(state) {\r\n this.editing = state;\r\n }\r\n\r\n setScore(score) {\r\n if (score){\r\n this.score = score;\r\n } else {\r\n this.score = 1.0;\r\n }\r\n }\r\n\r\n setIsThing(isThing) {\r\n this.isThing = isThing;\r\n }\r\n\r\n setText(text, score=1.0) {\r\n if (typeof text === 'string') {\r\n this.text = text;\r\n } else {\r\n this.text = '';\r\n }\r\n this.textScore = score;\r\n }\r\n\r\n setFindText(num) {\r\n this.findText = num;\r\n }\r\n\r\n zoom(): Promise {\r\n console.warn(\"Not Implemented\");\r\n return Promise.resolve(false);\r\n }\r\n\r\n setHighlighted(highlight) {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n destroy() {\r\n this.clear();\r\n }\r\n\r\n clear() {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n draw() {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n insertPoint(point, index) {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n createCoordData(coordinate) {\r\n console.warn(\"Not Implemented\");\r\n\r\n let coordArray = [];\r\n let point = new Vector3();\r\n\r\n return {coordArray, point};\r\n }\r\n\r\n toScreenPosition(point) {\r\n console.warn(\"Not Implemented\");\r\n return [0, 0];\r\n }\r\n\r\n duplicatePoint(oldPoint, newPoint) {\r\n if (!oldPoint) return false;\r\n\r\n // Check screen distance from previous point\r\n let screenPosNew = this.toScreenPosition(oldPoint);\r\n let screenPosOld = this.toScreenPosition(newPoint);\r\n let dU = screenPosNew[0] - screenPosOld[0];\r\n let dV = screenPosNew[1] - screenPosOld[1];\r\n let distance = Math.sqrt(dU**2 + dV**2);\r\n\r\n return distance < this.duplicatePixelDistance;\r\n }\r\n}\r\n\r\nexport class LabelCategory {\r\n public id;\r\n public name;\r\n public listIdx = -1;\r\n public labels: ImageLabel[] = [];\r\n private invalidLabels: ImageLabel[] = [];\r\n public visible = true;\r\n private sorted = false;\r\n private originalOrder = [];\r\n\r\n constructor(name) {\r\n this.id = nanoid();\r\n this.name = name;\r\n }\r\n\r\n get numLabelsAll() {\r\n return this.labels.length + this.invalidLabels.length;\r\n }\r\n\r\n getLabelByID(labelID) {\r\n return this.labels.find(label => label.id === labelID);\r\n }\r\n\r\n setText(labelID, text, score=1.0) {\r\n let label = this.getLabelByID(labelID);\r\n if (label) {\r\n label.setText(text, score);\r\n }\r\n return;\r\n }\r\n\r\n setFindText(state) {\r\n this.labels.forEach(label => label.findText = state);\r\n }\r\n\r\n setVisible(visibility) {\r\n this.visible = visibility;\r\n }\r\n\r\n addNewLabel(drawLabel) {\r\n console.warn(\"Not implemented\");\r\n return null;\r\n }\r\n\r\n updateColor() {\r\n console.warn(\"Not implemented\");\r\n }\r\n\r\n insertPoint(labelID, coordinate) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n let {coordArray, point} = label.createCoordData(coordinate);\r\n let idxCoord = minDistanceIdx(coordArray, point);\r\n label.insertPoint(point, idxCoord);\r\n\r\n toast.success(t(\"toast.labels-add-point\"));\r\n }\r\n\r\n editLabel(labelID, coordinate) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n label.setEditing(true);\r\n\r\n let {coordArray, point} = label.createCoordData(coordinate);\r\n let idxCoord = minDistanceIdx(coordArray, point);\r\n let endIdx = (idxCoord === coordArray.length - 1) ? 0 : idxCoord + 1;\r\n let line = createSegment(coordArray[idxCoord], coordArray[endIdx]);\r\n\r\n let reverse = line.closestPointToPointParameter(point, true) > 0.5;\r\n label.coordinates = [\r\n ...label.coordinates.slice(idxCoord+1, label.coordinates.length),\r\n ...label.coordinates.slice(0, idxCoord+1)\r\n ];\r\n\r\n if (reverse) {\r\n label.coordinates.reverse();\r\n }\r\n }\r\n\r\n deleteLabel(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n label.destroy();\r\n const index = this.labels.indexOf(label);\r\n this.labels.splice(index, 1);\r\n }\r\n\r\n deleteLabels(labelIDs) {\r\n labelIDs.forEach(labelID => {\r\n this.deleteLabel(labelID);\r\n });\r\n }\r\n\r\n async zoomToLabel(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n let validLabel = await label.zoom();\r\n if (validLabel) {\r\n label.setHighlighted(true);\r\n }\r\n }\r\n\r\n unHighlight(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n label.setHighlighted(false);\r\n }\r\n\r\n updateName(name) {\r\n this.name = name;\r\n this.updateColor();\r\n }\r\n\r\n toggleVisibility(state) {\r\n this.labels.forEach(label => label.setDrawable(state));\r\n this.invalidLabels.forEach(label => label.setDrawable(state));\r\n this.setVisible(state);\r\n }\r\n\r\n completeLabel(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return false;\r\n }\r\n\r\n if (!label.hasEnoughPoints) {\r\n return false;\r\n }\r\n\r\n label.setHighlighted(false);\r\n label.unSelect();\r\n label.complete();\r\n\r\n return true;\r\n }\r\n\r\n unSelectAll() {\r\n this.labels.forEach(label =>\r\n label.unSelect()\r\n );\r\n }\r\n\r\n selectLabel(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n label.select();\r\n label.score = 1.0;\r\n }\r\n\r\n sortLabels(scoreThreshold, type) {\r\n let allLabels = [...this.labels, ...this.invalidLabels];\r\n\r\n if (!this.sorted) {\r\n let order = [];\r\n this.labels.forEach(label => order.push(label.id));\r\n this.originalOrder = order;\r\n this.sorted = true;\r\n }\r\n\r\n if (type === \"ascending\"){\r\n allLabels.sort((a,b) => a.score - b.score);\r\n }\r\n else if (type === \"descending\") {\r\n allLabels.sort((a,b) => b.score - a.score);\r\n }\r\n\r\n this.labels = allLabels.filter(label => label.score > scoreThreshold);\r\n this.invalidLabels = allLabels.filter(label => label.score <= scoreThreshold);\r\n\r\n this.invalidLabels.forEach(label => label.clear());\r\n }\r\n\r\n undoSort() {\r\n let allLabels = [...this.labels, ...this.invalidLabels];\r\n\r\n let unsortedLabels = [];\r\n this.originalOrder.forEach(labelID => {\r\n let match = allLabels.find(label => label.id === labelID);\r\n unsortedLabels.push(match);\r\n });\r\n\r\n this.labels = unsortedLabels;\r\n this.invalidLabels = [];\r\n this.sorted = false;\r\n }\r\n\r\n moveToLabelInList(labelID) {\r\n this.labels.forEach((label, index) => {\r\n if (label.id === labelID) {\r\n this.listIdx = index;\r\n }\r\n });\r\n }\r\n}\r\n\r\nexport class ImageLabelTools {\r\n public viewer: Viewer;\r\n public orthoLabels: AerialLabelTools;\r\n public sceneLabels: SceneLabelTools;\r\n private activeLabeler: AerialLabelTools | SceneLabelTools;\r\n public categories: LabelCategory[] = [];\r\n private currentCategory;\r\n private allowUpdate = true;\r\n\r\n private setCategoryList: React.Dispatch;\r\n private setTrainingArea: React.Dispatch;\r\n\r\n constructor(viewer: Viewer, props: ViewerProps) {\r\n const {setCategoryList, setTrainingArea} = props;\r\n\r\n this.viewer = viewer;\r\n this.orthoLabels = new AerialLabelTools(this);\r\n this.sceneLabels = new SceneLabelTools(this);\r\n this.setCategoryList = setCategoryList;\r\n this.setTrainingArea = setTrainingArea;\r\n\r\n this.setCategories();\r\n }\r\n\r\n get currentCategoryName() {\r\n return this.currentCategory.name;\r\n }\r\n\r\n get trainingArea() {\r\n if (this.activeLabeler instanceof AerialLabelTools) {\r\n return this.activeLabeler.trainingArea;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n get isAerialLabels() {\r\n return this.activeLabeler instanceof AerialLabelTools;\r\n }\r\n\r\n get isSceneLabels() {\r\n return this.activeLabeler instanceof SceneLabelTools;\r\n }\r\n\r\n get polygonScene() {\r\n return this.sceneLabels.polygonScene;\r\n }\r\n\r\n get standardScene() {\r\n return this.sceneLabels.standardScene;\r\n }\r\n\r\n get numHighlighted() {\r\n let count = 0;\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.highlighted) {\r\n count++;\r\n }\r\n });\r\n });\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.highlighted) {\r\n count++;\r\n }\r\n });\r\n\r\n return count;\r\n }\r\n\r\n get noneHighlighted() {\r\n return this.numHighlighted === 0;\r\n }\r\n\r\n get oneHighlighted() {\r\n return this.numHighlighted === 1;\r\n }\r\n\r\n get numLabels() {\r\n let count = 0;\r\n this.categories.forEach(category => {\r\n count += category.numLabelsAll;\r\n });\r\n return count;\r\n }\r\n\r\n highlightedLabels() {\r\n let labels = [];\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.highlighted) {\r\n labels.push(label);\r\n }\r\n });\r\n });\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.highlighted) {\r\n labels.push(label);\r\n }\r\n });\r\n\r\n return labels;\r\n }\r\n\r\n getIdxInList(category) {\r\n let validCategory = this.categories.find(x => x.name === category.name);\r\n if (!validCategory) {\r\n return;\r\n }\r\n\r\n return validCategory.listIdx;\r\n }\r\n\r\n setUpdateState(state) {\r\n this.allowUpdate = state;\r\n }\r\n\r\n setFindText(categoryID) {\r\n this.categories.forEach(category => category.setFindText(false));\r\n\r\n const category = this.getCategoryByID(categoryID);\r\n if (!category) {\r\n return;\r\n }\r\n\r\n category.setFindText(true);\r\n }\r\n\r\n onKeyDown(event) {\r\n let label = this.activeLabeler.activeLabel;\r\n\r\n if (label) {\r\n // Check for completion hotkey -> Enter\r\n if (event.which === 13) {\r\n if (label.selected){\r\n this.completeLabel(label.id);\r\n }\r\n }\r\n\r\n // Check for deletion hotkey -> Delete\r\n if (event.which === 46) {\r\n this.activeLabeler.deletePoint();\r\n }\r\n\r\n }\r\n else {\r\n // Check add new label in current category hotkey -> space\r\n if (event.which === 32 && (this.currentCategory)) {\r\n if (!this.currentCategory.visible) {\r\n return;\r\n }\r\n this.addLabel(this.currentCategory.id);\r\n return;\r\n }\r\n }\r\n\r\n }\r\n\r\n setActiveLabelType(type) {\r\n this.deleteAllCategories();\r\n this.orthoLabels.setState(false);\r\n this.sceneLabels.setState(false);\r\n this.viewer.minimap.setDragState(true);\r\n\r\n if (type === \"ortho\") {\r\n this.activeLabeler = this.orthoLabels;\r\n } else if (type === \"scene\") {\r\n this.activeLabeler = this.sceneLabels;\r\n } else {\r\n this.activeLabeler = null;\r\n return;\r\n }\r\n\r\n this.activeLabeler.setState(true);\r\n }\r\n\r\n activeImagePaths() {\r\n if (!this.activeLabeler) {\r\n return [];\r\n }\r\n\r\n return this.activeLabeler.activeImagePaths;\r\n }\r\n\r\n activeImages() {\r\n if (!this.activeLabeler) {\r\n return [];\r\n }\r\n\r\n return this.activeLabeler.activeImages;\r\n }\r\n\r\n loadedImagePaths() {\r\n if (!this.activeLabeler) {\r\n return [];\r\n }\r\n\r\n return this.activeLabeler.loadedImagePaths;\r\n }\r\n\r\n checkIfSelected() {\r\n if (!this.activeLabeler) {\r\n return false;\r\n }\r\n\r\n return this.activeLabeler.activeLabel\r\n ? true\r\n : false;\r\n }\r\n\r\n checkUniqueName(name) {\r\n const categoriesWithName = this.categories.filter(category => {\r\n return category.name.toUpperCase() === name.toUpperCase();\r\n });\r\n\r\n return (categoriesWithName.length === 0);\r\n }\r\n\r\n getCategoryByID(id) {\r\n if (this.trainingArea?.id === id) {\r\n return this.trainingArea;\r\n }\r\n\r\n return this.categories.find(x => x.id === id);\r\n }\r\n\r\n getCategoryByLabelID(labelID) {\r\n let chosenCategory;\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.id === labelID) {\r\n chosenCategory = category;\r\n }\r\n });\r\n });\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.id === labelID){\r\n chosenCategory = this.trainingArea;\r\n }\r\n });\r\n return chosenCategory;\r\n }\r\n\r\n getCategoryByName(name) {\r\n return this.categories.find(x => x.name === name);\r\n }\r\n\r\n setCategories() {\r\n if (!this.allowUpdate) {\r\n return;\r\n }\r\n\r\n // Sort categories based on name\r\n //this.categories.sort((a, b) => a.name.localeCompare(b.name));\r\n\r\n this.setCategoryList([...this.categories]);\r\n\r\n if (this.trainingArea) {\r\n this.setTrainingArea([this.trainingArea]);\r\n } else {\r\n this.setTrainingArea([]);\r\n }\r\n }\r\n\r\n sortCategory(category, score, sortType) {\r\n if (!this.activeLabeler) {\r\n return;\r\n }\r\n\r\n let categoryToSort = this.getCategoryByName(category.name);\r\n if (!categoryToSort) {\r\n return;\r\n }\r\n\r\n this.unHighlightAll();\r\n categoryToSort.unSelectAll();\r\n\r\n categoryToSort.sortLabels(score, sortType);\r\n this.setCategories();\r\n this.activeLabeler.drawAll();\r\n }\r\n\r\n undoSort(category) {\r\n if (!this.activeLabeler) {\r\n return;\r\n }\r\n\r\n let categoryToSort = this.getCategoryByName(category.name);\r\n if (!categoryToSort) {\r\n return;\r\n }\r\n\r\n this.unHighlightAll();\r\n categoryToSort.unSelectAll();\r\n\r\n categoryToSort.undoSort();\r\n this.setCategories();\r\n this.activeLabeler.drawAll();\r\n }\r\n\r\n addCategory(name, visible=true) {\r\n if (!this.activeLabeler) {\r\n return;\r\n }\r\n\r\n let category = this.activeLabeler.getNewCategory(name);\r\n category.setVisible(visible);\r\n this.categories.push(category);\r\n\r\n if (this.categories.length === 1) {\r\n this.currentCategory = category;\r\n }\r\n\r\n this.setCategories();\r\n\r\n return category;\r\n }\r\n\r\n addTrainingArea() {\r\n if (this.activeLabeler instanceof SceneLabelTools) {\r\n return;\r\n }\r\n\r\n if (this.trainingArea) {\r\n return;\r\n }\r\n\r\n let trainingArea = this.activeLabeler.getNewTrainingArea();\r\n this.activeLabeler.setTrainingArea(trainingArea);\r\n this.setCategories();\r\n\r\n return trainingArea;\r\n }\r\n\r\n deleteCategory(categoryID) {\r\n const category = this.getCategoryByID(categoryID);\r\n if (!category) {\r\n return;\r\n }\r\n\r\n category.labels.forEach(label => {\r\n label.destroy();\r\n });\r\n\r\n const index = this.categories.indexOf(category);\r\n this.categories.splice(index, 1);\r\n\r\n if (this.currentCategory === category) {\r\n this.currentCategory = this.categories[0];\r\n } else if (this.categories.length === 0) {\r\n this.currentCategory = null;\r\n }\r\n\r\n this.setCategories();\r\n }\r\n\r\n editCategoryName(categoryID, name) {\r\n const category = this.getCategoryByID(categoryID);\r\n if (!category) {\r\n return;\r\n }\r\n\r\n category.updateName(name);\r\n this.setCategories();\r\n }\r\n\r\n toggleCategoryVisibility(categoryID, state) {\r\n const category = this.getCategoryByID(categoryID);\r\n if (!category) {\r\n return;\r\n }\r\n\r\n category.toggleVisibility(state);\r\n this.setCategories();\r\n this.activeLabeler.drawAll();\r\n }\r\n\r\n deleteAllCategories() {\r\n let categories = [...this.categories];\r\n categories.forEach(category => {\r\n this.deleteCategory(category.id);\r\n });\r\n\r\n if (this.trainingArea) {\r\n this.deleteTrainingArea();\r\n }\r\n }\r\n\r\n deleteTrainingArea() {\r\n if (this.activeLabeler instanceof SceneLabelTools) {\r\n return;\r\n }\r\n\r\n this.activeLabeler.deleteTrainingArea();\r\n this.setCategories();\r\n }\r\n\r\n addTrainingAreaLabel(drawLabel=true) {\r\n if (this.activeLabeler instanceof SceneLabelTools) {\r\n return;\r\n }\r\n\r\n if (!this.trainingArea) {\r\n return;\r\n }\r\n\r\n const trainingArea = this.trainingArea;\r\n this.currentCategory = trainingArea;\r\n\r\n let label = trainingArea.addNewLabel(drawLabel);\r\n this.unSelectLabels();\r\n trainingArea.selectLabel(label.id);\r\n\r\n this.setCategories();\r\n\r\n return label;\r\n }\r\n\r\n addLabel(categoryID, drawLabel=null) {\r\n const category = this.getCategoryByID(categoryID);\r\n if (!category) {\r\n return;\r\n }\r\n this.currentCategory = category;\r\n\r\n if (drawLabel === null) {\r\n drawLabel = category.visible;\r\n }\r\n\r\n let label = category.addNewLabel(drawLabel);\r\n this.unSelectLabels();\r\n category.selectLabel(label.id);\r\n\r\n this.setCategories();\r\n\r\n return label;\r\n }\r\n\r\n editLabel(labelID, coord) {\r\n this.unHighlight(labelID);\r\n this.selectLabel(labelID);\r\n this.categories.forEach(category => {\r\n category.editLabel(labelID, coord);\r\n });\r\n }\r\n\r\n deleteLabel(labelID) {\r\n this.categories.forEach(category => {\r\n category.deleteLabel(labelID);\r\n });\r\n\r\n this.trainingArea?.deleteLabel(labelID);\r\n\r\n this.setCategories();\r\n this.clearTooltips();\r\n }\r\n\r\n transferLabel(labelIDs, newCategoryID) {\r\n const newCategory = this.getCategoryByID(newCategoryID);\r\n labelIDs.forEach(labelID => {\r\n const oldCategory = this.getCategoryByLabelID(labelID);\r\n if (oldCategory === newCategory) {\r\n return;\r\n }\r\n\r\n const label = oldCategory.getLabelByID(labelID);\r\n let newLabel;\r\n if (newCategory.id === this.trainingArea?.id) {\r\n newLabel = newCategory.addNewLabel(true);\r\n } else {\r\n newLabel = this.addLabel(newCategory.id, false);\r\n }\r\n\r\n newLabel.setScore(label.score);\r\n newLabel.setText(label.text, label.textScore);\r\n newLabel.setFindText(label.findText);\r\n newLabel.setIsThing(label.isThing);\r\n\r\n if (this.activeLabeler instanceof SceneLabelTools){\r\n label.coordinates.forEach(coordinate => {\r\n newLabel.addPoint(coordinate.pixel);\r\n });\r\n } else if (this.activeLabeler instanceof AerialLabelTools) {\r\n label.coordinates.forEach(coordinate => {\r\n newLabel.addPoint(coordinate.point);\r\n });\r\n }\r\n\r\n newLabel.complete();\r\n oldCategory.deleteLabel(labelID);\r\n newLabel.selected = false;\r\n });\r\n this.activeLabeler.drawAll();\r\n this.setCategories();\r\n }\r\n\r\n deletePoint(pointID) {\r\n this.activeLabeler.deleteSpecificPoint(pointID);\r\n }\r\n\r\n insertPoint(labelID, coord) {\r\n this.unHighlight(labelID);\r\n this.categories.forEach(category => {\r\n category.insertPoint(labelID, coord);\r\n });\r\n }\r\n\r\n setText(labelID, text, score=1.0) {\r\n this.categories.forEach(category => {\r\n category.setText(labelID, text, score);\r\n });\r\n }\r\n\r\n async zoomToLabel(labelID) {\r\n this.unHighlightAll();\r\n\r\n for (const category of this.categories) {\r\n await category.zoomToLabel(labelID);\r\n };\r\n\r\n await this.trainingArea?.zoomToLabel(labelID);\r\n this.setCategories();\r\n }\r\n\r\n unHighlight(labelID) {\r\n this.categories.forEach(category => {\r\n category.unHighlight(labelID);\r\n });\r\n\r\n this.trainingArea?.unHighlight(labelID);\r\n this.setCategories();\r\n }\r\n\r\n unHighlightAll() {\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.highlighted) {\r\n category.unHighlight(label.id);\r\n }\r\n });\r\n });\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.highlighted) {\r\n this.trainingArea.unHighlight(label.id);\r\n }\r\n });\r\n\r\n this.setCategories();\r\n }\r\n\r\n deleteHighlighted() {\r\n this.categories.forEach(category => {\r\n let labelIDs = [];\r\n category.labels.forEach(label => {\r\n if (label.highlighted) {\r\n labelIDs.push(label.id);\r\n }\r\n });\r\n category.deleteLabels(labelIDs);\r\n });\r\n\r\n let labelIDs = [];\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.highlighted) {\r\n labelIDs.push(label.id);\r\n }\r\n });\r\n this.trainingArea?.deleteLabels(labelIDs);\r\n\r\n this.setCategories();\r\n }\r\n\r\n completeLabel(labelID) {\r\n let success = false;\r\n let label = this.activeLabeler.activeLabel;\r\n\r\n this.categories.forEach(category => {\r\n success = success || category.completeLabel(labelID);\r\n });\r\n\r\n const isTrainingArea = this.trainingArea\r\n ? this.trainingArea.completeLabel(labelID)\r\n : false;\r\n\r\n success = success || isTrainingArea;\r\n\r\n this.setCategories();\r\n this.clearTooltips();\r\n\r\n if (!success || !label) {\r\n return;\r\n }\r\n\r\n if (isTrainingArea) {\r\n toast.success(t(\"toast.labels-add-training\"));\r\n } else {\r\n if (label.editing) {\r\n toast.success(t(\"toast.labels-update\"));\r\n } else {\r\n toast.success(t(\"toast.labels-add-standard\"));\r\n }\r\n }\r\n\r\n label.setEditing(false);\r\n }\r\n\r\n selectLabel(labelID) {\r\n this.unSelectLabels();\r\n this.categories.forEach(category => {\r\n category.unHighlight(labelID);\r\n category.selectLabel(labelID);\r\n });\r\n\r\n this.trainingArea?.unHighlight(labelID);\r\n this.trainingArea?.selectLabel(labelID);\r\n\r\n this.activeLabeler.resetTemporaryPoint();\r\n this.setCategories();\r\n }\r\n\r\n unSelectLabels() {\r\n this.categories.forEach(category => {\r\n category.unSelectAll();\r\n });\r\n\r\n this.trainingArea?.unSelectAll();\r\n }\r\n\r\n moveToLabelInList(labelID) {\r\n this.categories.forEach(category => {\r\n category.moveToLabelInList(labelID);\r\n });\r\n\r\n this.setCategories();\r\n }\r\n\r\n simplifyPolygon(points, tolerance=2, highQuality=false) {\r\n let simplePolygon;\r\n try {\r\n let newPoints = [...points, points[0]];\r\n let polygon = turfPolygon([newPoints]);\r\n let options = {tolerance, highQuality};\r\n let simplified = turfSimplify(polygon, options);\r\n simplePolygon = simplified.geometry.coordinates[0];\r\n // simplePolygon.pop();\r\n } catch {\r\n simplePolygon = [];\r\n }\r\n\r\n // console.log(`Simplify geometry: ${newPoints.length} => ${simplePolygon.length}`);\r\n\r\n return simplePolygon;\r\n }\r\n\r\n mergeTrainingLabels(category, labelsToMerge) {\r\n let maxPointDistance = 0.5;\r\n let mergedLabels = new Set();\r\n\r\n labelsToMerge.forEach((firstLabel, index) => {\r\n if (mergedLabels.has(firstLabel.id)) {\r\n return;\r\n }\r\n\r\n const isPlanarImage = firstLabel.camera instanceof PlanarImage;\r\n const isPanoramicImage = firstLabel.camera instanceof PanoramicImage;\r\n\r\n // Not required for planar images\r\n if (isPlanarImage) {\r\n return;\r\n }\r\n\r\n let mergeableArray = labelsToMerge.slice(index + 1);\r\n mergeableArray.forEach(mergeLabel => {\r\n if (mergedLabels.has(mergeLabel.id)) {\r\n return;\r\n }\r\n\r\n if (firstLabel.camera !== mergeLabel.camera) {\r\n return;\r\n }\r\n\r\n let points1 = [...firstLabel.coords];\r\n let points2 = [...mergeLabel.coords];\r\n\r\n if (isPanoramicImage) {\r\n // Add image offset\r\n let width = firstLabel.imageWidth;\r\n points1 = points1.map(x => [(x[0]+(width/2)) % width, x[1]]);\r\n points2 = points2.map(x => [(x[0]+(width/2)) % width, x[1]]);\r\n }\r\n\r\n let matches = [];\r\n points1.forEach((point1, index1) => {\r\n let matchFound = false;\r\n points2.forEach((point2, index2) => {\r\n if (matchFound) {\r\n return;\r\n }\r\n\r\n let dist = new Vector2(...point1)\r\n .distanceTo(new Vector2(...point2));\r\n\r\n if (dist < maxPointDistance) {\r\n matchFound = true;\r\n matches.push({point1, point2, dist, index1, index2});\r\n }\r\n });\r\n });\r\n\r\n if (matches.length === 0) {\r\n return;\r\n }\r\n\r\n // Take the two best matches and update\r\n // the original point to match the second\r\n matches.sort((a,b) => a.dist - b.dist);\r\n matches = matches.slice(0,2);\r\n matches.forEach(data => {\r\n points1[data.index1] = data.point2;\r\n });\r\n\r\n let polygonPoints1 = [...points1, points1[0]];\r\n let polygonPoints2 = [...points2, points2[0]];\r\n\r\n // Checks for polygon length, otherwise turfUnion crashes app with error\r\n if (polygonPoints1.length < 4) {\r\n return;\r\n }\r\n\r\n if (polygonPoints2.length < 4) {\r\n return;\r\n }\r\n let union;\r\n try {\r\n union = turfUnion(\r\n turfPolygon([polygonPoints1]),\r\n turfPolygon([polygonPoints2]));\r\n } catch {\r\n console.warn('turf union failed...');\r\n return;\r\n }\r\n\r\n if (!union) {\r\n return;\r\n }\r\n\r\n // Union must have a single geometry\r\n if (union.geometry.type !== \"Polygon\") {\r\n return;\r\n }\r\n\r\n let coordinates = union.geometry.coordinates[0] as any;\r\n coordinates.pop(0);\r\n\r\n // Remove any duplicates from merged result\r\n coordinates = coordinates.filter(point1 => {\r\n let duplicate = false;\r\n matches.forEach(data => {\r\n let point2 = data.point2;\r\n let d = new Vector2(...point1)\r\n .distanceTo(new Vector2(...point2));\r\n\r\n if (d < maxPointDistance) {\r\n duplicate = true;\r\n }\r\n });\r\n\r\n return !duplicate;\r\n });\r\n\r\n if (isPanoramicImage) {\r\n // Subtract image offset and convert to pixel\r\n let width = firstLabel.imageWidth;\r\n coordinates = coordinates.map(coord => {\r\n return {\r\n u: (coord[0] - (width/2)) % width,\r\n v: coord[1]\r\n };\r\n });\r\n }\r\n\r\n // Delete second label\r\n category.deleteLabel(mergeLabel.id);\r\n\r\n // Add points to first label\r\n firstLabel.coordinates = [];\r\n coordinates.forEach(coord => {\r\n firstLabel.addPoint(coord, false);\r\n });\r\n category.completeLabel(firstLabel.id);\r\n mergedLabels.add(mergeLabel.id);\r\n });\r\n });\r\n\r\n const remainingLabels = labelsToMerge.filter(label => {\r\n return mergedLabels.has(label.id) === false;\r\n });\r\n\r\n const numLabelMerged = mergedLabels.size;\r\n\r\n if (numLabelMerged > 0) {\r\n this.mergeTrainingLabels(category, remainingLabels);\r\n }\r\n }\r\n\r\n simplifyPanoramicLabels(category) {\r\n // Simplify new labels (panoramic)\r\n category.labels.forEach(label => {\r\n const isPanoramicImage = label.camera instanceof PanoramicImage;\r\n if (!isPanoramicImage) {\r\n return;\r\n }\r\n\r\n let coordinates = [...label.coords];\r\n coordinates = this.simplifyPolygon(coordinates);\r\n\r\n // Subtract image offset and convert to pixel\r\n let width = label.imageWidth;\r\n coordinates = coordinates.map(coord => {\r\n return {\r\n u: (coord[0] + width) % width,\r\n v: coord[1]\r\n };\r\n });\r\n\r\n label.coordinates = [];\r\n coordinates.forEach(coord => {\r\n label.addPoint(coord, false);\r\n });\r\n label.complete();\r\n });\r\n }\r\n\r\n /** @private */\r\n geometryWithBuffer(geom, bufferSize: number, divisor: number) {\r\n const JSTSReader = new GeoJSONReader();\r\n const geomJSTS = JSTSReader.read(geom);\r\n const buffer = BufferOp.bufferOp(geomJSTS.geometry, bufferSize);\r\n const points = buffer.getCoordinates().map(coord => [coord.x, coord.y]);\r\n const simplified = this.simplifyPolygon(points, bufferSize/divisor);\r\n\r\n return simplified;\r\n }\r\n\r\n /** @private */\r\n checkForImageOverlap(label) {\r\n let hasOverlap = false;\r\n this.orthoLabels.visibleOrthos.forEach(ortho => {\r\n if (hasOverlap) {\r\n return;\r\n }\r\n\r\n let intersects = ortho.intersectAerialPoints(label.polygonPointsOnly);\r\n if (intersects) {\r\n hasOverlap = true;\r\n }\r\n });\r\n\r\n return hasOverlap;\r\n }\r\n\r\n /** @private */\r\n importLabel(label, category, images, projection, progressData, isTrainingArea) {\r\n let addedLabel;\r\n let cameras = this.viewer.cameraHandler;\r\n\r\n // Add new label\r\n let imageData = images[label.image_id];\r\n label.segmentation.forEach(points => {\r\n // Convert points to 2d array and simplify geometry\r\n points = coordinatesToArray(points);\r\n\r\n // Make sure enough points exist\r\n let minPoints = 3;\r\n if (label.is_linestring) {\r\n minPoints = 2;\r\n } else if (label.is_point) {\r\n minPoints = 1;\r\n }\r\n\r\n if (points.length < minPoints) {\r\n progressData.skippedLabels += 1;\r\n return;\r\n }\r\n\r\n if (this.activeLabeler instanceof AerialLabelTools) {\r\n\r\n if (label.is_linestring) {\r\n // Convert linestring to buffered polygon\r\n let lineGeom = turfLineString(points);\r\n points = this.geometryWithBuffer(lineGeom, label.buffer_size, 4);\r\n } else if (label.is_point) {\r\n let pointGeom = turfPoint(points[0]);\r\n points = this.geometryWithBuffer(pointGeom, label.buffer_size, 8);\r\n }\r\n\r\n // Create simplified version of polygon.\r\n if (!label.linework_data) {\r\n points = this.simplifyPolygon(points);\r\n }\r\n\r\n // Convert from image space to map coordinates\r\n points = imagePixelsToAerial(points, imageData, projection);\r\n } else if (this.activeLabeler instanceof SceneLabelTools) {\r\n // Planar images cant be immediately simplified\r\n let camera = cameras.getCameraByName(imageData.file_name);\r\n if (camera && (camera instanceof PlanarImage)) {\r\n points = this.simplifyPolygon(points);\r\n }\r\n\r\n points = this.activeLabeler.pointsToPixels(points);\r\n }\r\n\r\n // Make sure enough points exist after simplification / pixel function\r\n if (points.length < 3) {\r\n progressData.skippedLabels += 1;\r\n return;\r\n }\r\n\r\n // Create label\r\n let newLabel = isTrainingArea\r\n ? this.addTrainingAreaLabel(false)\r\n : this.addLabel(category.id, false);\r\n\r\n newLabel.setScore(label.score);\r\n newLabel.setText(label.text, label.textScore);\r\n newLabel.setFindText(label.findText);\r\n newLabel.setIsThing(label.isThing);\r\n\r\n if (this.activeLabeler instanceof SceneLabelTools) {\r\n // Camera is required for scene tools\r\n\r\n let camera = cameras.getCameraByName(imageData.file_name);\r\n\r\n if (camera) {\r\n // Set camera label\r\n newLabel.setCamera(camera);\r\n newLabel.setKnownImageSize(\r\n imageData.width,\r\n imageData.height\r\n );\r\n } else {\r\n // Delete label and continue\r\n progressData.skippedLabels += 1;\r\n this.deleteLabel(newLabel.id);\r\n return;\r\n }\r\n }\r\n\r\n // Add points to new label\r\n points.forEach(point => {\r\n newLabel.addPoint(point, false);\r\n });\r\n\r\n newLabel.complete();\r\n addedLabel = newLabel;\r\n });\r\n\r\n return addedLabel;\r\n }\r\n\r\n async addCategoryLabels(labels, category, images, projection, progressData, isTrainingArea) {\r\n let labelsToMerge = {};\r\n\r\n for (let label of labels) {\r\n // Add new label from data\r\n let addedLabel = this.importLabel(label, category, images,\r\n projection, progressData, isTrainingArea);\r\n if (!addedLabel) continue;\r\n\r\n // Update loading progress\r\n const {labelTotal, labelIndex} = progressData;\r\n const percent = 100 * (labelIndex+1)/labelTotal;\r\n progressData.progress = Math.min(100, percent);\r\n progressData.labelIndex += 1;\r\n\r\n // Asynchronous timeout to stop ui from freezing\r\n if (labelIndex % 10 === 0) {\r\n progressData.callback(progressData.progress);\r\n await asyncTimeout(10.0);\r\n }\r\n\r\n const mergeID = label.merge_id;\r\n if (!addedLabel || !mergeID) continue;\r\n\r\n let previous = labelsToMerge[mergeID];\r\n labelsToMerge[mergeID] = previous\r\n ? [...previous, addedLabel]\r\n : [addedLabel];\r\n }\r\n\r\n return Object.keys(labelsToMerge)\r\n .map(x => labelsToMerge[x]);\r\n }\r\n\r\n /** @private */\r\n checkLabelOverlap(newCategory, checkOverlap, progressData) {\r\n if (!checkOverlap) {\r\n return;\r\n }\r\n\r\n [...newCategory.labels].forEach(label => {\r\n let hasOverlap = this.checkForImageOverlap(label);\r\n if (!hasOverlap) {\r\n progressData.skippedLabels += 1;\r\n newCategory.deleteLabel(label.id);\r\n }\r\n });\r\n }\r\n\r\n /** @private */\r\n checkLabelInvalid(newCategory, progressData) {\r\n [...newCategory.labels].forEach(label => {\r\n if (!label.hasEnoughPoints) {\r\n progressData.skippedLabels += 1;\r\n newCategory.deleteLabel(label.id);\r\n };\r\n });\r\n }\r\n\r\n private clearTooltips() {\r\n clearAerialTooltip();\r\n clearViewerTooltip();\r\n }\r\n\r\n async loadImageLabelData(data, progressCallback, overwrite, checkOverlap) {\r\n if (overwrite) {\r\n this.deleteAllCategories();\r\n }\r\n\r\n let projection = data.projection;\r\n let categories = data.categories;\r\n let labels = data.annotations;\r\n let hasTrainingArea = data.hasOwnProperty('trainingAreas');\r\n\r\n // Check for valid projection string\r\n let validProjection = isValidProjection(projection.string);\r\n if (!validProjection) {\r\n toast.error(t(\"toast.labels-invalid-projection\"));\r\n return;\r\n }\r\n\r\n let images = {};\r\n data.images.forEach(image => {\r\n images[image.id] = image;\r\n });\r\n\r\n // Calculate total combined labels\r\n let numLabelsTotal = 0;\r\n data.annotations.forEach(label => {\r\n numLabelsTotal += label.segmentation.length;\r\n });\r\n\r\n let progressData = {\r\n progress: 0,\r\n labelTotal: numLabelsTotal,\r\n labelIndex: 0,\r\n skippedLabels: 0,\r\n callback: progressCallback\r\n };\r\n\r\n // Stop category UI update\r\n this.setUpdateState(false);\r\n\r\n if (hasTrainingArea) {\r\n let trainingAreaCategory = this.addTrainingArea();\r\n\r\n let areasToMerge = await this.addCategoryLabels(\r\n data.trainingAreas, trainingAreaCategory, images,\r\n projection, progressData, true);\r\n\r\n // Merge training data was previously connected\r\n areasToMerge.forEach(mergeList => {\r\n this.mergeTrainingLabels(trainingAreaCategory, mergeList);\r\n });\r\n\r\n // Complete all labels\r\n trainingAreaCategory.labels.forEach(label => {\r\n trainingAreaCategory.completeLabel(label.id);\r\n });\r\n }\r\n\r\n for (let category of categories) {\r\n let newLabels = labels.filter(x => x.category_id === category.id);\r\n\r\n let currentCategory = this.getCategoryByName(category.name);\r\n const categoryVisible = (\"visible\" in category) ? category.visible : true;\r\n\r\n // Add new category (existing or current)\r\n let newCategory = currentCategory\r\n ? currentCategory\r\n : this.addCategory(category.name, categoryVisible);\r\n\r\n let labelsToMerge = await this.addCategoryLabels(\r\n newLabels, newCategory, images, projection,\r\n progressData, false\r\n );\r\n\r\n // Merge training data that was previously connected\r\n labelsToMerge.forEach(mergeList => {\r\n this.mergeTrainingLabels(newCategory, mergeList);\r\n });\r\n\r\n // Check for overlap between label and image\r\n this.checkLabelOverlap(newCategory, checkOverlap, progressData);\r\n\r\n // Simplify panoramic labels\r\n this.simplifyPanoramicLabels(newCategory);\r\n\r\n // Remove any labels that are invalid now\r\n this.checkLabelInvalid(newCategory, progressData);\r\n\r\n // Complete all labels\r\n newCategory.labels.forEach(label => {\r\n newCategory.completeLabel(label.id);\r\n });\r\n\r\n // Remove category if nothing is left\r\n if (newCategory.labels.length === 0) {\r\n console.log(`Delete empty category: ${newCategory.name}`);\r\n this.deleteCategory(newCategory.id);\r\n } else {\r\n console.log(`Import labels for category: ${newCategory.name}`);\r\n }\r\n }\r\n\r\n // assign labels drawability based on category\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n label.setDrawable(category.visible);\r\n });\r\n });\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n label.setDrawable(true);\r\n });\r\n\r\n // Draw all new labels\r\n this.activeLabeler.drawAll();\r\n\r\n // Categories can be updated in UI\r\n this.setUpdateState(true);\r\n\r\n if (progressData.skippedLabels > 0) {\r\n toast.error(t(\"toast.labels-skipped-import\", {\r\n count: progressData.skippedLabels\r\n }));\r\n }\r\n\r\n setTimeout(() => {\r\n this.setCategories();\r\n this.clearTooltips();\r\n progressCallback(0);\r\n }, 500);\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n this.sceneLabels.update(changeDetector);\r\n }\r\n\r\n labelObject() {\r\n let categories = this.categories.map((category, categoryID) => {\r\n let [r, g, b] = textToColorArray(category.name, 0);\r\n let color = [r, g, b];\r\n\r\n return {\r\n supercategory: category.name,\r\n id: categoryID,\r\n visible: category.visible,\r\n name: category.name,\r\n color: color\r\n } as CocoCategory;\r\n });\r\n\r\n let annotations = this.activeLabeler.getLabelAnnotations();\r\n let trainingAreas = this.activeLabeler.getTrainingAnnotations();\r\n\r\n let jsonObj = {\r\n type: this.activeLabeler.type,\r\n categories: categories,\r\n projection: LocalScene.dataProjection,\r\n images: this.activeLabeler.jsonImageObj(),\r\n annotations: annotations,\r\n ...(trainingAreas.length > 0 && {trainingAreas}),\r\n };\r\n\r\n return jsonObj;\r\n }\r\n}\r\n\r\nexport const sectionsFromIntersection = (intersection, removeDuplicate=true) => {\r\n let sections = [];\r\n\r\n if (!intersection) {\r\n return sections;\r\n }\r\n\r\n let geometry = intersection.geometry;\r\n geometry.coordinates.forEach(result => {\r\n let intersectPoints = [...result];\r\n\r\n if (geometry.type === \"MultiPolygon\") {\r\n intersectPoints = intersectPoints[0];\r\n }\r\n\r\n if (removeDuplicate) {\r\n intersectPoints.pop();\r\n }\r\n\r\n sections.push(intersectPoints);\r\n });\r\n\r\n return sections;\r\n};\r\n\r\nexport const annotationFromPolygon = (polygon, labelIndex, categoryID, imageID, mergeID, score=1.0, text='', textScore=0.0, findText=false) => {\r\n let segment = [...polygon].flat();\r\n let allX = polygon.map(x => x[0]);\r\n let allY = polygon.map(x => x[1]);\r\n\r\n let boundBox = [\r\n Math.min(...allX),\r\n Math.min(...allY),\r\n Math.max(...allX) - Math.min(...allX),\r\n Math.max(...allY) - Math.min(...allY)\r\n ].map(x => Math.round(x));\r\n\r\n let area = areaFromPolygon(polygon);\r\n let findTextNum = findText ? 1 : 0;\r\n\r\n let annotation = {\r\n segmentation: [segment],\r\n iscrowd: 0,\r\n image_id: imageID,\r\n bbox: boundBox,\r\n category_id: categoryID,\r\n id: labelIndex,\r\n area: area,\r\n score:score,\r\n text: text,\r\n textScore:textScore,\r\n findText: findTextNum\r\n } as CocoAnnotation;\r\n\r\n if (mergeID !== null) {\r\n annotation.merge_id = mergeID;\r\n }\r\n\r\n return annotation;\r\n};\r\n\r\nexport const areaFromPolygon = (polygon) => {\r\n let contour = polygon.map(x => new Vector2(...x));\r\n return Math.abs(ShapeUtils.area(contour));\r\n};\r\n\r\nconst minDistanceIdx = (coordArray, point) => {\r\n let shortestDistance = Infinity;\r\n let closestPoint = new Vector3();\r\n let idxCoord;\r\n\r\n for (let idx = 0; idx < coordArray.length; idx++) {\r\n let endIdx = (idx === coordArray.length - 1) ? 0 : idx + 1;\r\n let lineSegment = createSegment(coordArray[idx], coordArray[endIdx]);\r\n lineSegment.closestPointToPoint(point, true, closestPoint);\r\n let distance = point.distanceTo(closestPoint);\r\n if (Math.abs(distance) < Math.abs(shortestDistance)) {\r\n shortestDistance = distance;\r\n idxCoord = idx;\r\n }\r\n }\r\n\r\n return idxCoord;\r\n};\r\n\r\nconst createSegment = (P1, P2) => {\r\n let startPoint = new Vector3(P1[0], P1[1]);\r\n let endPoint = new Vector3(P2[0], P2[1]);\r\n return new Line3(startPoint, endPoint);\r\n};","import 'ol/ol.css';\r\nimport {Vector as VectorSource} from \"ol/source\";\r\nimport {Vector as VectorLayer} from \"ol/layer\";\r\nimport VectorImageLayer from 'ol/layer/VectorImage';\r\nimport {Point, Polygon} from \"ol/geom\";\r\nimport {Feature, MapBrowserEvent} from \"ol\";\r\nimport {\r\n Circle as CircleStyle,\r\n Fill, Stroke, Style\r\n} from \"ol/style\";\r\nimport { checkValidPolygon } from \"../utilities\";\r\nimport {\r\n annotationFromPolygon,\r\n CocoImage,\r\n ImageLabel,\r\n ImageLabelTools,\r\n LabelCategory,\r\n sectionsFromIntersection,\r\n textToColor\r\n} from '.';\r\nimport {Color, Vector3} from 'three';\r\nimport {polygon as turfPolygon} from '@turf/helpers';\r\nimport {default as turfIntersect} from '@turf/intersect';\r\nimport {\r\n OrthoMosaic,\r\n AerialMap,\r\n extentFromPoints\r\n} from '../aerial';\r\nimport { LabelContextData, showContextMenu } from '../../context-menu';\r\nimport { CustomMouseEvent } from '../controls';\r\nimport { clearAerialTooltip, setAerialTooltip } from '../viewer';\r\nimport { t } from '../../localization';\r\n\r\nconst pointRadius = 5.0;\r\nconst pointStrokeWidth = 1.0;\r\n\r\nclass LabelPoint extends Feature {\r\n public label: OrthoLabel;\r\n public index;\r\n\r\n constructor(opts, label, index) {\r\n super(opts);\r\n this.label = label;\r\n this.index = index;\r\n }\r\n}\r\n\r\nclass LabelPolygon extends Feature {\r\n public label: OrthoLabel;\r\n\r\n constructor(opts, label) {\r\n super(opts);\r\n this.label = label;\r\n }\r\n}\r\n\r\nclass Coordinate {\r\n public array = [];\r\n\r\n constructor(coordinates) {\r\n this.array = coordinates;\r\n }\r\n\r\n get x() {\r\n return this.array[0];\r\n }\r\n\r\n get y() {\r\n return this.array[1];\r\n }\r\n\r\n get point() {\r\n return this.array;\r\n }\r\n\r\n update(point) {\r\n if (point.length === 2) {\r\n this.array = point;\r\n }\r\n }\r\n}\r\n\r\nexport class OrthoLabel extends ImageLabel {\r\n public features = [];\r\n public category: OrthoCategory\r\n public coordinates: Coordinate[] = [];\r\n public aerialMap: AerialMap;\r\n private minCoordinates = 3;\r\n private styleCache = {};\r\n\r\n constructor(category: OrthoCategory, aerialMap: AerialMap) {\r\n super();\r\n this.category = category;\r\n this.aerialMap = aerialMap;\r\n }\r\n\r\n get hasEnoughPoints() {\r\n return this.numPoints >= this.minCoordinates;\r\n }\r\n\r\n get numPoints() {\r\n return this.coordinates.length;\r\n }\r\n\r\n get coords() {\r\n /** Used for polygon simplification */\r\n return this.coordinates.map(x => x.point);\r\n }\r\n\r\n get polygonPointsOnly() {\r\n return this.coordinates.map(x => x.point);\r\n }\r\n\r\n get isValid() {\r\n return checkValidPolygon(this.polygonPointsOnly);\r\n }\r\n\r\n get map() {\r\n return this.aerialMap.map;\r\n }\r\n\r\n get completedSource() {\r\n return this.category.featuresLayer.getSource();\r\n }\r\n\r\n get editingSource() {\r\n return this.category.editingLayer.getSource();\r\n }\r\n\r\n get featureStyle() {\r\n return this.getLayerFromCache(true);\r\n }\r\n\r\n get editingStyle() {\r\n return this.getLayerFromCache(false);\r\n }\r\n\r\n clearStyleCache() {\r\n this.styleCache = {};\r\n }\r\n\r\n setFeatureStyle() {\r\n this.features.forEach(feature => {\r\n if (this.completed) {\r\n feature.setStyle(this.featureStyle);\r\n } else {\r\n feature.setStyle(this.editingStyle);\r\n }\r\n });\r\n }\r\n\r\n getLayerFromCache(checkDefaultStyle) {\r\n if (checkDefaultStyle) {\r\n let defaults = this.category.defaultStyleParams;\r\n let isDefaultStyle = (this.valid === defaults[0])\r\n && (this.completed === defaults[1])\r\n && (this.highlighted === defaults[2]);\r\n\r\n if (isDefaultStyle) {\r\n return null;\r\n }\r\n }\r\n\r\n let styleKey = `${this.valid}-${this.completed}-${this.highlighted}`;\r\n\r\n if (!this.styleCache[styleKey]) {\r\n this.styleCache[styleKey] = this.category.getLayerStyle(\r\n this.valid, this.completed, this.highlighted);\r\n }\r\n\r\n return this.styleCache[styleKey];\r\n }\r\n\r\n updatePoint(point, index) {\r\n this.coordinates[index].update(point);\r\n }\r\n\r\n removePoint() {\r\n this.coordinates.pop();\r\n }\r\n\r\n removeSpecificPoint(index) {\r\n this.coordinates.splice(index, 1);\r\n this.draw();\r\n }\r\n\r\n toScreenPosition(point) {\r\n return this.map.getPixelFromCoordinate(point.point);\r\n }\r\n\r\n createCoordData(coordinate) {\r\n const point = new Vector3(coordinate[0], coordinate[1]);\r\n const coordArray = this.coordinates.map(coord => {\r\n return coord.array;\r\n });\r\n\r\n return {coordArray, point};\r\n }\r\n\r\n addPoint(point, checkDuplicate=true) {\r\n const newPoint = new Coordinate(point);\r\n const oldPoint = this.coordinates[this.coordinates.length - 1];\r\n\r\n if (checkDuplicate && this.duplicatePoint(oldPoint, newPoint)) {\r\n return true;\r\n }\r\n\r\n this.coordinates.push(newPoint);\r\n return false;\r\n }\r\n\r\n insertPoint(newPoint, idxCoord) {\r\n let newCoord = new Coordinate(newPoint.toArray());\r\n this.coordinates.splice(idxCoord+1, 0, newCoord);\r\n this.draw();\r\n }\r\n\r\n drawPoints(temporaryPoint) {\r\n let positions = this.coordinates;\r\n if (temporaryPoint && !this.completed) {\r\n positions = [...positions, temporaryPoint];\r\n }\r\n\r\n positions.forEach((point, index) => {\r\n const feature = new LabelPoint({\r\n geometry: new Point([point.x, point.y])\r\n }, this, index);\r\n\r\n this.features.push(feature);\r\n\r\n let source = this.completed\r\n ? this.completedSource\r\n : this.editingSource;\r\n\r\n source.addFeature(feature);\r\n });\r\n }\r\n\r\n drawPolygon(temporaryPoint) {\r\n let positions = this.polygonPointsOnly;\r\n if (temporaryPoint && !this.completed) {\r\n positions = [...positions, temporaryPoint.point];\r\n }\r\n\r\n if (this.hasEnoughPoints){\r\n let validPolygon = checkValidPolygon(positions);\r\n if (this.valid !== validPolygon) {\r\n this.valid = validPolygon;\r\n this.category.setCategories();\r\n }\r\n }\r\n\r\n let feature = new LabelPolygon({\r\n geometry: new Polygon([positions])\r\n }, this);\r\n\r\n this.features.push(feature);\r\n\r\n let source = this.completed\r\n ? this.completedSource\r\n : this.editingSource;\r\n\r\n source.addFeature(feature);\r\n }\r\n\r\n draw(temporaryPoint=null, visible=true) {\r\n this.clear();\r\n if (!this.drawable) {\r\n return;\r\n }\r\n\r\n this.clear();\r\n if (visible) {\r\n this.drawPoints(temporaryPoint);\r\n this.drawPolygon(temporaryPoint);\r\n this.setFeatureStyle();\r\n }\r\n }\r\n\r\n clear() {\r\n const sources = [\r\n this.completedSource,\r\n this.editingSource\r\n ];\r\n\r\n this.features.forEach(x => {\r\n sources.forEach(source => {\r\n if (source.hasFeature(x)) {\r\n source.removeFeature(x);\r\n }\r\n });\r\n });\r\n\r\n this.features = [];\r\n }\r\n\r\n zoom(): Promise {\r\n let positions = [...this.polygonPointsOnly];\r\n let extent = extentFromPoints(positions, false);\r\n this.aerialMap.setMapExtent(extent);\r\n return Promise.resolve(true);\r\n }\r\n\r\n setHighlighted(highlight) {\r\n if (highlight === this.highlighted) {\r\n return;\r\n }\r\n\r\n this.highlighted = highlight;\r\n this.draw();\r\n }\r\n}\r\n\r\nexport class OrthoCategory extends LabelCategory {\r\n private aerialTools: AerialLabelTools;\r\n public labels: OrthoLabel[] = [];\r\n public featuresLayer: VectorImageLayer;\r\n public editingLayer: VectorLayer;\r\n\r\n constructor(aerialTools: AerialLabelTools, name) {\r\n super(name);\r\n this.aerialTools = aerialTools;\r\n this.addMapLayers();\r\n }\r\n\r\n get aerialMap() {\r\n return this.aerialTools.aerialMap;\r\n }\r\n\r\n get map() {\r\n return this.aerialMap.map;\r\n }\r\n\r\n get defaultStyleParams() {\r\n // valid, completed, higlighted\r\n return [true, true, false];\r\n }\r\n\r\n darkenedColor(highlighted) {\r\n let pointColor = this.categoryColor(highlighted, 1.0);\r\n let dark = new Color(pointColor)\r\n .multiplyScalar(0.75);\r\n\r\n return `rgb(${dark.r*256}, ${dark.g*256}, ${dark.b*256})`;\r\n }\r\n\r\n categoryColor(highlighted=false, opacity=0.2) {\r\n if (highlighted) {\r\n return `rgba(${255}, ${255}, ${255}, ${opacity})`;\r\n }\r\n\r\n if (this instanceof TrainingAreaCategory){\r\n return `rgba(${0}, ${0}, ${0}, ${opacity})`;\r\n }\r\n\r\n return textToColor(this.name, opacity);\r\n }\r\n\r\n getLayerStyle(valid=true, completed=true, highlighted=false) {\r\n let opacity = valid ? 0.2 : 0.0;\r\n if (this instanceof TrainingAreaCategory) {\r\n opacity = 0.0;\r\n }\r\n\r\n return new Style({\r\n fill: new Fill({\r\n color: this.categoryColor(highlighted, opacity)\r\n }),\r\n stroke: new Stroke({\r\n lineDash: completed ? undefined : [10, 10],\r\n color: this.darkenedColor(highlighted),\r\n width: 2\r\n }),\r\n image: new CircleStyle({\r\n radius: pointRadius,\r\n stroke: new Stroke({\r\n width: pointStrokeWidth,\r\n color: 'rgba(0, 0, 0, 1.0)'\r\n }),\r\n fill: new Fill({\r\n color: this.categoryColor(highlighted, 0.8)\r\n }),\r\n })\r\n });\r\n }\r\n\r\n addMapLayers() {\r\n this.featuresLayer = new VectorImageLayer({\r\n zIndex: 1,\r\n source: new VectorSource({\r\n features: [],\r\n wrapX: false\r\n }),\r\n style: this.getLayerStyle()\r\n });\r\n\r\n this.map.addLayer(this.featuresLayer);\r\n\r\n this.editingLayer = new VectorLayer({\r\n zIndex: 1,\r\n source: new VectorSource({\r\n features: [],\r\n wrapX: false\r\n }),\r\n style: this.getLayerStyle(),\r\n updateWhileInteracting: false,\r\n updateWhileAnimating: false\r\n });\r\n\r\n this.map.addLayer(this.editingLayer);\r\n }\r\n\r\n setCategories() {\r\n this.aerialTools.imageLabelTools.setCategories();\r\n }\r\n\r\n updateColor() {\r\n this.featuresLayer.setStyle(this.getLayerStyle());\r\n this.editingLayer.setStyle(this.getLayerStyle());\r\n\r\n this.labels.forEach(label => {\r\n label.clearStyleCache();\r\n label.setFeatureStyle();\r\n });\r\n }\r\n\r\n addNewLabel(drawLabel) {\r\n let label = new OrthoLabel(this, this.aerialMap);\r\n label.setDrawable(this.visible);\r\n this.labels.push(label);\r\n\r\n return label;\r\n }\r\n}\r\n\r\nexport class TrainingAreaLabel extends OrthoLabel {\r\n constructor(category: OrthoCategory, aerialMap: AerialMap) {\r\n super(category, aerialMap);\r\n }\r\n\r\n polygonsInsideImage(image: OrthoMosaic) {\r\n // Find the part of the training area label that intersects with this image\r\n let intersection = image.intersectAerialPoints(this.polygonPointsOnly);\r\n let intersectionData = sectionsFromIntersection(intersection, false);\r\n\r\n return intersectionData.map((arr) => {\r\n return image.aerialToPixels(arr);\r\n });\r\n }\r\n}\r\n\r\nexport class TrainingAreaCategory extends OrthoCategory {\r\n public labels: TrainingAreaLabel[] = [];\r\n\r\n constructor(aerialTools: AerialLabelTools, name) {\r\n super(aerialTools, name);\r\n }\r\n\r\n addNewLabel(drawLabel) {\r\n let label = new TrainingAreaLabel(this, this.aerialMap);\r\n label.setDrawable(drawLabel);\r\n this.labels.push(label);\r\n\r\n return label;\r\n }\r\n}\r\n\r\nexport class AerialLabelTools {\r\n public type = \"ortho\";\r\n public enabled = false;\r\n public imageLabelTools: ImageLabelTools;\r\n private temporaryPoint: Coordinate;\r\n public trainingArea: TrainingAreaCategory;\r\n private polygonHover: LabelPolygon = null;\r\n private pointHover: LabelPoint = null;\r\n\r\n constructor(imageLabelTools: ImageLabelTools) {\r\n this.imageLabelTools = imageLabelTools;\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-start-drawing-polygon')\r\n ];\r\n }\r\n\r\n get dragTooltip() {\r\n return [\r\n t('measure.click-and-hold-to-move-vertex'),\r\n t('measure.right-click-to-select-point')\r\n ];\r\n }\r\n\r\n get highlightTooltip() {\r\n return [\r\n t('measure.right-click-to-select-label'),\r\n t('measure.ctrl-right-click-to-select-multiple-labels')\r\n ];\r\n }\r\n\r\n get categories() {\r\n return this.imageLabelTools.categories\r\n .filter(x => x instanceof OrthoCategory) as OrthoCategory[];\r\n }\r\n\r\n get viewer() {\r\n return this.imageLabelTools.viewer;\r\n }\r\n\r\n get aerialMap() {\r\n return this.viewer.minimap;\r\n }\r\n\r\n get map() {\r\n return this.aerialMap.map;\r\n }\r\n\r\n get drawing() {\r\n let label = this.activeLabel;\r\n if (!label || label.completed) {\r\n return false;\r\n }\r\n\r\n if (label.coordinates.length === 0) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n get activeLabel() {\r\n let selected = null;\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.selected) {\r\n selected = label;\r\n }\r\n });\r\n });\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.selected) {\r\n selected = label;\r\n }\r\n });\r\n\r\n return selected;\r\n }\r\n\r\n get numberLabels() {\r\n let count = 0;\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label => count++));\r\n return count;\r\n }\r\n\r\n get moreTooltip() {\r\n return [\r\n t(\"labels.click-to-add-more-points\", {\r\n count: this.numPoints\r\n }),\r\n t('labels.delete-key-to-remove-last-point'),\r\n ...(this.numPoints > 1 ? [t('labels.double-click-to-finish')] : []),\r\n ...(this.numPoints > 2 ? [t('labels.press-enter-to-exit')] : []),\r\n ...(this.activeLabel.editing ? [] : [t('labels.right-click-to-cancel')])\r\n ];\r\n }\r\n\r\n get invalidTooltip() {\r\n return [\r\n t('labels.polygon-is-invalid-due-to-self-intersection'),\r\n ...this.moreTooltip\r\n ];\r\n }\r\n\r\n get numPoints() {\r\n let pointCount = 0;\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label => {\r\n if (label.selected) {\r\n pointCount = label.numPoints;\r\n }\r\n })\r\n );\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.selected) {\r\n pointCount = label.numPoints;\r\n }\r\n });\r\n\r\n return pointCount;\r\n }\r\n\r\n get selected() {\r\n let selected = false;\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label =>\r\n selected = (selected || label.selected)\r\n )\r\n );\r\n\r\n this.trainingArea?.labels.forEach(label =>\r\n selected = (selected || label.selected)\r\n );\r\n\r\n return selected;\r\n }\r\n\r\n get visibleOrthos() {\r\n let orthoList = this.viewer.orthoList;\r\n return orthoList.orthos.filter(x => x.visible);\r\n }\r\n\r\n get activeImagePaths() {\r\n return this.visibleOrthos.map(ortho => ortho.path);\r\n }\r\n\r\n get loadedImagePaths() {\r\n let orthoList = this.viewer.orthoList;\r\n return orthoList.orthos.map(ortho => ortho.path);\r\n }\r\n\r\n get polygonFeaturesForExtent() {\r\n let features = [];\r\n this.categories.forEach(category => {\r\n let source = category.featuresLayer.getSource();\r\n let extent = this.map.getView().calculateExtent(this.map.getSize());\r\n let sourceFeatures = source.getFeaturesInExtent(extent);\r\n let points = sourceFeatures.filter(x => x instanceof LabelPolygon);\r\n features = [...features, ...points];\r\n });\r\n\r\n return features;\r\n }\r\n\r\n get pointFeaturesForExtent() {\r\n let features = [];\r\n\r\n this.categories.forEach(category => {\r\n let source = category.featuresLayer.getSource();\r\n let extent = this.map.getView().calculateExtent(this.map.getSize());\r\n let sourceFeatures = source.getFeaturesInExtent(extent);\r\n let points = sourceFeatures.filter(x => x instanceof LabelPoint);\r\n features = [...features, ...points];\r\n });\r\n\r\n if (this.trainingArea) {\r\n let source = this.trainingArea.featuresLayer.getSource();\r\n let extent = this.map.getView().calculateExtent(this.map.getSize());\r\n let sourceFeatures = source.getFeaturesInExtent(extent);\r\n let points = sourceFeatures.filter(x => x instanceof LabelPoint);\r\n features = [...features, ...points];\r\n }\r\n\r\n return features;\r\n }\r\n\r\n get trainingLabels() {\r\n return this.trainingArea\r\n ? this.trainingArea.labels.filter(label => label.isValid)\r\n : [];\r\n }\r\n\r\n completeLabel(label: OrthoLabel) {\r\n this.resetTemporaryPoint();\r\n this.imageLabelTools.completeLabel(label.id);\r\n this.markLastPointDraggable(label);\r\n }\r\n\r\n updateDraggablePoint(event: MapBrowserEvent) {\r\n let {label, index} = this.pointHover;\r\n label.updatePoint(event.coordinate, index);\r\n label.draw();\r\n\r\n if (label.score < 1.0) {\r\n label.setScore(1.0);\r\n this.imageLabelTools.setCategories();\r\n }\r\n }\r\n\r\n markLastPointDraggable(label: OrthoLabel) {\r\n let pointFeatures = label.features.filter(x => x instanceof LabelPoint);\r\n let lastPoint = pointFeatures[pointFeatures.length - 1];\r\n this.setPointHover(lastPoint);\r\n }\r\n\r\n cancelLabel() {\r\n if (this.activeLabel && !this.activeLabel.editing) {\r\n this.imageLabelTools.deleteLabel(this.activeLabel.id);\r\n this.setToolTipText();\r\n this.drawAll();\r\n }\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n clearAerialTooltip();\r\n }\r\n\r\n setPointHover(feature) {\r\n this.pointHover = feature;\r\n\r\n if (feature) {\r\n this.setPointGrabTooltip();\r\n }\r\n\r\n const canDrag = feature ? false : true;\r\n this.aerialMap.setDragState(canDrag);\r\n }\r\n\r\n setPolygonHover(feature) {\r\n this.polygonHover = feature;\r\n }\r\n\r\n setTrainingArea(category: TrainingAreaCategory) {\r\n this.trainingArea = category;\r\n }\r\n\r\n deleteTrainingArea() {\r\n this.trainingArea.labels.forEach(label => {\r\n label.destroy();\r\n });\r\n\r\n this.trainingArea = null;\r\n }\r\n\r\n openContextMenu(event, feature) {\r\n const pointID = (feature instanceof LabelPoint) ? feature.index : null;\r\n const labelID = feature.label.id;\r\n\r\n const pixel = this.map.getEventPixel(event);\r\n const coordinate = this.map.getCoordinateFromPixel(pixel);\r\n\r\n const labelData = {\r\n coordinate,\r\n pointID,\r\n labelID\r\n } as LabelContextData;\r\n\r\n showContextMenu(event, {\r\n isAerial: true,\r\n labelData\r\n });\r\n }\r\n\r\n onMapClick(event) {\r\n if (!this.enabled) return false;\r\n\r\n let label = this.activeLabel;\r\n if (!label) {\r\n return false;\r\n }\r\n\r\n let duplicatePoint = label.addPoint(event.coordinate);\r\n if (duplicatePoint && label.hasEnoughPoints) {\r\n this.completeLabel(label);\r\n return true;\r\n }\r\n\r\n this.setToolTipText();\r\n this.resetTemporaryPoint();\r\n this.drawActiveLabel();\r\n return true;\r\n }\r\n\r\n onDoubleClick(event) {\r\n if (!this.enabled) return false;\r\n\r\n // Restrict double click zoom\r\n event.preventDefault();\r\n event.stopPropagation();\r\n }\r\n\r\n onMouseMove(event: MapBrowserEvent) {\r\n if (!this.enabled) return false;\r\n\r\n this.resetTemporaryPoint();\r\n\r\n // Drawing new points\r\n if (this.selected) {\r\n this.temporaryPoint = new Coordinate(event.coordinate);\r\n this.setToolTipText();\r\n this.drawActiveLabel();\r\n return;\r\n }\r\n\r\n if (!event.dragging) {\r\n this.checkFeatureHover(event);\r\n }\r\n\r\n if (this.pointHover) {\r\n this.setPointGrabTooltip();\r\n if (event.dragging) {\r\n this.updateDraggablePoint(event);\r\n return;\r\n }\r\n } else if (this.polygonHover) {\r\n this.setPolygonHoverTooltip();\r\n } else {\r\n this.setToolTipText();\r\n }\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n if (!this.enabled) return false;\r\n\r\n if (event.isRightClick) {\r\n if (this.drawing) {\r\n this.cancelLabel();\r\n return true;\r\n }\r\n\r\n return this.onRightClick(event);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onRightClick(event) {\r\n const oneHighlighted = this.imageLabelTools.oneHighlighted;\r\n const noneHighlighted = this.imageLabelTools.noneHighlighted;\r\n\r\n if (noneHighlighted && !event.ctrlKey) {\r\n let feature = this.highlightLabel();\r\n if (feature) {\r\n this.openContextMenu(event, feature);\r\n return true;\r\n }\r\n }\r\n\r\n if (oneHighlighted && !event.ctrlKey) {\r\n this.imageLabelTools.unHighlightAll();\r\n let feature = this.highlightLabel();\r\n if (feature) {\r\n this.openContextMenu(event, feature);\r\n return true;\r\n }\r\n }\r\n\r\n if (event.ctrlKey) {\r\n this.highlightLabel();\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n checkFeatureHover(event: MapBrowserEvent) {\r\n let selectedPoint = this.getFeatureAtPixel(event,\r\n this.pointFeaturesForExtent);\r\n\r\n let selectedPolygon = this.getFeatureAtPixel(event,\r\n this.polygonFeaturesForExtent);\r\n\r\n this.setPointHover(selectedPoint);\r\n this.setPolygonHover(selectedPolygon);\r\n }\r\n\r\n getFeatureAtPixel(event, features) {\r\n const mousePixel = event.pixel;\r\n const mouseCoord = event.coordinate;\r\n const buffer = 10;\r\n\r\n const x = mousePixel[0];\r\n const y = mousePixel[1];\r\n\r\n const mouseBuffer = this.map.getCoordinateFromPixel([x, y])[0]\r\n - this.map.getCoordinateFromPixel([x - buffer, y])[0];\r\n\r\n for (let feature of features) {\r\n // NOTE: We know the geometry exists, so this is faster than\r\n // calling feature.getGeometry() or feature.get(\"geometry\")\r\n const geometry = feature.values_.geometry;\r\n\r\n const pointExtent = geometry.getExtent();\r\n const notVisible = (pointExtent[0] > (mouseCoord[0] + mouseBuffer))\r\n || (pointExtent[2] < (mouseCoord[0] - mouseBuffer))\r\n || (pointExtent[1] > (mouseCoord[1] + mouseBuffer))\r\n || (pointExtent[3] < (mouseCoord[1] - mouseBuffer));\r\n\r\n if (notVisible) {\r\n continue;\r\n }\r\n\r\n if (feature instanceof LabelPolygon) {\r\n const intersect = geometry.intersectsCoordinate(mouseCoord);\r\n if (intersect) {\r\n return feature;\r\n }\r\n }\r\n\r\n if (feature instanceof LabelPoint) {\r\n const coord = geometry.flatCoordinates;\r\n const pixel = this.map.getPixelFromCoordinate(coord);\r\n const dx = pixel[0] - mousePixel[0];\r\n const dy = pixel[1] - mousePixel[1];\r\n const dist = Math.sqrt(dx*dx + dy*dy);\r\n\r\n // Check using pointRadius + outline\r\n const maxDistance = pointRadius + pointStrokeWidth;\r\n const intersect = dist <= maxDistance;\r\n if (intersect) {\r\n return feature;\r\n }\r\n }\r\n };\r\n }\r\n\r\n highlightLabel() {\r\n let selected = null;\r\n\r\n if (this.pointHover) {\r\n selected = this.pointHover;\r\n } else if (this.polygonHover) {\r\n selected = this.polygonHover;\r\n } else {\r\n return;\r\n }\r\n\r\n let label = selected.label;\r\n label.setHighlighted(!label.highlighted);\r\n this.imageLabelTools.setCategories();\r\n\r\n return selected;\r\n }\r\n\r\n setToolTipText() {\r\n if (!this.activeLabel) {\r\n clearAerialTooltip();\r\n return;\r\n }\r\n\r\n const started = (this.numPoints === 0);\r\n\r\n let helpMsg = started\r\n ? this.startTooltip\r\n : this.moreTooltip;\r\n\r\n helpMsg = this.activeLabel.valid\r\n ? helpMsg\r\n : this.invalidTooltip;\r\n\r\n setAerialTooltip(helpMsg);\r\n }\r\n\r\n setPointGrabTooltip() {\r\n setAerialTooltip(this.dragTooltip);\r\n }\r\n\r\n setPolygonHoverTooltip() {\r\n setAerialTooltip(this.highlightTooltip);\r\n }\r\n\r\n drawAll() {\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n label.draw(this.temporaryPoint, category.visible);\r\n });\r\n });\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n label.draw(this.temporaryPoint);\r\n });\r\n }\r\n\r\n drawActiveLabel() {\r\n if (!this.activeLabel) {\r\n return;\r\n }\r\n\r\n this.activeLabel.draw(this.temporaryPoint);\r\n\r\n }\r\n\r\n getNewCategory(name) {\r\n return new OrthoCategory(this, name);\r\n }\r\n\r\n getNewTrainingArea() {\r\n return new TrainingAreaCategory(this, \"training area\");\r\n }\r\n\r\n deletePoint() {\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label => {\r\n if (label.selected) {\r\n label.removePoint();\r\n this.setToolTipText();\r\n this.drawActiveLabel();\r\n }\r\n })\r\n );\r\n\r\n this.imageLabelTools.setCategories();\r\n }\r\n\r\n deleteSpecificPoint(id) {\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label => {\r\n\r\n if (label.highlighted && (label.numPoints > 3)) {\r\n label.removeSpecificPoint(id);\r\n this.imageLabelTools.unHighlight(label.id);\r\n }\r\n })\r\n );\r\n\r\n this.trainingArea?.labels.forEach(label => {\r\n if (label.highlighted && (label.numPoints > 3)) {\r\n label.removeSpecificPoint(id);\r\n this.imageLabelTools.unHighlight(label.id);\r\n }\r\n });\r\n\r\n this.imageLabelTools.setCategories();\r\n }\r\n\r\n resetTemporaryPoint() {\r\n this.temporaryPoint = null;\r\n }\r\n\r\n calculatePolygonPixels = (polygonPoints, metadata) => {\r\n let pixelPolygon = [];\r\n\r\n polygonPoints.forEach(point => {\r\n let pixelPoint = [((point[0] - metadata.x_offset)/metadata.x_scale),\r\n ((point[1] - metadata.y_offset)/metadata.y_scale)];\r\n pixelPolygon.push(pixelPoint);\r\n });\r\n return pixelPolygon;\r\n }\r\n\r\n jsonImageObj() {\r\n let images = this.visibleOrthos.map((ortho, imageIndex) => {\r\n return {\r\n height: ortho.originalSize[1],\r\n width: ortho.originalSize[0],\r\n id: imageIndex,\r\n file_name: ortho.orthoName,\r\n metadata: ortho.metadata\r\n } as CocoImage;\r\n });\r\n\r\n return images;\r\n }\r\n\r\n getTrainingAnnotations = () => {\r\n let labelIndex = 0;\r\n let annotations = [];\r\n\r\n if (this.trainingLabels.length === 0) {\r\n return annotations;\r\n }\r\n\r\n this.visibleOrthos.forEach((image, imageID) => {\r\n this.trainingLabels.forEach((trainingLabel, trainingLabelIndex) => {\r\n trainingLabel.polygonsInsideImage(image).forEach(polygon => {\r\n let mergeID = trainingLabelIndex+1;\r\n let trainingLabel = annotationFromPolygon(polygon,\r\n labelIndex, 0, imageID, mergeID);\r\n\r\n annotations.push(trainingLabel);\r\n labelIndex += 1;\r\n });\r\n });\r\n });\r\n\r\n return annotations;\r\n }\r\n\r\n getLabelAnnotations() {\r\n let labelIndex = 0;\r\n let annotations = [];\r\n\r\n this.visibleOrthos.forEach((image, imageID) => {\r\n let boundsToCheck = [];\r\n\r\n if (this.trainingLabels.length === 0) {\r\n // Bounds are the entire image\r\n let boundsPolygon = [...image.cornerPixels, image.cornerPixels[0]];\r\n boundsToCheck.push({imageID, boundsPolygon});\r\n } else {\r\n // Bounds are training area polygons for this image\r\n this.trainingLabels.forEach(trainingLabel => {\r\n trainingLabel.polygonsInsideImage(image).forEach(boundsPolygon => {\r\n boundsToCheck.push({imageID, boundsPolygon});\r\n });\r\n });\r\n }\r\n\r\n this.categories.forEach((category, categoryID) => {\r\n category.labels.forEach((label, labelID) => {\r\n if (!label.valid) {\r\n return;\r\n }\r\n\r\n // Check for label inside each boundary polygon\r\n boundsToCheck.forEach(({imageID, boundsPolygon}) => {\r\n let labelPolygon = this.visibleOrthos[imageID]\r\n .aerialToPixels(label.polygonPointsOnly);\r\n labelPolygon = [...labelPolygon, labelPolygon[0]];\r\n\r\n let intersection = turfIntersect(\r\n turfPolygon([boundsPolygon]),\r\n turfPolygon([labelPolygon])\r\n );\r\n\r\n let intersectionData = sectionsFromIntersection(intersection);\r\n intersectionData.forEach((polygon) => {\r\n let mergeID = labelID + 1;\r\n let annotation = annotationFromPolygon(polygon, labelIndex,\r\n categoryID, imageID, mergeID, label.score, label.text, label.textScore,\r\n label.findText);\r\n\r\n annotations.push(annotation);\r\n labelIndex += 1;\r\n });\r\n });\r\n });\r\n });\r\n });\r\n\r\n return annotations;\r\n };\r\n\r\n get activeImages() {\r\n return [];\r\n }\r\n}\r\n","import { CustomMouseEvent } from \"../controls\";\r\nimport { ChangeDetector, getPointScale, toScreenPosition } from '../utilities';\r\nimport earcut from 'earcut';\r\nimport {\r\n BufferGeometry,\r\n Color,\r\n DoubleSide,\r\n Line,\r\n LineBasicMaterial,\r\n LineDashedMaterial,\r\n MathUtils,\r\n Mesh,\r\n MeshBasicMaterial,\r\n Scene,\r\n SphereGeometry,\r\n Triangle,\r\n Vector3\r\n} from \"three\";\r\nimport {\r\n pointInPolygon,\r\n checkValidPolygon\r\n} from \"../utilities\";\r\nimport {\r\n CameraImage,\r\n CameraLoadOptions,\r\n directionToCameraAngle,\r\n ImagePixel,\r\n PanoramicImage,\r\n PlanarImage\r\n} from \"../cameras\";\r\nimport {\r\n annotationFromPolygon,\r\n CocoImage,\r\n ImageLabel,\r\n ImageLabelTools,\r\n LabelCategory,\r\n sectionsFromIntersection,\r\n textToColor\r\n} from \".\";\r\nimport {\r\n polygon as turfPolygon,\r\n point as turfPoint\r\n} from '@turf/helpers';\r\nimport {default as turfIntersect} from '@turf/intersect';\r\nimport booleanContains from \"@turf/boolean-contains\";\r\nimport { Viewer } from \"../main\";\r\nimport { LabelContextData, showContextMenu } from \"../../context-menu\";\r\nimport { clearViewerTooltip, setViewerTooltip } from \"../viewer\";\r\nimport { RayCaster } from \"../ray-caster\";\r\nimport { t } from \"../../localization\";\r\n\r\nclass LabelPoint extends Mesh {\r\n public coordinate: Coordinate;\r\n public label: SceneLabel;\r\n public index;\r\n\r\n constructor(geometry, material, coordinate, label, index) {\r\n super(geometry, material);\r\n this.coordinate = coordinate;\r\n this.label = label;\r\n this.index = index;\r\n }\r\n}\r\n\r\nclass LabelPolygon extends Mesh {\r\n public label: SceneLabel;\r\n\r\n constructor(geometry, material, label) {\r\n super(geometry, material);\r\n this.label = label;\r\n }\r\n}\r\n\r\nclass Coordinate {\r\n private camera: CameraImage;\r\n public pixel: ImagePixel;\r\n public _direction: Vector3;\r\n public _position: Vector3;\r\n\r\n constructor(pixel, camera) {\r\n this.camera = camera;\r\n this.updateValues(pixel);\r\n }\r\n\r\n updateValues(pixel) {\r\n this.pixel = pixel;\r\n\r\n // Reset direction/position values\r\n this._direction = null;\r\n this._position = null;\r\n }\r\n\r\n get direction() {\r\n if (this._direction === null) {\r\n this._direction = this.camera\r\n .pixelToDirection(this.pixel);\r\n }\r\n\r\n return this._direction;\r\n }\r\n\r\n get position() {\r\n if (this._position === null) {\r\n let cameraPos = this.camera.position.scene;\r\n this._position = new Vector3()\r\n .copy(this.direction)\r\n .multiplyScalar(100)\r\n .add(cameraPos);\r\n }\r\n\r\n return this._position;\r\n }\r\n}\r\n\r\nclass SceneLabel extends ImageLabel {\r\n public camera: CameraImage;\r\n public category: SceneCategory\r\n public _imageWidth = null;\r\n public _imageHeight = null;\r\n public coordinates: Coordinate[] = [];\r\n public minCoordinates = 3;\r\n private standardMeshes = [];\r\n private polygonMeshes = [];\r\n private sphereGeometry = new SphereGeometry(0.05, 20, 20);\r\n private sphereMaterial: MeshBasicMaterial;\r\n private lineGeometry: BufferGeometry;\r\n private lineMaterial: LineBasicMaterial;\r\n private lineDashedMaterial: LineDashedMaterial;\r\n private polygonMaterial: MeshBasicMaterial;\r\n private polygonOpacity = 0.2;\r\n private minPoleAngle = 25;\r\n\r\n constructor(category: SceneCategory, camera: CameraImage) {\r\n super();\r\n this.category = category;\r\n\r\n this.lineGeometry = new BufferGeometry();\r\n this.updateMaterials();\r\n this.setCamera(camera);\r\n }\r\n\r\n get hasEnoughPoints() {\r\n return this.numPoints >= this.minCoordinates;\r\n }\r\n\r\n get numPoints() {\r\n return this.coordinates.length;\r\n }\r\n\r\n get coords() {\r\n /** Used for polygon simplification */\r\n return this.coordinates.map(x => [x.pixel.u, x.pixel.v]);\r\n }\r\n\r\n get positions() {\r\n return this.coordinates.map(x => x.position);\r\n }\r\n\r\n get directions() {\r\n return this.coordinates.map(x => x.direction);\r\n }\r\n\r\n get pixels() {\r\n return this.coordinates.map(x => x.pixel);\r\n }\r\n\r\n get viewer() : Viewer {\r\n return this.category.sceneLabels.viewer;\r\n }\r\n\r\n get standardScene() {\r\n return this.category.sceneLabels.standardScene;\r\n }\r\n\r\n get polygonScene() {\r\n return this.category.sceneLabels.polygonScene;\r\n }\r\n\r\n get standardColor() {\r\n return this.category.color(this.highlighted);\r\n }\r\n\r\n get darkenedColor() {\r\n let dark = new Color()\r\n .copy(this.category.color(this.highlighted))\r\n .multiplyScalar(0.75);\r\n\r\n return dark;\r\n }\r\n\r\n get imageWidth() {\r\n return this._imageWidth\r\n ? this._imageWidth\r\n : this.camera.imageWidth;\r\n }\r\n\r\n get imageHeight() {\r\n return this._imageHeight\r\n ? this._imageHeight\r\n : this.camera.imageHeight;\r\n }\r\n\r\n setCamera(camera) {\r\n this.camera = camera;\r\n }\r\n\r\n setKnownImageSize(width, height) {\r\n this._imageWidth = width;\r\n this._imageHeight = height;\r\n }\r\n\r\n updateMaterials() {\r\n this.dispose();\r\n\r\n this.sphereMaterial = new MeshBasicMaterial({\r\n color: this.standardColor\r\n });\r\n\r\n this.lineMaterial = new LineBasicMaterial({\r\n color: this.darkenedColor\r\n });\r\n\r\n this.lineDashedMaterial = new LineDashedMaterial({\r\n color: this.darkenedColor,\r\n dashSize: 1.5,\r\n gapSize: 2.5,\r\n });\r\n\r\n this.polygonMaterial = new MeshBasicMaterial({\r\n color: this.standardColor,\r\n opacity: this.polygonOpacity,\r\n side: DoubleSide\r\n });\r\n }\r\n\r\n removePoint() {\r\n this.coordinates.pop();\r\n }\r\n\r\n removeSpecificPoint(index) {\r\n this.coordinates.splice(index, 1);\r\n this.highlighted = false;\r\n this.updateMaterials();\r\n this.draw();\r\n }\r\n\r\n setPointScale(mesh) {\r\n const scale = getPointScale(this.viewer.camera, mesh);\r\n mesh.scale.set(scale, scale, scale);\r\n mesh.geometry.computeBoundingSphere();\r\n }\r\n\r\n /** @private */\r\n drawPoints(temporaryPoint) {\r\n let positions = this.positions;\r\n\r\n if (temporaryPoint && !this.completed) {\r\n positions = [...positions, temporaryPoint.position];\r\n }\r\n\r\n positions.forEach((position, index) => {\r\n const coordinate = this.coordinates[index];\r\n const mesh = new LabelPoint(this.sphereGeometry,\r\n this.sphereMaterial, coordinate, this, index);\r\n\r\n mesh.position.copy(position);\r\n\r\n this.standardScene.add(mesh);\r\n this.standardMeshes.push(mesh);\r\n this.setPointScale(mesh);\r\n });\r\n }\r\n\r\n /** @private */\r\n drawLines(temporaryPoint) {\r\n let positions = this.positions;\r\n if (positions.length === 0) {\r\n return;\r\n }\r\n\r\n if (temporaryPoint && !this.completed) {\r\n positions = [...positions, temporaryPoint.position];\r\n }\r\n\r\n let corners = [...positions, positions[0]];\r\n this.lineGeometry.setFromPoints(corners);\r\n this.lineGeometry.computeBoundingSphere();\r\n\r\n let material = this.completed\r\n ? this.lineMaterial\r\n : this.lineDashedMaterial;\r\n\r\n const line = new Line(this.lineGeometry, material);\r\n\r\n if (!this.completed) {\r\n line.computeLineDistances();\r\n }\r\n\r\n this.standardMeshes.push(line);\r\n this.standardScene.add(line);\r\n }\r\n\r\n /** @private */\r\n drawPolygons(temporaryPoint: Coordinate) {\r\n let positions = this.positions;\r\n let directions = this.directions;\r\n let pixels = this.pixels;\r\n\r\n if (temporaryPoint && !this.completed) {\r\n pixels = [...pixels, temporaryPoint.pixel];\r\n positions = [...positions, temporaryPoint.position];\r\n directions = [...directions, temporaryPoint.direction];\r\n }\r\n\r\n if (positions.length < this.minCoordinates) {\r\n return;\r\n }\r\n\r\n let coordinates3d = this.camera instanceof PanoramicImage\r\n ? this.camera.directionsToPlanar(directions)\r\n : pixels.map(x => new Vector3(x.u, x.v, 0.0));\r\n\r\n let oldState = this.valid;\r\n\r\n // Check for valid polygon\r\n let coordinates2d = coordinates3d.map(x => [x.x, x.y]);\r\n let pixels2d = pixels.map(x => [x.u, x.v]);\r\n // let validCoords = checkValidPolygon(coordinates2d);\r\n this.valid = checkValidPolygon(pixels2d);\r\n // this.valid = (validPix || validCoords);\r\n // this.valid = checkValidPolygon(coordinates2d);\r\n\r\n // Panoramic images aren't valid at the poles\r\n if (this.camera instanceof PanoramicImage) {\r\n\r\n this.valid = this.valid && !this.polygonAtPoles(directions);\r\n }\r\n\r\n if (this.valid !== oldState) {\r\n this.category.setCategories();\r\n }\r\n\r\n if (!this.valid) {\r\n return;\r\n }\r\n\r\n // Calculate triangle mesh indices\r\n let coordinatesFlat = coordinates2d.flat();\r\n let indices = earcut(coordinatesFlat, null, 2);\r\n\r\n // Deviation must be nearly zero to be valid\r\n let deviation = earcut.deviation(coordinatesFlat, null, 2, indices);\r\n if (deviation > 0.1) {\r\n return;\r\n }\r\n\r\n let numTriangles = indices.length / 3;\r\n for (var i = 0; i < numTriangles; i++) {\r\n let triangle = new Triangle(\r\n coordinates3d[indices[3 * i]],\r\n coordinates3d[indices[3 * i + 1]],\r\n coordinates3d[indices[3 * i + 2]]\r\n );\r\n\r\n // Remove invalid triangles\r\n let center = new Vector3();\r\n triangle.getMidpoint(center);\r\n let valid = pointInPolygon(center, coordinates3d);\r\n if (!valid) {\r\n continue;\r\n }\r\n\r\n const points = [\r\n positions[indices[3 * i]],\r\n positions[indices[3 * i + 1]],\r\n positions[indices[3 * i + 2]]\r\n ];\r\n\r\n const geometry = new BufferGeometry().setFromPoints(points);\r\n geometry.setIndex([0,1,2]);\r\n\r\n let polygon = new LabelPolygon(geometry, this.polygonMaterial, this);\r\n this.polygonMeshes.push(polygon);\r\n this.polygonScene.add(polygon);\r\n }\r\n }\r\n\r\n draw(temporaryPoint=null) {\r\n this.clear();\r\n\r\n if (!this.drawable) {\r\n return;\r\n }\r\n\r\n if (this.category.currentCamera !== this.camera) {\r\n return;\r\n }\r\n\r\n if (!this.camera || this.camera.missing) {\r\n return;\r\n }\r\n\r\n this.drawPoints(temporaryPoint);\r\n this.drawLines(temporaryPoint);\r\n this.drawPolygons(temporaryPoint);\r\n }\r\n\r\n toScreenPosition(point) {\r\n const uv = toScreenPosition(this.viewer, point.position);\r\n return [uv.x, uv.y];\r\n }\r\n\r\n addPoint(pixel: ImagePixel | [], checkDuplicate=true) {\r\n const newPoint = new Coordinate(pixel, this.camera);\r\n const oldPoint = this.coordinates[this.coordinates.length - 1];\r\n\r\n if (checkDuplicate && this.duplicatePoint(oldPoint, newPoint)) {\r\n return true;\r\n }\r\n\r\n this.coordinates.push(newPoint);\r\n return false;\r\n }\r\n\r\n createCoordData(coordinate) {\r\n const point = new Vector3(coordinate.u, coordinate.v);\r\n const coordArray = this.coordinates.map(coord => {\r\n return [coord.pixel.u, coord.pixel.v];\r\n });\r\n\r\n return {coordArray, point};\r\n }\r\n\r\n insertPoint(newPoint, idxCoord) {\r\n const point = {u: newPoint.x, v: newPoint.y};\r\n const newCoord = new Coordinate(point, this.camera);\r\n this.coordinates.splice(idxCoord+1, 0, newCoord);\r\n this.draw();\r\n }\r\n\r\n polygonAtPoles(coordinates): boolean {\r\n // Check each point to make sure the phi angle is safe\r\n let pointsAtPole = false;\r\n coordinates.forEach(x => {\r\n let phi = MathUtils.radToDeg(Math.acos(x.z));\r\n let minAngle = phi < this.minPoleAngle;\r\n let maxAngle = phi > (180 - this.minPoleAngle);\r\n\r\n pointsAtPole = pointsAtPole || minAngle;\r\n pointsAtPole = pointsAtPole || maxAngle;\r\n });\r\n\r\n if (pointsAtPole) {\r\n return true;\r\n }\r\n\r\n // Check to see if the polygon surrounds the pole\r\n coordinates = coordinates.map(x => [x.x, x.y]);\r\n let polyPointRing = [...coordinates, coordinates[0]];\r\n\r\n let surroundsPole = booleanContains(\r\n turfPolygon([polyPointRing]),\r\n turfPoint([0, 0])\r\n );\r\n\r\n return surroundsPole;\r\n }\r\n\r\n getCameraBestFit(): CameraLoadOptions {\r\n // Calculate average direction vector\r\n const averageDirection = new Vector3();\r\n this.directions.forEach(x => averageDirection.add(x));\r\n averageDirection.divideScalar(this.directions.length);\r\n\r\n const fovRequired = this.directions.map(direction => {\r\n let angle = direction.angleTo(averageDirection);\r\n return MathUtils.radToDeg(angle) * 2.0;\r\n });\r\n\r\n // Best fit field of view has as small buffer added\r\n const fov = Math.max(...fovRequired) * 1.10;\r\n\r\n // Convert average direction to camera angles\r\n const angles = directionToCameraAngle(averageDirection);\r\n\r\n return {fov, angles};\r\n }\r\n\r\n clear() {\r\n this.standardMeshes.forEach(mesh => {\r\n this.standardScene.remove(mesh);\r\n });\r\n\r\n this.polygonMeshes.forEach(mesh => {\r\n this.polygonScene.remove(mesh);\r\n });\r\n\r\n this.standardMeshes = [];\r\n this.polygonMeshes = [];\r\n }\r\n\r\n destroy() {\r\n this.clear();\r\n this.dispose();\r\n }\r\n\r\n dispose() {\r\n this.standardMeshes.forEach(mesh => {\r\n mesh.geometry.dispose();\r\n mesh.material.dispose();\r\n });\r\n\r\n this.polygonMeshes.forEach(mesh => {\r\n mesh.geometry.dispose();\r\n mesh.material.dispose();\r\n });\r\n }\r\n\r\n zoom(): Promise {\r\n // The camera must be loaded before we are able to calculate the\r\n // direction and zoom, so we load the camera before calculating\r\n\r\n return new Promise(async (resolve) => {\r\n const cameraID = this.camera.id;\r\n let currentCamera = this.viewer.getCurrentCamera();\r\n\r\n let camera = currentCamera.id !== cameraID\r\n ? await this.viewer.loadImage(cameraID)\r\n : currentCamera;\r\n\r\n if (camera.missing) {\r\n resolve(false);\r\n } else {\r\n let opts = this.getCameraBestFit();\r\n this.viewer.loadImage(cameraID, opts);\r\n resolve(true);\r\n }\r\n });\r\n }\r\n\r\n setHighlighted(highlight) {\r\n if (highlight === this.highlighted) {\r\n return;\r\n }\r\n\r\n this.highlighted = highlight;\r\n this.updateMaterials();\r\n this.draw();\r\n }\r\n}\r\n\r\nclass SceneCategory extends LabelCategory {\r\n public sceneLabels: SceneLabelTools;\r\n public labels: SceneLabel[] = [];\r\n\r\n constructor(sceneLabels, name) {\r\n super(name);\r\n this.sceneLabels = sceneLabels;\r\n }\r\n\r\n get currentCamera() {\r\n return this.sceneLabels.currentCamera;\r\n }\r\n\r\n color(highlight=false) : Color {\r\n let color = `rgba(${Math.ceil(255)}, ${Math.ceil(255)}, ${Math.ceil(255)})`;\r\n if (!highlight) {\r\n color = textToColor(this.name);\r\n }\r\n return new Color(color);\r\n }\r\n\r\n setCategories() {\r\n this.sceneLabels.imageLabelTools.setCategories();\r\n }\r\n\r\n updateColor() {\r\n this.labels.forEach(label => {\r\n label.updateMaterials();\r\n });\r\n\r\n this.sceneLabels.drawAll();\r\n }\r\n\r\n addNewLabel(drawLabel) {\r\n let label = new SceneLabel(this, this.currentCamera);\r\n label.setDrawable(this.visible);\r\n this.labels.push(label);\r\n\r\n return label;\r\n }\r\n\r\n deleteUnfinishedLabel() {\r\n let numberOfLabels = this.labels.length;\r\n if (numberOfLabels === 0) {\r\n return;\r\n }\r\n\r\n if (!this.labels[numberOfLabels - 1].completed) {\r\n this.labels.pop();\r\n }\r\n }\r\n}\r\n\r\nexport class SceneLabelTools {\r\n public type = \"scene\";\r\n public imageLabelTools: ImageLabelTools;\r\n public standardScene: Scene;\r\n public polygonScene: Scene;\r\n public enabled = false;\r\n private temporaryPoint: Coordinate;\r\n public draggable = false;\r\n private polygonHover: LabelPolygon = null;\r\n private pointHover: LabelPoint = null;\r\n\r\n constructor(imageLabelTools: ImageLabelTools) {\r\n this.imageLabelTools = imageLabelTools;\r\n this.standardScene = new Scene();\r\n this.polygonScene = new Scene();\r\n\r\n window.addEventListener('keydown', event => {\r\n this.onKeyDown(event);\r\n }, false);\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-start-drawing-polygon')\r\n ];\r\n }\r\n\r\n get dragTooltip() {\r\n return [\r\n t('measure.click-and-hold-to-move-vertex'),\r\n t('measure.right-click-to-select-point')\r\n ];\r\n }\r\n\r\n get highlightTooltip() {\r\n return [\r\n t('measure.right-click-to-select-label'),\r\n t('measure.ctrl-right-click-to-select-multiple-labels')\r\n ];\r\n }\r\n\r\n get categories() {\r\n return this.imageLabelTools.categories\r\n .filter(x => x instanceof SceneCategory) as SceneCategory[];\r\n }\r\n\r\n get viewer() {\r\n return this.imageLabelTools.viewer;\r\n }\r\n\r\n get cameraHandler() {\r\n return this.viewer.cameraHandler;\r\n }\r\n\r\n get currentCamera() {\r\n let current = this.cameraHandler.current;\r\n if (this.viewer.orbitState || !current) {\r\n return null;\r\n }\r\n\r\n return current;\r\n }\r\n\r\n get drawing() {\r\n let label = this.activeLabel;\r\n if (!label || label.completed) {\r\n return false;\r\n }\r\n\r\n if (label.coordinates.length === 0) {\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n get activeLabel() {\r\n let selected = null;\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.selected) {\r\n selected = label;\r\n }\r\n });\r\n });\r\n\r\n return selected;\r\n }\r\n\r\n get moreTooltip() {\r\n return [\r\n t(\"labels.click-to-add-more-points\", {\r\n count: this.numPoints\r\n }),\r\n t('labels.delete-key-to-remove-last-point'),\r\n ...(this.numPoints > 1 ? [t('labels.double-click-to-finish')] : []),\r\n ...(this.numPoints > 2 ? [t('labels.press-enter-to-exit')] : []),\r\n ...(this.activeLabel.editing ? [] : [t('labels.right-click-to-cancel')])\r\n ];\r\n }\r\n\r\n get invalidTooltip() {\r\n const isPanoramic = this.activeLabel.camera instanceof PanoramicImage;\r\n\r\n const errorMessage = isPanoramic\r\n ? t('labels.polygon-is-invalid-due-to-self-intersection-or-closeness-to-poles')\r\n : t('labels.polygon-is-invalid-due-to-self-intersection');\r\n\r\n return [\r\n errorMessage,\r\n ...this.moreTooltip\r\n ];\r\n }\r\n\r\n get numPoints() {\r\n return this.activeLabel.numPoints;\r\n }\r\n\r\n get visibleCameras() {\r\n let visited = new Set();\r\n let cameras = [];\r\n\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (!label.valid) {\r\n return;\r\n }\r\n\r\n let camera = label.camera;\r\n let cameraID = camera.id;\r\n\r\n if (visited.has(cameraID)) {\r\n return;\r\n }\r\n\r\n visited.add(cameraID);\r\n cameras.push(camera);\r\n });\r\n });\r\n\r\n return cameras;\r\n }\r\n\r\n get activeImagePaths() {\r\n return this.visibleCameras.map(image => image.path);\r\n }\r\n\r\n get activeImages() {\r\n return this.visibleCameras;\r\n }\r\n\r\n get loadedImagePaths() {\r\n let imageList = this.viewer.cameraHandler;\r\n const validImageList = imageList.cameras.filter(image => (image instanceof PanoramicImage));\r\n return validImageList.map(image => image.path);\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n clearViewerTooltip();\r\n }\r\n\r\n getNewCategory(name) {\r\n return new SceneCategory(this, name);\r\n }\r\n\r\n getClickedDirection(event) {\r\n const raycaster = new RayCaster(this.viewer, event);\r\n const direction = raycaster.direction;\r\n return direction;\r\n }\r\n\r\n getImagePixel(event): ImagePixel {\r\n const direction = this.getClickedDirection(event);\r\n return this.currentCamera.directionToPixel(direction);\r\n }\r\n\r\n deletePoint() {\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label => {\r\n if (label.selected) {\r\n label.removePoint();\r\n this.setToolTipText();\r\n }\r\n })\r\n );\r\n\r\n this.imageLabelTools.setCategories();\r\n }\r\n\r\n deleteSpecificPoint(id) {\r\n this.categories.forEach(category =>\r\n category.labels.forEach(label => {\r\n\r\n if (label.highlighted && label.hasEnoughPoints) {\r\n label.removeSpecificPoint(id);\r\n this.imageLabelTools.unHighlight(label.id);\r\n }\r\n })\r\n );\r\n this.imageLabelTools.setCategories();\r\n }\r\n\r\n highlightLabel() {\r\n let selected = null;\r\n\r\n if (this.pointHover) {\r\n selected = this.pointHover;\r\n } else if (this.polygonHover) {\r\n selected = this.polygonHover;\r\n } else {\r\n return;\r\n }\r\n\r\n let label = selected.label;\r\n label.setHighlighted(!label.highlighted);\r\n this.imageLabelTools.setCategories();\r\n\r\n return selected;\r\n }\r\n\r\n mouseClick(event) {\r\n if (!this.currentCamera) return;\r\n\r\n let label = this.activeLabel;\r\n if (!label) return;\r\n\r\n let point = this.getImagePixel(event);\r\n if (!point) return;\r\n\r\n let duplicatePoint = label.addPoint(point);\r\n if (duplicatePoint && label.hasEnoughPoints) {\r\n this.completeLabel(label);\r\n return;\r\n }\r\n\r\n this.setToolTipText();\r\n this.resetTemporaryPoint();\r\n this.drawAll();\r\n }\r\n\r\n completeLabel(label) {\r\n this.resetTemporaryPoint();\r\n this.imageLabelTools.completeLabel(label.id);\r\n this.markLastPointDraggable(label);\r\n }\r\n\r\n markLastPointDraggable(label) {\r\n let labelPoints = label.standardMeshes\r\n .filter(x => x instanceof LabelPoint);\r\n\r\n let lastPoint = labelPoints[labelPoints.length - 1];\r\n this.setPointHover(lastPoint);\r\n }\r\n\r\n cancelLabel() {\r\n if (this.activeLabel && !this.activeLabel.editing) {\r\n this.imageLabelTools.deleteLabel(this.activeLabel.id);\r\n this.setToolTipText();\r\n this.drawAll();\r\n }\r\n }\r\n\r\n checkFeatureHover(event) {\r\n if (this.drawing) {\r\n this.setPolygonHover(false);\r\n return;\r\n }\r\n\r\n let targetPoly = this.polygonScene.children\r\n .filter(x => (x instanceof LabelPolygon));\r\n\r\n let targets = this.standardScene.children\r\n .filter(x => x instanceof LabelPoint);\r\n\r\n targets = targets.concat(targetPoly);\r\n\r\n let selectedPoint = null;\r\n let selectedPolygon = null;\r\n\r\n if (targets.length > 0) {\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let objects = raycaster.intersectObjects(targets).map(x => x.object);\r\n\r\n let polygons = objects\r\n .filter(x => x instanceof LabelPolygon);\r\n\r\n let points = objects\r\n .filter(x => x instanceof LabelPoint);\r\n\r\n selectedPoint = (points.length > 0)\r\n ? points[0]\r\n : null;\r\n\r\n selectedPolygon = (polygons.length > 0)\r\n ? polygons[0]\r\n : null;\r\n }\r\n\r\n this.setPolygonHover(selectedPolygon);\r\n this.setPointHover(selectedPoint);\r\n }\r\n\r\n updateDraggablePoint(event) {\r\n let coordinate = this.pointHover.coordinate;\r\n let point = this.getImagePixel(event);\r\n if (!point) return;\r\n\r\n coordinate.updateValues(point);\r\n this.drawAll();\r\n\r\n const {label} = this.pointHover;\r\n if (label.score < 1.0) {\r\n label.setScore(1.0);\r\n this.imageLabelTools.setCategories();\r\n }\r\n }\r\n\r\n setPointHover(feature) {\r\n this.pointHover = feature;\r\n\r\n if (feature) {\r\n this.setPointGrabTooltip();\r\n }\r\n }\r\n\r\n setPolygonHover(feature) {\r\n this.polygonHover = feature;\r\n }\r\n\r\n setToolTipText() {\r\n if (!this.activeLabel) {\r\n clearViewerTooltip();\r\n return;\r\n }\r\n\r\n if (this.drawing) {\r\n let tooltipText = this.activeLabel.valid\r\n ? this.moreTooltip\r\n : this.invalidTooltip;\r\n\r\n setViewerTooltip(tooltipText);\r\n } else if (this.currentCamera) {\r\n setViewerTooltip(this.startTooltip);\r\n } else {\r\n clearViewerTooltip();\r\n }\r\n }\r\n\r\n setPointGrabTooltip() {\r\n setViewerTooltip(this.dragTooltip);\r\n }\r\n\r\n setPolygonHoverTooltip() {\r\n setViewerTooltip(this.highlightTooltip);\r\n }\r\n\r\n resetTemporaryPoint() {\r\n this.temporaryPoint = null;\r\n }\r\n\r\n openContextMenu(event, feature) {\r\n let point = this.getImagePixel(event);\r\n let pointID = (feature instanceof LabelPoint) ? feature.index : null;\r\n let labelID = feature.label.id;\r\n\r\n const labelData = {\r\n coordinate: point,\r\n pointID,\r\n labelID\r\n } as LabelContextData;\r\n\r\n showContextMenu(event, {\r\n labelData\r\n });\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n if (event.mouseMoved || !this.enabled) {\r\n return false;\r\n }\r\n\r\n if (event.isLeftClick) {\r\n this.mouseClick(event);\r\n return !!this.activeLabel;\r\n } else if (event.isRightClick) {\r\n if (this.drawing) {\r\n this.cancelLabel();\r\n return true;\r\n }\r\n\r\n return this.onRightClick(event);\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onRightClick(event) {\r\n const oneHighlighted = this.imageLabelTools.oneHighlighted;\r\n const noneHighlighted = this.imageLabelTools.noneHighlighted;\r\n\r\n if (noneHighlighted && !event.ctrlKey) {\r\n let feature = this.highlightLabel();\r\n if (feature) {\r\n this.openContextMenu(event, feature);\r\n return true;\r\n }\r\n }\r\n\r\n if (oneHighlighted && !event.ctrlKey) {\r\n this.imageLabelTools.unHighlightAll();\r\n let feature = this.highlightLabel();\r\n if (feature) {\r\n this.openContextMenu(event, feature);\r\n return true;\r\n }\r\n }\r\n\r\n if (event.ctrlKey) {\r\n this.highlightLabel();\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n this.resetTemporaryPoint();\r\n\r\n if (!this.enabled) return false;\r\n\r\n if (!event.mouseMoved && !event.mouseDown) {\r\n this.checkFeatureHover(event);\r\n }\r\n\r\n if (this.drawing) {\r\n let point = this.getImagePixel(event);\r\n if (!point) return false;\r\n\r\n this.temporaryPoint = new Coordinate(point,\r\n this.currentCamera);\r\n\r\n this.drawAll();\r\n }\r\n\r\n if (this.pointHover) {\r\n this.setPointGrabTooltip();\r\n return true;\r\n }\r\n\r\n if (this.polygonHover) {\r\n this.setPolygonHoverTooltip();\r\n return true;\r\n }\r\n\r\n this.setToolTipText();\r\n return !!this.activeLabel;\r\n }\r\n\r\n onMouseDrag(event: CustomMouseEvent) {\r\n if (!this.pointHover) return false;\r\n\r\n if (event.mouseDown && event.isLeftClick) {\r\n this.updateDraggablePoint(event);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onKeyDown(event) {\r\n if (event.which === 13) {\r\n let label = this.activeLabel;\r\n if (!label) {\r\n return;\r\n }\r\n\r\n if (label.selected){\r\n this.imageLabelTools.completeLabel(label.id);\r\n }\r\n }\r\n }\r\n\r\n drawAll() {\r\n this.standardScene.clear();\r\n this.polygonScene.clear();\r\n\r\n if (this.viewer.orbitState) {\r\n return;\r\n }\r\n\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n label.draw(this.temporaryPoint);\r\n });\r\n });\r\n }\r\n\r\n /** @private */\r\n calculatePlanarSections(polyPointRing, imageWidth, imageHeight) {\r\n let sections = [];\r\n\r\n let imageBorders = [\r\n [0, 0],\r\n [0, imageHeight-1],\r\n [imageWidth-1, imageHeight-1],\r\n [imageWidth-1, 0],\r\n [0, 0]\r\n ];\r\n\r\n let intersection = turfIntersect(\r\n turfPolygon([polyPointRing]),\r\n turfPolygon([imageBorders]),\r\n );\r\n\r\n let intersectionData = sectionsFromIntersection(intersection);\r\n intersectionData.forEach((arr) => {\r\n sections.push(arr);\r\n });\r\n\r\n return sections;\r\n }\r\n\r\n /** @private */\r\n calculatePanoramicSections(polyPointRing, image: PanoramicImage, imageWidth, imageHeight) {\r\n let sections = [];\r\n let horizontalShift = this.getHorizontalShift(polyPointRing, imageWidth);\r\n\r\n // Add horizontal shift\r\n polyPointRing = polyPointRing.map(x=> {\r\n return [(x[0] + horizontalShift) % imageWidth, x[1]];\r\n });\r\n\r\n // Interpolate pixels for smooth curve in pixel space\r\n polyPointRing = image.interpolatePixels(\r\n polyPointRing, imageWidth, imageHeight);\r\n\r\n const polygon = turfPolygon([polyPointRing]);\r\n\r\n if (horizontalShift === 0) {\r\n // No shift is required, which means the entire polygon is\r\n // inside the bounds of the image and no intersects are required\r\n const geometry = polygon.geometry;\r\n const coordinates = [...geometry.coordinates[0]];\r\n coordinates.pop();\r\n return [coordinates];\r\n }\r\n\r\n let imageBordersLeft = [\r\n [-9999, 0],\r\n [-9999, imageHeight],\r\n [horizontalShift-0.05, imageHeight],\r\n [horizontalShift-0.05, 0],\r\n [-9999, 0]\r\n ];\r\n\r\n let imageBordersRight = [\r\n [horizontalShift, 0],\r\n [horizontalShift, imageHeight],\r\n [9999, imageHeight],\r\n [9999, 0],\r\n [horizontalShift, 0]\r\n ];\r\n\r\n const polygonLeft = turfPolygon([imageBordersLeft]);\r\n const polygonRight = turfPolygon([imageBordersRight]);\r\n\r\n const intersectionLeft = turfIntersect(polygon, polygonLeft);\r\n const intersectionRight = turfIntersect(polygon, polygonRight);\r\n\r\n sectionsFromIntersection(intersectionLeft).forEach(arr => {\r\n sections.push(arr);\r\n });\r\n\r\n sectionsFromIntersection(intersectionRight).forEach(arr => {\r\n sections.push(arr);\r\n });\r\n\r\n // Subtract shift from sections\r\n sections = sections.map(points => {\r\n return points.map(point => {\r\n let y = point[1];\r\n let x = point[0] - horizontalShift;\r\n x = (x + imageWidth) % imageWidth;\r\n\r\n return [x, y];\r\n });\r\n });\r\n\r\n return sections;\r\n }\r\n\r\n /** @private */\r\n getHorizontalShift(polyPointRing, imageWidth) {\r\n let minSpread = Infinity;\r\n let widthCutoff = imageWidth / 4.0;\r\n let horizontalShift = 0;\r\n\r\n let increment = Math.ceil(imageWidth/20);\r\n let xValues = polyPointRing.map(point => point[0]);\r\n let minX = Math.min(...xValues);\r\n let maxX = Math.max(...xValues);\r\n let spread = Math.abs(minX - maxX);\r\n\r\n // Polygon must be good, return immediately\r\n if (spread < widthCutoff) {\r\n return 0;\r\n }\r\n\r\n for (var i=0; i [x.u, x.v]);\r\n let polyPointRing = [...coordinates, coordinates[0]];\r\n\r\n if (image instanceof PlanarImage) {\r\n sections = this.calculatePlanarSections(\r\n polyPointRing, imageWidth, imageHeight);\r\n } else if (image instanceof PanoramicImage) {\r\n if (label.isThing) {\r\n sections = this.calculatePanoramicSections(\r\n polyPointRing, image, imageWidth, imageHeight);\r\n } else {\r\n sections = [polyPointRing];\r\n }\r\n\r\n }\r\n\r\n return sections;\r\n }\r\n\r\n pointsToPixels(points): ImagePixel[] {\r\n return points.map(x => {\r\n return {u: x[0], v: x[1]} as ImagePixel;\r\n });\r\n }\r\n\r\n getCameraSize(image) {\r\n let width = 0;\r\n let height = 0;\r\n\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n if (label.camera === image) {\r\n width = label.imageWidth;\r\n height = label.imageHeight;\r\n }\r\n });\r\n });\r\n\r\n return {width, height};\r\n }\r\n\r\n jsonImageObj() {\r\n let images = this.visibleCameras.map((image, imageIndex) => {\r\n const {width, height} = this.getCameraSize(image);\r\n return {\r\n height: height,\r\n width: width,\r\n id: imageIndex,\r\n file_name: image.name,\r\n } as CocoImage;\r\n });\r\n\r\n return images;\r\n }\r\n\r\n getTrainingAnnotations() {\r\n return [];\r\n }\r\n\r\n getLabelAnnotations() {\r\n let labelIndex = 1;\r\n let mergeIndex = 1;\r\n let annotations = [];\r\n\r\n const visibleCameras = this.visibleCameras;\r\n\r\n this.categories.forEach((category, categoryID) => {\r\n category.labels.forEach(label => {\r\n if (!label.valid) return;\r\n\r\n const imageID = visibleCameras.indexOf(label.camera);\r\n const polygonsInside = this.polygonInImage(label);\r\n const mergeable = polygonsInside.length > 1;\r\n\r\n polygonsInside.forEach((polygon, index) => {\r\n let annotation = annotationFromPolygon(\r\n polygon,\r\n labelIndex,\r\n categoryID,\r\n imageID,\r\n mergeable ? mergeIndex : null,\r\n label.score,\r\n label.text,\r\n label.textScore,\r\n label.findText\r\n );\r\n\r\n annotations.push(annotation);\r\n labelIndex++;\r\n });\r\n\r\n if (mergeable) {\r\n mergeIndex++;\r\n }\r\n });\r\n });\r\n\r\n return annotations;\r\n }\r\n\r\n setPointScale(mesh) {\r\n const scale = getPointScale(this.viewer.camera, mesh);\r\n mesh.scale.set(scale, scale, scale);\r\n mesh.geometry.computeBoundingSphere();\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n if (!changeDetector.changed) return;\r\n\r\n if (changeDetector.cameraChanged || changeDetector.orbitChanged) {\r\n this.categories.forEach(category => {\r\n // Remove incomplete observation if camera changed\r\n category.deleteUnfinishedLabel();\r\n this.resetTemporaryPoint();\r\n });\r\n\r\n this.drawAll();\r\n return;\r\n }\r\n\r\n this.standardScene.children.forEach(mesh => {\r\n if (mesh instanceof LabelPoint) {\r\n this.setPointScale(mesh);\r\n }\r\n });\r\n }\r\n}\r\n\r\n","import { Viewer } from \"../main\";\r\nimport { RayCaster } from \"../ray-caster\";\r\nimport { getPointScale } from \"../utilities\";\r\nimport {\r\n Box3,\r\n BoxGeometry,\r\n BufferGeometry,\r\n Color,\r\n DoubleSide,\r\n EdgesGeometry,\r\n Euler,\r\n Group,\r\n Line,\r\n Line3,\r\n LineBasicMaterial,\r\n LineSegments,\r\n Matrix4,\r\n Mesh,\r\n MeshBasicMaterial,\r\n Plane,\r\n PlaneGeometry,\r\n SphereGeometry,\r\n Vector3\r\n} from \"three\";\r\nimport LocalScene, { SceneCoordinate } from \"../projections\";\r\nimport { t } from \"../../localization\";\r\n\r\nexport class ScaleHandle extends Mesh {\r\n private clippingBox: ClippingBox;\r\n\r\n constructor(clippingBox: ClippingBox, opts) {\r\n const geometry = new PlaneGeometry(1, 1);\r\n const material = new MeshBasicMaterial({\r\n color: opts.color,\r\n side: DoubleSide,\r\n opacity: 0.6,\r\n transparent: true\r\n });\r\n\r\n super(geometry, material);\r\n\r\n this.clippingBox = clippingBox;\r\n this.position.copy(opts.position);\r\n this.lookAt(new Vector3(0,0,0));\r\n this.scale.set(2.0, 2.0, 2.0);\r\n this.visible = false;\r\n }\r\n\r\n get tooltip() {\r\n return [\r\n t('point-markup.click_and_hold_to_adjust_bounding_box'),\r\n t('point-markup.hold_to_select_background_planes')\r\n ];\r\n }\r\n\r\n get viewer() {\r\n return this.clippingBox.viewer;\r\n }\r\n\r\n set highlighted(state) {\r\n this.visible = state;\r\n }\r\n\r\n drag(event, point) {\r\n const raycaster = new RayCaster(this.viewer, event);\r\n const camera = this.viewer.camera;\r\n\r\n // Opposite cube face\r\n const minusPoint = new Vector3()\r\n .add(this.position)\r\n .multiplyScalar(-1.0)\r\n .applyMatrix4(this.parent.matrix);\r\n\r\n const lineStart = new Vector3()\r\n .copy(this.parent.position);\r\n\r\n const lineEnd = new Vector3()\r\n .add(this.position)\r\n .applyMatrix4(this.parent.matrix);\r\n\r\n const line = new Line3(lineStart, lineEnd);\r\n\r\n const camOnLine = new Vector3();\r\n line.closestPointToPoint(camera.position, false, camOnLine);\r\n\r\n // Normal from camera to line\r\n const normal = new Vector3()\r\n .add(camera.position)\r\n .sub(camOnLine);\r\n\r\n // Position in direction of plane\r\n const plane = new Plane();\r\n plane.setFromNormalAndCoplanarPoint(normal, point);\r\n const intersect = raycaster.intersectPlane(plane);\r\n if (!intersect) return;\r\n\r\n const intersectOnLine = new Vector3();\r\n line.closestPointToPoint(intersect, false, intersectOnLine);\r\n\r\n // New midpoint\r\n const midpoint = new Vector3()\r\n .add(intersectOnLine)\r\n .add(minusPoint)\r\n .divideScalar(2.0);\r\n\r\n // Stop movement when the cube would become negative width\r\n const axis = new Line3(minusPoint, lineEnd);\r\n const valid = axis.closestPointToPointParameter(midpoint, false) > 0;\r\n if (!valid) return;\r\n\r\n // Update scale\r\n const distance = intersectOnLine.distanceTo(minusPoint);\r\n this.setScale(distance/2.0);\r\n\r\n // Set new position\r\n this.parent.position.copy(midpoint);\r\n }\r\n\r\n setScale(newScale) {\r\n if (this.position.x !== 0) {\r\n this.parent.scale.x = newScale;\r\n }\r\n\r\n if (this.position.y !== 0) {\r\n this.parent.scale.y = newScale;\r\n }\r\n\r\n if (this.position.z !== 0) {\r\n this.parent.scale.z = newScale;\r\n }\r\n }\r\n}\r\n\r\nexport class RotateHandle extends Mesh {\r\n public highlighted\r\n private clippingBox: ClippingBox;\r\n private normal: Vector3;\r\n private ordering;\r\n\r\n constructor(clippingBox: ClippingBox,opts) {\r\n const geometry = new SphereGeometry(0.1, 32, 32);\r\n const material = new MeshBasicMaterial({\r\n color: opts.color\r\n });\r\n\r\n super(geometry, material);\r\n\r\n this.clippingBox = clippingBox;\r\n this.normal = opts.normal;\r\n this.ordering = opts.ordering;\r\n this.position.copy(opts.position);\r\n }\r\n\r\n get tooltip() {\r\n return [\r\n t('point-markup.click_and_hold_to_rotate_bounding_box')\r\n ];\r\n }\r\n\r\n get viewer() {\r\n return this.clippingBox.viewer;\r\n }\r\n\r\n drag(event, point) {\r\n const raycaster = new RayCaster(this.viewer, event);\r\n\r\n const zAxis = new Vector3()\r\n .copy(this.normal)\r\n .applyQuaternion(this.parent.quaternion);\r\n\r\n const plane = new Plane();\r\n plane.setFromNormalAndCoplanarPoint(zAxis, this.parent.position);\r\n\r\n const intersect = raycaster.intersectPlane(plane);\r\n const projected = new Vector3();\r\n plane.projectPoint(intersect, projected);\r\n\r\n const xAxis = new Vector3()\r\n .copy(projected)\r\n .sub(this.parent.position)\r\n .setLength(1.0);\r\n\r\n const yAxis = new Vector3()\r\n .copy(zAxis)\r\n .cross(xAxis);\r\n\r\n const newAxis = [xAxis, yAxis, zAxis];\r\n const matrix = new Matrix4().makeBasis(\r\n newAxis[this.ordering[0]],\r\n newAxis[this.ordering[1]],\r\n newAxis[this.ordering[2]]\r\n );\r\n\r\n const rotation = new Euler().setFromRotationMatrix(matrix);\r\n this.parent.rotation.copy(rotation);\r\n }\r\n}\r\n\r\nexport class PositionHandle extends Mesh {\r\n public highlighted;\r\n private clippingBox: ClippingBox;\r\n\r\n constructor(clippingBox: ClippingBox) {\r\n const geometry = new SphereGeometry(0.1, 32, 32);\r\n const material = new MeshBasicMaterial({\r\n color: 0xFFFF00\r\n });\r\n\r\n super(geometry, material);\r\n\r\n this.clippingBox = clippingBox;\r\n this.highlighted = false;\r\n }\r\n\r\n\r\n get tooltip() {\r\n return [\r\n t('point-markup.click_and_hold_to_move_bounding_box')\r\n ];\r\n }\r\n\r\n get viewer() {\r\n return this.clippingBox.viewer;\r\n }\r\n\r\n get controls() {\r\n return this.viewer.controls;\r\n }\r\n\r\n drag(event, point) {\r\n let {coordinate} = this.controls.getPickerResults(event);\r\n if (!coordinate) return;\r\n\r\n this.clippingBox.position.copy(coordinate);\r\n }\r\n}\r\n\r\nexport class ClippingBox extends Group {\r\n public viewer: Viewer;\r\n private wireframe: LineSegments\r\n private positionHandle: PositionHandle;\r\n private scaleHandles: ScaleHandle[] = [];\r\n private rotateHandles: RotateHandle[] = [];\r\n private wireframeMaterialStandard = new MeshBasicMaterial({color: 0xFFFF00});\r\n private wireframeMaterialHover = new MeshBasicMaterial({color: 0xFFFFFF});\r\n\r\n public operationID = null;\r\n public hidePoints = false;\r\n public updateClassification = false;\r\n public newClassification = 0;\r\n public ignoredClassification = 2;\r\n\r\n constructor(viewer: Viewer, operationID=null) {\r\n super();\r\n\r\n this.viewer = viewer;\r\n this.operationID = operationID;\r\n\r\n this.addWireframe();\r\n this.addScaleHandles();\r\n this.addRotateHandles();\r\n this.addPositionHandle();\r\n }\r\n\r\n get boundingBox() {\r\n const bbox = new Box3()\r\n .setFromObject(this.wireframe);\r\n\r\n return bbox;\r\n }\r\n\r\n get attributes() {\r\n const position = new SceneCoordinate(this.position)\r\n .toDataProjection()\r\n .toArray();\r\n\r\n const rotation = this.rotation\r\n .toArray()\r\n .slice(0,3);\r\n\r\n // Convert scalar to projection units\r\n const dataScale = new Vector3()\r\n .copy(this.scale)\r\n .divideScalar(LocalScene.dataToMeters)\r\n .toArray();\r\n\r\n return {\r\n position,\r\n rotation,\r\n scale: dataScale,\r\n hidePoints: this.hidePoints,\r\n updateClassification: this.updateClassification,\r\n newClassification: this.newClassification,\r\n ignoredClassification: this.ignoredClassification\r\n };\r\n }\r\n\r\n setHover(hover) {\r\n const wireframeMaterial = hover\r\n ? this.wireframeMaterialHover\r\n : this.wireframeMaterialStandard;\r\n\r\n this.wireframe.material = wireframeMaterial;\r\n this.wireframe.material.needsUpdate = true;\r\n }\r\n\r\n setColor(color) {\r\n this.wireframeMaterialStandard.color = new Color(color);\r\n }\r\n\r\n addWireframe() {\r\n // Wireframe\r\n const geometry = new EdgesGeometry(new BoxGeometry(2, 2, 2));\r\n const edgeMesh = new LineSegments(geometry, this.wireframeMaterialStandard);\r\n this.wireframe = edgeMesh;\r\n this.add(edgeMesh);\r\n\r\n // X-Axis\r\n const xAxisMaterial = new LineBasicMaterial({color: 0xFF0000});\r\n const xAxisGeometry = new BufferGeometry().setFromPoints([\r\n new Vector3(0,0,0), new Vector3(1,0,0)]);\r\n const xAxis = new Line(xAxisGeometry, xAxisMaterial);\r\n this.add(xAxis);\r\n\r\n // Y-Axis\r\n const yAxisMaterial = new LineBasicMaterial({color: 0x008000});\r\n const yAxisGeometry = new BufferGeometry().setFromPoints([\r\n new Vector3(0,0,0), new Vector3(0,1,0)]);\r\n const yAxis = new Line(yAxisGeometry, yAxisMaterial);\r\n this.add(yAxis);\r\n\r\n // Z-Axis\r\n const zAxisMaterial = new LineBasicMaterial({color: 0x0000FF});\r\n const zAxisGeometry = new BufferGeometry().setFromPoints([\r\n new Vector3(0,0,0), new Vector3(0,0,1)]);\r\n const zAxis = new Line(zAxisGeometry, zAxisMaterial);\r\n this.add(zAxis);\r\n }\r\n\r\n addScaleHandles() {\r\n const px = new ScaleHandle(this, {\r\n color: 0xFF0000,\r\n position: new Vector3(1,0,0),\r\n });\r\n\r\n const nx = new ScaleHandle(this, {\r\n color: 0xFF0000,\r\n position: new Vector3(-1,0,0),\r\n });\r\n\r\n const py = new ScaleHandle(this, {\r\n color: 0x008000,\r\n position: new Vector3(0,1,0),\r\n });\r\n\r\n const ny = new ScaleHandle(this, {\r\n color: 0x008000,\r\n position: new Vector3(0,-1,0),\r\n });\r\n\r\n const pz = new ScaleHandle(this, {\r\n color: 0x0000FF,\r\n position: new Vector3(0,0,1)\r\n });\r\n\r\n const nz = new ScaleHandle(this, {\r\n color: 0x0000FF,\r\n position: new Vector3(0,0,-1)\r\n });\r\n\r\n const newObjects = [px, nx, py, ny, pz, nz];\r\n newObjects.forEach(object => {\r\n this.scaleHandles.push(object);\r\n this.add(object);\r\n });\r\n }\r\n\r\n addRotateHandles() {\r\n const xRotate = new RotateHandle(this, {\r\n color: 0xFF0000,\r\n rotation: Math.PI/2,\r\n position: new Vector3(0,1,0),\r\n normal: new Vector3(1,0,0),\r\n ordering: [2,0,1]\r\n });\r\n\r\n const yRotate = new RotateHandle(this, {\r\n color: 0x008000,\r\n rotation: 0,\r\n position: new Vector3(0,0,1),\r\n normal: new Vector3(0,1,0),\r\n ordering: [1,2,0]\r\n });\r\n\r\n const zRotate = new RotateHandle(this, {\r\n color: 0x0000FF,\r\n rotation: Math.PI/2,\r\n position: new Vector3(1,0,0),\r\n normal: new Vector3(0,0,1),\r\n ordering: [0,1,2]\r\n });\r\n\r\n const newObjects = [xRotate, yRotate, zRotate];\r\n newObjects.forEach(object => {\r\n this.rotateHandles.push(object);\r\n this.add(object);\r\n });\r\n }\r\n\r\n addPositionHandle() {\r\n const handle = new PositionHandle(this);\r\n this.positionHandle = handle;\r\n this.add(handle);\r\n }\r\n\r\n setVisible(state) {\r\n this.positionHandle.highlighted = false;\r\n\r\n this.scaleHandles.forEach(handle => {\r\n handle.highlighted = state;\r\n });\r\n\r\n this.rotateHandles.forEach(handle => {\r\n handle.highlighted = state;\r\n });\r\n }\r\n\r\n raycast(raycaster, intersects) {\r\n this.positionHandle.raycast(raycaster, intersects);\r\n\r\n //return\r\n this.scaleHandles.forEach(handle => {\r\n handle.raycast(raycaster, intersects);\r\n });\r\n\r\n this.rotateHandles.forEach(handle => {\r\n handle.raycast(raycaster, intersects);\r\n });\r\n }\r\n\r\n update() {\r\n const camera = this.viewer.camera;\r\n const parentScale = this.scale;\r\n\r\n const objects = [this.positionHandle, ...this.rotateHandles];\r\n\r\n objects.forEach(object => {\r\n const objectScale = getPointScale(camera, this);\r\n const highlightScale = object.highlighted ? 1.2 : 1;\r\n\r\n const newScale = new Vector3(1,1,1)\r\n .divide(parentScale)\r\n .multiplyScalar(objectScale)\r\n .multiplyScalar(highlightScale);\r\n\r\n object.scale.copy(newScale);\r\n object.geometry.computeBoundingSphere();\r\n });\r\n }\r\n}\r\n","import { nanoid } from \"@reduxjs/toolkit\";\r\nimport { AmbientLight, Scene, Vector3 } from \"three\";\r\nimport { t } from \"../../localization\";\r\nimport { clearViewerTooltip, setViewerTooltip } from \"../viewer\";\r\nimport { CustomMouseEvent, OrbitPosition, PanoControls } from \"../controls\";\r\nimport { textToColor } from \"../labelling\";\r\nimport { Viewer, ViewerProps } from \"../main\";\r\nimport { RayCaster } from \"../ray-caster\";\r\nimport { getPointScale } from \"../utilities\";\r\nimport { ClippingBox, PositionHandle, RotateHandle } from \"./clipping-box\";\r\n\r\nexport enum OperationType {\r\n Delete,\r\n Classify,\r\n Split\r\n}\r\n\r\nexport class ClippingGroup {\r\n public type;\r\n public name;\r\n public color;\r\n public id = nanoid();\r\n public active = false;\r\n public newClassification = 0;\r\n public ignoredClassification = 0;\r\n\r\n private markupList: PointMarkupList;\r\n public clippingBoxes: ClippingBox[] = [];\r\n\r\n constructor(markupList: PointMarkupList, type, name) {\r\n this.markupList = markupList;\r\n this.type = type;\r\n this.setName(name);\r\n }\r\n\r\n get isDelete() {\r\n return this.type === OperationType.Delete;\r\n }\r\n\r\n get isClassify() {\r\n return this.type === OperationType.Classify;\r\n }\r\n\r\n get isSplit() {\r\n return this.type === OperationType.Split;\r\n }\r\n\r\n get controls() {\r\n return this.markupList.controls;\r\n }\r\n\r\n get scene() {\r\n return this.markupList.scene;\r\n }\r\n\r\n getByID(id) {\r\n return this.clippingBoxes.find(x => x.id === id);\r\n }\r\n\r\n add(clippingBox: ClippingBox) {\r\n clippingBox.setColor(this.color);\r\n clippingBox.hidePoints = this.isDelete;\r\n clippingBox.updateClassification = this.isClassify;\r\n clippingBox.newClassification = this.newClassification;\r\n clippingBox.ignoredClassification = this.ignoredClassification;\r\n\r\n this.clippingBoxes.push(clippingBox);\r\n this.scene.add(clippingBox);\r\n this.setActive(false);\r\n }\r\n\r\n setName(name) {\r\n this.name = name;\r\n this.color = textToColor(name);\r\n\r\n this.clippingBoxes.forEach(clippingBox => {\r\n clippingBox.setColor(this.color);\r\n });\r\n }\r\n\r\n setNewClassification(value) {\r\n this.newClassification = value;\r\n\r\n this.clippingBoxes.forEach(clippingBox => {\r\n clippingBox.newClassification = value;\r\n });\r\n }\r\n\r\n setIgnoredClassification(value) {\r\n this.ignoredClassification = value;\r\n\r\n this.clippingBoxes.forEach(clippingBox => {\r\n clippingBox.ignoredClassification = value;\r\n });\r\n }\r\n\r\n setActive(state) {\r\n this.active = state;\r\n }\r\n\r\n setHover(id, hover) {\r\n const clippingBox = this.getByID(id);\r\n if (!clippingBox) return;\r\n\r\n clippingBox.setHover(hover);\r\n }\r\n\r\n zoom(id) {\r\n const clippingBox = this.getByID(id);\r\n if (!clippingBox) return;\r\n\r\n const pivot = clippingBox.position;\r\n\r\n const axisOffset = new Vector3(2, 0, 0.25)\r\n .applyQuaternion(clippingBox.quaternion)\r\n .multiply(clippingBox.scale)\r\n .multiplyScalar(2.0);\r\n\r\n const orbit = new Vector3()\r\n .copy(clippingBox.position)\r\n .add(axisOffset);\r\n\r\n const position = {orbit, pivot, smooth: true} as OrbitPosition;\r\n this.controls.setOrbitValues(true, position);\r\n }\r\n\r\n resetRotation(id) {\r\n const clippingBox = this.getByID(id);\r\n if (!clippingBox) return;\r\n\r\n let count = 0;\r\n let totalCount = 20;\r\n\r\n let dx = clippingBox.rotation.x / totalCount;\r\n let dy = clippingBox.rotation.y / totalCount;\r\n let dz = clippingBox.rotation.z / totalCount;\r\n\r\n const interval = setInterval(() => {\r\n const index = totalCount - count;\r\n\r\n clippingBox.rotation.set(\r\n dx*index,\r\n dy*index,\r\n dz*index\r\n );\r\n\r\n if (count === totalCount) {\r\n clearInterval(interval);\r\n }\r\n\r\n count = count + 1;\r\n }, 16);\r\n }\r\n\r\n removeByID(id) {\r\n const clippingBox = this.getByID(id);\r\n if (!clippingBox) return;\r\n\r\n this.scene.remove(clippingBox);\r\n this.clippingBoxes = this.clippingBoxes.filter(x => x.id !== id);\r\n }\r\n\r\n clear() {\r\n this.clippingBoxes.forEach(clippingBox => {\r\n this.scene.remove(clippingBox);\r\n });\r\n\r\n this.clippingBoxes = [];\r\n }\r\n\r\n update() {\r\n this.clippingBoxes.forEach(clippingBox => {\r\n clippingBox.update();\r\n });\r\n }\r\n}\r\n\r\nexport class PointMarkupList {\r\n public scene: Scene;\r\n public controls: PanoControls;\r\n public enabled = false;\r\n private mouseEvent = null;\r\n private modifier = false;\r\n private dragObject = null;\r\n public clippingGroups: ClippingGroup[] = [];\r\n\r\n private setMarkupGroups: React.Dispatch;\r\n\r\n constructor(controls: PanoControls, props: ViewerProps) {\r\n const {setMarkupGroups} = props;\r\n\r\n this.controls = controls;\r\n this.setMarkupGroups = setMarkupGroups;\r\n\r\n this.initScene();\r\n }\r\n\r\n get viewer(): Viewer {\r\n return this.controls.viewer;\r\n }\r\n\r\n get standardTooltip() {\r\n return [\r\n t('point-markup.click_to_add_new_bounding_box'),\r\n t('point-markup.right-click_to_cancel')\r\n ];\r\n }\r\n\r\n get active() {\r\n return !!this.activeGroup;\r\n }\r\n\r\n get activeGroup() {\r\n return this.clippingGroups.find(x => x.active);\r\n }\r\n\r\n get clippingBoxes() {\r\n return this.clippingGroups.map(x => x.clippingBoxes).flat();\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n getByID(id) {\r\n return this.clippingGroups.find(x => x.id === id);\r\n }\r\n\r\n setName(id, name) {\r\n const clippingGroup = this.getByID(id);\r\n if (!clippingGroup) return;\r\n\r\n clippingGroup.setName(name);\r\n this.refreshMarkupList();\r\n }\r\n\r\n setActive(id) {\r\n this.clippingGroups.forEach(group => {\r\n group.setActive(group.id === id);\r\n });\r\n this.refreshMarkupList();\r\n }\r\n\r\n addNewGroup(type, name) {\r\n let newGroup = new ClippingGroup(this, type, name);\r\n this.clippingGroups.push(newGroup);\r\n this.refreshMarkupList();\r\n }\r\n\r\n refreshMarkupList() {\r\n this.setMarkupGroups([...this.clippingGroups]);\r\n }\r\n\r\n setState(state) {\r\n if (state) {\r\n this.enable();\r\n } else {\r\n this.disable();\r\n }\r\n }\r\n\r\n zoom(id) {\r\n this.clippingGroups.forEach(group => {\r\n group.zoom(id);\r\n });\r\n }\r\n\r\n resetRotation(id) {\r\n this.clippingGroups.forEach(group => {\r\n group.resetRotation(id);\r\n });\r\n }\r\n\r\n removeClippingGroup(id) {\r\n const clippingGroup = this.getByID(id);\r\n if (!clippingGroup) return;\r\n\r\n clippingGroup.clippingBoxes.forEach(clippingBox => {\r\n this.scene.remove(clippingBox);\r\n });\r\n\r\n this.clippingGroups = this.clippingGroups.filter(x => x.id !== id);\r\n this.refreshMarkupList();\r\n }\r\n\r\n removeClippingBox(id) {\r\n this.clippingGroups.forEach(clippingGroup => {\r\n clippingGroup.removeByID(id);\r\n });\r\n\r\n this.refreshMarkupList();\r\n }\r\n\r\n setHover(id, state) {\r\n this.clippingGroups.forEach(clippingGroup => {\r\n clippingGroup.setHover(id, state);\r\n });\r\n }\r\n\r\n setNewClassification(id, value) {\r\n const clippingGroup = this.getByID(id);\r\n if (!clippingGroup) return;\r\n\r\n clippingGroup.setNewClassification(value);\r\n }\r\n\r\n setIgnoredClassification(id, value) {\r\n const clippingGroup = this.getByID(id);\r\n if (!clippingGroup) return;\r\n\r\n clippingGroup.setIgnoredClassification(value);\r\n }\r\n\r\n enable() {\r\n this.enabled = true;\r\n }\r\n\r\n disable() {\r\n this.enabled = false;\r\n\r\n this.clippingGroups.forEach(clippingGroup => {\r\n clippingGroup.clear();\r\n });\r\n\r\n this.clippingGroups = [];\r\n this.refreshMarkupList();\r\n\r\n clearViewerTooltip();\r\n }\r\n\r\n clear() {\r\n this.disable();\r\n this.enable();\r\n }\r\n\r\n addNewBlock(event) {\r\n if (this.dragObject) return;\r\n\r\n let {coordinate} = this.controls.getPickerResults(event);\r\n if (!coordinate) return;\r\n\r\n const camera = this.viewer.camera;\r\n\r\n const clippingBox = new ClippingBox(this.viewer);\r\n clippingBox.position.copy(coordinate);\r\n\r\n const vector = new Vector3()\r\n .add(coordinate)\r\n .sub(camera.position)\r\n .setLength(1.0);\r\n\r\n const cameraAngle = Math.atan2(vector.y, vector.x) - Math.PI / 2;\r\n const newBoxScale = getPointScale(camera, clippingBox);\r\n clippingBox.rotation.z = cameraAngle;\r\n clippingBox.scale.setScalar(newBoxScale);\r\n\r\n this.activeGroup.add(clippingBox);\r\n\r\n clearViewerTooltip();\r\n this.refreshMarkupList();\r\n }\r\n\r\n clearNewBlock() {\r\n this.clippingGroups.forEach(group => {\r\n group.setActive(false);\r\n });\r\n\r\n clearViewerTooltip();\r\n this.refreshMarkupList();\r\n }\r\n\r\n setDragObject(dragObject) {\r\n this.dragObject = dragObject;\r\n\r\n let draggable = dragObject ? true : false;\r\n let controls = this.viewer.controls;\r\n controls.setMovementState(!draggable);\r\n }\r\n\r\n getDragObject(event, camera) {\r\n const raycaster = new RayCaster(this.viewer, event);\r\n\r\n this.clippingBoxes.forEach(object => {\r\n object.setVisible(false);\r\n });\r\n\r\n // Ignore clipping box if we are inside its bounds\r\n const objects = this.clippingBoxes.filter(clippingBox => {\r\n const bbox = clippingBox.boundingBox;\r\n return !bbox.containsPoint(camera.position);\r\n });\r\n\r\n let intersects = raycaster.intersectObjects(objects, {\r\n recursive: false\r\n });\r\n\r\n if (intersects.length === 0) {\r\n this.setDragObject(null);\r\n return;\r\n }\r\n\r\n // Position and rotation have priority\r\n const handleOverride = intersects\r\n .find(intersect => {\r\n const isPosition = intersect.object instanceof PositionHandle;\r\n const isRotation = intersect.object instanceof RotateHandle;\r\n return isPosition || isRotation;\r\n });\r\n\r\n if (handleOverride) {\r\n this.setDragObject(handleOverride);\r\n } else {\r\n if (this.modifier && intersects.length > 1) {\r\n this.setDragObject(intersects[1]);\r\n } else {\r\n this.setDragObject(intersects[0]);\r\n }\r\n }\r\n\r\n const {object} = this.dragObject;\r\n object.highlighted = true;\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent) {\r\n if (!this.enabled || !this.active || event.mouseMoved) {\r\n return false;\r\n }\r\n\r\n if (event.isLeftClick) {\r\n this.addNewBlock(event);\r\n } else if (event.isRightClick) {\r\n this.clearNewBlock();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n if (!this.enabled || !event) return false;\r\n\r\n const camera = this.viewer.camera;\r\n this.mouseEvent = event;\r\n\r\n if (this.dragObject) {\r\n const {object} = this.dragObject;\r\n setViewerTooltip(object.tooltip);\r\n } else {\r\n if (this.active) {\r\n setViewerTooltip(this.standardTooltip);\r\n } else {\r\n clearViewerTooltip();\r\n }\r\n }\r\n\r\n this.getDragObject(event, camera);\r\n\r\n if (this.dragObject) return true;\r\n\r\n return this.active;\r\n }\r\n\r\n onMouseDrag(event: CustomMouseEvent) {\r\n if (!this.dragObject) return false;\r\n\r\n if (event.mouseDown && event.isLeftClick) {\r\n this.updateDraggablePoint(event);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onKeyDown(event) {\r\n if (!this.enabled) return;\r\n\r\n if ((event.key === \"Alt\") && !this.modifier) {\r\n this.modifier = true;\r\n this.onMouseMove(this.mouseEvent);\r\n }\r\n }\r\n\r\n onKeyUp(event) {\r\n if (!this.enabled) return;\r\n\r\n if (event.key === \"Alt\") {\r\n this.modifier = false;\r\n this.setDragObject(null);\r\n this.onMouseMove(this.mouseEvent);\r\n }\r\n }\r\n\r\n updateDraggablePoint(event: CustomMouseEvent) {\r\n const {object, point} = this.dragObject;\r\n object.drag(event, point);\r\n }\r\n\r\n update() {\r\n this.clippingGroups.forEach(group => {\r\n group.update();\r\n });\r\n }\r\n}\r\n","let isFirstTouch = false;\r\nlet numTouching = 0;\r\nlet pinchStart = null;\r\nlet pinchEnd = null;\r\n\r\nexport const touchToMouse = (event) => {\r\n let touches = event.changedTouches;\r\n\r\n // touchstart will increment numTouching\r\n if (event.type === \"touchstart\") {\r\n if (numTouching === 0) {\r\n isFirstTouch = true;\r\n numTouching = numTouching + 1;\r\n } else {\r\n isFirstTouch = false;\r\n }\r\n }\r\n\r\n // touchend will decrement numTouching\r\n if (event.type === \"touchend\") {\r\n numTouching = Math.max(0, numTouching - 1);\r\n }\r\n\r\n // Single touch, so create a fake mouse event instead\r\n if (touches.length === 1) {\r\n // We dont want to move after a pinch effect (it will be super glitchy)\r\n if (event.type === \"touchmove\") {\r\n if (!isFirstTouch) {\r\n return null;\r\n }\r\n }\r\n\r\n let first = touches[0];\r\n let eventType = \"\";\r\n\r\n switch (event.type) {\r\n case \"touchstart\":\r\n eventType = \"mousedown\";\r\n break;\r\n case \"touchmove\":\r\n eventType = \"mousemove\";\r\n break;\r\n case \"touchend\":\r\n eventType = \"mouseup\";\r\n break;\r\n default:\r\n return null;\r\n }\r\n\r\n event = new MouseEvent(eventType, {\r\n bubbles: true,\r\n cancelable: true,\r\n view: window,\r\n detail: 1,\r\n screenX: first.screenX,\r\n screenY: first.screenY,\r\n clientX: first.clientX,\r\n clientY: first.clientY,\r\n ctrlKey: false,\r\n altKey: false,\r\n shiftKey: false,\r\n metaKey: false,\r\n button: 0\r\n });\r\n\r\n return event;\r\n }\r\n\r\n // 2 finger touch (zoom in or out)\r\n if (touches.length === 2) {\r\n if (event.type === \"touchmove\") {\r\n let dist = Math.sqrt(\r\n (touches[0].clientX - touches[1].clientX) * (touches[0].clientX - touches[1].clientX) +\r\n (touches[0].clientY - touches[1].clientY) * (touches[0].clientY - touches[1].clientY)\r\n );\r\n\r\n if (pinchStart === null) {\r\n pinchStart = dist;\r\n } else {\r\n pinchEnd = dist;\r\n let pinchMove = pinchStart - pinchEnd;\r\n let sign = pinchMove / (Math.abs(pinchMove));\r\n\r\n event = new MouseEvent('wheel', {\r\n bubbles: true,\r\n cancelable: true,\r\n view: window,\r\n screenX: 0,\r\n screenY: 0,\r\n clientX: 0,\r\n clientY: 0,\r\n detail: sign,\r\n ctrlKey: false,\r\n altKey: false,\r\n shiftKey: false,\r\n metaKey: false,\r\n button: 0\r\n });\r\n event.deltaY = sign;\r\n pinchStart = null;\r\n\r\n return event;\r\n }\r\n }\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const onLongPress = (event) => {\r\n return new MouseEvent('mouseup', {\r\n bubbles: true,\r\n cancelable: true,\r\n view: window,\r\n detail: 1,\r\n screenX: event.changedPointers[0].screenX,\r\n screenY: event.changedPointers[0].screenY,\r\n clientX: event.changedPointers[0].clientX,\r\n clientY: event.changedPointers[0].clientY,\r\n ctrlKey: false,\r\n altKey: false,\r\n shiftKey: false,\r\n metaKey: false,\r\n button: 2\r\n });\r\n};\r\n\r\nexport const onDoubleTap = (event) => {\r\n let pointer = event.changedPointers[0];\r\n\r\n return new MouseEvent('dblclick', {\r\n bubbles: true,\r\n cancelable: true,\r\n view: window,\r\n detail: 1,\r\n screenX: pointer.screenX,\r\n screenY: pointer.screenY,\r\n clientX: pointer.clientX,\r\n clientY: pointer.clientY,\r\n ctrlKey: false,\r\n altKey: false,\r\n shiftKey: false,\r\n metaKey: false,\r\n button: 0\r\n });\r\n};\r\n","import {\r\n DataProjectionCoordinate,\r\n SceneCoordinate\r\n} from \"../projections\";\r\nimport Chart from 'chart.js/auto';\r\nimport zoomPlugin from 'chartjs-plugin-zoom';\r\nimport {\r\n Line3,\r\n Mesh,\r\n MeshBasicMaterial,\r\n Scene,\r\n SphereGeometry,\r\n Vector2,\r\n Vector3\r\n} from \"three\";\r\nimport { CustomMouseEvent, PanoControls } from \"../controls\";\r\nimport { UnitConverter } from \"../utilities\";\r\nimport { t } from \"../../localization\";\r\nimport { ViewerProps } from \"../main\";\r\nimport { Units } from \"../../types/project\";\r\n\r\nChart.register(zoomPlugin);\r\n\r\nexport class PointProfile {\r\n public drawing = false;\r\n public scene = new Scene();\r\n public controls: PanoControls;\r\n public profileChart: ProfileChart;\r\n public line2D = new Line3();\r\n public line3D = new Line3();\r\n private sphere: Mesh;\r\n\r\n private lineWidth = 0.5;\r\n private hoverColor = 0x099c7b;\r\n private markerSize = 0.05;\r\n\r\n constructor(controls: PanoControls, props) {\r\n this.controls = controls;\r\n this.profileChart = new ProfileChart(this, props);\r\n\r\n this.initSphere();\r\n this.reset();\r\n }\r\n\r\n get viewer() {\r\n return this.controls.viewer;\r\n }\r\n\r\n get pointclouds() {\r\n return this.viewer.pointclouds;\r\n }\r\n\r\n reset() {\r\n this.line3D = new Line3();\r\n this.clearScene();\r\n this.updateUniforms();\r\n }\r\n\r\n destroy() {\r\n this.profileChart.destroy();\r\n }\r\n\r\n initSphere() {\r\n let geometry = new SphereGeometry(this.markerSize, 20, 20);\r\n let material = new MeshBasicMaterial({color: this.hoverColor});\r\n this.sphere = new Mesh(geometry, material);\r\n this.hideSphere();\r\n }\r\n\r\n clearScene() {\r\n if (!this.scene) return;\r\n this.scene.remove(this.sphere);\r\n }\r\n\r\n updateUniforms() {\r\n this.pointclouds.updateCrossSection(this.line3D.start,\r\n this.line3D.end, this.lineWidth);\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n if (!this.drawing) return false;\r\n\r\n let {coordinate} = this.controls.getPickerResults(event);\r\n\r\n if (coordinate) {\r\n this.line3D.end = coordinate;\r\n this.updateUniforms();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent) {\r\n if (!this.drawing) return false;\r\n\r\n return event.isLeftClick;\r\n }\r\n\r\n selectStart(coordinate: number[]) {\r\n this.reset();\r\n this.profileChart.setData([]);\r\n this.drawing = true;\r\n\r\n const localPosition = new DataProjectionCoordinate(coordinate)\r\n .toScene();\r\n\r\n this.line3D.start.copy(localPosition);\r\n this.line3D.end.copy(localPosition);\r\n }\r\n\r\n selectEnd() {\r\n this.line2D = new Line3().copy(this.line3D);\r\n this.line2D.end.setZ(0);\r\n this.line2D.start.setZ(0);\r\n\r\n if (this.line3D.distance() === 0) {\r\n return;\r\n }\r\n\r\n this.drawing = false;\r\n this.updateUniforms();\r\n this.updatePoints();\r\n this.resetZoom();\r\n }\r\n\r\n selectCancel() {\r\n this.reset();\r\n this.drawing = false;\r\n }\r\n\r\n updatePoints() {\r\n let center = new Vector3();\r\n this.line3D.getCenter(center);\r\n let distance = this.line3D.distance() + this.lineWidth;\r\n\r\n // Grab points in a radius around our line\r\n let points = this.pointclouds.pointsInRadius(center, distance);\r\n\r\n // Filter for points that are along our line, with a valid width\r\n points = points.filter(vector => {\r\n let linePoint = new Vector3();\r\n this.line2D.closestPointToPoint(vector, false, linePoint);\r\n\r\n // Calculate distance from line\r\n let dx = vector.x - linePoint.x;\r\n let dy = vector.y - linePoint.y;\r\n let distanceAcrossLine = Math.sqrt(dx**2 + dy**2);\r\n let validWidth = distanceAcrossLine <= (this.lineWidth / 2.0);\r\n\r\n // Calculate distance along line\r\n let distanceAlongLine = this.line2D.closestPointToPointParameter(linePoint, false);\r\n let validDistance = (distanceAlongLine >= 0) && (distanceAlongLine <= 1);\r\n\r\n // Remember our distance travelled\r\n vector.distance = distanceAlongLine * this.line2D.distance();\r\n\r\n return validDistance && validWidth;\r\n });\r\n\r\n // Sort by distance along line\r\n points.sort((a, b) => a.distance - b.distance);\r\n\r\n this.profileChart.setData(points);\r\n this.profileChart.show();\r\n }\r\n\r\n drawSphere(position) {\r\n this.scene.remove(this.sphere);\r\n\r\n // Point to draw is snapped to the line, but with\r\n // the height of the original point\r\n let linePoint = new Vector3();\r\n let distanceClamped = position.distance / this.line2D.distance();\r\n this.line3D.at(distanceClamped, linePoint);\r\n linePoint.z = position.z;\r\n\r\n this.sphere.position.copy(linePoint);\r\n this.scene.add(this.sphere);\r\n }\r\n\r\n hideSphere() {\r\n if (!this.sphere) return;\r\n this.sphere.visible = false;\r\n }\r\n\r\n showSphere() {\r\n if (!this.sphere) return;\r\n this.sphere.visible = true;\r\n }\r\n\r\n resetZoom() {\r\n this.profileChart.resetZoom();\r\n }\r\n\r\n updateUnits(units: Units) {\r\n this.profileChart.updateUnits(units);\r\n }\r\n\r\n updateSampling(type) {\r\n this.profileChart.updateSampling(type);\r\n }\r\n\r\n getProfileImage() {\r\n return this.profileChart.chartImageBase64.toBase64Image();\r\n }\r\n}\r\n\r\nclass ProfileChart {\r\n private data = [];\r\n private sampled = [];\r\n\r\n private displayUnits = Units.Meters;\r\n private samplingType = \"highest\";\r\n private samplingRate = 1000;\r\n private sampleMinimum = 0.02;\r\n private sampleMaximum = 1.00;\r\n\r\n private chart: Chart;\r\n private converter = new UnitConverter();\r\n private pointProfile: PointProfile;\r\n\r\n public setPointProfileOpen: React.Dispatch;\r\n\r\n constructor(pointProfile: PointProfile, props: ViewerProps) {\r\n const {setPointProfileOpen} = props;\r\n\r\n this.data = [];\r\n this.sampled = [];\r\n this.pointProfile = pointProfile;\r\n\r\n this.setPointProfileOpen = setPointProfileOpen;\r\n }\r\n\r\n get viewer() {\r\n return this.pointProfile.viewer;\r\n }\r\n\r\n get chartImageBase64() {\r\n return this.chart;\r\n }\r\n\r\n init(type, units: Units) {\r\n const element = document.getElementById('profile-chart') as HTMLCanvasElement;\r\n const canvas = element.getContext('2d');\r\n\r\n const scales = {\r\n x: {\r\n type: 'linear',\r\n title: {\r\n display: true,\r\n text: t('profile.axis-distance')\r\n },\r\n ticks: {\r\n callback: value => {\r\n const output = this.convert(value);\r\n return `${output.toFixed(2)} ${this.displayUnits}.`;\r\n }\r\n }\r\n },\r\n y: {\r\n type: 'linear',\r\n title: {\r\n display: true,\r\n text: t('profile.axis-height')\r\n },\r\n ticks: {\r\n callback: value => {\r\n const output = this.convert(value);\r\n return `${output.toFixed(2)} ${this.displayUnits}.`;\r\n }\r\n }\r\n },\r\n };\r\n\r\n const tooltip = {\r\n caretPadding: 10,\r\n displayColors: false,\r\n filter: (_, index) => {\r\n // Return the first result only\r\n return index === 0;\r\n },\r\n callbacks: {\r\n label: context => {\r\n let vector = this.sampled[context.dataIndex];\r\n this.pointProfile.drawSphere(vector);\r\n\r\n const distance = this.convert(context.raw.x);\r\n const height = this.convert(context.raw.y);\r\n\r\n return [\r\n t(\"profile.height\", {\r\n height: height.toFixed(2),\r\n units: this.displayUnits\r\n }),\r\n t(\"profile.distance\", {\r\n distance: distance.toFixed(2),\r\n units: this.displayUnits\r\n }),\r\n ];\r\n }\r\n }\r\n };\r\n\r\n const plugins = {\r\n tooltip,\r\n legend: {\r\n display: false\r\n },\r\n title: {\r\n display: true,\r\n text: t('profile.elevation-profile'),\r\n fontSize: 14\r\n },\r\n zoom: {\r\n pan: {\r\n enabled: true,\r\n mode: 'xy',\r\n },\r\n zoom: {\r\n wheel: {\r\n enabled: true,\r\n },\r\n pinch: {\r\n enabled: true\r\n },\r\n mode: 'y',\r\n }\r\n }\r\n };\r\n\r\n const onHover = (_, items) => {\r\n if (items.length) {\r\n this.pointProfile.showSphere();\r\n } else {\r\n this.pointProfile.hideSphere();\r\n }\r\n };\r\n\r\n const otherOptions = {\r\n maintainAspectRatio: false,\r\n legend: {display: false},\r\n animation: {duration: 0},\r\n hover: {animationDuration: 0},\r\n responsive: true,\r\n responsiveAnimationDuration: 0\r\n };\r\n\r\n const dataset = {\r\n label: \"\",\r\n backgroundColor: 'rgb(255, 99, 132)',\r\n borderColor: 'rgb(255, 99, 132)',\r\n pointHoverBackgroundColor: 'rgb(0, 156, 123)',\r\n pointHoverBorderColor: 'rgb(0, 156, 123)',\r\n data: []\r\n };\r\n\r\n this.chart?.destroy();\r\n this.chart = new Chart(canvas, {\r\n type: 'scatter',\r\n data: {\r\n datasets: [dataset]\r\n },\r\n options: {\r\n onHover,\r\n plugins,\r\n scales,\r\n ...otherOptions\r\n } as any\r\n });\r\n\r\n this.updateUnits(units);\r\n this.updateSampling(type);\r\n }\r\n\r\n convert(value) {\r\n return this.converter.convert(value, Units.Meters, this.displayUnits, 2);\r\n }\r\n\r\n destroy() {\r\n this.chart?.destroy();\r\n }\r\n\r\n setData(data) {\r\n this.data = data;\r\n this.updateChart();\r\n }\r\n\r\n hide() {\r\n this.setPointProfileOpen(false);\r\n this.pointProfile.hideSphere();\r\n }\r\n\r\n show() {\r\n this.setPointProfileOpen(true);\r\n }\r\n\r\n resetZoom() {\r\n if (!this.chart) return;\r\n this.chart.resetZoom();\r\n }\r\n\r\n getSampledData() {\r\n let pointcloud = this.viewer.pointclouds;\r\n let highest = this.samplingType === \"highest\";\r\n let lineLength = this.pointProfile.line2D.distance();\r\n\r\n let distance = lineLength / this.samplingRate;\r\n distance = Math.max(this.sampleMinimum, distance);\r\n distance = Math.min(this.sampleMaximum, distance);\r\n\r\n const callback = point => {\r\n return Math.floor(point.distance / distance);\r\n };\r\n\r\n return pointcloud.getSampledPoints(this.data, highest, callback);\r\n }\r\n\r\n updateChart() {\r\n if (!this.chart) return;\r\n\r\n const needsSampling = this.samplingType !== \"all\";\r\n\r\n this.sampled = needsSampling\r\n ? this.getSampledData()\r\n : this.data;\r\n\r\n const numPoints = this.sampled.length;\r\n const chartTitle = needsSampling\r\n ? t('profile.elevation-profile-sampled-points', {numPoints})\r\n : t('profile.elevation-profile-points', {numPoints});\r\n\r\n // Convert to distance + projected height\r\n const points = this.sampled.map(vector => {\r\n const coordinate = new SceneCoordinate(vector)\r\n .toDataProjection();\r\n\r\n const height = coordinate.z;\r\n const distance = vector.distance;\r\n return new Vector2(distance, height);\r\n });\r\n\r\n // Update chart with new data\r\n this.chart.options.plugins.title.text = chartTitle;\r\n this.chart.data.datasets[0].data = points;\r\n this.chart.update();\r\n }\r\n\r\n /** Update units and refresh chart ui */\r\n updateUnits(units: Units) {\r\n this.displayUnits = units;\r\n\r\n if (!this.chart) return;\r\n this.chart.update();\r\n }\r\n\r\n updateSampling(type) {\r\n this.samplingType = type;\r\n this.updateChart();\r\n }\r\n}\r\n","import CustomOrbitControls from \"./orbit-controls\";\r\nimport {Viewer} from '../main';\r\nimport { CameraAlignerAdv, CameraAlignerBasic, LocalAligner } from '../data-aligner';\r\nimport { ChangeDetector, isMobile, mergeBoundingBoxes } from '../utilities';\r\nimport { SceneCoordinate, SphericalPosition } from '../projections';\r\nimport {\r\n PerspectiveCamera,\r\n Scene,\r\n Vector3,\r\n} from 'three';\r\nimport { PointMarkupList } from \"../markup\";\r\nimport { MouseControls, touchToMouse } from \".\";\r\nimport Hammer from \"hammerjs\";\r\nimport { onDoubleTap, onLongPress } from \"./mobile-controls\";\r\nimport { showContextMenu } from \"../../context-menu\";\r\nimport { PointProfile } from \"../point-profile\";\r\nimport { directionToCameraAngle } from \"../cameras\";\r\n\r\nexport interface OrbitPosition {\r\n orbit: Vector3,\r\n pivot: Vector3\r\n smooth: boolean;\r\n}\r\n\r\ninterface SavedCameraState {\r\n fov: number;\r\n angles: number[];\r\n orbitState: boolean;\r\n orbitPosition: Vector3;\r\n orbitTarget: Vector3;\r\n}\r\n\r\nexport class PanoControls {\r\n public viewer: Viewer;\r\n public object: PerspectiveCamera;\r\n public scene: Scene;\r\n public domElement: HTMLCanvasElement;\r\n public mouseControls: MouseControls;\r\n public cameraAlignerAdv: CameraAlignerAdv;\r\n public cameraAlignerBasic: CameraAlignerBasic;\r\n public localAligner: LocalAligner;\r\n public pointMarkup: PointMarkupList;\r\n public pointProfile: PointProfile;\r\n private hammer: Hammer;\r\n private enabled = true;\r\n public direction = new Vector3(0, 0, 0);\r\n private up = new Vector3(0, 0, 1);\r\n public orbitControls: OrbitController;\r\n public flyControls: FlyMoveControls;\r\n private oldCameraState: SavedCameraState;\r\n\r\n constructor(viewer: Viewer, object: PerspectiveCamera, domElement: HTMLCanvasElement, props) {\r\n this.viewer = viewer;\r\n this.object = object;\r\n this.domElement = domElement;\r\n\r\n this.hammer = new Hammer(this.domElement);\r\n this.orbitControls = new OrbitController(this.viewer, this, this.up);\r\n this.flyControls = new FlyMoveControls(this);\r\n this.mouseControls = new MouseControls(this.viewer, this.object);\r\n\r\n this.pointMarkup = new PointMarkupList(this, props);\r\n this.pointProfile = new PointProfile(this, props);\r\n this.cameraAlignerAdv = new CameraAlignerAdv(this, props);\r\n this.cameraAlignerBasic = new CameraAlignerBasic(this);\r\n this.localAligner = new LocalAligner(this, props);\r\n\r\n this.initEvents();\r\n this.initScene();\r\n }\r\n\r\n get anyToolEnabled() {\r\n return this.pointMarkup.enabled\r\n || this.sceneLabels.enabled\r\n || this.measurements.enabled\r\n || this.cameraAlignerAdv.enabled\r\n || this.cameraAlignerBasic.enabled\r\n || this.localAligner.enabled;\r\n }\r\n\r\n get renderUtils() {\r\n return this.viewer.renderUtils;\r\n }\r\n\r\n get cameraHandler() {\r\n return this.viewer.cameraHandler;\r\n }\r\n\r\n get sceneLabels() {\r\n return this.viewer.imageLabels.sceneLabels;\r\n }\r\n\r\n get cadHandler() {\r\n return this.viewer.cadHandler;\r\n }\r\n\r\n get compass() {\r\n return this.viewer.compass;\r\n }\r\n\r\n get tagsHandler() {\r\n return this.viewer.tagsHandler;\r\n }\r\n\r\n get measurements() {\r\n return this.viewer.measurements;\r\n }\r\n\r\n get pointclouds() {\r\n return this.viewer.pointclouds;\r\n }\r\n\r\n get picker() {\r\n return this.viewer.gpuPickers.default;\r\n }\r\n\r\n get fov(): number {\r\n return this.object.fov;\r\n }\r\n\r\n get angles(): number[] {\r\n return this.mouseControls.angles;\r\n }\r\n\r\n set angles(values) {\r\n this.mouseControls.angles = values;\r\n }\r\n\r\n get lookat() {\r\n return this.mouseControls.lookat\r\n .add(this.viewer.camera.position);\r\n }\r\n\r\n destroy() {\r\n this.pointProfile.destroy();\r\n this.removeEvents();\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(this.pointProfile.scene);\r\n this.scene.add(this.cameraAlignerAdv.scene);\r\n this.scene.add(this.pointMarkup.scene);\r\n this.scene.add(this.localAligner.scene);\r\n }\r\n\r\n initEvents() {\r\n this.onMouseDown = this.onMouseDown.bind(this);\r\n this.onMouseUp = this.onMouseUp.bind(this);\r\n this.onMouseWheel = this.onMouseWheel.bind(this);\r\n this.onMouseDoubleClick = this.onMouseDoubleClick.bind(this);\r\n this.onMouseMove = this.onMouseMove.bind(this);\r\n this.touchHandler = this.touchHandler.bind(this);\r\n\r\n this.domElement.addEventListener('mousedown', this.onMouseDown, false);\r\n this.domElement.addEventListener('mouseup', this.onMouseUp, false);\r\n this.domElement.addEventListener('wheel', this.onMouseWheel, false);\r\n this.domElement.addEventListener('dblclick', this.onMouseDoubleClick, false);\r\n this.domElement.addEventListener('mousemove', this.onMouseMove, false);\r\n this.domElement.addEventListener('touchstart', this.touchHandler, true);\r\n this.domElement.addEventListener('touchmove', this.touchHandler, true);\r\n this.domElement.addEventListener('touchend', this.touchHandler, true);\r\n this.domElement.addEventListener('touchcancel', this.touchHandler, true);\r\n\r\n if (!isMobile) return;\r\n\r\n // Doubletap and longpress are handled by hammer.js\r\n this.hammer.on('doubletap', touchEvent => {\r\n const mouseEvent = onDoubleTap(touchEvent);\r\n this.domElement.dispatchEvent(mouseEvent);\r\n });\r\n\r\n this.hammer.on('press', touchEvent => {\r\n const mouseEvent = onLongPress(touchEvent);\r\n this.mouseControls.down = true;\r\n this.domElement.dispatchEvent(mouseEvent);\r\n });\r\n }\r\n\r\n removeEvents() {\r\n this.domElement.removeEventListener('mousedown', this.onMouseDown, false);\r\n this.domElement.removeEventListener('mouseup', this.onMouseUp, false);\r\n this.domElement.removeEventListener('wheel', this.onMouseWheel, false);\r\n this.domElement.removeEventListener('dblclick', this.onMouseDoubleClick, false);\r\n this.domElement.removeEventListener('mousemove', this.onMouseMove, false);\r\n this.domElement.removeEventListener('touchstart', this.touchHandler, true);\r\n this.domElement.removeEventListener('touchmove', this.touchHandler, true);\r\n this.domElement.removeEventListener('touchend', this.touchHandler, true);\r\n this.domElement.removeEventListener('touchcancel', this.touchHandler, true);\r\n this.hammer.destroy();\r\n }\r\n\r\n resetSceneView() {\r\n this.mouseControls.angles = [0, 0];\r\n this.mouseControls.fov = 90;\r\n }\r\n\r\n setControlType(type) {\r\n this.orbitControls.setControls(type);\r\n }\r\n\r\n updateFarPlane(far) {\r\n this.object.far = far;\r\n this.orbitControls.camera.far = far;\r\n }\r\n\r\n getCameraTarget() {\r\n let cameraPosition = this.orbitControls.state\r\n ? this.orbitControls.activeTarget\r\n : this.object.position;\r\n\r\n return cameraPosition;\r\n }\r\n\r\n setOrbitValues(newOrbitState, position: OrbitPosition = null) {\r\n this.viewer.updatePickers();\r\n\r\n const stateChanged = this.orbitControls.state !== newOrbitState;\r\n if (!position && !stateChanged) return;\r\n\r\n let newOrbit;\r\n let newPivot;\r\n let smoothTransition = false;\r\n\r\n this.enabled = false;\r\n if (newOrbitState) {\r\n // Set our orbit controls position and target\r\n if (!position) {\r\n newOrbit = this.object.position;\r\n newPivot = new Vector3(0, 0, -1 * this.orbitControls.rotateLength)\r\n .applyQuaternion(this.object.quaternion)\r\n .add(newOrbit);\r\n } else {\r\n newOrbit = position.orbit;\r\n newPivot = position.pivot;\r\n smoothTransition = position.smooth;\r\n }\r\n\r\n this.orbitControls.setWalkMode(false);\r\n this.orbitControls.setPositionValues(newOrbit, newPivot,\r\n newOrbitState, smoothTransition);\r\n\r\n this.viewer.camera = this.orbitControls.camera;\r\n\r\n if (!smoothTransition) {\r\n this.flyControls.disable();\r\n }\r\n } else {\r\n this.orbitControls.setState(newOrbitState);\r\n this.viewer.camera = this.object;\r\n }\r\n\r\n this.enabled = true;\r\n\r\n // Set panoramic visibility\r\n if (this.cameraHandler) {\r\n this.cameraHandler.setMeshVisible(!newOrbitState);\r\n }\r\n\r\n this.viewer.handleWindowResize();\r\n this.viewer.updateCamera();\r\n }\r\n\r\n getPickerResults(event) {\r\n this.picker.update();\r\n const index = this.picker.value(event);\r\n return this.picker.getClosestCoordinate(index, event);\r\n }\r\n\r\n resetCamera(side) {\r\n const boundingBoxes = [\r\n this.pointclouds.combinedBoundingBox,\r\n this.tagsHandler.combinedBoundingBox,\r\n this.cadHandler.combinedBoundingBox\r\n ];\r\n\r\n let combinedBounds = mergeBoundingBoxes(boundingBoxes);\r\n if (!combinedBounds) return;\r\n\r\n let newPosition = this.orbitFromBounds(combinedBounds, side, true);\r\n this.setOrbitValues(true, newPosition);\r\n }\r\n\r\n orbitFromBounds(bbox: {min: Vector3, max: Vector3}, side, smooth): OrbitPosition {\r\n let boxSize = new Vector3()\r\n .add(bbox.max)\r\n .sub(bbox.min);\r\n\r\n let boxMean = new Vector3()\r\n .add(boxSize)\r\n .divideScalar(2.0)\r\n .add(bbox.min);\r\n\r\n boxSize.multiplyScalar(1.5);\r\n\r\n let boundSize = Math.max(boxSize.x, boxSize.y, boxSize.z);\r\n let height = bbox.min.z + boxSize.z*0.25;\r\n let pivot = new Vector3(boxMean.x, boxMean.y, height);\r\n\r\n // Make sure our initial height doesnt exceed the far plane\r\n let maxHeight = this.viewer.camera.far * 0.75;\r\n let radius = Math.min(maxHeight, boundSize / 2.0);\r\n\r\n let orbit = this.orbitWithAngle(pivot, radius, side);\r\n\r\n return {orbit, pivot, smooth};\r\n }\r\n\r\n orbitWithAngle(pivot, radius, side) {\r\n let theta;\r\n let phi;\r\n\r\n side = side.toLowerCase();\r\n switch (side) {\r\n case \"top\":\r\n theta = 270;\r\n phi = 0.01;\r\n break;\r\n case \"bottom\":\r\n theta = 270;\r\n phi = 179.99;\r\n break;\r\n case \"right\":\r\n theta = 0.0;\r\n phi = 90;\r\n break;\r\n case \"left\":\r\n theta = 180;\r\n phi = 90;\r\n break;\r\n case \"front\":\r\n theta = 270;\r\n phi = 90;\r\n break;\r\n case \"back\":\r\n theta = 90;\r\n phi = 90;\r\n break;\r\n default:\r\n theta = 0.0;\r\n phi = 0.0;\r\n }\r\n\r\n let orbit = new SphericalPosition()\r\n .fromValues(radius, theta, phi)\r\n .toVector3()\r\n .add(pivot);\r\n\r\n return orbit;\r\n }\r\n\r\n onMouseMove(initialEvent) {\r\n initialEvent.preventDefault();\r\n\r\n const event = this.mouseControls.onMouseMove(initialEvent);\r\n\r\n this.viewer.onMouseMove(event);\r\n this.renderUtils.onMouseMove(event);\r\n\r\n const draggingObject = this.measurements.onMouseDrag(event)\r\n || this.pointMarkup.onMouseDrag(event)\r\n || this.sceneLabels.onMouseDrag(event);\r\n\r\n if (draggingObject) return;\r\n\r\n this.compass.onMouseMove(event);\r\n\r\n // Check onMouseMove of all scene elements.\r\n const mouseMoved = this.measurements.onMouseMoveScene(event)\r\n || this.pointMarkup.onMouseMove(event)\r\n || this.sceneLabels.onMouseMove(event)\r\n || this.cameraAlignerAdv.onMouseMove()\r\n || this.pointProfile.onMouseMove(event)\r\n || this.localAligner.onMouseMoveScene()\r\n || this.tagsHandler.onMouseMoveScene(event);\r\n\r\n if (mouseMoved) {\r\n this.cameraHandler.clearArrowNavigation();\r\n } else {\r\n this.cameraHandler.onMouseMove(event);\r\n }\r\n\r\n if (!this.enabled || this.orbitControls.state || !this.mouseControls.movement) {\r\n return;\r\n }\r\n\r\n this.mouseControls.updateRotation(\r\n this.object.fov,\r\n this.domElement.clientWidth,\r\n this.domElement.clientHeight\r\n );\r\n }\r\n\r\n onKeyDown(event) {\r\n this.pointMarkup.onKeyDown(event);\r\n this.cameraAlignerBasic.onKeyDown(event);\r\n\r\n if (event.key === \"Shift\") {\r\n this.onZoomStart();\r\n }\r\n }\r\n\r\n onKeyUp(event) {\r\n this.pointMarkup.onKeyUp(event);\r\n\r\n if (event.key === \"Shift\") {\r\n this.onZoomFinish();\r\n }\r\n }\r\n\r\n onMouseDown(event) {\r\n event.preventDefault();\r\n this.mouseControls.onMouseDown(event);\r\n }\r\n\r\n onMouseUp(initialEvent) {\r\n if (!this.mouseControls.down || !this.enabled) return;\r\n const event = this.mouseControls.onMouseUp(initialEvent);\r\n\r\n this.measurements.measureGrabFinished();\r\n this.orbitControls.toggle(true);\r\n\r\n // Check onMouseUp of all scene elements\r\n const mouseClicked = this.compass.onMouseUp(event)\r\n || this.tagsHandler.onMouseUpScene(event)\r\n || this.pointMarkup.onMouseUp(event)\r\n || this.cameraAlignerAdv.onMouseUp(event)\r\n || this.localAligner.onMouseUp(event)\r\n || this.sceneLabels.onMouseUp(event)\r\n || this.measurements.onMouseUpScene(event)\r\n || this.pointProfile.onMouseUp(event);\r\n\r\n if (!mouseClicked) {\r\n this.cameraHandler.onMouseUp(event);\r\n }\r\n\r\n if (event.mouseMoved && !this.orbitControls.state) {\r\n this.viewer.updatePickers();\r\n }\r\n\r\n if (event.mouseMoved || mouseClicked) return;\r\n\r\n if (event.isRightClick) {\r\n this.cameraHandler.clearArrowNavigation();\r\n this.openContextMenu(event);\r\n }\r\n }\r\n\r\n onMouseWheel(event) {\r\n this.viewer.updatePickers();\r\n this.mouseControls.onMouseScroll();\r\n if (!this.enabled || this.orbitControls.state) return;\r\n\r\n event.preventDefault();\r\n\r\n this.mouseControls.onMouseWheel(event);\r\n }\r\n\r\n onMouseDoubleClick(event) {\r\n if ((!this.enabled) || (this.measurements.enabled)) return;\r\n if (!this.orbitControls.state) return;\r\n\r\n let {coordinate} = this.getPickerResults(event);\r\n if (!coordinate) return;\r\n\r\n const currentOrbit = this.orbitControls.activePosition;\r\n\r\n const vector = new Vector3()\r\n .add(coordinate)\r\n .sub(currentOrbit)\r\n .setLength(2.0);\r\n\r\n const orbit = new Vector3()\r\n .add(coordinate)\r\n .sub(vector);\r\n\r\n // Move to new pointcloud location\r\n this.flyControls.start(coordinate, orbit);\r\n }\r\n\r\n /** @private */\r\n async onZoomStart() {\r\n if (this.renderUtils.zooming) return;\r\n\r\n await this.viewer.updatePreviousTexture();\r\n this.renderUtils.zoomToCursor = true;\r\n this.mouseControls.zoomToCursor = true;\r\n this.saveLastPosition();\r\n\r\n this.viewer.updatePickers();\r\n }\r\n\r\n /** @private */\r\n onZoomFinish() {\r\n if (!this.renderUtils.zooming) return;\r\n this.renderUtils.zoomToCursor = false;\r\n this.mouseControls.zoomToCursor = false;\r\n this.loadLastPosition();\r\n this.viewer.updatePickers();\r\n }\r\n\r\n /** @private */\r\n async saveLastPosition() {\r\n const lookat = this.viewer.lookatVector.clone();\r\n const orbitPosition = this.orbitControls.position.clone();\r\n const orbitTarget = this.orbitControls.target.clone();\r\n\r\n this.oldCameraState = {\r\n fov: this.mouseControls.fov,\r\n angles: this.mouseControls.angles,\r\n orbitState: this.orbitControls.state,\r\n orbitPosition: orbitPosition,\r\n orbitTarget: orbitTarget\r\n };\r\n\r\n if (this.orbitControls.state) {\r\n // Turn on the standard camera\r\n this.setOrbitValues(false);\r\n this.cameraHandler.setMeshVisible(false);\r\n this.viewer.camera.position.copy(orbitPosition);\r\n\r\n const angles = directionToCameraAngle(lookat);\r\n this.mouseControls.zoom(90);\r\n this.mouseControls.angles = angles;\r\n }\r\n\r\n // Start slightly more zoomed in\r\n const fov = this.mouseControls.fov;\r\n this.mouseControls.zoom(fov * 0.70);\r\n }\r\n\r\n /** @private */\r\n loadLastPosition() {\r\n const { fov, angles, orbitState,\r\n orbitPosition, orbitTarget } = this.oldCameraState;\r\n\r\n if (orbitState) {\r\n // Restore orbit mode state\r\n this.setOrbitValues(true);\r\n this.orbitControls.setPositionValues(\r\n orbitPosition, orbitTarget);\r\n }\r\n\r\n // Apply original camera fov + angles\r\n this.mouseControls.angles = angles;\r\n this.mouseControls.zoom(fov);\r\n }\r\n\r\n async openContextMenu(event) {\r\n if (this.anyToolEnabled) {\r\n return showContextMenu(event);\r\n }\r\n\r\n // Clicked scene coordinate\r\n const position = this.getPickerResults(event).coordinate;\r\n const sceneCoord = position\r\n ? new SceneCoordinate(position).toDataProjection().toArray()\r\n : null;\r\n\r\n // Tag attributes\r\n const tag = this.tagsHandler.getPickerResults(event);\r\n const selectedTags = tag ? [tag.id] : [];\r\n\r\n // Model attributes\r\n const modelData = await this.cadHandler.getProperties(event);\r\n\r\n // Show default context menu\r\n showContextMenu(event, {\r\n selectedTags,\r\n modelData,\r\n sceneCoord\r\n });\r\n }\r\n\r\n setMovementState(state) {\r\n this.orbitControls.enableRotate = state;\r\n this.orbitControls.enablePan = state;\r\n this.orbitControls.enableZoom = state;\r\n }\r\n\r\n getCameraDistance() {\r\n let minDistance = 1.0;\r\n let distance = minDistance;\r\n\r\n if (this.orbitControls.state) {\r\n let cameraPosition = this.orbitControls.position;\r\n let cameraPivot = this.orbitControls.target;\r\n let pivotLength = cameraPivot.distanceTo(cameraPosition);\r\n distance = Math.max(minDistance, pivotLength);\r\n }\r\n\r\n return distance;\r\n }\r\n\r\n getPrecision(precision) {\r\n let approxDistance = this.getCameraDistance();\r\n\r\n if (precision === null) {\r\n precision = Math.abs((1 - (100 - approxDistance) / 100.0) * (0.95) + 0.05);\r\n precision = Math.min(precision, 100.00);\r\n precision = Math.max(precision, 0.05);\r\n }\r\n\r\n let multiplier = this.viewer.far / this.viewer.defaultFarPlane;\r\n precision = precision * multiplier;\r\n\r\n return precision;\r\n }\r\n\r\n touchHandler(touchEvent) {\r\n // The only event allowed during 3d mode is touchend (mouseup). We dont\r\n // capture the initial mouseDown so we need to fake the down state\r\n if (this.orbitControls.state) {\r\n if (touchEvent.type !== \"touchend\") return;\r\n this.mouseControls.down = true;\r\n }\r\n\r\n const mouseEvent = touchToMouse(touchEvent);\r\n if (!mouseEvent) return;\r\n\r\n const target = touchEvent.changedTouches[0].target;\r\n touchEvent.preventDefault();\r\n target.dispatchEvent(mouseEvent);\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n this.cameraAlignerAdv.update(changeDetector);\r\n this.localAligner.update(changeDetector);\r\n this.pointMarkup.update();\r\n\r\n if (this.flyControls.enabled) {\r\n this.flyControls.move();\r\n }\r\n\r\n if (!this.enabled) return;\r\n\r\n this.mouseControls.update();\r\n this.orbitControls.update();\r\n }\r\n}\r\n\r\nclass FlyMoveControls {\r\n public enabled;\r\n private panoControls: PanoControls;\r\n private numberOfSteps = 20;\r\n private positions = [];\r\n\r\n constructor(parent) {\r\n this.panoControls = parent;\r\n this.disable();\r\n }\r\n\r\n get viewer() {\r\n return this.panoControls.viewer;\r\n }\r\n\r\n get orbitControls() {\r\n return this.panoControls.orbitControls;\r\n }\r\n\r\n enable(positions) {\r\n this.enabled = true;\r\n this.positions = positions;\r\n }\r\n\r\n disable() {\r\n this.enabled = false;\r\n this.positions = [];\r\n }\r\n\r\n getAngleDiff(sphereStart, sphereFinish) {\r\n let dRadius = sphereFinish.radius - sphereStart.radius;\r\n let dPhi = sphereFinish.phi - sphereStart.phi;\r\n let dTheta = sphereFinish.theta - sphereStart.theta;\r\n if (dTheta > 180) {\r\n dTheta = -1 * (360 - dTheta);\r\n } else if (dTheta < -180) {\r\n dTheta = dTheta + 360;\r\n }\r\n\r\n return {dRadius, dTheta, dPhi};\r\n }\r\n\r\n start(pivot, orbit) {\r\n let currentOrbit = this.orbitControls.activePosition;\r\n let currentPivot = this.orbitControls.activeTarget;\r\n\r\n let sphereStart = new SphericalPosition()\r\n .fromVectors(currentPivot, currentOrbit);\r\n\r\n let sphereFinish = new SphericalPosition()\r\n .fromVectors(pivot, orbit);\r\n\r\n let {dRadius, dTheta, dPhi} = this.getAngleDiff(\r\n sphereStart, sphereFinish);\r\n\r\n let dPivot = new Vector3()\r\n .add(pivot)\r\n .sub(currentPivot);\r\n\r\n let positions = [];\r\n for (let i = 0; i <= this.numberOfSteps; i++) {\r\n // Sine function provide smoother movement\r\n let value = (Math.PI/2) * (i / this.numberOfSteps);\r\n value = Math.sin(value);\r\n value = Math.pow(value, 0.5);\r\n\r\n const pivotOffset = dPivot.clone()\r\n .multiplyScalar(value);\r\n\r\n const newPivot = new Vector3()\r\n .add(currentPivot)\r\n .add(pivotOffset);\r\n\r\n let theta = sphereStart.theta + dTheta * value;\r\n let radius = sphereStart.radius + dRadius * value;\r\n let phi = sphereStart.phi + dPhi * value;\r\n\r\n let newOrbit = new SphericalPosition()\r\n .fromValues(radius, theta, phi)\r\n .toVector3()\r\n .add(newPivot);\r\n\r\n positions.push({\r\n orbit: newOrbit,\r\n pivot: newPivot\r\n });\r\n }\r\n\r\n this.enable(positions);\r\n }\r\n\r\n move() {\r\n if (this.positions.length === 0) {\r\n this.disable();\r\n return;\r\n }\r\n\r\n let {orbit, pivot} = this.positions.shift();\r\n this.orbitControls.setPositionValues(orbit, pivot);\r\n }\r\n}\r\n\r\nclass OrbitController {\r\n private viewer: Viewer;\r\n private controls: PanoControls;\r\n public controller\r\n\r\n public rotateLength = 10.0;\r\n public movement = false;\r\n public camera;\r\n public callback;\r\n\r\n get position() {\r\n return this.controller.object.position.clone();\r\n }\r\n\r\n get target() {\r\n return this.controller.target.clone();\r\n }\r\n\r\n set enableRotate(state: boolean) {\r\n this.controller.enableRotate = state;\r\n }\r\n\r\n set enablePan(state: boolean) {\r\n this.controller.enablePan = state;\r\n }\r\n\r\n set enableZoom(state: boolean) {\r\n this.controller.enableZoom = state;\r\n }\r\n\r\n setState(state: boolean) {\r\n this.controller.enabled = state;\r\n }\r\n\r\n constructor(viewer: Viewer, controls: PanoControls, up) {\r\n this.viewer = viewer;\r\n this.controls = controls;\r\n\r\n this.camera = this.controls.object.clone();\r\n this.camera.isPerspectiveCamera = true;\r\n this.camera.up.copy(up);\r\n\r\n this.controller = new CustomOrbitControls(\r\n this.viewer, this.camera, this.controls.domElement);\r\n\r\n this.controller.addEventListener(\"stop\", () => {\r\n this.viewer.updatePickers();\r\n });\r\n\r\n this.controller.enableDamping = true;\r\n this.controller.dampingFactor = 0.15;\r\n this.controller.rotateSpeed = 0.50;\r\n this.controller.panSpeed = 0.50;\r\n this.controller.enabled = false;\r\n }\r\n\r\n get state() {\r\n return this.controller.enabled;\r\n }\r\n\r\n get walkMode() {\r\n return this.controller.walkMode;\r\n }\r\n\r\n get activePosition() {\r\n return this.controller.activePosition();\r\n }\r\n\r\n get activeTarget() {\r\n return this.controller.activeTarget();\r\n }\r\n\r\n setControls(value) {\r\n this.controller.setControls(value);\r\n }\r\n\r\n setWalkMode(state) {\r\n this.controller.setWalkMode(state);\r\n }\r\n\r\n getPositionValues() {\r\n let pivot = null;\r\n let orbit = null;\r\n\r\n try {\r\n orbit = new SceneCoordinate(this.activePosition)\r\n .toDataProjection()\r\n .toArray();\r\n\r\n pivot = new SceneCoordinate(this.activeTarget)\r\n .toDataProjection()\r\n .toArray();\r\n } catch {\r\n // Nothing\r\n }\r\n\r\n return {orbit, pivot};\r\n }\r\n\r\n setPositionValues(orbit, pivot, enabled=true, smooth=false) {\r\n if (smooth) {\r\n this.controls.flyControls.start(pivot, orbit);\r\n } else {\r\n this.controller.position0.set(orbit.x, orbit.y, orbit.z);\r\n this.controller.target0.set(pivot.x, pivot.y, pivot.z);\r\n this.controller.reset();\r\n }\r\n\r\n this.controller.enabled = enabled;\r\n }\r\n\r\n object() {\r\n return this.controls;\r\n }\r\n\r\n toggle(value) {\r\n if (this.state) {\r\n this.controller.enabled = value;\r\n }\r\n }\r\n\r\n update() {\r\n if (!this.state) return;\r\n this.controller.update();\r\n }\r\n}\r\n","import { Viewer, ViewerProps } from \"../main\";\r\nimport {\r\n AmbientLight,\r\n BackSide,\r\n BoxBufferGeometry,\r\n DoubleSide,\r\n FrontSide,\r\n Group,\r\n Mesh,\r\n MeshPhongMaterial,\r\n PerspectiveCamera,\r\n PlaneBufferGeometry,\r\n Raycaster,\r\n Scene,\r\n SpotLight,\r\n Texture,\r\n Vector2,\r\n Vector3,\r\n WebGLRenderer\r\n} from \"three\";\r\nimport { eventToPixel } from \"../utilities\";\r\nimport { SceneCoordinate } from \"../projections\";\r\nimport { EffectComposer } from \"three/examples/jsm/postprocessing/EffectComposer\";\r\nimport { ShaderPass } from \"three/examples/jsm/postprocessing/ShaderPass\";\r\nimport { CopyShader } from \"three/examples/jsm/shaders/CopyShader\";\r\nimport { SSAARenderPass } from \"three/examples/jsm/postprocessing/SSAARenderPass\";\r\nimport { CustomMouseEvent } from \".\";\r\nimport { clearViewerTooltip } from \"../viewer\";\r\nimport {t} from \"../../localization\";\r\n\r\nclass TextMaterial extends MeshPhongMaterial {\r\n public textures;\r\n public text: string;\r\n public key: string;\r\n\r\n constructor(opts, textures, text, key) {\r\n super(opts);\r\n\r\n this.textures = textures;\r\n this.text = text;\r\n this.key = key;\r\n }\r\n}\r\n\r\nexport class CompassControls {\r\n private viewer: Viewer;\r\n private scene: Scene;\r\n private renderer: WebGLRenderer;\r\n private composer: EffectComposer\r\n private camera: PerspectiveCamera;\r\n private raycaster = new Raycaster();\r\n private pixelRatio = 2;\r\n private antialias = true;\r\n\r\n private sizeRatioLarge = 0.20;\r\n private sizeRatioSmall = 0.40;\r\n private alphaTest = 0.25;\r\n private lightPosition = new Vector3(3, 3, 3);\r\n private pivot: Group;\r\n\r\n private cube: Mesh;\r\n private cubeSize = 0.4;\r\n private cubeColorStandard = \"#dddddd\";\r\n private cubeColorHover = \"#aaaaaa\";\r\n private cubeEdgeColor = \"#444444\";\r\n private cubeTextColor = \"#000000\";\r\n private cubeMaterials: TextMaterial[] = [];\r\n\r\n private donutSize = 0.80;\r\n private donutColor = \"#444444\";\r\n private donutTextColor = \"#ffffff\";\r\n\r\n private north: Group;\r\n private west: Group;\r\n private east: Group;\r\n private south: Group;\r\n\r\n constructor(viewer: Viewer, props: ViewerProps) {\r\n const {compassClassName} = props;\r\n\r\n this.viewer = viewer;\r\n\r\n this.initScene();\r\n this.initAntiAliasing();\r\n this.addObjects();\r\n this.addLights();\r\n\r\n // Apply compass class name from props\r\n this.domElement.className = compassClassName;\r\n }\r\n\r\n get width() {\r\n return this.domElement.width;\r\n }\r\n\r\n get height() {\r\n return this.domElement.height;\r\n }\r\n\r\n get domElement() {\r\n return this.renderer.domElement;\r\n }\r\n\r\n get cameraDistance() {\r\n return this.donutSize * 2.0;\r\n }\r\n\r\n get letters() {\r\n return [this.east, this.west, this.north, this.south];\r\n }\r\n\r\n initScene() {\r\n this.renderer = new WebGLRenderer({\r\n alpha: true,\r\n });\r\n\r\n this.renderer.setPixelRatio(this.pixelRatio);\r\n this.renderer.domElement.id = \"compass-canvas\";\r\n\r\n this.camera = new PerspectiveCamera(40, 1.0, 1, 10);\r\n this.camera.position.z = this.cameraDistance;\r\n this.camera.up = new Vector3(0, 1, 0);\r\n this.camera.lookAt(new Vector3(0, 0, 0));\r\n this.scene = new Scene();\r\n }\r\n\r\n initAntiAliasing() {\r\n this.composer = new EffectComposer(this.renderer);\r\n\r\n let ssaaRenderPass = new SSAARenderPass(this.scene,\r\n this.camera, \"white\", 0.0);\r\n\r\n ssaaRenderPass.unbiased = true;\r\n ssaaRenderPass.sampleLevel = 3;\r\n this.composer.addPass(ssaaRenderPass);\r\n\r\n let copyPass = new ShaderPass(CopyShader);\r\n this.composer.addPass(copyPass);\r\n }\r\n\r\n addObjects() {\r\n this.pivot = new Group();\r\n this.pivot.position.set(0, 0, 0);\r\n this.pivot.visible = false;\r\n\r\n this.addRotationCube();\r\n this.addCompassRing();\r\n this.addCompassLetters();\r\n\r\n // Add all items to scene\r\n this.scene.add(this.pivot);\r\n }\r\n\r\n addLights() {\r\n let ambientLight = new AmbientLight(0xffffff, 0.9);\r\n this.scene.add(ambientLight);\r\n\r\n let spotLight = new SpotLight(0xffffff, 0.5);\r\n spotLight.castShadow = true;\r\n spotLight.position.copy(this.lightPosition);\r\n this.scene.add(spotLight);\r\n }\r\n\r\n addRotationCube() {\r\n const cubeGeometry = new BoxBufferGeometry(this.cubeSize,\r\n this.cubeSize, this.cubeSize);\r\n\r\n this.cubeMaterials = [\r\n this.getTextMaterial(\"right\", t(\"directions.right\"), 270),\r\n this.getTextMaterial(\"left\", t(\"directions.left\"), 90),\r\n this.getTextMaterial(\"back\", t(\"directions.back\"), 180),\r\n this.getTextMaterial(\"front\", t(\"directions.front\"), 0),\r\n this.getTextMaterial(\"top\", t(\"directions.top\"), 0),\r\n this.getTextMaterial(\"bottom\", t(\"directions.bottom\"), 180),\r\n ];\r\n\r\n this.pivot.remove(this.cube);\r\n this.cube = new Mesh(cubeGeometry, this.cubeMaterials);\r\n this.pivot.add(this.cube);\r\n }\r\n\r\n addCompassRing() {\r\n let donutGeometry = new PlaneBufferGeometry(\r\n this.donutSize, this.donutSize\r\n );\r\n\r\n let donutMaterial = this.getCircleMaterial();\r\n donutMaterial.alphaTest = this.alphaTest;\r\n donutMaterial.side = DoubleSide;\r\n\r\n const mesh = new Mesh(donutGeometry, donutMaterial);\r\n mesh.position.z = -this.cubeSize / 2.0;\r\n this.pivot.add(mesh);\r\n }\r\n\r\n addCompassLetters() {\r\n this.letters.forEach(letter => this.pivot.remove(letter));\r\n this.east = this.getDirectionMesh(\"east\", t(\"directions.shorthand-east\"));\r\n this.west = this.getDirectionMesh(\"west\", t(\"directions.shorthand-west\"));\r\n this.north = this.getDirectionMesh(\"north\", t(\"directions.shorthand-north\"));\r\n this.south = this.getDirectionMesh(\"south\", t(\"directions.shorthand-south\"));\r\n this.letters.forEach(letter => this.pivot.add(letter));\r\n }\r\n\r\n getTextMaterial(direction, text, rotation): TextMaterial {\r\n let canvasSize = 1024;\r\n let fontSize = 200;\r\n let border = 32;\r\n let outlineSize = 5;\r\n\r\n // Scale is applied to fit text inside canvas\r\n let maxLength = canvasSize / fontSize;\r\n let fontScale = Math.min(1.0, maxLength / text.length);\r\n fontSize = fontSize * fontScale;\r\n\r\n let textures = [];\r\n\r\n [this.cubeColorStandard, this.cubeColorHover].forEach(cubeColor => {\r\n let canvas = document.createElement(\"canvas\");\r\n canvas.width = canvasSize;\r\n canvas.height = canvasSize;\r\n let context = canvas.getContext(\"2d\");\r\n\r\n // Rotate from center point\r\n context.translate( canvasSize / 2, canvasSize / 2 );\r\n context.rotate(rotation * Math.PI / 180);\r\n context.translate( -canvasSize / 2, -canvasSize / 2 );\r\n\r\n // Fill background (border + color)\r\n context.fillStyle = this.cubeEdgeColor;\r\n context.fillRect(0, 0, canvasSize, canvasSize);\r\n context.fillStyle = cubeColor;\r\n context.fillRect(border, border, canvasSize - 2 * border,\r\n canvasSize - 2 * border);\r\n\r\n // Write text\r\n let x = canvasSize / 2.0;\r\n let y = canvasSize / 2.0 + fontSize / 2.0;\r\n context.textAlign = \"center\";\r\n context.font = `bold ${fontSize}px Verdana`;\r\n context.fillStyle = this.cubeTextColor;\r\n context.fillText(text, x, y);\r\n\r\n // Black outline\r\n context.lineWidth = outlineSize;\r\n context.strokeStyle = \"#000000\";\r\n context.strokeText(text, x, y);\r\n\r\n let texture = new Texture(canvas);\r\n texture.needsUpdate = true;\r\n textures.push(texture);\r\n });\r\n\r\n let material = new TextMaterial({\r\n map: textures[0],\r\n }, textures, text, direction);\r\n\r\n return material;\r\n }\r\n\r\n getLetterMaterial(text): MeshPhongMaterial {\r\n let canvasSize = 256;\r\n let fontSize = 230;\r\n let outlineSize = 5;\r\n\r\n let canvas = document.createElement(\"canvas\");\r\n canvas.width = canvasSize;\r\n canvas.height = canvasSize;\r\n let context = canvas.getContext(\"2d\");\r\n\r\n let x = canvasSize / 2.0;\r\n let y = canvasSize / 2.0 + fontSize / 2.0 - fontSize * 0.1;\r\n context.textAlign = \"center\";\r\n context.font = `bold ${fontSize}px Verdana`;\r\n\r\n // Colored text\r\n context.fillStyle = this.donutTextColor;\r\n context.fillText(text, x, y);\r\n\r\n // Black outline\r\n context.lineWidth = outlineSize;\r\n context.strokeStyle = \"#000000\";\r\n context.strokeText(text, x, y);\r\n\r\n let texture = new Texture(canvas);\r\n texture.needsUpdate = true;\r\n\r\n return new MeshPhongMaterial({\r\n map: texture\r\n });\r\n }\r\n\r\n getCircleMaterial(): MeshPhongMaterial {\r\n let canvasSize = 256;\r\n\r\n let canvas = document.createElement(\"canvas\");\r\n canvas.width = canvasSize;\r\n canvas.height = canvasSize;\r\n let context = canvas.getContext(\"2d\");\r\n\r\n context.fillStyle = this.donutColor;\r\n\r\n let x = canvasSize / 2.0;\r\n let y = canvasSize / 2.0;\r\n\r\n context.beginPath();\r\n context.arc(x, y, canvasSize * 0.5 * 1.00, 0, Math.PI * 2, false);\r\n context.arc(x, y, canvasSize * 0.5 * 0.75, 0, Math.PI * 2, true);\r\n context.fill();\r\n\r\n let texture = new Texture(canvas);\r\n texture.needsUpdate = true;\r\n\r\n return new MeshPhongMaterial({\r\n map: texture\r\n });\r\n }\r\n\r\n getDirectionMesh(direction, text): Group {\r\n let pivot = new Group();\r\n\r\n // Set the height just barely above the circle texture\r\n let textHeight = this.cubeSize * 0.005;\r\n\r\n if (direction === \"east\") {\r\n pivot.position.x = this.cubeSize;\r\n } else if (direction === \"west\") {\r\n pivot.position.x = -1 * this.cubeSize;\r\n } else if (direction === \"north\") {\r\n pivot.position.y = this.cubeSize;\r\n } else if (direction === \"south\") {\r\n pivot.position.y = -1 * this.cubeSize;\r\n }\r\n\r\n pivot.position.z = -this.cubeSize / 2.0;\r\n\r\n let geometryUpper = new PlaneBufferGeometry(this.donutSize * 0.25,\r\n this.donutSize * 0.25);\r\n let materialUpper = this.getLetterMaterial(text);\r\n materialUpper.alphaTest = this.alphaTest;\r\n materialUpper.side = FrontSide;\r\n let meshUpper = new Mesh(geometryUpper, materialUpper);\r\n meshUpper.position.z = textHeight;\r\n pivot.add(meshUpper);\r\n\r\n let geometryLower = new PlaneBufferGeometry(this.donutSize * 0.25,\r\n this.donutSize * 0.25);\r\n let materialLower = this.getLetterMaterial(text);\r\n materialLower.alphaTest = this.alphaTest;\r\n materialLower.side = BackSide;\r\n let meshLower = new Mesh(geometryLower, materialLower);\r\n meshLower.scale.y = -1;\r\n meshLower.position.z = -1 * textHeight;\r\n pivot.add(meshLower);\r\n\r\n return pivot;\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n if (event.mouseMoved) return false;\r\n\r\n let controls = this.viewer.controls;\r\n let {hovering, side} = this.onMouseMove(event);\r\n\r\n if (side) {\r\n controls.resetCamera(side);\r\n }\r\n\r\n return hovering;\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n const side = this.getSelectedSide(event);\r\n const hovering = side ? true : false;\r\n this.togglePointer(hovering);\r\n\r\n return {hovering, side};\r\n }\r\n\r\n getSelectedSide(event) {\r\n if (!this.cube.visible) {\r\n return;\r\n }\r\n\r\n let offset = new Vector3(\r\n this.domElement.offsetLeft,\r\n this.domElement.offsetTop,\r\n 0\r\n );\r\n\r\n let {x, y} = eventToPixel(event).sub(offset);\r\n\r\n let mouse = new Vector2();\r\n mouse.x = (x / this.width) * this.pixelRatio * 2 - 1;\r\n mouse.y = -1 * (y / this.height) * this.pixelRatio * 2 + 1;\r\n\r\n if ((mouse.x < -1) || (mouse.x > 1)) {\r\n return;\r\n }\r\n\r\n if ((mouse.y < -1) || (mouse.y > 1)) {\r\n return;\r\n }\r\n\r\n this.raycaster.setFromCamera(mouse, this.camera);\r\n\r\n let intersect = this.raycaster\r\n .intersectObject(this.cube);\r\n\r\n if (intersect.length === 0) {\r\n this.setCubeMaterials();\r\n return;\r\n }\r\n\r\n let materialIndex = Math.floor(intersect[0].faceIndex / 2);\r\n let material = this.cubeMaterials[materialIndex];\r\n this.setCubeMaterials(materialIndex);\r\n\r\n return material.key;\r\n }\r\n\r\n setCubeMaterials(hoverIndex = null) {\r\n let materials = this.cube.material as TextMaterial[];\r\n\r\n for (var i = 0; i < materials.length; i++) {\r\n if (hoverIndex === i) {\r\n this.cube.material[i].map = materials[i].textures[1];\r\n } else {\r\n this.cube.material[i].map = materials[i].textures[0];\r\n }\r\n\r\n this.cube.material[i].needsUpdate = true;\r\n }\r\n }\r\n\r\n rotateLetters(yaw) {\r\n this.east.rotation.z = yaw;\r\n this.west.rotation.z = yaw;\r\n this.north.rotation.z = yaw;\r\n this.south.rotation.z = yaw;\r\n }\r\n\r\n zenith(pointA, pointB) {\r\n let height = pointA.z - pointB.z;\r\n let distance = pointA.distanceTo(pointB);\r\n let zenith = Math.acos(height / distance);\r\n return -1 * zenith;\r\n }\r\n\r\n bearing(pointA, pointB) {\r\n let startLat = pointA.y * Math.PI / 180;\r\n let destLat = pointB.y * Math.PI / 180;\r\n\r\n let startLng = pointA.x * Math.PI / 180;\r\n let destLng = pointB.x * Math.PI / 180;\r\n\r\n let y = Math.sin(destLng - startLng) * Math.cos(destLat);\r\n let x = Math.cos(startLat) * Math.sin(destLat) -\r\n Math.sin(startLat) * Math.cos(destLat) * Math.cos(destLng - startLng);\r\n let brng = Math.atan2(y, x);\r\n brng = brng * 180 / Math.PI;\r\n brng = (brng + 360.0) % 360;\r\n return brng * Math.PI / 180;\r\n }\r\n\r\n updateOffset(offset) {\r\n let shift = this.viewer.expanded\r\n ? offset\r\n : 0;\r\n\r\n this.domElement.style.right = `${shift}px`;\r\n }\r\n\r\n setSize(width, height) {\r\n const ratio = this.viewer.expanded\r\n ? this.sizeRatioLarge\r\n : this.sizeRatioSmall;\r\n\r\n const size = Math.min(width, height) * ratio;\r\n this.renderer.setSize(size, size);\r\n this.composer.setSize(size, size);\r\n }\r\n\r\n togglePointer(state) {\r\n if (state) {\r\n clearViewerTooltip();\r\n }\r\n\r\n const cursor = state ? \"pointer\" : \"\";\r\n this.viewer.setContainerCursor(cursor);\r\n }\r\n\r\n calculateRotations(loaded, camera, orbitMode) {\r\n if (!loaded) {\r\n return;\r\n }\r\n\r\n let quaternion = camera.quaternion;\r\n this.cube.visible = orbitMode;\r\n\r\n let lookatLocal = new Vector3(0, 0, -1)\r\n .applyQuaternion(quaternion)\r\n .add(camera.position);\r\n\r\n let lookatLonLat = new SceneCoordinate(lookatLocal)\r\n .toLonLat();\r\n\r\n let yPosLocal = new Vector3(0, 1, 0)\r\n .add(camera.position);\r\n\r\n let yPosLonLat = new SceneCoordinate(yPosLocal)\r\n .toLonLat();\r\n\r\n // Center point\r\n let cameraLocal = camera.position.clone();\r\n let cameraLatLon = new SceneCoordinate(cameraLocal)\r\n .toLonLat();\r\n\r\n let groupYaw = this.bearing(cameraLatLon, lookatLonLat);\r\n let groupPitch = orbitMode ? this.zenith(cameraLocal, lookatLocal) : 0;\r\n\r\n // Rotate our direction textures\r\n this.rotateLetters(-1 * groupYaw);\r\n\r\n // Pivot our geometry group\r\n this.pivot.rotation.z = groupYaw;\r\n this.pivot.rotation.x = groupPitch;\r\n\r\n // North wont equal our y-axis, so the cube is rotated independantly\r\n let cubeYaw = this.bearing(cameraLatLon, yPosLonLat);\r\n this.cube.rotation.z = -1 * cubeYaw;\r\n }\r\n\r\n render(loaded, camera, orbitMode) {\r\n this.calculateRotations(loaded, camera, orbitMode);\r\n this.pivot.visible = loaded;\r\n\r\n if (this.antialias) {\r\n this.composer.render();\r\n } else {\r\n this.renderer.render(this.scene, this.camera);\r\n }\r\n }\r\n}\r\n","import { MathUtils, PerspectiveCamera, Vector2, Vector3 } from \"three\";\r\nimport { Viewer } from \"../main\";\r\nimport { directionToCameraAngle } from \"../cameras\";\r\nimport { RayCaster } from \"../ray-caster\";\r\n\r\nexport interface CustomMouseEvent extends MouseEvent {\r\n isLeftClick: boolean\r\n isRightClick: boolean\r\n mouseDown: boolean\r\n mouseMoved: boolean\r\n scrolling: boolean\r\n}\r\n\r\nexport class MouseControls {\r\n private viewer: Viewer;\r\n private camera: PerspectiveCamera;\r\n\r\n public down = false;\r\n public button = 0;\r\n\r\n private phiDelta = 0;\r\n public thetaDelta = 0;\r\n public wheelDelta = 0;\r\n\r\n private wheelTimeout = null;\r\n private wheelDelay = 150;\r\n\r\n private endTimeout = 50;\r\n private endDelay = 500;\r\n\r\n public rotating = false;\r\n public zooming = false;\r\n public scrolling = false;\r\n public movement = false;\r\n private moveInterval = null;\r\n\r\n private _zoomEvent = null;\r\n private _zooming = false\r\n\r\n private mouseEvent = null;\r\n private moveStart = new Vector2();\r\n private moveEnd = new Vector2();\r\n private moveDelta = new Vector2();\r\n private moveDistance = 0;\r\n private lastMovement = performance.now();\r\n private maxPixelDistance = 4;\r\n\r\n constructor(viewer: Viewer, camera: PerspectiveCamera) {\r\n this.viewer = viewer;\r\n this.camera = camera;\r\n }\r\n\r\n get angles(): number[] {\r\n return [this.thetaDelta, this.phiDelta];\r\n }\r\n\r\n set angles(values) {\r\n const [theta, phi] = values;\r\n\r\n if (theta != null) {\r\n this.thetaDelta = theta;\r\n }\r\n\r\n if (phi != null) {\r\n this.phiDelta = phi;\r\n }\r\n\r\n this.updateCameraMatrix();\r\n }\r\n\r\n get lookat() {\r\n let phiDelta = this.phiDelta + MathUtils.degToRad(90);\r\n let x = Math.cos(this.thetaDelta) * Math.sin(phiDelta);\r\n let y = Math.sin(this.thetaDelta) * Math.sin(phiDelta);\r\n let z = -1 * Math.cos(phiDelta);\r\n\r\n return new Vector3(x,y,z);\r\n }\r\n\r\n get recentActivity() {\r\n /** Returns true if movement occured within endDelay milliseconds */\r\n let now = performance.now();\r\n let end = this.lastMovement + this.endDelay;\r\n return now < end;\r\n }\r\n\r\n get fov() {\r\n return this.camera.fov;\r\n }\r\n\r\n set fov(value: number) {\r\n this.camera.fov = Math.max(10, Math.min(90, value));\r\n }\r\n\r\n set zoomToCursor(value: boolean) {\r\n this._zooming = value;\r\n\r\n if (value) {\r\n this._zoomEvent = this.mouseEvent;\r\n } else {\r\n this._zoomEvent = null;\r\n }\r\n }\r\n\r\n getCustomEvent(event): CustomMouseEvent {\r\n event.isLeftClick = event.button === 0;\r\n event.isRightClick = event.button === 2;\r\n event.mouseDown = this.down;\r\n event.mouseMoved = this.movement;\r\n event.scrolling = this.scrolling;\r\n\r\n return event;\r\n }\r\n\r\n clearInterval() {\r\n if (this.moveInterval !== null) {\r\n clearTimeout(this.moveInterval);\r\n }\r\n }\r\n\r\n setInterval(callback) {\r\n this.moveInterval = setTimeout(() => {\r\n callback();\r\n }, this.endTimeout);\r\n }\r\n\r\n onMouseScroll() {\r\n this.scrolling = true;\r\n clearTimeout(this.wheelTimeout);\r\n\r\n this.wheelTimeout = setTimeout(() => {\r\n this.scrolling = false;\r\n }, this.wheelDelay);\r\n }\r\n\r\n onMouseMove(event): CustomMouseEvent {\r\n this.mouseEvent = event;\r\n\r\n if (this.down === false) {\r\n return this.getCustomEvent(event);\r\n }\r\n\r\n this.moveEnd.set(event.clientX, event.clientY);\r\n\r\n const distance = this.moveStart.distanceTo(this.moveEnd);\r\n this.moveDistance += distance;\r\n\r\n this.moveDelta.subVectors(this.moveEnd, this.moveStart);\r\n this.moveStart.copy(this.moveEnd);\r\n this.movement = this.moveDistance > this.maxPixelDistance;\r\n\r\n return this.getCustomEvent(event);\r\n }\r\n\r\n updateRotation(fov: number, width: number, height: number) {\r\n if (this.button !== 0) return;\r\n\r\n const delta = new Vector2()\r\n .copy(this.moveDelta)\r\n .multiplyScalar(fov / 90);\r\n\r\n this.rotate(\r\n 2 * Math.PI * delta.x / width,\r\n Math.PI * delta.y / height\r\n );\r\n\r\n this.lastMovement = performance.now();\r\n }\r\n\r\n updateCameraMatrix() {\r\n const lookat = new Vector3()\r\n .copy(this.lookat)\r\n .add(this.camera.position);\r\n\r\n this.camera.lookAt(lookat);\r\n this.camera.updateProjectionMatrix();\r\n }\r\n\r\n onMouseWheel(event) {\r\n if (event.deltaY > 0) {\r\n this.zoom(this.camera.fov + 5);\r\n } else if (event.deltaY < 0) {\r\n this.zoom(this.camera.fov - 5);\r\n }\r\n }\r\n\r\n zoom(fov: number) {\r\n if (this._zooming) {\r\n this.updateCameraMatrix();\r\n\r\n const raycaster = new RayCaster(this.viewer, this._zoomEvent);\r\n const vector0 = raycaster.vectorFromEvent(this._zoomEvent);\r\n const angles0 = directionToCameraAngle(vector0);\r\n\r\n this.fov = fov;\r\n this.updateCameraMatrix();\r\n\r\n const vector1 = raycaster.vectorFromEvent(this._zoomEvent);\r\n const angles1 = directionToCameraAngle(vector1);\r\n\r\n const dTheta = angles0[0] - angles1[0];\r\n const dPhi = angles0[1] - angles1[1];\r\n\r\n this.rotate(dTheta, dPhi);\r\n } else {\r\n this.fov = fov;\r\n this.updateCameraMatrix();\r\n }\r\n\r\n this.lastMovement = performance.now();\r\n }\r\n\r\n rotate(theta, phi) {\r\n this.thetaDelta += theta;\r\n this.phiDelta += phi;\r\n this.phiDelta = Math.min(this.phiDelta, MathUtils.degToRad(89));\r\n this.phiDelta = Math.max(this.phiDelta, MathUtils.degToRad(-89));\r\n\r\n const maxAngle = 360 * Math.PI / 180;\r\n this.thetaDelta = this.thetaDelta % maxAngle;\r\n this.phiDelta = this.phiDelta % maxAngle;\r\n this.updateCameraMatrix();\r\n }\r\n\r\n onMouseDown(event): CustomMouseEvent {\r\n this.down = true;\r\n this.button = event.button;\r\n this.moveStart.set(event.clientX, event.clientY);\r\n this.moveDistance = 0;\r\n this.movement = false;\r\n\r\n return this.getCustomEvent(event);\r\n }\r\n\r\n onMouseUp(event): CustomMouseEvent {\r\n const newEvent = this.getCustomEvent(event);\r\n this.down = false;\r\n this.movement = false;\r\n\r\n return newEvent;\r\n }\r\n\r\n update() {\r\n this.updateCameraMatrix();\r\n }\r\n\r\n}\r\n","import { Viewer, ViewerProps } from \"../main\";\r\nimport { RenderUtils } from \"../rendering\";\r\nimport {\r\n Color,\r\n Line3,\r\n Mesh,\r\n MeshBasicMaterial,\r\n PerspectiveCamera,\r\n Scene,\r\n SphereGeometry,\r\n Vector3,\r\n WebGLRenderer\r\n} from \"three\";\r\nimport { MouseControls } from \".\";\r\nimport onresize from \"resize-event\";\r\nimport { CameraImage, PanoramicImage, PlanarImage, CameraArguments } from \"../cameras\";\r\nimport { getPointScale } from \"../utilities\";\r\nimport { RayCaster } from \"../ray-caster\";\r\n\r\nexport interface IntersectResponse {\r\n error: number;\r\n distances: [number, number];\r\n calculated: boolean;\r\n valid: boolean;\r\n message: any;\r\n}\r\n\r\ninterface Coordinate {\r\n position: Vector3\r\n direction: Vector3\r\n}\r\n\r\nexport interface MultiImageOptions {\r\n canComplete?: boolean\r\n canAddMore?: boolean\r\n disableAddMore?: boolean\r\n disableComplete?: boolean\r\n disablePreviousImage?: boolean\r\n disableNextImage?: boolean\r\n coordinates?: [Coordinate | null, Coordinate | null]\r\n intersect?: null | IntersectResponse\r\n}\r\n\r\n\r\n// TODO: replace with actual function requirements\r\n\r\ninterface WindowLoadOptions {\r\n onClose?: () => void;\r\n onComplete?: () => void;\r\n onAddPoint?: () => void;\r\n canComplete: boolean;\r\n canAddMore: boolean;\r\n}\r\n\r\ninterface SavedCameraState {\r\n fov: number;\r\n angles: number[];\r\n}\r\n\r\nexport class MultiImageWindow {\r\n private viewer: Viewer;\r\n private cameraScene: Scene;\r\n public objectScene: Scene;\r\n private backgroundScene: Scene;\r\n private mouseControls: MouseControls;\r\n public camera: PerspectiveCamera\r\n private renderer: WebGLRenderer;\r\n private renderUtils: RenderUtils;\r\n private containerElement;\r\n private activeCamera: CameraImage\r\n private tools: MultipleCameraMeasurement;\r\n\r\n private setMultiImageOpen: React.Dispatch;\r\n private setMultiImageState: React.Dispatch;\r\n\r\n public onComplete: Function;\r\n public onAddPoint: Function;\r\n public onClose: Function;\r\n\r\n private intersectResponse = null;\r\n private pixelRatio = 1.0;\r\n private minCameraDistance = 2.0;\r\n private enabled = false;\r\n public canComplete = false;\r\n private canAddMore = false;\r\n private disablePreviousImage = false;\r\n private disableNextImage = false;\r\n public disableAddMore = false;\r\n public disableComplete = false;\r\n private focused = false;\r\n private oldCameraState: SavedCameraState;\r\n private cameraIndex;\r\n private observer;\r\n\r\n constructor(viewer: Viewer, props: ViewerProps) {\r\n const {setMultiImageOpen, setMultiImageState} = props;\r\n\r\n this.viewer = viewer;\r\n this.setMultiImageOpen = setMultiImageOpen;\r\n this.setMultiImageState = setMultiImageState;\r\n\r\n this.initRenderer();\r\n this.initEvents();\r\n\r\n this.mouseControls = new MouseControls(this.viewer, this.camera);\r\n this.tools = new MultipleCameraMeasurement(viewer, this);\r\n }\r\n\r\n get width(): number {\r\n return this.parentElement\r\n ? this.parentElement.offsetWidth\r\n : 0;\r\n }\r\n\r\n get height(): number {\r\n return this.parentElement\r\n ? this.parentElement.offsetHeight\r\n : 0;\r\n }\r\n\r\n get aspect() {\r\n return this.width / this.height;\r\n }\r\n\r\n get lookat() {\r\n return this.mouseControls.lookat\r\n .add(this.camera.position);\r\n }\r\n\r\n get parentElement() {\r\n return this.containerElement?.parentElement;\r\n }\r\n\r\n init(container) {\r\n this.containerElement = container;\r\n this.containerElement.appendChild(this.renderer.domElement);\r\n\r\n this.initResize();\r\n }\r\n\r\n destroy() {\r\n if (this.observer) {\r\n this.observer.disconnect();\r\n }\r\n\r\n this.removeEvents();\r\n }\r\n\r\n update() {\r\n const state = {\r\n canComplete: this.canComplete,\r\n canAddMore: this.canAddMore,\r\n disableAddMore: this.disableAddMore,\r\n disableComplete: this.disableComplete,\r\n disablePreviousImage: this.disablePreviousImage,\r\n disableNextImage: this.disableNextImage,\r\n coordinates: this.tools.coordinates,\r\n intersect: this.intersectResponse\r\n } as MultiImageOptions;\r\n\r\n this.setMultiImageState(state);\r\n }\r\n\r\n updateIntersect() {\r\n this.intersectResponse = this.tools.calculate();\r\n this.update();\r\n }\r\n\r\n updateBackground(color: string) {\r\n this.backgroundScene.background = new Color(color);\r\n }\r\n\r\n show(options: WindowLoadOptions) {\r\n const {\r\n canComplete = true,\r\n canAddMore = true,\r\n onComplete = () => {},\r\n onAddPoint = () => {},\r\n onClose = () => {}\r\n } = options;\r\n\r\n this.canComplete = canComplete;\r\n this.canAddMore = canAddMore;\r\n this.onComplete = onComplete;\r\n this.onAddPoint = onAddPoint;\r\n this.onClose = onClose;\r\n\r\n if (this.enabled) {\r\n this.update();\r\n } else {\r\n this.setMultiImageOpen(true);\r\n }\r\n }\r\n\r\n loadNextImage() {\r\n const numCameras = this.viewer.cameraHandler.cameras.length;\r\n const index = (this.cameraIndex + 1) % numCameras;\r\n this.loadCamera(index);\r\n }\r\n\r\n loadPreviousImage() {\r\n const numCameras = this.viewer.cameraHandler.cameras.length;\r\n const index = ((this.cameraIndex - 1) + numCameras) % numCameras;\r\n this.loadCamera(index);\r\n }\r\n\r\n async loadCamera(index) {\r\n this.cameraIndex = index;\r\n\r\n this.resetSecondObservation();\r\n this.disablePreviousImage = true;\r\n this.disableNextImage = true;\r\n this.update();\r\n\r\n const nextCamera = this.viewer.cameraHandler.cameras[index];\r\n const camera = this.getNewCamera(nextCamera);\r\n\r\n // Load new camera\r\n console.log(`Load camera: ${camera.name}`);\r\n\r\n // Load image data from path\r\n camera.initialize();\r\n await camera.load();\r\n\r\n // Update previous texture\r\n await this.renderUtils.updateTexture();\r\n\r\n // Destroy previously loaded camera\r\n this.activeCamera?.destroy();\r\n this.activeCamera = camera;\r\n\r\n camera.activate();\r\n\r\n this.updateIntersect();\r\n\r\n this.disablePreviousImage = false;\r\n this.disableNextImage = false;\r\n this.update();\r\n }\r\n\r\n /** @private */\r\n getNewCamera(nextCamera: CameraImage): CameraImage {\r\n const args = [\r\n nextCamera.cameraFile,\r\n nextCamera.cameraData,\r\n this.cameraScene,\r\n this.camera,\r\n this.mouseControls,\r\n ] as CameraArguments;\r\n\r\n let camera;\r\n if (nextCamera instanceof PanoramicImage) {\r\n camera = new PanoramicImage(...args);\r\n } else if (nextCamera instanceof PlanarImage) {\r\n camera = new PlanarImage(...args);\r\n }\r\n\r\n return camera;\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n\r\n if (!state) {\r\n this.resetObservations();\r\n this.activeCamera?.destroy();\r\n this.activeCamera = null;\r\n }\r\n }\r\n\r\n close() {\r\n this.setMultiImageOpen(false);\r\n }\r\n\r\n initResize() {\r\n if (this.observer) {\r\n this.observer.disconnect();\r\n }\r\n\r\n this.observer = onresize(this.parentElement, () => {\r\n this.handleWindowResize();\r\n });\r\n\r\n this.handleWindowResize();\r\n }\r\n\r\n initEvents() {\r\n this.onMouseDown = this.onMouseDown.bind(this);\r\n this.onMouseUp = this.onMouseUp.bind(this);\r\n this.onMouseMove = this.onMouseMove.bind(this);\r\n this.onMouseWheel = this.onMouseWheel.bind(this);\r\n this.onKeyDown = this.onKeyDown.bind(this);\r\n this.onKeyUp = this.onKeyUp.bind(this);\r\n this.onMouseFocus = this.onMouseFocus.bind(this);\r\n\r\n const element = this.renderer.domElement;\r\n element.addEventListener('mousedown', this.onMouseDown, false);\r\n element.addEventListener('mouseup', this.onMouseUp, false);\r\n element.addEventListener('mousemove', this.onMouseMove, false);\r\n element.addEventListener('wheel', this.onMouseWheel, false);\r\n element.addEventListener('mouseover', this.onMouseFocus, false);\r\n element.addEventListener('mouseout', this.onMouseFocus, false);\r\n\r\n // Keydown doesnt work on canvas\r\n window.addEventListener('keydown', this.onKeyDown, false);\r\n window.addEventListener('keyup', this.onKeyUp, false);\r\n }\r\n\r\n removeEvents() {\r\n const element = this.renderer.domElement;\r\n element.removeEventListener('mousedown', this.onMouseDown, false);\r\n element.removeEventListener('mouseup', this.onMouseUp, false);\r\n element.removeEventListener('mousemove', this.onMouseMove, false);\r\n element.removeEventListener('wheel', this.onMouseWheel, false);\r\n element.removeEventListener('mouseover', this.onMouseFocus, false);\r\n element.removeEventListener('mouseout', this.onMouseFocus, false);\r\n\r\n window.removeEventListener('keydown', this.onKeyDown, false);\r\n window.removeEventListener('keyup', this.onKeyUp, false);\r\n }\r\n\r\n initRenderer() {\r\n this.renderer = new WebGLRenderer({\r\n alpha: true,\r\n });\r\n\r\n this.renderer.autoClear = false;\r\n this.renderer.setPixelRatio(this.pixelRatio);\r\n this.renderer.domElement.id = \"multi-image-canvas\";\r\n\r\n this.camera = new PerspectiveCamera(90);\r\n this.camera.near = 0.1;\r\n this.camera.far = 10;\r\n this.camera.up = new Vector3(0, 0, 1);\r\n\r\n this.cameraScene = new Scene();\r\n this.objectScene = new Scene();\r\n this.backgroundScene = new Scene();\r\n\r\n this.renderUtils = new RenderUtils(\r\n this.renderer,\r\n this.camera,\r\n this.pixelRatio\r\n );\r\n }\r\n\r\n onKeyDown(event) {\r\n if (!this.focused) return;\r\n event.preventDefault();\r\n\r\n if (event.key === \"Shift\") {\r\n this.onZoomStart();\r\n }\r\n }\r\n\r\n onKeyUp(event) {\r\n if (event.key === \"Shift\") {\r\n this.onZoomFinish();\r\n }\r\n }\r\n\r\n onMouseFocus(event) {\r\n if (event.type === 'mouseover') {\r\n this.focused = true;\r\n } else if (event.type === 'mouseout') {\r\n this.focused = false;\r\n }\r\n }\r\n\r\n onMouseDown(event) {\r\n event.preventDefault();\r\n this.mouseControls.onMouseDown(event);\r\n }\r\n\r\n onMouseUp(initialEvent) {\r\n if (!this.mouseControls.down || !this.enabled) return;\r\n\r\n const event = this.mouseControls.onMouseUp(initialEvent);\r\n if (event.mouseMoved || event.isRightClick) return;\r\n\r\n const raycaster = new RayCaster(this, event);\r\n const direction = raycaster.direction;\r\n const position = raycaster.position;\r\n this.addSecondObservation(position, direction);\r\n }\r\n\r\n onMouseMove(initialEvent) {\r\n if (!this.enabled) return;\r\n\r\n const event = this.mouseControls.onMouseMove(initialEvent);\r\n\r\n this.renderUtils.onMouseMove(event);\r\n\r\n if (!event.mouseMoved || !event.mouseDown) return;\r\n\r\n this.mouseControls.updateRotation(\r\n this.camera.fov,\r\n this.width,\r\n this.height\r\n );\r\n }\r\n\r\n onMouseWheel(event) {\r\n if (!this.enabled) return false;\r\n\r\n this.mouseControls.onMouseScroll();\r\n this.mouseControls.onMouseWheel(event);\r\n }\r\n\r\n /** @private */\r\n async onZoomStart() {\r\n if (this.renderUtils.zooming) return;\r\n\r\n await this.renderUtils.updateTexture();\r\n this.renderUtils.zoomToCursor = true;\r\n this.mouseControls.zoomToCursor = true;\r\n await this.saveLastPosition();\r\n }\r\n\r\n /** @private */\r\n onZoomFinish() {\r\n if (!this.renderUtils.zooming) return;\r\n this.renderUtils.zoomToCursor = false;\r\n this.mouseControls.zoomToCursor = false;\r\n this.loadLastPosition();\r\n }\r\n\r\n /** @private */\r\n async saveLastPosition() {\r\n // Save previous state\r\n this.oldCameraState = {\r\n fov: this.camera.fov,\r\n angles: this.mouseControls.angles\r\n };\r\n\r\n // Start slightly more zoomed in\r\n this.mouseControls.zoom(this.camera.fov * 0.80);\r\n }\r\n\r\n /** @private */\r\n loadLastPosition() {\r\n const {fov, angles,} = this.oldCameraState;\r\n\r\n // Restore original FOV\r\n this.mouseControls.fov = fov;\r\n this.mouseControls.updateCameraMatrix();\r\n\r\n // Restore original position\r\n this.mouseControls.angles = angles;\r\n }\r\n\r\n getClickedPoint() {\r\n return this.tools.getClickedPoint();\r\n }\r\n\r\n resetObservations() {\r\n this.resetFirstObservation();\r\n this.resetSecondObservation();\r\n }\r\n\r\n resetFirstObservation() {\r\n this.tools.resetFirstObservation();\r\n this.updateIntersect();\r\n }\r\n\r\n resetSecondObservation() {\r\n this.tools.resetSecondObservation();\r\n this.updateIntersect();\r\n }\r\n\r\n /** @private */\r\n getBestCamera(position: Vector3, direction: Vector3) {\r\n const currentIndex = this.viewer.getCurrentCameraIndex();\r\n const cameras = this.viewer.cameraHandler.cameras;\r\n const numCameras = cameras.length;\r\n\r\n let increment;\r\n let nextIndex;\r\n\r\n if (currentIndex === 0) {\r\n // Only valid direction is forwards\r\n increment = 1;\r\n } else if (currentIndex === (numCameras - 1)) {\r\n // Only valid direction is backwards\r\n increment = -1;\r\n } else {\r\n // Determine direction by creating a line\r\n // and projecting our clicked point on it\r\n let nextIndex = ((currentIndex + 1) % numCameras) % numCameras;\r\n let clickedPoint = new Vector3().copy(position).add(direction);\r\n let nextPosition = cameras[nextIndex].position.scene;\r\n\r\n let nextLine = new Line3(position, nextPosition);\r\n let alongLine = nextLine.closestPointToPointParameter(clickedPoint);\r\n increment = (alongLine > 0.0) ? 1 : -1;\r\n }\r\n\r\n for (let i=1; i<10; i++) {\r\n nextIndex = currentIndex + i*increment;\r\n\r\n // Reached the start / end of list, exit loop early\r\n if ((nextIndex === 0) || (nextIndex === (numCameras - 1))) {\r\n break;\r\n }\r\n\r\n let newPosition = cameras[nextIndex].position.scene;\r\n let distance = position.distanceTo(newPosition);\r\n if (distance >= this.minCameraDistance) {\r\n break;\r\n }\r\n }\r\n\r\n this.loadCamera(nextIndex);\r\n }\r\n\r\n addFirstObservation(position: Vector3, direction: Vector3) {\r\n this.tools.addFirstObservation(position, direction);\r\n this.updateIntersect();\r\n\r\n if (!this.activeCamera) {\r\n this.getBestCamera(position, direction);\r\n }\r\n }\r\n\r\n addSecondObservation(position: Vector3, direction: Vector3) {\r\n this.tools.addSecondObservation(position, direction);\r\n this.updateIntersect();\r\n }\r\n\r\n handleWindowResize() {\r\n this.camera.aspect = this.aspect;\r\n this.camera.updateProjectionMatrix();\r\n\r\n this.renderer.domElement.style.display = \"none\";\r\n this.renderer.setSize(this.width, this.height);\r\n this.renderer.domElement.style.display = \"block\";\r\n\r\n // Re-render is required or else the div will flash white\r\n this.render();\r\n }\r\n\r\n updateMaterial(material, values) {\r\n let keys = Object.keys(values);\r\n keys.forEach(key => {\r\n material[key] = values[key];\r\n });\r\n }\r\n\r\n renderSceneObjects() {\r\n // Render background color and image data\r\n this.renderUtils.setEDLState(false);\r\n this.renderUtils.setRenderTarget(true);\r\n this.renderUtils.renderScene(this.backgroundScene);\r\n this.renderUtils.renderScene(this.cameraScene);\r\n this.renderUtils.renderToTarget(1.0);\r\n\r\n // Render objects\r\n this.renderUtils.setEDLState(true);\r\n this.renderUtils.setRenderTarget(true);\r\n this.renderUtils.renderScene(this.objectScene);\r\n this.renderUtils.renderToTarget(1.0);\r\n\r\n // Render target to screen\r\n this.renderUtils.renderToScreen();\r\n\r\n // Update previous texture\r\n this.renderUtils.renderToPrevious();\r\n }\r\n\r\n render() {\r\n if (!this.enabled) return false;\r\n\r\n this.mouseControls.update();\r\n this.tools.update();\r\n this.renderUtils.update();\r\n\r\n this.renderSceneObjects();\r\n }\r\n};\r\n\r\nclass MultipleCameraMeasurement {\r\n private viewer: Viewer;\r\n private window: MultiImageWindow;\r\n public coordinates = [null, null];\r\n private firstPoint = null;\r\n private secondPoint = null;\r\n private sphereGeometry = new SphereGeometry(0.05, 20, 20);\r\n private sphereMaterial = new MeshBasicMaterial({color: 0xe6e600});\r\n\r\n constructor(viewer, window) {\r\n this.viewer = viewer;\r\n this.window = window;\r\n }\r\n\r\n get viewerScene() {\r\n return this.viewer.measurements.scene;\r\n }\r\n\r\n get viewerCamera() {\r\n return this.viewer.camera;\r\n }\r\n\r\n get windowScene() {\r\n return this.window.objectScene;\r\n }\r\n\r\n get windowCamera() {\r\n return this.window.camera;\r\n }\r\n\r\n get sameCamera() {\r\n const origin1 = this.window.camera?.position;\r\n const origin2 = this.viewer.camera?.position;\r\n\r\n if (origin1 && origin2) {\r\n if (origin1.distanceTo(origin2) < 0.005) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n getEndpoint(origin, direction) {\r\n return direction\r\n .clone()\r\n .setLength(1.0)\r\n .add(origin);\r\n }\r\n\r\n getSphereMesh(position) {\r\n let sphere = new Mesh(this.sphereGeometry, this.sphereMaterial);\r\n sphere.position.copy(position);\r\n\r\n return sphere;\r\n }\r\n\r\n getClickedPoint() {\r\n let rayA = this.coordinates[0];\r\n let rayB = this.coordinates[1];\r\n if ((rayA === null) || (rayB === null)) {\r\n return;\r\n }\r\n\r\n if (this.sameCamera) {\r\n return;\r\n }\r\n\r\n let {point, valid} = this.getIntersection(rayA, rayB);\r\n\r\n if (valid) {\r\n return point;\r\n }\r\n }\r\n\r\n setButtonDisabled(state) {\r\n this.window.disableComplete = state;\r\n this.window.disableAddMore = state;\r\n }\r\n\r\n calculate() {\r\n const defaultResponse = {\r\n error: null,\r\n distances: [0, 0],\r\n calculated: false,\r\n valid: true,\r\n message: null\r\n };\r\n\r\n if (this.sameCamera) {\r\n this.setButtonDisabled(true);\r\n return {\r\n ...defaultResponse,\r\n valid: false,\r\n message: \"Measuring from same camera\"\r\n };\r\n } else {\r\n this.setButtonDisabled(false);\r\n }\r\n\r\n let rayA = this.coordinates[0];\r\n let rayB = this.coordinates[1];\r\n if ((rayA === null) || (rayB === null)) {\r\n return defaultResponse;\r\n }\r\n\r\n let {error, distances, valid, message}\r\n = this.getIntersection(rayA, rayB);\r\n\r\n this.setButtonDisabled(!valid);\r\n\r\n if (!valid) {\r\n return {...defaultResponse, message, valid: false};\r\n }\r\n\r\n return {\r\n ...defaultResponse,\r\n error,\r\n distances,\r\n calculated: true\r\n };\r\n }\r\n\r\n resetFirstObservation() {\r\n if (this.firstPoint) {\r\n this.viewerScene.remove(this.firstPoint);\r\n }\r\n this.coordinates[0] = null;\r\n this.firstPoint = null;\r\n }\r\n\r\n resetSecondObservation() {\r\n if (this.secondPoint) {\r\n this.windowScene.remove(this.secondPoint);\r\n }\r\n this.coordinates[1] = null;\r\n this.secondPoint = null;\r\n }\r\n\r\n addFirstObservation(position, direction) {\r\n this.viewerScene.remove(this.firstPoint);\r\n\r\n let origin = position.clone();\r\n let endPoint = this.getEndpoint(origin, direction);\r\n this.coordinates[0] = {origin, direction};\r\n\r\n this.firstPoint = this.getSphereMesh(endPoint);\r\n this.viewerScene.add(this.firstPoint);\r\n this.updatePointScale();\r\n }\r\n\r\n addSecondObservation(position, direction) {\r\n this.windowScene.remove(this.secondPoint);\r\n\r\n let origin = position.clone();\r\n let endPoint = this.getEndpoint(origin, direction);\r\n this.coordinates[1] = {origin, direction};\r\n\r\n this.secondPoint = this.getSphereMesh(endPoint);\r\n this.windowScene.add(this.secondPoint);\r\n this.updatePointScale();\r\n }\r\n\r\n setPointScale(mesh: Mesh, camera: PerspectiveCamera) {\r\n if (!mesh) return;\r\n const scale = getPointScale(camera, mesh);\r\n mesh.scale.set(scale, scale, scale);\r\n mesh.geometry.computeBoundingSphere();\r\n }\r\n\r\n updatePointScale() {\r\n this.setPointScale(this.firstPoint, this.viewerCamera);\r\n this.setPointScale(this.secondPoint, this.windowCamera);\r\n }\r\n\r\n /** Get closest possible midpoint for two line segments */\r\n getIntersection(rayA, rayB) {\r\n let message = \"\";\r\n let valid = true;\r\n\r\n let Nv = rayA.direction.clone().cross(rayB.direction);\r\n let Na = rayA.direction.clone().cross(Nv).normalize();\r\n let Nb = rayB.direction.clone().cross(Nv).normalize();\r\n let Da = rayA.direction.clone().normalize();\r\n let Db = rayB.direction.clone().normalize();\r\n let da = rayB.origin.clone().sub(rayA.origin).dot(Nb) / Da.dot(Nb);\r\n let db = rayA.origin.clone().sub(rayB.origin).dot(Na) / Db.dot(Na);\r\n let ptA = rayA.origin.clone().add(Da.multiplyScalar(da));\r\n let ptB = rayB.origin.clone().add(Db.multiplyScalar(db));\r\n\r\n // Get our midpoint and segment length\r\n let lineSegment = new Line3(ptA, ptB);\r\n let segmentLength = lineSegment.distance();\r\n let midPoint = new Vector3();\r\n lineSegment.getCenter(midPoint);\r\n\r\n // Make sure our result is in front of us\r\n const d1n = ptA.clone().sub(rayA.origin).setLength(1.0);\r\n const d2n = ptB.clone().sub(rayB.origin).setLength(1.0);\r\n const a1 = Math.abs(rayA.direction.angleTo(d1n));\r\n const a2 = Math.abs(rayB.direction.angleTo(d2n));\r\n const behindCamera = (a1 > 0.005) || (a2 > 0.005);\r\n if (behindCamera) {\r\n valid = false;\r\n message = \"Intersection point behind camera\";\r\n }\r\n\r\n let distances = [\r\n ptA.distanceTo(rayA.origin),\r\n ptB.distanceTo(rayB.origin)\r\n ];\r\n\r\n return {\r\n point: midPoint,\r\n error: segmentLength,\r\n distances,\r\n valid,\r\n message\r\n };\r\n }\r\n\r\n update() {\r\n this.updatePointScale();\r\n }\r\n}\r\n","import {\r\n calculatePointsPCA,\r\n DataProjectionCoordinate,\r\n GeocentricCoordinate,\r\n geometryToArray,\r\n ProjectedCoordinate,\r\n SceneCoordinate,\r\n webMercator\r\n} from '../projections';\r\nimport {MeasurementController} from '.';\r\nimport {getArea, getDistance, getLength} from 'ol/sphere';\r\nimport {LineString, Polygon} from 'ol/geom';\r\nimport Delaunator from 'delaunator';\r\nimport earcut from 'earcut';\r\nimport {nanoid} from '@reduxjs/toolkit';\r\nimport {isMobile, pointInPolygon, randomHexColor, toVector2} from '../utilities';\r\nimport {transform} from 'ol/proj';\r\nimport {t} from '../../localization';\r\nimport {\r\n BufferGeometry,\r\n DoubleSide,\r\n MathUtils,\r\n Mesh,\r\n MeshBasicMaterial,\r\n Triangle,\r\n Vector3\r\n} from 'three';\r\nimport {spiralIntersect} from \"./land-xml-calculation\";\r\nimport {toast} from \"../../app\";\r\nimport { PointCloudManager } from '../pointcloud';\r\nimport {\r\n AerialMeasureType,\r\n AerialSegment,\r\n MeasureType,\r\n SamplingRate,\r\n VolumeType\r\n} from '../../types/measurements';\r\nimport { Units } from '../../types/project';\r\n\r\nexport type MeasurementType = MeasurementArea\r\n | MeasurementLine\r\n | MeasurementPoint\r\n | MeasurementVolume\r\n | SnapDownMeasurement\r\n | SnapUpMeasurement\r\n | HeightMeasurement\r\n | StationMeasurement\r\n\r\nexport class Measurement {\r\n public controller: MeasurementController;\r\n public id = nanoid();\r\n public type: MeasureType;\r\n private _header = 'measure.measurement';\r\n private _title = 'measure.measurement';\r\n public timeCreated = new Date();\r\n\r\n get title() {\r\n return t(this._title);\r\n }\r\n\r\n get header() {\r\n return t(this._header);\r\n }\r\n\r\n get timestamp() {\r\n return Math.floor(this.timeCreated.getTime() / 1000);\r\n }\r\n\r\n get cancelMessage() {\r\n return isMobile\r\n ? t('measure.long-press-to-cancel')\r\n : t('measure.right-click-to-cancel');\r\n }\r\n\r\n get startTooltip() {\r\n console.warn(\"Not Implemented\");\r\n return [] as string[];\r\n }\r\n\r\n get startTooltipMulti() {\r\n return [\r\n t('measure.click-to-add-observation-1')\r\n ];\r\n }\r\n\r\n get endTooltip() {\r\n console.warn(\"Not Implemented\");\r\n return [] as string[];\r\n }\r\n\r\n get endTooltipMulti() {\r\n console.warn(\"Not Implemented\");\r\n return [] as string[];\r\n }\r\n\r\n get moreTooltip() {\r\n console.warn(\"Not Implemented\");\r\n return [] as string[];\r\n }\r\n\r\n get moreTooltipMulti() {\r\n console.warn(\"Not Implemented\");\r\n return [] as string[];\r\n }\r\n\r\n get viewer() {\r\n return this.controller.viewer;\r\n }\r\n\r\n get pointclouds() {\r\n return this.controller.pointclouds;\r\n }\r\n\r\n get valid() {\r\n return true;\r\n }\r\n\r\n get numVertices() {\r\n console.warn(\"Not Implemented\");\r\n return 0;\r\n }\r\n\r\n setController(controller) {\r\n this.controller = controller;\r\n }\r\n\r\n setTitle(title) {\r\n this._title = title;\r\n }\r\n\r\n setHeader(header) {\r\n this._header = header;\r\n }\r\n\r\n setTimestamp(isoTime) {\r\n this.timeCreated = new Date(isoTime);\r\n }\r\n\r\n clear() {}\r\n}\r\n\r\nexport class Measurement3D extends Measurement {\r\n public vertices:Array = [];\r\n public maxVertexLength = 2;\r\n public minVertexRequired = 2;\r\n public type = MeasureType.Length;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.setTitle(\"measure.3d-measurement\");\r\n this.setHeader(\"measure.3d-measurement\");\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-start-line')\r\n ];\r\n }\r\n\r\n get canFinish() {\r\n return (this.vertices.length + 1) >= this.minVertexRequired;\r\n }\r\n\r\n get hasPoints() {\r\n return this.vertices.length > 0;\r\n }\r\n\r\n get numVertices() {\r\n return this.vertices.length;\r\n }\r\n\r\n /** Return 3d distance in meters, based on scene view coordinates */\r\n get distance3D() {\r\n return this.getLineDistance(false);\r\n }\r\n\r\n /** Return 2d distance in meters, based on scene view coordinates */\r\n get distance2D() {\r\n return this.getLineDistance(true);\r\n }\r\n\r\n /** Get measurement height difference in meters, based on scene view coordinates */\r\n get rise() {\r\n // Currently uses the first + last point\r\n let lastIndex = this.vertices.length - 1;\r\n let firstPoint = this.vertices[0].toScene();\r\n let lastPoint = this.vertices[lastIndex].toScene();\r\n let height = Math.abs(lastPoint.z - firstPoint.z);\r\n\r\n return height;\r\n }\r\n\r\n get angle() {\r\n let numberOfPoints = this.vertices.length;\r\n if (numberOfPoints !== 2) {\r\n return NaN;\r\n }\r\n\r\n let angle = Math.atan(this.rise / this.distance2D);\r\n return MathUtils.radToDeg(angle);\r\n }\r\n\r\n get grade() {\r\n let numberOfPoints = this.vertices.length;\r\n if (numberOfPoints !== 2) {\r\n return NaN;\r\n }\r\n\r\n return 100 * (this.rise / this.distance2D);\r\n }\r\n\r\n get coordinates() {\r\n return this.vertices.map(vertex => {\r\n return vertex.toArray();\r\n });\r\n }\r\n\r\n get sceneVertices() {\r\n return this.vertices.map(vertex => {\r\n return vertex.toScene().toArray();\r\n });\r\n }\r\n\r\n add(vertex) {\r\n let finished = false;\r\n let addedPoint = false;\r\n\r\n let coordinate = new SceneCoordinate(vertex).toGeocentric();\r\n\r\n if (this.vertices.length === 0) {\r\n this.vertices.push(coordinate);\r\n addedPoint = true;\r\n } else {\r\n // We only add a new point if the distance travelled is large enough\r\n let oldVertex = this.vertices[this.vertices.length - 1];\r\n if (oldVertex.distanceTo(coordinate) > 0.10) {\r\n // New point is far enough away from previous point\r\n this.vertices.push(coordinate);\r\n addedPoint = true;\r\n } else {\r\n // Clicked the same point twice, so we finish the measurement\r\n // if we have gathered enough points\r\n if (this.vertices.length >= this.minVertexRequired) {\r\n finished = true;\r\n }\r\n }\r\n }\r\n\r\n // For types with a fixed number of points, set finished to\r\n // true if we have reached the max number of points\r\n if (!finished) {\r\n finished = this.vertices.length === this.maxVertexLength;\r\n }\r\n\r\n return {\r\n finished: finished,\r\n added: addedPoint,\r\n valid: true\r\n };\r\n }\r\n\r\n getProjectedVertices(projection) {\r\n let vertices = this.vertices.map(vertex => {\r\n return vertex.toProjection(projection).toArray();\r\n });\r\n\r\n if (this instanceof MeasurementArea) {\r\n vertices.push(vertices[0]);\r\n }\r\n\r\n return vertices;\r\n }\r\n\r\n /** Private */\r\n getLineDistance(ignoreHeight) {\r\n let vertexA;\r\n let vertexB;\r\n\r\n let distance = 0;\r\n let vertices = this.vertices;\r\n\r\n for (var i = 1; i < vertices.length; i++) {\r\n let prevIndex = i - 1;\r\n vertexA = vertices[prevIndex].toScene();\r\n vertexB = vertices[i].toScene();\r\n\r\n if (ignoreHeight) {\r\n vertexA.z = 0;\r\n vertexB.z = 0;\r\n }\r\n\r\n distance += vertexA.distanceTo(vertexB);\r\n }\r\n\r\n return distance;\r\n }\r\n}\r\n\r\nexport class StationMeasurement extends Measurement3D {\r\n public type = MeasureType.Station;\r\n public distAlong = 0.0;\r\n public distAcross = 0.0;\r\n public stationStart = 0.0;\r\n public sideOfLine = 'R';\r\n private clickedPoint;\r\n private enu = false;\r\n public units = Units.Meters;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.setTitle(\"measure.station-measure\");\r\n this.setHeader(\"measure.station-info\");\r\n }\r\n\r\n get activeAlignment() {\r\n return this.controller.activeAlignment;\r\n }\r\n\r\n get alignmentInfo() {\r\n return this.controller.getAlignmentByID(this.activeAlignment);\r\n }\r\n\r\n get startTooltip() {\r\n if (this.activeAlignment) {\r\n return [\r\n t('measure.click-to-station')\r\n ];\r\n } else {\r\n return [\r\n t('measure.choose-alignment')\r\n ];\r\n }\r\n }\r\n\r\n get distanceAcross() {\r\n return this.distAcross;\r\n }\r\n\r\n get distanceAlong() {\r\n return this.distAlong;\r\n }\r\n\r\n get staStart() {\r\n return this.stationStart;\r\n }\r\n\r\n get sideOfSegment() {\r\n return this.sideOfLine;\r\n }\r\n\r\n isBetween(segment) {\r\n if (segment.shapeType === 'Curve') {\r\n const curveCheck = this.curveIntersect(segment, true);\r\n if (!curveCheck) {\r\n return false;\r\n }\r\n }\r\n\r\n const x1 = segment.Start[0];\r\n const x2 = segment.End[0];\r\n const x3 = this.clickedPoint[0];\r\n\r\n const y1 = segment.Start[1];\r\n const y2 = segment.End[1];\r\n const y3 = this.clickedPoint[1];\r\n\r\n const distEndsSquared = Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2);\r\n\r\n const u = ((x3-x1)*(x2-x1)+(y3-y1)*(y2-y1)) / distEndsSquared;\r\n const deltaX = x1 + u * (x2-x1);\r\n const deltaY = y1 + u * (y2-y1);\r\n\r\n const epsilon = 0.001;\r\n const crossProduct = (deltaY - y1) * (x2 - x1) - (deltaX - x1) * (y2 - y1);\r\n if (Math.abs(crossProduct) > epsilon) {\r\n return false;\r\n }\r\n\r\n const dotProduct = (deltaX - x1)*(x2 - x1) + (deltaY - y1)*(y2 - y1);\r\n return !(dotProduct < 0 || dotProduct > distEndsSquared);\r\n }\r\n\r\n getClosestSegment(segments) {\r\n let minDist;\r\n let chosenSegment;\r\n segments.forEach(segmentTest => {\r\n this.lineIntersect(segmentTest, true);\r\n if (!minDist) {\r\n minDist = this.distAcross;\r\n }\r\n if(this.distAcross<=minDist) {\r\n chosenSegment = segmentTest;\r\n minDist = this.distAcross;\r\n }\r\n });\r\n\r\n return chosenSegment;\r\n }\r\n\r\n lineIntersect(segment, checkOnly=false) {\r\n const x1 = segment.Start[0];\r\n const x2 = segment.End[0];\r\n const x3 = this.clickedPoint[0];\r\n\r\n const y1 = segment.Start[1];\r\n const y2 = segment.End[1];\r\n const y3 = this.clickedPoint[1];\r\n\r\n const distEndsSquared = Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2);\r\n\r\n const u = ((x3-x1)*(x2-x1)+(y3-y1)*(y2-y1)) / distEndsSquared;\r\n const deltaX = x1 + u * (x2-x1);\r\n const deltaY = y1 + u * (y2-y1);\r\n\r\n let intersectCoordinate: DataProjectionCoordinate;\r\n let clickedCoordinate: DataProjectionCoordinate;\r\n let startCoordinate: DataProjectionCoordinate;\r\n\r\n if (this.enu){\r\n clickedCoordinate = new DataProjectionCoordinate(\r\n [this.clickedPoint[0], this.clickedPoint[1],\r\n this.clickedPoint[2]]);\r\n startCoordinate = new DataProjectionCoordinate([x1, y1,\r\n this.clickedPoint[2]]);\r\n intersectCoordinate = new DataProjectionCoordinate(\r\n [deltaX, deltaY, this.clickedPoint[2]]);\r\n } else {\r\n clickedCoordinate = new DataProjectionCoordinate(\r\n [this.clickedPoint[1], this.clickedPoint[0],\r\n this.clickedPoint[2]]);\r\n startCoordinate = new DataProjectionCoordinate([y1, x1,\r\n this.clickedPoint[2]]);\r\n intersectCoordinate = new DataProjectionCoordinate(\r\n [deltaY, deltaX, this.clickedPoint[2]]);\r\n }\r\n\r\n if (!checkOnly) {\r\n this.vertices.unshift(intersectCoordinate.toGeocentric());\r\n }\r\n\r\n const intersectCoordinate2D = toVector2(intersectCoordinate);\r\n const clickedCoordinate2D = toVector2(clickedCoordinate);\r\n const startCoordinate2D = toVector2(startCoordinate);\r\n\r\n const distAlong = startCoordinate2D\r\n .distanceTo(intersectCoordinate2D);\r\n\r\n const distAcross = clickedCoordinate2D\r\n .distanceTo(intersectCoordinate2D);\r\n\r\n const sideValue = (x1-x2)*(y3-y2) - (y1-y2)*(x3-x2);\r\n const side = sideValue > 0 ? 'L':'R';\r\n\r\n this.distAlong = distAlong;\r\n this.distAcross = distAcross;\r\n this.sideOfLine = side;\r\n\r\n // console.log(`across: ${this.distAcross} | along: ${this.distAlong} | side: ${this.sideOfLine}`);\r\n\r\n return true;\r\n }\r\n\r\n curveIntersect(segment, checkOnly=false) {\r\n const rotation = segment.rot;\r\n const radius = segment.radius;\r\n const center = segment.Center.slice(0, 2);\r\n const point = this.clickedPoint;\r\n\r\n const distance = Math.sqrt(Math.pow(center[0] - point[0], 2)\r\n + Math.pow(center[1] - point[1], 2));\r\n\r\n const distAcross = radius - distance;\r\n\r\n const pointVector = [(point[0] - center[0]) / distance,\r\n (point[1] - center[1]) / distance];\r\n\r\n const startVector = [(segment.Start[0] - center[0]) / radius,\r\n (segment.Start[1] - center[1]) / radius];\r\n\r\n const endVector = [(segment.End[0] - center[0]) / radius,\r\n (segment.End[1] - center[1]) / radius];\r\n\r\n let pointArc = [center[0] + (radius*pointVector[0]),\r\n center[1]+(radius*pointVector[1])];\r\n\r\n const distStartToArc = Math.sqrt(Math.pow(pointArc[0] - segment.Start[0], 2)\r\n + Math.pow(segment.Start[1] - pointArc[1], 2));\r\n\r\n const calcAngle = Math.acos(1 - (distStartToArc * distStartToArc) /\r\n (2 * radius * radius));\r\n\r\n let angle = Math.atan2(pointVector[1], pointVector[0]);\r\n angle = (angle < 0) ? angle + Math.PI*2 : angle;\r\n let angleStart = Math.atan2(startVector[1], startVector[0]);\r\n angleStart = (angleStart < 0) ? angleStart + Math.PI*2 : angleStart;\r\n let angleEnd = Math.atan2(endVector[1], endVector[0]);\r\n angleEnd = (angleEnd < 0) ? angleEnd + Math.PI*2 : angleEnd;\r\n let angleLarge = (angleStart > angleEnd) ? angleStart : angleEnd;\r\n let angleSmall = (angleStart < angleEnd) ? angleStart : angleEnd;\r\n let angleSmallQuadrant = angleSmall;\r\n let angleLargeQuadrant = angleLarge;\r\n let angleQuadrant = angle;\r\n\r\n // console.log(`original rotations: ${angle} | ${angleStart} | ${angleEnd}`)\r\n // console.log(`original size rotations: ${angle} | ${angleSmall} | ${angleLarge}`)\r\n\r\n if ((angleSmall > 0) && (angleSmall < Math.PI/2)) {\r\n // console.log('small angle check')\r\n if ((angleLarge < Math.PI*2) && (angleLarge > Math.PI * 1.5)) {\r\n // console.log('big angle check')\r\n angleLargeQuadrant = angleSmall + (Math.PI/2);\r\n angleLargeQuadrant = (angleLargeQuadrant > Math.PI*2) ? angleLargeQuadrant - Math.PI*2 : angleLargeQuadrant;\r\n angleSmallQuadrant = angleLarge + (Math.PI/2);\r\n angleSmallQuadrant = (angleSmallQuadrant > Math.PI*2) ? angleSmallQuadrant - Math.PI*2 : angleSmallQuadrant;\r\n angleQuadrant += (Math.PI/2);\r\n angleQuadrant = (angleQuadrant > Math.PI*2) ? angleQuadrant - Math.PI*2 : angleQuadrant;\r\n }\r\n }\r\n // console.log(`altered size rotations: ${angleQuadrant} | ${angleSmallQuadrant} | ${angleLargeQuadrant}`)\r\n let angleReverse = angleQuadrant - Math.PI;\r\n angleReverse = (angleReverse < 0) ? angleReverse + Math.PI*2 : angleReverse;\r\n\r\n if ((angleQuadrant <= angleSmallQuadrant) || (angleQuadrant >= angleLargeQuadrant)) {\r\n if ((angleReverse <= angleSmallQuadrant) || (angleReverse >= angleLargeQuadrant)) {\r\n // console.log(`failed rotations: ${angleReverse} | ${angleSmallQuadrant} | ${angleLargeQuadrant}`)\r\n return false;\r\n }\r\n // console.log(`succeeded rotations: ${angleReverse} | ${angleSmallQuadrant} | ${angleLargeQuadrant}`)\r\n }\r\n\r\n const distAlong = radius * calcAngle;\r\n\r\n if (rotation === \"ccw\"){\r\n if (distAcross > 0){\r\n this.sideOfLine = \"L\";\r\n } else {\r\n this.sideOfLine = \"R\";\r\n }\r\n } else if (rotation === \"cw\") {\r\n if (distAcross > 0) {\r\n this.sideOfLine = \"R\";\r\n } else {\r\n this.sideOfLine = \"L\";\r\n }\r\n } else {\r\n console.error(`Rotation Type ${rotation} is invalid for this geometry`);\r\n return false;\r\n }\r\n\r\n if (!checkOnly){\r\n this.distAcross = Math.abs(distAcross);\r\n this.distAlong = distAlong;\r\n let coordinate;\r\n if (this.enu){\r\n coordinate = new DataProjectionCoordinate(\r\n [pointArc[0], pointArc[1], this.clickedPoint[2]]).toGeocentric();\r\n } else {\r\n coordinate = new DataProjectionCoordinate(\r\n [pointArc[1], pointArc[0], this.clickedPoint[2]]).toGeocentric();\r\n }\r\n this.vertices.unshift(coordinate);\r\n // console.log(`across: ${this.distAcross} | along: ${this.distAlong} | side: ${this.sideOfLine}`);\r\n }\r\n\r\n return true;\r\n }\r\n\r\n spiralIntersection(spiral) {\r\n const results = spiralIntersect(spiral, this.clickedPoint);\r\n if (!results) return false;\r\n\r\n let coordinate;\r\n if (this.enu){\r\n coordinate = new DataProjectionCoordinate(\r\n [results.coordinates[0], results.coordinates[1],\r\n this.clickedPoint[2]]).toGeocentric();\r\n } else {\r\n coordinate = new DataProjectionCoordinate(\r\n [results.coordinates[1], results.coordinates[0],\r\n this.clickedPoint[2]]).toGeocentric();\r\n }\r\n this.distAlong = results.distAlong;\r\n this.distAcross = results.distAcross;\r\n this.sideOfLine = results.sideOfLine;\r\n this.vertices.unshift(coordinate);\r\n\r\n return true;\r\n }\r\n\r\n getIntersect(segment) {\r\n this.stationStart = segment.staStart;\r\n if (segment.shapeType === \"Line\") {\r\n //console.log('Line shape on XML');\r\n return this.lineIntersect(segment);\r\n } else if (segment.shapeType === \"Curve\") {\r\n //console.log('Curve shape on XML');\r\n return this.curveIntersect(segment);\r\n } else if (segment.shapeType === \"Spiral\") {\r\n //console.log('Spiral shape on XML');\r\n return this.spiralIntersection(segment);\r\n } else {\r\n console.error('Unknown Shape type in XML file');\r\n return false;\r\n }\r\n }\r\n\r\n add(vertex) {\r\n let finished = false;\r\n let addedPoint = false;\r\n let valid = false;\r\n\r\n const coordinate = new SceneCoordinate(vertex).toGeocentric();\r\n const clickPointInData = new SceneCoordinate(vertex).toDataProjection();\r\n\r\n const alignmentInfo = this.alignmentInfo;\r\n const enu = alignmentInfo.enu;\r\n const xmlAlignment = alignmentInfo.alignment;\r\n\r\n let units;\r\n if (alignmentInfo.units === \"meter\") {\r\n units = Units.Meters;\r\n } else if (alignmentInfo.units === \"USSurveyFoot\") {\r\n units = Units.SurveyFeet;\r\n } else {\r\n units = Units.Feet;\r\n }\r\n this.units = units;\r\n\r\n if (!xmlAlignment) {\r\n toast.warning(t(\"toast.station-no-alignment\"));\r\n return {\r\n finished: finished,\r\n added: addedPoint,\r\n valid: valid\r\n };\r\n }\r\n\r\n this.enu = enu;\r\n\r\n if (this.enu) {\r\n this.clickedPoint = [clickPointInData.x, clickPointInData.y, clickPointInData.z];\r\n } else {\r\n this.clickedPoint = [clickPointInData.y, clickPointInData.x, clickPointInData.z];\r\n }\r\n\r\n const segments = xmlAlignment.geometry.filter(segment => this.isBetween(segment));\r\n const segment = this.getClosestSegment(segments);\r\n\r\n if (segment) {\r\n finished = this.getIntersect(segment);\r\n if (finished) {\r\n this.vertices.push(coordinate);\r\n addedPoint = true;\r\n const allCoords = this.vertices;\r\n valid = (allCoords.length === 2);\r\n }\r\n } else {\r\n toast.warning(t(\"toast.station-no-segment\"));\r\n }\r\n\r\n return {\r\n finished: finished,\r\n added: addedPoint,\r\n valid: valid\r\n };\r\n }\r\n\r\n loadExistingStation(measurement) {\r\n this.distAlong = measurement.along;\r\n this.distAcross = Math.abs(measurement.across);\r\n this.stationStart = measurement.station;\r\n this.sideOfLine = (measurement.across > 0) ? 'R' : 'L';\r\n this.units = measurement.units;\r\n }\r\n}\r\n\r\nexport class MeasurementLine extends Measurement3D {\r\n public maxVertexLength = 16;\r\n\r\n constructor() {\r\n super();\r\n }\r\n\r\n get moreTooltip() {\r\n return [\r\n t('measure.click-to-add-more-points', {\r\n count: this.numVertices\r\n }),\r\n t('measure.double-click-to-finish'),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get moreTooltipMulti() {\r\n return [\r\n t('measure.click-to-add-observation-1-multiple', {\r\n count: this.numVertices\r\n }),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get endTooltip() {\r\n return this.moreTooltip;\r\n }\r\n\r\n get endTooltipMulti() {\r\n return [\r\n t('measure.click-to-add-observation-1'),\r\n t('measure.number-of-points', {\r\n count: this.numVertices\r\n }),\r\n this.cancelMessage\r\n ];\r\n }\r\n}\r\n\r\nexport class MeasurementPoint extends Measurement3D {\r\n public type = MeasureType.Point;\r\n public maxVertexLength = 1;\r\n public minVertexRequired = 1;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.setTitle(\"measure.3d-point\");\r\n this.setHeader(\"measure.3d-point\");\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-for-single-point')\r\n ];\r\n }\r\n}\r\n\r\nexport class MeasurementArea extends Measurement3D {\r\n public surfaceGenerator: SurfaceGenerator;\r\n public type = MeasureType.Area;\r\n public maxVertexLength = 16;\r\n public minVertexRequired = 3;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.setTitle(\"measure.3d-area\");\r\n this.setHeader(\"measure.3d-area\");\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-start-area')\r\n ];\r\n }\r\n\r\n get moreTooltip() {\r\n return [\r\n t('measure.click-to-add-more-points', {\r\n count: this.numVertices\r\n }),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get moreTooltipMulti() {\r\n return [\r\n t('measure.click-to-add-observation-1-multiple', {\r\n count: this.numVertices\r\n }),\r\n t('measure.number-of-points', {\r\n count: this.numVertices\r\n }),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get endTooltip() {\r\n return [\r\n t('measure.click-to-add-more-points', {\r\n count: this.numVertices\r\n }),\r\n t('measure.double-click-to-finish'),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get endTooltipMulti() {\r\n return [\r\n t('measure.click-to-add-observation-1'),\r\n t('measure.number-of-points', {\r\n count: this.numVertices\r\n }),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get surfaceVertices() {\r\n return this.surfaceGenerator.vertices;\r\n }\r\n\r\n get surfaceIndices() {\r\n return this.surfaceGenerator.indices;\r\n }\r\n\r\n get area() {\r\n return {\r\n area: this.surfaceGenerator.area,\r\n valid: this.surfaceGenerator.valid\r\n };\r\n }\r\n\r\n setController(controller) {\r\n this.controller = controller;\r\n this.surfaceGenerator = new SurfaceGenerator(this);\r\n }\r\n\r\n generateSurface(temporaryPoint: SceneCoordinate = null) {\r\n this.surfaceGenerator.clear();\r\n this.surfaceGenerator.generate(temporaryPoint);\r\n }\r\n\r\n clear() {\r\n this.surfaceGenerator.clear();\r\n }\r\n}\r\n\r\nexport class MeasurementVolume extends MeasurementArea {\r\n public volumeHelper: VolumeHelper;\r\n public type = MeasureType.Volume;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.setHeader(\"measure.3d-volume\");\r\n this.setTitle(\"measure.3d-volume\");\r\n }\r\n\r\n get invalidVolumeMessage() {\r\n return t('measure.invalid-volume');\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-start-volume')\r\n ];\r\n }\r\n\r\n get calculated() {\r\n return this.volumeHelper.calculated;\r\n }\r\n\r\n get calculating() {\r\n return this.volumeHelper.calculatingVolume;\r\n }\r\n\r\n get volume() {\r\n return this.volumeHelper.value;\r\n }\r\n\r\n async calculateVolume() {\r\n const sampleRate = this.controller.sampleRate;\r\n const volumeType = this.controller.volumeType;\r\n\r\n this.volumeHelper.clear();\r\n this.volumeHelper.setSampleRate(sampleRate);\r\n this.volumeHelper.setVolumeType(volumeType);\r\n\r\n await this.volumeHelper.calculate();\r\n\r\n this.controller.renderMeasurement(this);\r\n this.controller.refreshMeasurementList();\r\n }\r\n\r\n /** Cancel webworker and pass empty array as results */\r\n stopVolumeCalculation() {\r\n this.volumeHelper.stopCalculation();\r\n }\r\n\r\n setController(controller) {\r\n this.controller = controller;\r\n this.volumeHelper = new VolumeHelper(this, this.pointclouds);\r\n this.surfaceGenerator = new SurfaceGenerator(this);\r\n }\r\n\r\n loadExistingVolume(value) {\r\n if (!value) return;\r\n this.volumeHelper.setVolume(value);\r\n }\r\n\r\n clear() {\r\n this.volumeHelper.destroyWorker();\r\n this.volumeHelper.clear();\r\n this.surfaceGenerator.clear();\r\n }\r\n}\r\n\r\nexport class HeightMeasurement extends Measurement3D {\r\n public type = MeasureType.Height\r\n\r\n constructor() {\r\n super();\r\n\r\n this.setTitle(\"measure.height-measurement\");\r\n this.setHeader(\"measure.height-measurement\");\r\n }\r\n\r\n get moreTooltip() {\r\n return [\r\n t('measure.select_another_point_to_finish'),\r\n this.cancelMessage\r\n ];\r\n }\r\n\r\n get height() {\r\n let vertex0 = this.vertices[0].toScene();\r\n let vertex1 = this.vertices[1].toScene();\r\n return Math.abs(vertex0.z - vertex1.z);\r\n }\r\n}\r\n\r\nexport class SnapMeasurement extends Measurement3D {\r\n constructor() {\r\n super();\r\n }\r\n\r\n add(vertex) {\r\n let valid = false;\r\n let added = false;\r\n let snapResult = this.snap(vertex);\r\n\r\n let coordinate = new SceneCoordinate(vertex).toGeocentric();\r\n this.vertices.push(coordinate);\r\n\r\n if (snapResult) {\r\n valid = true;\r\n added = true;\r\n\r\n let snapCoordinate = new SceneCoordinate(snapResult).toGeocentric();\r\n this.vertices.push(snapCoordinate);\r\n }\r\n\r\n return {\r\n finished: true,\r\n added: added,\r\n valid: valid\r\n };\r\n }\r\n\r\n snap(vertex) {\r\n let verticalTolerance = 0.30;\r\n let finalHeight;\r\n let validHeights;\r\n\r\n let pos = new Vector3().copy(vertex);\r\n let points = this.pointclouds.pointsInRadius(pos, 0.15);\r\n let heights = points.map(point => point.z);\r\n\r\n if (this instanceof SnapDownMeasurement) {\r\n validHeights = heights.filter(height => vertex.z - height > verticalTolerance);\r\n } else {\r\n validHeights = heights.filter(height => height - vertex.z > verticalTolerance);\r\n }\r\n\r\n if (validHeights.length === 0) {\r\n return undefined;\r\n }\r\n\r\n if (this instanceof SnapDownMeasurement) {\r\n finalHeight = validHeights.reduce((acc, curr) => Math.max(acc, curr));\r\n } else {\r\n finalHeight = validHeights.reduce((acc, curr) => Math.min(acc, curr));\r\n }\r\n\r\n return new Vector3(vertex.x, vertex.y, finalHeight);\r\n }\r\n}\r\n\r\nexport class SnapUpMeasurement extends SnapMeasurement {\r\n constructor() {\r\n super();\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-snap-up')\r\n ];\r\n }\r\n}\r\n\r\nexport class SnapDownMeasurement extends SnapMeasurement {\r\n constructor() {\r\n super();\r\n }\r\n\r\n get startTooltip() {\r\n return [\r\n t('measure.click-to-snap-down')\r\n ];\r\n }\r\n}\r\n\r\nexport class AerialMeasurement extends Measurement {\r\n public geometry;\r\n\r\n constructor(geometry = null) {\r\n super();\r\n\r\n this.setTitle(null);\r\n this.setHeader(\"measure.2d-measurement\");\r\n this.geometry = geometry;\r\n }\r\n\r\n get distance2D() {\r\n const type = this.controller.aerialMeasureType;\r\n return getAerialLength(this.geometry, type);\r\n }\r\n\r\n get coordinates() {\r\n return this.geometry.getCoordinates();\r\n }\r\n\r\n get numVertices() {\r\n return this.coordinates[0].length;\r\n }\r\n\r\n getGeometry() {\r\n return this.geometry;\r\n }\r\n\r\n getProjectedVertices(projection) {\r\n return geometryToArray(this.geometry, projection);\r\n }\r\n\r\n loadFromCoordinates(coordinates) {}\r\n}\r\n\r\nexport class AerialLengthMeasurement extends AerialMeasurement {\r\n public type = MeasureType.Length;\r\n\r\n constructor(geometry = null) {\r\n super(geometry);\r\n\r\n this.setTitle(\"measure.2d-length\");\r\n this.setHeader(\"measure.length\");\r\n }\r\n\r\n loadFromCoordinates(coordinates) {\r\n this.geometry = new LineString(coordinates);\r\n }\r\n}\r\n\r\nexport class AerialAreaMeasurement extends AerialMeasurement {\r\n public type = MeasureType.Area\r\n\r\n constructor(geometry = null) {\r\n super(geometry);\r\n\r\n this.setTitle(\"measure.2d-area\");\r\n this.setHeader(\"measure.area\");\r\n }\r\n\r\n get numVertices() {\r\n return this.coordinates[0].length - 1;\r\n }\r\n\r\n get area() {\r\n const type = this.controller.aerialMeasureType;\r\n return getAerialArea(this.geometry, type);\r\n }\r\n\r\n loadFromCoordinates(coordinates) {\r\n this.geometry = new Polygon(coordinates);\r\n }\r\n}\r\n\r\nclass VolumeHelper {\r\n private measurement: MeasurementVolume;\r\n private pointclouds: PointCloudManager;\r\n public calculatingVolume = false;\r\n public calculated = false;\r\n public value = 0.0;\r\n private sigma = 2.0;\r\n private numNeighbours = 10;\r\n private sampleRate = SamplingRate.Medium;\r\n private volumeType = VolumeType.MultiPlane;\r\n private worker = null;\r\n private vertices;\r\n private bounds;\r\n private meshes = [];\r\n\r\n constructor(measurement, pointclouds) {\r\n this.measurement = measurement;\r\n this.pointclouds = pointclouds;\r\n this.initWebworker();\r\n this.clear();\r\n }\r\n\r\n get scene() {\r\n return this.measurement.controller.scene;\r\n }\r\n\r\n setVolumeType(type: VolumeType) {\r\n this.volumeType = type;\r\n }\r\n\r\n setSampleRate(rate: SamplingRate) {\r\n this.sampleRate = rate;\r\n }\r\n\r\n async calculate() {\r\n if (this.calculatingVolume) return;\r\n\r\n this.vertices = this.measurement.vertices.map(vertex => {\r\n return vertex.toScene();\r\n });\r\n\r\n if (this.volumeType === VolumeType.LowestPlane) {\r\n const minHeight = Math.min(...this.vertices.map(x => x.z));\r\n this.vertices.forEach(vertex => {\r\n vertex.z = minHeight;\r\n });\r\n }\r\n\r\n this.bounds = this.getCalculatedBounds();\r\n\r\n await this.calculateVolume();\r\n }\r\n\r\n initWebworker() {\r\n const workerURL = \"workers/sparse-outliers.js\";\r\n this.worker = new Worker(`${process.env.PUBLIC_URL}/${workerURL}`);\r\n }\r\n\r\n getCalculatedBounds() {\r\n let arr = this.vertices;\r\n\r\n let x = arr.map(vertex => vertex.x);\r\n let xMin = Math.min(...x);\r\n let xMax = Math.max(...x);\r\n\r\n let y = arr.map(vertex => vertex.y);\r\n let yMin = Math.min(...y);\r\n let yMax = Math.max(...y);\r\n\r\n let z = arr.map(vertex => vertex.z);\r\n let zMin = Math.min(...z);\r\n let zMax = Math.max(...z);\r\n\r\n let center = new Vector3(\r\n xMin + (xMax - xMin) / 2.0,\r\n yMin + (yMax - yMin) / 2.0,\r\n zMin + (zMax - zMin) / 2.0\r\n );\r\n\r\n let size = Math.max(xMax - xMin, yMax - yMin);\r\n\r\n return {\r\n center: center,\r\n size: size\r\n };\r\n }\r\n\r\n async removeOutliers(points): Promise {\r\n return new Promise(resolve => {\r\n this.worker.onmessage = event => {\r\n resolve(event.data);\r\n };\r\n\r\n this.worker.postMessage({\r\n points: points,\r\n sigma: this.sigma,\r\n numNeighbours: this.numNeighbours\r\n });\r\n });\r\n }\r\n\r\n destroyWorker() {\r\n if (!this.worker) return;\r\n\r\n this.worker.terminate();\r\n this.initWebworker();\r\n }\r\n\r\n drawMesh(points, triangles) {\r\n const material = new MeshBasicMaterial({\r\n color: 0xFFFFFF, side: DoubleSide});\r\n\r\n const indices = triangles.flat();\r\n const geometry = new BufferGeometry().setFromPoints(points);\r\n geometry.setIndex(indices);\r\n\r\n const mesh = new Mesh(geometry, material);\r\n\r\n this.meshes.push(mesh);\r\n this.scene.add(mesh);\r\n }\r\n\r\n setVolume(value) {\r\n this.calculated = true;\r\n this.value = value;\r\n }\r\n\r\n getVolume(points, triangles) {\r\n let volume = 0;\r\n triangles.forEach(tri => {\r\n let p1 = points[tri[0]].clone();\r\n let p2 = points[tri[1]].clone();\r\n let p3 = points[tri[2]].clone();\r\n let signedTetrahedronVolume = p1.dot(p2.cross(p3)) / 6.0;\r\n volume += signedTetrahedronVolume;\r\n });\r\n\r\n return volume;\r\n }\r\n\r\n generateTriangleArray(buffer, reverse = false) {\r\n let arr = Array.from(buffer);\r\n let v1 = arr.filter((v, index) => index % 3 === 0);\r\n let v2 = arr.filter((v, index) => index % 3 === 1);\r\n let v3 = arr.filter((v, index) => index % 3 === 2);\r\n let final = [];\r\n for (var i = 0; i < arr.length / 3; i++) {\r\n let vertices = [v1[i], v2[i], v3[i]];\r\n if (reverse) {\r\n vertices = [v1[i], v3[i], v2[i]];\r\n }\r\n final.push(vertices);\r\n }\r\n\r\n return final;\r\n }\r\n\r\n removeInvalidTriangles(points, triangles) {\r\n let validTriangles = [];\r\n triangles.forEach(triangle => {\r\n let p1 = points[triangle[0]];\r\n let p2 = points[triangle[1]];\r\n let p3 = points[triangle[2]];\r\n\r\n let tri = new Triangle(p1, p2, p3);\r\n let center = new Vector3();\r\n tri.getMidpoint(center);\r\n let valid = pointInPolygon(center, this.vertices);\r\n\r\n if (valid) {\r\n validTriangles.push(triangle);\r\n }\r\n });\r\n\r\n return validTriangles;\r\n }\r\n\r\n getDelaunayTriangles(points, reverseWinding) {\r\n let xFunc = point => {\r\n return point.x;\r\n };\r\n\r\n let yFunc = point => {\r\n return point.y;\r\n };\r\n\r\n let delaunay = Delaunator.from(points, xFunc, yFunc);\r\n\r\n let triangles = this.generateTriangleArray(delaunay.triangles, reverseWinding);\r\n triangles = this.removeInvalidTriangles(points, triangles);\r\n\r\n return triangles;\r\n }\r\n\r\n async calculateVolume() {\r\n this.calculatingVolume = true;\r\n this.measurement.controller.refreshMeasurementList();\r\n\r\n // Create a more dense version of our boundary polygon\r\n let denseBounds = getDensePolygon(this.vertices, this.sampleRate);\r\n\r\n // Query points for this bounding box\r\n let points = this.pointclouds.pointsInRadius(this.bounds.center,\r\n this.bounds.size / 2.0);\r\n\r\n // Get the points inside a polygon only\r\n points = this.pointclouds.pointsInPolygon(points, this.vertices);\r\n\r\n const callback = point => {\r\n let x = Math.floor(point.x / this.sampleRate);\r\n let y = Math.floor(point.y / this.sampleRate);\r\n return `${x}-${y}`;\r\n };\r\n\r\n // Calculate DTM for points, in a 2d grid\r\n points = this.pointclouds.getSampledPoints(points, true, callback);\r\n\r\n // Remove sparse outliers\r\n points = await this.removeOutliers(points);\r\n\r\n this.calculationFinished(points, denseBounds);\r\n }\r\n\r\n calculationFinished(points, denseBounds=[]) {\r\n this.destroyWorker();\r\n\r\n if (points.length !== 0) {\r\n this.webWorkerFinished(points, denseBounds);\r\n }\r\n\r\n this.calculatingVolume = false;\r\n this.measurement.controller.refreshMeasurementList();\r\n }\r\n\r\n /** @private */\r\n webWorkerFinished(pointsArray, denseBounds) {\r\n const points = pointsArray.map(point => {\r\n return new Vector3().copy(point);\r\n });\r\n\r\n // Calculate upper mesh with reverse winding order\r\n const upperPoints = [...denseBounds, ...points];\r\n const trianglesUpper = this.getDelaunayTriangles(\r\n upperPoints, true);\r\n\r\n // Calculate lower mesh\r\n const lowerPoints = [...denseBounds];\r\n const trianglesLower = this.getDelaunayTriangles(\r\n lowerPoints, false);\r\n\r\n const trianglesCombined = [\r\n ...trianglesLower,\r\n ...trianglesUpper\r\n ];\r\n\r\n this.value = this.getVolume(upperPoints, trianglesCombined);\r\n this.drawMesh(upperPoints, trianglesCombined);\r\n this.calculated = true;\r\n }\r\n\r\n /** @private */\r\n stopCalculation() {\r\n if (!this.calculatingVolume) return;\r\n this.calculationFinished([]);\r\n }\r\n\r\n clear() {\r\n this.meshes.forEach(mesh => {\r\n this.scene.remove(mesh);\r\n });\r\n\r\n this.meshes = [];\r\n this.value = null;\r\n this.calculatingVolume = false;\r\n this.calculated = false;\r\n }\r\n}\r\n\r\nclass SurfaceGenerator {\r\n private measurement: MeasurementArea;\r\n private changeRequired = 0.01;\r\n private renderInScene = false;\r\n public indices = [];\r\n private meshes = [];\r\n public vertices = [];\r\n public area = 0;\r\n\r\n constructor(measurement) {\r\n this.measurement = measurement;\r\n this.clear();\r\n }\r\n\r\n get scene() {\r\n let measurement = this.measurement;\r\n return measurement.controller.scene;\r\n }\r\n\r\n get valid() {\r\n return this.indices.length > 0;\r\n }\r\n\r\n clear() {\r\n this.removeMeshesFromScene();\r\n this.indices = [];\r\n this.meshes = [];\r\n }\r\n\r\n addMeshesToScene() {\r\n if (!this.meshes || !this.renderInScene) {\r\n return;\r\n }\r\n\r\n this.meshes.forEach(mesh => {\r\n this.scene.add(mesh);\r\n });\r\n }\r\n\r\n removeMeshesFromScene() {\r\n if (!this.meshes || !this.renderInScene) {\r\n return;\r\n }\r\n\r\n this.meshes.forEach(mesh => {\r\n this.scene.remove(mesh);\r\n });\r\n }\r\n\r\n generateMesh(triangle) {\r\n let hexColor = randomHexColor(); // TODO: remove random coloring later\r\n\r\n const vertices = [triangle.a, triangle.b, triangle.c];\r\n const geometry = new BufferGeometry()\r\n .setFromPoints(vertices);\r\n\r\n const material = new MeshBasicMaterial({\r\n color: hexColor,\r\n side: DoubleSide\r\n });\r\n\r\n const mesh = new Mesh(geometry, material);\r\n\r\n return mesh;\r\n }\r\n\r\n calculateArea() {\r\n let area = 0;\r\n\r\n this.indices.forEach(indices => {\r\n let triangle = new Triangle(\r\n this.vertices[indices[0]],\r\n this.vertices[indices[1]],\r\n this.vertices[indices[2]]\r\n );\r\n area += triangle.getArea();\r\n });\r\n\r\n this.area = area;\r\n }\r\n\r\n optimize(vertices, triangleIndices) {\r\n let verticesModified = false;\r\n let numIndices = triangleIndices.length;\r\n\r\n for (var triIndexA = 0; triIndexA < numIndices; triIndexA++) {\r\n for (var triIndexB = 0; triIndexB < numIndices; triIndexB++) {\r\n if (verticesModified) {\r\n continue;\r\n }\r\n\r\n let triA = triangleIndices[triIndexA];\r\n let triB = triangleIndices[triIndexB];\r\n\r\n let vertSet = new Set([...triA, ...triB]);\r\n let allVerts = Array.from(vertSet);\r\n if (allVerts.length !== 4) {\r\n continue;\r\n }\r\n\r\n let sharedVerts = triA.filter(x => triB.includes(x));\r\n let uniqueVerts = allVerts.filter(x => !sharedVerts.includes(x));\r\n\r\n let modTriA = [...uniqueVerts, sharedVerts[0]];\r\n let modTriB = [...uniqueVerts, sharedVerts[1]];\r\n\r\n let t1 = new Triangle(vertices[triA[0]],\r\n vertices[triA[1]], vertices[triA[2]]);\r\n let t2 = new Triangle(vertices[triB[0]],\r\n vertices[triB[1]], vertices[triB[2]]);\r\n let oldArea = t1.getArea() + t2.getArea();\r\n\r\n let t3 = new Triangle(vertices[modTriA[0]],\r\n vertices[modTriA[1]], vertices[modTriA[2]]);\r\n let t4 = new Triangle(vertices[modTriB[0]],\r\n vertices[modTriB[1]], vertices[modTriB[2]]);\r\n let newArea = t3.getArea() + t4.getArea();\r\n\r\n // New area must be smaller\r\n if (newArea > oldArea) {\r\n continue;\r\n }\r\n\r\n // Difference between areas must be non-trivial\r\n let diff = (oldArea - newArea) / oldArea;\r\n if (diff < this.changeRequired) {\r\n continue;\r\n }\r\n\r\n triangleIndices[triIndexA] = modTriA;\r\n triangleIndices[triIndexB] = modTriB;\r\n verticesModified = true;\r\n }\r\n }\r\n\r\n if (verticesModified) {\r\n return this.optimize(vertices, triangleIndices);\r\n }\r\n\r\n return triangleIndices;\r\n }\r\n\r\n generate(temporaryPoint: SceneCoordinate) {\r\n this.vertices = this.measurement.vertices.map(vertex => {\r\n return vertex.toScene();\r\n });\r\n\r\n if (temporaryPoint) {\r\n this.vertices.push(temporaryPoint);\r\n }\r\n\r\n let numVertices = this.vertices.length;\r\n let triangles = [];\r\n\r\n if (numVertices === 3) {\r\n triangles.push([0, 1, 2]);\r\n } else if (numVertices > 3) {\r\n let points = calculatePointsPCA(this.vertices, true);\r\n let indices = earcut(points, null, 3);\r\n let deviation = earcut.deviation(points, null, 3, indices);\r\n\r\n // Deviation must be nearly zero to be valid\r\n if (deviation > 1E-6) {\r\n return;\r\n }\r\n\r\n let triangleIndices = [];\r\n let numTriangles = indices.length / 3;\r\n for (var i = 0; i < numTriangles; i++) {\r\n triangleIndices.push([\r\n indices[3 * i],\r\n indices[3 * i + 1],\r\n indices[3 * i + 2]\r\n ]);\r\n }\r\n\r\n // Optimized surface meshes\r\n triangleIndices = this.optimize(this.vertices, triangleIndices);\r\n\r\n triangleIndices.forEach(triVertices => {\r\n triangles.push(triVertices);\r\n });\r\n }\r\n\r\n let meshes = [];\r\n triangles.forEach(indices => {\r\n let triangle = new Triangle(\r\n this.vertices[indices[0]],\r\n this.vertices[indices[1]],\r\n this.vertices[indices[2]]\r\n );\r\n let mesh = this.generateMesh(triangle);\r\n meshes.push(mesh);\r\n });\r\n\r\n this.indices = triangles;\r\n this.meshes = meshes;\r\n\r\n this.addMeshesToScene();\r\n this.calculateArea();\r\n }\r\n}\r\n\r\nexport const getAerialArea = (geometry, type: AerialMeasureType) => {\r\n let area = 0;\r\n let valid = false;\r\n\r\n if (type === AerialMeasureType.Spherical) {\r\n area = getArea(geometry);\r\n valid = true;\r\n }\r\n\r\n if (type === AerialMeasureType.Planar) {\r\n const flatCoordinates = geometry.flatCoordinates;\r\n const numPoints = flatCoordinates.length / 2;\r\n\r\n const points = [];\r\n const flatPoints = [];\r\n for (let i=0; i {\r\n let triangle = new Triangle(\r\n points[indices[0]],\r\n points[indices[1]],\r\n points[indices[2]]\r\n );\r\n area += triangle.getArea();\r\n });\r\n }\r\n\r\n return {area, valid};\r\n};\r\n\r\nexport const getAerialLength = (geometry, type: AerialMeasureType) => {\r\n let length = 0;\r\n\r\n if (type === AerialMeasureType.Spherical) {\r\n length = getLength(geometry);\r\n }\r\n\r\n if (type === AerialMeasureType.Planar) {\r\n const flatCoordinates = geometry.flatCoordinates;\r\n const numPoints = flatCoordinates.length / 2;\r\n\r\n for (let i=0; i {\r\n const flatCoordinates = geometry.flatCoordinates;\r\n const numPoints = flatCoordinates.length / 2;\r\n\r\n const segments: AerialSegment[] = [];\r\n\r\n for (let i=0; i {\r\n let densePolygonTemp = [];\r\n\r\n vertices.forEach((start, index) => {\r\n let nextIndex = (index + 1) % vertices.length;\r\n\r\n let end = vertices[nextIndex];\r\n let direction = new Vector3().add(end).sub(start);\r\n let vectorLength = direction.length();\r\n let steps = Math.floor(vectorLength / spacing);\r\n let increment = vectorLength / steps;\r\n direction.setLength(1.0);\r\n\r\n if (steps === 0) {\r\n densePolygonTemp.push(start);\r\n return;\r\n }\r\n\r\n for (var i = 0; i <= steps; i++) {\r\n let directionIncrement = new Vector3().add(direction)\r\n .multiplyScalar(increment * i);\r\n let final = new Vector3().add(start).add(directionIncrement);\r\n densePolygonTemp.push(final);\r\n }\r\n });\r\n\r\n let densePolygon = [];\r\n densePolygonTemp.forEach((point, index) => {\r\n if (index === 0) {\r\n densePolygon.push(point);\r\n } else {\r\n let old = densePolygonTemp[index - 1];\r\n let distance = point.distanceTo(old);\r\n if (distance > 0) {\r\n densePolygon.push(point);\r\n }\r\n }\r\n });\r\n\r\n return densePolygonTemp;\r\n};\r\n","import { getAerialArea, getAerialLength, getAerialSegments, MeasurementController } from \".\";\r\nimport {Circle as CircleStyle, Fill, Stroke, Style} from \"ol/style\";\r\nimport {Vector as VectorSource} from \"ol/source\";\r\nimport {Vector as VectorLayer} from \"ol/layer\";\r\nimport {Draw} from \"ol/interaction\";\r\nimport Overlay from 'ol/Overlay';\r\nimport {unByKey} from 'ol/Observable';\r\nimport Feature from 'ol/Feature';\r\nimport Polygon from 'ol/geom/Polygon';\r\nimport LineString from 'ol/geom/LineString';\r\nimport './aerial-tooltip.css';\r\nimport { setAerialTooltip } from \"../viewer\";\r\nimport { t } from \"../../localization\";\r\nimport { MeasureType } from \"../../types/measurements\";\r\nimport { MapBrowserEvent } from \"ol\";\r\n\r\nexport class MinimapMeasure {\r\n private controller: MeasurementController;\r\n private mapSource: VectorSource;\r\n private mapLayer: VectorLayer;\r\n private styleHover: Style;\r\n private styleDefault: Style;\r\n private drawStyle: Style;\r\n\r\n public enabled = false;\r\n public measurementType: MeasureType;\r\n public sketch = null;\r\n private draw = null;\r\n private initialized = false;\r\n private tempTooltips = [];\r\n private measurements = [];\r\n\r\n constructor(controller) {\r\n this.controller = controller;\r\n\r\n this.styleHover = new Style({\r\n fill: new Fill({\r\n color: 'rgba(255, 255, 255, 0.2)'\r\n }),\r\n image: new CircleStyle({\r\n radius: 7,\r\n fill: new Fill({\r\n color: '#008B8B'\r\n })\r\n }),\r\n stroke: new Stroke({\r\n color: \"#ffcc33\",\r\n width: 2\r\n })\r\n });\r\n\r\n this.styleDefault = new Style({\r\n fill: new Fill({\r\n color: 'rgba(255, 255, 255, 0.2)'\r\n }),\r\n image: new CircleStyle({\r\n radius: 7,\r\n fill: new Fill({\r\n color: '#008B8B'\r\n })\r\n }),\r\n stroke: new Stroke({\r\n color: \"#008B8B\",\r\n width: 2\r\n })\r\n });\r\n\r\n this.drawStyle = new Style({\r\n fill: new Fill({\r\n color: 'rgba(255, 255, 255, 0.2)'\r\n }),\r\n stroke: new Stroke({\r\n color: 'rgba(0, 0, 0, 0.5)',\r\n lineDash: [10, 10],\r\n width: 2\r\n }),\r\n image: new CircleStyle({\r\n radius: 5,\r\n stroke: new Stroke({\r\n color: 'rgba(0, 0, 0, 0.7)'\r\n }),\r\n fill: new Fill({\r\n color: 'rgba(255, 255, 255, 0.2)'\r\n })\r\n })\r\n });\r\n }\r\n\r\n get map() {\r\n return this.controller.viewer.minimap.map;\r\n }\r\n\r\n get mapElement() {\r\n return this.controller.viewer.minimap.containerElement;\r\n }\r\n\r\n get drawingType() {\r\n return (this.measurementType === MeasureType.Area)\r\n ? \"Polygon\"\r\n : \"LineString\";\r\n }\r\n\r\n get moreTooltip() {\r\n let coordinates = this.sketch.getGeometry().flatCoordinates;\r\n let numPoints = (coordinates.length / 2.0) - 1;\r\n\r\n let canFinish = (this.measurementType === MeasureType.Area)\r\n ? numPoints > 2\r\n : true;\r\n\r\n if (canFinish) {\r\n return [\r\n t(\"measure.click-to-add-more-points\", {\r\n count: numPoints\r\n }),\r\n t('measure.double-click-to-finish'),\r\n t('measure.right-click-to-cancel')\r\n ];\r\n }\r\n\r\n return [\r\n t(\"measure.click-to-add-more-points\", {\r\n count: numPoints\r\n }),\r\n t('measure.right-click-to-cancel')\r\n ];\r\n }\r\n\r\n get startTooltip() {\r\n if (this.measurementType === MeasureType.Length) {\r\n return [t('measure.click-to-start-drawing-line')];\r\n }\r\n\r\n if (this.measurementType === MeasureType.Area) {\r\n return [t('measure.click-to-start-drawing-polygon')];\r\n }\r\n\r\n return [t('measure.invalid-measure-type')];\r\n }\r\n\r\n get formatter() {\r\n return this.controller.formatter;\r\n }\r\n\r\n init() {\r\n if (this.initialized) return;\r\n\r\n this.mapSource = new VectorSource({\r\n wrapX: false\r\n });\r\n\r\n this.mapLayer = new VectorLayer({\r\n zIndex: 1,\r\n source: this.mapSource,\r\n style: feature => {\r\n return feature.get(\"hover\")\r\n ? this.styleHover\r\n : this.styleDefault;\r\n },\r\n properties: {\r\n type: \"measure\"\r\n }\r\n });\r\n\r\n this.map.addLayer(this.mapLayer);\r\n\r\n this.addInteraction();\r\n this.initEvents();\r\n this.initialized = true;\r\n }\r\n\r\n initEvents() {\r\n this.mapElement.addEventListener('mouseenter', () => {\r\n if (this.controller.enabled) {\r\n this.reloadInteraction();\r\n }\r\n });\r\n\r\n this.mapElement.addEventListener('mouseleave', () => {\r\n if (this.controller.enabled) {\r\n this.removeInteraction();\r\n }\r\n });\r\n }\r\n\r\n render(measurement) {\r\n this.removeByID(measurement.id);\r\n\r\n const geometry = measurement.geometry;\r\n const feature = new Feature(geometry);\r\n feature.set(\"hover\", false);\r\n\r\n const tooltips = this.getTooltipsForGeometry(geometry);\r\n this.mapSource.addFeature(feature);\r\n\r\n this.measurements.push({\r\n id: measurement.id,\r\n feature,\r\n tooltips\r\n });\r\n }\r\n\r\n getByID(id) {\r\n return this.measurements.find(measurement => measurement.id === id);\r\n }\r\n\r\n removeByID(id) {\r\n const measurement = this.getByID(id);\r\n if (!measurement) return;\r\n\r\n const {feature, tooltips} = measurement;\r\n\r\n this.mapSource.removeFeature(feature);\r\n tooltips.forEach(tooltip => {\r\n this.map.removeOverlay(tooltip);\r\n });\r\n\r\n this.measurements = this.measurements\r\n .filter(measurement => measurement.id !== id);\r\n }\r\n\r\n removeAll() {\r\n [...this.measurements].forEach(measurement => {\r\n this.removeByID(measurement.id);\r\n });\r\n\r\n this.measurements = [];\r\n }\r\n\r\n setHover(id, hover) {\r\n const measurement = this.getByID(id);\r\n if (!measurement) return;\r\n\r\n measurement.feature.set(\"hover\", hover);\r\n measurement.tooltips.forEach(tooltip => {\r\n const element = tooltip.element;\r\n const child = element.children[0];\r\n\r\n if (hover) {\r\n child.classList.add(\"tooltip-hover\");\r\n } else {\r\n child.classList.remove(\"tooltip-hover\");\r\n }\r\n });\r\n }\r\n\r\n setMeasurementType(measurementType: MeasureType) {\r\n const validMeasureType = (measurementType === MeasureType.Length)\r\n || (measurementType === MeasureType.Area);\r\n\r\n this.measurementType = validMeasureType\r\n ? measurementType\r\n : null;\r\n\r\n this.reloadInteraction();\r\n\r\n if (this.measurementType === null) {\r\n this.removeInteraction();\r\n }\r\n }\r\n\r\n onMouseMove(event: MapBrowserEvent) {\r\n if (event.dragging) return;\r\n\r\n let helpMsg = this.sketch\r\n ? this.moreTooltip\r\n : this.startTooltip;\r\n\r\n setAerialTooltip(helpMsg);\r\n }\r\n\r\n getTooltipsForGeometry(geometry) {\r\n const tooltips = [];\r\n const type = this.controller.aerialMeasureType;\r\n\r\n // Per segment length tooltips\r\n const segments = getAerialSegments(geometry, type);\r\n segments.forEach(segment => {\r\n const {midpoint, length} = segment;\r\n const message = this.formatter.formatLength(length);\r\n const {element, tooltip} = this.addNewTooltip(false);\r\n tooltip.setPosition(midpoint);\r\n element.innerHTML = message;\r\n tooltips.push(tooltip);\r\n });\r\n\r\n // Additional tooltip for total length / area\r\n let objectMessage;\r\n let objectPosition;\r\n\r\n // Total line length\r\n if (geometry instanceof LineString) {\r\n const length = getAerialLength(geometry, type);\r\n objectMessage = this.formatter.formatLength(length);\r\n objectPosition = geometry.getLastCoordinate();\r\n }\r\n\r\n // Total area\r\n const hasEnoughSegments = segments.length >= 3;\r\n if ((geometry instanceof Polygon) && hasEnoughSegments) {\r\n const {area, valid} = getAerialArea(geometry, type);\r\n\r\n objectMessage = valid\r\n ? this.formatter.formatArea(area)\r\n : t('measure.invalid-area');\r\n\r\n objectPosition = geometry\r\n .getInteriorPoint()\r\n .getCoordinates();\r\n }\r\n\r\n if (objectPosition) {\r\n const {element, tooltip} = this.addNewTooltip(true);\r\n tooltip.setPosition(objectPosition);\r\n element.innerHTML = objectMessage;\r\n tooltips.push(tooltip);\r\n }\r\n\r\n return tooltips;\r\n }\r\n\r\n clearTempTooltips() {\r\n this.tempTooltips.forEach(tooltip => {\r\n this.map.removeOverlay(tooltip);\r\n });\r\n\r\n this.tempTooltips = [];\r\n }\r\n\r\n reloadInteraction() {\r\n if (!this.map) return;\r\n\r\n if (this.draw) {\r\n this.map.removeInteraction(this.draw);\r\n }\r\n\r\n this.sketch = null;\r\n this.addInteraction();\r\n }\r\n\r\n removeInteraction() {\r\n if (!this.draw) return;\r\n\r\n this.clearTempTooltips();\r\n this.map.removeInteraction(this.draw);\r\n }\r\n\r\n cancelMeasurement() {\r\n if (!this.sketch) return false;\r\n\r\n this.reloadInteraction();\r\n setAerialTooltip(this.startTooltip);\r\n return true;\r\n }\r\n\r\n addInteraction() {\r\n if (this.measurementType === null || this.map === null) return;\r\n if (!this.controller.editable) return;\r\n\r\n this.removeInteraction();\r\n\r\n this.draw = new Draw({\r\n type: this.drawingType,\r\n condition: event => event.originalEvent.button === 0,\r\n style: this.drawStyle\r\n });\r\n\r\n this.map.addInteraction(this.draw);\r\n\r\n let listener;\r\n\r\n this.draw.on('drawstart', event => {\r\n this.sketch = event.feature;\r\n this.clearTempTooltips();\r\n\r\n const geometry = this.sketch.getGeometry();\r\n listener = geometry.on('change', () => {\r\n this.clearTempTooltips();\r\n this.tempTooltips = this.getTooltipsForGeometry(geometry);\r\n });\r\n }, this);\r\n\r\n this.draw.on('drawend', (event) => {\r\n this.clearTempTooltips();\r\n\r\n this.sketch = null;\r\n unByKey(listener);\r\n\r\n const geometry = event.feature.getGeometry();\r\n this.controller.addAerialMeasurement(\r\n geometry, this.measurementType);\r\n\r\n setAerialTooltip(this.startTooltip);\r\n }, this);\r\n }\r\n\r\n addNewTooltip(alternateColor) {\r\n const element = document.createElement('div');\r\n element.className = \"tooltip tooltip-minimap\";\r\n\r\n element.className = alternateColor\r\n ? \"tooltip tooltip-minimap tooltip-alternate\"\r\n : \"tooltip tooltip-minimap\";\r\n\r\n const tooltip = new Overlay({\r\n element,\r\n positioning: \"center-center\",\r\n className: \"ol-overlay-container tooltip-container\"\r\n });\r\n\r\n this.map.addOverlay(tooltip);\r\n return {tooltip, element};\r\n }\r\n}\r\n","import {\r\n MeasurementArea,\r\n MeasurementLine,\r\n MeasurementPoint,\r\n MeasurementVolume,\r\n SnapDownMeasurement,\r\n SnapUpMeasurement,\r\n MeasurementController,\r\n HeightMeasurement,\r\n MeasurementType,\r\n StationMeasurement\r\n} from \".\";\r\nimport { MeasureType } from \"../../types/measurements\";\r\n\r\n\r\nexport class MeasurementConstructor {\r\n private controller: MeasurementController;\r\n public measurement: MeasurementType;\r\n private measureType: MeasureType = null;\r\n public isFinished = false;\r\n private measureAssets = null;\r\n\r\n constructor(controller) {\r\n this.controller = controller;\r\n }\r\n\r\n get active() {\r\n return this.measurement && this.measurement.vertices.length > 0;\r\n }\r\n\r\n get assets() {\r\n return this.measureAssets;\r\n }\r\n\r\n setBuilder(type: MeasureType) {\r\n this.measureType = type;\r\n\r\n if (this.measureType === MeasureType.None) {\r\n this.measurement = null;\r\n } else {\r\n this.measurement = this.getEmptyMeasurement();\r\n this.measurement.setController(this.controller);\r\n }\r\n }\r\n\r\n getEmptyMeasurement() {\r\n const type = this.measureType;\r\n\r\n if (type === MeasureType.SnapUp) {\r\n return new SnapUpMeasurement();\r\n } else if (type === MeasureType.SnapDown) {\r\n return new SnapDownMeasurement();\r\n } else if (type === MeasureType.Height) {\r\n return new HeightMeasurement();\r\n } else if (type === MeasureType.Point) {\r\n return new MeasurementPoint();\r\n } else if (type === MeasureType.Area) {\r\n return new MeasurementArea();\r\n } else if (type === MeasureType.Volume) {\r\n return new MeasurementVolume();\r\n } else if (type === MeasureType.Station) {\r\n return new StationMeasurement();\r\n } else if (type === MeasureType.Length) {\r\n return new MeasurementLine();\r\n }\r\n }\r\n\r\n getMeasurement() {\r\n if (this.isFinished) {\r\n const measurement = this.measurement;\r\n this.measurement = this.getEmptyMeasurement();\r\n this.measurement.setController(this.controller);\r\n this.isFinished = false;\r\n\r\n return measurement;\r\n }\r\n\r\n return this.measurement;\r\n }\r\n\r\n reset() {\r\n this.isFinished = false;\r\n if (!this.measurement) return;\r\n\r\n this.measurement.vertices = [];\r\n this.measurement.clear();\r\n }\r\n\r\n add(vertex) {\r\n if (!this.isFinished) {\r\n let result = this.measurement.add(vertex);\r\n this.isFinished = result.finished;\r\n return result;\r\n }\r\n\r\n return {\r\n added: false,\r\n valid: false\r\n };\r\n }\r\n}\r\n","import { AmbientLight, Scene, Vector3 } from 'three';\r\nimport { CustomMouseEvent } from '../controls';\r\nimport { Viewer, ViewerProps } from '../main';\r\nimport LocalScene from '../projections';\r\nimport {\r\n AerialAreaMeasurement,\r\n AerialLengthMeasurement,\r\n Measurement3D,\r\n MeasurementArea,\r\n MeasurementPoint,\r\n MinimapMeasure,\r\n MeasurementConstructor,\r\n MeasurementFormatter,\r\n MeasurementGroup,\r\n MeasurementGroupExporter,\r\n MeasurementSceneView,\r\n MeasureEndpoint,\r\n MeasurementVolume,\r\n HeightMeasurement\r\n} from '.';\r\nimport { clearAerialTooltip, clearViewerTooltip } from '../viewer';\r\nimport { RayCaster } from '../ray-caster';\r\nimport { toast } from '../../app';\r\nimport { t } from '../../localization';\r\nimport { ChangeDetector } from '../utilities';\r\nimport { Asset, XMLData } from '../../redux/assets-slice';\r\nimport { MeasureType, VolumeType, SamplingRate, AerialMeasureType } from '../../types/measurements';\r\nimport { MapBrowserEvent } from 'ol';\r\nimport { Units } from '../../types/project';\r\n\r\nexport class MeasurementController {\r\n public viewer: Viewer;\r\n public enabled = false;\r\n public timeout = false;\r\n private measureAssets = [] as Asset[];\r\n public activeAlignment = '';\r\n\r\n private measureType = MeasureType.Length;\r\n public volumeType = VolumeType.MultiPlane;\r\n public sampleRate = SamplingRate.Medium;\r\n public aerialMeasureType = AerialMeasureType.Spherical;\r\n\r\n public formatter: MeasurementFormatter;\r\n public measurementSceneView: MeasurementSceneView;\r\n public measurementAerialView: MinimapMeasure;\r\n public measurementBuilder: MeasurementConstructor;\r\n public measurementGroupExporter: MeasurementGroupExporter;\r\n public measurementGroup: MeasurementGroup;\r\n\r\n public scene: Scene;\r\n\r\n public setMeasurements: React.Dispatch;\r\n\r\n constructor(viewer: Viewer, props: ViewerProps) {\r\n const {setMeasurements} = props;\r\n\r\n this.viewer = viewer;\r\n this.setMeasurements = setMeasurements;\r\n\r\n this.initScene();\r\n\r\n this.formatter = new MeasurementFormatter(Units.Meters);\r\n this.measurementSceneView = new MeasurementSceneView(this, this.scene);\r\n this.measurementAerialView = new MinimapMeasure(this);\r\n this.measurementBuilder = new MeasurementConstructor(this);\r\n this.measurementGroupExporter = new MeasurementGroupExporter(this);\r\n this.measurementGroup = new MeasurementGroup(this);\r\n }\r\n\r\n get pointclouds() {\r\n return this.viewer.pointclouds;\r\n }\r\n\r\n get controls() {\r\n return this.viewer.controls;\r\n }\r\n\r\n get isImageOnly() {\r\n return this.viewer.isImageOnly;\r\n }\r\n\r\n get measuring() {\r\n return this.measurementBuilder.active;\r\n }\r\n\r\n get activeMeasurement() {\r\n return this.measurementBuilder.measurement;\r\n }\r\n\r\n get notEmpty() {\r\n return this.measurementGroup.measurements.length > 0;\r\n }\r\n\r\n get dragObject() {\r\n return this.measurementSceneView.dragObject;\r\n }\r\n\r\n get editable() {\r\n // Always true since view-only mode doesnt exist\r\n return true;\r\n }\r\n\r\n get disabled() {\r\n return this.measureType === MeasureType.None;\r\n }\r\n\r\n get hoveredPoint() {\r\n return this.measurementSceneView.hoveredPoint;\r\n }\r\n\r\n get measurementAssets() {\r\n return this.measureAssets;\r\n }\r\n\r\n reconcileXMLs(xmlFiles) {\r\n const currentAssets = new Set(\r\n this.measurementAssets.map(asset => asset.id));\r\n const newAssets = new Set(xmlFiles.map(asset => asset.id));\r\n const assetsToLoad = xmlFiles.filter(xml => !currentAssets.has(xml.id));\r\n const assetToDelete = this.measurementAssets.filter(\r\n xml => !newAssets.has(xml.id));\r\n\r\n this.updateMeasureAssets(assetToDelete, xmlFiles);\r\n\r\n assetsToLoad.forEach(xmlFile => {\r\n this.loadMeasureAsset(xmlFile);\r\n });\r\n }\r\n\r\n setState(state) {\r\n if (state) {\r\n this.enable();\r\n } else {\r\n this.disable(true);\r\n }\r\n }\r\n\r\n enable() {\r\n this.enabled = true;\r\n this.createNewMeasurementGroup();\r\n this.measurementAerialView.enabled = true;\r\n this.measurementAerialView.init();\r\n }\r\n\r\n disable(clear=false) {\r\n if (clear) {\r\n this.measurementSceneView.removeAll();\r\n this.measurementAerialView.removeAll();\r\n }\r\n\r\n this.enabled = false;\r\n this.stopDrawingItems();\r\n this.measurementGroup.reset();\r\n this.measurementAerialView.enabled = false;\r\n this.measurementAerialView.removeInteraction();\r\n this.viewer.closeMultiImageWindow();\r\n\r\n clearAerialTooltip();\r\n clearViewerTooltip();\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n enableTimeout() {\r\n this.timeout = true;\r\n setTimeout(() => {\r\n this.timeout = false;\r\n }, 500);\r\n }\r\n\r\n loadMeasureAsset(asset) {\r\n this.measureAssets.push(asset);\r\n }\r\n\r\n updateMeasureAssets(toDelete=[], xmlFiles) {\r\n const removeIDs = new Set(toDelete.map(deletable => deletable.id));\r\n const currentAssets = [...this.measureAssets];\r\n this.measureAssets = [];\r\n currentAssets.forEach(asset => {\r\n if (!(removeIDs.has(asset.id))) {\r\n xmlFiles.forEach(xmlFile => {\r\n if (asset.id === xmlFile.id) {\r\n this.measureAssets.push(xmlFile);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n\r\n setActiveAlignment(id) {\r\n this.activeAlignment = id;\r\n }\r\n\r\n getAlignmentByID(id) {\r\n for (let asset of this.measureAssets) {\r\n const {alignments, enu, units} = asset.data as XMLData;\r\n const alignment = alignments.find(x => x.id === id);\r\n const alignUnits = (units as any).linearUnit as string;\r\n\r\n if (!alignment) continue;\r\n\r\n return {\r\n alignment,\r\n enu,\r\n units: alignUnits\r\n };\r\n };\r\n }\r\n\r\n loadMeasurementData(data) {\r\n try {\r\n const projection = data.projection;\r\n const sameProjection = LocalScene.isDataProjection(projection.name);\r\n\r\n if (!sameProjection) {\r\n toast.error(t(\"toast.measure-projection-mismatch\", {\r\n projection: projection.name\r\n }));\r\n\r\n return false;\r\n };\r\n\r\n // Clear data and create new group\r\n this.createNewMeasurementGroup();\r\n\r\n // Load measurements into new group\r\n let measurements = data.measurements;\r\n this.measurementGroup.loadMeasurements(measurements);\r\n this.refreshMeasurementList();\r\n\r\n toast.success(t(\"toast.measure-load-success\", {\r\n count: data.count\r\n }));\r\n } catch {\r\n this.createNewMeasurementGroup();\r\n toast.error(t(\"toast.measure-load-error\"));\r\n }\r\n }\r\n\r\n cancelMeasurement() {\r\n this.stopDrawingItems();\r\n this.viewer.closeMultiImageWindow();\r\n }\r\n\r\n returnCoordinate(obj) {\r\n return false;\r\n /*\r\n return isLineworkObject(obj)\r\n || isFeatureServerObject(obj)\r\n || obj instanceof TexturedSprite;\r\n */\r\n }\r\n\r\n getCoordinate(event) : Vector3 {\r\n return this.controls.getPickerResults(event).coordinate;\r\n }\r\n\r\n getAreaGeometry() {\r\n const temporaryMeasurement = this.activeMeasurement;\r\n return this.measurementGroup\r\n .getAreaGeometry(temporaryMeasurement);\r\n }\r\n\r\n /** @private */\r\n clickMultiImage(event) {\r\n if (!this.editable) return;\r\n\r\n const measurement = this.measurementBuilder.measurement;\r\n const multiImage = this.viewer.multiImageWindow;\r\n const isSinglePoint = measurement instanceof MeasurementPoint;\r\n\r\n // Calculate clicked position\r\n const raycaster = new RayCaster(this.viewer, event);\r\n const direction = raycaster.direction;\r\n const position = raycaster.position;\r\n\r\n const onClose = () => {\r\n if (measurement.hasPoints) {\r\n return {\r\n title: t('asset.discard-measurements'),\r\n text: t('asset.active-measurements-found'),\r\n callback: () => {\r\n this.cancelMeasurement();\r\n clearViewerTooltip();\r\n }\r\n };\r\n }\r\n };\r\n\r\n const onComplete = () => {\r\n const coordinate = multiImage.getClickedPoint();\r\n if (!coordinate) return;\r\n\r\n const isFinished = this.onClickFinish(coordinate);\r\n\r\n // Certain measurement types require a simulated double-click\r\n if (!isFinished) {\r\n this.onClickFinish(coordinate);\r\n }\r\n\r\n clearViewerTooltip();\r\n multiImage.close();\r\n };\r\n\r\n const onAddPoint = () => {\r\n const coordinate = multiImage.getClickedPoint();\r\n if (!coordinate) return;\r\n\r\n this.onClickFinish(coordinate);\r\n multiImage.canComplete = measurement.canFinish;\r\n multiImage.resetObservations();\r\n };\r\n\r\n multiImage.show({\r\n onClose,\r\n onComplete,\r\n onAddPoint,\r\n canComplete: measurement.canFinish,\r\n canAddMore: !isSinglePoint,\r\n });\r\n\r\n multiImage.addFirstObservation(position, direction);\r\n }\r\n\r\n /** @private */\r\n clickStandard(event) {\r\n let coordinate = this.hoveredPoint\r\n ? this.hoveredPoint.position\r\n : this.getCoordinate(event);\r\n\r\n if (!coordinate) return;\r\n this.onClickFinish(coordinate);\r\n }\r\n\r\n /** @private */\r\n onClickFinish(coordinate) {\r\n let isFinished = false;\r\n let result = this.measurementBuilder.add(coordinate);\r\n\r\n if (!result.valid) {\r\n this.cancelMeasurement();\r\n return isFinished;\r\n }\r\n\r\n if (result.added) {\r\n this.measurementSceneView.addTemporaryPoint(coordinate);\r\n this.updateMeasureText();\r\n }\r\n\r\n if (this.measurementBuilder.isFinished) {\r\n isFinished = true;\r\n this.addSceneMeasurement();\r\n };\r\n\r\n return isFinished;\r\n }\r\n\r\n onMouseUpAerial(event: CustomMouseEvent) {\r\n if (!this.enabled || this.disabled) return false;\r\n\r\n if (event.isRightClick) {\r\n return this.measurementAerialView.cancelMeasurement();\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMouseUpScene(event: CustomMouseEvent): boolean {\r\n if (event.mouseMoved || !this.enabled || this.disabled) {\r\n return false;\r\n }\r\n\r\n if (event.isLeftClick) {\r\n this.mouseClick(event);\r\n return true;\r\n }\r\n\r\n if (event.isRightClick) {\r\n if (this.measuring) {\r\n // Cancel measurement\r\n this.cancelMeasurement();\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n mouseClick(event) {\r\n if (!this.editable || this.timeout) return;\r\n\r\n if (this.isImageOnly) {\r\n // Image only multi-image measurements\r\n this.clickMultiImage(event);\r\n } else {\r\n this.clickStandard(event);\r\n }\r\n }\r\n\r\n onMouseMoveAerial(event: MapBrowserEvent) {\r\n if (!this.enabled || this.disabled) return false;\r\n return this.measurementAerialView.onMouseMove(event);\r\n }\r\n\r\n onMouseMoveScene(event: CustomMouseEvent) {\r\n if (!this.enabled) return false;\r\n return this.measurementSceneView.onMouseMove(event);\r\n }\r\n\r\n onMouseDrag(event: CustomMouseEvent) {\r\n if (!this.enabled) return false;\r\n return this.measurementSceneView.onMouseDrag(event);\r\n }\r\n\r\n resetDragObject() {\r\n this.measurementSceneView.setDragObject(null);\r\n }\r\n\r\n addSceneMeasurement() {\r\n this.updateMeasureText();\r\n\r\n let measurement = this.measurementBuilder.getMeasurement();\r\n\r\n if (measurement instanceof MeasurementArea) {\r\n measurement.generateSurface();\r\n }\r\n\r\n if (measurement instanceof HeightMeasurement) {\r\n this.enableTimeout();\r\n }\r\n\r\n this.measurementSceneView.removeTemporaryObjects();\r\n this.measurementGroup.add(measurement);\r\n this.renderMeasurement(measurement);\r\n this.markLastPointDraggable(measurement);\r\n\r\n if (measurement instanceof MeasurementVolume) {\r\n measurement.calculateVolume();\r\n }\r\n }\r\n\r\n addAerialMeasurement(geometry, type: MeasureType) {\r\n let measurement;\r\n\r\n if (type === MeasureType.Area) {\r\n measurement = new AerialAreaMeasurement(geometry);\r\n } else {\r\n measurement = new AerialLengthMeasurement(geometry);\r\n }\r\n\r\n measurement.setController(this);\r\n this.measurementGroup.add(measurement);\r\n this.renderMeasurement(measurement);\r\n }\r\n\r\n markLastPointDraggable(measurement) {\r\n let sceneEndpoints = this.scene.children\r\n .filter(x => x instanceof MeasureEndpoint) as MeasureEndpoint[];\r\n\r\n let measureEndpoints = sceneEndpoints\r\n .filter(x => x.measurementID === measurement.id);\r\n\r\n let lastPoint = measureEndpoints[measureEndpoints.length - 1];\r\n this.measurementSceneView.setDragObject(lastPoint);\r\n }\r\n\r\n stopDrawingItems() {\r\n this.measurementBuilder.reset();\r\n this.measurementSceneView.removeTemporaryObjects();\r\n this.measurementAerialView.reloadInteraction();\r\n this.updateMeasureText(false);\r\n }\r\n\r\n measureGrabFinished() {\r\n this.measurementSceneView.measureGrabFinished();\r\n }\r\n\r\n refreshMeasurementList() {\r\n this.setMeasurements([...this.measurementGroup.measurements]);\r\n }\r\n\r\n updateMeasureText(checkMorePoints = true) {\r\n if (!this.enabled) return false;\r\n\r\n let morepoints = false;\r\n let measurement = this.measurementBuilder.measurement;\r\n\r\n if (measurement && checkMorePoints) {\r\n morepoints = !this.measurementBuilder.isFinished;\r\n if (measurement.vertices.length === 0) {\r\n morepoints = false;\r\n }\r\n }\r\n\r\n this.measurementSceneView.setTooltipText(measurement, morepoints);\r\n }\r\n\r\n createNewMeasurementGroup() {\r\n this.measurementAerialView.removeAll();\r\n this.measurementSceneView.removeAll();\r\n this.measurementGroup = new MeasurementGroup(this);\r\n this.setMeasurementType(this.measureType);\r\n }\r\n\r\n setMeasurementType(measurementType: MeasureType) {\r\n if (!this.enabled) return;\r\n\r\n this.measureType = measurementType;\r\n this.measurementBuilder.setBuilder(measurementType);\r\n this.measurementSceneView.removeTemporaryObjects();\r\n this.viewer.closeMultiImageWindow();\r\n\r\n let measurement = this.measurementBuilder.measurement;\r\n this.measurementSceneView.setTooltipText(measurement);\r\n\r\n this.stopDrawingItems();\r\n this.measurementAerialView.setMeasurementType(measurementType);\r\n }\r\n\r\n removeByID(id) {\r\n this.measurementSceneView.removeByID(id);\r\n this.measurementGroup.removeByID(id);\r\n this.measurementAerialView.removeByID(id);\r\n\r\n clearViewerTooltip();\r\n }\r\n\r\n setTitle(id, title) {\r\n const measurement = this.measurementGroup.getByID(id);\r\n\r\n if (measurement) {\r\n measurement.setTitle(title);\r\n this.refreshMeasurementList();\r\n }\r\n\r\n clearViewerTooltip();\r\n }\r\n\r\n removeAll() {\r\n this.measurementGroup.removeAll();\r\n this.clearViews();\r\n }\r\n\r\n clearViews() {\r\n this.measurementSceneView.removeAll();\r\n this.measurementAerialView.removeAll();\r\n }\r\n\r\n export(type, ordering) {\r\n if (type === \"csv\") {\r\n this.exportCSV(ordering);\r\n } else if (type === \"dat\") {\r\n this.exportDAT();\r\n } else if (type === \"dxf\" || type === \"shp\") {\r\n this.exportLinework(type);\r\n }\r\n }\r\n\r\n exportDAT() {\r\n this.measurementGroupExporter\r\n .exportDAT(this.measurementGroup);\r\n }\r\n\r\n exportCSV(ordering) {\r\n this.measurementGroupExporter.exportCSV(\r\n this.measurementGroup, ordering);\r\n }\r\n\r\n exportLinework(type) {\r\n this.measurementGroupExporter\r\n .exportLinework(this.measurementGroup, type);\r\n }\r\n\r\n setUnits(units: Units) {\r\n this.formatter.setUnits(units);\r\n\r\n if (this.measurementGroup) {\r\n this.reload();\r\n }\r\n }\r\n\r\n setAerialMeasureType(type: AerialMeasureType) {\r\n this.aerialMeasureType = type;\r\n\r\n if (this.measurementGroup) {\r\n this.reload();\r\n }\r\n }\r\n\r\n setVolumeType(type: VolumeType) {\r\n this.volumeType = type;\r\n this.refreshVolume();\r\n }\r\n\r\n setSampleRate(rate: SamplingRate) {\r\n this.sampleRate = rate;\r\n this.refreshVolume();\r\n }\r\n\r\n reload() {\r\n this.clearViews();\r\n this.measurementGroup.measurements.forEach(measurement => {\r\n this.renderMeasurement(measurement);\r\n });\r\n this.refreshMeasurementList();\r\n }\r\n\r\n refreshVolume() {\r\n // All volumes will need to be recalculated\r\n this.measurementGroup.measurements.forEach(measurement => {\r\n if (measurement instanceof MeasurementVolume) {\r\n measurement.stopVolumeCalculation();\r\n measurement.calculateVolume();\r\n }\r\n });\r\n }\r\n\r\n setHover(measurement, hover = false) {\r\n if (measurement instanceof Measurement3D) {\r\n this.measurementSceneView.setHover(measurement.id, hover);\r\n } else {\r\n this.measurementAerialView.setHover(measurement.id, hover);\r\n }\r\n }\r\n\r\n renderMeasurement(measurement) {\r\n if (measurement instanceof Measurement3D) {\r\n this.measurementSceneView.render(measurement);\r\n } else {\r\n this.measurementAerialView.render(measurement);\r\n }\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n this.measurementSceneView.update(changeDetector);\r\n }\r\n}\r\n","import { t } from \"../../localization\";\r\nimport { MeasureType } from \"../../types/measurements\";\r\nimport { Units } from \"../../types/project\";\r\nimport { isLonLatProjection } from \"../projections\";\r\nimport { MeasurementVolume, StationMeasurement } from \"./measurement\";\r\n\r\nexport class MeasurementFormatter {\r\n public units: Units;\r\n public emptyValue = \"\";\r\n private metersCutoff = 500;\r\n private squareMetersCutoff = 250000;\r\n private precision = 2; // 0.01m\r\n private vectorPrecisionLonLat = 6; // ~0.01m\r\n private vectorPrecisionStandard = 2; // 0.01m\r\n\r\n constructor(units: Units) {\r\n const allowedUnits = Object.values(Units);\r\n\r\n if (!allowedUnits.includes(units)) {\r\n throw TypeError(`Units must be ${allowedUnits}`);\r\n }\r\n\r\n this.setUnits(units);\r\n }\r\n\r\n get nullValue() {\r\n return t(\"general.not-applicable\");\r\n }\r\n\r\n get isMetric() {\r\n return this.units === Units.Meters;\r\n }\r\n\r\n get isImperial() {\r\n return (this.units === Units.Feet) || (this.units === Units.SurveyFeet);\r\n }\r\n\r\n get isSurveyFeet() {\r\n return this.units === Units.SurveyFeet;\r\n }\r\n\r\n get areaUnits() {\r\n return `${this.isMetric ? \"m\" : \"ft\"}^2`;\r\n }\r\n\r\n get volumeUnits() {\r\n return `${this.isMetric ? \"m\" : \"yd\"}^3`;\r\n }\r\n\r\n setUnits(units: Units) {\r\n this.units = units;\r\n }\r\n\r\n formatLength(value: number) {\r\n let units;\r\n let finalValue = value;\r\n\r\n if ((this.units === Units.Feet) || (this.units === Units.SurveyFeet)) {\r\n if (value > this.metersCutoff) {\r\n units = \"mi\";\r\n finalValue = MeasurementFormatter.metresToMiles(finalValue, this.isSurveyFeet);\r\n } else {\r\n // Round the meters units first for feet + inches\r\n finalValue = this.roundFloat(finalValue);\r\n finalValue = MeasurementFormatter.metresToFeet(finalValue, this.isSurveyFeet);\r\n let feet = Math.floor(finalValue);\r\n let inches = Math.round((finalValue - feet) * 12.0);\r\n return `${feet} ft ${inches} in `;\r\n }\r\n } else {\r\n if (value > this.metersCutoff) {\r\n units = \"km\";\r\n finalValue = MeasurementFormatter.metresToKiloMetres(finalValue);\r\n } else {\r\n units = \"m\";\r\n }\r\n }\r\n\r\n finalValue = this.roundFloat(finalValue);\r\n\r\n return `${finalValue} ${units}`;\r\n }\r\n\r\n formatVolume(measurement: MeasurementVolume) {\r\n let units;\r\n let value = measurement.volume;\r\n\r\n if ((this.units === Units.Feet) || (this.units === Units.SurveyFeet)) {\r\n units = \"yd3\";\r\n value = MeasurementFormatter.cubicMetresToCubicYards(value);\r\n } else {\r\n units = \"m3\";\r\n }\r\n\r\n value = this.roundFloat(value);\r\n\r\n return `${value} ${units}`;\r\n }\r\n\r\n formatArea(value: number) {\r\n let units;\r\n let finalValue = value;\r\n\r\n if ((this.units === Units.Feet) || (this.units === Units.SurveyFeet)) {\r\n if (value > this.squareMetersCutoff) {\r\n units = \"mi2\";\r\n finalValue = MeasurementFormatter.squareMetresToSquareMiles(\r\n finalValue, this.isSurveyFeet);\r\n } else {\r\n units = \"ft2\";\r\n finalValue = MeasurementFormatter.squareMetresToSquareFeet(\r\n finalValue, this.isSurveyFeet);\r\n }\r\n } else {\r\n if (value > this.squareMetersCutoff) {\r\n units = \"km2\";\r\n finalValue = MeasurementFormatter.squareMetresToSquareKilometres(\r\n finalValue);\r\n } else {\r\n units = \"m2\";\r\n }\r\n }\r\n\r\n finalValue = this.roundFloat(finalValue);\r\n\r\n return `${finalValue} ${units}`;\r\n }\r\n\r\n formatAngle(value: number, format = true) {\r\n if (!isNaN(value)) {\r\n value = this.roundFloat(value);\r\n return format ? `${value}°` : value;\r\n }\r\n\r\n return this.nullValue;\r\n }\r\n\r\n formatGrade(value: number, format = true) {\r\n let maxGrade = 1000000;\r\n if (isFinite(value) && (value < maxGrade)) {\r\n value = this.roundFloat(value);\r\n return format ? `${value}%` : value;\r\n }\r\n\r\n return this.nullValue;\r\n }\r\n\r\n formatStation(measurement: StationMeasurement, format=true) {\r\n const along = measurement.distanceAlong;\r\n const start = measurement.staStart;\r\n const lengthUnits = measurement.units;\r\n\r\n let alongFinal = along;\r\n let stationFinal = start;\r\n\r\n if (this.isImperial) {\r\n if (lengthUnits === Units.Meters) {\r\n alongFinal = MeasurementFormatter.metresToFeet(alongFinal, this.isSurveyFeet);\r\n stationFinal = MeasurementFormatter.metresToFeet(stationFinal, this.isSurveyFeet);\r\n }\r\n\r\n } else {\r\n if (lengthUnits === Units.SurveyFeet) {\r\n stationFinal = MeasurementFormatter.feetToMetres(stationFinal, true);\r\n alongFinal = MeasurementFormatter.feetToMetres(alongFinal, true);\r\n } else if (lengthUnits === Units.Feet){\r\n stationFinal = MeasurementFormatter.feetToMetres(stationFinal, false);\r\n alongFinal = MeasurementFormatter.feetToMetres(alongFinal, false);\r\n }\r\n }\r\n\r\n const stationTotal = stationFinal + alongFinal;\r\n\r\n let stationNumber: number;\r\n let stationAlong: number;\r\n\r\n if (this.isImperial) {\r\n stationNumber = parseInt(String(stationTotal).slice(0,4));\r\n stationAlong = parseFloat(String(stationTotal).slice(4));\r\n } else {\r\n stationNumber = parseInt(String(stationTotal).slice(0,3));\r\n stationAlong = parseFloat(String(stationTotal).slice(3));\r\n }\r\n\r\n stationAlong = this.roundFloat(stationAlong);\r\n\r\n return format\r\n ? `${stationNumber} + ${stationAlong} ${this.units}`\r\n : `${stationNumber} + ${stationAlong}`;\r\n }\r\n\r\n formatOffset(measurement: StationMeasurement, format=true) {\r\n const across = measurement.distanceAcross;\r\n const side = measurement.sideOfSegment;\r\n let finalValue = (side === \"R\") ? across : -across;\r\n const lengthUnits = measurement.units;\r\n\r\n if (this.isImperial) {\r\n if (lengthUnits === Units.Meters) {\r\n finalValue = MeasurementFormatter.metresToFeet(finalValue, this.isSurveyFeet);\r\n }\r\n } else {\r\n if (lengthUnits === Units.SurveyFeet) {\r\n finalValue = MeasurementFormatter.feetToMetres(finalValue, true);\r\n } else if (lengthUnits === Units.Feet){\r\n finalValue = MeasurementFormatter.feetToMetres(finalValue, false);\r\n }\r\n }\r\n\r\n finalValue = this.roundFloat(finalValue);\r\n\r\n return format\r\n ? `${finalValue} ${this.units}`\r\n : `${finalValue}`;\r\n }\r\n\r\n convertUnits(value: number, type: MeasureType) {\r\n if ((this.units === Units.Feet) || (this.units === Units.SurveyFeet)) {\r\n if (type === MeasureType.Area) {\r\n value = MeasurementFormatter.squareMetresToSquareFeet(\r\n value, this.isSurveyFeet);\r\n } else if (type === MeasureType.Volume) {\r\n value = MeasurementFormatter.cubicMetresToCubicYards(value);\r\n } else {\r\n value = MeasurementFormatter.metresToFeet(value, this.isSurveyFeet);\r\n }\r\n }\r\n\r\n value = this.roundFloat(value);\r\n\r\n return value;\r\n }\r\n\r\n getVectorPrecision(projection = null) {\r\n let precisionX = this.vectorPrecisionStandard;\r\n let precisionY = this.vectorPrecisionStandard;\r\n let precisionZ = this.vectorPrecisionStandard;\r\n\r\n if (projection && isLonLatProjection(projection)) {\r\n precisionX = this.vectorPrecisionLonLat;\r\n precisionY = this.vectorPrecisionLonLat;\r\n }\r\n\r\n return {\r\n x: precisionX,\r\n y: precisionY,\r\n z: precisionZ\r\n };\r\n }\r\n\r\n roundFloat(value: number) {\r\n return parseFloat(value.toFixed(this.precision));\r\n }\r\n\r\n static metresToYards(value) {\r\n /** International units and US units are the same for yards */\r\n return value * (1 / 0.9144);\r\n }\r\n\r\n static metresToFeet(value, isSurveryFeet=false) {\r\n if (isSurveryFeet) {\r\n return value * (3937.0 / 1200.0);\r\n }\r\n\r\n return value * (1 / 0.3048);\r\n }\r\n\r\n static feetToMetres(value, isSurveryFeet=false) {\r\n if (isSurveryFeet) {\r\n return value * (1200.0 / 3937.0);\r\n }\r\n\r\n return value * (0.3048);\r\n }\r\n\r\n static metresToMiles(value, isSurveryFeet=false) {\r\n return value * this.metresToFeet(1.0, isSurveryFeet) / 5280;\r\n }\r\n\r\n static metresToKiloMetres(metres) {\r\n return metres * 0.001;\r\n }\r\n\r\n static squareMetresToSquareKilometres(squareMetres) {\r\n return squareMetres * 0.000001;\r\n }\r\n\r\n static squareMetresToSquareFeet(squareMetres, isSurveryFeet=false) {\r\n let val = Math.pow(this.metresToFeet(1.0, isSurveryFeet), 2);\r\n return squareMetres * val;\r\n }\r\n\r\n static squareMetresToSquareMiles(squareMetres, isSurveryFeet=false) {\r\n let val = Math.pow(this.metresToMiles(1.0, isSurveryFeet), 2);\r\n return squareMetres * val;\r\n }\r\n\r\n static cubicMetresToCubicYards(cubicMetres) {\r\n let val = Math.pow(this.metresToYards(1.0), 3);\r\n return cubicMetres * val;\r\n }\r\n}\r\n\r\n\r\n","import LocalScene, {\r\n GeocentricCoordinate,\r\n ProjectedCoordinate,\r\n} from '../projections';\r\nimport {\r\n AerialAreaMeasurement,\r\n AerialMeasurement,\r\n Measurement3D,\r\n MeasurementArea,\r\n MeasurementPoint,\r\n MeasurementVolume,\r\n MeasurementController, StationMeasurement, MeasurementGroup\r\n} from '.';\r\nimport { Vector3 } from 'three';\r\nimport { windowSafeDateISO } from '../utilities';\r\nimport {\r\n DXFModelFilter,\r\n measureCSVFilter,\r\n measureDataFilter,\r\n measureDataFormat,\r\n ZIPFileFilter\r\n} from '../../file-extensions';\r\nimport { t } from '../../localization';\r\nimport { downloadFile } from '../../utilities';\r\nimport {dialog, fs, getTemporaryFile} from \"../../electron-modules\";\r\nimport {toast} from \"../../app\";\r\nimport {PythonExecutable} from \"../../executable\";\r\nimport path from \"path\";\r\nimport slash from \"slash\";\r\nimport * as CSV from 'csv-string';\r\n\r\nexport class MeasurementGroupExporter {\r\n private controller: MeasurementController;\r\n\r\n constructor(controller) {\r\n this.controller = controller;\r\n }\r\n\r\n get viewer() {\r\n return this.controller.viewer;\r\n }\r\n\r\n get formatter() {\r\n return this.controller.formatter;\r\n }\r\n\r\n\r\n exportCSV(measurementGroup, ordering) {\r\n this.handleExport3D(measurementGroup, ordering);\r\n this.handleExport2D(measurementGroup, ordering);\r\n }\r\n\r\n exportDAT(measurementGroup) {\r\n const name = `${this.viewer.projectName}.${measureDataFormat}`;\r\n const data = this.getDataExport(measurementGroup);\r\n const content = JSON.stringify(data, null, 2);\r\n downloadFile(name, content, \"plain\", measureDataFilter);\r\n }\r\n\r\n handleExport2D(measurementGroup: MeasurementGroup, ordering) {\r\n const name = t('measure.name-measurements-2d', {\r\n name: this.viewer.projectName,\r\n date: windowSafeDateISO()\r\n });\r\n\r\n const rows = this.getExportRows2D(measurementGroup, ordering);\r\n if (rows.length === 0) return;\r\n\r\n const content = CSV.stringify(rows);\r\n downloadFile(name, content, \"csv\", measureCSVFilter);\r\n }\r\n\r\n handleExport3D(measurementGroup: MeasurementGroup, ordering) {\r\n const name = t('measure.name-measurements-3d', {\r\n name: this.viewer.projectName,\r\n date: windowSafeDateISO()\r\n });\r\n\r\n const rows = this.getExportRows3D(measurementGroup, ordering);\r\n if (rows.length === 0) return;\r\n\r\n const content = CSV.stringify(rows);\r\n downloadFile(name, content, \"csv\", measureCSVFilter);\r\n }\r\n\r\n /** @private */\r\n getDataExport(measurementGroup: MeasurementGroup, viewProjection=false) {\r\n let data = {\r\n count: 0,\r\n name: measurementGroup.name,\r\n projection: LocalScene.dataProjection,\r\n measurements: {\r\n measurements2D: [],\r\n measurements3D: []\r\n }\r\n };\r\n\r\n let measurements = measurementGroup.measurements;\r\n measurements.forEach(measurement => {\r\n let measurement_coordinates;\r\n if (viewProjection) {\r\n measurement_coordinates = measurement.vertices.map(vertex => {\r\n let vertextView = vertex.toViewProjection();\r\n let coordinates = [vertextView.x, vertextView.y];\r\n if (typeof vertextView.z !== 'undefined') {\r\n coordinates.push(vertextView.z);\r\n }\r\n return coordinates;\r\n });\r\n } else {\r\n measurement_coordinates = measurement.coordinates;\r\n }\r\n\r\n const created = measurement.timeCreated\r\n .toISOString()\r\n .split('.')[0];\r\n\r\n const info = {\r\n id: null,\r\n coordinates: measurement_coordinates,\r\n time_created: created,\r\n title: measurement.title,\r\n type: measurement.type,\r\n volume: null,\r\n station: null,\r\n along: null,\r\n across: null,\r\n units: null\r\n };\r\n\r\n if (measurement instanceof AerialMeasurement) {\r\n data.measurements.measurements2D.push(info);\r\n } else {\r\n if (measurement instanceof MeasurementVolume) {\r\n info.volume = measurement.volumeHelper.value;\r\n }\r\n if (measurement instanceof StationMeasurement) {\r\n info.station = measurement.stationStart;\r\n info.across = measurement.distanceAcross;\r\n info.along = measurement.distanceAlong;\r\n info.units = measurement.units;\r\n }\r\n\r\n data.measurements.measurements3D.push(info);\r\n }\r\n\r\n data.count += 1;\r\n });\r\n\r\n return data;\r\n }\r\n\r\n /** @private */\r\n getExportRows2D(measurementGroup, ordering) {\r\n let measureCsvOut = [];\r\n\r\n const precision = this.formatter\r\n .getVectorPrecision(LocalScene.viewProjection);\r\n\r\n let measurements = measurementGroup.measurements.filter(measurement =>\r\n measurement instanceof AerialMeasurement\r\n ) as AerialMeasurement[];\r\n\r\n if (measurements.length === 0) {\r\n return measureCsvOut;\r\n }\r\n\r\n let mapProjection = this.viewer.minimap.mapSystem;\r\n\r\n let header = this.getHeaderValues2D(measurements, ordering);\r\n let nullValue = this.formatter.nullValue;\r\n measureCsvOut.push(header);\r\n\r\n // Load measurements in reverse order\r\n measurements.reverse();\r\n measurements.forEach(measurement => {\r\n let row;\r\n let value;\r\n\r\n if (measurement instanceof AerialAreaMeasurement) {\r\n let value;\r\n\r\n let {area, valid} = measurement.area;\r\n\r\n if (valid) {\r\n value = this.formatter.convertUnits(\r\n area, measurement.type);\r\n } else {\r\n value = t('measure.invalid-area');\r\n }\r\n\r\n row = [measurement.title, t('measure.area'), nullValue, value];\r\n } else {\r\n value = this.formatter.convertUnits(\r\n measurement.distance2D, measurement.type);\r\n row = [measurement.title, t('measure.length'), value, nullValue];\r\n }\r\n\r\n let coordinates = measurement.geometry.flatCoordinates;\r\n if (measurement instanceof AerialAreaMeasurement) {\r\n coordinates = coordinates.slice(0, coordinates.length - 2);\r\n }\r\n\r\n let vertices = [];\r\n let numPoints = coordinates.length / 2.0;\r\n\r\n for (var i = 0; i < numPoints; i++) {\r\n let x = coordinates[2 * i];\r\n let y = coordinates[(2 * i) + 1];\r\n\r\n let coord = new Vector3(x, y, 0.0);\r\n let ecef = new ProjectedCoordinate(coord, mapProjection).toGeocentric();\r\n let proj = new GeocentricCoordinate(ecef).toViewProjection();\r\n vertices.push(proj);\r\n }\r\n\r\n vertices.forEach(vertex => {\r\n // Export with x and y values swapped\r\n if (ordering === \"yxz\") {\r\n vertex = new Vector3(vertex.y, vertex.x, vertex.z);\r\n }\r\n\r\n row = row.concat([\r\n vertex.x.toFixed(precision.x),\r\n vertex.y.toFixed(precision.y),\r\n ]);\r\n });\r\n\r\n measureCsvOut.push(row);\r\n });\r\n\r\n return measureCsvOut;\r\n }\r\n\r\n /** @private */\r\n getExportRows3D(measurementGroup, ordering) {\r\n let measureCsvOut = [];\r\n\r\n const precision = this.formatter\r\n .getVectorPrecision(LocalScene.viewProjection);\r\n\r\n let measurements = measurementGroup.measurements.filter(measurement =>\r\n measurement instanceof Measurement3D\r\n ) as Measurement3D[];\r\n\r\n if (measurements.length === 0) {\r\n return measureCsvOut;\r\n }\r\n\r\n let header = this.getHeaderValues3D(measurements, ordering);\r\n let nullValue = this.formatter.nullValue;\r\n measureCsvOut.push(header);\r\n\r\n // Load measurements in reverse order\r\n measurements.reverse();\r\n measurements.forEach(measurement => {\r\n let row;\r\n\r\n if (measurement instanceof MeasurementPoint) {\r\n // Most data will be blank for a single point\r\n row = [\r\n measurement.title,\r\n nullValue,\r\n nullValue,\r\n nullValue,\r\n nullValue,\r\n nullValue,\r\n nullValue,\r\n nullValue,\r\n nullValue\r\n ];\r\n } else if (measurement instanceof StationMeasurement){\r\n row = [\r\n measurement.title,\r\n this.formatter.convertUnits(\r\n measurement.distance2D, measurement.type),\r\n this.formatter.convertUnits(\r\n measurement.distance3D, measurement.type),\r\n nullValue,\r\n nullValue,\r\n this.formatter.formatGrade(measurement.grade, false),\r\n this.formatter.formatAngle(measurement.angle, false),\r\n this.formatter.formatStation(measurement, false),\r\n this.formatter.formatOffset(measurement, false)\r\n ];\r\n } else if (measurement instanceof MeasurementArea) {\r\n let areaValue;\r\n let volumeValue: any = nullValue;\r\n\r\n const {area, valid} = measurement.area;\r\n\r\n if (valid) {\r\n areaValue = this.formatter.convertUnits(\r\n area, measurement.type);\r\n } else {\r\n areaValue = t('measure.invalid-area');\r\n }\r\n\r\n if (measurement instanceof MeasurementVolume) {\r\n volumeValue = measurement.invalidVolumeMessage;\r\n if (measurement.valid && measurement.calculated) {\r\n volumeValue = this.formatter.convertUnits(\r\n measurement.volume, measurement.type);\r\n }\r\n }\r\n\r\n row = [\r\n measurement.title,\r\n nullValue,\r\n nullValue,\r\n areaValue,\r\n volumeValue,\r\n nullValue,\r\n nullValue,\r\n nullValue,\r\n nullValue\r\n ];\r\n } else {\r\n row = [\r\n measurement.title,\r\n this.formatter.convertUnits(\r\n measurement.distance2D, measurement.type),\r\n this.formatter.convertUnits(\r\n measurement.distance3D, measurement.type),\r\n nullValue,\r\n nullValue,\r\n this.formatter.formatGrade(measurement.grade, false),\r\n this.formatter.formatAngle(measurement.angle, false),\r\n nullValue,\r\n nullValue\r\n ];\r\n }\r\n\r\n let verticesReprojected = measurement.vertices.map(vertex => {\r\n return vertex.toViewProjection();\r\n });\r\n\r\n verticesReprojected.forEach(vertex => {\r\n const values = (ordering === \"yxz\")\r\n ? new Vector3(vertex.y, vertex.x, vertex.z)\r\n : new Vector3().copy(vertex);\r\n\r\n row = row.concat([\r\n values.x.toFixed(precision.x),\r\n values.y.toFixed(precision.y),\r\n values.z.toFixed(precision.z)\r\n ]);\r\n });\r\n\r\n measureCsvOut.push(row);\r\n });\r\n\r\n return measureCsvOut;\r\n }\r\n\r\n getHeaderValues2D(measurements, ordering) {\r\n let header = [\r\n t('measure.notes'),\r\n t('measure.measure-type'),\r\n t('measure.length-formatter-units', {\r\n units: this.formatter.units\r\n }),\r\n t('measure.area-formatter-units-2', {\r\n units: this.formatter.units\r\n })\r\n ];\r\n\r\n let numVertices = 0;\r\n measurements.forEach(measurement => {\r\n let coordinates = measurement.geometry.flatCoordinates;\r\n if (measurement instanceof AerialAreaMeasurement) {\r\n coordinates = coordinates.slice(0, coordinates.length - 2);\r\n }\r\n\r\n let numPoints = coordinates.length / 2.0;\r\n numVertices = Math.max(numVertices, numPoints);\r\n });\r\n\r\n for (var i = 0; i < numVertices; i++) {\r\n if (ordering === \"yxz\") {\r\n header = header.concat([`Y_${i + 1}`, `X_${i + 1}`]);\r\n } else {\r\n header = header.concat([`X_${i + 1}`, `Y_${i + 1}`]);\r\n }\r\n }\r\n\r\n return header;\r\n }\r\n\r\n getHeaderValues3D(measurements, ordering) {\r\n let header = [\r\n t('measure.notes'),\r\n t('measure.distance-2d-formatter-units', {\r\n units: this.formatter.units\r\n }),\r\n t('measure.distance-3d-formatter-units', {\r\n units: this.formatter.units\r\n }),\r\n t('measure.area-3d-formatter-areaunits', {\r\n units: this.formatter.areaUnits\r\n }),\r\n t('measure.volume-3d-formatter-volumeunits', {\r\n units: this.formatter.volumeUnits\r\n }),\r\n t('measure.grade'),\r\n t('measure.angle-deg'),\r\n t('measure.station-info'),\r\n t('measure.station-offset')\r\n ];\r\n\r\n // Determine the max number of vertices\r\n let numVertices = 0;\r\n measurements.forEach(measurement => {\r\n let measurementVertices = measurement.vertices.length;\r\n numVertices = Math.max(numVertices, measurementVertices);\r\n });\r\n\r\n for (var i = 0; i < numVertices; i++) {\r\n if (ordering === \"yxz\") {\r\n header = header.concat([`Y_${i + 1}`, `X_${i + 1}`, `Z_${i + 1}`]);\r\n } else {\r\n header = header.concat([`X_${i + 1}`, `Y_${i + 1}`, `Z_${i + 1}`]);\r\n }\r\n }\r\n\r\n return header;\r\n }\r\n\r\n exportLinework = (measurementGroup, type) => {\r\n const isDXF = type === \"dxf\";\r\n dialog.showSaveDialog({\r\n defaultPath: this.viewer.projectName,\r\n filters: [\r\n ...(isDXF ? DXFModelFilter : []),\r\n ...(!isDXF ? ZIPFileFilter : [])\r\n ],\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n if (result.filePath) {\r\n const filePath = slash(result.filePath);\r\n const extension = path.extname(filePath);\r\n\r\n const data = this.getDataExport(measurementGroup, true);\r\n const content = JSON.stringify(data, null, 2);\r\n\r\n let temp3DMPath = getTemporaryFile(\"3dm\");\r\n try {\r\n fs.writeFileSync(temp3DMPath, content);\r\n } catch (err) {\r\n console.log(err);\r\n toast.error(t(\"toast.measurement-export-failed\"));\r\n return;\r\n }\r\n\r\n let pythonName = 'linework_from_3dm';\r\n\r\n if (!pythonName) {\r\n return;\r\n }\r\n\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--3dm_path\", temp3DMPath,\r\n `--output_path`, filePath\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onClose: () => {\r\n toast.success(t(\"toast.measurement-export-success\", {\r\n type: extension,\r\n path: path.basename(filePath)\r\n }));\r\n }\r\n });\r\n\r\n }\r\n });\r\n }\r\n}\r\n","import {GeocentricCoordinate} from '../projections';\r\nimport {\r\n AerialAreaMeasurement,\r\n AerialLengthMeasurement,\r\n AerialMeasurement,\r\n HeightMeasurement,\r\n Measurement,\r\n Measurement3D,\r\n MeasurementArea,\r\n MeasurementController,\r\n MeasurementLine,\r\n MeasurementPoint,\r\n MeasurementVolume,\r\n StationMeasurement\r\n} from '.';\r\nimport {Vector3} from \"three\";\r\nimport { MeasureType } from '../../types/measurements';\r\n\r\nexport class MeasurementGroup {\r\n public name;\r\n public controller: MeasurementController;\r\n public measurements = [];\r\n\r\n get viewer() {\r\n return this.controller.viewer;\r\n }\r\n\r\n constructor(controller) {\r\n this.controller = controller;\r\n }\r\n\r\n add(measurement) {\r\n this.measurements.push(measurement);\r\n this.updateMeasurements();\r\n }\r\n\r\n getByID(id) {\r\n return this.measurements.find(measurement => measurement.id === id);\r\n }\r\n\r\n removeByID(id) {\r\n this.removeFromArray(id);\r\n this.updateMeasurements();\r\n }\r\n\r\n removeFromArray(id) {\r\n this.measurements = this.measurements.filter(measurement => measurement.id !== id);\r\n }\r\n\r\n reset() {\r\n this.removeAll();\r\n }\r\n\r\n removeAll() {\r\n this.measurements.forEach(measurement => {\r\n measurement.clear();\r\n });\r\n this.measurements = [];\r\n this.updateMeasurements();\r\n }\r\n\r\n updateMeasurements() {\r\n this.controller.refreshMeasurementList();\r\n }\r\n\r\n loadMeasurements(result) {\r\n // Add 3d measurements\r\n let measure3D = result.measurements3D.map(measurement => {\r\n let newMeasurement = this.getEmptyMeasurement(measurement.type);\r\n newMeasurement.setController(this.controller);\r\n newMeasurement.setTitle(measurement.title);\r\n newMeasurement.setTimestamp(measurement.time_created);\r\n\r\n measurement.coordinates.forEach(vertex => {\r\n vertex = new Vector3().fromArray(vertex);\r\n if (vertex.length() === 0) return;\r\n\r\n newMeasurement.vertices.push(new GeocentricCoordinate(vertex));\r\n });\r\n\r\n if (newMeasurement instanceof MeasurementArea) {\r\n newMeasurement.generateSurface();\r\n }\r\n\r\n if (newMeasurement instanceof MeasurementVolume) {\r\n newMeasurement.loadExistingVolume(measurement.volume);\r\n }\r\n\r\n if (newMeasurement instanceof StationMeasurement) {\r\n newMeasurement.loadExistingStation(measurement);\r\n }\r\n\r\n return newMeasurement;\r\n });\r\n\r\n // Add 2d measurements\r\n let measure2D = result.measurements2D.map(measurement => {\r\n let newMeasurement = (measurement.type === MeasureType.Length)\r\n ? new AerialLengthMeasurement()\r\n : new AerialAreaMeasurement();\r\n\r\n newMeasurement.loadFromCoordinates(measurement.coordinates);\r\n newMeasurement.setController(this.controller);\r\n newMeasurement.setTitle(measurement.title);\r\n newMeasurement.setTimestamp(measurement.time_created);\r\n\r\n return newMeasurement;\r\n });\r\n\r\n this.measurements = [...measure3D, ...measure2D];\r\n\r\n // Sort by reverse timestamp ordering\r\n this.measurements = this.measurements.sort((a, b) =>\r\n a.timestamp < b.timestamp ? 1 : b.timestamp < a.timestamp ? -1 : 0\r\n );\r\n this.measurements.reverse();\r\n\r\n // Display the measurements\r\n this.measurements.forEach(measurement => {\r\n this.controller.renderMeasurement(measurement);\r\n });\r\n\r\n // Make sure drag object is false\r\n this.controller.resetDragObject();\r\n }\r\n\r\n getEmptyMeasurement(type: MeasureType) {\r\n if (type === MeasureType.Point) {\r\n return new MeasurementPoint();\r\n } else if (type === MeasureType.Area) {\r\n return new MeasurementArea();\r\n } else if (type === MeasureType.Volume) {\r\n return new MeasurementVolume();\r\n } else if (type === MeasureType.Height) {\r\n return new HeightMeasurement();\r\n } else if (type === MeasureType.Station) {\r\n return new StationMeasurement();\r\n }\r\n\r\n return new MeasurementLine();\r\n }\r\n\r\n getLineCoordinates(projection) {\r\n let lines = [];\r\n let names = [];\r\n let measurements = this.measurements;\r\n\r\n measurements.forEach(measurement => {\r\n if (measurement instanceof MeasurementPoint) {\r\n return;\r\n }\r\n\r\n let isAerial = measurement instanceof AerialMeasurement;\r\n let isLine = measurement instanceof Measurement3D;\r\n if (isAerial || isLine) {\r\n let line = measurement.getProjectedVertices(projection);\r\n lines.push(line);\r\n names.push(measurement.title);\r\n }\r\n });\r\n\r\n return {\r\n data: lines,\r\n names: names\r\n };\r\n }\r\n\r\n getPointCoordinates(projection) {\r\n let points = [];\r\n let names = [];\r\n let measurements = this.measurements;\r\n\r\n measurements.forEach(measurement => {\r\n if (measurement instanceof MeasurementPoint) {\r\n let point = measurement.getProjectedVertices(projection);\r\n points.push(point[0]);\r\n names.push(measurement.title);\r\n }\r\n });\r\n\r\n return {\r\n data: points,\r\n names: names\r\n };\r\n }\r\n\r\n getAreaGeometry(temporaryMeasurement: Measurement = null) {\r\n let measurements = [...this.measurements];\r\n\r\n if (temporaryMeasurement) {\r\n measurements.push(temporaryMeasurement);\r\n }\r\n\r\n let areaMeasurements = measurements.filter(measurement => {\r\n return measurement instanceof MeasurementArea;\r\n });\r\n\r\n let measureGeometry = [];\r\n areaMeasurements.forEach(measurement => {\r\n if (!measurement.valid) return;\r\n\r\n let volumeStatus = 0;\r\n if (measurement instanceof MeasurementVolume) {\r\n volumeStatus = measurement.calculated ? 2 : 1;\r\n }\r\n\r\n measureGeometry.push({\r\n vertices: measurement.surfaceVertices,\r\n indices: measurement.surfaceIndices,\r\n volumeStatus: volumeStatus\r\n });\r\n });\r\n\r\n measureGeometry.sort((a, b) => {\r\n return a.volumeStatus - b.volumeStatus;\r\n });\r\n measureGeometry.reverse();\r\n\r\n return measureGeometry;\r\n }\r\n}\r\n","import { CustomMouseEvent } from '../controls';\r\nimport { SceneCoordinate } from '../projections';\r\nimport { ChangeDetector, getPointScale } from '../utilities';\r\nimport {\r\n MeasurementArea,\r\n MeasurementVolume,\r\n MeasurementController,\r\n Measurement,\r\n HeightMeasurement,\r\n MeasurementLine,\r\n MeasurementType,\r\n StationMeasurement\r\n} from '.';\r\nimport {\r\n Mesh,\r\n Scene,\r\n SphereGeometry,\r\n MeshBasicMaterial,\r\n LineBasicMaterial,\r\n Line,\r\n BufferGeometry,\r\n Vector3,\r\n Sphere\r\n} from 'three';\r\nimport { clearViewerTooltip, setViewerTooltip } from '../viewer';\r\nimport { RayCaster } from '../ray-caster';\r\nimport { t } from '../../localization';\r\n\r\ninterface MeasureObject {\r\n id: number\r\n lines: Line[]\r\n points: MeasureEndpoint[]\r\n labels: any[]\r\n}\r\n\r\nconst alternateLabelColor = \"lightgreen\";\r\n\r\nexport class MeasureEndpoint extends Mesh {\r\n public measurementVertex;\r\n public measurementID;\r\n\r\n constructor(geometry, material, index, id) {\r\n super(geometry, material);\r\n this.measurementVertex = index;\r\n this.measurementID = id;\r\n }\r\n\r\n /** Custom hit detection based on bounding sphere */\r\n raycast(raycaster, intersects) {\r\n const sphere = new Sphere();\r\n sphere.copy(this.geometry.boundingSphere);\r\n sphere.applyMatrix4(this.matrixWorld);\r\n\r\n const ray = raycaster.ray;\r\n if (!ray.intersectsSphere(sphere)) return;\r\n\r\n const origin = raycaster.ray.origin;\r\n const distance = origin.distanceTo(this.position);\r\n\r\n intersects.push({\r\n distance: distance,\r\n point: null,\r\n object: this\r\n });\r\n }\r\n}\r\n\r\nexport class TemporaryEndpoint extends Mesh {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n}\r\n\r\nexport class MeasurementSceneView {\r\n private controller: MeasurementController;\r\n private scene: Scene;\r\n\r\n private sphereBuffer = 1.2;\r\n private sphereGeometry = new SphereGeometry(0.05, 20, 20);\r\n private sphereMaterialStandard = new MeshBasicMaterial({color: 0xffffff});\r\n private sphereMaterialHover = new MeshBasicMaterial({color: 0xffcc33});\r\n private lineMaterialStandard = new LineBasicMaterial({color: 0x008B8B});\r\n private lineMaterialHeight = new LineBasicMaterial({color: 0xFF7474});\r\n private lineMaterialHover = new LineBasicMaterial({color: 0xffcc33});\r\n\r\n private measurements: MeasureObject[] = [];\r\n private temporaryEndpoints: TemporaryEndpoint[] = [];\r\n private temporaryLines = [];\r\n private temporaryLabels = [];\r\n public hoveredPoint: TemporaryEndpoint = null;\r\n public dragObject: MeasureEndpoint = null;\r\n private dragValid = false;\r\n\r\n constructor(controller, scene) {\r\n this.controller = controller;\r\n this.scene = scene;\r\n }\r\n\r\n get viewer() {\r\n return this.controller.viewer;\r\n }\r\n\r\n get camera() {\r\n return this.viewer.camera;\r\n }\r\n\r\n get dragging() {\r\n return !!this.dragObject;\r\n }\r\n\r\n get dragTooltip() {\r\n return [\r\n t('measure.click-and-hold-to-move-vertex')\r\n ];\r\n }\r\n\r\n get restrictedTooltip() {\r\n return [\r\n t('measure.unable-to-move-this-measurement-type')\r\n ];\r\n }\r\n\r\n get formatter() {\r\n return this.controller.formatter;\r\n }\r\n\r\n get measurementGroup() {\r\n return this.controller.measurementGroup;\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n if (!event.mouseMoved && !event.mouseDown) {\r\n this.checkEndpointSelected(event);\r\n }\r\n\r\n if (this.controller.measuring) {\r\n let measurement = this.controller.activeMeasurement;\r\n let coordinate = this.controller.getCoordinate(event);\r\n this.addActiveEndpoint(measurement, coordinate);\r\n }\r\n\r\n if (this.dragObject) return true;\r\n\r\n this.controller.updateMeasureText();\r\n return !this.controller.disabled;\r\n }\r\n\r\n onMouseDrag(event: CustomMouseEvent) {\r\n if (!this.dragObject) return false;\r\n\r\n if (event.mouseDown && event.isLeftClick) {\r\n let coordinate = this.controller.getCoordinate(event);\r\n this.updateMeasureEndpoint(coordinate);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n updateMeasureEndpoint(coordinate) {\r\n if (!this.dragObject) return;\r\n if (!coordinate) return;\r\n\r\n let id = this.dragObject.measurementID;\r\n let vertexIndex = this.dragObject.measurementVertex;\r\n let measurement = this.measurementGroup.getByID(id);\r\n\r\n if (!measurement) return;\r\n\r\n if (measurement instanceof StationMeasurement) {\r\n this.setRestrictedPointTooltip();\r\n this.dragValid = false;\r\n return;\r\n }\r\n if (measurement instanceof MeasurementVolume) {\r\n measurement.stopVolumeCalculation();\r\n }\r\n\r\n this.dragValid = true;\r\n\r\n // Update our measurement vertex value\r\n let vertex = new SceneCoordinate(coordinate).toGeocentric();\r\n measurement.vertices[vertexIndex] = vertex;\r\n\r\n // Clear existing measurement and redraw\r\n this.removeByID(measurement.id);\r\n this.render(measurement);\r\n }\r\n\r\n measureGrabFinished() {\r\n if ((!this.dragObject) || (!this.dragValid)) return;\r\n\r\n this.controller.refreshMeasurementList();\r\n\r\n this.measurementGroup.measurements.forEach(measurement => {\r\n if (measurement instanceof MeasurementVolume) {\r\n if (measurement.calculated) return;\r\n measurement.calculateVolume();\r\n }\r\n });\r\n }\r\n\r\n checkEndpointSelected(event) {\r\n let controller = this.controller;\r\n if (!controller.editable) return;\r\n if (controller.measuring) return;\r\n\r\n let targets = this.scene.children\r\n .filter(x => x instanceof MeasureEndpoint);\r\n\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let objects = raycaster.intersectObjects(targets, {\r\n minDistance: 0.10,\r\n sortByRay: true\r\n });\r\n\r\n let draggable = objects.length > 0;\r\n let dragObject = draggable ? objects[0].object : null;\r\n this.setDragObject(dragObject);\r\n }\r\n\r\n setDragObject(dragObject) {\r\n // Image-only measurements can't be dragged\r\n if (this.controller.isImageOnly) {\r\n dragObject = null;\r\n }\r\n\r\n this.dragObject = dragObject;\r\n\r\n let draggable = dragObject ? true : false;\r\n let controls = this.controller.controls;\r\n controls.setMovementState(!draggable);\r\n\r\n if (dragObject) {\r\n this.setPointGrabTooltip();\r\n }\r\n }\r\n\r\n setPointGrabTooltip() {\r\n setViewerTooltip(this.dragTooltip);\r\n }\r\n\r\n setRestrictedPointTooltip() {\r\n setViewerTooltip(this.restrictedTooltip);\r\n }\r\n\r\n setTooltipText(measurement: MeasurementType, morepoints = false) {\r\n if (!measurement) {\r\n clearViewerTooltip();\r\n return;\r\n }\r\n\r\n let tooltipText = [] as string[];\r\n\r\n if (morepoints) {\r\n let endTooltipCount = measurement.minVertexRequired - 1;\r\n endTooltipCount = Math.max(2, endTooltipCount);\r\n\r\n if (measurement.vertices.length < endTooltipCount) {\r\n tooltipText = this.controller.isImageOnly\r\n ? measurement.moreTooltipMulti\r\n : measurement.moreTooltip;\r\n } else {\r\n tooltipText = this.controller.isImageOnly\r\n ? measurement.endTooltipMulti\r\n : measurement.endTooltip;\r\n }\r\n } else {\r\n tooltipText = this.controller.isImageOnly\r\n ? measurement.startTooltipMulti\r\n : measurement.startTooltip;\r\n }\r\n\r\n setViewerTooltip(tooltipText);\r\n }\r\n\r\n setPointScale(mesh) {\r\n const scale = getPointScale(this.camera, mesh);\r\n mesh.scale.set(scale, scale, scale);\r\n mesh.geometry.computeBoundingSphere();\r\n mesh.geometry.boundingSphere.radius *= this.sphereBuffer;\r\n }\r\n\r\n addTemporaryPoint(coordinate) {\r\n let sphere = this.createTempEndpoint(coordinate);\r\n this.scene.add(sphere);\r\n this.temporaryEndpoints.push(sphere);\r\n }\r\n\r\n addActiveEndpoint(measurement, coordinate) {\r\n if (coordinate === null) return;\r\n\r\n if (this.hoveredPoint) {\r\n this.scene.remove(this.hoveredPoint);\r\n }\r\n\r\n let sphere = this.createTempEndpoint(coordinate);\r\n this.scene.add(sphere);\r\n this.hoveredPoint = sphere;\r\n\r\n this.removeObjects(this.temporaryLines);\r\n this.removeLabels(this.temporaryLabels);\r\n\r\n this.temporaryLines = [];\r\n this.temporaryLabels = [];\r\n\r\n // Draw new lines and area\r\n let vertices = [...this.temporaryEndpoints, this.hoveredPoint]\r\n .map(point => point.position);\r\n\r\n const temporaryPoint = new SceneCoordinate(\r\n this.hoveredPoint.position);\r\n\r\n this.temporaryLines = this.drawLines(\r\n measurement, vertices, temporaryPoint);\r\n\r\n this.temporaryLabels = this.drawLabels(\r\n measurement, this.temporaryLines);\r\n }\r\n\r\n createEndpoint(coordinates, index, id) {\r\n let sphere = new MeasureEndpoint(this.sphereGeometry,\r\n this.sphereMaterialStandard, index, id);\r\n\r\n sphere.position.copy(coordinates);\r\n this.setPointScale(sphere);\r\n\r\n return sphere;\r\n }\r\n\r\n createTempEndpoint(coordinate) {\r\n let sphere = new TemporaryEndpoint(this.sphereGeometry,\r\n this.sphereMaterialStandard);\r\n\r\n sphere.position.copy(coordinate);\r\n this.setPointScale(sphere);\r\n\r\n return sphere;\r\n }\r\n\r\n createLine(start: Vector3, end: Vector3, useAlternate) {\r\n const vertices = [start.clone(), end.clone()];\r\n const geometry = new BufferGeometry().setFromPoints(vertices);\r\n const material = useAlternate\r\n ? this.lineMaterialHeight\r\n : this.lineMaterialStandard;\r\n\r\n let line = new Line(geometry, material);\r\n line.userData.defaultMaterial = material;\r\n\r\n return line;\r\n }\r\n\r\n setHover(id, hover) {\r\n let measurement = this.getByID(id);\r\n if (!measurement) return;\r\n\r\n for (let object of measurement.lines) {\r\n const lineMaterial = hover\r\n ? this.lineMaterialHover\r\n : object.userData.defaultMaterial;\r\n\r\n object.material = lineMaterial as LineBasicMaterial;\r\n object.material.needsUpdate = true;\r\n }\r\n\r\n for (let object of measurement.points) {\r\n const pointMaterial = hover\r\n ? this.sphereMaterialHover\r\n : this.sphereMaterialStandard;\r\n\r\n object.material = pointMaterial;\r\n object.material.needsUpdate = true;\r\n }\r\n }\r\n\r\n drawPoints(measurement: Measurement, vertices: Vector3[]): MeasureEndpoint[] {\r\n let points = [];\r\n\r\n for (let i=0; i= 3;\r\n if ((measurement instanceof MeasurementArea) && hasEnoughPoints) {\r\n vertices.push(vertices[0]);\r\n measurement.generateSurface(temporaryPoint);\r\n }\r\n\r\n // Draw standard lines\r\n for (let i=0; i vertices[1].z;\r\n let vertex0 = firstPointHigher ? vertices[0] : vertices[1];\r\n let vertex1 = firstPointHigher ? vertices[1] : vertices[0];\r\n let vertex2 = new SceneCoordinate([vertex0.x, vertex0.y, vertex1.z]);\r\n\r\n let line0 = this.createLine(vertex1, vertex2, true);\r\n this.scene.add(line0);\r\n lines.push(line0);\r\n\r\n let line1 = this.createLine(vertex2, vertex0, true);\r\n this.scene.add(line1);\r\n lines.push(line1);\r\n }\r\n\r\n return lines;\r\n }\r\n\r\n drawLabels(measurement: Measurement, lines: Line[]) {\r\n let totalLength = 0;\r\n let labels = [];\r\n\r\n // Draw standard length labels\r\n lines.forEach((line, index) => {\r\n const positions = line.geometry.attributes.position;\r\n const P1 = new Vector3().fromBufferAttribute(positions, 0);\r\n const P2 = new Vector3().fromBufferAttribute(positions, 1);\r\n\r\n const length = P1.distanceTo(P2);\r\n const message = this.formatter.formatLength(length);\r\n\r\n totalLength += length;\r\n\r\n const midpoint = new Vector3()\r\n .addVectors(P1, P2)\r\n .divideScalar(2.0);\r\n\r\n const position = new SceneCoordinate(midpoint)\r\n .toDataProjection()\r\n .toArray();\r\n\r\n const isHeight = measurement instanceof HeightMeasurement;\r\n const lastLines = index >= lines.length-2;\r\n\r\n const style = (isHeight && lastLines)\r\n ? {color: alternateLabelColor}\r\n : null;\r\n\r\n const label = this.viewer.addSceneLabel(\r\n message, position, null, style);\r\n\r\n labels.push(label);\r\n });\r\n\r\n let objectMessage;\r\n let objectPosition;\r\n\r\n // Total line length\r\n if (measurement instanceof MeasurementLine) {\r\n const line = lines[lines.length - 1];\r\n const positions = line.geometry.attributes.position;\r\n const endPoint = new Vector3().fromBufferAttribute(positions, 1);\r\n\r\n objectMessage = this.formatter.formatLength(totalLength);\r\n objectPosition = new SceneCoordinate(endPoint)\r\n .toDataProjection()\r\n .toArray();\r\n }\r\n\r\n // Total area / volume\r\n const hasEnoughLines = lines.length >= 3;\r\n if ((measurement instanceof MeasurementArea) && hasEnoughLines) {\r\n const midpoint = new Vector3();\r\n lines.forEach(line => {\r\n const positions = line.geometry.attributes.position;\r\n const vertex = new Vector3().fromBufferAttribute(positions, 1);\r\n midpoint.add(vertex);\r\n });\r\n midpoint.divideScalar(lines.length);\r\n\r\n if (measurement instanceof MeasurementVolume) {\r\n if (measurement.calculated) {\r\n objectMessage = this.formatter.formatVolume(measurement);\r\n }\r\n } else {\r\n const {area, valid} = measurement.area;\r\n\r\n objectMessage = valid\r\n ? this.formatter.formatArea(area)\r\n : t('measure.invalid-area');\r\n }\r\n\r\n objectPosition = new SceneCoordinate(midpoint)\r\n .toDataProjection()\r\n .toArray();\r\n }\r\n\r\n if (objectPosition && objectMessage) {\r\n const style = {\r\n color: alternateLabelColor\r\n };\r\n\r\n const label = this.viewer.addSceneLabel(\r\n objectMessage, objectPosition, null, style);\r\n\r\n labels.push(label);\r\n }\r\n\r\n this.viewer.updateSceneLabels();\r\n\r\n return labels;\r\n }\r\n\r\n render(measurement) {\r\n let oldMeasurement = this.getByID(measurement.id);\r\n this.removeMeasurement(oldMeasurement);\r\n\r\n const vertices = measurement.vertices\r\n .map(vertex => vertex.toScene());\r\n\r\n const points = this.drawPoints(measurement, vertices);\r\n const lines = this.drawLines(measurement, vertices);\r\n const labels = this.drawLabels(measurement, lines);\r\n\r\n this.measurements.push({\r\n id: measurement.id,\r\n labels,\r\n lines,\r\n points\r\n });\r\n }\r\n\r\n removeObjects(objects) {\r\n objects.forEach(object => {\r\n this.scene.remove(object);\r\n });\r\n }\r\n\r\n removeLabels(labels) {\r\n labels.forEach(label => {\r\n this.viewer.removeSceneLabel(label);\r\n });\r\n\r\n this.viewer.updateSceneLabels();\r\n }\r\n\r\n removeTemporaryObjects() {\r\n this.removeObjects(this.temporaryEndpoints);\r\n this.removeObjects(this.temporaryLines);\r\n this.removeLabels(this.temporaryLabels);\r\n\r\n if (this.hoveredPoint) {\r\n this.scene.remove(this.hoveredPoint);\r\n }\r\n\r\n this.temporaryLines = [];\r\n this.temporaryLabels = [];\r\n this.temporaryEndpoints = [];\r\n this.hoveredPoint = null;\r\n }\r\n\r\n getByID(id) {\r\n return this.measurements.find(measurement => measurement.id === id);\r\n }\r\n\r\n removeByID(id) {\r\n // Clear scene objects and remove from array\r\n let measurement = this.getByID(id);\r\n this.removeMeasurement(measurement);\r\n\r\n // Reset measurement volume/area values\r\n let measurementObject = this.measurementGroup.getByID(id);\r\n measurementObject.clear();\r\n }\r\n\r\n removeMeasurement(measurement: MeasureObject) {\r\n if (!measurement) return;\r\n\r\n this.removeObjects(measurement.lines);\r\n this.removeObjects(measurement.points);\r\n this.removeLabels(measurement.labels);\r\n\r\n this.measurements = this.measurements\r\n .filter(x => x.id !== measurement.id);\r\n }\r\n\r\n removeAll() {\r\n for (let measurement of this.measurements) {\r\n this.removeObjects(measurement.lines);\r\n this.removeObjects(measurement.points);\r\n this.removeLabels(measurement.labels);\r\n }\r\n\r\n this.measurements = [];\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n if (!changeDetector.changed) return;\r\n\r\n this.temporaryEndpoints.forEach(mesh => {\r\n this.setPointScale(mesh);\r\n });\r\n\r\n this.measurements.forEach(measurement => {\r\n measurement.points.forEach(mesh => {\r\n this.setPointScale(mesh);\r\n });\r\n });\r\n }\r\n}\r\n","import {\r\n BufferAttribute,\r\n BufferGeometry,\r\n Color,\r\n Mesh,\r\n Points,\r\n Vector3,\r\n Camera,\r\n LineSegments,\r\n Object3D,\r\n Line,\r\n LineBasicMaterial,\r\n Triangle,\r\n Plane,\r\n} from \"three\";\r\nimport { LinearEncoding, NearestFilter, RGBAFormat } from \"three/src/constants\";\r\nimport { WebGLRenderer } from \"three/src/renderers/WebGLRenderer\";\r\nimport { WebGLRenderTarget } from \"three/src/renderers/WebGLRenderTarget\";\r\nimport { Scene } from \"three/src/scenes/Scene\";\r\nimport { RayCaster } from \"./ray-caster\";\r\nimport { Viewer } from \"./main\";\r\nimport { allIndexOf, eventToPixel } from \"./utilities\";\r\n\r\nexport const addGPUIndex = (mesh) => {\r\n const indices = new Int32Array(mesh.geometry.attributes.position.count);\r\n mesh.geometry.setAttribute('gpu_index', new BufferAttribute(indices, 1));\r\n return mesh;\r\n};\r\n\r\nexport const cloneMeshObject = (mesh) => {\r\n const clone = mesh.clone();\r\n\r\n if (Array.isArray(mesh.material)) {\r\n clone.material = mesh.material.slice(0);\r\n } else {\r\n clone.materials = mesh.material.clone();\r\n }\r\n\r\n return clone;\r\n};\r\n\r\nexport default class GPUPicker {\r\n private name\r\n public debug = false;\r\n public scene : Scene\r\n private viewer: Viewer\r\n private camera: Camera\r\n private numSections = 3;\r\n private sections;\r\n public target : WebGLRenderTarget\r\n private _needsUpdate = false;\r\n public result;\r\n\r\n constructor(viewer: Viewer, name) {\r\n this.name = name;\r\n this.viewer = viewer;\r\n this.scene = new Scene();\r\n\r\n this.target = new WebGLRenderTarget(0, 0, {\r\n minFilter: NearestFilter,\r\n magFilter: NearestFilter,\r\n format: RGBAFormat,\r\n encoding: LinearEncoding,\r\n generateMipmaps: false\r\n });\r\n\r\n this.clearSections();\r\n }\r\n\r\n get height() {\r\n return this.target.height;\r\n }\r\n\r\n get width() {\r\n return this.target.width;\r\n }\r\n\r\n get renderer(): WebGLRenderer {\r\n return this.viewer.renderer;\r\n }\r\n\r\n get needsUpdate() {\r\n return this._needsUpdate;\r\n }\r\n\r\n set needsUpdate(value) {\r\n if (this.debug) {\r\n console.log(`Update ${this.name} picker state`, value);\r\n }\r\n\r\n this._needsUpdate = value;\r\n }\r\n\r\n remove(mesh) {\r\n this.scene.remove(mesh);\r\n this.needsUpdate = true;\r\n }\r\n\r\n add(mesh) {\r\n this.scene.add(mesh);\r\n mesh.material.transparent = false;\r\n this.needsUpdate = true;\r\n }\r\n\r\n clear() {\r\n this.scene.clear();\r\n }\r\n\r\n value(event) {\r\n let uv = eventToPixel(event);\r\n let tX = uv.x;\r\n let tY = this.height - uv.y;\r\n\r\n const renderUtils = this.viewer.renderUtils;\r\n\r\n let insideRadius = renderUtils.insideRadius(uv);\r\n if (!insideRadius) return null;\r\n\r\n let sectionWidth = Math.floor(this.width/this.numSections);\r\n let sectionHeight = Math.floor(this.height/this.numSections);\r\n let sectionX = Math.floor(tX/sectionWidth);\r\n let sectionY = Math.floor(tY/sectionHeight);\r\n let sectionIndex = sectionX + (sectionY * this.numSections);\r\n\r\n tX = tX % sectionWidth;\r\n tY = tY % sectionHeight;\r\n let pixelIndex = 4 * (tX + tY * sectionWidth);\r\n\r\n if (this.sections[sectionIndex] === null) {\r\n const timeStart = performance.now();\r\n\r\n let startX = sectionX*sectionWidth;\r\n let startY = sectionY*sectionHeight;\r\n\r\n let pixelBuffer = new Uint8Array(4 * sectionWidth * sectionHeight);\r\n this.renderer.readRenderTargetPixels(this.target, startX, startY,\r\n sectionWidth, sectionHeight, pixelBuffer);\r\n\r\n // Update section results\r\n this.sections[sectionIndex] = pixelBuffer;\r\n\r\n const timeEnd = performance.now();\r\n let time = (timeEnd - timeStart).toFixed(1);\r\n\r\n if (this.debug) {\r\n console.log(`Render ${this.name} picker: ${time}ms`);\r\n }\r\n }\r\n\r\n let result = this.sections[sectionIndex];\r\n if (!result) return null;\r\n\r\n let mouseResult = new Uint8Array([\r\n result[pixelIndex + 0],\r\n result[pixelIndex + 1],\r\n result[pixelIndex + 2],\r\n result[pixelIndex + 3]\r\n ]);\r\n\r\n let pickerID = (mouseResult[0] << 24)\r\n + (mouseResult[1] << 16)\r\n + (mouseResult[2] << 8)\r\n + mouseResult[3];\r\n\r\n return (pickerID >= 0) ? pickerID : null;\r\n }\r\n\r\n update() {\r\n if (!this.needsUpdate) return;\r\n\r\n this.clearSections();\r\n this.updateBaseIDs();\r\n\r\n this.needsUpdate = false;\r\n\r\n const oldClearColor = new Color();\r\n const newClearColor = new Color(0xffffff);\r\n\r\n let oldRenderTarget = this.renderer.getRenderTarget();\r\n this.renderer.getClearColor(oldClearColor);\r\n let oldClearAlpha = this.renderer.getClearAlpha();\r\n\r\n this.renderer.setRenderTarget(this.target);\r\n this.renderer.setClearColor(newClearColor);\r\n this.renderer.clear();\r\n this.renderer.render(this.scene, this.camera);\r\n this.renderer.setRenderTarget(oldRenderTarget);\r\n this.renderer.setClearColor(oldClearColor);\r\n this.renderer.setClearAlpha(oldClearAlpha);\r\n }\r\n\r\n clearSections() {\r\n this.sections = new Array(this.numSections**2).fill(null);\r\n }\r\n\r\n updateBaseIDs() {\r\n let currentBaseID = 0;\r\n this.scene.children.forEach((child: Mesh) => {\r\n let geometry = child.geometry as BufferGeometry;\r\n let indices = geometry.attributes.gpu_index.array as any;\r\n\r\n for (var i=0;i {\r\n if (object !== null) return;\r\n\r\n let geometry = (child as any).geometry as BufferGeometry;\r\n let indices = geometry.attributes.gpu_index.array as Array;\r\n\r\n // Determine if the index exists inside this object\r\n let minIndex = indices[0];\r\n let maxIndex = indices[indices.length - 1];\r\n if ((gpuIndex < minIndex) || (gpuIndex > maxIndex)) {\r\n return;\r\n }\r\n\r\n let arrayIndex = indices.indexOf(gpuIndex);\r\n if (arrayIndex === -1) return;\r\n\r\n object = child;\r\n });\r\n\r\n return object;\r\n }\r\n\r\n getObjectPosition(object, gpuIndex, event): Vector3 {\r\n let coordinate = null;\r\n if (!object) return coordinate;\r\n\r\n const geometry = object.geometry as BufferGeometry;\r\n const indices = geometry.attributes.gpu_index.array as Array;\r\n const positions = geometry.attributes.position;\r\n const index = indices.indexOf(gpuIndex);\r\n\r\n const parameters = {geometry, indices, positions, index};\r\n\r\n if (object instanceof Points) {\r\n coordinate = this.coordinateFromBuffer(object, positions, index);\r\n } else if (object instanceof Mesh) {\r\n coordinate = this.coordinateFromMesh(object, parameters, event);\r\n } else if (object instanceof LineSegments) {\r\n coordinate = this.coordinateFromLine(object, parameters, event);\r\n }\r\n\r\n return coordinate;\r\n }\r\n\r\n /** @private */\r\n coordinateFromMesh(object, parameters, event): Vector3 {\r\n const {geometry, positions, index} = parameters;\r\n\r\n const toCheck = [];\r\n const triangles: Triangle[] = [];\r\n const planes: Plane[] = [];\r\n\r\n if (geometry.index !== null) {\r\n const faces = geometry.index.array as Array;\r\n const indices = allIndexOf(faces, index);\r\n\r\n // Multiple base index might exist for this position. All\r\n // of them need to be added and checked for validity\r\n indices.forEach(faceIndex => {\r\n faceIndex = Math.floor(faceIndex/3) * 3;\r\n\r\n toCheck.push([\r\n faces[faceIndex],\r\n faces[faceIndex + 1],\r\n faces[faceIndex + 2]\r\n ]);\r\n });\r\n } else {\r\n // Only one mesh face will exist\r\n const faceIndex = Math.floor(index/3) * 3;\r\n\r\n toCheck.push([\r\n faceIndex,\r\n faceIndex + 1,\r\n faceIndex + 2\r\n ]);\r\n }\r\n\r\n const raycaster = new RayCaster(this.viewer, event);\r\n\r\n toCheck.forEach(face => {\r\n const P1 = this.coordinateFromBuffer(object, positions, face[0]);\r\n const P2 = this.coordinateFromBuffer(object, positions, face[1]);\r\n const P3 = this.coordinateFromBuffer(object, positions, face[2]);\r\n\r\n const triangle = new Triangle(P1, P2, P3);\r\n triangles.push(triangle);\r\n\r\n const plane = new Plane().setFromCoplanarPoints(P1, P2, P3);\r\n planes.push(plane);\r\n });\r\n\r\n for (let triangle of triangles) {\r\n const coordinate = raycaster.intersectTriangle(triangle);\r\n if (coordinate) return coordinate;\r\n };\r\n\r\n for (let plane of planes) {\r\n const coordinate = raycaster.intersectPlane(plane);\r\n if (coordinate) return coordinate;\r\n };\r\n\r\n const intersections = raycaster.intersectObject(object);\r\n if (intersections.length > 0) {\r\n return intersections[0].point;\r\n }\r\n\r\n return null;\r\n }\r\n\r\n /** @private */\r\n coordinateFromLine(object, parameters, event) {\r\n const {geometry, positions, index} = parameters;\r\n\r\n let isFirstPoint;\r\n if (geometry.index !== null) {\r\n // Index positions (check position in index array);\r\n const pointIndices = geometry.index.array as Array;\r\n const pointIndex = pointIndices.indexOf(index);\r\n isFirstPoint = (pointIndex % 2) === 0;\r\n } else {\r\n // Non-index positions\r\n isFirstPoint = (index % 2) === 0;\r\n }\r\n\r\n const P1 = this.coordinateFromBuffer(object, positions, index);\r\n const P2 = isFirstPoint\r\n ? this.coordinateFromBuffer(object, positions, index + 1)\r\n : this.coordinateFromBuffer(object, positions, index - 1);\r\n\r\n const lineMaterial = new LineBasicMaterial({});\r\n const lineGeometry = new BufferGeometry().setFromPoints([P1, P2]);\r\n const line = new Line( lineGeometry, lineMaterial );\r\n const raycaster = new RayCaster(this.viewer, event);\r\n const results = raycaster.intersectObject(line);\r\n\r\n return (results.length > 0)\r\n ? results[0].point\r\n : null;\r\n }\r\n\r\n /** @private */\r\n coordinateFromBuffer(object, positions, index) {\r\n return new Vector3()\r\n .fromBufferAttribute(positions, index)\r\n .applyMatrix4(object.matrixWorld);\r\n }\r\n}\r\n","var Stats = function () {\r\n\r\n var mode = 0;\r\n\r\n var container = document.createElement( 'div' );\r\n container.style.cssText = 'position:fixed;top:0;left:0;cursor:pointer;opacity:0.9;z-index:10000';\r\n container.addEventListener( 'click', function ( event ) {\r\n\r\n event.preventDefault();\r\n showPanel( ++ mode % container.children.length );\r\n\r\n }, false );\r\n\r\n //\r\n\r\n function addPanel( panel ) {\r\n\r\n container.appendChild( panel.dom );\r\n return panel;\r\n\r\n }\r\n\r\n function showPanel( id ) {\r\n\r\n for ( var i = 0; i < container.children.length; i ++ ) {\r\n\r\n container.children[ i ].style.display = i === id ? 'block' : 'none';\r\n\r\n }\r\n\r\n mode = id;\r\n\r\n }\r\n\r\n //\r\n\r\n var beginTime = ( performance || Date ).now(), prevTime = beginTime, frames = 0;\r\n\r\n var fpsPanel = addPanel( new Stats.Panel( 'FPS', '#0ff', '#002' ) );\r\n var msPanel = addPanel( new Stats.Panel( 'MS', '#0f0', '#020' ) );\r\n\r\n if ( window.self.performance && window.self.performance.memory ) {\r\n\r\n var memPanel = addPanel( new Stats.Panel( 'MB', '#f08', '#201' ) );\r\n\r\n }\r\n\r\n showPanel( 0 );\r\n\r\n return {\r\n\r\n REVISION: 16,\r\n\r\n dom: container,\r\n\r\n addPanel: addPanel,\r\n showPanel: showPanel,\r\n\r\n begin: function () {\r\n\r\n beginTime = ( performance || Date ).now();\r\n\r\n },\r\n\r\n end: function () {\r\n\r\n frames ++;\r\n\r\n var time = ( performance || Date ).now();\r\n\r\n msPanel.update( time - beginTime, 200 );\r\n\r\n if ( time >= prevTime + 1000 ) {\r\n\r\n fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 );\r\n\r\n prevTime = time;\r\n frames = 0;\r\n\r\n if ( memPanel ) {\r\n\r\n var memory = performance.memory;\r\n memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 );\r\n\r\n }\r\n\r\n }\r\n\r\n return time;\r\n\r\n },\r\n\r\n update: function () {\r\n\r\n beginTime = this.end();\r\n\r\n },\r\n\r\n // Backwards Compatibility\r\n\r\n domElement: container,\r\n setMode: showPanel\r\n\r\n };\r\n\r\n};\r\n\r\nStats.Panel = function ( name, fg, bg ) {\r\n\r\n var min = Infinity, max = 0, round = Math.round;\r\n var PR = round( window.devicePixelRatio || 1 );\r\n\r\n var WIDTH = 80 * PR, HEIGHT = 48 * PR,\r\n TEXT_X = 3 * PR, TEXT_Y = 2 * PR,\r\n GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR,\r\n GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR;\r\n\r\n var canvas = document.createElement( 'canvas' );\r\n canvas.width = WIDTH;\r\n canvas.height = HEIGHT;\r\n canvas.style.cssText = 'width:80px;height:48px';\r\n\r\n var context = canvas.getContext( '2d' );\r\n context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif';\r\n context.textBaseline = 'top';\r\n\r\n context.fillStyle = bg;\r\n context.fillRect( 0, 0, WIDTH, HEIGHT );\r\n\r\n context.fillStyle = fg;\r\n context.fillText( name, TEXT_X, TEXT_Y );\r\n context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT );\r\n\r\n context.fillStyle = bg;\r\n context.globalAlpha = 0.9;\r\n context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT );\r\n\r\n return {\r\n\r\n dom: canvas,\r\n\r\n update: function ( value, maxValue ) {\r\n\r\n min = Math.min( min, value );\r\n max = Math.max( max, value );\r\n\r\n context.fillStyle = bg;\r\n context.globalAlpha = 1;\r\n context.fillRect( 0, 0, WIDTH, GRAPH_Y );\r\n context.fillStyle = fg;\r\n context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y );\r\n\r\n context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT );\r\n\r\n context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT );\r\n\r\n context.fillStyle = bg;\r\n context.globalAlpha = 0.9;\r\n context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) );\r\n\r\n }\r\n\r\n };\r\n\r\n};\r\n\r\nexport default Stats;\r\n","import { Box3, Mesh, Scene, Vector3 } from \"three\";\r\nimport {DataProjectionCoordinate, SceneCoordinate} from \"../projections\";\r\nimport {Viewer} from \"../main\";\r\nimport { isEqual } from 'lodash';\r\nimport { Asset, TagAnnotation, TagData, TagItemData } from '../../redux/assets-slice';\r\nimport { mergeBoundingBoxes } from '../utilities';\r\nimport { AnnotationDrawType, AnnotationSize, TagSize } from '../../types/tags';\r\nimport { SceneCameraState } from '../../redux/camera-slice';\r\nimport { CustomMouseEvent } from '../controls';\r\nimport { AerialTags, SceneViewTags, TagAnnotations } from '.';\r\nimport { MapBrowserEvent } from \"ol\";\r\n\r\n// TODO: have a mesh and layer per TagFile\r\n\r\nexport class TagMesh extends Mesh {\r\n public tags;\r\n\r\n constructor(geometry, material, tags) {\r\n super(geometry, material);\r\n this.tags = tags;\r\n };\r\n};\r\n\r\nclass TagPosition {\r\n private _scene: SceneCoordinate;\r\n private _aerial: number[];\r\n\r\n private input: Vector3;\r\n private tag: TagItem;\r\n\r\n constructor(tag: TagItem, position) {\r\n this.tag = tag;\r\n this.input = new Vector3(...position);\r\n }\r\n\r\n get array() {\r\n return this.tag.isAerial\r\n ? [this.input.x, this.input.y]\r\n : [this.input.x, this.input.y, this.input.z];\r\n }\r\n\r\n get scene() {\r\n if (!this._scene) {\r\n const value = new DataProjectionCoordinate(this.input).toScene();\r\n this._scene = value;\r\n }\r\n\r\n return this._scene;\r\n }\r\n\r\n get aerial() {\r\n if (!this._aerial) {\r\n const value = new DataProjectionCoordinate(this.input).toAerial();\r\n this._aerial = value;\r\n }\r\n\r\n return this._aerial;\r\n }\r\n\r\n reset() {\r\n this._scene = null;\r\n this._aerial = null;\r\n }\r\n}\r\n\r\nexport class TagItem {\r\n public id: string;\r\n public csv: string;\r\n public name: string;\r\n public file: TagFile;\r\n public position: TagPosition;\r\n public comment: string;\r\n public annotations: TagAnnotation[];\r\n public sceneState: SceneCameraState;\r\n public isAerial = false;\r\n public texture: string;\r\n public visible: boolean;\r\n public size: number;\r\n\r\n constructor(asset: TagFile, tag: TagItemData) {\r\n this.id = tag.id;\r\n this.file = asset;\r\n this.name = tag.name;\r\n this.comment = tag.comment;\r\n this.annotations = tag.annotations;\r\n this.sceneState = tag.sceneState;\r\n this.isAerial = !(\"z\" in tag);\r\n\r\n this.csv = asset.id;\r\n this.texture = asset.texture;\r\n this.visible = asset.visible;\r\n this.size = asset.size;\r\n\r\n const position = [tag.x, tag.y, tag.z];\r\n this.position = new TagPosition(this, position);\r\n }\r\n}\r\n\r\nexport class TagFile {\r\n private tagsHandler: TagsHandler;\r\n public id: string;\r\n public saved: boolean;\r\n public size: TagSize;\r\n public texture: string;\r\n public visible: boolean;\r\n public name: string;\r\n public tags: TagItem[] = [];\r\n\r\n constructor(tagsHandler: TagsHandler, asset: Asset) {\r\n this.tagsHandler = tagsHandler;\r\n\r\n this.id = asset.id;\r\n this.saved = asset.saved;\r\n this.name = asset.name;\r\n }\r\n\r\n get viewer() {\r\n return this.tagsHandler.viewer;\r\n }\r\n\r\n get sceneViewTags() {\r\n return this.tags.filter(tag => !tag.isAerial);\r\n }\r\n\r\n zoomToExtent() {\r\n if (this.tags.length === 0) return;\r\n const boundingBox = boundingBoxForTags(this.tags);\r\n this.viewer.zoomToSceneExtent(boundingBox, false);\r\n }\r\n\r\n update(asset: Asset) {\r\n const {size, texture, items} = asset.data as TagData;\r\n\r\n const visibleChanged = this.visible !== asset.visible;\r\n this.visible = asset.visible;\r\n\r\n const textureChanged = this.texture !== texture;\r\n this.texture = texture;\r\n\r\n const sizeChanged = this.size !== size;\r\n this.size = size;\r\n\r\n const newTagIDs = items.map(x => x.id);\r\n const currentTagIDs = this.tags.map(x => x.id);\r\n const tagsChanged = !isEqual(newTagIDs, currentTagIDs);\r\n\r\n // Update all tags (comments may have changed)\r\n this.tags = items.map(tag => {\r\n return new TagItem(this, tag);\r\n });\r\n\r\n if (!this.saved) {\r\n this.zoomToExtent();\r\n }\r\n\r\n return visibleChanged\r\n || textureChanged\r\n || tagsChanged\r\n || sizeChanged;\r\n }\r\n}\r\n\r\nexport class TagsHandler {\r\n public viewer: Viewer;\r\n private sceneViewController: SceneViewTags;\r\n private aerialController: AerialTags;\r\n private annotations: TagAnnotations;\r\n public tagState = {};\r\n private files: TagFile[] = [];\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n this.sceneViewController = new SceneViewTags(this);\r\n this.aerialController = new AerialTags(this);\r\n this.annotations = new TagAnnotations(this);\r\n }\r\n\r\n get hovering() {\r\n return this.aerialController.hovering;\r\n }\r\n\r\n get scene(): Scene {\r\n return this.sceneViewController.scene;\r\n }\r\n\r\n get tags(): TagItem[] {\r\n return this.files.map(file => file.tags).flat();\r\n }\r\n\r\n get combinedBoundingBox() {\r\n return boundingBoxForTags(this.tags);\r\n }\r\n\r\n public get numberOfFiles() {\r\n return this.files.length;\r\n }\r\n\r\n set drawDistance(distance: number) {\r\n this.sceneViewController.drawDistance = distance;\r\n }\r\n\r\n addNewFile(asset: Asset) {\r\n if (this.getByID(asset.id)) return;\r\n\r\n const file = new TagFile(this, asset);\r\n this.files.push(file);\r\n }\r\n\r\n deleteFile(file: TagFile) {\r\n const index = this.files.indexOf(file);\r\n this.files.splice(index, 1);\r\n }\r\n\r\n updateTagData = (assetID: string, asset) => {\r\n let file = this.getByID(assetID);\r\n if (!file) return false;\r\n\r\n return file.update(asset);\r\n }\r\n\r\n getTooltipText(tagID: string): string[] {\r\n const selected = this.tags.find(x => x.id === tagID);\r\n if (!selected) return;\r\n\r\n const fileName = selected.file.name;\r\n const tagName = selected.name;\r\n\r\n return [`[${fileName}]`, tagName];\r\n }\r\n\r\n getByID(assetID: string) {\r\n return this.files.find(file => file.id === assetID);\r\n }\r\n\r\n getTagByID(tagID: string) {\r\n const allTags = this.files\r\n .map(file => file.tags)\r\n .flat();\r\n\r\n return allTags.find(tag => tag.id === tagID);\r\n }\r\n\r\n getTagByQuery(query: string) {\r\n if (!query) return;\r\n\r\n const allTags = this.files\r\n .map(file => file.tags)\r\n .flat();\r\n\r\n const search = query.toLowerCase();\r\n\r\n return allTags.find(tag => {\r\n const name = tag.name.toLowerCase();\r\n const comment = tag.comment.toLowerCase();\r\n\r\n return (tag.id === search)\r\n || (name.includes(search))\r\n || (comment.includes(search));\r\n });\r\n }\r\n\r\n getRowsCSV(tags: TagItem[]) {\r\n let tagCsvOut = [];\r\n\r\n const hasHeight = tags.filter(tag => !tag.isAerial).length > 0;\r\n const hasComments = tags.filter(tag => tag.comment).length > 0;\r\n const hasAnnotations = tags.filter(tag => tag.annotations.length > 0).length > 0;\r\n\r\n const header = [\r\n 'Name',\r\n 'Easting',\r\n 'Northing',\r\n ...hasHeight ? ['Elevation'] : [],\r\n ...hasComments ? ['Comments'] : [],\r\n ...hasAnnotations ? ['Annotations'] : []\r\n ];\r\n\r\n tagCsvOut.push(header);\r\n\r\n tags.forEach(tag => {\r\n let annotations = \"\";\r\n\r\n if (tag.annotations.length > 0) {\r\n let annotation = tag.annotations\r\n .map(annotation => annotation.definition);\r\n annotations = JSON.stringify(annotation);\r\n }\r\n\r\n const row = [\r\n tag.name,\r\n ...tag.position.array,\r\n ...hasComments ? [tag.comment] : [],\r\n ...hasAnnotations ? [annotations] : []\r\n ];\r\n tagCsvOut.push(row);\r\n });\r\n\r\n return tagCsvOut;\r\n }\r\n\r\n reconcile(tagFiles: Asset[]) {\r\n const currentIDs = new Set(this.files.map(x => x.id));\r\n const newAssetIDs = new Set(tagFiles.map(x => x.id));\r\n const assetsToLoad = tagFiles.filter(x => !currentIDs.has(x.id));\r\n const filesToDelete = this.files.filter(x => !newAssetIDs.has(x.id));\r\n\r\n // Delete files that need to be removed\r\n filesToDelete.forEach(file => {\r\n this.deleteFile(file);\r\n });\r\n\r\n // Add new tag files\r\n assetsToLoad.forEach(file => {\r\n this.addNewFile(file);\r\n });\r\n\r\n let needsUpdate = filesToDelete.length > 0;\r\n tagFiles.forEach(file => {\r\n const updated = this.updateTagData(file.id, file);\r\n needsUpdate = needsUpdate || updated;\r\n });\r\n\r\n if (needsUpdate) {\r\n this.sceneViewController.reconcile(this.files);\r\n this.aerialController.reconcile(this.files);\r\n }\r\n\r\n return assetsToLoad.length;\r\n }\r\n\r\n toggleAnnotations(state: boolean) {\r\n this.annotations.setState(state);\r\n }\r\n\r\n loadAnnotations(annotations: TagAnnotation[]) {\r\n this.annotations.load(annotations);\r\n }\r\n\r\n getAnnotations() {\r\n return this.annotations.getAnnotations();\r\n }\r\n\r\n setAnnotationType(type: AnnotationDrawType) {\r\n this.annotations.setType(type);\r\n }\r\n\r\n setAnnotationDrawing(drawing: boolean) {\r\n this.annotations.setDrawing(drawing);\r\n }\r\n\r\n setAnnotationColor(color: string) {\r\n this.annotations.setColor(color);\r\n }\r\n\r\n setAnnotationSize(size: AnnotationSize) {\r\n this.annotations.setSize(size);\r\n }\r\n\r\n setSelected(tagID: string, timeoutSeconds: number) {\r\n //this.aerialController.setSelected(tagID, timeoutSeconds);\r\n this.sceneViewController.setSelected(tagID, timeoutSeconds);\r\n }\r\n\r\n onMouseMoveScene(event: CustomMouseEvent) {\r\n return this.sceneViewController.onMouseMove(event);\r\n }\r\n\r\n onMouseMoveAerial(event: MapBrowserEvent) {\r\n if (this.annotations.drawing) {\r\n this.annotations.onMouseMove();\r\n } else {\r\n this.aerialController.onMouseMove(event);\r\n }\r\n }\r\n\r\n onMouseUpScene(event: CustomMouseEvent) {\r\n return this.sceneViewController.onMouseUp(event);\r\n }\r\n\r\n onMouseUpAerial(event: CustomMouseEvent) {\r\n return this.annotations.onMouseUp(event);\r\n }\r\n\r\n onMapClick(event) {\r\n this.annotations.onMapClick(event);\r\n }\r\n\r\n getPickerResults(event) {\r\n return this.sceneViewController.getPickerResults(event);\r\n }\r\n\r\n getFeatureForEvent(event) {\r\n return this.aerialController.getFeatureForEvent(event);\r\n }\r\n\r\n update() {\r\n this.sceneViewController.update();\r\n }\r\n}\r\n\r\nexport const boundingBoxForTags = (tags: TagItem[]) => {\r\n const buffer = 2.0;\r\n\r\n const boundingBoxes = tags.map(tag => {\r\n if (tag.isAerial) return null;\r\n\r\n const position = tag.position.scene;\r\n return new Box3(\r\n new Vector3().copy(position).subScalar(buffer),\r\n new Vector3().copy(position).addScalar(buffer)\r\n );\r\n });\r\n\r\n return mergeBoundingBoxes(boundingBoxes);\r\n};","import {\r\n Scene,\r\n Vector3,\r\n AmbientLight,\r\n BufferGeometry,\r\n BufferAttribute,\r\n MathUtils\r\n} from \"three\";\r\nimport { setViewerTooltip, clearViewerTooltip } from \"../viewer\";\r\nimport { CustomMouseEvent } from \"../controls\";\r\nimport GPUPicker from \"../gpu-picker\";\r\nimport { TagMaterial } from \"../rendering\";\r\nimport { TagsHandler, TagMesh, TagItem, TagFile } from \".\";\r\n\r\nexport class SceneViewTags {\r\n public scene: Scene;\r\n private tagsHandler: TagsHandler;\r\n\r\n private numVertices = 6;\r\n private uvs: number[] = [0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1];\r\n private corners: number[] = [0, 2, 1, 2, 3, 1];\r\n private vertices: Vector3[] = [\r\n new Vector3(-0.5, 0.5, 0),\r\n new Vector3(0.5, 0.5, 0),\r\n new Vector3(-0.5, -0.5, 0),\r\n new Vector3(0.5, -0.5, 0)\r\n ]\r\n private pickingMeshes: TagMesh[] = [];\r\n private standardMeshes: TagMesh[] = [];\r\n private flashTimeout: NodeJS.Timeout;\r\n private _drawDistance = 0;\r\n\r\n constructor(tagsHandler: TagsHandler) {\r\n this.tagsHandler = tagsHandler;\r\n\r\n this.initScene();\r\n }\r\n\r\n get viewer() {\r\n return this.tagsHandler.viewer;\r\n }\r\n\r\n get meshes() {\r\n return [...this.pickingMeshes, ...this.standardMeshes];\r\n }\r\n\r\n get materials() {\r\n return this.meshes.map(mesh => mesh.material);\r\n }\r\n\r\n get numberOfTags() {\r\n let count = 0;\r\n\r\n this.standardMeshes.forEach(mesh => {\r\n let geometry = mesh.geometry;\r\n let positions = geometry.attributes.position;\r\n count += (positions.count / this.numVertices);\r\n });\r\n\r\n return count;\r\n }\r\n\r\n private get picker(): GPUPicker {\r\n return this.viewer.gpuPickers.tags;\r\n }\r\n\r\n get drawDistance() {\r\n if (this.viewer.orbitState) {\r\n return this.viewer.far;\r\n }\r\n\r\n return (this._drawDistance > 999)\r\n ? this.viewer.far\r\n : this._drawDistance;\r\n }\r\n\r\n set drawDistance(distance: number) {\r\n this._drawDistance = distance;\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n reconcile(files: TagFile[]) {\r\n this.scene.clear();\r\n this.picker.clear();\r\n\r\n this.standardMeshes = [];\r\n this.pickingMeshes = [];\r\n\r\n files.forEach(file => {\r\n if (!file.visible) return;\r\n\r\n const sceneViewTags = file.sceneViewTags;\r\n if (sceneViewTags.length === 0) return;\r\n\r\n const size = sceneViewTags.length * this.numVertices;\r\n const positions = new Float32Array(size * 3);\r\n const selected = new Float32Array(size);\r\n const hovering = new Float32Array(size);\r\n const gpuIndices = new Int32Array(size);\r\n const uvs = new Float32Array(size * 2);\r\n\r\n sceneViewTags.forEach((tag, i) => {\r\n const coordinate = tag.position.scene;\r\n\r\n this.corners.forEach((corner, cornerNumber) => {\r\n const tagIndex = ((this.corners.length * i) + cornerNumber) * 3;\r\n const points = this.vertices[corner];\r\n\r\n positions[tagIndex] = points.x + coordinate.x;\r\n positions[tagIndex + 1] = points.y + coordinate.y;\r\n positions[tagIndex + 2] = points.z + coordinate.z;\r\n });\r\n\r\n this.uvs.forEach((uv, j) => {\r\n uvs[(this.uvs.length * i) + j] = uv;\r\n });\r\n });\r\n\r\n const geometry = new BufferGeometry();\r\n\r\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\r\n geometry.setAttribute('selected', new BufferAttribute(selected, 1));\r\n geometry.setAttribute('hovering', new BufferAttribute(hovering, 1));\r\n geometry.setAttribute('gpu_index', new BufferAttribute(gpuIndices, 1));\r\n geometry.setAttribute('uv', new BufferAttribute(uvs, 2));\r\n\r\n const tagMaterial = new TagMaterial(file.texture, file.size, false);\r\n const standardMesh = new TagMesh(geometry, tagMaterial, sceneViewTags);\r\n this.scene.add(standardMesh);\r\n\r\n const pickingMaterial = new TagMaterial(file.texture, file.size, true);\r\n const pickingMesh = new TagMesh(geometry, pickingMaterial, sceneViewTags);\r\n this.picker.add(pickingMesh);\r\n\r\n this.standardMeshes.push(standardMesh);\r\n this.pickingMeshes.push(pickingMesh);\r\n });\r\n\r\n this.updateUniforms();\r\n this.updatePicker();\r\n }\r\n\r\n updatePicker() {\r\n this.picker.needsUpdate = true;\r\n }\r\n\r\n public updateUniforms() {\r\n if (this.numberOfTags === 0) return;\r\n\r\n const camera = this.viewer.camera;\r\n if (!camera) return;\r\n\r\n const rotation = camera.rotation.toVector3();\r\n const cameraLoading = this.viewer.initialCameraLoading;\r\n const drawDistance = this.drawDistance;\r\n\r\n // Set mesh visibility\r\n this.meshes.forEach(mesh => {\r\n mesh.visible = !cameraLoading;\r\n });\r\n\r\n this.materials.forEach((material: TagMaterial) => {\r\n material.cameraRotation = rotation;\r\n material.drawDistance = drawDistance;\r\n material.windowHeight = window.innerHeight;\r\n material.fov = MathUtils.degToRad(camera.fov);\r\n material.timeStamp = performance.now() % 1000;\r\n material.needsUpdate = true;\r\n });\r\n }\r\n\r\n tagFromPickerIndex(mesh: TagMesh, index: number) {\r\n if (!mesh) return;\r\n\r\n const attributes = mesh.geometry.attributes;\r\n const gpuIndex = attributes.gpu_index.array as Array;\r\n const arrayIndex = gpuIndex.indexOf(index);\r\n const tagIndex = Math.floor(arrayIndex / this.numVertices);\r\n\r\n return mesh.tags[tagIndex] as TagItem;\r\n }\r\n\r\n getPickerResults(event): TagItem {\r\n this.picker.update();\r\n\r\n const value = this.picker.value(event);\r\n const mesh = this.picker.getSelectedObject(value) as TagMesh;\r\n const tag = this.tagFromPickerIndex(mesh, value);\r\n\r\n if (tag) {\r\n this.setHovering(tag.id);\r\n } else {\r\n this.setHovering(null);\r\n }\r\n\r\n return tag;\r\n }\r\n\r\n setHovering(tagID: string) {\r\n this.meshes.forEach(mesh => {\r\n const attributes = mesh.geometry.attributes;\r\n const hovering = attributes.hovering.array as Array;\r\n const index = mesh.tags.map(tag => tag.id).indexOf(tagID);\r\n hovering.fill(0.0);\r\n\r\n const baseIndex = index * this.numVertices;\r\n for (let i = 0; i < this.numVertices; i++) {\r\n if (baseIndex < 0) continue;\r\n hovering[baseIndex + i] = 1.0;\r\n }\r\n\r\n attributes.hovering.needsUpdate = true;\r\n });\r\n }\r\n\r\n setSelected(tagID: string, timeoutSeconds: number) {\r\n clearTimeout(this.flashTimeout);\r\n\r\n this.meshes.forEach(mesh => {\r\n const attributes = mesh.geometry.attributes;\r\n const selected = attributes.selected.array as Array;\r\n const index = mesh.tags.map(tag => tag.id).indexOf(tagID);\r\n selected.fill(0.0);\r\n\r\n const baseIndex = index * this.numVertices;\r\n for (let i = 0; i < this.numVertices; i++) {\r\n if (baseIndex < 0) continue;\r\n selected[baseIndex + i] = 1.0;\r\n }\r\n\r\n attributes.selected.needsUpdate = true;\r\n });\r\n\r\n if (!tagID) return;\r\n\r\n this.flashTimeout = setTimeout(() => {\r\n this.setSelected(null, timeoutSeconds);\r\n }, timeoutSeconds * 1000);\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent) {\r\n if (event.mouseMoved) return false;\r\n\r\n if (event.isLeftClick) {\r\n const tag = this.getPickerResults(event);\r\n\r\n if (tag) {\r\n const selectedTagID = tag.id;\r\n this.viewer.showTagDetails(selectedTagID);\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n if (event.mouseMoved) return false;\r\n if (this.numberOfTags === 0) return false;\r\n\r\n const tag = this.getPickerResults(event);\r\n\r\n if (tag) {\r\n const selectedTagID = tag.id;\r\n let tooltipText = this.tagsHandler\r\n .getTooltipText(selectedTagID);\r\n setViewerTooltip(tooltipText);\r\n return true;\r\n }\r\n\r\n clearViewerTooltip();\r\n return false;\r\n }\r\n\r\n update() {\r\n this.updateUniforms();\r\n }\r\n}\r\n","import { MapBrowserEvent, Map as OLMap } from 'ol/index';\r\nimport {\r\n Fill,\r\n Style,\r\n Text,\r\n Icon,\r\n Stroke\r\n} from 'ol/style';\r\nimport { Point } from 'ol/geom';\r\nimport { getTagTexturePath } from \"../textures/tag-icons\";\r\nimport { clearAerialTooltip, setAerialTooltip } from \"../viewer\";\r\nimport { TagFeature } from \"../aerial\";\r\nimport { TagFile, TagsHandler } from \".\";\r\nimport { Cluster, Vector as VectorSource } from 'ol/source';\r\nimport { Layer, Vector as VectorLayer } from 'ol/layer';\r\nimport { t } from '../../localization';\r\n\r\nconst tagIconSize = 24;\r\n\r\nexport class AerialTags {\r\n private tagsHandler: TagsHandler;\r\n private mapSource: VectorSource;\r\n private mapLayer: VectorLayer;\r\n private styleCache = {};\r\n public hovering = false;\r\n\r\n constructor(tagsHandler: TagsHandler) {\r\n this.tagsHandler = tagsHandler;\r\n this.mapSource = new VectorSource();\r\n\r\n this.mapLayer = new VectorLayer({\r\n zIndex: 2,\r\n source: new Cluster({\r\n source: this.mapSource,\r\n }),\r\n style: feature => {\r\n return this.getClusterStyle(feature);\r\n },\r\n });\r\n\r\n this.map.addLayer(this.mapLayer);\r\n }\r\n\r\n get map(): OLMap {\r\n const viewer = this.tagsHandler.viewer;\r\n return viewer.minimap.map;\r\n }\r\n\r\n get numberOfTags() {\r\n return this.mapSource.getFeatures().length;\r\n }\r\n\r\n public onMouseMove(event: MapBrowserEvent) {\r\n if (this.numberOfTags === 0) return;\r\n\r\n const features = this.getFeatureForEvent(event);\r\n this.hovering = features.length > 0;\r\n\r\n if (features.length === 0) {\r\n clearAerialTooltip();\r\n } else if (features.length === 1) {\r\n const selected = features[0];\r\n let tooltipText = this.tagsHandler\r\n .getTooltipText(selected.tagID);\r\n\r\n setAerialTooltip(tooltipText);\r\n } else {\r\n setAerialTooltip([\r\n t(\"tags.multiple-tags\", {\r\n count: features.length\r\n })\r\n ]);\r\n }\r\n }\r\n\r\n getFeatureForEvent(event: MapBrowserEvent): TagFeature[] {\r\n const clusters = this.map.getFeaturesAtPixel(event.pixel, {\r\n layerFilter: (layer: Layer) => layer === this.mapLayer\r\n });\r\n\r\n const features = clusters.reduce((previous, current) =>\r\n [...previous, ...current.get('features')], []);\r\n\r\n return features;\r\n }\r\n\r\n getClusterStyle(feature) {\r\n const features = feature.get('features');\r\n const size = features.length;\r\n\r\n let tagScale = 0;\r\n const texturePaths = {};\r\n features.forEach((feature: TagFeature) => {\r\n const texture = feature.texture;\r\n const texturePath = getTagTexturePath(texture);\r\n tagScale = Math.max(tagScale, feature.size);\r\n\r\n if (!(texturePath in texturePaths)) {\r\n texturePaths[texturePath] = 0;\r\n }\r\n texturePaths[texturePath] += 1;\r\n });\r\n\r\n const mostFrequent = Object.keys(texturePaths)\r\n .sort((a,b) => texturePaths[a] - texturePaths[b])\r\n .reverse()\r\n .slice(0, 3);\r\n\r\n // Unique attributes that determines if we need a new style\r\n const attributes = [size, ...mostFrequent, tagScale];\r\n const key = attributes.join(\"-\");\r\n\r\n let style = this.styleCache[key];\r\n\r\n if (!style) {\r\n const strokeColor = '#000000';\r\n const textColor = '#FFFFFF';\r\n const combinedStyles = [];\r\n const iconSize = tagIconSize *tagScale;\r\n\r\n // First texture in feature cluster\r\n combinedStyles.push(new Style({\r\n image: new Icon({\r\n src: mostFrequent[0],\r\n width: iconSize,\r\n height: iconSize,\r\n anchor: [0.5, 1],\r\n anchorXUnits: 'fraction',\r\n anchorYUnits: 'fraction'\r\n })\r\n }));\r\n\r\n // Second texture in feature cluster\r\n if (mostFrequent[1]) {\r\n combinedStyles.push(new Style({\r\n image: new Icon({\r\n src: mostFrequent[1],\r\n width: iconSize,\r\n height: iconSize,\r\n anchor: [0.5 + 0.2, 1],\r\n anchorXUnits: 'fraction',\r\n anchorYUnits: 'fraction'\r\n })\r\n }));\r\n }\r\n\r\n // Third texture in feature cluster\r\n if (mostFrequent[2]) {\r\n combinedStyles.push(new Style({\r\n image: new Icon({\r\n src: mostFrequent[2],\r\n width: iconSize,\r\n height: iconSize,\r\n anchor: [0.5 + 0.4, 1],\r\n anchorXUnits: 'fraction',\r\n anchorYUnits: 'fraction'\r\n })\r\n }));\r\n }\r\n\r\n combinedStyles.reverse();\r\n\r\n combinedStyles.push(new Style({\r\n text: new Text({\r\n text: size > 1 ? size.toString() : \"\",\r\n offsetY: -15,\r\n offsetX: 7.5,\r\n scale: 1.25,\r\n stroke: new Stroke({\r\n color: strokeColor,\r\n width: 3\r\n }),\r\n fill: new Fill({\r\n color: textColor\r\n }),\r\n }),\r\n }));\r\n\r\n style = [...combinedStyles];\r\n this.styleCache[key] = style;\r\n }\r\n\r\n return style;\r\n }\r\n\r\n reconcile(files: TagFile[]) {\r\n const features = [];\r\n\r\n files.forEach(file => {\r\n file.tags.forEach(tag => {\r\n if (!tag.visible) return;\r\n\r\n const point = new Point(tag.position.aerial);\r\n const feature = new TagFeature(\r\n tag.id, tag.texture,\r\n tag.size, point\r\n );\r\n\r\n features.push(feature);\r\n });\r\n });\r\n\r\n this.mapSource.clear();\r\n this.mapSource.addFeatures(features);\r\n }\r\n}","import { Draw } from \"ol/interaction\";\r\nimport { Vector as VectorSource } from \"ol/source\";\r\nimport { Layer, Vector as VectorLayer } from \"ol/layer\";\r\nimport { TagsHandler } from \".\";\r\nimport { setAerialTooltip } from \"../viewer\";\r\nimport { createBox, createRegularPolygon, GeometryFunction } from \"ol/interaction/Draw\";\r\nimport { Circle, Fill, Stroke, Style } from \"ol/style\";\r\nimport { Feature } from \"ol\";\r\nimport { CustomMouseEvent } from \"../controls\";\r\nimport { t } from \"../../localization\";\r\nimport { AnnotationDrawType, AnnotationSize } from \"../../types/tags\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport { TagAnnotation } from \"../../redux/assets-slice\";\r\nimport { withOpacity } from \"../utilities\";\r\nimport GeoJSON from 'ol/format/GeoJSON';\r\nimport { Type } from \"ol/geom/Geometry\";\r\nimport { Polygon } from \"ol/geom\";\r\n\r\nconst format = new GeoJSON();\r\n\r\nexport class TagAnnotations {\r\n private tagsHandler: TagsHandler;\r\n private type: AnnotationDrawType;\r\n private draw: Draw;\r\n private sketch: Feature;\r\n public enabled = false;\r\n public drawing = false;\r\n private hitTolerance = 10;\r\n private color = \"#FF0000\";\r\n private size = AnnotationSize.Medium;\r\n private annotations: TagAnnotation[] = []\r\n private mapLayer: VectorLayer;\r\n private mapSource: VectorSource;\r\n\r\n constructor(tagsHandler: TagsHandler) {\r\n this.tagsHandler = tagsHandler;\r\n\r\n this.mapSource = new VectorSource({\r\n wrapX: false,\r\n });\r\n\r\n this.mapLayer = new VectorLayer({\r\n source: this.mapSource,\r\n style: feature => {\r\n const color = feature.get(\"color\") as string;\r\n const size = feature.get(\"size\") as number;\r\n return this.getLayerStyle(color, size, false);\r\n }\r\n });\r\n }\r\n\r\n get erasing() {\r\n return this.type === AnnotationDrawType.Eraser;\r\n }\r\n\r\n get viewer() {\r\n return this.tagsHandler.viewer;\r\n }\r\n\r\n get minimap() {\r\n return this.viewer.minimap;\r\n }\r\n\r\n get map() {\r\n return this.minimap.map;\r\n }\r\n\r\n get startTooltip() {\r\n if (this.type === AnnotationDrawType.Eraser) {\r\n return [t('tags.click_to_erase_annotation')];\r\n }\r\n\r\n return [\r\n t('tags.click_to_start_annotation')\r\n ];\r\n }\r\n\r\n get moreTooltip() {\r\n const isShape = (this.type === AnnotationDrawType.Rectangle)\r\n || (this.type === AnnotationDrawType.Circle)\r\n || (this.type === AnnotationDrawType.Star);\r\n\r\n if (this.type === AnnotationDrawType.Polygon) {\r\n return [\r\n t('tags.click_to_add_more_points'),\r\n t('tags.double-click_to_finish'),\r\n t('tags.right-click_to_cancel')\r\n ];\r\n } else if (this.type === AnnotationDrawType.PolygonFreeHand) {\r\n return [\r\n t('tags.click_and_hold_to_draw_polygon')\r\n ];\r\n } else if (this.type === AnnotationDrawType.LineString) {\r\n return [\r\n t('tags.click_to_add_more_points'),\r\n t('tags.double-click_to_finish'),\r\n t('tags.right-click_to_cancel')\r\n ];\r\n } else if (this.type === AnnotationDrawType.LineStringFreeHand) {\r\n return [\r\n t('tags.click_and_hold_to_draw_line')\r\n ];\r\n } else if (isShape) {\r\n return [\r\n t('tags.click_to_finish'),\r\n t('tags.right-click_to_cancel')\r\n ];\r\n } else if (this.type === AnnotationDrawType.Eraser) {\r\n return [\r\n t('tags.click_to_erase_annotation')\r\n ];\r\n }\r\n\r\n return [];\r\n }\r\n\r\n setState(state: boolean) {\r\n if (state === this.enabled) return;\r\n this.enabled = state;\r\n\r\n if (state) {\r\n this.map.addLayer(this.mapLayer);\r\n this.mapSource.clear();\r\n } else {\r\n this.map.removeLayer(this.mapLayer);\r\n this.reset();\r\n }\r\n }\r\n\r\n reset() {\r\n this.drawing = false;\r\n this.removeInteraction();\r\n this.mapSource.clear();\r\n this.annotations = [];\r\n }\r\n\r\n load(annotations: TagAnnotation[]) {\r\n this.annotations = annotations ? annotations : [];\r\n\r\n const features = this.annotations.map(annotation => {\r\n const {definition} = annotation;\r\n const feature = format.readFeature(definition) as Feature;\r\n return feature;\r\n });\r\n\r\n this.mapSource.clear();\r\n this.mapSource.addFeatures(features);\r\n }\r\n\r\n getAnnotations() {\r\n return this.annotations;\r\n }\r\n\r\n /** @private */\r\n removeInteraction() {\r\n if (!this.draw) return;\r\n this.map.removeInteraction(this.draw);\r\n this.draw = null;\r\n }\r\n\r\n /** @private */\r\n addInteraction() {\r\n this.removeInteraction();\r\n\r\n if (this.type === AnnotationDrawType.Polygon) {\r\n this.draw = this.getDrawTool({type: \"Polygon\"});\r\n } else if (this.type === AnnotationDrawType.PolygonFreeHand) {\r\n this.draw = this.getDrawTool({type: \"Polygon\", freehand: true});\r\n } else if (this.type === AnnotationDrawType.LineString) {\r\n this.draw = this.getDrawTool({type: \"LineString\"});\r\n } else if (this.type === AnnotationDrawType.LineStringFreeHand) {\r\n this.draw = this.getDrawTool({type: \"LineString\", freehand: true});\r\n } else if (this.type === AnnotationDrawType.Circle) {\r\n this.draw = this.getDrawTool({\r\n type: \"Circle\",\r\n geometryFunction: createRegularPolygon()\r\n });\r\n } else if (this.type === AnnotationDrawType.Rectangle) {\r\n this.draw = this.getDrawTool({\r\n type: \"Circle\",\r\n geometryFunction: createBox()\r\n });\r\n } else if (this.type === AnnotationDrawType.Star) {\r\n this.draw = this.getDrawTool({\r\n type: \"Circle\",\r\n geometryFunction: starGeometryFunction\r\n });\r\n } else {\r\n this.draw = null;\r\n }\r\n\r\n if (!this.draw) return;\r\n\r\n this.map.addInteraction(this.draw);\r\n\r\n this.draw.on('drawstart', event => {\r\n this.sketch = event.feature;\r\n });\r\n\r\n this.draw.on('drawend', (event) => {\r\n this.onDrawEnd(event);\r\n });\r\n }\r\n\r\n onDrawEnd(event) {\r\n this.sketch = null;\r\n\r\n setAerialTooltip(this.startTooltip);\r\n\r\n const feature = event.feature;\r\n const annotationID = nanoid();\r\n feature.set(\"id\", annotationID);\r\n feature.set(\"color\", this.color);\r\n feature.set(\"size\", this.size);\r\n\r\n const definition = format.writeFeatureObject(feature);\r\n\r\n const annotation = {\r\n id: annotationID,\r\n definition\r\n } as TagAnnotation;\r\n\r\n this.annotations.push(annotation);\r\n }\r\n\r\n setType(type: AnnotationDrawType) {\r\n this.type = type;\r\n if (!this.drawing) return;\r\n this.addInteraction();\r\n }\r\n\r\n setColor(color: string) {\r\n this.color = color;\r\n this.setType(this.type);\r\n }\r\n\r\n setSize(size: AnnotationSize) {\r\n this.size = size;\r\n this.setType(this.type);\r\n }\r\n\r\n setDrawing(drawing: boolean) {\r\n this.drawing = drawing;\r\n\r\n if (drawing) {\r\n this.addInteraction();\r\n } else {\r\n this.removeInteraction();\r\n }\r\n }\r\n\r\n getDrawTool(options: {\r\n type: Type,\r\n freehand?: boolean,\r\n geometryFunction?: GeometryFunction\r\n }) {\r\n const {type, freehand=false, geometryFunction} = options;\r\n\r\n const style = this.getLayerStyle(\r\n this.color, this.size, true);\r\n\r\n const condition = event => {\r\n return event.originalEvent.button === 0;\r\n };\r\n\r\n return new Draw({\r\n source: this.mapSource,\r\n type,\r\n freehand,\r\n condition,\r\n geometryFunction,\r\n style\r\n });\r\n }\r\n\r\n setLineStringTool(freehand: boolean) {\r\n const style = this.getLayerStyle(\r\n this.color, this.size, true);\r\n\r\n const condition = event => {\r\n return event.originalEvent.button === 0;\r\n };\r\n\r\n this.draw = new Draw({\r\n source: this.mapSource,\r\n type: \"LineString\",\r\n freehand,\r\n condition,\r\n style\r\n });\r\n }\r\n\r\n setRectangleTool() {\r\n const style = this.getLayerStyle(\r\n this.color, this.size, true);\r\n\r\n const condition = event => {\r\n return event.originalEvent.button === 0;\r\n };\r\n\r\n this.draw = new Draw({\r\n source: this.mapSource,\r\n type: \"Circle\",\r\n geometryFunction: createBox(),\r\n condition,\r\n style\r\n });\r\n }\r\n\r\n getLayerStyle(color: string, size: number, dashed: boolean) {\r\n const dash = dashed ? [10, 10] : undefined;\r\n const style = new Style({\r\n fill: new Fill({\r\n color: withOpacity(color, 0.2)\r\n }),\r\n stroke: new Stroke({\r\n color: color,\r\n width: size,\r\n lineDash: dash\r\n }),\r\n image: new Circle({\r\n radius: size + 1,\r\n stroke: new Stroke({\r\n color: 'rgba(0, 0, 0, 0.7)'\r\n }),\r\n fill: new Fill({\r\n color: color\r\n })\r\n })\r\n });\r\n\r\n return style;\r\n }\r\n\r\n onMouseMove() {\r\n if (!this.enabled) return;\r\n\r\n const tooltip = this.sketch\r\n ? this.moreTooltip\r\n : this.startTooltip;\r\n\r\n setAerialTooltip(tooltip);\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent) {\r\n if (!this.enabled || !this.drawing) return false;\r\n\r\n if (event.isRightClick) {\r\n this.setType(this.type);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMapClick(event) {\r\n if (!this.enabled || !this.erasing) return false;\r\n\r\n const features = this.map.getFeaturesAtPixel(event.pixel, {\r\n layerFilter: (layer: Layer) => layer === this.mapLayer,\r\n hitTolerance: this.hitTolerance\r\n }) as Feature[];\r\n\r\n for (let feature of features) {\r\n // Remove from map source\r\n this.mapSource.removeFeature(feature);\r\n\r\n // Remove from annotations array\r\n const toRemove = feature.get(\"id\");\r\n this.annotations = this.annotations\r\n .filter(annotation => annotation.id !== toRemove);\r\n }\r\n\r\n return features.length > 0;\r\n }\r\n}\r\n\r\nconst starGeometryFunction = (coordinates, geometry) => {\r\n const center = coordinates[0];\r\n const last = coordinates[coordinates.length - 1];\r\n const dx = center[0] - last[0];\r\n const dy = center[1] - last[1];\r\n const radius = Math.sqrt(dx * dx + dy * dy);\r\n const rotation = Math.atan2(dy, dx);\r\n const newCoordinates = [];\r\n const numPoints = 12;\r\n\r\n for (let i = 0; i < numPoints; ++i) {\r\n const angle = rotation + (i * 2 * Math.PI) / numPoints;\r\n const fraction = i % 2 === 0 ? 1 : 0.5;\r\n const offsetX = radius * fraction * Math.cos(angle);\r\n const offsetY = radius * fraction * Math.sin(angle);\r\n newCoordinates.push([center[0] + offsetX, center[1] + offsetY]);\r\n }\r\n newCoordinates.push(newCoordinates[0].slice());\r\n\r\n if (!geometry) {\r\n geometry = new Polygon([newCoordinates]);\r\n } else {\r\n geometry.setCoordinates([newCoordinates]);\r\n }\r\n\r\n return geometry;\r\n};","export default __webpack_public_path__ + \"static/media/point.cc8fa849.png\";","import { Viewer } from \"../main\";\r\nimport {\r\n DXFFile,\r\n IFCFile,\r\n SHPFile,\r\n} from \".\";\r\nimport {\r\n AmbientLight,\r\n LineSegments,\r\n Mesh,\r\n Scene,\r\n Points,\r\n Box3,\r\n MathUtils,\r\n TextureLoader,\r\n Color,\r\n Vector3,\r\n BufferGeometry,\r\n BufferAttribute,\r\n Texture,\r\n Sprite,\r\n SpriteMaterial,\r\n LinearFilter,\r\n Camera\r\n} from \"three\";\r\nimport { Asset, AssetType, LineworkLayerData } from \"../../redux/assets-slice\";\r\nimport { getCoordinateBounds, mergeBoundingBoxes, toVector2, withOpacity } from \"../utilities\";\r\nimport {\r\n LineworkBasicMaterial,\r\n LineworkSpriteMaterial,\r\n LineworkSpriteParams\r\n} from \"../rendering\";\r\nimport spritePath from \"../textures/sprites/point.png\";\r\nimport LocalScene, {\r\n latitudeLongitude,\r\n reprojectPoints,\r\n webMercator\r\n} from \"../projections\";\r\nimport { Feature } from \"ol\";\r\nimport { Vector as VectorSource } from \"ol/source\";\r\nimport VectorTileSource from 'ol/source/VectorTile';\r\nimport VectorTileLayer from 'ol/layer/VectorTile';\r\nimport { RayCaster } from \"../ray-caster\";\r\nimport geojsonvt from 'geojson-vt';\r\nimport GeoJSON from 'ol/format/GeoJSON';\r\nimport olProjection from \"ol/proj/Projection\";\r\nimport { Circle, Fill, Stroke, Style } from \"ol/style\";\r\nimport VectorLayer from \"ol/layer/Vector\";\r\nimport VectorImageLayer from \"ol/layer/VectorImage\";\r\nimport { Projection } from \"../../redux/projections-slice\";\r\n\r\nconst maxTileZoom = 22;\r\nconst tileSize = 4096;\r\nconst tileTolerance = 3;\r\n\r\nconst format = new GeoJSON({});\r\n\r\ntype Face = [number, number, number];\r\ntype Coordinate = [number, number, number?];\r\n\r\nconst pointTexture = new TextureLoader().load(spritePath);\r\n\r\n// Data returned from geojson-vt is in tile pixel units\r\nconst tileProjection = new olProjection({\r\n code: 'TILE_PIXELS',\r\n units: 'tile-pixels',\r\n extent: [0, 0, tileSize, tileSize],\r\n});\r\n\r\nexport enum GeomType {\r\n Points = \"POINTS\",\r\n Lines = \"LINES\",\r\n Polygons = \"POLYGONS\",\r\n Text = \"TEXT\"\r\n}\r\n\r\ninterface FeatureResponse {\r\n coordinates: Coordinate[];\r\n polygonFaces: Face[];\r\n isContinuous: boolean;\r\n properties: any;\r\n}\r\n\r\nexport class LineworkText extends Sprite {\r\n constructor(material: SpriteMaterial) {\r\n super(material);\r\n }\r\n\r\n checkVisibility(camera: Camera, drawDistance: number) {\r\n const cameraPosition2D = toVector2(camera.position);\r\n const meshPosition2D = toVector2(this.position);\r\n\r\n const distance = cameraPosition2D\r\n .distanceTo(meshPosition2D);\r\n\r\n this.visible = distance <= drawDistance;\r\n }\r\n}\r\n\r\nexport class LineworkPoints extends Points {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n\r\n updateUniforms(drawDistance: number, fov: number, height: number) {\r\n const material = this.material as LineworkSpriteMaterial;\r\n material.screenHeight = height;\r\n material.fov = MathUtils.degToRad(fov);\r\n material.drawDistance = drawDistance;\r\n material.needsUpdate = true;\r\n }\r\n}\r\n\r\nexport class LineworkLine extends LineSegments {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n\r\n updateUniforms(drawDistance: number) {\r\n const material = this.material as LineworkBasicMaterial;\r\n material.drawDistance = drawDistance;\r\n }\r\n}\r\n\r\nexport class LineworkPolygon extends Mesh {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n\r\n updateUniforms(drawDistance: number) {\r\n const material = this.material as LineworkBasicMaterial;\r\n material.drawDistance = drawDistance;\r\n }\r\n}\r\n\r\nclass MapLayer {\r\n private lineworkLayer: LineworkLayer;\r\n protected type: GeomType;\r\n private layer: VectorLayer | VectorTileLayer | VectorImageLayer;\r\n\r\n constructor(lineworkLayer: LineworkLayer) {\r\n this.lineworkLayer = lineworkLayer;\r\n }\r\n\r\n get map() {\r\n return this.lineworkLayer.map;\r\n }\r\n\r\n get color() {\r\n return this.lineworkLayer.color;\r\n }\r\n\r\n get visible() {\r\n return this.lineworkLayer.visible;\r\n }\r\n\r\n get style() {\r\n console.warn(\"Not implemented\");\r\n return null;\r\n }\r\n\r\n async reprojectFeatures(features: FeatureResponse[], projection: Projection) {\r\n const coordinates = [];\r\n features.forEach(feature => {\r\n feature.coordinates.forEach(coordinate => {\r\n coordinates.push(coordinate);\r\n });\r\n });\r\n\r\n const reprojected = await reprojectPoints(\r\n coordinates, LocalScene.dataProjection, projection);\r\n\r\n let startIndex = 0;\r\n let endIndex = 0;\r\n\r\n features.forEach(feature => {\r\n endIndex += feature.coordinates.length;\r\n const slice = reprojected.slice(startIndex, endIndex);\r\n feature.coordinates = slice;\r\n startIndex = endIndex;\r\n });\r\n\r\n return features;\r\n }\r\n\r\n async addCoordinates(features: FeatureResponse[]) {\r\n let numCoordinates = 0;\r\n features.forEach(feature => {\r\n numCoordinates += feature.coordinates.length;\r\n });\r\n\r\n const useVectorTile = numCoordinates > 100000;\r\n const useImageLayer = numCoordinates > 10000;\r\n\r\n const outProjection = useVectorTile\r\n ? latitudeLongitude\r\n : webMercator;\r\n\r\n // Reproject all features for this layer\r\n features = await this.reprojectFeatures(features, outProjection);\r\n\r\n const geojsonFeatures = this.getFeatures(features);\r\n\r\n const geojsonObject = {\r\n type: 'FeatureCollection',\r\n features: geojsonFeatures,\r\n };\r\n\r\n if (useVectorTile) {\r\n this.generateVectorTileLayer(geojsonObject);\r\n } else if (useImageLayer) {\r\n this.generateImageLayer(geojsonObject);\r\n } else {\r\n this.generateVectorLayer(geojsonObject);\r\n }\r\n\r\n // Add new map layer\r\n this.map.addLayer(this.layer);\r\n }\r\n\r\n generateVectorTileLayer(geojsonObject) {\r\n const tileIndex = geojsonvt(geojsonObject, {\r\n extent: tileSize,\r\n maxZoom: maxTileZoom,\r\n tolerance: tileTolerance,\r\n // force pre-computed tiles up to indexMaxZoom\r\n indexMaxZoom: 10,\r\n indexMaxPoints: 0,\r\n });\r\n\r\n const source = new VectorTileSource({\r\n tileUrlFunction: (tileCoord) => {\r\n return JSON.stringify(tileCoord);\r\n },\r\n tileLoadFunction: (tile: any, url) => {\r\n // Get data for this tile\r\n const tileCoord = JSON.parse(url);\r\n const data = tileIndex.getTile(...tileCoord);\r\n\r\n // Convert to openlayers style feature collection\r\n const geojson = JSON.stringify({\r\n type: 'FeatureCollection',\r\n features: data ? data.features : [],\r\n }, replacer);\r\n\r\n // Convert from TILE_PIXELS to web mercator\r\n const features = format.readFeatures(geojson, {\r\n extent: source.getTileGrid().getTileCoordExtent(tileCoord),\r\n dataProjection: tileProjection,\r\n featureProjection: \"EPSG:3857\"\r\n }) as Feature[];\r\n\r\n tile.setFeatures(features);\r\n }\r\n });\r\n\r\n this.layer = new VectorTileLayer({\r\n source: source,\r\n visible: this.visible,\r\n style: this.style,\r\n zIndex: 3\r\n });\r\n }\r\n\r\n generateImageLayer(geojsonObject) {\r\n const features = format.readFeatures(geojsonObject);\r\n\r\n const source = new VectorSource({\r\n wrapX: false,\r\n features: features as Feature[],\r\n });\r\n\r\n this.layer = new VectorImageLayer({\r\n source: source,\r\n visible: this.visible,\r\n style: this.style,\r\n zIndex: 1\r\n });\r\n }\r\n\r\n generateVectorLayer(geojsonObject) {\r\n const features = format.readFeatures(geojsonObject);\r\n\r\n const source = new VectorSource({\r\n wrapX: false,\r\n features: features as Feature[],\r\n });\r\n\r\n this.layer = new VectorLayer({\r\n source: source,\r\n visible: this.visible,\r\n style: this.style,\r\n zIndex: 2\r\n });\r\n }\r\n\r\n getFeatures(features: FeatureResponse[]) {\r\n console.warn(\"Not implemented\");\r\n return [];\r\n }\r\n\r\n setVisible(state: boolean) {\r\n if (!this.layer) return;\r\n this.layer.setVisible(state);\r\n }\r\n\r\n updateStyle() {\r\n if (!this.layer) return;\r\n this.layer.setStyle(this.style);\r\n }\r\n\r\n destroy() {\r\n if (!this.layer) return;\r\n this.map.removeLayer(this.layer);\r\n this.layer.dispose();\r\n }\r\n}\r\n\r\nclass PointsLayer extends MapLayer {\r\n protected type = GeomType.Points;\r\n\r\n private minRadius = 1;\r\n private maxRadius = 5;\r\n\r\n private minZoom = 10;\r\n private maxZoom = 18;\r\n\r\n private styleCache = {}\r\n\r\n get style() {\r\n return () => {\r\n const zoom = this.map.getView().getZoom();\r\n const styleKey = `${this.color}-${zoom}`;\r\n\r\n if (!this.styleCache[styleKey]) {\r\n const scale = (zoom - this.minZoom) / (this.maxZoom - this.minZoom);\r\n\r\n let pointSize = this.minRadius + scale\r\n * (this.maxRadius - this.minRadius);\r\n pointSize = Math.min(pointSize, this.maxRadius);\r\n pointSize = Math.max(pointSize, this.minRadius);\r\n\r\n this.styleCache[styleKey] = new Style({\r\n image: new Circle({\r\n radius: pointSize,\r\n fill: new Fill({\r\n color: this.color,\r\n }),\r\n stroke: new Stroke({\r\n color: \"#000000\",\r\n width: 1\r\n })\r\n })\r\n });\r\n }\r\n\r\n return this.styleCache[styleKey];\r\n };\r\n }\r\n\r\n getFeatures(features: FeatureResponse[]) {\r\n return features.map(feature => {\r\n const {coordinates, properties} = feature;\r\n\r\n return {\r\n type: \"Feature\",\r\n geometry: {\r\n type: \"Point\",\r\n coordinates: coordinates[0]\r\n },\r\n properties: properties\r\n };\r\n });\r\n }\r\n}\r\n\r\nclass LineLayer extends MapLayer {\r\n protected type = GeomType.Lines;\r\n\r\n get style() {\r\n return new Style({\r\n stroke: new Stroke({\r\n color: this.color,\r\n width: 1,\r\n }),\r\n fill: new Fill({\r\n color: this.color,\r\n })\r\n });\r\n }\r\n\r\n getFeatures(features: FeatureResponse[]) {\r\n return features.map(feature => {\r\n const {coordinates, properties} = feature;\r\n\r\n return {\r\n type: \"Feature\",\r\n geometry: {\r\n type: \"LineString\",\r\n coordinates: coordinates\r\n },\r\n properties: properties\r\n };\r\n });\r\n }\r\n}\r\n\r\nclass PolygonLayer extends MapLayer {\r\n protected type = GeomType.Polygons;\r\n private maxVertices = 500000;\r\n\r\n get style() {\r\n return new Style({\r\n stroke: new Stroke({\r\n color: \"#000000\",\r\n width: 1,\r\n }),\r\n fill: new Fill({\r\n color: withOpacity(this.color, 0.5),\r\n })\r\n });\r\n }\r\n\r\n /** @private */\r\n getFeature(coordinates, properties) {\r\n return {\r\n type: \"Feature\",\r\n geometry: {\r\n type: \"Polygon\",\r\n coordinates: [coordinates]\r\n },\r\n properties: properties\r\n };\r\n }\r\n\r\n /** @private */\r\n getOutline(coordinates, properties) {\r\n const {min, max} = getCoordinateBounds(coordinates);\r\n\r\n const outline = [\r\n [min.x, min.y, 0],\r\n [min.x, max.y, 0],\r\n [max.x, max.y, 0],\r\n [max.x, min.y, 0],\r\n [min.x, min.y, 0]\r\n ];\r\n\r\n return this.getFeature(outline, properties);\r\n }\r\n\r\n getFeatures(features: FeatureResponse[]) {\r\n let geojsonFeatures = [];\r\n\r\n for (let feature of features) {\r\n const {coordinates, polygonFaces, isContinuous, properties} = feature;\r\n\r\n if (coordinates.length > this.maxVertices) {\r\n console.warn(\"Using simplified polygon outline\", feature);\r\n const mapFeature = this.getOutline(coordinates, properties);\r\n geojsonFeatures.push(mapFeature);\r\n continue;\r\n }\r\n\r\n const isQuad = (coordinates.length === 4)\r\n && (polygonFaces.length === 2);\r\n\r\n if (isContinuous || isQuad) {\r\n // Return one feature for the polygon\r\n const mapFeature = this.getFeature(coordinates, properties);\r\n geojsonFeatures.push(mapFeature);\r\n } else {\r\n // Return one feature for each face\r\n polygonFaces.forEach(face => {\r\n const faceSlice = face.map(index => coordinates[index]);\r\n const mapFeature = this.getFeature(faceSlice, properties);\r\n geojsonFeatures.push(mapFeature);\r\n });\r\n }\r\n };\r\n\r\n return geojsonFeatures;\r\n }\r\n}\r\n\r\nexport class LineworkLayer {\r\n public id: string;\r\n public visible: boolean;\r\n public name: string;\r\n public file: LineworkFile\r\n public color: string;\r\n protected enabled = true;\r\n\r\n private mapLayers: MapLayer[] = [];\r\n private standardMeshes = [];\r\n private pickingMeshes = [];\r\n\r\n constructor(file: LineworkFile, layer: LineworkLayerData) {\r\n this.file = file;\r\n this.id = layer.id;\r\n this.visible = layer.visible;\r\n this.name = layer.name;\r\n this.color = layer.color;\r\n }\r\n\r\n get scene() {\r\n return this.file.scene;\r\n }\r\n\r\n get map() {\r\n return this.file.map;\r\n }\r\n\r\n get picker() {\r\n return this.file.picker;\r\n }\r\n\r\n get viewer() {\r\n return this.file.viewer;\r\n }\r\n\r\n get meshes() {\r\n return [...this.standardMeshes, ...this.pickingMeshes];\r\n }\r\n\r\n get meshColor() {\r\n return new Color(parseInt(this.color.slice(1), 16));\r\n }\r\n\r\n async addNewGeometry(data) {\r\n const keys = Object.keys(data) as GeomType[];\r\n\r\n for (let geomType of keys) {\r\n const features = data[geomType] as FeatureResponse[];\r\n\r\n if (geomType === GeomType.Text) {\r\n this.addTextData(features);\r\n continue;\r\n }\r\n\r\n await this.addSceneData(features, geomType);\r\n await this.addAerialData(features, geomType);\r\n }\r\n }\r\n\r\n /** @private */\r\n addTextData(features) {\r\n features.forEach(feature => {\r\n const {coordinates, properties} = feature;\r\n const offset = new Vector3(...coordinates[0]);\r\n const text = properties.text;\r\n\r\n const { texture, textScale } = generateTexture(text);\r\n\r\n const material = new SpriteMaterial({\r\n map: texture,\r\n transparent: false,\r\n alphaTest: 0.6,\r\n color: this.meshColor,\r\n });\r\n\r\n const standardMesh = new LineworkText(material);\r\n standardMesh.scale.copy(textScale);\r\n\r\n // Convert offset to meters\r\n offset.multiplyScalar(LocalScene.dataToMeters);\r\n\r\n // Move model to scene coordinates\r\n const shift = LocalScene.offsetToScene(offset);\r\n standardMesh.position.copy(shift);\r\n\r\n if (!this.enabled) return;\r\n\r\n // Scene view mesh\r\n this.standardMeshes.push(standardMesh);\r\n this.scene.add(standardMesh);\r\n\r\n // Initial visibility is false\r\n standardMesh.visible = false;\r\n });\r\n }\r\n\r\n /** @private */\r\n async addAerialData(features: FeatureResponse[], geomType: GeomType) {\r\n if (features.length === 0) return;\r\n\r\n let layer: MapLayer;\r\n\r\n if (geomType === GeomType.Points) {\r\n layer = new PointsLayer(this);\r\n } else if (geomType === GeomType.Polygons) {\r\n layer = new PolygonLayer(this);\r\n } else if (geomType === GeomType.Lines) {\r\n layer = new LineLayer(this);\r\n }\r\n\r\n if (!layer) return;\r\n\r\n await layer.addCoordinates(features);\r\n this.mapLayers.push(layer);\r\n }\r\n\r\n /** @private */\r\n async addSceneData(features: FeatureResponse[], geomType: GeomType) {\r\n if (features.length === 0) return;\r\n\r\n // Create flattened coordinates array\r\n const coordinates = [];\r\n features.forEach(feature => {\r\n feature.coordinates.forEach(coordinate => {\r\n coordinates.push(coordinate);\r\n });\r\n });\r\n\r\n // Not required for 2D data\r\n if (coordinates[0].length < 3) return;\r\n\r\n // Subtract offset to handle float32 issues\r\n const flatCoordinates = [];\r\n const offset = new Vector3(...coordinates[0]);\r\n coordinates.forEach(coordinate => {\r\n // Make sure height exists to avoid errors\r\n if (coordinate.length === 2) {\r\n coordinate.push(0);\r\n }\r\n\r\n flatCoordinates.push(\r\n coordinate[0] - offset.x,\r\n coordinate[1] - offset.y,\r\n coordinate[2] - offset.z\r\n );\r\n });\r\n\r\n const bufferGeometry = new BufferGeometry();\r\n const positions = new Float32Array(flatCoordinates);\r\n const gpuIndex = new Int32Array(flatCoordinates.length / 3);\r\n\r\n bufferGeometry.setAttribute('position', new BufferAttribute(positions, 3));\r\n bufferGeometry.setAttribute('gpu_index', new BufferAttribute(gpuIndex, 1));\r\n bufferGeometry.computeBoundingSphere();\r\n\r\n let standardMesh;\r\n let pickingMesh;\r\n\r\n let standardMaterial: LineworkSpriteMaterial | LineworkBasicMaterial;\r\n let pickingMaterial: LineworkSpriteMaterial | LineworkBasicMaterial;\r\n\r\n if (geomType === GeomType.Points) {\r\n // Create material and mesh objects\r\n const parameters = {\r\n size: 0.10,\r\n map: pointTexture,\r\n color: this.meshColor\r\n } as LineworkSpriteParams;\r\n\r\n standardMaterial = new LineworkSpriteMaterial(parameters, false);\r\n standardMesh = new LineworkPoints(bufferGeometry, standardMaterial);\r\n\r\n pickingMaterial = new LineworkSpriteMaterial(parameters, true);\r\n pickingMesh = new LineworkPoints(bufferGeometry, pickingMaterial);\r\n } else if (geomType === GeomType.Lines) {\r\n // Create line segments with basic material\r\n const indices = this.getLineIndices(features);\r\n bufferGeometry.setIndex(indices);\r\n\r\n standardMaterial = new LineworkBasicMaterial(this.meshColor, false);\r\n standardMesh = new LineworkLine(bufferGeometry, standardMaterial);\r\n\r\n pickingMaterial = new LineworkBasicMaterial(this.meshColor, true);\r\n pickingMesh = new LineworkLine(bufferGeometry, pickingMaterial);\r\n } else if (geomType === GeomType.Polygons) {\r\n // Create polygon with basic material\r\n const indices = this.getPolygonIndices(features);\r\n bufferGeometry.setIndex(indices);\r\n\r\n standardMaterial = new LineworkBasicMaterial(this.meshColor, false);\r\n standardMesh = new LineworkPolygon(bufferGeometry, standardMaterial);\r\n\r\n pickingMaterial = new LineworkBasicMaterial(this.meshColor, true);\r\n pickingMesh = new LineworkPolygon(bufferGeometry, pickingMaterial);\r\n } else {\r\n return;\r\n }\r\n\r\n // Convert mesh to meters\r\n standardMesh.scale.setScalar(LocalScene.dataToMeters);\r\n pickingMesh.scale.setScalar(LocalScene.dataToMeters);\r\n offset.multiplyScalar(LocalScene.dataToMeters);\r\n\r\n // Move model to scene coordinates\r\n const shift = LocalScene.offsetToScene(offset);\r\n standardMesh.position.copy(shift);\r\n pickingMesh.position.copy(shift);\r\n\r\n if (!this.enabled) return;\r\n\r\n // Scene view mesh\r\n this.standardMeshes.push(standardMesh);\r\n this.scene.add(standardMesh);\r\n\r\n // Picking scene mesh\r\n this.pickingMeshes.push(pickingMesh);\r\n this.picker.add(pickingMesh);\r\n\r\n // Update visibility\r\n standardMesh.visible = this.visible;\r\n pickingMesh.visible = this.visible;\r\n }\r\n\r\n /** Generate bufferGeometry index values for polygons */\r\n getPolygonIndices(features: FeatureResponse[]) {\r\n let indices = [];\r\n let pointIndex = 0;\r\n\r\n features.forEach(segment => {\r\n const { coordinates, polygonFaces } = segment;\r\n\r\n polygonFaces.forEach(face => {\r\n indices.push(face[0] + pointIndex);\r\n indices.push(face[1] + pointIndex);\r\n indices.push(face[2] + pointIndex);\r\n });\r\n\r\n pointIndex += coordinates.length;\r\n });\r\n\r\n return indices;\r\n }\r\n\r\n /** Generate bufferGeometry index values for line segments */\r\n getLineIndices(features: FeatureResponse[]) {\r\n let geomIndex = 0;\r\n let indices = [];\r\n\r\n features.forEach(segment => {\r\n const { coordinates } = segment;\r\n\r\n for (let i=0; i < coordinates.length - 1; i++) {\r\n indices.push(geomIndex, geomIndex + 1);\r\n geomIndex = geomIndex + 1;\r\n }\r\n\r\n geomIndex = geomIndex + 1;\r\n });\r\n\r\n return indices;\r\n }\r\n\r\n removeFromScene(item) {\r\n if (!item) return;\r\n this.picker.remove(item);\r\n this.scene.remove(item);\r\n }\r\n\r\n disposeGeometry(item) {\r\n if (!item) return;\r\n item.geometry.dispose();\r\n item.material.dispose();\r\n }\r\n\r\n setVisibility(state) {\r\n this.visible = state;\r\n\r\n for (let layer of this.mapLayers) {\r\n layer.setVisible(state);\r\n }\r\n\r\n this.standardMeshes.forEach(standardMesh => {\r\n standardMesh.visible = state;\r\n });\r\n\r\n this.pickingMeshes.forEach(pickingMesh => {\r\n pickingMesh.visible = state;\r\n });\r\n }\r\n\r\n setColor(color: string) {\r\n if (this.color === color) return;\r\n\r\n this.color = color;\r\n\r\n this.standardMeshes.forEach(mesh => {\r\n const material = mesh.material;\r\n material.color = this.meshColor;\r\n material.needsUpdate = true;\r\n });\r\n\r\n for (let layer of this.mapLayers) {\r\n layer.updateStyle();\r\n }\r\n }\r\n\r\n updateMaterials() {\r\n if (!this.visible) return;\r\n\r\n const drawDistance = this.file.drawDistance;\r\n\r\n this.meshes.forEach(mesh => {\r\n if (mesh instanceof LineworkText) {\r\n mesh.checkVisibility(this.viewer.camera, drawDistance);\r\n } else if (mesh instanceof LineworkPoints) {\r\n mesh.updateUniforms(drawDistance, this.viewer.camera.fov,\r\n this.viewer.height);\r\n } else if (mesh instanceof LineworkLine) {\r\n mesh.updateUniforms(drawDistance);\r\n } else if (mesh instanceof LineworkPolygon) {\r\n mesh.updateUniforms(drawDistance);\r\n }\r\n });\r\n }\r\n\r\n destroy() {\r\n this.enabled = false;\r\n\r\n this.standardMeshes.forEach(standardMesh => {\r\n this.removeFromScene(standardMesh);\r\n this.disposeGeometry(standardMesh);\r\n });\r\n this.standardMeshes = [];\r\n\r\n this.pickingMeshes.forEach(pickingMesh => {\r\n this.removeFromScene(pickingMesh);\r\n this.disposeGeometry(pickingMesh);\r\n });\r\n this.pickingMeshes = [];\r\n\r\n for (let layer of this.mapLayers) {\r\n layer.destroy();\r\n }\r\n this.mapLayers = [];\r\n }\r\n}\r\n\r\nexport class LineworkFile {\r\n public id: string;\r\n public cadHandler: CADHandler;\r\n protected path: string;\r\n protected name: string;\r\n protected saved: boolean\r\n public boundingBox: Box3;\r\n public layers: LineworkLayer[] = [];\r\n\r\n public loaded = false;\r\n public enabled = true;\r\n public loading = false;\r\n public visible = false;\r\n public percent = 0.0;\r\n public error = false;\r\n\r\n constructor(cadHandler: CADHandler, asset: Asset) {\r\n this.id = asset.id;\r\n this.path = asset.path;\r\n this.name = asset.name;\r\n this.saved = asset.saved;\r\n this.cadHandler = cadHandler;\r\n }\r\n\r\n get viewer() {\r\n return this.cadHandler.viewer;\r\n }\r\n\r\n get scene() {\r\n return this.cadHandler.scene;\r\n }\r\n\r\n get map() {\r\n return this.cadHandler.map;\r\n }\r\n\r\n get picker() {\r\n return this.cadHandler.picker;\r\n }\r\n\r\n get drawDistance() {\r\n return this.cadHandler.drawDistance;\r\n }\r\n\r\n load() {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n destroy() {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n updateProperties(asset: Asset) {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n updateMaterials() {\r\n this.layers.forEach(layer => {\r\n layer.updateMaterials();\r\n });\r\n }\r\n\r\n updatePercent(percent) {\r\n this.percent = percent;\r\n }\r\n\r\n updatePicker() {\r\n this.picker.needsUpdate = true;\r\n }\r\n\r\n validBounds(bounds: {min: number[], max: number[]}) {\r\n return [...bounds.min, ...bounds.max]\r\n .filter(x => isFinite(x)).length === 6;\r\n };\r\n}\r\n\r\nexport class LineworkHandler {\r\n protected files: LineworkFile[] = [];\r\n protected cadHandler: CADHandler;\r\n\r\n constructor(cadHandler: CADHandler) {\r\n this.cadHandler = cadHandler;\r\n }\r\n}\r\n\r\nexport class CADHandler {\r\n public scene: Scene;\r\n public viewer: Viewer;\r\n private files: LineworkFile[] = [];\r\n private _drawDistance = 0;\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n this.initScene();\r\n }\r\n\r\n get picker() {\r\n return this.viewer.gpuPickers.default;\r\n }\r\n\r\n get camera() {\r\n return this.viewer.camera;\r\n }\r\n\r\n get map() {\r\n return this.viewer.minimap.map;\r\n }\r\n\r\n get numberOfFiles() {\r\n return this.files.length;\r\n }\r\n\r\n get combinedBoundingBox() {\r\n const boundingBoxes = this.files\r\n .map(file => file.boundingBox);\r\n\r\n return mergeBoundingBoxes(boundingBoxes);\r\n }\r\n\r\n get drawDistance() {\r\n if (this.viewer.orbitState) {\r\n return this.viewer.far;\r\n }\r\n\r\n return (this._drawDistance > 999)\r\n ? this.viewer.far\r\n : this._drawDistance;\r\n }\r\n\r\n set drawDistance(distance: number) {\r\n this._drawDistance = distance;\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n getByID(assetID: string) {\r\n return this.files.find(file => file.id === assetID);\r\n }\r\n\r\n async getProperties(event) {\r\n // NOTE: need different strategy once we allow shp/dxf files to return attributes\r\n\r\n const ifcFiles = this.files\r\n .filter(file => file instanceof IFCFile) as IFCFile[];\r\n\r\n const objects = ifcFiles\r\n .map(file => file.standardMesh)\r\n .filter(mesh => mesh?.visible);\r\n\r\n const raycaster = new RayCaster(this.viewer, event);\r\n const intersects = raycaster.intersectObjects(objects);\r\n if (intersects.length === 0) return [];\r\n\r\n const intersect = intersects[0];\r\n\r\n const selectedFile = ifcFiles.find(file => {\r\n return file.standardMesh === intersect.object;\r\n });\r\n\r\n if (!selectedFile) return [];\r\n\r\n const attributes = await selectedFile\r\n .getProperties(intersect.faceIndex);\r\n\r\n return attributes;\r\n }\r\n\r\n clearHighlightedFiles() {\r\n for (let file of this.files) {\r\n if (file instanceof IFCFile) {\r\n file.removeSubset();\r\n }\r\n }\r\n }\r\n\r\n reconcile(modelFiles: Asset[]) {\r\n const currentIDs = new Set(this.files.map(ifc => ifc.id));\r\n const newAssetIDs = new Set(modelFiles.map(ifc => ifc.id));\r\n const assetsToLoad = modelFiles.filter(ifc => !currentIDs.has(ifc.id));\r\n const filesToDelete = this.files.filter(ifc => !newAssetIDs.has(ifc.id));\r\n\r\n // TODO: move up to cadhandler, get rid of ifchandler / dxfhandler / shphandler\r\n\r\n // Delete file that need to be removed\r\n filesToDelete.forEach(file => {\r\n this.deleteFile(file);\r\n });\r\n\r\n // Add new files\r\n assetsToLoad.forEach(file => {\r\n this.addNewFile(file);\r\n });\r\n\r\n // Toggle visibility and colors for each file\r\n modelFiles.forEach(file => {\r\n this.updateProperties(file);\r\n });\r\n\r\n return assetsToLoad.length;\r\n }\r\n\r\n addNewFile(asset: Asset) {\r\n if (this.getByID(asset.id)) return;\r\n\r\n let newFile;\r\n\r\n if (asset.type === AssetType.IFC) {\r\n newFile = new IFCFile(this, asset);\r\n } else if (asset.type === AssetType.SHP) {\r\n newFile = new SHPFile(this, asset);\r\n } else if (asset.type === AssetType.DXF) {\r\n newFile = new DXFFile(this, asset);\r\n } else {\r\n return;\r\n }\r\n\r\n this.files.push(newFile);\r\n }\r\n\r\n deleteFile(file: LineworkFile) {\r\n file.destroy();\r\n\r\n const index = this.files.indexOf(file);\r\n this.files.splice(index, 1);\r\n }\r\n\r\n updateProperties(asset) {\r\n let file = this.getByID(asset.id);\r\n if (!file) return;\r\n\r\n file.updateProperties(asset);\r\n }\r\n\r\n /** Load any file waiting for conversion */\r\n loadNextfile() {\r\n for (let file of this.files) {\r\n if (file.loaded || !file.enabled || !file.visible) continue;\r\n if (file.loading) break;\r\n\r\n // Load new file\r\n file.load();\r\n break;\r\n };\r\n }\r\n\r\n updateMaterials() {\r\n this.files.forEach(file => {\r\n file.updateMaterials();\r\n });\r\n }\r\n\r\n update() {\r\n this.loadNextfile();\r\n this.updateMaterials();\r\n }\r\n}\r\n\r\nconst generateTexture = (text: string[]) => {\r\n const fontSize = 48;\r\n const lineThickness = 4;\r\n const borderThickness = 4;\r\n const margin = 5;\r\n\r\n const numLines = text.length;\r\n const canvas = document.createElement('canvas');\r\n const font = `${fontSize}px Arial`;\r\n\r\n const context = canvas.getContext('2d');\r\n context.font = font;\r\n\r\n // Calculate accurate text width\r\n let textWidth = 0;\r\n text.forEach(line => {\r\n const width = Math.ceil(context.measureText(line).width);\r\n textWidth = Math.max(textWidth, width);\r\n });\r\n\r\n // Update canvas width and height with final values\r\n canvas.height = fontSize * (numLines + 0.5) + (2 * borderThickness);\r\n canvas.width = textWidth + (2 * margin) + (2 * borderThickness);\r\n context.font = font;\r\n\r\n // Draw text\r\n context.lineWidth = lineThickness;\r\n context.fillStyle = \"#ffffff\";\r\n context.strokeStyle = \"#000000\";\r\n\r\n text.forEach((line, i) => {\r\n const x = borderThickness + margin;\r\n const y = (i + 1) * fontSize + margin;\r\n\r\n context.strokeText(line, x, y);\r\n context.fillText(line, x, y);\r\n });\r\n\r\n const xScale = canvas.width / canvas.height;\r\n const textScale = new Vector3(xScale, 1.0, 1.0)\r\n .multiplyScalar(numLines)\r\n .divideScalar(3);\r\n\r\n let texture = new Texture(canvas);\r\n texture.flipY = true;\r\n texture.needsUpdate = true;\r\n texture.minFilter = LinearFilter;\r\n texture.magFilter = LinearFilter;\r\n\r\n return {texture, textScale};\r\n};\r\n\r\nconst replacer = function (key, value) {\r\n if (!value || !value.geometry) {\r\n return value;\r\n }\r\n\r\n let type;\r\n const rawType = value.type;\r\n let geometry = value.geometry;\r\n if (rawType === 1) {\r\n type = 'MultiPoint';\r\n if (geometry.length === 1) {\r\n type = 'Point';\r\n geometry = geometry[0];\r\n }\r\n } else if (rawType === 2) {\r\n type = 'MultiLineString';\r\n if (geometry.length === 1) {\r\n type = 'LineString';\r\n geometry = geometry[0];\r\n }\r\n } else if (rawType === 3) {\r\n type = 'Polygon';\r\n if (geometry.length > 1) {\r\n type = 'MultiPolygon';\r\n geometry = [geometry];\r\n }\r\n }\r\n\r\n return {\r\n 'type': 'Feature',\r\n 'geometry': {\r\n 'type': type,\r\n 'coordinates': geometry,\r\n },\r\n 'properties': value.tags,\r\n };\r\n};","import {\r\n Box3,\r\n BufferGeometry,\r\n Material,\r\n Mesh,\r\n MeshLambertMaterial,\r\n Vector3\r\n} from \"three\";\r\nimport { IFCLoader } from \"web-ifc-three\";\r\nimport { boundsToMapLayer, roundDigit } from \"../utilities\";\r\nimport { LineworkFile, CADHandler } from \".\";\r\nimport { readFileBuffer } from \"../file-system-loader\";\r\nimport { isDevMode } from \"../../electron-modules\";\r\nimport { toast } from \"../../app\";\r\nimport { Asset } from \"../../redux/assets-slice\";\r\nimport LocalScene from \"../projections\";\r\nimport { addGPUIndex, cloneMeshObject } from \"../gpu-picker\";\r\nimport { Vector as VectorSource } from \"ol/source\";\r\nimport VectorLayer from \"ol/layer/Vector\";\r\nimport { t } from \"../../localization\";\r\nimport { IFCMaterial } from \"../rendering\";\r\n\r\nexport class IFCFile extends LineworkFile {\r\n public standardMesh: Mesh;\r\n public pickingMesh: Mesh;\r\n private loader: IFCLoader;\r\n private useWebWorkers = true;\r\n public mapLayer: VectorLayer;\r\n public mapSource: VectorSource;\r\n\r\n private highlightMaterial = new IFCMaterial({\r\n color: 0xff00ff,\r\n depthTest: false,\r\n transparent: true,\r\n opacity: 0.3\r\n }, false);\r\n\r\n constructor(cadHandler: CADHandler, asset: Asset) {\r\n super(cadHandler, asset);\r\n this.loader = new IFCLoader();\r\n\r\n const mapSource = new VectorSource({\r\n wrapX: false,\r\n features: [],\r\n });\r\n\r\n const mapLayer = new VectorLayer({\r\n zIndex: 1,\r\n source: mapSource,\r\n });\r\n\r\n this.mapLayer = mapLayer;\r\n this.mapSource = mapSource;\r\n this.map.addLayer(mapLayer);\r\n }\r\n\r\n get manager() {\r\n return this.loader.ifcManager;\r\n }\r\n\r\n get ifcAPI() {\r\n return this.manager.ifcAPI;\r\n }\r\n\r\n async load() {\r\n this.loading = true;\r\n this.loaded = false;\r\n this.updatePercent(0);\r\n\r\n // Initialize IFC manager\r\n await this.initManager();\r\n\r\n try {\r\n const buffer = await readFileBuffer(this.path);\r\n if (!this.enabled) return;\r\n\r\n await this.parseFromBuffer(buffer);\r\n } catch {\r\n this.error = true;\r\n toast.error(t(\"toast.model-load-error\", {\r\n name: this.name\r\n }));\r\n }\r\n\r\n this.loaded = true;\r\n this.loading = false;\r\n this.updatePercent(100.0);\r\n\r\n if (this.saved || this.error) return;\r\n this.viewer.zoomToSceneExtent(this.boundingBox, false);\r\n }\r\n\r\n async parseFromBuffer(buffer) {\r\n return new Promise(async (resolve, reject) => {\r\n /** Note: requires modified code in ifc-worker.js */\r\n if (this.useWebWorkers) {\r\n const handler = (this.manager as any).worker;\r\n handler.ifcWorker.onmessage = (event) => {\r\n const {action, error} = event.data;\r\n if (action === \"error\") {\r\n reject(error);\r\n return;\r\n };\r\n\r\n handler.handleResponse(event);\r\n };\r\n }\r\n\r\n const mesh = await this.loader.parse(buffer);\r\n await this.addSceneData(mesh);\r\n await this.addAerialData();\r\n\r\n resolve(true);\r\n });\r\n }\r\n\r\n async addAerialData() {\r\n // Aerial view layer\r\n this.mapLayer = boundsToMapLayer(this.boundingBox);\r\n this.map.addLayer(this.mapLayer);\r\n\r\n // Apply current visibility\r\n this.mapLayer.setVisible(this.visible);\r\n }\r\n\r\n async addSceneData(mesh) {\r\n // Apply mesh scene rotation\r\n mesh.rotation.set(Math.PI/2, 0, 0);\r\n\r\n // Apply mesh coordinate shift\r\n const modelID = mesh.modelID;\r\n const coordinationMatrix = await this.ifcAPI.GetCoordinationMatrix(modelID);\r\n\r\n const offset = new Vector3()\r\n .fromArray(coordinationMatrix.slice(12, 15))\r\n .applyEuler(mesh.rotation)\r\n .multiplyScalar(-1);\r\n\r\n // Convert mesh to meters\r\n mesh.scale.setScalar(LocalScene.dataToMeters);\r\n offset.multiplyScalar(LocalScene.dataToMeters);\r\n\r\n // Move model to scene coordinates\r\n const shift = LocalScene.offsetToScene(offset);\r\n mesh.position.copy(shift);\r\n\r\n // Add gpu index to mesh\r\n const standardMesh = addGPUIndex(mesh);\r\n\r\n // Clone mesh for picking mesh\r\n const pickingMesh = cloneMeshObject(standardMesh);\r\n\r\n // Scene view mesh\r\n this.standardMesh = standardMesh;\r\n this.replaceMaterials(standardMesh, false);\r\n this.scene.add(this.standardMesh);\r\n\r\n // Picking scene mesh\r\n this.pickingMesh = pickingMesh;\r\n this.replaceMaterials(pickingMesh, true);\r\n this.picker.add(this.pickingMesh);\r\n\r\n // Apply current visibility\r\n this.standardMesh.visible = this.visible;\r\n this.pickingMesh.visible = this.visible;\r\n\r\n // Update bounding box\r\n this.boundingBox = new Box3()\r\n .setFromObject(this.standardMesh);\r\n }\r\n\r\n async initManager() {\r\n if (this.useWebWorkers) {\r\n const workerURL = \"workers/ifc-worker.js\";\r\n const workerPath = `${process.env.PUBLIC_URL}/${workerURL}`;\r\n await this.manager.useWebWorkers(true, workerPath);\r\n } else {\r\n await this.manager.useWebWorkers(false, null);\r\n }\r\n\r\n const wasmPath = isDevMode\r\n ? \"../../workers/\"\r\n : \"\";\r\n\r\n await this.manager.setWasmPath(wasmPath);\r\n\r\n this.manager.applyWebIfcConfig({\r\n COORDINATE_TO_ORIGIN: true,\r\n USE_FAST_BOOLS: true\r\n });\r\n\r\n this.manager.setOnProgress(event => {\r\n let percent = event.loaded / event.total;\r\n this.updatePercent(100 * percent);\r\n });\r\n }\r\n\r\n /** Update visibility */\r\n updateProperties(asset: Asset) {\r\n const state = asset.visible;\r\n this.visible = state;\r\n\r\n if (this.mapLayer) {\r\n this.mapLayer.setVisible(state);\r\n }\r\n\r\n if (this.standardMesh) {\r\n this.standardMesh.visible = state;\r\n }\r\n\r\n if (this.pickingMesh) {\r\n this.pickingMesh.visible = state;\r\n }\r\n\r\n this.updatePicker();\r\n }\r\n\r\n updateMaterials() {\r\n if (!this.visible) return;\r\n\r\n const drawDistance = this.drawDistance;\r\n\r\n let materials = [];\r\n\r\n if (this.standardMesh) {\r\n materials = [...materials, ...this.standardMesh.material];\r\n }\r\n\r\n if (this.pickingMesh) {\r\n materials = [...materials, ...this.pickingMesh.material];\r\n }\r\n\r\n materials.push(this.highlightMaterial);\r\n\r\n materials.forEach((material: IFCMaterial) => {\r\n material.drawDistance = drawDistance;\r\n });\r\n\r\n return;\r\n }\r\n\r\n replaceMaterials(mesh: Mesh, gpuPicker: boolean) {\r\n for (let i=0; i {\r\n material.dispose();\r\n });\r\n }\r\n\r\n destroy() {\r\n this.enabled = false;\r\n\r\n this.removeSubset();\r\n\r\n this.removeFromScene(this.standardMesh);\r\n this.disposeGeometry(this.standardMesh);\r\n this.standardMesh = null;\r\n\r\n this.removeFromScene(this.pickingMesh);\r\n this.disposeGeometry(this.pickingMesh);\r\n this.pickingMesh = null;\r\n\r\n this.map.removeLayer(this.mapLayer);\r\n this.mapLayer = null;\r\n this.mapSource = null;\r\n\r\n this.manager.dispose()\r\n .catch(err => {\r\n console.log(err);\r\n });\r\n }\r\n}\r\n","import { toast } from \"../../app\";\r\nimport { readFileBuffer } from \"../file-system-loader\";\r\nimport {\r\n CADHandler,\r\n LineworkLayer,\r\n LineworkFile\r\n} from \".\";\r\nimport { Asset, LineworkLayerData } from \"../../redux/assets-slice\";\r\nimport { pathWithExtension } from \"../../utilities\";\r\nimport { t } from \"../../localization\";\r\nimport { Box3 } from \"three\";\r\nimport { DataProjectionCoordinate } from \"../projections\";\r\n\r\n\r\nclass SHPLayer extends LineworkLayer {\r\n constructor(file: SHPFile, layer: LineworkLayerData) {\r\n super(file, layer);\r\n }\r\n}\r\n\r\nexport class SHPFile extends LineworkFile {\r\n constructor(cadHandler: CADHandler, asset: Asset) {\r\n super(cadHandler, asset);\r\n this.addLayers(asset.data);\r\n }\r\n\r\n get shpPath() {\r\n return pathWithExtension(this.path, \"shp\");\r\n }\r\n\r\n get dbfPath() {\r\n return pathWithExtension(this.path, \"dbf\");\r\n }\r\n\r\n getByName(name: string) {\r\n return this.layers.find(layer => layer.name === name);\r\n };\r\n\r\n async load() {\r\n this.loading = true;\r\n this.loaded = false;\r\n this.updatePercent(0);\r\n\r\n try {\r\n const shp = await readFileBuffer(this.shpPath);\r\n const dbf = await readFileBuffer(this.dbfPath);\r\n const {bounds, features, numInvalid}\r\n = await this.parseFromBuffer(shp, dbf);\r\n\r\n const layerNames = Object.keys(features);\r\n\r\n if (numInvalid) {\r\n toast.warning(t('toast.model_feature_error', {\r\n count: numInvalid\r\n }));\r\n }\r\n\r\n if (this.validBounds(bounds)) {\r\n this.boundingBox = new Box3(\r\n new DataProjectionCoordinate(bounds.min).toScene(),\r\n new DataProjectionCoordinate(bounds.max).toScene()\r\n );\r\n\r\n if (!this.saved) {\r\n this.viewer.zoomToSceneExtent(this.boundingBox, false);\r\n }\r\n }\r\n\r\n for (let i=0; i {\r\n return new Promise((resolve, reject) => {\r\n const workerURL = \"workers/shp-reader.js\";\r\n let worker = new Worker(`${process.env.PUBLIC_URL}/${workerURL}`);\r\n\r\n worker.onmessage = event => {\r\n const {success, response} = event.data;\r\n\r\n if (success) {\r\n resolve(response);\r\n } else {\r\n console.error(response);\r\n reject(response);\r\n }\r\n };\r\n\r\n const data = {shp, dbf, type: \"features\"};\r\n worker.postMessage(data, [data.shp, data.dbf]);\r\n });\r\n };\r\n\r\n addLayers(layers) {\r\n layers.forEach(data => {\r\n let newLayer = new SHPLayer(this, data);\r\n this.layers.push(newLayer);\r\n });\r\n }\r\n\r\n /** Update visibility and colors */\r\n updateProperties(asset: Asset) {\r\n this.visible = asset.visible;\r\n\r\n const layers = asset.data as LineworkLayerData[];\r\n\r\n layers.forEach(data => {\r\n const layer = this.getByName(data.name);\r\n const visible = this.visible ? data.visible : false;\r\n layer.setColor(data.color);\r\n layer.setVisibility(visible);\r\n });\r\n\r\n this.updatePicker();\r\n }\r\n\r\n destroy() {\r\n this.enabled = false;\r\n\r\n for (let layer of this.layers) {\r\n layer.destroy();\r\n }\r\n\r\n this.layers = [];\r\n }\r\n}\r\n","import {\r\n CADHandler,\r\n LineworkLayer,\r\n LineworkFile\r\n} from \".\";\r\nimport { Asset, LineworkLayerData } from \"../../redux/assets-slice\";\r\nimport { readFileText } from \"../file-system-loader\";\r\nimport { toast } from \"../../app\";\r\nimport { t } from \"../../localization\";\r\nimport { DataProjectionCoordinate } from \"../projections\";\r\nimport { Box3 } from \"three\";\r\n\r\nclass DXFLayer extends LineworkLayer {\r\n constructor(file: DXFFile, layer: LineworkLayerData) {\r\n super(file, layer);\r\n }\r\n}\r\n\r\nexport class DXFFile extends LineworkFile {\r\n constructor(cadHandler: CADHandler, asset: Asset) {\r\n super(cadHandler, asset);\r\n this.addLayers(asset.data);\r\n }\r\n\r\n getByName(name: string) {\r\n return this.layers.find(layer => layer.name === name);\r\n };\r\n\r\n async load() {\r\n this.loading = true;\r\n this.loaded = false;\r\n this.updatePercent(0);\r\n\r\n try {\r\n const text = await readFileText(this.path);\r\n const {bounds, features, numInvalid}\r\n = await this.parseFromText(text);\r\n\r\n const layerNames = Object.keys(features);\r\n\r\n if (numInvalid) {\r\n toast.warning(t('toast.model_feature_error', {\r\n count: numInvalid\r\n }));\r\n }\r\n\r\n if (this.validBounds(bounds)) {\r\n this.boundingBox = new Box3(\r\n new DataProjectionCoordinate(bounds.min).toScene(),\r\n new DataProjectionCoordinate(bounds.max).toScene()\r\n );\r\n\r\n if (!this.saved) {\r\n this.viewer.zoomToSceneExtent(this.boundingBox, false);\r\n }\r\n }\r\n\r\n for (let i=0; i {\r\n return new Promise((resolve, reject) => {\r\n const workerURL = \"workers/dxf-reader.js\";\r\n let worker = new Worker(`${process.env.PUBLIC_URL}/${workerURL}`);\r\n\r\n worker.onmessage = event => {\r\n const {success, response} = event.data;\r\n\r\n if (success) {\r\n resolve(response);\r\n } else {\r\n console.error(response);\r\n reject(response);\r\n }\r\n };\r\n\r\n const data = {text, type: \"features\"};\r\n worker.postMessage(data);\r\n });\r\n }\r\n\r\n addLayers(layers) {\r\n layers.forEach(data => {\r\n let newLayer = new DXFLayer(this, data);\r\n this.layers.push(newLayer);\r\n });\r\n }\r\n\r\n /** Update visibility and colors */\r\n updateProperties(asset: Asset) {\r\n this.visible = asset.visible;\r\n\r\n const layers = asset.data as LineworkLayerData[];\r\n\r\n layers.forEach(data => {\r\n const layer = this.getByName(data.name);\r\n const visible = this.visible ? data.visible : false;\r\n layer.setColor(data.color);\r\n layer.setVisibility(visible);\r\n });\r\n\r\n this.updatePicker();\r\n }\r\n\r\n destroy() {\r\n this.enabled = false;\r\n\r\n for (let layer of this.layers) {\r\n layer.destroy();\r\n }\r\n\r\n this.layers = [];\r\n }\r\n}\r\n","import { WebSourceAsset } from \"../../redux/assets-slice\";\r\nimport { ServerType } from \"../../types/web-sources\";\r\nimport { Viewer } from \"../main\";\r\nimport {\r\n WebSource,\r\n ArcGISMapServer,\r\n ArcGISImageServer,\r\n ArcGISFeatureServer,\r\n OGCWMS,\r\n OGCWFS,\r\n OGCWMTS,\r\n TileServer\r\n} from \".\";\r\n\r\nexport class WebSourceHandler {\r\n public viewer: Viewer;\r\n private sources: WebSource[] = [];\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n }\r\n\r\n reconcile(webSources: WebSourceAsset[]) {\r\n const currentIDs = new Set(this.sources.map(x => x.id));\r\n const newAssetIDs = new Set(webSources.map(x => x.id));\r\n const sourcesToLoad = webSources.filter(x => !currentIDs.has(x.id));\r\n const sourcesToDelete = this.sources.filter(x => !newAssetIDs.has(x.id));\r\n\r\n // Delete sources that need to be removed\r\n sourcesToDelete.forEach(webSource => {\r\n this.deleteSource(webSource);\r\n });\r\n\r\n // Add new sources\r\n sourcesToLoad.forEach(asset => {\r\n this.addNewSource(asset);\r\n });\r\n\r\n // Toggle visibility for each source\r\n webSources.forEach(asset => {\r\n this.toggleVisibility(asset);\r\n });\r\n }\r\n\r\n getByID(assetID) {\r\n return this.sources.find(file => file.id === assetID);\r\n }\r\n\r\n toggleVisibility(asset: WebSourceAsset) {\r\n let source = this.getByID(asset.id);\r\n if (!source) return;\r\n\r\n source.toggleVisibility(asset);\r\n }\r\n\r\n getNewSource(asset: WebSourceAsset) {\r\n const {type} = asset.data;\r\n\r\n switch (type) {\r\n case ServerType.ArcGISMapServer:\r\n return new ArcGISMapServer(this, asset);\r\n case ServerType.ArcGISImageServer:\r\n return new ArcGISImageServer(this, asset);\r\n case ServerType.ArcGISFeatureServer:\r\n return new ArcGISFeatureServer(this, asset);\r\n case ServerType.OGCWMS:\r\n return new OGCWMS(this, asset);\r\n case ServerType.OGCWFS:\r\n return new OGCWFS(this, asset);\r\n case ServerType.OGCWMTS:\r\n return new OGCWMTS(this, asset);\r\n case ServerType.TileServer:\r\n return new TileServer(this, asset);\r\n default:\r\n return;\r\n }\r\n }\r\n\r\n addNewSource(asset: WebSourceAsset) {\r\n let newSource = this.getNewSource(asset);\r\n if (!newSource) return;\r\n\r\n this.sources.push(newSource);\r\n }\r\n\r\n deleteSource(webSource: WebSource) {\r\n webSource.destroy();\r\n\r\n const index = this.sources.indexOf(webSource);\r\n this.sources.splice(index, 1);\r\n }\r\n}","import { Layer } from \"ol/layer\";\r\nimport { TileArcGISRest, TileWMS, XYZ } from \"ol/source\";\r\nimport { WebSourceAsset } from \"../../redux/assets-slice\";\r\nimport { ServerType } from \"../../types/web-sources\";\r\nimport { isEqual } from 'lodash';\r\nimport VectorSource from \"ol/source/Vector\";\r\nimport GeoJSON from 'ol/format/GeoJSON.js';\r\nimport { WebSourceHandler } from \".\";\r\nimport {createXYZ} from 'ol/tilegrid.js';\r\nimport VectorLayer from \"ol/layer/Vector\";\r\nimport WMTSCapabilities from \"ol/format/WMTSCapabilities\";\r\nimport WMTS, { optionsFromCapabilities } from \"ol/source/WMTS\";\r\nimport TileLayer from \"ol/layer/Tile\";\r\nimport EsriJSON from 'ol/format/EsriJSON.js';\r\nimport {\r\n fromUserExtent,\r\n fromUserResolution,\r\n Projection,\r\n ProjectionLike,\r\n toUserExtent,\r\n transformExtent\r\n} from \"ol/proj\";\r\nimport { createStyleFunction } from 'ol-esri-style';\r\nimport { Feature } from \"ol\";\r\nimport TileGrid from \"ol/tilegrid/TileGrid\";\r\nimport { Extent } from \"ol/extent\";\r\n\r\n/** Return the numeric part of openlayers style projection */\r\nconst projectionToEsriSRID = (projection: Projection) => {\r\n return projection\r\n .getCode()\r\n .split(/:(?=\\d+$)/)\r\n .pop();\r\n};\r\n\r\ntype WebSourceArguments = ConstructorParameters\r\n\r\nexport class WebSource {\r\n public id: string;\r\n protected name: string;\r\n protected url: string;\r\n protected enabled = true;\r\n protected visible = false;\r\n protected clearable = false;\r\n protected removeOnClear = true;\r\n protected layers: Layer[] = [];\r\n private visibleIdentifier = [];\r\n protected type: ServerType;\r\n private handler: WebSourceHandler\r\n\r\n constructor(webmapHandler: WebSourceHandler, asset: WebSourceAsset) {\r\n this.id = asset.id;\r\n this.name = asset.name;\r\n this.url = asset.data.url;\r\n this.handler = webmapHandler;\r\n }\r\n\r\n get viewer() {\r\n return this.handler.viewer;\r\n }\r\n\r\n get map() {\r\n return this.viewer.minimap.map;\r\n }\r\n\r\n getByID(identifier) {\r\n return this.layers.find(layer => {\r\n return layer.get(\"identifier\") === identifier;\r\n });\r\n }\r\n\r\n setLayerVisible(identifier) {\r\n const layer = this.getByID(identifier);\r\n if (!layer) return false;\r\n\r\n layer.setVisible(true);\r\n layer.changed();\r\n return true;\r\n }\r\n\r\n toggleVisibility(asset: WebSourceAsset) {\r\n this.visible = asset.visible;\r\n\r\n const newIdentifiers = asset.data.layers\r\n .filter(layer => layer.visible && this.visible)\r\n .map(layer => layer.identifier);\r\n\r\n const needsUpdate = !isEqual(newIdentifiers, this.visibleIdentifier);\r\n this.visibleIdentifier = newIdentifiers;\r\n if (!needsUpdate) return;\r\n\r\n // Clear old layers\r\n this.clearLayers(this.removeOnClear);\r\n\r\n if (newIdentifiers.length === 0) return;\r\n this.generateLayers(newIdentifiers);\r\n }\r\n\r\n generateLayers(identifiers: string[]) {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n clearLayers(removeLayers) {\r\n if (removeLayers) {\r\n // Remove all layers from map\r\n this.layers.forEach(layer => {\r\n this.map.removeLayer(layer);\r\n });\r\n this.layers = [];\r\n } else {\r\n // Set all layer visibility to false\r\n this.layers.forEach(layer => {\r\n layer.setVisible(false);\r\n });\r\n }\r\n }\r\n\r\n destroy() {\r\n this.enabled = false;\r\n this.clearLayers(true);\r\n }\r\n}\r\n\r\nclass FeatureVectorSource extends VectorSource {\r\n private prevResolution;\r\n\r\n constructor(source: FeatureWebSource, options) {\r\n const tileGrid = createXYZ({\r\n tileSize: source.tileSize\r\n });\r\n\r\n super({\r\n ...options,\r\n strategy: (extent, resolution, projection) => {\r\n return this.getExtents(\r\n source, tileGrid, extent, resolution, projection\r\n );\r\n }\r\n });\r\n }\r\n\r\n /** strategy was modified from https://github.com/openlayers/openlayers/blob/v7.5.1/src/ol/loadingstrategy.js */\r\n getExtents(source: FeatureWebSource, tileGrid: TileGrid, extent: Extent,\r\n resolution: number, projection: ProjectionLike) {\r\n if (resolution !== this.prevResolution) {\r\n source.onResolutionChange();\r\n }\r\n\r\n this.prevResolution = resolution;\r\n\r\n const z = tileGrid.getZForResolution(\r\n fromUserResolution(resolution, projection)\r\n );\r\n\r\n const tileRange = tileGrid.getTileRangeForExtentAndZ(\r\n fromUserExtent(extent, projection), z\r\n );\r\n\r\n const extents = [];\r\n for (let x = tileRange.minX; x <= tileRange.maxX; ++x) {\r\n for (let y = tileRange.minY; y <= tileRange.maxY; ++y) {\r\n const tileCoord = [z, x, y];\r\n const extent = tileGrid.getTileCoordExtent(tileCoord);\r\n extents.push(toUserExtent(extent, projection));\r\n }\r\n }\r\n\r\n return extents;\r\n }\r\n\r\n updateFeatures(features: Feature[]) {\r\n let newFeatures = [];\r\n\r\n // Update existing feature geometry\r\n features.forEach(feature => {\r\n const featureID = feature.getId();\r\n const oldFeature = this.getFeatureById(featureID) as Feature;\r\n\r\n if (oldFeature) {\r\n const geometry = feature.getGeometry();\r\n oldFeature.setGeometry(geometry);\r\n } else {\r\n newFeatures.push(feature);\r\n }\r\n });\r\n\r\n // Add new feature to source\r\n this.addFeatures(newFeatures);\r\n }\r\n}\r\n\r\nclass FeatureWebSource extends WebSource {\r\n public tileSize = 512;\r\n protected removeOnClear = false;\r\n protected controllers: AbortController[] = [];\r\n\r\n onResolutionChange() {\r\n this.cancelRequests();\r\n this.clearLoadedExtents();\r\n }\r\n\r\n cancelRequests() {\r\n // Cancel any existing requests\r\n this.controllers.forEach(controller => {\r\n controller.abort();\r\n });\r\n };\r\n\r\n clearLoadedExtents() {\r\n // Clear all loaded extents\r\n this.layers.forEach(layer => {\r\n const source = layer.getSource() as VectorSource;\r\n\r\n // @ts-expect-error\r\n source.loadedExtentsRtree_.clear();\r\n });\r\n }\r\n}\r\n\r\nexport class ArcGISMapServer extends WebSource {\r\n protected type = ServerType.ArcGISMapServer;\r\n\r\n /** Generate a single layer for all visible identifiers */\r\n generateLayers(identifiers: string[]) {\r\n const layer = new TileLayer({\r\n source: new TileArcGISRest({\r\n crossOrigin: \"anonymous\",\r\n url: this.url,\r\n params: {\r\n LAYERS: `show: ${identifiers.join(\",\")}`\r\n },\r\n wrapX: false\r\n })\r\n });\r\n\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n }\r\n}\r\n\r\nexport class ArcGISImageServer extends WebSource {\r\n protected type = ServerType.ArcGISImageServer;\r\n\r\n constructor(...args: WebSourceArguments) {\r\n super(...args);\r\n\r\n let layer = new TileLayer({\r\n source: new TileArcGISRest({\r\n crossOrigin: \"anonymous\",\r\n url: this.url,\r\n wrapX: false\r\n }),\r\n visible: false\r\n });\r\n\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n }\r\n\r\n toggleVisibility(asset: WebSourceAsset) {\r\n this.visible = asset.visible;\r\n this.layers[0].setVisible(this.visible);\r\n }\r\n}\r\n\r\ninterface ArcGISFeatureCapabilities {\r\n metadata: any;\r\n hasHeight: boolean;\r\n extent: number[];\r\n supportsPagination: boolean;\r\n supportsQuantization: boolean;\r\n supportsQueryWithResultType: boolean;\r\n}\r\n\r\nexport class ArcGISFeatureServer extends FeatureWebSource {\r\n protected type = ServerType.ArcGISFeatureServer;\r\n private capabilities: { [layer: string]: ArcGISFeatureCapabilities } = {};\r\n private featureCount: { [layer: string]: number } = {};\r\n\r\n async getCapabilities(identifier: string): Promise {\r\n if (identifier in this.capabilities) {\r\n return this.capabilities[identifier];\r\n }\r\n\r\n const url = new URL(this.url);\r\n url.pathname += `/${identifier}`;\r\n url.searchParams.set('f', 'json');\r\n\r\n const response = await fetch(url.toString());\r\n const metadata = await response.json();\r\n\r\n const hasHeight = metadata.hasZ;\r\n const capabilities = metadata.advancedQueryCapabilities || {};\r\n const {supportsPagination=false, supportsQueryWithResultType=false} = capabilities;\r\n const supportsQuantization = !!metadata.supportsCoordinatesQuantization;\r\n\r\n let extent;\r\n\r\n try {\r\n const projection = `EPSG:${metadata.extent.spatialReference.wkid}`;\r\n\r\n extent = transformExtent([\r\n metadata.extent.xmin, metadata.extent.ymin,\r\n metadata.extent.xmax, metadata.extent.ymax\r\n ], projection, 'EPSG:3857');\r\n } catch (err) {\r\n console.warn(\"Error grabbing feature extent\");\r\n }\r\n\r\n this.capabilities[identifier] = {\r\n metadata,\r\n hasHeight,\r\n extent,\r\n supportsPagination,\r\n supportsQuantization,\r\n supportsQueryWithResultType\r\n };\r\n\r\n return this.capabilities[identifier];\r\n }\r\n\r\n async getNumberOfFeatures(identifier) {\r\n if (identifier in this.featureCount) {\r\n return this.featureCount[identifier];\r\n }\r\n\r\n const url = new URL(this.url);\r\n url.pathname += `/${identifier}`;\r\n url.pathname += '/query';\r\n\r\n url.searchParams.set('f', 'json');\r\n url.searchParams.set(\"where\", \"1=1\");\r\n url.searchParams.set('returnCountOnly', 'true');\r\n\r\n const response = await fetch(url.toString());\r\n const esriResponse = await response.json();\r\n\r\n this.featureCount[identifier] = esriResponse.count;\r\n return this.featureCount[identifier];\r\n }\r\n\r\n /** Generate one layer for each identifier */\r\n generateLayers(identifiers: string[]) {\r\n identifiers.forEach(async identifier => {\r\n // Try to update existing layer visibility\r\n if (this.setLayerVisible(identifier)) return;\r\n\r\n const capabilities = await this.getCapabilities(identifier);\r\n const featureCount = await this.getNumberOfFeatures(identifier);\r\n\r\n const vectorSource = new FeatureVectorSource(this, {\r\n loader: (extent, resolution, projection) => {\r\n this.getFeatures(vectorSource, identifier,\r\n extent, projection, capabilities, featureCount);\r\n },\r\n wrapX: false\r\n });\r\n\r\n const layer = new VectorLayer({\r\n source: vectorSource,\r\n extent: capabilities.extent,\r\n properties: {identifier}\r\n });\r\n\r\n // Apply feature style based on metadata\r\n const mapProjection = this.map.getView().getProjection();\r\n const styleFunction = await createStyleFunction(\r\n capabilities.metadata, mapProjection);\r\n layer.setStyle(styleFunction);\r\n\r\n if (!this.enabled) return;\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n });\r\n }\r\n\r\n reconstructQuantizedGeometry(esriResponse) {\r\n if (!esriResponse.features) return [];\r\n\r\n const {geometryType} = esriResponse;\r\n\r\n return esriResponse.features.map(feature => {\r\n const [scaleX, scaleY] = esriResponse.transform.scale;\r\n const [offsetX, offsetY] = esriResponse.transform.translate;\r\n\r\n const geometry = feature.geometry;\r\n\r\n if (geometryType === \"esriGeometryPoint\") {\r\n /** Reconstruct single point */\r\n geometry.x = offsetX + geometry.x * scaleX;\r\n geometry.y = offsetY + geometry.y * scaleY;\r\n } else if (geometryType === \"esriGeometryPolygon\") {\r\n /** Reconstruct polygon(s) */\r\n geometry.rings = geometry.rings.map(ring => {\r\n let coordinate = [offsetX, offsetY];\r\n\r\n return ring.map(point => {\r\n coordinate[0] += (point[0]*scaleX);\r\n coordinate[1] -= (point[1]*scaleY);\r\n return [...coordinate];\r\n });\r\n });\r\n } else if (geometryType === \"esriGeometryPolyline\") {\r\n /** Reconstruct polyline(s) */\r\n if (geometry.hasOwnProperty(\"paths\")) {\r\n geometry.paths = geometry.paths.map(path => {\r\n let coordinate = [offsetX, offsetY];\r\n\r\n return path.map(point => {\r\n coordinate[0] += (point[0]*scaleX);\r\n coordinate[1] -= (point[1]*scaleY);\r\n return [...coordinate];\r\n });\r\n });\r\n }\r\n } else {\r\n console.log(`Unknown geometry type: ${geometryType}`);\r\n }\r\n\r\n return feature;\r\n });\r\n }\r\n\r\n async getFeatures(source: FeatureVectorSource, identifier: string, extent,\r\n projection, capabilities, featureCount, resultOffset=0) {\r\n const srid = projectionToEsriSRID(projection);\r\n\r\n const {supportsPagination, supportsQuantization,\r\n supportsQueryWithResultType, hasHeight} = capabilities;\r\n\r\n // Complex layers can use geometry simplification and quantization\r\n const isComplexLayer = featureCount >= 1000;\r\n\r\n const extendBounds = {\r\n xmin: extent[0],\r\n ymin: extent[1],\r\n xmax: extent[2],\r\n ymax: extent[3],\r\n spatialReference: {\r\n wkid: srid\r\n }\r\n };\r\n\r\n // Limit geometry complexity to one vertex point per tile pixel\r\n const extentWidth = extendBounds.xmax - extendBounds.xmin;\r\n const tolerance = extentWidth / this.tileSize;\r\n\r\n const quantizationParameters = {\r\n extent: {\r\n type: \"extent\",\r\n ...extendBounds\r\n },\r\n mode: \"view\",\r\n originPosition: \"upperLeft\",\r\n tolerance\r\n };\r\n\r\n const url = new URL(this.url);\r\n url.pathname += `/${identifier}`;\r\n url.pathname += '/query';\r\n\r\n url.searchParams.set('f', 'json');\r\n url.searchParams.set('returnGeometry', 'true');\r\n url.searchParams.set('spatialRel', 'esriSpatialRelIntersects');\r\n url.searchParams.set('geometry', JSON.stringify(extendBounds));\r\n url.searchParams.set('geometryType', 'esriGeometryEnvelope');\r\n url.searchParams.set('inSR', srid);\r\n url.searchParams.set('outFields', '*');\r\n url.searchParams.set('outSR', srid);\r\n url.searchParams.set('where', '1=1');\r\n url.searchParams.set('returnZ', 'true');\r\n\r\n if (isComplexLayer) {\r\n if (supportsQuantization) {\r\n url.searchParams.set('quantizationParameters', JSON.stringify(quantizationParameters));\r\n } else {\r\n url.searchParams.set('maxAllowableOffset', tolerance.toString());\r\n }\r\n }\r\n\r\n if (supportsPagination) {\r\n url.searchParams.set('orderByFields', 'OBJECTID');\r\n }\r\n\r\n if (resultOffset > 0) {\r\n url.searchParams.set(\"resultOffset\", resultOffset.toString());\r\n }\r\n\r\n if (supportsQueryWithResultType) {\r\n // Tile type supports more features per query\r\n url.searchParams.set('resultType', 'tile');\r\n }\r\n\r\n // Add controller to array\r\n const controller = new AbortController();\r\n this.controllers.push(controller);\r\n\r\n let esriResponse;\r\n let fetchError = false;\r\n\r\n try {\r\n const response = await fetch(url.toString(), {\r\n signal: controller.signal\r\n });\r\n esriResponse = await response.json();\r\n } catch (err) {\r\n fetchError = true;\r\n }\r\n\r\n // Remove controller from array\r\n const index = this.controllers.indexOf(controller);\r\n this.controllers.splice(index, 1);\r\n\r\n // Something went wrong, exit early\r\n if (fetchError || esriResponse.error) return;\r\n\r\n if (isComplexLayer) {\r\n if (supportsQuantization) {\r\n esriResponse.features = this.reconstructQuantizedGeometry(esriResponse);\r\n }\r\n }\r\n\r\n const parser = new EsriJSON();\r\n const features = parser.readFeatures(esriResponse, {\r\n featureProjection: projection\r\n }) as Feature[];\r\n\r\n if (features.length === 0) return;\r\n if (!this.enabled) return;\r\n\r\n // Add new features and update existing ones\r\n source.updateFeatures(features);\r\n\r\n // TODO: Add feature to scene view\r\n if (hasHeight) {\r\n //addSceneFeatures(esriResponse);\r\n }\r\n\r\n if (esriResponse.exceededTransferLimit && supportsPagination) {\r\n const newResultOffset = resultOffset + features.length;\r\n this.getFeatures(source, identifier, extent, projection,\r\n capabilities, featureCount, newResultOffset);\r\n }\r\n }\r\n}\r\n\r\nexport class OGCWMS extends WebSource {\r\n protected type = ServerType.OGCWMS;\r\n\r\n /** Generate a single layer for all visible identifiers */\r\n generateLayers(identifiers: string[]) {\r\n const layer = new TileLayer({\r\n source: new TileWMS({\r\n crossOrigin: \"anonymous\",\r\n url: this.url,\r\n params: {\r\n 'LAYERS': identifiers.join(\",\"),\r\n 'TILED': true\r\n },\r\n serverType: 'geoserver',\r\n wrapX: false\r\n })\r\n });\r\n\r\n if (!this.enabled) return;\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n }\r\n}\r\n\r\nexport class OGCWFS extends FeatureWebSource {\r\n protected type = ServerType.OGCWFS;\r\n\r\n /** Generate one layer for each identifier */\r\n generateLayers(identifiers: string[]) {\r\n identifiers.forEach(identifier => {\r\n // Try to update existing layer visibility\r\n if (this.setLayerVisible(identifier)) return;\r\n\r\n const vectorSource = new FeatureVectorSource(this, {\r\n loader: (extent, resolution, projection) => {\r\n this.getFeatures(vectorSource, identifier,\r\n extent, projection);\r\n },\r\n wrapX: false\r\n });\r\n\r\n const layer = new VectorLayer({\r\n source: vectorSource,\r\n properties: {identifier}\r\n });\r\n\r\n if (!this.enabled) return;\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n });\r\n }\r\n\r\n async getFeatures(source: FeatureVectorSource, identifier: string, extent, projection) {\r\n const url = new URL(this.url);\r\n url.searchParams.set('service', 'WFS');\r\n url.searchParams.set('request', 'GetFeature');\r\n url.searchParams.set('typename', identifier);\r\n url.searchParams.set('outputFormat', 'application/json');\r\n url.searchParams.set('srsname', 'EPSG:3857');\r\n\r\n const geomExtent = `${extent.join(',')},EPSG:3857`;\r\n url.searchParams.set('bbox', geomExtent);\r\n\r\n // Add controller to array\r\n const controller = new AbortController();\r\n this.controllers.push(controller);\r\n\r\n let serverResponse;\r\n let fetchError = false;\r\n\r\n try {\r\n const response = await fetch(url.toString(), {\r\n signal: controller.signal\r\n });\r\n serverResponse = await response.json();\r\n } catch (err) {\r\n fetchError = true;\r\n }\r\n\r\n // Remove controller from array\r\n const index = this.controllers.indexOf(controller);\r\n this.controllers.splice(index, 1);\r\n\r\n // Something went wrong, exit early\r\n if (fetchError) return;\r\n\r\n const parser = new GeoJSON();\r\n const features = parser.readFeatures(serverResponse, {\r\n featureProjection: projection\r\n }) as Feature[];\r\n\r\n if (features.length === 0) return;\r\n if (!this.enabled) return;\r\n\r\n // Add new features and update existing ones\r\n source.updateFeatures(features);\r\n }\r\n}\r\n\r\nexport class OGCWMTS extends WebSource {\r\n protected type = ServerType.OGCWMTS;\r\n protected removeOnClear = false;\r\n private capabilities;\r\n\r\n constructor(...args: WebSourceArguments) {\r\n super(...args);\r\n }\r\n\r\n async getCapabilities(): Promise {\r\n if (this.capabilities) {\r\n return this.capabilities;\r\n }\r\n\r\n const url = new URL(this.url);\r\n url.pathname = `${url.pathname}/1.0.0/WMTSCapabilities.xml`;\r\n\r\n const response = await fetch(url.href);\r\n const text = await response.text();\r\n\r\n const parser = new WMTSCapabilities();\r\n this.capabilities = parser.read(text);\r\n return this.capabilities;\r\n }\r\n\r\n /** Generate one layer for each identifier */\r\n async generateLayers(identifiers: string[]) {\r\n let capabilities = await this.getCapabilities();\r\n\r\n identifiers.forEach(identifier => {\r\n // Try to update existing layer visibility\r\n if (this.setLayerVisible(identifier)) return;\r\n\r\n const options = optionsFromCapabilities(capabilities, {\r\n layer: identifier,\r\n matrixSet: 'EPSG:3857',\r\n wrapX: false\r\n });\r\n\r\n const layer = new TileLayer({\r\n source: new WMTS(options),\r\n properties: {identifier}\r\n });\r\n\r\n if (!this.enabled) return;\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n });\r\n }\r\n}\r\n\r\nexport class TileServer extends WebSource {\r\n protected type = ServerType.TileServer;\r\n\r\n constructor(...args: WebSourceArguments) {\r\n super(...args);\r\n\r\n let url = this.url\r\n .replace(\"{level}\", \"{z}\")\r\n .replace(\"{zoom}\", \"{z}\")\r\n .replace(\"{col}\", \"{x}\")\r\n .replace(\"{row}\", \"{y}\");\r\n\r\n let layer = new TileLayer({\r\n source: new XYZ({\r\n crossOrigin: \"anonymous\",\r\n url: url,\r\n wrapX: false\r\n }),\r\n visible: false\r\n });\r\n\r\n this.layers.push(layer);\r\n this.map.addLayer(layer);\r\n }\r\n\r\n toggleVisibility(asset: WebSourceAsset) {\r\n this.visible = asset.visible;\r\n this.layers[0].setVisible(this.visible);\r\n }\r\n}\r\n","import {\r\n PointCloudManager,\r\n GenericPointCloud\r\n} from './pointcloud';\r\nimport {\r\n CompassControls,\r\n CustomMouseEvent,\r\n MultiImageOptions,\r\n PanoControls\r\n} from './controls';\r\nimport { mergeBoundingBoxes, toScreenPosition } from './utilities';\r\nimport { CameraImage, CameraHandler, CameraLoadOptions } from './cameras';\r\nimport {\r\n AerialMap,\r\n extentFromPoints\r\n} from './aerial';\r\nimport { Clamp, ColorMapKey, ColorType, MarkerNavType } from '../redux/settings-slice';\r\nimport LocalScene, {\r\n DataProjectionCoordinate,\r\n ProjectedCoordinate,\r\n SceneCoordinate,\r\n webMercator\r\n} from './projections';\r\nimport { getColorMap } from \"./textures/colormaps\";\r\nimport {\r\n MeasurementController,\r\n Measurement\r\n} from './measurements';\r\nimport { ChangeDetector } from './utilities';\r\nimport { isDevMode } from '../electron-modules';\r\nimport GPUPicker from './gpu-picker';\r\nimport { throttle } from 'throttle-debounce';\r\nimport { AerialViewState, SceneCameraState } from '../redux/camera-slice';\r\nimport { ImageLabelTools, OrthoCategory } from './labelling';\r\nimport {\r\n Vector3,\r\n PerspectiveCamera,\r\n WebGLRenderer,\r\n TextureLoader,\r\n Line3,\r\n Color,\r\n Scene,\r\n Box3,\r\n Frustum,\r\n Matrix4\r\n} from \"three\";\r\nimport Stats from '../stats.module.js';\r\nimport { RenderUtils } from './rendering';\r\nimport { MultiImageWindow } from './controls';\r\nimport onresize from \"resize-event\";\r\nimport { TagsHandler, TagItem, boundingBoxForTags } from './tags';\r\nimport {toast} from '../app';\r\nimport { updateMouseCoords } from '../app-bar';\r\nimport { CADHandler } from './linework';\r\nimport { t } from '../localization';\r\nimport { setCameraState } from './viewer';\r\nimport path from 'path';\r\nimport { VolumeType, SamplingRate, MeasureType, AerialMeasureType } from '../types/measurements';\r\nimport { WebSourceHandler } from './web-sources';\r\nimport { RayCaster } from './ray-caster';\r\nimport { showTagDetails } from '../folder';\r\nimport { tagQueryString } from '../urls';\r\nimport { AnnotationDrawType, AnnotationSize } from '../types/tags';\r\nimport { TagAnnotation } from '../redux/assets-slice';\r\nimport { Units } from '../types/project';\r\nimport { ObservationType } from '../types/aligner';\r\n\r\nconst newLabelStyle = {\r\n transform: \"translate(-50%, -50%)\",\r\n background: \"rgba(0,0,0,0.6)\",\r\n cursor: \"pointer\",\r\n borderRadius: \"4px\",\r\n color: \"white\",\r\n fontSize: \"0.7em\",\r\n padding: \"4px 8px\",\r\n position: \"absolute\",\r\n whiteSpace: \"nowrap\",\r\n userSelect: \"none\"\r\n};\r\n\r\ntype GPUPickerName = \"markers\" | \"tags\" | \"default\"\r\n\r\nexport interface ViewerProps {\r\n compassClassName: string;\r\n setMeasurements: React.Dispatch;\r\n setCategoryList: React.Dispatch;\r\n setTrainingArea: React.Dispatch;\r\n setMarkupGroups: React.Dispatch;\r\n setMultiImageOpen: React.Dispatch;\r\n setMultiImageState: React.Dispatch;\r\n setPointProfileOpen: React.Dispatch;\r\n setLocalObservations: React.Dispatch;\r\n setAlignerObservations: React.Dispatch;\r\n}\r\n\r\nexport class Viewer {\r\n public readonly containerElement: HTMLElement;\r\n public defaultFarPlane: number = 10000;\r\n private defaultNearPlane: number = 0.1;\r\n public pixelRatio = 1.0;\r\n public camera: PerspectiveCamera;\r\n public renderer: WebGLRenderer;\r\n public gpuPickers: {\r\n default: GPUPicker,\r\n markers: GPUPicker,\r\n tags: GPUPicker\r\n };\r\n private backgroundScene: Scene;\r\n public imageLabels: ImageLabelTools;\r\n public renderUtils: RenderUtils;\r\n private changeDetector: ChangeDetector;\r\n public compass: CompassControls;\r\n public controls: PanoControls;\r\n public pointclouds: PointCloudManager;\r\n public cameraHandler: CameraHandler;\r\n public minimap: AerialMap;\r\n public measurements: MeasurementController;\r\n public cadHandler: CADHandler;\r\n public webmapHandler: WebSourceHandler;\r\n public tagsHandler: TagsHandler;\r\n public multiImageWindow: MultiImageWindow;\r\n private stats: StatsPanel;\r\n public mouseCoords: Vector3;\r\n private updateMouseCoords: Function;\r\n private sceneLabels = [];\r\n private enabled = true;\r\n public isEmpty = true;\r\n private focused = false;\r\n private drawPickerScene = false;\r\n public expanded = false;\r\n public projectName;\r\n private observer;\r\n\r\n // TODO: add intial aerial state, and make these... nicer?\r\n private initialZoomApplied = false;\r\n private initialStateApplied = false;\r\n\r\n public timingDebug = {\r\n \"markers\": false,\r\n \"scene\": false\r\n };\r\n\r\n constructor(viewContainer, mapContainer, props: ViewerProps) {\r\n this.containerElement = viewContainer;\r\n\r\n this.initRenderer();\r\n this.initGpuPickers();\r\n this.initEvents();\r\n this.updateCamera();\r\n\r\n this.updateMouseCoords = throttle(100, (event) => {\r\n let coords = event\r\n ? this.controls.getPickerResults(event).coordinate\r\n : null;\r\n\r\n updateMouseCoords(coords);\r\n });\r\n\r\n const capabilities = this.renderer.capabilities;\r\n const maxTextureSize = capabilities.maxTextureSize;\r\n\r\n this.compass = new CompassControls(this, props);\r\n this.pointclouds = new PointCloudManager(this);\r\n this.controls = new PanoControls(this, this.camera,\r\n this.renderer.domElement, props);\r\n this.measurements = new MeasurementController(this, props);\r\n this.minimap = new AerialMap(this, mapContainer);\r\n this.cameraHandler = new CameraHandler(this, maxTextureSize);\r\n this.tagsHandler = new TagsHandler(this);\r\n this.cadHandler = new CADHandler(this);\r\n this.webmapHandler = new WebSourceHandler(this);\r\n this.imageLabels = new ImageLabelTools(this, props);\r\n this.changeDetector = new ChangeDetector(this);\r\n this.multiImageWindow = new MultiImageWindow(this, props);\r\n this.stats = new StatsPanel(this);\r\n\r\n this.addContainerElements();\r\n this.initResize();\r\n this.animate();\r\n }\r\n\r\n get width(): number {\r\n return this.containerElement.offsetWidth;\r\n }\r\n\r\n get height(): number {\r\n return this.containerElement.offsetHeight;\r\n }\r\n\r\n get near() {\r\n return this.camera.near;\r\n }\r\n\r\n get far() {\r\n return this.camera.far;\r\n }\r\n\r\n get fov() {\r\n return this.camera.fov;\r\n }\r\n\r\n get orthoList() {\r\n return this.minimap.orthoList;\r\n }\r\n\r\n get lookatVector() {\r\n return new Vector3(0, 0, -1)\r\n .applyQuaternion(this.camera.quaternion);\r\n }\r\n\r\n get upVector() {\r\n return new Vector3(0, 1, 0)\r\n .applyQuaternion(this.camera.quaternion);\r\n }\r\n\r\n get rightVector() {\r\n return new Vector3(1, 0, 0)\r\n .applyQuaternion(this.camera.quaternion);\r\n }\r\n\r\n get orbitState(): boolean {\r\n return this.controls.orbitControls.state;\r\n }\r\n\r\n get cameraSelected() {\r\n return this.cameraHandler.cameraLoaded;\r\n }\r\n\r\n get hasPoints() {\r\n return !this.pointclouds.isEmpty;\r\n }\r\n\r\n get hasCameras() {\r\n return !this.cameraHandler.isEmpty;\r\n }\r\n\r\n get hasModels() {\r\n return this.cadHandler.numberOfFiles > 0;\r\n }\r\n\r\n get hasTags() {\r\n return this.tagsHandler.numberOfFiles > 0;\r\n }\r\n\r\n get isImageOnly() {\r\n return this.hasCameras && !this.hasPoints;\r\n }\r\n\r\n get isPointsOnly() {\r\n return !this.hasCameras && this.hasPoints;\r\n }\r\n\r\n get showCompassElement() {\r\n if (!LocalScene.initialized) return false;\r\n let show = this.orbitState;\r\n\r\n if (this.hasCameras) {\r\n // Current camera is done loading (or there is no camera selected)\r\n let currentCamera = this.cameraHandler.current;\r\n show = currentCamera\r\n ? currentCamera.loaded || currentCamera.loading\r\n : true;\r\n }\r\n\r\n return show;\r\n }\r\n\r\n get initialCameraLoading() {\r\n return this.cameraHandler.newCameraLoading\r\n && !this.cameraHandler.cameraLoadedOnce;\r\n }\r\n\r\n get aerialState() {\r\n return this.minimap.aerialState;\r\n }\r\n\r\n get sceneState() {\r\n let state = {\r\n camera: null,\r\n fov: null,\r\n lookat: null,\r\n angles: null,\r\n orbit: null,\r\n pivot: null\r\n } as SceneCameraState;\r\n\r\n if (this.orbitState) {\r\n // Update for orbit camera\r\n let {orbit, pivot} = this.controls.orbitControls.getPositionValues();\r\n\r\n state = {\r\n ...state,\r\n orbit: orbit,\r\n pivot: pivot\r\n };\r\n } else if (this.cameraHandler.current) {\r\n // Update for standard camera\r\n state = {\r\n ...state,\r\n camera: this.cameraHandler.current.id,\r\n fov: this.controls.fov,\r\n angles: this.controls.angles\r\n };\r\n }\r\n\r\n return state;\r\n }\r\n\r\n /** Exposed Global Methods */\r\n setExpanded(state: boolean) {\r\n this.expanded = state;\r\n }\r\n\r\n setContainerCursor(cursor) {\r\n this.containerElement.style.cursor = cursor;\r\n }\r\n\r\n addContainerElements() {\r\n this.containerElement.appendChild(this.renderer.domElement);\r\n this.containerElement.appendChild(this.compass.domElement);\r\n }\r\n\r\n removeContainerElements() {\r\n this.containerElement.removeChild(this.renderer.domElement);\r\n this.containerElement.removeChild(this.compass.domElement);\r\n }\r\n\r\n setProjectName(name: string) {\r\n this.projectName = name;\r\n }\r\n\r\n togglePickerDebug(value) {\r\n this.drawPickerScene = value;\r\n }\r\n\r\n getAvailableClassifications(): number[] {\r\n return this.pointclouds.uniqueClassifications;\r\n }\r\n\r\n setVisibleClassifications(classifications) {\r\n this.pointclouds.setVisibleClassifications(classifications);\r\n }\r\n\r\n setPointsRenderPaused(state: boolean) {\r\n this.pointclouds.shouldUpdate = !state;\r\n }\r\n\r\n setPointBoundsVisible(state: boolean) {\r\n this.pointclouds.boundsVisible = state;\r\n }\r\n\r\n setPointCloudOpacity(opacity: number) {\r\n this.pointclouds.transparency = opacity;\r\n }\r\n\r\n setPointCloudMinimum(size: number) {\r\n this.pointclouds.setPointCloudMinimum(size);\r\n }\r\n\r\n setPointCloudScale(size: number) {\r\n this.pointclouds.setPointCloudScale(size);\r\n }\r\n\r\n setPointCloudMaxPoints(points: number) {\r\n this.pointclouds.visiblePointsTarget = points * 1000000;\r\n }\r\n\r\n setPointCloudHeightClip(clamp: Clamp) {\r\n this.pointclouds.updateClamping('heightClamp', clamp);\r\n }\r\n\r\n setPointCloudIntensityClip(clamp: Clamp) {\r\n this.pointclouds.updateClamping('intensityClamp', clamp);\r\n }\r\n\r\n setPointCloudColorMap(colorMapKey: ColorMapKey) {\r\n const textureData = getColorMap(colorMapKey).image;\r\n\r\n const loader = new TextureLoader();\r\n loader.load(textureData, texture => {\r\n this.pointclouds.materialDefaults.colorMap = colorMapKey;\r\n this.pointclouds.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.colorMap = texture;\r\n material.colorMap.needsUpdate = true;\r\n });\r\n });\r\n });\r\n }\r\n\r\n setPointCloudColorType(colorType: ColorType) {\r\n this.pointclouds.materialDefaults.colorType = colorType;\r\n this.pointclouds.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.colorType = colorType;\r\n });\r\n });\r\n }\r\n\r\n setPointCloudDynamicSize(state: boolean) {\r\n this.pointclouds.materialDefaults.dynamicSize = state;\r\n this.pointclouds.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.adaptiveSize = state;\r\n });\r\n });\r\n }\r\n\r\n setPointCloudCircularPoints(state: boolean) {\r\n this.pointclouds.materialDefaults.circularPoints = state;\r\n this.pointclouds.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.circularPoints = state;\r\n });\r\n });\r\n }\r\n\r\n setPointCloudDistance(distance: number) {\r\n this.pointclouds.drawDistance = distance;\r\n this.updatePicker(\"default\");\r\n }\r\n\r\n setTagDistance(distance: number) {\r\n this.tagsHandler.drawDistance = distance;\r\n this.updatePicker(\"tags\");\r\n }\r\n\r\n setModelDistance(distance: number) {\r\n this.cadHandler.drawDistance = distance;\r\n this.updatePicker(\"default\");\r\n }\r\n\r\n setNavigationType(type: MarkerNavType) {\r\n this.cameraHandler.setNavigationType(type);\r\n }\r\n\r\n setControlType(type: number) {\r\n this.controls.setControlType(type);\r\n }\r\n\r\n setOrbitValues(state: boolean) {\r\n this.controls.setOrbitValues(state);\r\n }\r\n\r\n resetCamera() {\r\n this.controls.resetCamera(\"top\");\r\n }\r\n\r\n /** NOTE: Temporary(?) solution for the viewer being created over and over again */\r\n destroy() {\r\n this.observer.disconnect();\r\n\r\n // Destroy viewer + events\r\n this.enabled = false;\r\n this.camera = null;\r\n this.removeContainerElements();\r\n this.removeEvents();\r\n\r\n this.minimap.destroy();\r\n this.controls.destroy();\r\n this.orthoList.destroy();\r\n this.multiImageWindow.destroy();\r\n }\r\n\r\n getDataProjection() {\r\n return LocalScene.dataProjection;\r\n }\r\n\r\n setDataProjection(newProjection) {\r\n LocalScene.setDataProjection(newProjection);\r\n }\r\n\r\n getViewProjection() {\r\n return LocalScene.viewProjection;\r\n }\r\n\r\n setViewProjection(newProjection) {\r\n LocalScene.setViewProjection(newProjection);\r\n }\r\n\r\n setMeasurementUnits(units: Units) {\r\n this.controls.measurements.setUnits(units);\r\n }\r\n\r\n setActiveAlignment(id) {\r\n this.measurements.setActiveAlignment(id);\r\n }\r\n\r\n async loadImage(cameraID: string, opts: CameraLoadOptions = {}) {\r\n this.setInitialZoomFlag(true);\r\n let newCamera = await this.cameraHandler.loadImage(cameraID, opts);\r\n return newCamera;\r\n }\r\n\r\n /** @private */\r\n setCameraState(state: SceneCameraState) {\r\n if (this.initialStateApplied) return false;\r\n\r\n if (state.camera || state.lookat) {\r\n if (this.cameraHandler.loadSavedCameraState(state)) {\r\n this.setInitialStateFlag(true);\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /** @private */\r\n setOrbitState(state: SceneCameraState) {\r\n if (this.initialStateApplied) return false;\r\n\r\n const has3dAssets = this.hasModels || this.hasTags || this.hasPoints;\r\n if (!has3dAssets) return false;\r\n\r\n if (state.orbit && state.pivot) {\r\n if (!this.orbitState) {\r\n // Move to orbit mode with default lookat\r\n this.controls.setOrbitValues(true);\r\n }\r\n\r\n const newPosition = {\r\n orbit: new DataProjectionCoordinate(state.orbit).toScene(),\r\n pivot: new DataProjectionCoordinate(state.pivot).toScene(),\r\n smooth: false\r\n };\r\n\r\n // Apply new positions to orbit camera\r\n this.controls.setOrbitValues(true, newPosition);\r\n this.setInitialZoomFlag(true);\r\n this.setInitialStateFlag(true);\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n /** @private */\r\n setTagState(tagID: string) {\r\n if (this.initialStateApplied) return false;\r\n\r\n this.jumpToTag(tagID, true);\r\n this.setInitialStateFlag(true);\r\n return true;\r\n }\r\n\r\n clearHighlightedLinework() {\r\n this.cadHandler.clearHighlightedFiles();\r\n }\r\n\r\n getAerialZoomLevel() {\r\n return this.minimap?.map.getView().getZoom();\r\n }\r\n\r\n getCameraPosition() {\r\n return new SceneCoordinate(this.camera.position)\r\n .toDataProjection();\r\n }\r\n\r\n getCameraFrustum() {\r\n // Calculate current view frustum\r\n this.camera.updateProjectionMatrix();\r\n this.camera.updateMatrixWorld(true);\r\n this.camera.matrixWorldInverse\r\n .copy(this.camera.matrixWorld)\r\n .invert();\r\n\r\n let cameraViewProjectionMatrix = new Matrix4();\r\n cameraViewProjectionMatrix.multiplyMatrices(\r\n this.camera.projectionMatrix,\r\n this.camera.matrixWorldInverse\r\n );\r\n\r\n let frustum = new Frustum();\r\n frustum.setFromProjectionMatrix(cameraViewProjectionMatrix);\r\n return frustum;\r\n }\r\n\r\n isBehindCamera(position: Vector3) {\r\n const start = new Vector3()\r\n .add(this.camera.position);\r\n\r\n const end = new Vector3()\r\n .add(this.camera.position)\r\n .add(this.lookatVector);\r\n\r\n const line = new Line3(start, end);\r\n return line.closestPointToPointParameter(position) < 0;\r\n }\r\n\r\n /** Scene labels */\r\n addSceneLabel(text: string, position: number[], onClick = null, customStyle = null) {\r\n const div = document.createElement(\"div\");\r\n\r\n Object.keys(newLabelStyle).forEach(key => {\r\n div.style[key] = newLabelStyle[key];\r\n });\r\n\r\n if (customStyle) {\r\n Object.keys(customStyle).forEach(key => {\r\n div.style[key] = customStyle[key];\r\n });\r\n }\r\n\r\n div.innerHTML = text;\r\n\r\n if (onClick) {\r\n div.onclick = onClick;\r\n } else {\r\n div.style.pointerEvents = \"none\";\r\n }\r\n\r\n const label = {\r\n position: position,\r\n element: div\r\n };\r\n\r\n this.sceneLabels.push(label);\r\n this.containerElement.appendChild(label.element);\r\n\r\n return label;\r\n }\r\n\r\n removeSceneLabel(annotation) {\r\n const index = this.sceneLabels.indexOf(annotation);\r\n this.sceneLabels.splice(index, 1);\r\n this.containerElement.removeChild(annotation.element);\r\n }\r\n\r\n /** Tag Annotations */\r\n toggleTagAnnotations(state: boolean) {\r\n this.tagsHandler.toggleAnnotations(state);\r\n }\r\n\r\n setTagAnnotationDrawing(drawing: boolean) {\r\n this.tagsHandler.setAnnotationDrawing(drawing);\r\n }\r\n\r\n setTagAnnotationType(type: AnnotationDrawType) {\r\n this.tagsHandler.setAnnotationType(type);\r\n }\r\n\r\n setTagAnnotationColor(color: string) {\r\n this.tagsHandler.setAnnotationColor(color);\r\n }\r\n\r\n setTagAnnotationSize(size: AnnotationSize) {\r\n this.tagsHandler.setAnnotationSize(size);\r\n }\r\n\r\n getTagAnnotations() {\r\n return this.tagsHandler.getAnnotations();\r\n }\r\n\r\n loadTagAnnotations(annotations: TagAnnotation[]) {\r\n this.tagsHandler.loadAnnotations(annotations);\r\n }\r\n\r\n /** Local Aligner */\r\n toggleLocalAligner(state: boolean) {\r\n this.controls.localAligner.setState(state);\r\n }\r\n\r\n estimateLocalTransform = (estimator: string, units: string) => {\r\n return this.controls.localAligner.getLocalProjection(estimator, units);\r\n };\r\n\r\n clearLocalTransformErrors = () => {\r\n this.controls.localAligner.resetErrorValues();\r\n };\r\n\r\n refreshLocalTransform() {\r\n this.controls.localAligner.drawObservations();\r\n }\r\n\r\n generateLocalAlignerRows(numRows) {\r\n this.controls.localAligner.addNewObservations(numRows);\r\n }\r\n\r\n setLocalAlignerActive(id, type) {\r\n this.controls.localAligner.setActiveObservation(id, type);\r\n };\r\n\r\n deleteLocalAlignment(id) {\r\n this.controls.localAligner.removeByID(id);\r\n }\r\n\r\n /** Point Markup */\r\n pointMarkupActive() {\r\n return this.controls.pointMarkup.active;\r\n }\r\n\r\n addPointMarkupOperation(type, name) {\r\n this.controls.pointMarkup.addNewGroup(type, name);\r\n }\r\n\r\n updatePointMarkupName(id, name) {\r\n this.controls.pointMarkup.setName(id, name);\r\n }\r\n\r\n setPointMarkupActive(id) {\r\n this.controls.pointMarkup.setActive(id);\r\n }\r\n\r\n pointMarkupToggle(state: boolean) {\r\n this.controls.pointMarkup.setState(state);\r\n }\r\n\r\n clearPointMarkup() {\r\n this.controls.pointMarkup.clear();\r\n }\r\n\r\n pointMarkupZoom(id) {\r\n this.controls.pointMarkup.zoom(id);\r\n }\r\n\r\n pointMarkupDeleteGroup(id) {\r\n this.controls.pointMarkup.removeClippingGroup(id);\r\n }\r\n\r\n pointMarkupDeleteBox(id) {\r\n this.controls.pointMarkup.removeClippingBox(id);\r\n }\r\n\r\n pointMarkupNameExists(name) {\r\n return this.controls.pointMarkup.clippingGroups\r\n .filter(x => x.name === name).length > 0;\r\n }\r\n\r\n setPointMarkupNewClassification(id, value) {\r\n this.controls.pointMarkup.setNewClassification(id, value);\r\n }\r\n\r\n setPointMarkupIgnoredClassification(id, value) {\r\n this.controls.pointMarkup.setIgnoredClassification(id, value);\r\n }\r\n\r\n resetPointMarkupRotation(id) {\r\n this.controls.pointMarkup.resetRotation(id);\r\n }\r\n\r\n setPointMarkupHover(id, hover) {\r\n this.controls.pointMarkup.setHover(id, hover);\r\n }\r\n\r\n /** Multi Image Window */\r\n initMultiImageContainer(container) {\r\n this.multiImageWindow.init(container);\r\n }\r\n\r\n toggleMultiImageWindow(state: boolean) {\r\n this.multiImageWindow.setState(state);\r\n }\r\n\r\n closeMultiImageWindow() {\r\n this.multiImageWindow.close();\r\n }\r\n\r\n async getMultiImageCoordinate(event): Promise {\r\n /** Use the multi-image measurements to get a single position */\r\n return new Promise((resolve) => {\r\n const multiImage = this.multiImageWindow;\r\n const raycaster = new RayCaster(this, event);\r\n const direction = raycaster.direction;\r\n const position = this.camera.position;\r\n\r\n const onComplete = () => {\r\n const coordinate = multiImage.getClickedPoint();\r\n\r\n if (coordinate) {\r\n multiImage.close();\r\n resolve(new SceneCoordinate(coordinate));\r\n } else {\r\n resolve(null);\r\n }\r\n };\r\n\r\n multiImage.show({\r\n onComplete,\r\n canComplete: true,\r\n canAddMore: false,\r\n });\r\n\r\n multiImage.addFirstObservation(position, direction);\r\n });\r\n }\r\n\r\n multiImageNextImage() {\r\n this.multiImageWindow.loadNextImage();\r\n }\r\n\r\n multiImagePreviousImage() {\r\n this.multiImageWindow.loadPreviousImage();\r\n }\r\n\r\n multiImageOnComplete() {\r\n this.multiImageWindow.onComplete();\r\n }\r\n\r\n multiImageOnAddPoint() {\r\n this.multiImageWindow.onAddPoint();\r\n }\r\n\r\n multiImageOnClose() {\r\n return this.multiImageWindow.onClose();\r\n }\r\n\r\n /** Point Profile */\r\n initProfileContainer(type, units: Units) {\r\n this.controls.pointProfile.profileChart.init(type, units);\r\n }\r\n\r\n resetPointProfile() {\r\n this.controls.pointProfile.reset();\r\n }\r\n\r\n refreshPointProfile() {\r\n this.controls.pointProfile.updatePoints();\r\n }\r\n\r\n resetPointProfileView() {\r\n this.controls.pointProfile.resetZoom();\r\n }\r\n\r\n pointProfileActive() {\r\n return this.controls.pointProfile.drawing;\r\n }\r\n\r\n pointProfileStart(coordinate) {\r\n this.controls.pointProfile.selectStart(coordinate);\r\n }\r\n\r\n pointProfileEnd() {\r\n this.controls.pointProfile.selectEnd();\r\n }\r\n\r\n pointProfileCancel() {\r\n this.controls.pointProfile.selectCancel();\r\n }\r\n\r\n setPointProfileUnits(units: Units) {\r\n this.controls.pointProfile.updateUnits(units);\r\n }\r\n\r\n setPointProfileSampling(type) {\r\n this.controls.pointProfile.updateSampling(type);\r\n }\r\n\r\n getPointProfileImage() {\r\n return this.controls.pointProfile.getProfileImage();\r\n }\r\n\r\n /** Measurements */\r\n toggleMeasurements(state: boolean) {\r\n this.controls.measurements.setState(state);\r\n }\r\n\r\n updateVolumeType(type: VolumeType) {\r\n this.controls.measurements.setVolumeType(type);\r\n }\r\n\r\n setAerialMeasureType(type: AerialMeasureType) {\r\n this.controls.measurements.setAerialMeasureType(type);\r\n }\r\n\r\n setAerialBasemap(basemap: string) {\r\n this.minimap.setVisibleBasemap(basemap);\r\n }\r\n\r\n updateVolumeSampleRate(rate: SamplingRate) {\r\n this.controls.measurements.setSampleRate(rate);\r\n }\r\n\r\n setMeasurementType(type: MeasureType) {\r\n this.controls.measurements.setMeasurementType(type);\r\n }\r\n\r\n updateMeasureHover(measurement: Measurement, state) {\r\n this.controls.measurements.setHover(measurement, state);\r\n }\r\n\r\n deleteMeasurement(measurement: Measurement) {\r\n this.controls.measurements.removeByID(measurement.id);\r\n }\r\n\r\n renameMeasurement(measurement: Measurement, title) {\r\n this.controls.measurements.setTitle(measurement.id, title);\r\n }\r\n\r\n exportMeasurements(type, ordering) {\r\n this.controls.measurements.export(type, ordering);\r\n }\r\n\r\n getMeasurementFormatter() {\r\n return this.controls.measurements.formatter;\r\n }\r\n\r\n loadMeasurementData(data) {\r\n return this.controls.measurements.loadMeasurementData(data);\r\n }\r\n\r\n /** Ortho Viewer */\r\n setOrthoOpacity(value) {\r\n this.orthoList.setOpacity(value);\r\n }\r\n\r\n /** Labelling/Annotation */\r\n activeImageLabelPaths() {\r\n return this.imageLabels.activeImagePaths();\r\n }\r\n\r\n activeImages() {\r\n return this.imageLabels.activeImages();\r\n }\r\n\r\n loadedImageLabelPaths() {\r\n return this.imageLabels.loadedImagePaths();\r\n }\r\n\r\n async loadImageLabelData(data, progressCallback, overwrite, checkOverlap) {\r\n await this.imageLabels.loadImageLabelData(\r\n data, progressCallback, overwrite, checkOverlap);\r\n }\r\n\r\n setActiveLabelType(state: boolean) {\r\n this.imageLabels.setActiveLabelType(state);\r\n }\r\n\r\n get numLabels() {\r\n return this.imageLabels.numLabels;\r\n }\r\n\r\n labelSelected() {\r\n return this.imageLabels.checkIfSelected();\r\n }\r\n\r\n labelHotkey(event) {\r\n this.imageLabels.onKeyDown(event);\r\n }\r\n\r\n setLabelText(id, text) {\r\n this.imageLabels.setText(id, text);\r\n }\r\n\r\n setLabelFindText(id) {\r\n this.imageLabels.setFindText(id);\r\n }\r\n\r\n addCategory(category) {\r\n this.imageLabels.addCategory(category);\r\n }\r\n\r\n deleteCategory(id) {\r\n this.imageLabels.deleteCategory(id);\r\n }\r\n\r\n getAllCategories() {\r\n const categories = [];\r\n this.imageLabels.categories.forEach(category => {\r\n categories.push(category);\r\n });\r\n if (this.imageLabels.trainingArea) {\r\n categories.push(this.imageLabels.trainingArea);\r\n }\r\n return categories;\r\n }\r\n\r\n toggleCategoryVisibility(id, state) {\r\n this.imageLabels.toggleCategoryVisibility(id, state);\r\n }\r\n\r\n addTrainingArea() {\r\n this.imageLabels.addTrainingArea();\r\n }\r\n\r\n deleteHighlighted() {\r\n this.imageLabels.deleteHighlighted();\r\n }\r\n\r\n editCategoryName(id, name) {\r\n this.imageLabels.editCategoryName(id, name);\r\n }\r\n\r\n deleteAllCategories() {\r\n this.imageLabels.deleteAllCategories();\r\n }\r\n\r\n deleteTrainingArea() {\r\n this.imageLabels.deleteTrainingArea();\r\n }\r\n\r\n deleteLabel(id) {\r\n this.imageLabels.deleteLabel(id);\r\n }\r\n\r\n zoomToLabel(id) {\r\n this.imageLabels.zoomToLabel(id);\r\n }\r\n\r\n addLabel(id) {\r\n this.imageLabels.addLabel(id);\r\n }\r\n\r\n addTrainingAreaLabel() {\r\n this.imageLabels.addTrainingAreaLabel();\r\n }\r\n\r\n currentCategory() {\r\n return this.imageLabels.currentCategoryName;\r\n }\r\n\r\n getIndexInList(category) {\r\n return this.imageLabels.getIdxInList(category);\r\n }\r\n\r\n getCategoryByLabelID(labelID) {\r\n return this.imageLabels.getCategoryByLabelID(labelID);\r\n }\r\n\r\n transferLabel(labelIDs, newCategoryID) {\r\n return this.imageLabels.transferLabel(labelIDs, newCategoryID);\r\n }\r\n\r\n selectLabel(id) {\r\n this.imageLabels.selectLabel(id);\r\n }\r\n\r\n deleteLabelPoint(pointID) {\r\n this.imageLabels.deletePoint(pointID);\r\n }\r\n\r\n insertLabelPoint(id, coord) {\r\n this.imageLabels.insertPoint(id, coord);\r\n }\r\n\r\n editLabel(id, coord) {\r\n this.imageLabels.editLabel(id, coord);\r\n }\r\n\r\n moveToLabel(id) {\r\n this.imageLabels.moveToLabelInList(id);\r\n }\r\n\r\n completeLabel(label) {\r\n this.imageLabels.completeLabel(label);\r\n }\r\n\r\n unHighlight(id) {\r\n this.imageLabels.unHighlight(id);\r\n }\r\n\r\n unHighlightAll() {\r\n this.imageLabels.unHighlightAll();\r\n }\r\n\r\n highlightedLabels() {\r\n return this.imageLabels.highlightedLabels();\r\n }\r\n\r\n sortCategory = (category, score, sortType) => {\r\n this.imageLabels.sortCategory(category, score, sortType);\r\n };\r\n\r\n undoSort = (category) => {\r\n this.imageLabels.undoSort(category);\r\n };\r\n\r\n numLabelsHighlighted() {\r\n return this.imageLabels.numHighlighted;\r\n }\r\n\r\n checkCategoryUniqueness(categoryName) {\r\n return this.imageLabels.checkUniqueName(categoryName);\r\n }\r\n\r\n labelObject = () => {\r\n return this.imageLabels.labelObject();\r\n };\r\n\r\n getOrthoLabelPolygons = () => {\r\n if (!this.imageLabels.isAerialLabels) return;\r\n\r\n const data = {};\r\n\r\n this.imageLabels.categories.forEach((category: OrthoCategory) => {\r\n const segments = category.labels\r\n .filter(label => label.valid)\r\n .map(label => {\r\n return label.polygonPointsOnly.map(coord => {\r\n return new ProjectedCoordinate(coord, webMercator)\r\n .toDataProjection()\r\n .toArray()\r\n .slice(0, 2);\r\n });\r\n });\r\n\r\n data[category.name] = segments;\r\n });\r\n\r\n return data;\r\n };\r\n\r\n anyLabelSelected = () => {\r\n return this.imageLabels.checkIfSelected();\r\n };\r\n\r\n getLasFileInfo(id) {\r\n const pointCloud = this.pointclouds.getByID(id);\r\n if (!pointCloud) return;\r\n if (!(pointCloud instanceof GenericPointCloud)) return;\r\n\r\n return pointCloud.headerFileInfo;\r\n }\r\n\r\n /** Asset Click */\r\n\r\n snapToFolder(assetIDs) {\r\n const boundingBoxes: Box3[] = [];\r\n\r\n assetIDs.forEach(assetID => {\r\n const file = this.cadHandler.getByID(assetID);\r\n if (file) {\r\n boundingBoxes.push(file.boundingBox);\r\n }\r\n\r\n const pointCloud = this.pointclouds.getByID(assetID);\r\n if (pointCloud) {\r\n boundingBoxes.push(pointCloud.tightBoundingBox);\r\n }\r\n\r\n const tagFile = this.tagsHandler.getByID(assetID);\r\n if (tagFile) {\r\n const tagBBOX = boundingBoxForTags(tagFile.tags);\r\n boundingBoxes.push(tagBBOX);\r\n }\r\n });\r\n\r\n const combinedBounds = mergeBoundingBoxes(boundingBoxes);\r\n\r\n this.setInitialZoomFlag(false);\r\n this.zoomToSceneExtent(combinedBounds, true);\r\n }\r\n\r\n snapToOrtho(id) {\r\n const ortho = this.minimap.orthoList.getByID(id);\r\n if (!ortho) return;\r\n\r\n ortho.zoomToExtent();\r\n }\r\n\r\n snapToModel(id) {\r\n const file = this.cadHandler.getByID(id);\r\n if (!file) return;\r\n\r\n this.setInitialZoomFlag(false);\r\n this.zoomToSceneExtent(file.boundingBox, true);\r\n }\r\n\r\n snapToPointCloud(id) {\r\n const pointCloud = this.pointclouds.getByID(id);\r\n if (!pointCloud) return;\r\n\r\n this.setInitialZoomFlag(false);\r\n this.zoomToSceneExtent(pointCloud.tightBoundingBox, true);\r\n }\r\n\r\n snapToImages(assetID) {\r\n const features = this.getCamerasByCSV(assetID)\r\n .map(camera => camera.feature);\r\n\r\n if (features.length === 0) return;\r\n\r\n let positions = features.map(x => x.getGeometry().getCoordinates());\r\n let extent = extentFromPoints(positions, false);\r\n this.minimap.setMapExtent(extent);\r\n }\r\n\r\n zoomToSceneExtent(boundingBox, smooth: boolean) {\r\n if (!boundingBox || this.initialZoomApplied) return;\r\n\r\n try {\r\n this.setInitialZoomFlag(true);\r\n\r\n let newPosition = this.controls.orbitFromBounds(\r\n boundingBox, \"top\", smooth);\r\n\r\n // Apply new positions to orbit camera\r\n this.controls.setOrbitValues(true, newPosition);\r\n\r\n // Zoom to map extent\r\n let positions = [boundingBox.min, boundingBox.max].map(position => {\r\n return new SceneCoordinate(position).toDataProjection();\r\n });\r\n\r\n let extent = extentFromPoints(positions);\r\n this.minimap.setMapExtent(extent);\r\n } catch (err) {\r\n console.error(\"Error zooming to extent\", boundingBox);\r\n }\r\n }\r\n\r\n /** Camera Aligner */\r\n toggleCameraAligner(state: boolean) {\r\n this.controls.cameraAlignerAdv.setState(state);\r\n }\r\n\r\n resetCameraAligner() {\r\n this.controls.cameraAlignerAdv.reset();\r\n }\r\n\r\n generateAdvancedAlignerRows(numRows) {\r\n this.controls.cameraAlignerAdv.addNewObservations(numRows);\r\n }\r\n\r\n setErrorsCameraAligner(errors) {\r\n this.controls.cameraAlignerAdv.setErrors(errors);\r\n }\r\n\r\n clearErrorsCameraAligner() {\r\n this.controls.cameraAlignerAdv.clearErrors();\r\n }\r\n\r\n deleteRowCameraAligner(i) {\r\n this.controls.cameraAlignerAdv.removeByID(i);\r\n }\r\n\r\n setBasicAlignerState(state: boolean) {\r\n this.controls.cameraAlignerBasic.setState(state);\r\n }\r\n\r\n resetBasicAlignerCamera(values = [0, 0, 0]) {\r\n this.controls.cameraAlignerBasic.reset(values);\r\n }\r\n\r\n getBasicAlignerValue() {\r\n return this.controls.cameraAlignerBasic.cameraAngles;\r\n }\r\n\r\n flashObservations(id: string) {\r\n this.controls.cameraAlignerAdv.flashObservations(id);\r\n }\r\n\r\n setCurrentObservation(id: string, type: ObservationType) {\r\n this.controls.cameraAlignerAdv.setCurrentObservation(id, type);\r\n }\r\n\r\n /** Panoramic/Planar image functions */\r\n\r\n getCurrentCamera() {\r\n return this.cameraHandler.current;\r\n }\r\n\r\n getNextCamera() {\r\n const index = this.cameraHandler.getNextIndex();\r\n return this.cameraHandler.cameras[index];\r\n }\r\n\r\n getPreviousCamera() {\r\n const index = this.cameraHandler.getPreviousIndex();\r\n return this.cameraHandler.cameras[index];\r\n }\r\n\r\n getCurrentCameraName() {\r\n return this.cameraHandler.current?.name;\r\n }\r\n\r\n getCurrentCameraIndex() {\r\n return this.cameraHandler.cameras\r\n .indexOf(this.cameraHandler.current);\r\n }\r\n\r\n updateCompass() {\r\n this.compass.addRotationCube();\r\n this.compass.addCompassLetters();\r\n }\r\n\r\n updateCompassOffset(offset) {\r\n this.compass.updateOffset(offset);\r\n }\r\n\r\n getCamerasByCSV = (assetID: string) => {\r\n return this.cameraHandler.getCamerasByCSV(assetID);\r\n };\r\n\r\n getCamerasByFolder = (folderID: string) => {\r\n return this.cameraHandler.getCamerasByFolder(folderID);\r\n };\r\n\r\n getCameraRowsCSV = (cameras: CameraImage[]) => {\r\n return this.cameraHandler.getRowsCSV(cameras);\r\n };\r\n\r\n getAllCameras() {\r\n return this.cameraHandler.cameras;\r\n }\r\n\r\n getCameraFolders(cameras) {\r\n let folderPaths = [];\r\n let previousCSV = null;\r\n\r\n cameras.forEach(camera => {\r\n if (camera.csv === previousCSV) return;\r\n\r\n previousCSV = camera.csv;\r\n const imagePath = camera.path;\r\n folderPaths.push(path.dirname(imagePath));\r\n });\r\n\r\n return folderPaths;\r\n };\r\n\r\n getTagByID = (tagID: string) => {\r\n return this.tagsHandler.getTagByID(tagID);\r\n };\r\n\r\n getTagsByCSV = (assetID: string) => {\r\n return this.tagsHandler.getByID(assetID).tags;\r\n };\r\n\r\n getTagRowsCSV = (tags: TagItem[]) => {\r\n return this.tagsHandler.getRowsCSV(tags);\r\n };\r\n\r\n getModelStatus(assetID) {\r\n let file = this.cadHandler.getByID(assetID);\r\n\r\n return {\r\n assetPercent: file ? file.percent : 0.0,\r\n assetError: file ? file.error : false,\r\n assetIsLarge: false\r\n };\r\n }\r\n\r\n getCloudStatus(assetID) {\r\n let cloud = this.pointclouds.getByID(assetID);\r\n\r\n return {\r\n assetIsLarge: cloud instanceof GenericPointCloud ? cloud.isLargeFile : false,\r\n assetPercent: cloud instanceof GenericPointCloud ? cloud.percent : 0.0,\r\n assetError: cloud ? cloud.error : false\r\n };\r\n }\r\n\r\n setEmptyProject(state: boolean) {\r\n this.isEmpty = state;\r\n\r\n if (!this.isEmpty) return;\r\n this.setInitialZoomFlag(false);\r\n LocalScene.resetSceneShift();\r\n }\r\n\r\n reconcileAssets(assets, savedCameraState: SceneCameraState) {\r\n const {\r\n camerasFiles, pointCloudFiles, orthoFiles,\r\n tagFiles, modelFiles, xmlFiles, webSources\r\n } = assets;\r\n\r\n // Tag CSV files\r\n this.tagsHandler.reconcile(tagFiles);\r\n\r\n // Model/Linework files\r\n this.cadHandler.reconcile(modelFiles);\r\n\r\n // Web sources\r\n this.webmapHandler.reconcile(webSources);\r\n\r\n // LandXML files\r\n this.measurements.reconcileXMLs(xmlFiles);\r\n\r\n // Orthomosaics\r\n this.orthoList.reconcile(orthoFiles);\r\n\r\n // Point Clouds\r\n const {pointCloudsRemoved} =\r\n this.pointclouds.reconcile(pointCloudFiles);\r\n\r\n // Image CSV files\r\n const {cameraFilesAdded, cameraFilesRemoved} =\r\n this.cameraHandler.reconcile(camerasFiles);\r\n\r\n // Try to apply forced tag perspective\r\n if (this.applySavedTagState(tagQueryString, false)) return;\r\n\r\n // Try to apply forced scene state\r\n if (this.applySavedSceneState(savedCameraState, false)) return;\r\n\r\n const allCameras = this.cameraHandler.cameras;\r\n const numberOfCameras = allCameras.length;\r\n\r\n const allPointClouds = this.pointclouds.clouds;\r\n const numberOfPointClouds = allPointClouds.length;\r\n\r\n const numCamerasChanged = cameraFilesAdded + cameraFilesRemoved;\r\n\r\n // All pointclouds have been removed\r\n if ((numberOfPointClouds === 0) && (pointCloudsRemoved > 0) && (numberOfCameras > 0)) {\r\n if (this.cameraHandler.cameraLoaded) {\r\n // Exit 3d mode if camera is loaded\r\n this.controls.setOrbitValues(false);\r\n } else {\r\n // Load first camera\r\n this.loadImage(allCameras[0].id, {\r\n centerOnImage: false\r\n });\r\n }\r\n }\r\n\r\n // Load first camera if nothing is loaded\r\n const loadCamera = (numCamerasChanged > 0)\r\n && !this.cameraHandler.cameraLoaded\r\n && !this.cameraHandler.newCameraLoading\r\n && !this.cameraHandler.cameraLoadedOnce\r\n && (allCameras.length > 0);\r\n\r\n if (loadCamera) {\r\n this.loadImage(allCameras[0].id, {\r\n centerOnImage: false\r\n });\r\n }\r\n }\r\n\r\n clearCurrentCamera() {\r\n this.controls.resetSceneView();\r\n this.minimap.setCurrentCamera(null, false);\r\n this.cameraHandler.setOrbitCamera();\r\n this.cameraHandler.setCurrentImage(null);\r\n this.clearArrowNavigation();\r\n }\r\n\r\n clearArrowNavigation() {\r\n this.cameraHandler.clearArrowNavigation();\r\n }\r\n\r\n showTagDetails(tagID: string) {\r\n showTagDetails(tagID);\r\n }\r\n\r\n /** Mark tag as selected. Default timeout is 1 day */\r\n setTagSelected(tagID: string, timeoutSeconds = 86400) {\r\n this.tagsHandler.setSelected(tagID, timeoutSeconds);\r\n }\r\n\r\n async jumpToTag(tagID: string, showDetails = false) {\r\n const tag = this.tagsHandler.getTagByID(tagID);\r\n if (!tag) return;\r\n\r\n if (showDetails) {\r\n this.showTagDetails(tagID);\r\n } else {\r\n this.setTagSelected(tagID, 10);\r\n }\r\n\r\n const mapPosition = tag.position.aerial;\r\n this.minimap.jumpToPosition(mapPosition);\r\n\r\n const position = tag.position.array;\r\n if (position.length === 2) {\r\n toast.success(t(\"toast.tag-jump-success\"));\r\n return;\r\n }\r\n\r\n if (tag.sceneState) {\r\n // Apply tag scene state\r\n if (this.applySavedSceneState(tag.sceneState, true)) {\r\n toast.success(t(\"toast.tag-jump-success\"));\r\n return;\r\n }\r\n }\r\n\r\n if (this.hasCameras) {\r\n // Tag has not scene state, so we use the closest camera instead\r\n const lookat = new DataProjectionCoordinate(position);\r\n const closestCameraID = this.cameraHandler\r\n .closestCameraToPosition(lookat);\r\n\r\n if (closestCameraID) {\r\n await this.loadImage(closestCameraID, {lookat});\r\n toast.success(t(\"toast.tag-jump-success\"));\r\n } else {\r\n toast.warning(t(\"toast.camera-error-position\"));\r\n }\r\n }\r\n }\r\n\r\n setCameraHeight(height: number) {\r\n this.cameraHandler.setCameraHeight(height);\r\n }\r\n\r\n setCameraAdjustments(adjustments) {\r\n this.cameraHandler.setCameraAdjustments(adjustments);\r\n }\r\n\r\n setCameraMatrix(matrix) {\r\n this.cameraHandler.setCameraMatrix(matrix);\r\n if (this.controls.cameraAlignerAdv.enabled) {\r\n this.controls.cameraAlignerAdv.redrawImageObsMarkers();\r\n }\r\n }\r\n\r\n resetCameraMatrix() {\r\n this.cameraHandler.resetCameraMatrix();\r\n if (this.controls.cameraAlignerAdv.enabled) {\r\n this.controls.cameraAlignerAdv.redrawImageObsMarkers();\r\n }\r\n }\r\n\r\n setInitialZoomFlag(state: boolean) {\r\n this.initialZoomApplied = state;\r\n }\r\n\r\n setInitialStateFlag(state: boolean) {\r\n this.initialStateApplied = state;\r\n }\r\n\r\n applySavedSceneState(state, resetInitialFlag: boolean) {\r\n if (resetInitialFlag) {\r\n this.setInitialStateFlag(false);\r\n }\r\n\r\n return state.orbit\r\n ? this.setOrbitState(state)\r\n : this.setCameraState(state);\r\n };\r\n\r\n applySavedTagState(query: string, resetInitialFlag: boolean) {\r\n const tag = this.tagsHandler.getTagByQuery(query);\r\n if (!tag) return false;\r\n\r\n if (resetInitialFlag) {\r\n this.setInitialStateFlag(false);\r\n }\r\n\r\n return this.setTagState(tag.id);\r\n }\r\n\r\n applySavedAerialState(state: AerialViewState) {\r\n this.minimap.map.updateSize();\r\n this.minimap.resetView(state);\r\n }\r\n\r\n resetTextureCache() {\r\n this.cameraHandler.resetTextureCache();\r\n }\r\n\r\n resetDefaultAerialCamera() {\r\n this.minimap.setCurrentCamera(null, false);\r\n }\r\n\r\n resetDefaultControlState() {\r\n this.setInitialStateFlag(false);\r\n this.controls.resetSceneView();\r\n }\r\n\r\n removeInteractions() {\r\n const measurements = this.controls.measurements;\r\n if (measurements.enabled) {\r\n measurements.measurementAerialView.removeInteraction();\r\n }\r\n }\r\n\r\n /** Private Methods */\r\n onKeyDown(event) {\r\n if (!this.focused) return;\r\n\r\n event.preventDefault();\r\n this.cameraHandler.onKeyDown(event);\r\n this.controls.onKeyDown(event);\r\n }\r\n\r\n onKeyUp(event) {\r\n this.controls.onKeyUp(event);\r\n }\r\n\r\n onMouseFocus(event) {\r\n if (event.type === 'mouseover') {\r\n this.focused = true;\r\n } else if (event.type === 'mouseout') {\r\n this.focused = false;\r\n this.clearCoordinates();\r\n }\r\n }\r\n\r\n onMouseMove(event: CustomMouseEvent) {\r\n this.updateCoordinates(event);\r\n }\r\n\r\n initEvents() {\r\n this.onMouseFocus = this.onMouseFocus.bind(this);\r\n this.onKeyDown = this.onKeyDown.bind(this);\r\n this.onKeyUp = this.onKeyUp.bind(this);\r\n\r\n // Keep track of our canvas focus\r\n this.containerElement.addEventListener('mouseover', this.onMouseFocus, false);\r\n this.containerElement.addEventListener('mouseout', this.onMouseFocus, false);\r\n\r\n // Keydown doesnt work on canvas\r\n window.addEventListener('keydown', this.onKeyDown, false);\r\n window.addEventListener('keyup', this.onKeyUp, false);\r\n }\r\n\r\n removeEvents() {\r\n this.containerElement.removeEventListener('mouseover', this.onMouseFocus, false);\r\n this.containerElement.removeEventListener('mouseout', this.onMouseFocus, false);\r\n window.removeEventListener('keydown', this.onKeyDown, false);\r\n window.removeEventListener('keyup', this.onKeyUp, false);\r\n }\r\n\r\n updateCoordinates(event) {\r\n if (event.mouseDown || event.scrolling) {\r\n this.clearCoordinates();\r\n return;\r\n }\r\n\r\n if (!this.focused) return;\r\n this.updateMouseCoords(event);\r\n }\r\n\r\n clearCoordinates() {\r\n this.updateMouseCoords(null);\r\n }\r\n\r\n updateBackground(color: string) {\r\n this.backgroundScene.background = new Color(color);\r\n this.multiImageWindow.updateBackground(color);\r\n }\r\n\r\n updateCamera() {\r\n this.renderUtils.setCamera(this.camera);\r\n\r\n // Update GPU picker camera\r\n Object.values(this.gpuPickers).forEach(picker => {\r\n picker.setCamera(this.camera);\r\n });\r\n }\r\n\r\n updatePickers() {\r\n Object.keys(this.gpuPickers).forEach((name: GPUPickerName) => {\r\n this.updatePicker(name);\r\n });\r\n }\r\n\r\n updatePicker(name: GPUPickerName) {\r\n this.gpuPickers[name].needsUpdate = true;\r\n }\r\n\r\n initRenderer() {\r\n this.camera = new PerspectiveCamera(90);\r\n this.camera.near = this.defaultNearPlane;\r\n this.camera.far = this.defaultFarPlane;\r\n this.camera.up = new Vector3(0, 0, 1);\r\n\r\n this.renderer = new WebGLRenderer({\r\n antialias: true,\r\n alpha: true,\r\n logarithmicDepthBuffer: false,\r\n powerPreference: \"high-performance\"\r\n });\r\n\r\n this.renderer.autoClear = false;\r\n this.renderer.setPixelRatio(this.pixelRatio);\r\n this.renderer.clear();\r\n\r\n this.backgroundScene = new Scene();\r\n\r\n this.renderUtils = new RenderUtils(\r\n this.renderer,\r\n this.camera,\r\n this.pixelRatio\r\n );\r\n }\r\n\r\n initGpuPickers() {\r\n this.gpuPickers = {\r\n markers: new GPUPicker(this, \"markers\"),\r\n default: new GPUPicker(this, \"default\"),\r\n tags: new GPUPicker(this, \"tags\")\r\n };\r\n\r\n Object.values(this.gpuPickers).forEach(picker => {\r\n this.renderUtils.addTarget(picker.target);\r\n });\r\n }\r\n\r\n initResize() {\r\n this.observer = onresize(this.containerElement, () => {\r\n this.handleWindowResize();\r\n });\r\n\r\n this.handleWindowResize();\r\n }\r\n\r\n updateSavedState() {\r\n setCameraState(this.sceneState);\r\n }\r\n\r\n handleWindowResize() {\r\n let aspect = this.width / this.height;\r\n\r\n this.camera.aspect = aspect;\r\n this.camera.updateProjectionMatrix();\r\n\r\n this.renderer.domElement.style.display = \"none\";\r\n this.renderer.setSize(this.width, this.height);\r\n this.compass?.setSize(this.width, this.height);\r\n this.renderer.domElement.style.display = \"block\";\r\n\r\n this.updatePickers();\r\n\r\n // Re-render is required or else the div will flash white\r\n this.render();\r\n }\r\n\r\n updateMaterial(material, values) {\r\n let keys = Object.keys(values);\r\n keys.forEach(key => {\r\n material[key] = values[key];\r\n });\r\n }\r\n\r\n renderSceneObjects() {\r\n this.renderUtils.setEDLState(false);\r\n\r\n // Render background color and image data\r\n this.renderUtils.setRenderTarget(true);\r\n this.renderUtils.renderScene(this.backgroundScene);\r\n this.renderUtils.renderScene(this.cameraHandler.cameraScene);\r\n this.renderUtils.renderToTarget(1.0);\r\n\r\n this.renderUtils.setEDLState(true);\r\n\r\n // Render objects\r\n this.renderUtils.setRenderTarget(true);\r\n if (!this.cameraHandler.renderInFront) {\r\n this.renderUtils.renderScene(this.cameraHandler.markerScene);\r\n }\r\n this.renderUtils.renderScene(this.cadHandler.scene);\r\n this.renderUtils.renderToTarget(1.0);\r\n\r\n // Render pointcloud with transparency\r\n this.renderUtils.setRenderTarget(false);\r\n this.renderUtils.renderScene(this.pointclouds.scene);\r\n this.renderUtils.renderToTarget(this.pointclouds.transparency);\r\n\r\n // Render scene labels polygons first\r\n this.renderUtils.setRenderTarget(true);\r\n this.renderUtils.renderScene(this.imageLabels.polygonScene);\r\n this.renderUtils.renderToTarget(1.0);\r\n\r\n // Render objects on top of everything else\r\n this.renderUtils.setRenderTarget(true);\r\n if (this.cameraHandler.renderInFront) {\r\n this.renderUtils.renderScene(this.cameraHandler.markerScene);\r\n }\r\n this.renderUtils.renderScene(this.imageLabels.standardScene);\r\n this.renderUtils.renderScene(this.controls.scene);\r\n this.renderUtils.renderScene(this.measurements.scene);\r\n this.renderUtils.renderScene(this.tagsHandler.scene);\r\n this.renderUtils.renderToTarget(1.0);\r\n\r\n // Render target to screen\r\n this.renderUtils.renderToScreen();\r\n\r\n // Update previous texture\r\n this.renderUtils.renderToPrevious();\r\n }\r\n\r\n renderPickerScene() {\r\n Object.values(this.gpuPickers).forEach(picker => {\r\n // Force gpu picker data\r\n picker.needsUpdate = true;\r\n picker.update();\r\n\r\n // Render picker scene\r\n this.renderer.render(picker.scene, this.camera);\r\n });\r\n }\r\n\r\n updateSceneElements() {\r\n withTiming(\"pointclouds\", () => this.pointclouds.update());\r\n withTiming(\"measurements\", () => this.measurements.update(this.changeDetector));\r\n withTiming(\"cameras\", () => this.cameraHandler.update());\r\n withTiming(\"minimap\", () => this.minimap.update(this.changeDetector));\r\n withTiming(\"image labels\", () => this.imageLabels.update(this.changeDetector));\r\n withTiming(\"tags\", () => this.tagsHandler.update());\r\n withTiming(\"cad handler\", () => this.cadHandler.update());\r\n withTiming(\"orthomosaic list\", () => this.orthoList.update());\r\n }\r\n\r\n updateSceneLabels() {\r\n if (!this.enabled) return;\r\n if (this.sceneLabels.length === 0) return;\r\n\r\n const pixelBuffer = 100;\r\n const minCameraDistance = 1.0;\r\n\r\n const labels = this.sceneLabels.map(label => {\r\n const scenePos = new DataProjectionCoordinate(\r\n label.position).toScene();\r\n const distance = scenePos.distanceTo(\r\n this.camera.position);\r\n\r\n return {...label, position: scenePos, distance};\r\n });\r\n\r\n labels.sort((a, b) => {\r\n return b.distance - a.distance;\r\n });\r\n\r\n labels.forEach((label, zIndex) => {\r\n const {element, position, distance} = label;\r\n\r\n const uv = toScreenPosition(this, position);\r\n\r\n const hidden = (distance <= minCameraDistance)\r\n || (uv.x < -pixelBuffer)\r\n || (uv.x > this.width + pixelBuffer)\r\n || (uv.y < -pixelBuffer)\r\n || (uv.y > this.height + pixelBuffer)\r\n || !this.renderUtils.insideRadius(uv)\r\n || this.isBehindCamera(position);\r\n\r\n if (hidden) {\r\n element.style.display = \"none\";\r\n return;\r\n }\r\n\r\n element.style.left = `${uv.x}px`;\r\n element.style.top = `${uv.y}px`;\r\n element.style['z-index'] = zIndex;\r\n element.style.display = \"\";\r\n });\r\n }\r\n\r\n updatePreviousTexture() {\r\n return this.renderUtils.updateTexture();\r\n }\r\n\r\n render() {\r\n this.changeDetector.update();\r\n this.renderUtils.update();\r\n this.controls.update(this.changeDetector);\r\n\r\n this.updateSceneElements();\r\n\r\n if (this.drawPickerScene) {\r\n this.renderPickerScene();\r\n } else {\r\n this.renderSceneObjects();\r\n }\r\n\r\n if (this.changeDetector.changed) {\r\n this.updateSceneLabels();\r\n this.updateSavedState();\r\n }\r\n\r\n // Render compass element\r\n this.compass.render(this.showCompassElement,\r\n this.camera, this.orbitState);\r\n\r\n this.multiImageWindow.render();\r\n }\r\n\r\n animate() {\r\n if (!this.enabled) return;\r\n\r\n this.stats.begin();\r\n this.render();\r\n this.stats.end();\r\n\r\n requestAnimationFrame(() => {\r\n this.animate();\r\n });\r\n }\r\n}\r\n\r\nclass StatsPanel {\r\n private stats: Stats;\r\n private viewer: Viewer;\r\n private nodesVisible;\r\n private pointsVisible;\r\n private enabled = isDevMode;\r\n private expanded = false;\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n this.clear();\r\n this.init();\r\n }\r\n\r\n get indexToShow() {\r\n let childCount = this.stats.dom.children.length;\r\n return [0, childCount-1, childCount-2];\r\n }\r\n\r\n get parentElement() {\r\n return document.getElementById(\"debug-placeholder\");\r\n }\r\n\r\n clear() {\r\n // Remove old stats panels\r\n [...document.getElementsByClassName(\"stats\")].forEach(element => {\r\n element.remove();\r\n });\r\n }\r\n\r\n init() {\r\n if (!this.enabled) return false;\r\n\r\n this.stats = new Stats();\r\n this.stats.dom.classList.add(\"stats\");\r\n this.setStyle();\r\n\r\n this.pointsVisible = this.stats.addPanel(\r\n new Stats.Panel('', '#ff8', '#221'));\r\n\r\n this.nodesVisible = this.stats.addPanel(\r\n new Stats.Panel('NODE', '#f8f', '#212'));\r\n\r\n [...this.stats.dom.children].forEach(element => {\r\n element.style.display = 'none';\r\n element.style.margin = '2px';\r\n });\r\n\r\n this.parentElement.appendChild(this.stats.dom);\r\n\r\n this.drawExpandedState();\r\n this.initEvents();\r\n }\r\n\r\n drawExpandedState() {\r\n // Hide all elements\r\n [...this.stats.dom.children].forEach(element => {\r\n element.style.display = 'none';\r\n });\r\n\r\n this.indexToShow.forEach(index => {\r\n this.stats.dom.children[index].style.display = 'inline-block';\r\n });\r\n\r\n if (this.expanded) {\r\n [...this.stats.dom.children].forEach(element => {\r\n element.style.display = 'inline-block';\r\n });\r\n }\r\n }\r\n\r\n initEvents() {\r\n this.stats.dom.onclick = (event) => {\r\n event.preventDefault();\r\n this.expanded = !this.expanded;\r\n this.drawExpandedState();\r\n };\r\n }\r\n\r\n setStyle() {\r\n this.stats.dom.style.position = \"\";\r\n this.stats.dom.style.top = \"\";\r\n this.stats.dom.style['z-index'] = \"\";\r\n this.stats.dom.style.display = \"flex\";\r\n this.stats.dom.style.flexDirection = \"column\";\r\n }\r\n\r\n begin() {\r\n if (!this.enabled) return false;\r\n\r\n this.stats.begin();\r\n }\r\n\r\n end() {\r\n if (!this.enabled) return false;\r\n\r\n const {numSceneNodesVisible, numVisiblePoints,\r\n visiblePointsTarget} = this.viewer.pointclouds;\r\n\r\n this.pointsVisible.update(\r\n numVisiblePoints / 1000,\r\n visiblePointsTarget / 1000\r\n );\r\n\r\n this.nodesVisible.update(numSceneNodesVisible, 500);\r\n\r\n this.stats.end();\r\n }\r\n}\r\n\r\n/** @private */\r\nconst withTiming = (name, callback, timeout=10) => {\r\n const timeStart = performance.now();\r\n\r\n callback();\r\n\r\n const timeElapsed = performance.now() - timeStart;\r\n if (timeElapsed < timeout) return;\r\n\r\n console.warn(`Slow update detected: ${name} took ${timeElapsed.toFixed(2)}ms`);\r\n};","import React, {useCallback, useEffect, useRef, useState} from \"react\";\r\nimport {Viewer} from './main';\r\nimport {ContextMenu} from \"../context-menu\";\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n changeMeasureUnits,\r\n selectDataProjection,\r\n selectViewProjection,\r\n} from '../redux/projections-slice';\r\nimport {useSelector, useDispatch} from 'react-redux';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport {\r\n getPointCloudAssets,\r\n getOrthoAssets,\r\n selectAllAssets,\r\n getTagAssets,\r\n getModelAssets,\r\n getLandXMLAssets,\r\n getWebMapAssets,\r\n getCameraFileAssets\r\n} from \"../redux/assets-slice\";\r\nimport {headerHeight, toast} from \"../app\";\r\nimport LocalScene from \"./projections\";\r\nimport { debounce } from 'throttle-debounce';\r\nimport { selectProjectName } from \"../redux/project-slice\";\r\nimport {assetDrawerWidth, assetDrawerHeight} from \"../asset-drawer\";\r\nimport RotateLeftIcon from '@mui/icons-material/RotateLeft';\r\nimport {\r\n changeSwitched,\r\n selectAssetDrawerState,\r\n selectViewerSwitched\r\n} from \"../redux/settings-slice\";\r\nimport {\r\n CursorTooltip,\r\n OpenLayersIcon\r\n} from \"../components\";\r\nimport {isDevMode, isElectronApp} from '../electron-modules';\r\nimport {\r\n AerialViewState,\r\n SceneCameraState,\r\n changeCameraState,\r\n changeCameraTransform,\r\n changeSavedAerialState,\r\n initialAerialState,\r\n initialSceneState,\r\n selectBasicAdjustments,\r\n selectCameraHeight,\r\n selectCameraState,\r\n selectCameraTransform,\r\n selectSavedAerialState\r\n} from \"../redux/camera-slice\";\r\nimport { isEqual } from 'lodash';\r\nimport {\r\n readTransformFile,\r\n clearWindowHash,\r\n setWindowHash,\r\n getLocalizedProjectName\r\n} from \"../utilities\";\r\nimport proj4 from 'proj4';\r\nimport { transform } from 'ol/proj';\r\nimport {register} from 'ol/proj/proj4';\r\nimport {\r\n getModifiedAerialState,\r\n getModifiedSceneState,\r\n parseURLParams,\r\n roundDigit,\r\n toBoolean\r\n} from \"./utilities\";\r\nimport { MathUtils } from \"three\";\r\nimport { useUniqueProjectID, useViewer, useGlobalSettings, useBookmarks } from \"../hooks\";\r\nimport { MultiImageOptions } from \"./controls\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n parent: {\r\n width: \"100vw\",\r\n height: `calc(100vh - ${headerHeight}px)`,\r\n },\r\n containerLarge: {\r\n width: '100%',\r\n height: `calc(100vh - ${headerHeight}px)`,\r\n position: 'fixed'\r\n },\r\n offsetLarge: {\r\n marginTop: theme.spacing(0),\r\n marginLeft: assetDrawerWidth,\r\n width: `calc(100% - ${assetDrawerWidth}px)`,\r\n height: `calc(100vh - ${headerHeight}px)`,\r\n },\r\n containerSmall: {\r\n overflow: \"hidden\",\r\n width: `${assetDrawerWidth}px`,\r\n height: `${assetDrawerWidth*0.75}px`,\r\n position: 'fixed',\r\n background: 'white',\r\n margin: '0.5em',\r\n boxShadow: \"0px 0px 1px 1px rgba(0,0,0,0.5)\",\r\n zIndex: 1,\r\n \"@media (max-width: 600px) and (min-height: 450px)\": {\r\n /* Mobile devices (portrait) */\r\n height: `25vh`,\r\n width: \"100%\",\r\n margin: theme.spacing(0),\r\n },\r\n \"@media (max-height: 450px)\": {\r\n /* Mobile devices (landscape) */\r\n width: \"30%\",\r\n height: `calc(100% - ${headerHeight}px)`,\r\n margin: theme.spacing(0)\r\n },\r\n },\r\n offsetSmall: {\r\n width: `${assetDrawerWidth}px`,\r\n height: `${100-assetDrawerHeight}%`,\r\n bottom: theme.spacing(0),\r\n margin: theme.spacing(0),\r\n border: theme.spacing(0),\r\n borderTop: \"1px solid black\",\r\n boxShadow: \"none\",\r\n zIndex: theme.zIndex.modal,\r\n },\r\n compassElement: {\r\n pointerEvents: \"none\",\r\n position: \"absolute\",\r\n top: theme.spacing(0),\r\n right: theme.spacing(0)\r\n }\r\n }),\r\n);\r\n\r\ninterface ViewSwitcherProps {\r\n onClick(): void\r\n}\r\n\r\nconst ViewSwitcher = (props: ViewSwitcherProps) => {\r\n const {onClick} = props;\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport interface SceneViewerProps {\r\n setMeasurements: React.Dispatch;\r\n setCategoryList: React.Dispatch;\r\n setTrainingArea: React.Dispatch;\r\n setMarkupGroups: React.Dispatch;\r\n setMultiImageOpen: React.Dispatch;\r\n setMultiImageState: React.Dispatch;\r\n setPointProfileOpen: React.Dispatch;\r\n setLocalObservations: React.Dispatch;\r\n setAlignerObservations: React.Dispatch;\r\n}\r\n\r\nexport const SceneViewer = (props: SceneViewerProps) => {\r\n const {setMeasurements, setCategoryList,\r\n setTrainingArea, setMarkupGroups, setMultiImageOpen,\r\n setMultiImageState, setPointProfileOpen, setLocalObservations,\r\n setAlignerObservations} = props;\r\n\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n const classes = useStyles(theme);\r\n const dispatch = useDispatch();\r\n const uniqueProjectID = useUniqueProjectID();\r\n\r\n const {viewerBackground, aerialBackground, controlType, orthoOpacity,\r\n volumeType, volumeSampleRate, aerialMeasureType} = useGlobalSettings();\r\n\r\n const viewerRef = useRef(null);\r\n const aerialRef = useRef(null);\r\n\r\n const {viewer, setViewer} = useViewer();\r\n const {loadBookmark} = useBookmarks();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const assetDrawerState = useSelector(selectAssetDrawerState);\r\n const dataProjection = useSelector(selectDataProjection);\r\n const viewProjection = useSelector(selectViewProjection);\r\n const cameraTransformPath = useSelector(selectCameraTransform);\r\n const projectName = useSelector(selectProjectName);\r\n const viewerSwitched = useSelector(selectViewerSwitched);\r\n const cameraHeight = useSelector(selectCameraHeight);\r\n const basicAdjustments = useSelector(selectBasicAdjustments);\r\n const savedAerialState = useSelector(selectSavedAerialState);\r\n const savedCameraState = useSelector(selectCameraState);\r\n\r\n const [viewerTooltipLines, setViewerTooltipLines] = useState([]);\r\n const [aerialTooltipLines, setAerialTooltipLines] = useState([]);\r\n const [aerialState, setAerialState] = useState({...initialAerialState});\r\n const [cameraState, setCameraState] = useState({...initialSceneState});\r\n\r\n const clearTooltipText = useCallback(() => {\r\n clearViewerTooltip();\r\n clearAerialTooltip();\r\n }, []);\r\n\r\n const getClasses = (switched) => {\r\n let mapClasses = [];\r\n let viewerClasses = [];\r\n\r\n const classSmall = [\r\n classes.containerSmall,\r\n assetDrawerState ? classes.offsetSmall : \"\"\r\n ];\r\n\r\n if (switched) {\r\n mapClasses = [...mapClasses, classes.containerLarge];\r\n viewerClasses = [...viewerClasses, ...classSmall];\r\n } else {\r\n mapClasses = [...mapClasses, ...classSmall];\r\n viewerClasses = [...viewerClasses, classes.containerLarge];\r\n }\r\n\r\n return {\r\n viewerClasses: viewerClasses.join(\" \"),\r\n mapClasses: mapClasses.join(\" \")\r\n };\r\n };\r\n\r\n const handleSwitched = useCallback(() => {\r\n dispatch(changeSwitched(!viewerSwitched));\r\n }, [viewerSwitched]);\r\n\r\n const clearAllAssets = () => {\r\n // Adding an empty array will clear everything\r\n addAllAssets([]);\r\n };\r\n\r\n const addAllAssets = (assetList) => {\r\n if (!viewer) return;\r\n\r\n const viewerAssets = {\r\n camerasFiles: getCameraFileAssets(assetList),\r\n pointCloudFiles: getPointCloudAssets(assetList),\r\n orthoFiles: getOrthoAssets(assetList),\r\n tagFiles: getTagAssets(assetList),\r\n modelFiles: getModelAssets(assetList),\r\n xmlFiles: getLandXMLAssets(assetList),\r\n webSources: getWebMapAssets(assetList)\r\n };\r\n\r\n const numAssets = assetList.length;\r\n viewer.reconcileAssets(viewerAssets, savedCameraState);\r\n viewer.setEmptyProject(numAssets === 0);\r\n };\r\n\r\n const handleHashUpdate = () => {\r\n if (isElectronApp) return;\r\n\r\n const state = {} as any;\r\n\r\n /** Scene state values */\r\n if (cameraState.camera) {\r\n const [theta, phi] = cameraState.angles;\r\n state.cam = cameraState.camera;\r\n state.fov = cameraState.fov;\r\n state.theta = roundDigit(MathUtils.radToDeg(theta), 3);\r\n state.phi = roundDigit(MathUtils.radToDeg(phi), 3);\r\n }\r\n\r\n if (cameraState.orbit) {\r\n const [ox, oy, oz] = cameraState.orbit;\r\n state.ox = roundDigit(ox, 3);\r\n state.oy = roundDigit(oy, 3);\r\n state.oz = roundDigit(oz, 3);\r\n\r\n const [px, py, pz] = cameraState.pivot;\r\n state.px = roundDigit(px, 3);\r\n state.py = roundDigit(py, 3);\r\n state.pz = roundDigit(pz, 3);\r\n }\r\n\r\n /** Aerial state values */\r\n if (aerialState.center) {\r\n const [lon, lat] = transform(aerialState.center, 'EPSG:3857', 'EPSG:4326');\r\n state.lat = roundDigit(lat, 8);\r\n state.lon = roundDigit(lon, 8);\r\n state.zoom = roundDigit(aerialState.zoom, 3);\r\n state.rotation = roundDigit(aerialState.rotation, 3);\r\n state.expanded = viewerSwitched ? 1 : 0;\r\n }\r\n\r\n const hash = Object.entries(state)\r\n .map(([key, value]) => `${key}=${value}`)\r\n .join(\"&\");\r\n\r\n if (cameraState.orbit || cameraState.camera) {\r\n setWindowHash(hash);\r\n } else {\r\n clearWindowHash();\r\n }\r\n };\r\n\r\n const handleHashChange = (url) => {\r\n if (isElectronApp) return;\r\n\r\n const parameters = parseURLParams(url);\r\n if (!parameters) return;\r\n\r\n const modifiedSceneState = getModifiedSceneState(\r\n viewer.sceneState, parameters);\r\n\r\n const modifiedAerialState = getModifiedAerialState(\r\n viewer.aerialState, parameters);\r\n\r\n if (\"expanded\" in parameters) {\r\n const switched = toBoolean(parameters.expanded);\r\n dispatch(changeSwitched(switched));\r\n }\r\n\r\n if (\"bookmark\" in parameters) {\r\n const bookmarkID = parameters.bookmark;\r\n if (loadBookmark(bookmarkID)) return;\r\n }\r\n\r\n if (\"tag\" in parameters) {\r\n const tagQuery = parameters.tag;\r\n if (viewer.applySavedTagState(tagQuery, true)) return;\r\n }\r\n\r\n viewer.applySavedAerialState(modifiedAerialState);\r\n viewer.applySavedSceneState(modifiedSceneState, true);\r\n };\r\n\r\n const onMatrixChange = async (filePath: string) => {\r\n const {success, content} = await readTransformFile(filePath);\r\n\r\n if (success) {\r\n viewer?.setCameraMatrix(content);\r\n } else {\r\n toast.error(t(\"toast.correction-matrix-error\"));\r\n dispatch(changeCameraTransform(null));\r\n }\r\n };\r\n\r\n const onMouseLeaveViewer = () => {\r\n clearViewerTooltip();\r\n viewer?.clearArrowNavigation();\r\n };\r\n\r\n const onMouseLeaveAerial = () => {\r\n clearAerialTooltip();\r\n };\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n /** Ran after new project is created or project is loaded */\r\n viewer.applySavedAerialState(savedAerialState);\r\n viewer.resetDefaultAerialCamera();\r\n viewer.resetDefaultControlState();\r\n viewer.setEmptyProject(true);\r\n viewer.resetTextureCache();\r\n }, [viewer, uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n handleHashUpdate();\r\n dispatch(changeCameraState(cameraState));\r\n }, [viewer, cameraState]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n handleHashUpdate();\r\n dispatch(changeSavedAerialState(aerialState));\r\n }, [viewer, aerialState]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n viewer.setProjectName(localizedProjectName);\r\n }, [viewer, projectName]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n clearTooltipText();\r\n if (viewerSwitched) {\r\n viewer.removeInteractions();\r\n }\r\n\r\n handleHashUpdate();\r\n viewer.setExpanded(!viewerSwitched);\r\n }, [viewer, viewerSwitched]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n window.onhashchange = event => {\r\n handleHashChange(event.newURL);\r\n };\r\n }, [viewer, loadBookmark]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setControlType(controlType);\r\n }, [viewer, controlType]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setOrthoOpacity(orthoOpacity);\r\n }, [viewer, orthoOpacity]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.updateVolumeType(volumeType);\r\n }, [viewer, volumeType]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.updateVolumeSampleRate(volumeSampleRate);\r\n }, [viewer, volumeSampleRate]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setAerialMeasureType(aerialMeasureType);\r\n }, [viewer, aerialMeasureType]);\r\n\r\n useEffect(() => {\r\n const viewerProps = {\r\n setMeasurements,\r\n setCategoryList,\r\n setTrainingArea,\r\n setMarkupGroups,\r\n setMultiImageOpen,\r\n setMultiImageState,\r\n compassClassName,\r\n setPointProfileOpen,\r\n setLocalObservations,\r\n setAlignerObservations\r\n };\r\n\r\n let viewerObj = new Viewer(\r\n viewerRef.current,\r\n aerialRef.current,\r\n viewerProps\r\n );\r\n\r\n setViewer(viewerObj);\r\n\r\n if (isDevMode) {\r\n // Temporary global for easy access\r\n window['viewer'] = viewerObj;\r\n window['local'] = LocalScene;\r\n window['toast'] = toast;\r\n }\r\n\r\n return () => {\r\n console.log(\"Destroy viewer\");\r\n viewerObj.destroy();\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setCameraHeight(cameraHeight);\r\n }, [viewer, cameraHeight]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setCameraAdjustments(basicAdjustments);\r\n }, [viewer, basicAdjustments]);\r\n\r\n useEffect(() => {\r\n // Register current projection for openlayers to use\r\n proj4.defs(dataProjection.name, dataProjection.string);\r\n register(proj4);\r\n\r\n // Clear previous asset data\r\n clearAllAssets();\r\n\r\n if (!viewer) return;\r\n\r\n // Update data projection\r\n viewer.setDataProjection(dataProjection);\r\n\r\n // Reset saved state + initial zoom\r\n viewer.setInitialStateFlag(false);\r\n viewer.setInitialZoomFlag(false);\r\n\r\n // Refresh values that rely on previously\r\n // calculated scene position\r\n viewer.refreshLocalTransform();\r\n\r\n // All all assets back to the project\r\n addAllAssets(assets);\r\n }, [viewer, dataProjection]);\r\n\r\n useEffect(() => {\r\n viewer?.setViewProjection(viewProjection);\r\n\r\n const units = LocalScene.viewProjectionUnits;\r\n dispatch(changeMeasureUnits(units));\r\n }, [viewer, viewProjection]);\r\n\r\n useEffect(() => {\r\n if (!cameraTransformPath) {\r\n viewer?.resetCameraMatrix();\r\n return;\r\n }\r\n\r\n onMatrixChange(cameraTransformPath);\r\n }, [viewer, cameraTransformPath]);\r\n\r\n useEffect(() => {\r\n addAllAssets(assets);\r\n }, [viewer, assets]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.updateBackground(viewerBackground);\r\n }, [viewer, viewerBackground]);\r\n\r\n /** Viewer tooltip interval */\r\n useEffect(() => {\r\n const callback = () => {\r\n if (isEqual(oldViewerTooltipLines, newViewerTooltipLines)) return;\r\n oldViewerTooltipLines = [...newViewerTooltipLines];\r\n setViewerTooltipLines(newViewerTooltipLines);\r\n };\r\n\r\n const interval = setInterval(callback, 100);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, []);\r\n\r\n /** Aerial tooltip interval */\r\n useEffect(() => {\r\n const callback = () => {\r\n if (isEqual(oldAerialTooltipLines, newAerialTooltipLines)) return;\r\n oldAerialTooltipLines = [...newAerialTooltipLines];\r\n setAerialTooltipLines(newAerialTooltipLines);\r\n };\r\n\r\n const interval = setInterval(callback, 100);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, []);\r\n\r\n /** Viewer state interval */\r\n useEffect(() => {\r\n const callback = () => {\r\n if (isEqual(oldCameraState, newCameraState)) return;\r\n oldCameraState = {...newCameraState};\r\n setCameraState(newCameraState);\r\n };\r\n\r\n const interval = setInterval(callback, 100);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, []);\r\n\r\n /** Aerial state interval */\r\n useEffect(() => {\r\n const callback = () => {\r\n if (isEqual(oldAerialState, newAerialState)) return;\r\n oldAerialState = {...newAerialState};\r\n setAerialState(newAerialState);\r\n };\r\n\r\n const interval = setInterval(callback, 100);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, []);\r\n\r\n const {viewerClasses, mapClasses} = getClasses(viewerSwitched);\r\n const compassClassName = classes.compassElement;\r\n\r\n return (\r\n \r\n
\r\n\r\n {/* Viewer div */}\r\n \r\n \r\n {viewerSwitched && }\r\n\r\n \r\n
\r\n \r\n\r\n {/* Aerial div */}\r\n \r\n \r\n {!viewerSwitched && }\r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n\r\nlet oldAerialTooltipLines = [];\r\nlet newAerialTooltipLines = [];\r\nexport const clearAerialTooltip = () => setAerialTooltip([]);\r\nexport const setAerialTooltip = (lines: string[]) => {\r\n newAerialTooltipLines = lines;\r\n};\r\n\r\nlet oldViewerTooltipLines = [];\r\nlet newViewerTooltipLines = [];\r\nexport const clearViewerTooltip = () => setViewerTooltip([]);\r\nexport const setViewerTooltip = (lines: string[]) => {\r\n newViewerTooltipLines = lines;\r\n};\r\n\r\nlet oldAerialState = null;\r\nlet newAerialState = null;\r\nexport const setAerialState = debounce(100, (state: AerialViewState) => {\r\n newAerialState = state;\r\n});\r\n\r\nlet oldCameraState = null;\r\nlet newCameraState = null;\r\nexport const setCameraState = debounce(100, (state: SceneCameraState) => {\r\n newCameraState = state;\r\n});\r\n","export enum ObservationType {\r\n Points,\r\n Image\r\n}\r\n\r\nexport enum LocalObservationType {\r\n None,\r\n Scene,\r\n Aerial\r\n}","import { CustomMouseEvent, PanoControls } from '../controls';\r\nimport { DataProjectionCoordinate, SceneCoordinate } from '../projections';\r\nimport { ChangeDetector, getPointScale } from '../utilities';\r\nimport {\r\n Scene,\r\n SphereGeometry,\r\n MeshBasicMaterial,\r\n Vector3,\r\n AmbientLight\r\n} from 'three';\r\nimport { Viewer, ViewerProps } from '../main';\r\nimport { clearViewerTooltip, setViewerTooltip } from '../viewer';\r\nimport { RayCaster } from '../ray-caster';\r\nimport { t } from '../../localization';\r\nimport { flashColor, imageObsColor, ImageObservation, pointObsColor, PointObservation } from '.';\r\nimport { nanoid } from '@reduxjs/toolkit';\r\nimport { toast } from '../../app';\r\nimport { ObservationType } from '../../types/aligner';\r\n\r\nexport interface AlignerObservation {\r\n id: string,\r\n imageObs: Vector3,\r\n imageMesh: ImageObservation,\r\n imageSelected: boolean,\r\n pointObs: DataProjectionCoordinate,\r\n pointMesh: PointObservation,\r\n pointSelected: boolean,\r\n imageIdentifier: string,\r\n name: string,\r\n pose: any[],\r\n error: number\r\n}\r\n\r\n\r\nexport class CameraAlignerAdv {\r\n private controls: PanoControls;\r\n public enabled = false;\r\n public scene: Scene;\r\n private observations = [] as AlignerObservation[];\r\n private imageObsInterval = null;\r\n private pointObsInterval = null;\r\n private sphereGeometry = new SphereGeometry(0.05, 20, 20);\r\n\r\n private setObservations: React.Dispatch;\r\n\r\n constructor(controls: PanoControls, props: ViewerProps) {\r\n const {setAlignerObservations} = props;\r\n\r\n this.controls = controls;\r\n this.setObservations = setAlignerObservations;\r\n this.initScene();\r\n }\r\n\r\n get viewer(): Viewer {\r\n return this.controls.viewer;\r\n }\r\n\r\n get cameraHandler() {\r\n return this.viewer.cameraHandler;\r\n }\r\n\r\n get selecting() {\r\n return !!this.selected;\r\n }\r\n\r\n get selected() {\r\n return this.observations.find(x => x.imageSelected || x.pointSelected);\r\n }\r\n\r\n get currentRow() {\r\n return this.observations.indexOf(this.selected);\r\n }\r\n\r\n get observationType() {\r\n const selected = this.selected;\r\n if (!selected) return null;\r\n\r\n return selected.imageSelected\r\n ? ObservationType.Image\r\n : ObservationType.Points;\r\n }\r\n\r\n get moreTooltip() {\r\n const type = this.observationType;\r\n\r\n if (type === ObservationType.Points) {\r\n return [\r\n t(`data-aligner-adv.click-to-add-point`),\r\n t(\"data-aligner-adv.right-click-to-cancel\")\r\n ];\r\n }\r\n\r\n if (type === ObservationType.Image) {\r\n return [\r\n t(`data-aligner-adv.click-to-add-image`),\r\n t(\"data-aligner-adv.right-click-to-cancel\")\r\n ];\r\n }\r\n\r\n return [];\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n setState(state: boolean) {\r\n this.resetObservations();\r\n this.enabled = state;\r\n }\r\n\r\n refreshObservationList() {\r\n this.setObservations([...this.observations]);\r\n }\r\n\r\n resetObservations() {\r\n for (let observation of this.observations) {\r\n this.scene.remove(observation.imageMesh);\r\n this.scene.remove(observation.pointMesh);\r\n }\r\n\r\n this.observations = [];\r\n this.refreshObservationList();\r\n }\r\n\r\n reset() {\r\n }\r\n\r\n addNewObservations(numObservations: number) {\r\n for (let i=0; i x.id === id);\r\n }\r\n\r\n removeByID(id: string) {\r\n const observation = this.getByID(id);\r\n if (!observation) return;\r\n\r\n this.observations = this.observations.filter(x => x.id !== id);\r\n this.scene.remove(observation.imageMesh);\r\n this.scene.remove(observation.pointMesh);\r\n this.cancelAlignment();\r\n }\r\n\r\n clickImage(event: CustomMouseEvent) {\r\n let currentCamera = this.cameraHandler.current;\r\n\r\n // Get direction vector\r\n if (currentCamera != null && !this.viewer.orbitState) {\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let direction = raycaster.direction;\r\n let position = currentCamera.position.value;\r\n let rotation = currentCamera.rotation.array;\r\n\r\n // Allows for observations to overwrite each other\r\n this.scene.remove(this.observations[this.currentRow].imageMesh);\r\n\r\n toast.success(t('data-aligner-adv.new_point_observation_added'));\r\n this.observations[this.currentRow].name = currentCamera.name;\r\n this.observations[this.currentRow].imageIdentifier = currentCamera.id;\r\n this.observations[this.currentRow].imageObs = direction;\r\n this.observations[this.currentRow].pose = [\r\n currentCamera.path,\r\n position.x, position.y, position.z,\r\n rotation[0], rotation[1], rotation[2]\r\n ];\r\n\r\n let imageDir = direction.clone().add(this.viewer.camera.position);\r\n\r\n this.addImageObservationMesh(imageDir);\r\n clearViewerTooltip();\r\n }\r\n }\r\n\r\n clickScene(event: CustomMouseEvent) {\r\n let {coordinate} = this.controls.getPickerResults(event);\r\n if (!coordinate) {\r\n console.warn(\"Cloud position: no result\");\r\n return;\r\n }\r\n\r\n toast.success(t('data-aligner-adv.new_point_observation_added'));\r\n let position = new SceneCoordinate(coordinate).toDataProjection();\r\n this.scene.remove(this.observations[this.currentRow].pointMesh);\r\n this.observations[this.currentRow].pointObs = position;\r\n\r\n this.addPointObservationMesh(coordinate);\r\n clearViewerTooltip();\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n if (event.mouseMoved || !this.enabled) {\r\n return false;\r\n }\r\n\r\n if (event.isLeftClick) {\r\n // Get direction vector\r\n return this.mouseClick(event);\r\n }\r\n\r\n if (event.isRightClick) {\r\n if (this.selecting) {\r\n // Cancel observation selection\r\n this.cancelAlignment();\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMouseMove() {\r\n if (!this.enabled) return false;\r\n\r\n const type = this.observationType;\r\n const valid = Object.values(ObservationType).includes(type);\r\n\r\n if (valid) {\r\n setViewerTooltip(this.moreTooltip);\r\n return true;\r\n }\r\n\r\n clearViewerTooltip();\r\n return false;\r\n }\r\n\r\n mouseClick(event: CustomMouseEvent) {\r\n const type = this.observationType;\r\n\r\n if (type === ObservationType.Points) {\r\n this.clickScene(event);\r\n } else if (type === ObservationType.Image) {\r\n this.clickImage(event);\r\n } else {\r\n return false;\r\n }\r\n\r\n this.refreshObservationList();\r\n return true;\r\n }\r\n\r\n cancelAlignment() {\r\n clearViewerTooltip();\r\n\r\n this.resetSelectedState();\r\n this.updateAllMeshes();\r\n this.refreshObservationList();\r\n }\r\n\r\n addPointObservationMesh(position: Vector3) {\r\n let sphereMaterial = new MeshBasicMaterial({color: pointObsColor});\r\n let mesh = new PointObservation(this.sphereGeometry, sphereMaterial);\r\n\r\n this.scene.add(mesh);\r\n this.observations[this.currentRow].pointMesh = mesh;\r\n this.observations[this.currentRow].pointSelected = false;\r\n\r\n mesh.position.copy(position);\r\n this.setPointScale(mesh);\r\n }\r\n\r\n addImageObservationMesh(position: Vector3) {\r\n let sphereMaterial = new MeshBasicMaterial({color: imageObsColor});\r\n let mesh = new ImageObservation(this.sphereGeometry, sphereMaterial);\r\n\r\n this.scene.add(mesh);\r\n this.observations[this.currentRow].imageMesh = mesh;\r\n this.observations[this.currentRow].imageSelected = false;\r\n\r\n // update position (new or existing mesh)\r\n mesh.position.copy(position);\r\n this.setPointScale(mesh);\r\n }\r\n\r\n /** @private */\r\n flashObservation(mesh, defaultColor) {\r\n let numberOfFlashes = 0;\r\n const maxNumberOfFlashes = 6;\r\n const timerDelay = 500;\r\n\r\n const interval = setInterval(() => {\r\n if (numberOfFlashes % 2 === 0) {\r\n mesh.material.color.setHex(flashColor);\r\n } else {\r\n mesh.material.color.setHex(defaultColor);\r\n }\r\n\r\n numberOfFlashes++;\r\n\r\n if (numberOfFlashes === maxNumberOfFlashes) {\r\n mesh.material.color.setHex(defaultColor);\r\n clearInterval(interval);\r\n }\r\n }, timerDelay);\r\n\r\n return interval;\r\n };\r\n\r\n clearFlashIntervals() {\r\n if (this.imageObsInterval) {\r\n clearInterval(this.imageObsInterval);\r\n this.imageObsInterval = null;\r\n }\r\n\r\n if (this.pointObsInterval) {\r\n clearInterval(this.pointObsInterval);\r\n this.pointObsInterval = null;\r\n }\r\n\r\n // Reset the color for all observations\r\n this.observations.forEach(observation => {\r\n if (observation.imageMesh) {\r\n let material = observation.imageMesh.material as any;\r\n material.color.setHex(imageObsColor);\r\n }\r\n\r\n if (observation.pointMesh) {\r\n let material = observation.pointMesh.material as any;\r\n material.color.setHex(pointObsColor);\r\n }\r\n });\r\n }\r\n\r\n flashObservations(id: string) {\r\n this.clearFlashIntervals();\r\n\r\n const observation = this.getByID(id);\r\n if (!observation) return;\r\n\r\n if (observation.imageMesh) {\r\n this.imageObsInterval = this.flashObservation(\r\n observation.imageMesh, imageObsColor);\r\n }\r\n\r\n if (observation.pointMesh) {\r\n this.pointObsInterval = this.flashObservation(\r\n observation.pointMesh, pointObsColor);\r\n }\r\n };\r\n\r\n setCurrentObservation(id: string, type: ObservationType) {\r\n const observation = this.getByID(id);\r\n if (!observation) return;\r\n\r\n this.resetSelectedState();\r\n\r\n if (type === ObservationType.Image) {\r\n observation.imageSelected = true;\r\n } else if (type === ObservationType.Points) {\r\n observation.pointSelected = true;\r\n }\r\n\r\n this.updateAllMeshes();\r\n this.refreshObservationList();\r\n }\r\n\r\n resetSelectedState() {\r\n this.observations.forEach(obs => {\r\n obs.imageSelected = false;\r\n obs.pointSelected= false;\r\n });\r\n }\r\n\r\n redrawImageObsMarkers() {\r\n if (this.observations === null || this.observations.length === 0) {\r\n return;\r\n }\r\n\r\n for (let i=0; i {\r\n // Resize point observations and set visibility\r\n if (obs.pointMesh) {\r\n this.setPointScale(obs.pointMesh);\r\n obs.pointMesh.visible = !obs.pointSelected;\r\n }\r\n\r\n // Resize image ibservations and set visibility\r\n if (obs.imageMesh && this.cameraHandler.current){\r\n const currentID = this.cameraHandler.current.id;\r\n const matchingCamera = obs.imageIdentifier === currentID;\r\n\r\n if (matchingCamera && !this.viewer.orbitState) {\r\n this.setPointScale(obs.imageMesh);\r\n obs.imageMesh.visible = !obs.imageSelected;\r\n } else {\r\n obs.imageMesh.visible = false;\r\n }\r\n }\r\n });\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n if (!this.enabled || !changeDetector.changed) return;\r\n\r\n this.updateAllMeshes();\r\n }\r\n}","import { CameraImage } from \"../cameras\";\r\nimport { PanoControls } from \"../controls\";\r\n\r\nexport class CameraAlignerBasic {\r\n public enabled = false;\r\n private increment = 0.1;\r\n public cameraAngles = [0, 0, 0];\r\n private controls: PanoControls\r\n\r\n constructor(controls: PanoControls) {\r\n this.controls = controls;\r\n this.reset();\r\n }\r\n\r\n get currentCamera() : CameraImage {\r\n return this.controls.cameraHandler?.current;\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n }\r\n\r\n reset(values = [0,0,0]) {\r\n this.cameraAngles = [...values];\r\n this.updateAlignment();\r\n }\r\n\r\n onKeyDown(event) {\r\n if (!this.enabled) return false;\r\n\r\n let increment = event.altKey\r\n ? this.increment*10\r\n : this.increment;\r\n\r\n if (event.code === \"Numpad7\") {\r\n this.cameraAngles[0] -= increment;\r\n } else if (event.code === \"Numpad9\") {\r\n this.cameraAngles[0] += increment;\r\n } else if (event.code === \"Numpad4\") {\r\n this.cameraAngles[1] -= increment;\r\n } else if (event.code === \"Numpad6\") {\r\n this.cameraAngles[1] += increment;\r\n } else if (event.code === \"Numpad1\") {\r\n this.cameraAngles[2] -= increment;\r\n } else if (event.code === \"Numpad3\") {\r\n this.cameraAngles[2] += increment;\r\n } else {\r\n return;\r\n }\r\n\r\n this.updateAlignment();\r\n }\r\n\r\n updateAlignment() {\r\n this.currentCamera?.applyTempRotation(this.cameraAngles);\r\n }\r\n}","import { Mesh } from \"three\";\r\n\r\nexport const pointObsColor = 0xE6E600;\r\nexport const aerialObsColor = 0x62B7B0;\r\nexport const imageObsColor = 0x9900CC;\r\nexport const flashColor = 0xFFFFFF;\r\n\r\nexport class ImageObservation extends Mesh {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n}\r\n\r\nexport class PointObservation extends Mesh {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n}\r\n","import { nanoid } from '@reduxjs/toolkit';\r\nimport {transform} from 'ol/proj';\r\nimport { AmbientLight, MeshBasicMaterial, Scene, SphereGeometry, Vector3 } from 'three';\r\nimport { toast } from '../../app';\r\nimport { t } from '../../localization';\r\nimport { Projection } from '../../redux/projections-slice';\r\nimport {\r\n clearAerialTooltip,\r\n clearViewerTooltip,\r\n setAerialTooltip,\r\n setViewerTooltip\r\n} from \"../viewer\";\r\nimport { CustomMouseEvent, PanoControls } from \"../controls\";\r\nimport { Viewer, ViewerProps } from '../main';\r\nimport {\r\n closestUtmZone,\r\n DataProjectionCoordinate,\r\n estimateTransform,\r\n latitudeLongitude,\r\n reprojectPoints,\r\n SceneCoordinate\r\n} from '../projections';\r\nimport { ChangeDetector, getPointScale } from \"../utilities\";\r\nimport { aerialObsColor, pointObsColor, PointObservation } from './observations';\r\nimport {Vector as VectorSource} from \"ol/source\";\r\nimport {Vector as VectorLayer} from \"ol/layer\";\r\nimport {Circle as CircleStyle, Fill, Stroke, Style} from \"ol/style\";\r\nimport {Point} from \"ol/geom\";\r\nimport {Feature} from \"ol\";\r\nimport * as olColor from 'ol/color';\r\nimport { LocalObservationType } from '../../types/aligner';\r\n\r\nexport interface LocalObservation {\r\n id: string\r\n scene: DataProjectionCoordinate\r\n aerial: number[]\r\n error: number\r\n active: LocalObservationType\r\n}\r\n\r\nexport class LocalAligner {\r\n public scene: Scene;\r\n private mapLayer: VectorLayer;\r\n private mapSource: VectorSource;\r\n private controls: PanoControls;\r\n\r\n private setObservations: React.Dispatch;\r\n\r\n public enabled = false;\r\n private activeObservation: LocalObservation = null;\r\n private observations = [] as LocalObservation[];\r\n private sphereGeometry = new SphereGeometry(0.05, 20, 20);\r\n\r\n constructor(controls: PanoControls, props: ViewerProps) {\r\n const {setLocalObservations} = props;\r\n\r\n this.controls = controls;\r\n this.setObservations = setLocalObservations;\r\n\r\n this.initScene();\r\n this.addMapLayers();\r\n }\r\n\r\n get viewer(): Viewer {\r\n return this.controls.viewer;\r\n }\r\n\r\n get map() {\r\n return this.viewer.minimap.map;\r\n }\r\n\r\n get aerialTooltip() {\r\n return [\r\n t('local-projection.click_to_add_aerial_observation'),\r\n t('local-projection.right-click_to_cancel')\r\n ];\r\n }\r\n\r\n get sceneTooltip() {\r\n return [\r\n t('local-projection.click_to_add_point_observation'),\r\n t('local-projection.right-click_to_cancel')\r\n ];\r\n }\r\n\r\n get isSceneObs() {\r\n return this.activeObservation\r\n ? this.activeObservation.active === LocalObservationType.Scene\r\n : false;\r\n }\r\n\r\n get isAerialObs() {\r\n return this.activeObservation\r\n ? this.activeObservation.active === LocalObservationType.Aerial\r\n : false;\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n this.scene.add(new AmbientLight(0xFFFFFF));\r\n }\r\n\r\n addMapLayers() {\r\n const styleColor = `#${aerialObsColor.toString(16)}`;\r\n const color = olColor\r\n .asArray(styleColor)\r\n .slice();\r\n color[3] = 0.8;\r\n\r\n this.mapSource = new VectorSource({\r\n features: [],\r\n wrapX: false\r\n });\r\n\r\n this.mapLayer = new VectorLayer({\r\n zIndex: 1,\r\n source: this.mapSource,\r\n style: new Style({\r\n image: new CircleStyle({\r\n radius: 5,\r\n stroke: new Stroke({\r\n color: 'rgba(0, 0, 0, 0.7)'\r\n }),\r\n fill: new Fill({\r\n color: color\r\n })\r\n })\r\n })\r\n });\r\n }\r\n\r\n async getLocalProjection(estimator: string, units: string) {\r\n const filled = this.observations.filter(observation => {\r\n return observation.scene && observation.aerial;\r\n });\r\n\r\n const valid = (this.observations.length >= 3)\r\n && (filled.length === this.observations.length);\r\n\r\n if (!valid) {\r\n toast.error(t('local-projection.all_observations_must_be_used_to_calculate_projection'));\r\n return;\r\n }\r\n\r\n const input = this.observations.map(observation => {\r\n return observation.scene.toArray().slice(0,2);\r\n });\r\n\r\n const latlon = this.observations.map(observation => {\r\n return transform(observation.aerial, 'EPSG:3857', 'EPSG:4326');\r\n });\r\n\r\n // Calculate average map coordinate\r\n const average = [\r\n latlon.map(p => p[0]).reduce((a,b) => a+b, 0) / latlon.length,\r\n latlon.map(p => p[1]).reduce((a,b) => a+b, 0) / latlon.length\r\n ];\r\n\r\n // Determine closest UTM zone and reproject points\r\n const {projection, utmZone} = closestUtmZone(new Vector3(...average), units);\r\n const output = await reprojectPoints(latlon, latitudeLongitude, projection);\r\n\r\n // Estimate local transform\r\n const local = estimateTransform(estimator, input, output);\r\n if (!local.transform) return;\r\n\r\n const newProjection = {\r\n ...projection,\r\n transform: local.transform\r\n } as Projection;\r\n\r\n // Update observation errors\r\n this.observations.forEach((observation, index) => {\r\n observation.error = local.errors[index];\r\n });\r\n\r\n this.refreshObservationList();\r\n\r\n return {projection: newProjection, utmZone};\r\n };\r\n\r\n resetErrorValues() {\r\n this.observations.forEach(observation => {\r\n observation.error = null;\r\n });\r\n }\r\n\r\n setActiveObservation(id: string, type: LocalObservationType) {\r\n this.observations = this.observations.map(observation => {\r\n return {\r\n ...observation,\r\n active: observation.id === id ? type : LocalObservationType.None,\r\n };\r\n });\r\n\r\n this.activeObservation = this.observations.find(x => x.id === id);\r\n this.refreshObservationList();\r\n this.drawObservations();\r\n }\r\n\r\n addPointObservationMesh(position) {\r\n let sphereMaterial = new MeshBasicMaterial({color: pointObsColor});\r\n let mesh = new PointObservation(this.sphereGeometry, sphereMaterial);\r\n\r\n this.scene.add(mesh);\r\n\r\n mesh.position.copy(position);\r\n this.setPointScale(mesh);\r\n\r\n return mesh;\r\n }\r\n\r\n drawObservations() {\r\n if (!this.enabled) return;\r\n this.drawPointObservations();\r\n this.drawAerialObservations();\r\n }\r\n\r\n /** @private */\r\n drawPointObservations() {\r\n // Delete old point meshes\r\n this.scene.children\r\n .filter(mesh => mesh instanceof PointObservation)\r\n .forEach(mesh => this.scene.remove(mesh));\r\n\r\n // Draw new point meshes\r\n this.observations.forEach(observation => {\r\n if (!observation.scene) return;\r\n\r\n // Active observation will be ignored, to allow for replacing of points\r\n if (this.activeObservation) {\r\n const isActiveObservation = observation.id === this.activeObservation.id;\r\n if (isActiveObservation && this.isSceneObs) return;\r\n }\r\n\r\n // Add point\r\n const position = new DataProjectionCoordinate(observation.scene).toScene();\r\n const mesh = this.addPointObservationMesh(position);\r\n this.scene.add(mesh);\r\n });\r\n }\r\n\r\n /** @private */\r\n drawAerialObservations() {\r\n // Delete old points\r\n this.mapSource.clear();\r\n\r\n let features = [];\r\n this.observations.forEach(observation => {\r\n if (!observation.aerial) return;\r\n\r\n // Active observation will be ignored, to allow for replacing of points\r\n if (this.activeObservation) {\r\n const isActiveObservation = observation.id === this.activeObservation.id;\r\n if (isActiveObservation && this.isAerialObs) return;\r\n }\r\n\r\n const polygon = new Point(observation.aerial);\r\n const feature = new Feature(polygon);\r\n features.push(feature);\r\n });\r\n\r\n this.mapSource.addFeatures(features);\r\n }\r\n\r\n addNewObservations(numObservations) {\r\n for (let i=0; i x.id === id);\r\n }\r\n\r\n removeByID(id) {\r\n const observation = this.getByID(id);\r\n if (!observation) return;\r\n\r\n this.observations = this.observations.filter(x => x.id !== id);\r\n this.resetErrorValues();\r\n this.clearActiveObservation();\r\n this.drawObservations();\r\n }\r\n\r\n resetObservations() {\r\n this.observations = [];\r\n this.clearActiveObservation();\r\n this.drawObservations();\r\n }\r\n\r\n clearActiveObservation() {\r\n clearAerialTooltip();\r\n clearViewerTooltip();\r\n this.setActiveObservation(null, LocalObservationType.None);\r\n }\r\n\r\n onMouseUp(event: CustomMouseEvent): boolean {\r\n if (!this.enabled || !this.activeObservation || event.mouseMoved) {\r\n return false;\r\n }\r\n\r\n if (event.isLeftClick && this.isSceneObs) {\r\n this.onSceneClick(event);\r\n return true;\r\n } else if (event.isRightClick) {\r\n this.clearActiveObservation();\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onSceneClick(event) {\r\n let coordinate = this.getCoordinate(event);\r\n if (!coordinate) return;\r\n\r\n toast.success(t('local-projection.new_point_observation_added'));\r\n let position = new SceneCoordinate(coordinate).toDataProjection();\r\n this.activeObservation.scene = position;\r\n this.clearActiveObservation();\r\n this.drawObservations();\r\n }\r\n\r\n onMapClick(event) {\r\n if (!this.enabled || !this.isAerialObs) {\r\n return false;\r\n }\r\n\r\n toast.success(t('local-projection.new_aerial_observation_added'));\r\n this.activeObservation.aerial = event.coordinate;\r\n this.clearActiveObservation();\r\n }\r\n\r\n onMouseMoveScene() {\r\n if (!this.enabled || !this.isSceneObs) return false;\r\n\r\n if (this.activeObservation) {\r\n setViewerTooltip(this.sceneTooltip);\r\n return true;\r\n }\r\n\r\n clearViewerTooltip();\r\n return false;\r\n }\r\n\r\n onMouseMoveAerial() {\r\n if (!this.enabled || !this.isAerialObs) {\r\n return false;\r\n }\r\n\r\n if (this.activeObservation) {\r\n setAerialTooltip(this.aerialTooltip);\r\n } else {\r\n clearAerialTooltip();\r\n }\r\n }\r\n\r\n updateAllMeshes() {\r\n this.scene.children.forEach(child => {\r\n if (child instanceof PointObservation) {\r\n this.setPointScale(child);\r\n }\r\n });\r\n }\r\n\r\n update(changeDetector: ChangeDetector) {\r\n if (!this.enabled || !changeDetector.changed) return;\r\n\r\n this.updateAllMeshes();\r\n }\r\n}","import React from 'react';\r\nimport ControlPointIcon from '@mui/icons-material/ControlPoint';\r\nimport { Theme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { Box } from '@mui/material';\r\nimport { aerialObsColor, imageObsColor, pointObsColor } from '../viewer/data-aligner';\r\nimport clsx from 'clsx';\r\nimport { EnhancedIconButton, EnhancedIconButtonProps } from '../components';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n aerialObservationSuccess: {\r\n color: `#${aerialObsColor.toString(16)}`\r\n },\r\n imageObservationSuccess: {\r\n color: `#${imageObsColor.toString(16)}`\r\n },\r\n pointObservationSuccess: {\r\n color: `#${pointObsColor.toString(16)}`\r\n },\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n error: {\r\n color: theme.palette.error.main\r\n },\r\n info: {\r\n color: theme.palette.info.main\r\n },\r\n errorLow: {\r\n color: theme.palette.success.main\r\n },\r\n errorMedium: {\r\n color: theme.palette.warning.main\r\n },\r\n errorHigh: {\r\n color: theme.palette.error.main\r\n },\r\n }),\r\n);\r\n\r\ninterface BaseObservationIconProps extends EnhancedIconButtonProps {\r\n selected: boolean;\r\n clicked: boolean;\r\n}\r\n\r\nexport const PointObservationIcon = (props: BaseObservationIconProps) => {\r\n const classes = useStyles();\r\n return ObservationIcon({\r\n ...props,\r\n color: classes.pointObservationSuccess\r\n });\r\n};\r\n\r\nexport const AerialObservationIcon = (props: BaseObservationIconProps) => {\r\n const classes = useStyles();\r\n return ObservationIcon({\r\n ...props,\r\n color: classes.aerialObservationSuccess\r\n });\r\n};\r\n\r\nexport const ImageObservationIcon = (props: BaseObservationIconProps) => {\r\n const classes = useStyles();\r\n return ObservationIcon({\r\n ...props,\r\n color: classes.imageObservationSuccess\r\n });\r\n};\r\n\r\ninterface ObservationIconProps extends BaseObservationIconProps {\r\n color: string;\r\n}\r\n\r\nconst ObservationIcon = (props: ObservationIconProps) => {\r\n const {color, selected, clicked, ...other} = props;\r\n const classes = useStyles();\r\n\r\n let buttonColor;\r\n\r\n if (clicked) {\r\n buttonColor = classes.info;\r\n } else if (selected) {\r\n buttonColor = color;\r\n } else {\r\n buttonColor = classes.error;\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface ObservationErrorProps {\r\n value: any;\r\n lowCutoff: number;\r\n highCutoff: number\r\n}\r\n\r\nexport const ObservationError = (props: ObservationErrorProps) => {\r\n const {value, lowCutoff, highCutoff} = props;\r\n const classes = useStyles();\r\n const isNumber = !isNaN(parseFloat(value));\r\n\r\n if (!isNumber) {\r\n return {\"N/A\"};\r\n }\r\n\r\n return (\r\n = lowCutoff),\r\n [classes.errorHigh]: (value >= highCutoff)\r\n })}>\r\n {value.toFixed(2)}\r\n \r\n );\r\n};","import React, {useEffect, useState, memo, useMemo} from 'react';\r\nimport Button from '@mui/material/Button';\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {Checkbox} from \"@mui/material\";\r\nimport DialogActions from '@mui/material/DialogActions';\r\nimport DialogContent from '@mui/material/DialogContent';\r\nimport Typography from '@mui/material/Typography';\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport {\r\n EnhancedTable,\r\n DraggableDialog,\r\n PromptDialog\r\n} from '../components';\r\nimport { PythonExecutable, trackToolUsage } from '../executable';\r\nimport { fse, getTemporaryFile, registerEvent} from '../electron-modules';\r\nimport {\r\n getMatrixValues,\r\n saveMatrixFile,\r\n saveProject\r\n} from \"../utilities\";\r\nimport path from 'path';\r\nimport {\r\n changeBasicAdjustments,\r\n changeCameraTransform,\r\n selectBasicAdjustments,\r\n selectCameraTransform,\r\n selectActiveCamera\r\n} from '../redux/camera-slice';\r\nimport { selectAllAssets, getCameraFileAssets } from '../redux/assets-slice';\r\nimport LocalScene, { SceneCoordinate } from '../viewer/projections';\r\nimport { toast } from '../app';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { ImageObservationIcon, ObservationError, PointObservationIcon } from './observations';\r\nimport { AlignerObservation } from '../viewer/data-aligner';\r\nimport { UnitConverter } from '../viewer/utilities';\r\nimport {\r\n useDialog,\r\n useUniqueProjectID,\r\n useViewer,\r\n useActiveTool\r\n} from '../hooks';\r\nimport { useTableState } from '../hooks/use-table-state';\r\nimport * as CSV from 'csv-string';\r\nimport { Units } from '../types/project';\r\nimport { ObservationType } from '../types/aligner';\r\n\r\nconst converter = new UnitConverter();\r\n\r\nconst highCutoff = 1.0;\r\nconst lowCutoff = 0.5;\r\nconst requiredRows = 5;\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n minHeightContent: {\r\n minHeight: \"100px\"\r\n },\r\n toggleOptionParent: {\r\n margin: theme.spacing(0),\r\n padding: theme.spacing(0),\r\n boxShadow: \"0px 10px 10px 2px\",\r\n justifyContent: \"center\"\r\n },\r\n toggleOptionCheckbox: {\r\n paddingTop: theme.spacing(0.5),\r\n paddingBottom: theme.spacing(0.5)\r\n },\r\n toggleOptionFlex: {\r\n flex: 1,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n userWarning: {\r\n padding: theme.spacing(3)\r\n },\r\n box: {\r\n padding: theme.spacing(4)\r\n },\r\n marginBottom: {\r\n marginBottom: theme.spacing(2)\r\n },\r\n adornedEnd: {\r\n paddingRight: theme.spacing(0)\r\n },\r\n utmButton: {\r\n marginLeft: theme.spacing(1)\r\n },\r\n selectMargin: {\r\n margin: theme.spacing(1),\r\n },\r\n button: {\r\n marginTop: theme.spacing(2),\r\n marginLeft: theme.spacing(1)\r\n },\r\n dropdown: {\r\n minWidth: 200,\r\n },\r\n formControl: {\r\n width: '100%'\r\n },\r\n buttonDiv: {\r\n textAlign: \"right\"\r\n },\r\n success: {\r\n color: theme.palette.success.main\r\n },\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n error: {\r\n color: theme.palette.error.main\r\n },\r\n info: {\r\n color: theme.palette.info.main\r\n },\r\n assetCheckbox: {\r\n position: \"relative\",\r\n transform: \"translateY(0%)\"\r\n },\r\n checkboxPadding: {\r\n padding: \"0px\"\r\n },\r\n matrixValuesParent: {\r\n display: \"flex\",\r\n paddingTop: theme.spacing(2),\r\n justifyContent: \"space-evenly\"\r\n },\r\n matrixValues: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n textAlign: \"center\"\r\n }\r\n }),\r\n);\r\n\r\ninterface ResidualErrorProps {\r\n value: number\r\n}\r\n\r\nconst ResidualError = (props: ResidualErrorProps) => {\r\n return ;\r\n};\r\n\r\ninterface ImageAlignerAdvancedProps {\r\n observations: AlignerObservation[];\r\n}\r\n\r\nexport const ImageAlignerAdvanced = memo((props: ImageAlignerAdvancedProps) => {\r\n const {observations} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const theme = useTheme();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const tableState = useTableState();\r\n const alignerAdvDialog = useDialog();\r\n const removeDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {activeToolOpen, setActiveToolOpen} = useActiveTool();\r\n\r\n const [calculating, setCalculating] = useState(false);\r\n const [alignerMatrixPath, setAlignerMatrixPath] = useState(null);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [alignPosition, setAlignPosition] = useState(true);\r\n const [alignRotation, setAlignRotation] = useState(true);\r\n const [newRotation, setNewRotation] = useState([0,0,0]);\r\n const [newOffset, setNewOffset] = useState([0,0,0]);\r\n const units = LocalScene.dataProjectionUnits;\r\n\r\n const cameraTransformPath = useSelector(selectCameraTransform);\r\n const currentCamera = useSelector(selectActiveCamera);\r\n const basicAdjustments = useSelector(selectBasicAdjustments);\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const camerasFiles = getCameraFileAssets(assets);\r\n\r\n const exportCSV = async () => {\r\n let observationsCSV = [];\r\n let tmpObservationPath = getTemporaryFile('csv');\r\n\r\n let encompassCSV = [];\r\n let tmpEncompassPath = getTemporaryFile('csv');\r\n\r\n encompassCSV.push([\r\n 'filename', 'X', 'Y', 'Z', 'Roll', 'Pitch', 'Yaw'\r\n ]);\r\n\r\n observationsCSV.push([\r\n 'filename', 'x_img', 'y_img', 'z_img',\r\n 'x_ground', 'y_ground', 'z_ground'\r\n ]);\r\n\r\n observations.forEach(observation => {\r\n const {imageObs, pointObs, name, pose} = observation;\r\n\r\n observationsCSV.push([\r\n name,\r\n imageObs.x, imageObs.y, imageObs.z,\r\n pointObs.x, pointObs.y, pointObs.z\r\n ]);\r\n\r\n encompassCSV.push(pose);\r\n });\r\n\r\n const observationsCSVContent = CSV.stringify(observationsCSV);\r\n await fse.writeFile(tmpObservationPath, observationsCSVContent);\r\n\r\n const encompassCSVContent = CSV.stringify(encompassCSV);\r\n await fse.writeFile(tmpEncompassPath, encompassCSVContent);\r\n\r\n return {tmpObservationPath, tmpEncompassPath};\r\n };\r\n\r\n const runCalculation = async () => {\r\n const {tmpObservationPath, tmpEncompassPath} = await exportCSV();\r\n\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", \"camera_aligner_advanced\",\r\n \"--csv_obs\", tmpObservationPath,\r\n \"--csv_encompass\", tmpEncompassPath,\r\n \"--sulphur\", true,\r\n \"--align_position\", alignPosition,\r\n \"--align_rotation\", alignRotation,\r\n \"--units\", LocalScene.dataProjectionUnits\r\n ];\r\n\r\n let isConverted = false;\r\n let largeResiduals = false;\r\n\r\n let camPoseEntry = observations[0].pose;\r\n let initialPath = path.dirname(camPoseEntry[0]);\r\n let nameCorrection = path.basename(initialPath);\r\n let correctionName = nameCorrection + \"_correction_matrix.4x4\";\r\n let correctionPath = path.join(initialPath, correctionName);\r\n\r\n setCalculating(true);\r\n trackToolUsage(\"aligner-advanced\");\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n let residualsTemp = parseResiduals(jsonData);\r\n if (residualsTemp.length === 0) return;\r\n\r\n isConverted = true;\r\n viewer.setErrorsCameraAligner(residualsTemp);\r\n largeResiduals = residualsTemp\r\n .filter(x => x > highCutoff).length > 0;\r\n },\r\n onClose: () => {\r\n setCalculating(false);\r\n\r\n if (!isConverted) {\r\n return toast.error(t(\"toast.aligner-failed\"));\r\n }\r\n\r\n toast.success(t(\"toast.alignment-completed\"));\r\n setAlignerMatrixPath(correctionPath);\r\n\r\n if (largeResiduals) {\r\n toast.warning(t(\"toast.data-aligner-adv-large-error\"));\r\n }\r\n }\r\n });\r\n\r\n };\r\n\r\n const parseResiduals = (jsonData) => {\r\n let resArray = [];\r\n\r\n if (jsonData) {\r\n jsonData.forEach(res => {\r\n let rounded = Math.round(parseFloat(res) * 100) / 100;\r\n resArray.push(rounded);\r\n });\r\n }\r\n\r\n return resArray;\r\n };\r\n\r\n const addNewRow = () => {\r\n viewer.generateAdvancedAlignerRows(1);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const onDelete = (row) => {\r\n viewer.deleteRowCameraAligner(row.id);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const onClick = (row, index) => {\r\n if (index !== 0) return;\r\n\r\n const observation = observations.find(x => x.id === row.id);\r\n if (!observation) return;\r\n\r\n const camID = observation.imageIdentifier;\r\n const position = observation.imageMesh?.position;\r\n\r\n if (!position) return;\r\n\r\n const lookat = new SceneCoordinate(position).toDataProjection();\r\n viewer.loadImage(camID, {lookat});\r\n viewer.flashObservations(observation.id);\r\n };\r\n\r\n const onCancel = () => {\r\n setAlignerMatrixPath(null);\r\n viewer.clearErrorsCameraAligner();\r\n dispatch(changeCameraTransform(null));\r\n };\r\n\r\n const onClearAlignments = () => {\r\n dispatch(changeBasicAdjustments({}));\r\n viewer?.resetBasicAlignerCamera();\r\n saveProject(false);\r\n onCancel();\r\n };\r\n\r\n const confirmAlignment = () => {\r\n dispatch(changeCameraTransform(alignerMatrixPath));\r\n };\r\n\r\n const saveAlignmentFile = () => {\r\n saveMatrixFile(cameraTransformPath);\r\n };\r\n\r\n const handleAlignPositionCheck = () => {\r\n setAlignPosition(!alignPosition);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const handleAlignRotationCheck = () => {\r\n setAlignRotation(!alignRotation);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const checkClose = () => {\r\n if (!hasAlignment && !isTableEmpty()) {\r\n setClosePrompt(true);\r\n } else {\r\n alignerAdvDialog.handleClose();\r\n }\r\n };\r\n\r\n const onImageClick = (id: string) => {\r\n viewer.setCurrentObservation(id, ObservationType.Image);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const onSceneClick = (id: string) => {\r\n viewer.setCurrentObservation(id, ObservationType.Points);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const isTableEmpty = () => {\r\n const filledRows = observations.filter(observation => {\r\n return observation.pointObs || observation.imageObs;\r\n });\r\n\r\n return filledRows.length === 0;\r\n };\r\n\r\n const isTableFilled = () => {\r\n const filledRows = observations.filter(observation => {\r\n return observation.pointObs && observation.imageObs;\r\n });\r\n\r\n return filledRows.length === observations.length;\r\n };\r\n\r\n const getTransformValues = async (filePath) => {\r\n const cameraTransform = await getMatrixValues(filePath);\r\n\r\n let offset;\r\n if (cameraTransform.success) {\r\n offset = [\r\n converter.convert(cameraTransform.offset.x, Units.Meters, units, 2),\r\n converter.convert(cameraTransform.offset.y, Units.Meters, units, 2),\r\n converter.convert(cameraTransform.offset.z, Units.Meters, units, 2)\r\n ];\r\n } else {\r\n offset = [0,0,0];\r\n }\r\n\r\n let rotation;\r\n if (cameraTransform.success) {\r\n rotation = [\r\n cameraTransform.rotation.x.toFixed(2),\r\n cameraTransform.rotation.y.toFixed(2),\r\n cameraTransform.rotation.z.toFixed(2)\r\n ];\r\n } else {\r\n rotation = [0,0,0];\r\n }\r\n\r\n setNewRotation(rotation);\r\n setNewOffset(offset);\r\n };\r\n\r\n useEffect(() => {\r\n /** Keep track if a tool is currently being used */\r\n setActiveToolOpen(alignerAdvDialog.open);\r\n }, [alignerAdvDialog.open]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n alignerAdvDialog.handleClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-image-aligner-adv\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n alignerAdvDialog.handleOpen();\r\n });\r\n }, [activeToolOpen]);\r\n\r\n useEffect(() => {\r\n const aligned = cameraTransformPath !== null;\r\n const removed = currentCamera === null;\r\n const noCameras = camerasFiles.length === 0;\r\n\r\n if (aligned && removed && noCameras) {\r\n removeDialog.handleOpen();\r\n }\r\n }, [currentCamera]);\r\n\r\n useEffect(() => {\r\n getTransformValues(alignerMatrixPath);\r\n }, [alignerMatrixPath]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n viewer.toggleCameraAligner(alignerAdvDialog.open);\r\n if (!alignerAdvDialog.open) return;\r\n\r\n viewer.generateAdvancedAlignerRows(requiredRows);\r\n }, [viewer, alignerAdvDialog.open]);\r\n\r\n const getRows = (observations, calculating) => {\r\n return observations.map(observation => {\r\n const disabled = calculating;\r\n\r\n const imageSelected = !!observation.imageObs;\r\n const imageClicked = observation.imageSelected;\r\n\r\n const pointSelected = !!observation.pointObs;\r\n const pointClicked = observation.pointSelected;\r\n\r\n const imageObs = (\r\n {\r\n if (disabled) return;\r\n onImageClick(observation.id);\r\n }}\r\n />\r\n );\r\n\r\n const pointObs = (\r\n {\r\n if (disabled) return;\r\n onSceneClick(observation.id);\r\n }}\r\n />\r\n );\r\n\r\n const error = (\r\n \r\n );\r\n\r\n return {\r\n id: observation.id,\r\n name: t(observation.name),\r\n img_obs: imageObs,\r\n pc_obs: pointObs,\r\n error,\r\n disabled\r\n };\r\n });\r\n };\r\n\r\n const calculated = !!alignerMatrixPath;\r\n const hasBasicAlignment = Object.keys(basicAdjustments).length !== 0;\r\n const hasAdvancedAlignment = !!cameraTransformPath;\r\n const hasAlignment = hasBasicAlignment || hasAdvancedAlignment;\r\n\r\n const canSubmit = isTableFilled()\r\n && observations.length >= requiredRows\r\n && (alignPosition || alignRotation)\r\n && !calculating;\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t(\"data-aligner-adv.filename\"),\r\n pointer: true,\r\n wordBreak: true\r\n },\r\n {\r\n id: 'img_obs',\r\n label: t(\"data-aligner-adv.image-control\"),\r\n center: true,\r\n sortable: false\r\n },\r\n {\r\n id: 'pc_obs',\r\n label: t(\"data-aligner-adv.point-control\"),\r\n center: true,\r\n sortable: false\r\n },\r\n {\r\n id: 'error',\r\n label: t(\"data-aligner-adv.error\") + '(\\u00B0)',\r\n numeric: true,\r\n center: true\r\n }\r\n ];\r\n\r\n const rows = useMemo(() => {\r\n return getRows(observations, calculating);\r\n }, [observations, calculating]);\r\n\r\n const actions = [\r\n {\r\n title: t(\"buttons.delete\"),\r\n icon: ,\r\n onClick: (row) => {\r\n deleteDialog.handleOpen(row);\r\n }\r\n }\r\n ];\r\n\r\n return (\r\n \r\n\r\n \r\n {/** Clear previous alignment */}\r\n {hasAlignment && (\r\n \r\n \r\n {t(\"data-aligner-adv.have-set-alignment\")}\r\n \r\n \r\n\r\n \r\n\r\n {/** Download saved alignment matrix */}\r\n {hasAdvancedAlignment && (\r\n \r\n )}\r\n\r\n {/** Clear all previous alignments */}\r\n \r\n\r\n \r\n )}\r\n\r\n {/** Standard conditions */}\r\n {!hasAlignment && (\r\n \r\n \r\n {t(\"data-aligner-adv.select-at-least\", {requiredRows})}\r\n \r\n\r\n \r\n\r\n \r\n\r\n {calculated && (
\r\n \r\n {t('data-aligner-adv.matrix_offset_units', {units})}: [{newOffset[0]}, {newOffset[1]}, {newOffset[2]}]\r\n \r\n\r\n \r\n {t('data-aligner-adv.matrix_rotation')}: [{newRotation[0]}, {newRotation[1]}, {newRotation[2]}]\r\n \r\n
)}\r\n\r\n \r\n {/** Add new observation row */}\r\n \r\n\r\n {/** Cancel calculated alignment */}\r\n {calculated && (\r\n \r\n )}\r\n\r\n {/** Run python calculations */}\r\n {!calculated && (\r\n \r\n )}\r\n\r\n {/** Confirm alignment */}\r\n {calculated && (\r\n \r\n )}\r\n \r\n\r\n \r\n {/* Calculate lever arm */}\r\n
\r\n \r\n {t('data-aligner-adv.allow_offset')}\r\n \r\n \r\n
\r\n\r\n {/* Calculate rotation */}\r\n
\r\n \r\n {t('data-aligner-adv.allow_rotation')}\r\n \r\n \r\n
\r\n
\r\n\r\n
)}\r\n\r\n \r\n\r\n {/* Delete Dialog */}\r\n {\r\n onDelete(deleteDialog.data);\r\n deleteDialog.handleClose();\r\n }}\r\n title={t(\"enhanced-table.prompt-delete-title\")}\r\n prompt={t('data-aligner-adv.do_you_want_to_delete_this_observation')}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n setClosePrompt(false)}\r\n onSubmit={() => {\r\n alignerAdvDialog.handleClose();\r\n setClosePrompt(false);\r\n }}\r\n title={t(\"data-aligner-adv.prompt-close-aligner-title\")}\r\n prompt={t(\"data-aligner-adv.prompt-close-aligner-text\")}\r\n button={t('buttons.close')}\r\n />\r\n\r\n {\r\n dispatch(changeCameraTransform(null));\r\n removeDialog.handleClose();\r\n }}\r\n title={t(\"data-aligner-adv.prompt-remove-matrix-title\")}\r\n prompt={t(\"data-aligner-adv.prompt-remove-matrix-text\")}\r\n button={t('buttons.remove-matrix')}\r\n />\r\n
\r\n );\r\n});\r\n","import React, {useEffect, useState, memo} from 'react';\r\nimport { Theme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n Box,\r\n Button,\r\n DialogActions,\r\n DialogContent,\r\n Grid,\r\n Typography\r\n} from '@mui/material';\r\nimport { DraggableDialog, PromptDialog } from '../components';\r\nimport clsx from 'clsx';\r\nimport {\r\n changeBasicAdjustments,\r\n changeCameraTransform,\r\n selectBasicAdjustments,\r\n selectCameraTransform,\r\n selectActiveCamera\r\n} from '../redux/camera-slice';\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport { saveProject } from \"../utilities\";\r\nimport { trackToolUsage } from \"../executable\";\r\nimport { toast } from '../app';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport {isEqual} from 'lodash';\r\nimport {\r\n useDialog,\r\n useUniqueProjectID,\r\n useViewer,\r\n useActiveTool\r\n} from '../hooks';\r\nimport { registerEvent } from '../electron-modules';\r\nimport { Vector3 } from 'three';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n minHeightContent: {\r\n minHeight: \"100px\"\r\n },\r\n titleTop: {\r\n marginTop: theme.spacing(2.0)\r\n },\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n success: {\r\n color: theme.palette.success.main\r\n }\r\n }),\r\n);\r\n\r\nconst AlignerShortcuts = () => {\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n {t(\"data-aligner-basic.adjust-roll\")} (-):\r\n {t(\"data-aligner-basic.keypad\")} 7\r\n \r\n \r\n\r\n \r\n \r\n \r\n {t(\"data-aligner-basic.adjust-roll\")} (+):\r\n {t(\"data-aligner-basic.keypad\")} 9\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"data-aligner-basic.adjust-pitch\")} (-):\r\n {t(\"data-aligner-basic.keypad\")} 4\r\n \r\n \r\n\r\n \r\n \r\n \r\n {t(\"data-aligner-basic.adjust-pitch\")} (+):\r\n {t(\"data-aligner-basic.keypad\")} 6\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n {t(\"data-aligner-basic.adjust-yaw\")} (-):\r\n {t(\"data-aligner-basic.keypad\")} 1\r\n \r\n \r\n\r\n \r\n \r\n \r\n {t(\"data-aligner-basic.adjust-yaw\")} (+):\r\n {t(\"data-aligner-basic.keypad\")} 3\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const ImageAlignerBasic = memo(() => {\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const alignerBasicDialog = useDialog();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {activeToolOpen, setActiveToolOpen} = useActiveTool();\r\n\r\n const [singleAlignment, setSingleAlignment] = useState([0, 0, 0]);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [hasTransform, setHasTransform] = useState(false);\r\n const currentCamera = useSelector(selectActiveCamera);\r\n const basicAdjustments = useSelector(selectBasicAdjustments);\r\n const cameraTransformPath = useSelector(selectCameraTransform);\r\n\r\n const handleClose = () => {\r\n alignerBasicDialog.handleClose();\r\n setClosePrompt(false);\r\n };\r\n\r\n const checkClose = () => {\r\n if (isModified) {\r\n setClosePrompt(true);\r\n } else {\r\n handleClose();\r\n }\r\n };\r\n\r\n const resetAligner = () => {\r\n viewer?.resetBasicAlignerCamera(savedAngle);\r\n toast.success(t(\"toast.alignment-reset\"));\r\n };\r\n\r\n const saveAdjustment = () => {\r\n const updated = {...basicAdjustments};\r\n\r\n const vector = new Vector3(...alignment);\r\n const valid = vector.length() !== 0;\r\n\r\n if (valid) {\r\n updated[currentCamera] = alignment;\r\n } else {\r\n delete updated[currentCamera];\r\n }\r\n\r\n dispatch(changeBasicAdjustments(updated));\r\n viewer?.resetBasicAlignerCamera(alignment);\r\n saveProject(false);\r\n\r\n trackToolUsage(\"aligner-basic\");\r\n toast.success(t(\"toast.alignment-saved\"));\r\n };\r\n\r\n const cancelAdvancedAlignment = () => {\r\n dispatch(changeCameraTransform(null));\r\n saveProject(false);\r\n };\r\n\r\n const checkDataModified = () => {\r\n if (!hasActiveCamera) return false;\r\n\r\n const epsilon = 1e-10;\r\n const dx = Math.abs(savedAngle[0] - singleAlignment[0]) < epsilon;\r\n const dy = Math.abs(savedAngle[1] - singleAlignment[1]) < epsilon;\r\n const dz = Math.abs(savedAngle[2] - singleAlignment[2]) < epsilon;\r\n\r\n return !(dx && dy && dz);\r\n };\r\n\r\n useEffect(() => {\r\n /** Keep track if a tool is currently being used */\r\n setActiveToolOpen(alignerBasicDialog.open);\r\n }, [alignerBasicDialog.open]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n alignerBasicDialog.handleClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-image-aligner-basic\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n alignerBasicDialog.handleOpen();\r\n });\r\n }, [activeToolOpen]);\r\n\r\n useEffect(() => {\r\n setHasTransform(cameraTransformPath !== null);\r\n }, [viewer, cameraTransformPath]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n\r\n const enabled = hasActiveCamera && alignerBasicDialog.open;\r\n viewer.setBasicAlignerState(enabled);\r\n }, [viewer, alignerBasicDialog.open, currentCamera]);\r\n\r\n useEffect(() => {\r\n // Not applicable if transform matrix is applied\r\n if (hasTransform) return;\r\n\r\n viewer?.resetBasicAlignerCamera(savedAngle);\r\n }, [viewer, currentCamera]);\r\n\r\n useEffect(() => {\r\n if (!viewer || !alignerBasicDialog.open) return;\r\n\r\n let interval = setInterval(() => {\r\n const angles = viewer.getBasicAlignerValue();\r\n\r\n /** NOTE: react will never return equal for arrays, so lodash is used */\r\n if (isEqual(singleAlignment, angles)) return;\r\n setSingleAlignment([...angles]);\r\n }, 50);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [viewer, alignerBasicDialog.open, singleAlignment]);\r\n\r\n const hasActiveCamera = currentCamera !== null;\r\n const activeCameraName = hasActiveCamera ?\r\n viewer?.getCurrentCameraName() : null;\r\n\r\n const alignment = hasActiveCamera\r\n ? singleAlignment.map(x => parseFloat(x.toFixed(2)))\r\n : [0,0,0];\r\n\r\n const savedAngle = currentCamera in basicAdjustments\r\n ? basicAdjustments[currentCamera]\r\n : [0, 0, 0];\r\n\r\n const isModified = checkDataModified();\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {(hasTransform) && (\r\n {t(\"data-aligner-basic.global-transformation\")}\r\n )}\r\n\r\n {(hasTransform === false) && (\r\n {/* Current camera section */}\r\n \r\n \r\n {t(\"data-aligner-basic.current-camera\")}:\r\n \r\n\r\n \r\n {hasActiveCamera ? activeCameraName : t(\"data-aligner-basic.no-camera-selected\")}\r\n \r\n \r\n\r\n {/* Current adjustment section */}\r\n \r\n \r\n {t(\"data-aligner-basic.current-adjustment\")}:\r\n \r\n\r\n \r\n {hasActiveCamera ? `[${alignment[0]}, ${alignment[1]}, ${alignment[2]}]` :\r\n t(\"general.not-applicable\")}\r\n \r\n \r\n\r\n {/* Current adjustment section */}\r\n \r\n \r\n {t(\"data-aligner-basic.alignment-status\")}:\r\n \r\n\r\n \r\n {isModified ? t(\"data-aligner-basic.modified\") : t(\"data-aligner-basic.saved\")}\r\n \r\n \r\n\r\n {/* Alignment shortcut keys */}\r\n \r\n \r\n {t(\"data-aligner-basic.alignment-shortcuts\")}:\r\n \r\n\r\n \r\n \r\n )}\r\n\r\n \r\n\r\n \r\n {(hasTransform) && ()}\r\n\r\n {(hasTransform === false) && (\r\n \r\n {t(\"buttons.reset-values\")}\r\n \r\n\r\n \r\n {t(\"buttons.save-adjustment\")}\r\n \r\n )}\r\n \r\n \r\n\r\n setClosePrompt(false)}\r\n onSubmit={() => {\r\n viewer?.resetBasicAlignerCamera(savedAngle);\r\n handleClose();\r\n }}\r\n title={t(\"data-aligner-basic.prompt-close-aligner-title\")}\r\n prompt={t(\"data-aligner-basic.prompt-close-aligner-text\")}\r\n button={t('buttons.close')}\r\n />\r\n \r\n );\r\n});","import React, {useEffect, useState, memo, useMemo} from 'react';\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { toast } from '../app';\r\nimport DeleteIcon from \"@mui/icons-material/Delete\";\r\nimport { DraggableDialog, EnhancedTable, PromptDialog, TextDialog } from '../components';\r\nimport { Button, Checkbox, DialogActions, DialogContent, Typography } from '@mui/material';\r\nimport { LocalObservation } from '../viewer/data-aligner';\r\nimport { AerialObservationIcon, ObservationError, PointObservationIcon } from './observations';\r\nimport { updateDataProjection, updateViewProjection, selectDataProjection, Transform } from '../redux/projections-slice';\r\nimport { useDispatch, useSelector } from 'react-redux';\r\nimport { projectionToUnits } from '../viewer/projections';\r\nimport { UnitConverter } from '../viewer/utilities';\r\nimport { userProjections } from '../projections';\r\nimport { trackToolUsage } from '../executable';\r\nimport { nanoid } from '@reduxjs/toolkit';\r\nimport {\r\n useDialog,\r\n useUniqueProjectID,\r\n useViewer,\r\n useActiveTool\r\n} from '../hooks';\r\nimport { registerEvent } from '../electron-modules';\r\nimport { useTableState } from '../hooks/use-table-state';\r\nimport { Units } from '../types/project';\r\nimport { LocalObservationType } from '../types/aligner';\r\n\r\nconst highCutoff = 0.5;\r\nconst lowCutoff = 0.25;\r\nconst requiredRows = 3;\r\n\r\nconst converter = new UnitConverter();\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n transformInfo: {\r\n display: \"flex\",\r\n justifyContent: \"space-evenly\",\r\n paddingTop: theme.spacing(1)\r\n },\r\n toggleOptionFlex: {\r\n flex: 1,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n toggleOptionParent: {\r\n margin: theme.spacing(0),\r\n padding: theme.spacing(0),\r\n boxShadow: \"0px 10px 10px 2px\",\r\n justifyContent: \"center\"\r\n },\r\n toggleOptionCheckbox: {\r\n paddingTop: theme.spacing(0.5),\r\n paddingBottom: theme.spacing(0.5)\r\n },\r\n transformValues: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n textAlign: \"center\"\r\n }\r\n }),\r\n);\r\n\r\ninterface AlignmentErrorProps {\r\n value: number;\r\n units: Units;\r\n}\r\n\r\nconst AlignmentError = (props: AlignmentErrorProps) => {\r\n const lowCutoffWithUnits = converter.convert(lowCutoff, Units.Meters, props.units);\r\n const highCutoffWithUnits = converter.convert(highCutoff, Units.Meters, props.units);\r\n\r\n return ;\r\n};\r\n\r\ninterface LocalAlignerProps {\r\n observations: LocalObservation[];\r\n}\r\n\r\nexport const LocalAligner = memo((props: LocalAlignerProps) => {\r\n const observations = props.observations as LocalObservation[];\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const theme = useTheme();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const tableState = useTableState();\r\n const localAlignerDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {activeToolOpen, setActiveToolOpen} = useActiveTool();\r\n\r\n const dataProjection = useSelector(selectDataProjection);\r\n const units = projectionToUnits(dataProjection);\r\n\r\n const [calculating, setCalculating] = useState(false);\r\n const [rotate, setRotate] = useState(true);\r\n const [scale, setScale] = useState(true);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [utmZone, setUtmZone] = useState(0);\r\n const [savePrompt, setSavePrompt] = useState(false);\r\n const [oldProjection, setOldProjection] = useState(null);\r\n const [newProjection, setNewProjection] = useState(null);\r\n\r\n const handleScale = () => {\r\n setScale(!scale);\r\n };\r\n\r\n const handleRotate = () => {\r\n setRotate(!rotate);\r\n };\r\n\r\n const addNewRow = () => {\r\n viewer.generateLocalAlignerRows(1);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const onDelete = (row) => {\r\n viewer.deleteLocalAlignment(row.id);\r\n setNewProjection(null);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const checkClose = () => {\r\n if (!isTableEmpty()) {\r\n setClosePrompt(true);\r\n } else {\r\n localAlignerDialog.handleClose();\r\n }\r\n };\r\n\r\n const isTableEmpty = () => {\r\n const filledRows = observations.filter(observation => {\r\n return observation.scene || observation.aerial;\r\n });\r\n\r\n return filledRows.length === 0;\r\n };\r\n\r\n const isTableFilled = () => {\r\n const filledRows = observations.filter(observation => {\r\n return observation.scene && observation.aerial;\r\n });\r\n\r\n return filledRows.length === observations.length;\r\n };\r\n\r\n const getEstimator = () => {\r\n let estimator = \"T\";\r\n if (scale) estimator += \"S\";\r\n if (rotate) estimator += \"R\";\r\n return estimator;\r\n };\r\n\r\n const runCalculation = async () => {\r\n setCalculating(true);\r\n trackToolUsage(\"aligner-local\");\r\n\r\n const estimator = getEstimator();\r\n const {projection, utmZone}\r\n = await viewer.estimateLocalTransform(estimator, units);\r\n\r\n const tempProjection = {\r\n ...projection,\r\n name: `Temp Projection ${nanoid(6)}`\r\n };\r\n\r\n userProjections.save(tempProjection);\r\n dispatch(updateDataProjection(tempProjection));\r\n dispatch(updateViewProjection(tempProjection));\r\n\r\n setNewProjection(tempProjection);\r\n setUtmZone(utmZone);\r\n\r\n setCalculating(false);\r\n toast.success(t('local-projection.calculation_completed'));\r\n };\r\n\r\n const onCancel = () => {\r\n // Revert back to original projection\r\n updateViewerProjection(oldProjection);\r\n\r\n // Delete new projection\r\n deleteViewerProjection(newProjection);\r\n\r\n // Clear calculated values\r\n viewer.clearLocalTransformErrors();\r\n setNewProjection(null);\r\n };\r\n\r\n const saveNewProjection = () => {\r\n setSavePrompt(true);\r\n };\r\n\r\n const deleteViewerProjection = (projection) => {\r\n if (!projection) return;\r\n userProjections.delete(projection.name);\r\n };\r\n\r\n const updateViewerProjection = (projection) => {\r\n if (dataProjection === projection) return;\r\n dispatch(updateDataProjection(projection));\r\n dispatch(updateViewProjection(projection));\r\n };\r\n\r\n const onAddProjection = (name) => {\r\n if (userProjections.getByName(name)) {\r\n toast.error(t(\"toast.projection-duplicate\"));\r\n return;\r\n }\r\n\r\n const projection = {...newProjection, name};\r\n userProjections.save(projection);\r\n updateViewerProjection(projection);\r\n setSavePrompt(false);\r\n localAlignerDialog.handleClose();\r\n };\r\n\r\n const resetDefaults = () => {\r\n setRotate(true);\r\n setScale(true);\r\n setNewProjection(null);\r\n };\r\n\r\n const onAerialClick = (id) => {\r\n viewer.setLocalAlignerActive(id, LocalObservationType.Aerial);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const onSceneClick = (id) => {\r\n viewer.setLocalAlignerActive(id, LocalObservationType.Scene);\r\n if (!calculated) return;\r\n onCancel();\r\n };\r\n\r\n const getTransformValues = () => {\r\n let translateX;\r\n let translateY;\r\n let rotation;\r\n let scaling;\r\n\r\n if (calculated) {\r\n const transform = newProjection.transform as Transform;\r\n translateX = transform.origin[0].toFixed(2);\r\n translateY = transform.origin[1].toFixed(2);\r\n rotation = (-1*transform.rotation).toFixed(2);\r\n scaling = (1.0/transform.scale).toFixed(2);\r\n }\r\n\r\n return {translateX, translateY, rotation, scaling};\r\n };\r\n\r\n const getRows = (observations, calculating) => {\r\n return observations.map(observation => {\r\n const disabled = calculating;\r\n\r\n const aerialSelected = !!observation.aerial;\r\n const aerialClicked = observation.active === LocalObservationType.Aerial;\r\n\r\n const pointSelected = !!observation.scene;\r\n const pointClicked = observation.active === LocalObservationType.Scene;\r\n\r\n const aerialObs = (\r\n {\r\n if (disabled) return;\r\n onAerialClick(observation.id);\r\n }}\r\n />\r\n );\r\n\r\n const pointObs = (\r\n {\r\n if (disabled) return;\r\n onSceneClick(observation.id);\r\n }}\r\n />\r\n );\r\n\r\n const error = (\r\n \r\n );\r\n\r\n return {\r\n id: observation.id,\r\n disabled,\r\n map_obs: aerialObs,\r\n pc_obs: pointObs,\r\n error: error,\r\n };\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n /** Keep track if a tool is currently being used */\r\n setActiveToolOpen(localAlignerDialog.open);\r\n }, [localAlignerDialog.open]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n localAlignerDialog.handleClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-local-projection\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n localAlignerDialog.handleOpen();\r\n });\r\n }, [activeToolOpen]);\r\n\r\n useEffect(() => {\r\n viewer?.toggleLocalAligner(localAlignerDialog.open);\r\n\r\n if (localAlignerDialog.open) {\r\n viewer?.generateLocalAlignerRows(requiredRows);\r\n setOldProjection(dataProjection);\r\n } else {\r\n resetDefaults();\r\n }\r\n userProjections.load();\r\n }, [viewer, localAlignerDialog.open]);\r\n\r\n const calculated = !!newProjection;\r\n const {translateX, translateY, rotation, scaling}\r\n = getTransformValues();\r\n\r\n const canSubmit = isTableFilled()\r\n && observations.length >= requiredRows\r\n && !calculating;\r\n\r\n const columns = [\r\n {\r\n id: \"map_obs\",\r\n label: t('local-projection.aerial_control'),\r\n center: true,\r\n sortable: false\r\n },\r\n {\r\n id: \"pc_obs\",\r\n label: t('local-projection.point_control'),\r\n center: true,\r\n sortable: false\r\n },\r\n {\r\n id: \"error\",\r\n label: t('local-projection.error_units', {units}),\r\n numeric: true,\r\n center: true,\r\n forceOpacity: true\r\n }\r\n ];\r\n\r\n const rows = useMemo(() => {\r\n return getRows(observations, calculating);\r\n }, [observations, calculating]);\r\n\r\n const actions = [\r\n {\r\n title: t(\"buttons.delete\"),\r\n icon: ,\r\n onClick: (row) => {\r\n deleteDialog.handleOpen(row);\r\n }\r\n }\r\n ];\r\n\r\n return (\r\n \r\n\r\n \r\n \r\n \r\n {t(\"local-projection.select-at-least\", {requiredRows})}\r\n \r\n\r\n \r\n \r\n\r\n {calculated && (\r\n
\r\n \r\n {t('local-projection.estimated_rotation')} {rotation}\r\n \r\n\r\n \r\n {t('local-projection.estimated_scale')} {scaling}\r\n \r\n
\r\n\r\n
\r\n \r\n {t('local-projection.estimated_offset')} [{translateX}, {translateY}]\r\n \r\n\r\n \r\n {t('local-projection.closest_utm_zone')} {utmZone}\r\n \r\n
\r\n
)}\r\n\r\n \r\n {/** Add new observation row */}\r\n \r\n\r\n {/** Cancel projection */}\r\n {calculated && (\r\n \r\n )}\r\n\r\n {/** Run python calculations */}\r\n {!calculated && (\r\n \r\n )}\r\n\r\n {/** Confirm projection */}\r\n {calculated && (\r\n \r\n )}\r\n \r\n\r\n \r\n {/* Allow scaling while estimating transform */}\r\n
\r\n \r\n {t('local-projection.allow_scaling')}\r\n \r\n \r\n
\r\n\r\n {/* Allow rotation while estimating transform */}\r\n
\r\n \r\n {t('local-projection.allow_rotation')}\r\n \r\n \r\n
\r\n
\r\n\r\n \r\n\r\n {/* Delete Dialog */}\r\n {\r\n onDelete(deleteDialog.data);\r\n deleteDialog.handleClose();\r\n }}\r\n title={t(\"enhanced-table.prompt-delete-title\")}\r\n prompt={t('local-projection..do_you_want_to_delete_this_observation')}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n setSavePrompt(false)}\r\n onSubmit={onAddProjection}\r\n title={t('local-projection.create_new_projection')}\r\n prompt={t('local-projection.enter_local_projection_name')}\r\n label={t('local-projection.projection_name')}\r\n clear={true}\r\n />\r\n\r\n setClosePrompt(false)}\r\n onSubmit={() => {\r\n onCancel();\r\n localAlignerDialog.handleClose();\r\n setClosePrompt(false);\r\n }}\r\n title={t('local-projection.close_local_alignment')}\r\n prompt={t('local-projection.do_you_want_to_close_the_local_projection_aligner')}\r\n button={t('buttons.close')}\r\n />\r\n\r\n
\r\n );\r\n});\r\n","import React, {useRef, useCallback, useEffect, useState, memo} from 'react';\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport InfoIcon from '@mui/icons-material/Info';\r\nimport WarningIcon from '@mui/icons-material/Warning';\r\nimport PriorityHighIcon from '@mui/icons-material/PriorityHigh';\r\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\r\nimport ExpandLessIcon from '@mui/icons-material/ExpandLess';\r\nimport HistoryIcon from '@mui/icons-material/History';\r\nimport AddToPhotosIcon from '@mui/icons-material/AddToPhotos';\r\nimport DeleteIcon from '@mui/icons-material/Delete';\r\nimport ZoomInIcon from '@mui/icons-material/ZoomIn';\r\nimport SortIcon from '@mui/icons-material/Sort';\r\nimport SortByAlphaIcon from '@mui/icons-material/SortByAlpha';\r\nimport ImportExportIcon from '@mui/icons-material/ImportExport';\r\nimport TextFieldsIcon from '@mui/icons-material/TextFields';\r\nimport Visibility from '@mui/icons-material/Visibility';\r\nimport VisibilityOff from '@mui/icons-material/VisibilityOff';\r\nimport {\r\n Box,\r\n Card,\r\n CardHeader,\r\n Checkbox,\r\n CircularProgress,\r\n Dialog,\r\n DialogContent,\r\n FormHelperText,\r\n Grid,\r\n InputLabel,\r\n List,\r\n ListItem,\r\n MenuItem,\r\n TextField,\r\n Typography\r\n} from '@mui/material';\r\nimport {\r\n LinearProgressWithLabel,\r\n EnhancedIconButton,\r\n ProgressDialog,\r\n TextDialog,\r\n DraggableDialog,\r\n PromptDialog,\r\n DenseDivider,\r\n IconToolBar,\r\n SlimScrollbar,\r\n ToolBarButton,\r\n ArrowTooltip,\r\n EnhancedTable,\r\n DropdownWithLabel,\r\n NumberFieldWithLabel,\r\n CheckboxWithLabel,\r\n FileWithLabel,\r\n FolderWithLabel,\r\n NumberField,\r\n DraggableList,\r\n TextWithLabel,\r\n InputWithLabel,\r\n LabelCategoryDialog,\r\n DenseMenu\r\n} from '../components';\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n dialog,\r\n ipcRenderer,\r\n fs,\r\n getTemporaryFile,\r\n shell,\r\n tempDirectoryPath,\r\n registerEvent,\r\n fse\r\n} from '../electron-modules';\r\nimport { changeSwitched } from \"../redux/settings-slice\";\r\nimport slash from 'slash';\r\nimport { PythonExecutable } from '../executable';\r\nimport LocalScene from '../viewer/projections';\r\nimport { FixedSizeList } from \"react-window\";\r\nimport path from 'path';\r\nimport {\r\n addAsset,\r\n Asset,\r\n AssetType,\r\n deleteAsset,\r\n getCameraFileAssets,\r\n getPointCloudAssets,\r\n selectAllAssets\r\n} from '../redux/assets-slice';\r\nimport { asyncTimeout, useAssetTools } from '../utilities';\r\nimport DialogTitle from '@mui/material/DialogTitle/DialogTitle';\r\nimport Button from '@mui/material/Button/Button';\r\nimport DialogActions from '@mui/material/DialogActions/DialogActions';\r\nimport Select from '@mui/material/Select/Select';\r\nimport { nanoid } from '@reduxjs/toolkit';\r\nimport { throttle } from 'throttle-debounce';\r\nimport { selectProjectName } from '../redux/project-slice';\r\nimport Paper from '@mui/material/Paper';\r\nimport { DropResult } from 'react-beautiful-dnd';\r\nimport { toast } from '../app';\r\nimport clsx from 'clsx';\r\nimport {\r\n ImageLabel,\r\n LabelCategory,\r\n textToColor,\r\n getClassFromAlias,\r\n getNameFromClass,\r\n TrainingAreaLabel,\r\n TrainingAreaCategory\r\n} from '../viewer/labelling';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {\r\n drawingFilter,\r\n DXFModelFilter,\r\n getCombinedExtension,\r\n labelFilter,\r\n modelFilter,\r\n SHPModelFilter\r\n} from '../file-extensions';\r\nimport {\r\n useDialog,\r\n useUniqueProjectID,\r\n useViewer,\r\n useActiveTool,\r\n useContextMenu\r\n} from '../hooks';\r\nimport {selectDefaultFolder} from \"../redux/folders-slice\";\r\nimport { useTableState } from '../hooks/use-table-state';\r\nimport CompareArrowsIcon from \"@mui/icons-material/CompareArrows\";\r\nimport * as CSV from 'csv-string';\r\n\r\nenum LabelImportType {\r\n Ignore=\"__ignore\",\r\n Default=\"__default\"\r\n}\r\n\r\nconst labelHeight = 53;\r\nconst geometryLimit = 1000;\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n titleClose: {\r\n position: 'absolute',\r\n right: theme.spacing(0),\r\n color: theme.palette.grey[500],\r\n },\r\n titleInfo: {\r\n position: 'absolute',\r\n right: theme.spacing(4),\r\n marginTop: theme.spacing(0),\r\n color: theme.palette.grey[500],\r\n },\r\n titleMin: {\r\n position: 'absolute',\r\n right: theme.spacing(4),\r\n marginTop: theme.spacing(-1),\r\n color: theme.palette.grey[500],\r\n },\r\n userWarning: {\r\n padding: theme.spacing(3)\r\n },\r\n marginTop: {\r\n marginTop: theme.spacing(2)\r\n },\r\n box: {\r\n padding: theme.spacing(4)\r\n },\r\n formControl: {\r\n width: '100%'\r\n },\r\n listContent: {\r\n margin: theme.spacing(0),\r\n padding: theme.spacing(0)\r\n },\r\n categoryName: {\r\n flex: 1\r\n },\r\n inputLabel: {\r\n height: \"fit-content\",\r\n whiteSpace: \"normal\"\r\n },\r\n success: {\r\n color: theme.palette.success.main\r\n },\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n error: {\r\n color: theme.palette.error.main\r\n },\r\n info: {\r\n color: theme.palette.info.main\r\n },\r\n folderList: {\r\n padding: \"0px\",\r\n overflow: \"auto\",\r\n flex: 1,\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n headerTitle: {\r\n fontWeight: \"bold\",\r\n cursor: \"pointer\"\r\n },\r\n cardHeader: {\r\n padding: theme.spacing(1)\r\n },\r\n cardButtons: {\r\n marginTop: 0,\r\n alignSelf: \"center\"\r\n },\r\n labelFixedHeight: {\r\n height: `${labelHeight}px`\r\n },\r\n labelParent: {\r\n flex: 1,\r\n userSelect: \"none\",\r\n display: \"flex\",\r\n flexDirection: \"column\"\r\n },\r\n labelTitleWarning: {\r\n color: theme.palette.warning.main\r\n },\r\n labelTitleError: {\r\n color: theme.palette.error.main\r\n },\r\n classificationText: {\r\n fontSize: \"0.6rem\"\r\n },\r\n card: {\r\n margin: theme.spacing(2),\r\n marginTop: theme.spacing(0),\r\n padding: theme.spacing(1),\r\n userSelect: \"none\"\r\n },\r\n progressToolbar: {\r\n display: \"flex\",\r\n marginLeft: \"12px\",\r\n marginRight: \"12px\"\r\n },\r\n toolbarLinear: {\r\n margin: \"auto 12px\"\r\n },\r\n toolbarProgressCenter: {\r\n top: \"50%\",\r\n height: \"6px\",\r\n marginTop: \"-3px\"\r\n },\r\n downloadMargin: {\r\n marginTop: theme.spacing(1)\r\n },\r\n downloadResourceDialog: {\r\n paddingTop: theme.spacing(2.5),\r\n paddingBottom: theme.spacing(2.5),\r\n paddingLeft: theme.spacing(4),\r\n paddingRight: theme.spacing(4)\r\n },\r\n mixedDataWarning: {\r\n padding: theme.spacing(2.0),\r\n color: theme.palette.warning.main\r\n },\r\n tableDropdown: {\r\n fontSize: \"0.875rem\",\r\n width: \"100%\"\r\n },\r\n checkBoxWithLabel: {\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n },\r\n toggleOptionFlex: {\r\n flex: 1,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n toggleOptionCheckbox: {\r\n paddingTop: theme.spacing(0.5),\r\n paddingBottom: theme.spacing(0.5)\r\n },\r\n mappingMargin: {\r\n marginBottom: \"3px\"\r\n },\r\n checkBoxParent: {\r\n paddingLeft: theme.spacing(3),\r\n paddingRight: theme.spacing(3)\r\n },\r\n paddingBottom: {\r\n paddingBottom: theme.spacing(3),\r\n display: \"block\"\r\n },\r\n captionPadding: {\r\n paddingBottom: theme.spacing(1),\r\n paddingTop: theme.spacing(0.5),\r\n display: \"block\"\r\n },\r\n paddingBottomAndTop: {\r\n paddingBottom: theme.spacing(3),\r\n paddingTop: theme.spacing(3),\r\n display: \"block\"\r\n },\r\n paddingBottomAndTopMinimal: {\r\n paddingBottom: theme.spacing(1),\r\n paddingTop: theme.spacing(1),\r\n display: \"block\"\r\n },\r\n fileButtonDiv: {\r\n paddingTop: theme.spacing(1),\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n outputFolder: {\r\n paddingBottom: theme.spacing(4)\r\n },\r\n selectDivider: {\r\n margin: theme.spacing(0.5),\r\n opacity: 0.2\r\n },\r\n infoLabel: {\r\n fontWeight: \"bold\",\r\n paddingRight: theme.spacing(0.5)\r\n },\r\n flexPaper: {\r\n flex: 1,\r\n margin: 16,\r\n minWidth: 350\r\n },\r\n }),\r\n);\r\n\r\ninterface LabelProps {\r\n label: ImageLabel;\r\n index: number;\r\n isScrolling: boolean;\r\n style?: object;\r\n labelName: string;\r\n isSceneLabel: boolean;\r\n}\r\n\r\nconst Label = (props: LabelProps) => {\r\n const {label, index, isScrolling, style, labelName, isSceneLabel} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const changeCategoryDialog = useDialog();\r\n\r\n const [getInfo, setGetInfo] = useState(false);\r\n\r\n const selected = label.selected;\r\n const completed = label.completed;\r\n const isTrainingLabel = label instanceof TrainingAreaLabel;\r\n const multipleCategories = ((viewer?.getAllCategories().length) > 1);\r\n\r\n const scoreClass = () => {\r\n let scoreValidity = classes.success;\r\n if (label.score < 0.9) {\r\n scoreValidity = classes.warning;\r\n }\r\n if (label.score < 0.7) {\r\n scoreValidity = classes.error;\r\n }\r\n return scoreValidity;\r\n };\r\n\r\n const getInfoLabel = () => {\r\n setGetInfo(true);\r\n };\r\n\r\n const deleteLabel = (id) => {\r\n viewer?.deleteLabel(id);\r\n };\r\n\r\n const zoomToLabel = (id) => {\r\n viewer?.zoomToLabel(id);\r\n };\r\n\r\n const unHighlight = (id) => {\r\n viewer?.unHighlight(id);\r\n };\r\n\r\n return (\r\n \r\n
\r\n {/** Label number */}\r\n \r\n {`${labelName} #${index + 1} (${label.numPoints})`}\r\n \r\n\r\n {/** Classification score */}\r\n {!isTrainingLabel && (
\r\n \r\n {t('labels.classification-score')}: \r\n \r\n\r\n \r\n {label.score.toFixed(2)}\r\n \r\n
)}\r\n
\r\n\r\n {isScrolling && (\r\n \r\n Loading...\r\n \r\n )}\r\n\r\n {!isScrolling && (\r\n\r\n {/*Classification Score*/}\r\n \r\n\r\n \r\n\r\n {/* Warning on Label */}\r\n \r\n \r\n \r\n\r\n {/* Highlighted Label */}\r\n {\r\n unHighlight(label.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Info on Label */}\r\n getInfoLabel()}\r\n >\r\n \r\n \r\n\r\n {/* Zoom to extent */}\r\n {\r\n zoomToLabel(label.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Switch Labels Category */}\r\n {\r\n changeCategoryDialog.handleOpen();\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Delete Label */}\r\n {\r\n deleteLabel(label.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Label Info */}\r\n \r\n\r\n {/* Change Category Dialog */}\r\n \r\n )}\r\n
\r\n );\r\n};\r\n\r\ninterface CategoryContentProps {\r\n category: LabelCategory;\r\n labelName: string;\r\n index: number;\r\n isSceneLabel?: boolean;\r\n}\r\n\r\nconst CategoryContent = (props: CategoryContentProps) => {\r\n const {category, labelName, index, isSceneLabel=false} = props;\r\n\r\n const classes = useStyles();\r\n const listRef = useRef(null);\r\n\r\n const scrollingDivLength = category.labels.length;\r\n const useScrollingDiv = scrollingDivLength > 5;\r\n const scrollingDivHeight = Math.min(scrollingDivLength*labelHeight, 250);\r\n\r\n useEffect(() => {\r\n if (listRef) {\r\n if (listRef.current){\r\n listRef.current.scrollToItem(index);\r\n }\r\n }\r\n }, [index, listRef]);\r\n\r\n return (\r\n {/* Use normal list for small labels list */}\r\n {!useScrollingDiv && (\r\n \r\n {category.labels.map((label, index) =>\r\n \r\n )}\r\n \r\n )}\r\n\r\n {/* Use scrolling list for large amounts of labels */}\r\n {useScrollingDiv && (\r\n \r\n {({index, isScrolling, style}) => (\r\n \r\n )}\r\n \r\n )}\r\n );\r\n};\r\n\r\ninterface CategoryExpandProps {\r\n expanded: boolean;\r\n setExpanded: React.Dispatch;\r\n}\r\n\r\nconst CategoryExpand = (props: CategoryExpandProps) => {\r\n const {setExpanded, expanded} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n return ( {\r\n event.stopPropagation();\r\n setExpanded(!expanded);\r\n }}\r\n >\r\n {expanded && }\r\n {!expanded && }\r\n );\r\n};\r\n\r\ninterface TrainingAreaProps {\r\n trainingArea: TrainingAreaCategory;\r\n}\r\n\r\nconst TrainingArea = (props: TrainingAreaProps) => {\r\n const {trainingArea} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [expanded, setExpanded] = useState(false);\r\n const [deletePrompt, setDeletePrompt] = useState(false);\r\n\r\n const clearTrainingArea = () => {\r\n // Delete all areas\r\n [...trainingArea.labels].forEach(label => {\r\n viewer?.deleteLabel(label.id);\r\n });\r\n\r\n setDeletePrompt(false);\r\n };\r\n\r\n const addThenExpand = () => {\r\n addLabel();\r\n setExpanded(true);\r\n };\r\n\r\n const addLabel = () => {\r\n viewer?.addTrainingAreaLabel();\r\n };\r\n\r\n const addNewLabelDisabled = viewer?.labelSelected();\r\n const addNewlabelTooltip = t('labels.add-new-training-area');\r\n\r\n return (\r\n \r\n \r\n {/* Header */}\r\n \r\n {/* Expand/collapse areas */}\r\n \r\n\r\n {/* Add new area label */}\r\n {\r\n addThenExpand();\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Delete Training Area */}\r\n {\r\n setDeletePrompt(true);\r\n }}\r\n >\r\n \r\n \r\n\r\n \r\n }\r\n disableTypography={true}\r\n title={\r\n \r\n {t('labels.training-areas')}\r\n \r\n }\r\n subheader={\r\n \r\n {t('labels.total-areas', {\r\n count: trainingArea.labels.length\r\n })}\r\n \r\n }\r\n />\r\n\r\n {/* Expandable content */}\r\n {expanded && ()}\r\n \r\n\r\n setDeletePrompt(false)}\r\n onSubmit={clearTrainingArea}\r\n title={t('labels.clear-training-areas')}\r\n prompt={t('labels.do-you-want-to-remove-all-training-areas')}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n \r\n );\r\n};\r\n\r\ninterface CategoryProps {\r\n category: LabelCategory;\r\n isValidCategory: (name) => boolean;\r\n labelDisabled: boolean;\r\n runTextDetection: (score, spellcheck) => void;\r\n isSceneLabel: boolean;\r\n}\r\n\r\nconst Category = (props: CategoryProps) => {\r\n const {category, isValidCategory, labelDisabled,\r\n runTextDetection, isSceneLabel} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [expanded, setExpanded] = useState(false);\r\n const [editPrompt, setEditPrompt] = useState(false);\r\n const [deletePrompt, setDeletePrompt] = useState(false);\r\n const [sortPrompt, setSortPrompt] = useState(false);\r\n const [textDetectPrompt, setTextDetectPrompt] = useState(false);\r\n const [sorted, setSorted] = useState(false);\r\n\r\n const categoryVisible = category.visible;\r\n const index = viewer?.getIndexInList(category);\r\n const labelsAdded = category.labels.length > 0;\r\n const addNewLabelDisabled = (viewer?.labelSelected() || !categoryVisible);\r\n\r\n const formatName = (name) => {\r\n const maxLength = 22;\r\n\r\n return (name.length > maxLength)\r\n ? name.substr(0, maxLength - 1) + \"...\"\r\n : name;\r\n };\r\n\r\n const addThenExpand = (categoryID) => {\r\n addLabel(categoryID);\r\n setExpanded(true);\r\n };\r\n\r\n const addLabel = (id) => {\r\n viewer?.addLabel(id);\r\n };\r\n\r\n const handleDeleteCategory = () => {\r\n viewer?.deleteCategory(category.id);\r\n setDeletePrompt(false);\r\n };\r\n\r\n const handleEditCategory = (name) => {\r\n if (!isValidCategory(name)) {\r\n return;\r\n }\r\n\r\n viewer?.editCategoryName(category.id, name);\r\n setEditPrompt(false);\r\n };\r\n\r\n const runSort = (scoreValue, sortType) => {\r\n viewer?.sortCategory(category, scoreValue, sortType);\r\n setSorted(true);\r\n };\r\n\r\n const undoSort = () => {\r\n viewer?.undoSort(category);\r\n setSorted(false);\r\n };\r\n\r\n const handleToggleVisibility = (state) => {\r\n viewer?.toggleCategoryVisibility(category.id, state);\r\n };\r\n\r\n useEffect(() => {\r\n if (index >= 0) {\r\n setExpanded(true);\r\n }\r\n }, [index]);\r\n\r\n const addNewlabelTooltip = t('labels.add-new-label', {\r\n type: viewer.currentCategory()\r\n });\r\n\r\n const numLabelsTooltip = t('labels.click-to-undo-sort', {\r\n count: category.numLabelsAll\r\n });\r\n\r\n const color = textToColor(category.name);\r\n\r\n return (\r\n \r\n \r\n {/* Header */}\r\n \r\n {/* Expand/collapse labels */}\r\n \r\n\r\n {/* Class Visibility */}\r\n {(categoryVisible) && {\r\n handleToggleVisibility(false);\r\n }}\r\n >\r\n \r\n }\r\n\r\n {(!categoryVisible && labelsAdded) && {\r\n handleToggleVisibility(true);\r\n }}\r\n >\r\n \r\n }\r\n\r\n {/* Detect Text in Class */}\r\n {\r\n setTextDetectPrompt(true);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Sort by Scores */}\r\n {\r\n setSortPrompt(true);\r\n }}\r\n >\r\n \r\n \r\n\r\n\r\n {/* Edit category name */}\r\n {\r\n setEditPrompt(true);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Add new label */}\r\n {\r\n addThenExpand(category.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Delete category */}\r\n {\r\n setDeletePrompt(true);\r\n }}\r\n >\r\n \r\n \r\n\r\n \r\n }\r\n disableTypography={true}\r\n title={\r\n \r\n {formatName(category.name)}\r\n \r\n }\r\n subheader={\r\n \r\n \r\n {t('labels.total-labels', {\r\n count: category.labels.length\r\n })}\r\n \r\n {(sorted) && undoSort()}\r\n error\r\n />}\r\n \r\n }\r\n />\r\n\r\n {/* Expandable content */}\r\n {expanded && ()}\r\n\r\n \r\n\r\n setEditPrompt(false)}\r\n onSubmit={handleEditCategory}\r\n title={t('labels.edit-class')}\r\n prompt={t('labels.enter-new-class-name')}\r\n placeholder={category.name}\r\n label={t('labels.class-name')}\r\n />\r\n\r\n setDeletePrompt(false)}\r\n onSubmit={handleDeleteCategory}\r\n title={t('labels.delete-class')}\r\n prompt={t('labels.do-you-want-to-delete-this-class', {\r\n name: category.name\r\n })}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n \r\n\r\n \r\n\r\n \r\n );\r\n};\r\n\r\ninterface LabelIntersectDialogProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n forceInitialProgress: () => void;\r\n setTrainClassifyExe: React.Dispatch;\r\n setTrainClassifyProgress: React.Dispatch;\r\n resetExecutableValues: () => void;\r\n checkTrainingData: (data) => boolean;\r\n pointClouds: Asset[];\r\n categories: LabelCategory[];\r\n setProcessType: React.Dispatch;\r\n}\r\n\r\nconst LabelIntersectDialog = (props: LabelIntersectDialogProps) => {\r\n const {open, setOpen, forceInitialProgress, setTrainClassifyExe,\r\n setTrainClassifyProgress, resetExecutableValues,\r\n checkTrainingData, pointClouds, categories, setProcessType} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n const defaultFolder = useSelector(selectDefaultFolder);\r\n\r\n const {addTagCSVs, addPointCloudFiles} = useAssetTools();\r\n\r\n const projectName = useSelector(selectProjectName);\r\n const [outputPath, setOutputPath] = useState(null);\r\n\r\n const LASfiles = pointClouds.filter(x => x.type === AssetType.LAS);\r\n\r\n const minLasVersion = Math.min(...LASfiles.map(pointCloud => {\r\n const header = viewer.getLasFileInfo(pointCloud.id);\r\n return header ? parseFloat(header.attributes.version) : 0;\r\n }));\r\n\r\n const visibleClouds = LASfiles.filter(x => x.visible);\r\n const cloudsAvailable = (visibleClouds.length > 0);\r\n // const mixedData = (LASfiles.length !== pointClouds.length);\r\n const maxNumClasses = (minLasVersion >= 1.4) ? 255 : 31;\r\n const availableLasClasses = viewer?.getAvailableClassifications();\r\n availableLasClasses?.sort(function(a, b) {\r\n return a - b;\r\n });\r\n\r\n const defaults = {\r\n image_sampling_dist: {value: 1, error: false},\r\n intersection_angle: {value: 10, error: false},\r\n min_num_matches: {value: 2, error: false},\r\n position_confidence: {value: \"high\", error: false},\r\n max_distance_from_camera: {value: 60, error: false},\r\n close_label_dist: {value: 1, error: false},\r\n min_camera_distance: {value: 1, error: false},\r\n max_camera_distance: {value: 60, error: false},\r\n max_intersect_distance: {value: 1, error: false},\r\n cluster_distance: {value: 1, error: false},\r\n num_matches_required: {value: 3, error: false},\r\n object_size: {value: 0.5, error: false},\r\n min_label_angle: {value: 1.0, error: false}\r\n };\r\n\r\n // Shared parameters\r\n const [imageSamplingDistance, setImageSamplingDistance] = useState(defaults.image_sampling_dist);\r\n\r\n // Ray intersection parameters\r\n const [minCameraDistance, setMinCameraDistance] = useState(defaults.min_camera_distance);\r\n const [maxCameraDistance, setMaxCameraDistance] = useState(defaults.max_camera_distance);\r\n const [maxIntersectDistance, setMaxIntersectDistance] = useState(defaults.max_intersect_distance);\r\n const [clusterDistance, setClusterDistance] = useState(defaults.cluster_distance);\r\n const [numMatchesRequired, setNumMatchesRequired] = useState(defaults.num_matches_required);\r\n const [minAngle, setMinAngle] = useState(defaults.min_label_angle);\r\n\r\n // Extract Point Cloud shared\r\n const [categoryClasses, setCategoryClasses] = useState(null);\r\n const [overwrite, setOverwrite] = useState(false);\r\n const [extractPoints, setExtractPoints] = useState(false);\r\n const [objSize, setObjSize] = useState(defaults.object_size);\r\n const [collapse1, setCollapse1] = useState(true);\r\n const [collapse2, setCollapse2] = useState(true);\r\n const [ignoreClasses, setIgnoreClasses] = useState(null);\r\n\r\n\r\n const getCategoryClasses = (categories) => {\r\n let categoriesTemp = categories.map((category, index) => {\r\n let name = category.name;\r\n let lasClass = getClassFromAlias(name);\r\n if (lasClass < 0) {\r\n lasClass = 0;\r\n }\r\n\r\n return {\r\n id: nanoid(),\r\n index: index,\r\n primary: name,\r\n secondary: lasClass.toString(),\r\n error: false,\r\n min: 0,\r\n max: maxNumClasses,\r\n step:1,\r\n };\r\n });\r\n setCategoryClasses([...categoriesTemp]);\r\n };\r\n\r\n const getIgnoreClasses = () => {\r\n let ignoreTemp = availableLasClasses?.map((classification, index) => {\r\n const name = getNameFromClass(classification);\r\n return {\r\n id: nanoid(),\r\n classification: classification,\r\n index: index,\r\n name: name,\r\n value: false\r\n };\r\n });\r\n if (ignoreTemp) {\r\n setIgnoreClasses([...ignoreTemp]);\r\n }\r\n };\r\n\r\n const updateCategoryNumbers = (data) => {\r\n let categoriesTemp = [...categoryClasses];\r\n categoriesTemp[data.index].secondary = data.value;\r\n categoriesTemp[data.index].error = data.error;\r\n setCategoryClasses([...categoriesTemp]);\r\n };\r\n\r\n const updateIgnoreClasses = (index, checked) => {\r\n let ignoreTemp = [...ignoreClasses];\r\n ignoreTemp[index].value = checked;\r\n setIgnoreClasses([...ignoreTemp]);\r\n };\r\n\r\n const onDragEnd = ({ destination, source }: DropResult) => {\r\n if (!destination) return;\r\n\r\n let rowsTemp = [...categoryClasses];\r\n const [removed] = rowsTemp.splice(source.index, 1);\r\n rowsTemp.splice(destination.index, 0, removed);\r\n rowsTemp.forEach((row, index) => row.index=index);\r\n\r\n setCategoryClasses([...rowsTemp]);\r\n return;\r\n };\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n runIntersection();\r\n setOpen(false);\r\n };\r\n\r\n const runIntersection = async () => {\r\n const jsonData = viewer?.labelObject();\r\n if (!checkTrainingData(jsonData)) {\r\n return false;\r\n }\r\n\r\n const tempCocoPath = getTemporaryFile(\"3dl\");\r\n const csvEncompassPath = getTemporaryFile('csv');\r\n\r\n\r\n try {\r\n // Write COCO file to temp path\r\n let text = JSON.stringify(jsonData, null, 2);\r\n await fse.writeFile(tempCocoPath, text);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-export-failed\"));\r\n return;\r\n }\r\n\r\n try {\r\n // Export cameras to csv\r\n const cameras = viewer.activeImages();\r\n const rows = viewer.getCameraRowsCSV(cameras);\r\n const content = CSV.stringify(rows);\r\n await fse.writeFile(csvEncompassPath, content);\r\n } catch {\r\n toast.error(t(\"toast.label-image-csv-failed\"));\r\n return;\r\n }\r\n\r\n let exe = new PythonExecutable();\r\n\r\n // Primary parameters\r\n let commands = [];\r\n commands = [\r\n ...commands,\r\n \"-p\", 'label_intersect_v2',\r\n \"--csv_image_file\", csvEncompassPath,\r\n \"--coco_data_file\", tempCocoPath,\r\n \"--output_folder\", outputPath,\r\n \"--project_name\", projectName,\r\n \"--image_sampling_dist\", imageSamplingDistance.value,\r\n \"--min_camera_distance\", minCameraDistance.value,\r\n \"--max_camera_distance\", maxCameraDistance.value,\r\n \"--max_intersect_distance\", maxIntersectDistance.value,\r\n \"--cluster_distance\", clusterDistance.value,\r\n \"--num_matches_required\", numMatchesRequired.value,\r\n \"--min_label_angle\", minAngle.value,\r\n ];\r\n\r\n\r\n if (extractPoints) {\r\n const classesToIgnore = ignoreClasses.filter(ic => ic.value).map(ic => {\r\n return ic.classification;\r\n });\r\n\r\n const categoryClassesNames = categoryClasses.map(category => {\r\n return category.primary;\r\n });\r\n\r\n const categoryClassesNums = categoryClasses.map(category => {\r\n return category.secondary;\r\n });\r\n\r\n commands = [...commands,\r\n \"--max_obj_size\", objSize.value,\r\n \"--find_in_lidar\", visibleClouds.map(cloud=>cloud.path),\r\n \"--ignore_classes\", classesToIgnore,\r\n \"--overwrite_las\", (overwrite) ? \"True\" : \"False\",\r\n \"--label_class_names\", categoryClassesNames,\r\n \"--label_class_nums\", categoryClassesNums,\r\n \"--units\", LocalScene.dataProjectionUnits];\r\n }\r\n\r\n forceInitialProgress();\r\n setTrainClassifyExe(exe);\r\n\r\n toast.success(t(\"toast.labels-position-submit\"));\r\n\r\n let successEstimate = false;\r\n let successLabelInPC = false;\r\n let successCombine = false;\r\n let successConvert = false;\r\n let convertAttempted = false;\r\n let successLasWritten = false;\r\n let lasOutputPath;\r\n let csvOutputPaths=[];\r\n let classifiedPaths=[];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: async jsonData => {\r\n if (!jsonData) {\r\n return;\r\n }\r\n\r\n if (jsonData.position_estimate_progress) {\r\n setTrainClassifyProgress(jsonData.position_estimate_progress);\r\n setProcessType(t(\"labels.label-process-export\"));\r\n } else if (jsonData.positions_found) {\r\n successEstimate = true;\r\n toast.success(t(\"toast.labels-position-found\", {\r\n count: jsonData.positions_found\r\n }));\r\n } else if (jsonData.csvs_written) {\r\n csvOutputPaths = jsonData.csvs_written;\r\n await addTagCSVs(csvOutputPaths, defaultFolder.id);\r\n\r\n } else if (jsonData[\"Locate Points in Labels\"]) {\r\n setTrainClassifyProgress(jsonData[\"Locate Points in Labels\"]);\r\n setProcessType(t(\"labels.label-process-extract-points\"));\r\n } else if (jsonData.labels_found_pointcloud) {\r\n successLabelInPC = true;\r\n toast.success(t(\"toast.labels-points-found\", {\r\n count: jsonData.labels_found_pointcloud\r\n }));\r\n } else if (jsonData.combine_las) {\r\n setTrainClassifyProgress(jsonData.combine_las);\r\n setProcessType(t(\"labels.label-process-combine_pointcloud\"));\r\n } else if (jsonData.combine_las_complete) {\r\n successCombine = true;\r\n toast.success(t(\"toast.labels-points-found\", {\r\n count: jsonData.combine_las_complete\r\n }));\r\n } else if (jsonData.las_to_3dp) {\r\n convertAttempted = true;\r\n setTrainClassifyProgress(jsonData.las_to_3dp);\r\n setProcessType(t(\"labels.label-process-convert-pointcloud\"));\r\n } else if (jsonData.las_to_3dp_success) {\r\n successConvert = true;\r\n toast.success(t(\"toast.labels-pointcloud-converted\"));\r\n } else if (jsonData.writing_las) {\r\n setTrainClassifyProgress(jsonData.writing_las);\r\n setProcessType(t(\"labels.label-process-writing-las\"));\r\n } else if (jsonData.las_written) {\r\n successLasWritten = true;\r\n lasOutputPath = jsonData.las_written;\r\n } else if (jsonData.las_classified_written) {\r\n toast.success(t(\"toast.las-classified-save\", {\r\n path: jsonData.las_classified_written\r\n }));\r\n classifiedPaths.push(jsonData.las_classified_written);\r\n }\r\n },\r\n onClose: async () => {\r\n if (successEstimate) {\r\n toast.success(t(\"toast.labels-position-save\", {\r\n path: outputPath\r\n }));\r\n }\r\n if (extractPoints) {\r\n if (!successCombine && (visibleClouds.length > 1)) {\r\n toast.error(t(\"toast.labels-combine-failed\"));\r\n }\r\n else if (!successConvert && convertAttempted) {\r\n toast.error(t(\"toast.labels-convert-failed\"));\r\n }\r\n else if (!successLabelInPC) {\r\n toast.error(t(\"toast.labels-find-points-failed\"));\r\n }\r\n else if (!successLasWritten) {\r\n toast.error(t(\"toast.labels-write-failed\"));\r\n }\r\n else {\r\n toast.success(t(\"toast.labels-las-written-save\", {\r\n path: lasOutputPath\r\n }));\r\n await addPointCloudFiles([lasOutputPath], defaultFolder.id);\r\n if (overwrite && (visibleClouds.length === 1)){\r\n dispatch(deleteAsset(visibleClouds[0].id));\r\n }\r\n }\r\n } else if (extractPoints) {\r\n await addPointCloudFiles(classifiedPaths, defaultFolder.id);\r\n if (overwrite && (visibleClouds.length === 1)){\r\n dispatch(deleteAsset(visibleClouds[0].id));\r\n }\r\n toast.success(t(\"toast.las-classified-success\", {\r\n path: outputPath\r\n }));\r\n }\r\n resetExecutableValues();\r\n }\r\n });\r\n };\r\n\r\n const resetDefaultValues = () => {\r\n // Shared parameters\r\n setImageSamplingDistance(defaults.image_sampling_dist);\r\n setExtractPoints(false);\r\n\r\n // Ray intersection parameters\r\n setMinCameraDistance(defaults.min_camera_distance);\r\n setMaxCameraDistance(defaults.max_camera_distance);\r\n setMaxIntersectDistance(defaults.max_intersect_distance);\r\n setClusterDistance(defaults.cluster_distance);\r\n setNumMatchesRequired(defaults.num_matches_required);\r\n setMinAngle(defaults.min_label_angle);\r\n\r\n // Point Extraction general parameters\r\n setOverwrite(false);\r\n\r\n // Point Extraction & Ray Intersection Parameters\r\n setObjSize(defaults.object_size);\r\n };\r\n\r\n useEffect(() => {\r\n getCategoryClasses(categories);\r\n getIgnoreClasses();\r\n if (open) {\r\n return;\r\n }\r\n resetDefaultValues();\r\n setOutputPath(null);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n resetDefaultValues();\r\n }, [open]);\r\n\r\n const folderSelected = outputPath !== null;\r\n\r\n let canSubmit = folderSelected\r\n && !imageSamplingDistance.error\r\n && !minCameraDistance.error\r\n && !maxCameraDistance.error\r\n && !maxIntersectDistance.error\r\n && !clusterDistance.error\r\n && !numMatchesRequired.error;\r\n\r\n return (\r\n \r\n {/* Label Analysis Dialog */}\r\n \r\n {t('labels.label-analysis')}\r\n \r\n \r\n {/* Output folder */}\r\n \r\n \r\n \r\n\r\n {(cloudsAvailable) && (\r\n \r\n )}\r\n\r\n \r\n\r\n \r\n \r\n \r\n {t('labels.position-parameters')}\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n\r\n {/* Function parameters for V2 of function */}\r\n {(collapse1) && (\r\n\r\n {/* Intersect Distance */}\r\n \r\n \r\n \r\n\r\n {/* Number of matches required */}\r\n \r\n \r\n \r\n\r\n {/* Min camera distance */}\r\n \r\n \r\n \r\n\r\n {/* Max camera distance */}\r\n \r\n \r\n \r\n\r\n {/* Image sampling distance */}\r\n \r\n \r\n \r\n\r\n {/* Clustering distance */}\r\n \r\n \r\n \r\n\r\n {/* Min Angle Threshold */}\r\n \r\n \r\n \r\n \r\n )}\r\n\r\n {(extractPoints) && (\r\n \r\n \r\n {t('labels.point-extraction-parameters')}\r\n \r\n \r\n \r\n \r\n \r\n \r\n {(collapse2) && (\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n {/* Object Size */}\r\n {(extractPoints) && (\r\n \r\n )}\r\n {/* Overwrite Las */}\r\n \r\n \r\n \r\n \r\n {(extractPoints) && ()}\r\n {(extractPoints) && (\r\n {ignoreClasses.map((ignoreClass, index) => (\r\n \r\n \r\n {ignoreClass.name}\r\n \r\n {\r\n updateIgnoreClasses(index, event.target.checked);\r\n }}\r\n />\r\n \r\n {`${ignoreClass.classification}`}\r\n \r\n \r\n ))}\r\n )}\r\n\r\n\r\n )}\r\n )}\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst ClassifyPointsDialog = (props: LabelIntersectDialogProps) => {\r\n const {open, setOpen, forceInitialProgress, setTrainClassifyExe,\r\n setTrainClassifyProgress, resetExecutableValues,\r\n checkTrainingData, pointClouds, categories, setProcessType} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const dispatch = useDispatch();\r\n const defaultFolder = useSelector(selectDefaultFolder);\r\n const {addPointCloudFiles} = useAssetTools();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n\r\n const LASfiles = pointClouds.filter(x => x.type === AssetType.LAS);\r\n\r\n const minLasVersion = Math.min(...LASfiles.map(pointCloud => {\r\n const header = viewer.getLasFileInfo(pointCloud.id);\r\n return header ? parseFloat(header.attributes.version) : 0;\r\n }));\r\n\r\n const visibleClouds = LASfiles.filter(x => x.visible);\r\n const useableClouds = visibleClouds.length > 0;\r\n const maxNumClasses = (minLasVersion >= 1.4) ? 255 : 31;\r\n const availableLasClasses = viewer?.getAvailableClassifications();\r\n availableLasClasses?.sort(function(a, b) {\r\n return a - b;\r\n });\r\n\r\n const defaults = {\r\n max_distance: {value: 60, error: false},\r\n min_cameras: {value: 1, error: false},\r\n };\r\n\r\n // Classify Points from Label Parameters\r\n const [categoryClasses, setCategoryClasses] = useState(null);\r\n const [overwrite, setOverwrite] = useState(false);\r\n const [ignoreClasses, setIgnoreClasses] = useState(null);\r\n const [weightByDist, setWeightByDist] = useState(true);\r\n const [ignoreHidden, setIgnoreHidden] = useState(true);\r\n const [maxDist, setMaxDist] = useState(defaults.max_distance);\r\n const [minCameras, setMinCameras] = useState(defaults.min_cameras);\r\n\r\n\r\n const getCategoryClasses = (categories) => {\r\n let categoriesTemp = categories.map((category, index) => {\r\n let name = category.name;\r\n let lasClass = getClassFromAlias(name);\r\n if (lasClass < 0) {\r\n lasClass = 0;\r\n }\r\n\r\n return {\r\n id: nanoid(),\r\n index: index,\r\n primary: name,\r\n secondary: lasClass.toString(),\r\n error: false,\r\n min: 0,\r\n max: maxNumClasses,\r\n step:1,\r\n };\r\n });\r\n setCategoryClasses([...categoriesTemp]);\r\n };\r\n\r\n const getIgnoreClasses = () => {\r\n let ignoreTemp = availableLasClasses?.map((classification, index) => {\r\n const name = getNameFromClass(classification);\r\n return {\r\n id: nanoid(),\r\n classification: classification,\r\n index: index,\r\n name: name,\r\n value: false\r\n };\r\n });\r\n if (ignoreTemp) {\r\n setIgnoreClasses([...ignoreTemp]);\r\n }\r\n };\r\n\r\n const updateCategoryNumbers = (data) => {\r\n let categoriesTemp = [...categoryClasses];\r\n categoriesTemp[data.index].secondary = data.value;\r\n categoriesTemp[data.index].error = data.error;\r\n setCategoryClasses([...categoriesTemp]);\r\n };\r\n\r\n const updateIgnoreClasses = (index, checked) => {\r\n let ignoreTemp = [...ignoreClasses];\r\n ignoreTemp[index].value = checked;\r\n setIgnoreClasses([...ignoreTemp]);\r\n };\r\n\r\n const onDragEnd = ({ destination, source }: DropResult) => {\r\n if (!destination) return;\r\n\r\n let rowsTemp = [...categoryClasses];\r\n const [removed] = rowsTemp.splice(source.index, 1);\r\n rowsTemp.splice(destination.index, 0, removed);\r\n rowsTemp.forEach((row, index) => row.index=index);\r\n\r\n setCategoryClasses([...rowsTemp]);\r\n return;\r\n };\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n runClassifyFromLabel();\r\n setOpen(false);\r\n };\r\n\r\n const runClassifyFromLabel = async () => {\r\n const jsonData = viewer?.labelObject();\r\n if (!checkTrainingData(jsonData)) {\r\n return false;\r\n }\r\n\r\n const tempCocoPath = getTemporaryFile(\"3dl\");\r\n const csvEncompassPath = getTemporaryFile('csv');\r\n\r\n\r\n try {\r\n // Write COCO file to temp path\r\n let text = JSON.stringify(jsonData, null, 2);\r\n await fse.writeFile(tempCocoPath, text);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-export-failed\"));\r\n return;\r\n }\r\n\r\n try {\r\n // Export cameras to csv\r\n const cameras = viewer.activeImages();\r\n const rows = viewer.getCameraRowsCSV(cameras);\r\n const content = CSV.stringify(rows);\r\n await fse.writeFile(csvEncompassPath, content);\r\n } catch {\r\n toast.error(t(\"toast.label-image-csv-failed\"));\r\n return;\r\n }\r\n\r\n let exe = new PythonExecutable();\r\n\r\n const classesToIgnore = ignoreClasses.filter(ic => ic.value).map(ic => {\r\n return ic.classification;\r\n });\r\n\r\n const categoryClassesNames = categoryClasses.map(category => {\r\n return category.primary;\r\n });\r\n\r\n const categoryClassesNums = categoryClasses.map(category => {\r\n return category.secondary;\r\n });\r\n\r\n let commands = [\r\n \"-p\", 'classify_from_panoramic',\r\n \"--input_paths\", visibleClouds.map(cloud=>cloud.path),\r\n \"--output_path\", outputPath,\r\n \"--csv_path\", csvEncompassPath,\r\n \"--label_file\", tempCocoPath,\r\n \"weight_by_distance\", (weightByDist) ? \"True\" : \"False\",\r\n \"--ignore_classes\", classesToIgnore,\r\n \"--ignore_hidden_points\", (ignoreHidden) ? \"True\" : \"False\",\r\n \"--overwrite_las\", (overwrite) ? \"True\" : \"False\",\r\n \"--label_class_names\", categoryClassesNames,\r\n \"--label_class_nums\", categoryClassesNums,\r\n \"--max_distance\", maxDist.value,\r\n \"--min_cameras\", minCameras.value,\r\n \"--units\", LocalScene.dataProjectionUnits\r\n ];\r\n\r\n forceInitialProgress();\r\n setTrainClassifyExe(exe);\r\n\r\n toast.success(t(\"toast.labels-position-submit\"));\r\n\r\n let classifiedPaths=[];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: async jsonData => {\r\n if (!jsonData) {\r\n return;\r\n }\r\n if (jsonData[\"Create Masks\"]) {\r\n let imagePercent = jsonData[\"Create Masks\"];\r\n setTrainClassifyProgress(imagePercent);\r\n setProcessType(t(\"labels.label-process-analyze-imagery\"));\r\n } else if (jsonData[\"Classify Pointcloud\"]) {\r\n let pointPercent = jsonData[\"Classify Pointcloud\"];\r\n setTrainClassifyProgress(pointPercent);\r\n setProcessType(t(\"labels.label-process-classify-pointcloud\"));\r\n } else if (jsonData.las_classified_written) {\r\n toast.success(t(\"toast.las-classified-save\", {\r\n path: jsonData.las_classified_written\r\n }));\r\n classifiedPaths.push(jsonData.las_classified_written);\r\n } else if (jsonData.las_to_3dp) {\r\n setTrainClassifyProgress(jsonData.las_to_3dp);\r\n setProcessType(t(\"labels.label-process-convert-pointcloud\"));\r\n }\r\n },\r\n onClose: async () => {\r\n await addPointCloudFiles(classifiedPaths, defaultFolder.id);\r\n if (overwrite && (visibleClouds.length === 1)){\r\n dispatch(deleteAsset(visibleClouds[0].id));\r\n }\r\n toast.success(t(\"toast.las-classified-success\", {\r\n path: outputPath\r\n }));\r\n resetExecutableValues();\r\n }\r\n });\r\n };\r\n\r\n const resetDefaultValues = () => {\r\n setOverwrite(false);\r\n setWeightByDist(true);\r\n setIgnoreHidden(true);\r\n setMaxDist(defaults.max_distance);\r\n setMinCameras(defaults.min_cameras);\r\n };\r\n\r\n useEffect(() => {\r\n getCategoryClasses(categories);\r\n getIgnoreClasses();\r\n if (open) {\r\n return;\r\n }\r\n resetDefaultValues();\r\n setOutputPath(null);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n resetDefaultValues();\r\n }, [open]);\r\n\r\n const folderSelected = outputPath !== null;\r\n\r\n let canSubmit = folderSelected\r\n && !maxDist.error\r\n && !minCameras.error;\r\n\r\n return (\r\n \r\n {/* Classify Points from Pano Dialog */}\r\n \r\n {t('labels.label-analysis')}\r\n \r\n \r\n {/* Output folder */}\r\n \r\n \r\n \r\n {/* Overwrite Las */}\r\n \r\n \r\n \r\n {/* Weight by Dist */}\r\n \r\n \r\n \r\n {/* Ignore Hidden Points */}\r\n \r\n \r\n \r\n {/* Min Cameras */}\r\n \r\n \r\n \r\n {/* Max distance */}\r\n \r\n \r\n \r\n \r\n\r\n \r\n {/* Drag-drop class section */}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n \r\n {(useableClouds && open) && \r\n {ignoreClasses?.map((ignoreClass, index) => (\r\n \r\n \r\n {ignoreClass.name}\r\n \r\n {\r\n updateIgnoreClasses(index, event.target.checked);\r\n }}\r\n />\r\n \r\n {`${ignoreClass.classification}`}\r\n \r\n \r\n ))}\r\n }\r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface ImportDialogProps {\r\n importData: any;\r\n setImportData: React.Dispatch;\r\n isOrthoLabel: boolean;\r\n categoryList: LabelCategory[];\r\n setLabelLoadProgress: React.Dispatch;\r\n}\r\n\r\nconst ImportDialog = (props: ImportDialogProps) => {\r\n const {importData, setImportData, isOrthoLabel,\r\n categoryList, setLabelLoadProgress} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n const {viewer} = useViewer();\r\n const theme = useTheme();\r\n\r\n const tableState = useTableState();\r\n\r\n const [disabled, setDisabled] = useState(false);\r\n const [importCategory, setImportCategory] = useState({});\r\n const [overwrite, setOverwrite] = useState(true);\r\n const [importLarge, setImportLarge] = useState(false);\r\n const [importPoints, setImportPoints] = useState(true);\r\n const [importLines, setImportLines] = useState(true);\r\n const [checkOverlap, setCheckOverlap] = useState(false);\r\n\r\n const [lineBuffer, setLineBuffer] = useState(\"0.5\"); // TODO: pull from global setting later?\r\n const [pointBuffer, setPointBuffer] = useState(\"0.5\"); // TODO: pull from global setting later?\r\n\r\n const open = !!importData;\r\n\r\n const categories = importData\r\n ? importData.categories as any[]\r\n : [];\r\n\r\n let annotations = importData\r\n ? importData.annotations as any[]\r\n : [];\r\n\r\n const hasLines = annotations.filter(x => x.is_linestring).length > 0;\r\n const hasPoints = annotations.filter(x => x.is_point).length > 0;\r\n\r\n let hasLargeClasses = false;\r\n categories.forEach(category => {\r\n let numGeometry = annotations\r\n .filter(x => x.category_id === category.id)\r\n .length;\r\n if (numGeometry > geometryLimit) {\r\n hasLargeClasses = true;\r\n }\r\n });\r\n\r\n const columns = [\r\n {\r\n id: 'name',\r\n label: t('labels.class-name')\r\n },\r\n {\r\n id: 'count',\r\n label: t('labels.geometry-count'),\r\n numeric: true\r\n },\r\n {\r\n id: 'category',\r\n label: t('labels.imported-class-name')\r\n },\r\n ];\r\n\r\n const categoryNames = Array.from(new Set([\r\n ...categoryList.map(x => x.name),\r\n ...categories.map(x => x.name)\r\n ])).sort((a, b) => a.localeCompare(b));\r\n\r\n const filterAnnotationTypes = (data) => {\r\n return [...data].filter(x => {\r\n if (!importPoints && x.is_point) {\r\n return false;\r\n } else if (!importLines && x.is_linestring) {\r\n return false;\r\n }\r\n\r\n return true;\r\n });\r\n };\r\n\r\n const validBufferSize = (buffer) => {\r\n let bufferSize = parseFloat(buffer);\r\n let minIterations = 0.01;\r\n let maxIterations = 10;\r\n\r\n let validNumber = (bufferSize >= minIterations)\r\n && (bufferSize <= maxIterations);\r\n\r\n if (!validNumber) {\r\n toast.error(t(\"toast.labels-buffer-size\", {\r\n minIterations,\r\n maxIterations\r\n }));\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const handleClose = () => {\r\n setImportData(null);\r\n };\r\n\r\n const handleImport = async () => {\r\n if ((hasPoints && importPoints) && !validBufferSize(pointBuffer)) {\r\n return;\r\n }\r\n\r\n if ((hasLines && importLines) && !validBufferSize(lineBuffer)) {\r\n return;\r\n }\r\n\r\n const labelData = {\r\n ...importData,\r\n annotations: filterAnnotationTypes(importData.annotations)\r\n };\r\n\r\n const importCategories = [];\r\n\r\n labelData.categories.forEach((category, index) => {\r\n let newCategoryName = getMappedCategory(category.name);\r\n\r\n let numGeometry = labelData.annotations\r\n .filter(x => x.category_id === category.id)\r\n .length;\r\n\r\n if (numGeometry === 0) {\r\n return;\r\n }\r\n\r\n let ignoreLayer = (newCategoryName === LabelImportType.Ignore)\r\n || (importLarge ? false : numGeometry > geometryLimit);\r\n\r\n if (ignoreLayer) {\r\n // Filter our data for this category\r\n labelData.annotations = labelData.annotations\r\n .filter(x => x.category_id !== category.id);\r\n\r\n return;\r\n }\r\n\r\n importCategories.push({\r\n ...category,\r\n name: newCategoryName\r\n });\r\n });\r\n\r\n // Apply linestring / point buffer\r\n labelData.annotations.forEach((anno, index) => {\r\n if (anno.is_linestring) {\r\n labelData.annotations[index].buffer_size = lineBuffer;\r\n } else if (anno.is_point) {\r\n labelData.annotations[index].buffer_size = pointBuffer;\r\n }\r\n });\r\n\r\n // Replace categories with remapped version\r\n labelData.categories = importCategories;\r\n\r\n handleClose();\r\n\r\n // Nothing left, exit early\r\n if (labelData.categories.length === 0) {\r\n toast.warning(t(\"toast.labels-not-available\"));\r\n } else {\r\n await viewer?.loadImageLabelData(\r\n labelData,\r\n setLabelLoadProgress,\r\n overwrite,\r\n checkOverlap\r\n );\r\n\r\n toast.success(t(\"toast.labels-load-success\"));\r\n }\r\n };\r\n\r\n const getMappedCategory = (key) => {\r\n return importCategory[key]\r\n ? importCategory[key]\r\n : key;\r\n };\r\n\r\n const createSelect = (key, disabled) => {\r\n return (\r\n {\r\n const updated = {...importCategory};\r\n updated[key] = event.target.value;\r\n setImportCategory(updated);\r\n }}\r\n >\r\n {getLayerMenuItems()}\r\n \r\n );\r\n };\r\n\r\n const getLayerMenuItems = () => {\r\n const menuIgnore = (\r\n \r\n {t('labels.ignore-layer')}\r\n \r\n );\r\n\r\n const menuDivider = (\r\n
\r\n );\r\n\r\n return [\r\n menuIgnore,\r\n menuDivider,\r\n ...categoryNames.map(name => (\r\n \r\n {name}\r\n \r\n ))\r\n ];\r\n };\r\n\r\n const onMenuClick = (event) => {\r\n const value = event.target.value;\r\n const updated = {...importCategory};\r\n categories.forEach(data => {\r\n if (value === LabelImportType.Default) {\r\n delete updated[data.name];\r\n } else {\r\n updated[data.name] = value;\r\n }\r\n });\r\n\r\n setImportCategory(updated);\r\n };\r\n\r\n const getRows = () => {\r\n const filtered = categories.filter(category => {\r\n let numGeometry = annotations\r\n .filter(x => x.category_id === category.id)\r\n .length;\r\n return numGeometry > 0;\r\n });\r\n\r\n return filtered.map((category, index) => {\r\n let numGeometry = annotations\r\n .filter(x => x.category_id === category.id)\r\n .length;\r\n\r\n let disabled = !importLarge && (numGeometry > geometryLimit);\r\n\r\n return {\r\n id: `ImportLayerTableRow_${index}`,\r\n name: category.name as string,\r\n count: numGeometry,\r\n category: createSelect(category.name, disabled),\r\n disabled\r\n };\r\n });\r\n };\r\n\r\n const handlePointBufferChange = (event) => {\r\n setPointBuffer(event.target.value);\r\n };\r\n\r\n const handleLineBufferChange = (event) => {\r\n setLineBuffer(event.target.value);\r\n };\r\n\r\n useEffect(() => {\r\n if (!importData) {\r\n setImportCategory({});\r\n setOverwrite(true);\r\n setCheckOverlap(false);\r\n setImportLarge(false);\r\n setImportPoints(true);\r\n setImportLines(true);\r\n }\r\n }, [importData]);\r\n\r\n useEffect(() => {\r\n let valid = true;\r\n\r\n if (importLines && lineBuffer === \"\") {\r\n valid = false;\r\n }\r\n\r\n if (importPoints && pointBuffer === \"\") {\r\n valid = false;\r\n }\r\n\r\n setDisabled(!valid);\r\n }, [importLines, importPoints, pointBuffer, lineBuffer]);\r\n\r\n annotations = filterAnnotationTypes(annotations);\r\n\r\n const rows = getRows();\r\n\r\n return (\r\n \r\n {t('labels.import-labels')}\r\n\r\n \r\n\r\n {/* Setting layer default */}\r\n \r\n
\r\n {t('labels.apply-class-mapping')}\r\n\r\n \r\n {t('labels.select-option')}\r\n {t('labels.default-mapping')}\r\n {getLayerMenuItems()}\r\n \r\n
\r\n
\r\n\r\n {/* Overwrite existing labels */}\r\n \r\n
\r\n {t('labels.overwrite-existing-labels')}\r\n\r\n {\r\n setOverwrite(event.target.checked);\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Ignore outside image bounds */}\r\n {isOrthoLabel && (\r\n
\r\n {t('labels.discard-non-overlapping-labels')}\r\n\r\n \r\n {\r\n setCheckOverlap(event.target.checked);\r\n }}\r\n />\r\n \r\n
\r\n
)}\r\n\r\n {/* Import large classes */}\r\n {hasLargeClasses && (\r\n
\r\n \r\n {t('labels.import-large-classes')}\r\n \r\n\r\n \r\n {\r\n setImportLarge(event.target.checked);\r\n }}\r\n />\r\n \r\n
\r\n
)}\r\n\r\n {/* Import polylines */}\r\n \r\n {hasLines && (
\r\n {t('labels.import-linestrings')}\r\n\r\n {\r\n setImportLines(event.target.checked);\r\n }}\r\n />\r\n
)}\r\n {(hasLines && importLines) && (\r\n {t('labels.a-buffer-will-be-applied-to-convert-to-a-polygon')}\r\n )}\r\n
\r\n\r\n \r\n {(hasLines && importLines) && (
\r\n \r\n
)}\r\n
\r\n\r\n {/* Import points */}\r\n \r\n {hasPoints && (
\r\n {t('labels.import-points')}\r\n\r\n {\r\n setImportPoints(event.target.checked);\r\n }}\r\n />\r\n
)}\r\n {(hasPoints && importPoints) && (\r\n {t('labels.a-buffer-will-be-applied-to-convert-to-a-polygon')}\r\n )}\r\n
\r\n\r\n \r\n {(hasPoints && importPoints) && (
\r\n \r\n
)}\r\n
\r\n\r\n
\r\n\r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface ClassifyFromAerialProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n setProgress: React.Dispatch;\r\n categories: LabelCategory[];\r\n pointClouds: Asset[];\r\n}\r\n\r\nconst ClassifyFromAerial = (props: ClassifyFromAerialProps) => {\r\n const {categories, open, setOpen, setProgress,\r\n pointClouds} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [rows, setRows] = useState([]);\r\n const [sorted, setSorted] = useState(false);\r\n const [sortedAlpha, setSortedAlpha] = useState(false);\r\n const [sortByNum, setSortByNum] = useState(false);\r\n const [overwriteFile, setOverwriteFile] = useState(false);\r\n const [preserveGround, setPreserveGround] = useState(false);\r\n const [newLasPath, setNewLasPath] = useState(null);\r\n\r\n const LASfiles = pointClouds.filter(x => x.type === AssetType.LAS);\r\n\r\n const minLasVersion = Math.min(...LASfiles.map(pointCloud => {\r\n const header = viewer.getLasFileInfo(pointCloud.id);\r\n return header ? parseFloat(header.attributes.version) : 0;\r\n }));\r\n\r\n const visibleClouds = LASfiles.filter(x => x.visible);\r\n const mixedData = (LASfiles.length !== pointClouds.length);\r\n const maxNumClasses = (minLasVersion >= 1.4) ? 255 : 31;\r\n\r\n const canSubmit = (visibleClouds.length > 0)\r\n && (minLasVersion > 0)\r\n && ((newLasPath !== null) || (overwriteFile))\r\n && rows.filter(x => x.error).length === 0;\r\n\r\n const checkNamesForClass = (name) => {\r\n let classNum = getClassFromAlias(name);\r\n if (classNum < 0) {\r\n classNum = 0;\r\n }\r\n return classNum;\r\n };\r\n\r\n const getRows = (categories) => {\r\n let rowsTemp = categories.map((category, index) => {\r\n let name = category.name;\r\n let lasClass = checkNamesForClass(name);\r\n\r\n return {\r\n id: `AerialClassifyTableRow_${index}`,\r\n index: index,\r\n primary: name,\r\n secondary: lasClass,\r\n error: false,\r\n min: 0,\r\n max: maxNumClasses,\r\n step:1,\r\n };\r\n });\r\n\r\n setRows([...rowsTemp]);\r\n };\r\n\r\n const updateClassNumbers = (data) => {\r\n let rowsTemp = [...rows];\r\n rowsTemp[data.index].secondary = data.value;\r\n rowsTemp[data.index].error = data.error;\r\n setRows([...rowsTemp]);\r\n };\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n setProgress(0);\r\n setOverwriteFile(false);\r\n setPreserveGround(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n setOpen(false);\r\n classifyPointclouds();\r\n };\r\n\r\n const classifyPointclouds = () => {\r\n const applicationOrder = rows.map(row => row.primary);\r\n const lasClasses = rows.map(row => parseInt(row.secondary));\r\n const inputPaths = visibleClouds.map(x => x.path);\r\n const overwriteGround = !preserveGround;\r\n const outputPath = newLasPath;\r\n\r\n const polygonData = viewer.getOrthoLabelPolygons();\r\n const jsonData = applicationOrder.map((name, index) => {\r\n return {\r\n name,\r\n class: lasClasses[index],\r\n segments: polygonData[name]\r\n };\r\n });\r\n\r\n const text = JSON.stringify(jsonData, null, 4);\r\n const tempTextPath = getTemporaryFile(\"txt\");\r\n\r\n try {\r\n fs.writeFileSync(tempTextPath, text);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-aerial-error\"));\r\n return;\r\n }\r\n\r\n toast.success(t('toast.aerial_classification_submitted'));\r\n\r\n let newCloudPaths = null;\r\n let processTimeout = 500;\r\n\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", \"classify_from_aerial\",\r\n \"--input_paths\", inputPaths,\r\n \"--input_json\", tempTextPath,\r\n \"--overwrite_ground\", overwriteGround,\r\n \"--overwrite_file\", overwriteFile\r\n ];\r\n\r\n if (!overwriteFile) {\r\n commands.push(\"--output_folder\");\r\n commands.push(outputPath);\r\n }\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (jsonData.label_bounds_error) {\r\n toast.error(t(\"toast.labels-aerial-error-bounds\"));\r\n } else if (jsonData.progress) {\r\n setProgress(jsonData.progress);\r\n } else if (jsonData.overwrite_failure) {\r\n toast.error(t(\"toast.labels-aerial-error-overwrite\"));\r\n } else if (jsonData.output_paths) {\r\n newCloudPaths = jsonData.output_paths;\r\n }\r\n },\r\n onClose: async () => {\r\n if (!newCloudPaths) {\r\n toast.warning(t(\"toast.labels-classify-incomplete\"));\r\n handleClose();\r\n return;\r\n }\r\n\r\n await asyncTimeout(processTimeout);\r\n toast.success(t(\"toast.labels-import-modified\"));\r\n\r\n visibleClouds.forEach((asset, index) => {\r\n const assetPath = newCloudPaths[index];\r\n\r\n // Add new pointcloud\r\n dispatch(addAsset({\r\n folderID: asset.folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: asset.type\r\n }));\r\n\r\n // Remove old pointcloud\r\n dispatch(deleteAsset(asset.id));\r\n });\r\n\r\n handleClose();\r\n }\r\n });\r\n };\r\n\r\n const sortRowsByClassNum = (reverseSort) => {\r\n let rowsTemp = [...rows];\r\n if (rows.length === 0) {\r\n return;\r\n }\r\n\r\n if (!reverseSort){\r\n rowsTemp.sort((a,b) => a.secondary - b.secondary);\r\n }\r\n else {\r\n rowsTemp.sort((a,b) => b.secondary - a.secondary);\r\n }\r\n\r\n rowsTemp.forEach((row, index) => row.index=index);\r\n setRows([...rowsTemp]);\r\n setSortByNum(!reverseSort);\r\n setSorted(true);\r\n };\r\n\r\n const sortRowsAlphabetically = () => {\r\n let rowsTemp = [...rows];\r\n if (rows.length === 0) {\r\n return;\r\n }\r\n\r\n rowsTemp.sort((a, b) => a.primary.localeCompare(b.primary));\r\n rowsTemp.forEach((row, index) => row.index=index);\r\n setSortedAlpha(true);\r\n setRows([...rowsTemp]);\r\n };\r\n\r\n const sortReset = () => {\r\n let rowsTemp = [...rows];\r\n if (rows.length === 0) {\r\n return;\r\n }\r\n\r\n rowsTemp.sort((a,b) => parseInt(a.id) - parseInt(b.id));\r\n rowsTemp.forEach((row, index) => row.index=index);\r\n setSorted(false);\r\n setSortedAlpha(false);\r\n setRows([...rowsTemp]);\r\n };\r\n\r\n const onDragEnd = ({ destination, source }: DropResult) => {\r\n if (!destination) return;\r\n\r\n let rowsTemp = [...rows];\r\n const [removed] = rowsTemp.splice(source.index, 1);\r\n rowsTemp.splice(destination.index, 0, removed);\r\n rowsTemp.forEach((row, index) => row.index=index);\r\n\r\n setRows([...rowsTemp]);\r\n return;\r\n };\r\n\r\n useEffect(() => {\r\n getRows(categories);\r\n }, [open]);\r\n\r\n const sortButtonTitle = sorted\r\n ? t('labels.reverse-sort-order')\r\n : t('labels.sort-by-las-classification');\r\n\r\n return (\r\n \r\n {t('labels.classify-point-cloud-from-aerial-image')}\r\n \r\n \r\n {t('labels.classes-lower-in-the-list-will-be-applied')}\r\n \r\n\r\n
\r\n {\r\n sortRowsByClassNum(sortByNum);\r\n }}\r\n >\r\n \r\n \r\n\r\n {\r\n sortRowsAlphabetically();\r\n }}\r\n >\r\n \r\n \r\n\r\n\r\n {(sorted || sortedAlpha) && {\r\n sortReset();\r\n }}\r\n >\r\n \r\n }\r\n
\r\n\r\n \r\n \r\n \r\n\r\n \r\n\r\n {/* Preserve ground classification */}\r\n \r\n \r\n \r\n\r\n {/* Overwrite point clouds */}\r\n \r\n \r\n \r\n\r\n {/* Output folder */}\r\n {!overwriteFile && \r\n \r\n }\r\n\r\n \r\n\r\n {mixedData && (\r\n \r\n {t('labels.classification-from-aerial-will-only-apply-to-las-files')}\r\n \r\n )}\r\n\r\n
\r\n\r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n );\r\n};\r\n\r\ninterface ClassificationParametersProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n runClassification: (score, modelPath, runOnCPU, usePretrained) => void;\r\n defaultScore: string;\r\n isOrthoLabel: boolean;\r\n}\r\n\r\nconst ClassificationParameters = (props: ClassificationParametersProps) => {\r\n const {open, setOpen, runClassification, defaultScore, isOrthoLabel} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const [modelPath, setModelPath] = useState(null);\r\n const [runOnCPU, setRunOnCPU] = useState(false);\r\n const [usePretrained, setUsePretrained] = useState(false);\r\n const [score, setScore] = useState({\r\n value: defaultScore,\r\n error: false\r\n });\r\n\r\n const handleCancel = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n toast.success(t(\"toast.labels-classify-submit\"));\r\n runClassification(parseFloat(score.value), modelPath, runOnCPU, usePretrained);\r\n setOpen(false);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setModelPath(null);\r\n setRunOnCPU(false);\r\n setUsePretrained(false);\r\n setScore({value: defaultScore, error: false});\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const canSubmit = (modelPath !== null || usePretrained) && (!score.error);\r\n\r\n return (\r\n \r\n {t('labels.model-classification-parameters')}\r\n\r\n \r\n\r\n {/* Classification Score */}\r\n {t('labels.classification-score')}\r\n \r\n\r\n {/* Model path */}\r\n {(!usePretrained) &&
\r\n \r\n
}\r\n\r\n {/* Use Pretrained Panoptic Model */}\r\n {(!isOrthoLabel) &&
\r\n {t('labels.use-pretrained')}\r\n {\r\n setUsePretrained(event.target.checked);\r\n }}\r\n size=\"small\"\r\n color=\"secondary\"\r\n />\r\n
}\r\n\r\n {(!isOrthoLabel) && \r\n {t('labels.use-pretrained-panoptic')}\r\n }\r\n\r\n {/* Run on CPU */}\r\n
\r\n {t('labels.run-on-cpu')}\r\n {\r\n setRunOnCPU(event.target.checked);\r\n }}\r\n />\r\n
\r\n\r\n \r\n {t('labels.running-on-cpu-is-slower')}\r\n \r\n\r\n
\r\n\r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface TrainingParametersProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n runTraining: (\r\n numIterations: number, imageTileSize: number, outputPath: string,\r\n pretrainedModelPath: string, runOnCPU: boolean, modelName: string\r\n ) => void;\r\n isOrthoLabel: boolean;\r\n defaultIterations: string;\r\n}\r\n\r\nconst TrainingParameters = (props: TrainingParametersProps) => {\r\n const {open, setOpen, runTraining, isOrthoLabel, defaultIterations} = props;\r\n const {t} = useTranslation();\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [pretrainedPath, setPretrainedPath] = useState(null);\r\n const [runOnCPU, setRunOnCPU] = useState(false);\r\n const [modelName, setModelName] = useState(\"\");\r\n const [imageTileSize, setImageTileSize] = useState(512);\r\n const [iterations, setIterations] = useState({\r\n value: defaultIterations,\r\n error: false,\r\n });\r\n\r\n const handleCancel = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n const numIterations = parseInt(iterations.value);\r\n runTraining(numIterations, imageTileSize, outputPath,\r\n pretrainedPath, runOnCPU, modelName);\r\n setOpen(false);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setPretrainedPath(null);\r\n setRunOnCPU(false);\r\n setOutputPath(null);\r\n setImageTileSize(512);\r\n setIterations({\r\n value: defaultIterations,\r\n error: false\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const canSubmit = (outputPath !== null) && (!iterations.error);\r\n\r\n return (\r\n \r\n {t('labels.model-training-parameters')}\r\n\r\n \r\n \r\n\r\n {/* Training iterations */}\r\n \r\n \r\n \r\n\r\n {/* Training Model Name */}\r\n \r\n \r\n \r\n\r\n {/* Training iterations */}\r\n {isOrthoLabel && \r\n \r\n }\r\n\r\n {/* Output folder */}\r\n \r\n \r\n \r\n\r\n \r\n {/* Pretrained model */}\r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface GetInfoWindowProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n index: number;\r\n isSceneLabel: boolean;\r\n label: ImageLabel\r\n}\r\n\r\nconst GetInfoWindow = (props: GetInfoWindowProps) => {\r\n const {open, setOpen, label, index, isSceneLabel} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const orignalText = label.text.split('\\n');\r\n const [text, setText] = useState(orignalText);\r\n\r\n const scoreClass = (score) => {\r\n let scoreValidity = classes.success;\r\n if (score < 0.9) {\r\n scoreValidity = classes.warning;\r\n }\r\n if (score < 0.7) {\r\n scoreValidity = classes.error;\r\n }\r\n return scoreValidity;\r\n };\r\n\r\n const handleCancel = () => {\r\n setText([...orignalText]);\r\n setOpen(false);\r\n };\r\n\r\n const updateLabelText = (txtList) => {\r\n const newText = txtList.join(\"\\n\");\r\n viewer?.setLabelText(label.id, newText);\r\n };\r\n\r\n const handleSubmit = () => {\r\n let trimmedText = text.map(x => x.trim());\r\n setText([...trimmedText]);\r\n updateLabelText(trimmedText);\r\n setOpen(false);\r\n };\r\n\r\n const handleKeyDown = (event) => {\r\n if (event.key === 'Enter') {\r\n handleSubmit();\r\n }\r\n };\r\n\r\n const handleTextChange = (event, index) => {\r\n let newText = [...text];\r\n newText[index] = event.target.value;\r\n setText([...newText]);\r\n };\r\n\r\n const classValid = label.valid\r\n ? classes.success\r\n : classes.error;\r\n\r\n const classHighlight = label.highlighted\r\n ? classes.success\r\n : classes.error;\r\n\r\n return (\r\n \r\n {t('labels.label-info')}\r\n\r\n \r\n {t('labels.information')}\r\n \r\n\r\n {/** Label Number */}\r\n \r\n \r\n {t('labels.label-number', {index})}\r\n \r\n \r\n\r\n {/** Valid Geometry */}\r\n \r\n \r\n {`${t('labels.polygon-valid')}:`}\r\n \r\n \r\n {String(label.valid).toUpperCase()}\r\n \r\n \r\n\r\n {/** Highlighted */}\r\n \r\n \r\n {`${t('labels.highlighted')}:`}\r\n \r\n \r\n {String(label.highlighted).toUpperCase()}\r\n \r\n \r\n\r\n {/** Classification Score */}\r\n \r\n \r\n {`${t('labels.classification-score')}:`}\r\n \r\n \r\n {label.score.toFixed(2)}\r\n \r\n \r\n\r\n {(isSceneLabel) && \r\n {/** Text Confidence */}\r\n \r\n \r\n {`${t('labels.text-detection-score')}:`}\r\n \r\n \r\n {`${label.textScore.toFixed(2)}`}\r\n \r\n \r\n\r\n {/** Detected Text */}\r\n \r\n \r\n {text.map((txt, index)=>\r\n handleTextChange(event, index)}\r\n onKeyDown={(event) => handleKeyDown(event)}\r\n autoFocus\r\n margin=\"dense\"\r\n size=\"small\"\r\n label={t('labels.detected-text-line-line', {\r\n line: index+1\r\n })}\r\n type=\"text\"\r\n fullWidth\r\n value={txt}\r\n />\r\n )}\r\n \r\n \r\n\r\n }\r\n\r\n \r\n \r\n\r\n \r\n \r\n\r\n {(isSceneLabel) && }\r\n \r\n \r\n );\r\n};\r\n\r\ninterface TextDetectionParametersProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n defaultScore: string;\r\n category: LabelCategory;\r\n runTextDetection: (score, spellcheck) => void;\r\n}\r\n\r\nconst TextDetectionParameters = (props: TextDetectionParametersProps) => {\r\n const {open, setOpen, runTextDetection, defaultScore, category} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [spellcheck, setSpellcheck] = useState(false);\r\n const [score, setScore] = useState({\r\n value: defaultScore,\r\n error: false\r\n });\r\n\r\n const handleCancel = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n viewer?.setLabelFindText(category.id);\r\n runTextDetection(parseFloat(score.value), spellcheck);\r\n setOpen(false);\r\n };\r\n\r\n const resetDefaults = () => {\r\n setSpellcheck(false);\r\n setScore({value: defaultScore, error: false});\r\n };\r\n\r\n useEffect(() => {\r\n if (open) return;\r\n resetDefaults();\r\n }, [open]);\r\n\r\n const canSubmit = (!score.error);\r\n\r\n return (\r\n \r\n {t('labels.detect-text-in-name-labels', {\r\n name: category.name\r\n })}\r\n\r\n \r\n\r\n {/* Classification Score */}\r\n {t('labels.detection-score-threshold')}\r\n \r\n {t('labels.detected-text-with-detection-scores-below')}\r\n \r\n \r\n\r\n {/* Spell check toggle */}\r\n
\r\n {t('labels.spell-check-detected-text')}\r\n {\r\n setSpellcheck(event.target.checked);\r\n }}\r\n />\r\n
\r\n\r\n \r\n {t('labels.utilize-spell-checking')}\r\n \r\n\r\n
\r\n\r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface ScoreSortingParametersProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n defaultScore: string;\r\n category: LabelCategory;\r\n runSort: (scoreValue, sortType) => void;\r\n}\r\n\r\nconst ScoreSortingParameters = (props: ScoreSortingParametersProps) => {\r\n const {open, setOpen, runSort, defaultScore, category} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const [sortType, setSortType] = useState('descending');\r\n const [score, setScore] = useState({\r\n value: defaultScore,\r\n error: false\r\n });\r\n\r\n const handleCancel = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleSubmit = () => {\r\n toast.success(t(\"toast.labels-sort-submit\"));\r\n runSort(parseFloat(score.value), sortType);\r\n setOpen(false);\r\n };\r\n\r\n /*\r\n useEffect(() => {\r\n if (open) {\r\n return;\r\n }\r\n\r\n // Reset default values\r\n setSortType('descending');\r\n setScore({value: defaultScore, error: false});\r\n }, [open]);\r\n */\r\n\r\n const canSubmit = (!score.error);\r\n\r\n return (\r\n \r\n {t('labels.sort-name-labels', {\r\n name: category.name\r\n })}\r\n\r\n \r\n\r\n {/* Classification Score */}\r\n {t('labels.classification-score-threshold')}\r\n \r\n {t('labels.classification-scores-below', {\r\n name: category.name\r\n })}\r\n \r\n \r\n\r\n {/* Sort Type */}\r\n
\r\n {t('labels.sorting-method')}\r\n \r\n {t('labels.choose-method-if-any-by-which-to-sort-the-category')}\r\n \r\n\r\n
\r\n {\r\n let value = event.target.value as any;\r\n setSortType(value);\r\n }}\r\n >\r\n {t('labels.ascending-low-to-high')}\r\n {t('labels.descending-high-to-low')}\r\n {t('labels.dont-sort')}\r\n \r\n {\" \"}\r\n
\r\n
\r\n\r\n
\r\n\r\n \r\n \r\n\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface ImageLabellingProps {\r\n categoryList: LabelCategory[];\r\n trainingArea: TrainingAreaCategory[];\r\n}\r\n\r\nexport const ImageLabelling = memo((props: ImageLabellingProps) => {\r\n const {categoryList, trainingArea} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const imageLabelDialog = useDialog();\r\n const contextMenu = useContextMenu();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {activeToolOpen, setActiveToolOpen} = useActiveTool();\r\n\r\n const [labelType, setLabelType] = useState(null);\r\n const [addCategory, setAddCategory] = useState(false);\r\n const [classifyLasPrompt, setClassifyLasPrompt] = useState(false);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [importData, setImportData] = useState(null);\r\n const [labelLoadProgress, setLabelLoadProgress] = useState(0);\r\n const [classifyAerialProgress, setClassifyAerialProgress] = useState(0);\r\n const [trainClassifyProgress, updateTrainClassifyProgress] = useState(0);\r\n const [trainClassifyExe, setTrainClassifyExe] = useState(null);\r\n const [processType, setProcessType] = useState(\"\");\r\n const [classifyImage, setClassifyImage] = useState(false);\r\n const [readingLabelFile, setReadingLabelFile] = useState(false);\r\n const [training, setTraining] = useState(false);\r\n const [trainingURL, setTrainingURL] = useState(null);\r\n const [downloadResourcesDialog, setDownloadResourcesDialog] = useState(\"\");\r\n const [trainingPrompt, setTrainingPrompt] = useState(false);\r\n const [classificationPrompt, setClassificationPrompt] = useState(false);\r\n const [labelExportOpen, setLabelExportOpen] = useState(false);\r\n const [classifyPointsPanoOpen, setClassifyPointsPanoOpen] = useState(false);\r\n const [textDetection, setTextDetection] = useState(false);\r\n const assets = useSelector(selectAllAssets);\r\n const cameraFiles = getCameraFileAssets(assets);\r\n const pointCloudFiles = getPointCloudAssets(assets);\r\n\r\n const isOrthoLabel = labelType === \"ortho\";\r\n const isSceneLabel = labelType === \"scene\";\r\n // const numPlanars = cameraFiles.filter(x => x.type === AssetType.Planar).length;\r\n // const canExportCSV = isSceneLabel && (numPlanars === 0);\r\n const LASfiles = pointCloudFiles.filter(x => x.type === AssetType.LAS);\r\n const visibleClouds = LASfiles.filter(x => x.visible);\r\n const pointCloudsUsable = (visibleClouds.length > 0);\r\n\r\n // UI progress needs to be throttled, so it doesnt update too quickly and freeze the app\r\n const progressThrottleMilliseconds = 50;\r\n\r\n const setTrainClassifyProgress = useCallback(throttle(\r\n progressThrottleMilliseconds, (value) => {\r\n updateTrainClassifyProgress(value);\r\n }), []);\r\n\r\n const resetExecutableValues = () => {\r\n setTrainClassifyProgress(0);\r\n setTrainingURL(null);\r\n setTraining(false);\r\n setTextDetection(false);\r\n setClassifyImage(false);\r\n };\r\n\r\n const handleClose = () => {\r\n imageLabelDialog.handleClose();\r\n handleCancelProgress();\r\n };\r\n\r\n const checkClose = () => {\r\n if (isModified) {\r\n setClosePrompt(true);\r\n } else {\r\n handleClose();\r\n }\r\n };\r\n\r\n const isValidCategory = (name) => {\r\n // Uniqueness check\r\n const isUnique = viewer?.checkCategoryUniqueness(name);\r\n if (!isUnique) {\r\n toast.error(t(\"toast.labels-class-exists\"));\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const handleCategoryChange = (state) => {\r\n setAddCategory(state);\r\n };\r\n\r\n const handleCancel = () => {\r\n handleCategoryChange(false);\r\n };\r\n\r\n const handleAddCategory = (name) => {\r\n if (!isValidCategory(name)) {\r\n return;\r\n }\r\n\r\n viewer?.addCategory(name);\r\n handleCategoryChange(false);\r\n };\r\n\r\n const handleCancelProgress = () => {\r\n trainClassifyExe?.destroy();\r\n resetExecutableValues();\r\n };\r\n\r\n const showTrainingWindow = (url) => {\r\n ipcRenderer?.send(\"show-training-window\", url);\r\n };\r\n\r\n const stopTrainingWindow = () => {\r\n ipcRenderer?.send(\"stop-training-window\");\r\n };\r\n\r\n const checkTrainingData = (jsonData) => {\r\n const canTrain = jsonData\r\n && (jsonData.annotations.length > 0)\r\n && (jsonData.images.length > 0);\r\n\r\n if (!canTrain) {\r\n toast.warning(t(\"toast.labels-not-active\"));\r\n }\r\n\r\n return canTrain;\r\n };\r\n\r\n const exportImageLabels = () => {\r\n // No labels to export\r\n if (categoryList.length === 0) {\r\n toast.warning(t(\"toast.labels-not-created\"));\r\n return;\r\n }\r\n\r\n dialog.showSaveDialog({\r\n defaultPath: viewer.projectName,\r\n filters: [\r\n ...labelFilter,\r\n ...(isOrthoLabel ? DXFModelFilter : []),\r\n ...(isOrthoLabel ? SHPModelFilter : [])\r\n ],\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n if (result.filePath) {\r\n const filePath = slash(result.filePath);\r\n const extension = path.extname(filePath);\r\n\r\n if (extension === \".dxf\") {\r\n exportToLinework(filePath, extension, \"dxf_path\");\r\n }\r\n\r\n if (extension === \".shp\") {\r\n exportToLinework(filePath, extension, \"shp_path\");\r\n }\r\n\r\n if (extension === \".3dl\") {\r\n exportLabels3DL(filePath);\r\n }\r\n }\r\n }).catch(error => {\r\n console.log(error);\r\n });\r\n };\r\n\r\n /** @private */\r\n const exportLabels3DL = (filePath) => {\r\n const jsonData = viewer?.labelObject();\r\n\r\n let text = JSON.stringify(jsonData, null, 2);\r\n fs.writeFile(filePath, text, 'utf8', (err) => {\r\n if (err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-export-failed\"));\r\n }\r\n else {\r\n toast.success(t(\"toast.labels-export-to\", {\r\n path: path.basename(filePath)\r\n }));\r\n\r\n console.log(`File written successfully to ${filePath}`);\r\n }\r\n });\r\n };\r\n\r\n /** @private */\r\n const exportToLinework = (filePath, extension, outputKey) => {\r\n const jsonData = viewer?.labelObject();\r\n if (!checkTrainingData(jsonData)) {\r\n return false;\r\n }\r\n\r\n // Write COCO file to temp path\r\n let text = JSON.stringify(jsonData, null, 2);\r\n let tempCocoPath = getTemporaryFile(\"3dl\");\r\n\r\n try {\r\n fs.writeFileSync(tempCocoPath, text);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-export-failed\"));\r\n return;\r\n }\r\n\r\n let pythonName;\r\n if (extension === \".dxf\") {\r\n pythonName = \"coco_to_dxf\";\r\n } else if (extension === \".shp\") {\r\n pythonName = \"coco_to_shp\";\r\n }\r\n\r\n if (!pythonName) {\r\n return;\r\n }\r\n\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--coco_path\", tempCocoPath,\r\n `--${outputKey}`, filePath\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onClose: () => {\r\n toast.success(t(\"toast.labels-saved-linework\", {\r\n type: extension,\r\n path: path.basename(filePath)\r\n }));\r\n }\r\n });\r\n };\r\n\r\n const importImageLabels = () => {\r\n const combinedExtension = getCombinedExtension(\r\n \"dialog.supported-files\", [\r\n labelFilter,\r\n modelFilter,\r\n isOrthoLabel ? drawingFilter : null\r\n ]);\r\n\r\n dialog.showOpenDialog({\r\n properties: ['openFile'],\r\n filters: [\r\n ...combinedExtension,\r\n ...labelFilter,\r\n ...modelFilter,\r\n ...(isOrthoLabel ? drawingFilter : [])\r\n ]\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n const filePath = slash(result.filePaths[0]);\r\n const extension = path.extname(filePath);\r\n\r\n if (extension === \".pth\") {\r\n importLabelsPTH(filePath);\r\n }\r\n\r\n if (extension === \".3dl\") {\r\n importLabels3DL(filePath);\r\n }\r\n\r\n const importLinework =\r\n (extension === \".shp\")\r\n || (extension === \".dxf\")\r\n || (extension === \".zip\");\r\n\r\n if (importLinework) {\r\n importLabelsLinework(filePath);\r\n }\r\n }).catch(error => {\r\n setReadingLabelFile(false);\r\n console.log(error);\r\n });\r\n };\r\n\r\n /** @private */\r\n const importLabelsPTH = (filePath) => {\r\n setReadingLabelFile(true);\r\n\r\n const exe = new PythonExecutable();\r\n\r\n let response;\r\n let commands = [\r\n \"-p\", \"extract_coco_from_model\",\r\n \"--model_path\", filePath,\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (jsonData.downloading_resources) {\r\n setDownloadResourcesDialog(\"download\");\r\n } else if (jsonData.extracting_resources) {\r\n setDownloadResourcesDialog(\"extract\");\r\n } else if (jsonData.coco_data) {\r\n response = jsonData.coco_data;\r\n }\r\n },\r\n onClose: () => {\r\n setDownloadResourcesDialog(\"\");\r\n\r\n if (response) {\r\n importLabelData(response);\r\n } else {\r\n toast.error(t(\"toast.labels-read-error\"));\r\n }\r\n }\r\n });\r\n };\r\n\r\n /** @private */\r\n const importLabelsLinework = (filePath) => {\r\n setReadingLabelFile(true);\r\n\r\n const exe = new PythonExecutable();\r\n\r\n let response;\r\n let commands = [\r\n \"-p\", \"convert_linework\",\r\n \"--input_paths\", [filePath],\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n onLine: jsonData => {\r\n if (jsonData.label_data) {\r\n response = {\r\n ...jsonData.label_data,\r\n projection: LocalScene.dataProjection\r\n };\r\n }\r\n },\r\n onClose: () => {\r\n importLabelData(response);\r\n }\r\n });\r\n };\r\n\r\n /** @private */\r\n const importLabels3DL = (filePath) => {\r\n try {\r\n const text = fs.readFileSync(filePath, 'utf8');\r\n const data = JSON.parse(text);\r\n importLabelData(data);\r\n } catch {\r\n toast.error(t(\"toast.labels-read-error\"));\r\n }\r\n };\r\n\r\n /** @private */\r\n const importLabelData = (data) => {\r\n setReadingLabelFile(false);\r\n\r\n if (!data) {\r\n toast.error(t(\"toast.labels-read-error\"));\r\n return;\r\n }\r\n\r\n if (data.type !== labelType) {\r\n toast.error(t(\"toast.labels-type-mismatch\", {\r\n type: data.type\r\n }));\r\n return;\r\n }\r\n\r\n setImportData(data);\r\n };\r\n\r\n const forceInitialProgress = () => {\r\n setTrainClassifyProgress(0.001);\r\n };\r\n\r\n const cudaErrorDialog = (cudaError) => {\r\n const downloadURL = 'https://developer.nvidia.com/cuda-11.1.0-download-archive?target_os=Windows&target_arch=x86_64&target_version=10';\r\n\r\n dialog.showMessageBox({\r\n title: t(\"dialog.cuda-error-title\"),\r\n message: t(\"dialog.cuda-error-message\", {version: cudaError}),\r\n buttons: [\r\n t(\"buttons.dismiss\"),\r\n t(\"buttons.get-cuda\")\r\n ],\r\n type: 'error',\r\n noLink: true\r\n })\r\n .then(selection => {\r\n if (selection.response !== 1) return;\r\n shell.openExternal(downloadURL);\r\n });\r\n };\r\n\r\n const mlResourceErrorDialog = () => {\r\n const downloadURL = 'https://solv3d.com/support/';\r\n\r\n dialog.showMessageBox({\r\n title: t(\"dialog.ml-resource-error-title\"),\r\n message: t(\"dialog.ml-resource-error-message\"),\r\n buttons: [\r\n t(\"buttons.dismiss\"),\r\n t(\"buttons.download-resources\")\r\n ],\r\n type: 'error',\r\n noLink: true\r\n })\r\n .then(selection => {\r\n if (selection.response !== 1) return;\r\n shell.openExternal(downloadURL);\r\n });\r\n };\r\n\r\n const canRunClassification = () => {\r\n const imagePaths = viewer?.loadedImageLabelPaths();\r\n const canClassify = imagePaths && (imagePaths.length > 0);\r\n\r\n if (!canClassify) {\r\n toast.warning(t(\"toast.labels-no-images\"));\r\n }\r\n\r\n return canClassify;\r\n };\r\n\r\n const runClassification = (score, modelPath, runOnCPU, usePretrained) => {\r\n resetExecutableValues();\r\n setClassifyImage(true);\r\n\r\n let tempImagePath = getTemporaryFile(\"txt\");\r\n let imageData = viewer.loadedImageLabelPaths();\r\n let imageJSON = JSON.stringify(imageData, null, 4);\r\n\r\n try {\r\n fs.writeFileSync(tempImagePath, imageJSON);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-classify-error\"));\r\n\r\n setTraining(false);\r\n return;\r\n }\r\n\r\n try {\r\n let pythonName = isOrthoLabel\r\n ? \"image_classification_orthomosaic\"\r\n : \"image_classification_panoramic\";\r\n\r\n pythonName = usePretrained ? \"panoptic_segmentation\" : pythonName;\r\n\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--image_paths_txt\", tempImagePath,\r\n \"--output_folder\", tempDirectoryPath,\r\n \"--proj_string\", LocalScene.dataProjection,\r\n \"--prediction_score_threshold\", score,\r\n \"--run_on_cpu\", runOnCPU\r\n ];\r\n\r\n if (!usePretrained) {\r\n commands.push(\"--prediction_model\");\r\n commands.push(modelPath);\r\n }\r\n\r\n forceInitialProgress();\r\n\r\n let importData;\r\n let exe = new PythonExecutable();\r\n setTrainClassifyExe(exe);\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n\r\n if (jsonData.cudaError){\r\n cudaErrorDialog(jsonData.cudaError);\r\n }\r\n\r\n if (jsonData.noMlResources){\r\n mlResourceErrorDialog();\r\n }\r\n\r\n if (jsonData.progress) {\r\n setTrainClassifyProgress(jsonData.progress);\r\n } else if (jsonData.coco_data) {\r\n importData = jsonData.coco_data;\r\n }\r\n },\r\n onClose: async () => {\r\n if (importData) {\r\n toast.success(t(\"toast.labels-classify-loading\"));\r\n\r\n await viewer.loadImageLabelData(\r\n importData,\r\n setLabelLoadProgress,\r\n true,\r\n false\r\n );\r\n\r\n toast.success(t(\"toast.labels-classify-loaded\"));\r\n } else {\r\n toast.error(t(\"toast.labels-classify-error\"));\r\n }\r\n\r\n resetExecutableValues();\r\n }\r\n });\r\n } catch {\r\n setClassifyImage(false);\r\n toast.error(t(\"toast.labels-classify-error\"));\r\n }\r\n };\r\n\r\n const runTraining = (\r\n numIterations: number, imageTileSize: number, outputPath: string,\r\n pretrainedModelPath: string, runOnCPU: boolean, modelName: string\r\n ) => {\r\n resetExecutableValues();\r\n setTraining(true);\r\n\r\n let modelPath;\r\n let tempCocoPath = path.join(outputPath, \"labels_for_training.3dl\");\r\n let tempImagePath = getTemporaryFile(\"txt\");\r\n\r\n try {\r\n const jsonData = viewer.labelObject();\r\n if (!checkTrainingData(jsonData)) {\r\n setTraining(false);\r\n return;\r\n }\r\n\r\n toast.success(t(\"toast.labels-train-submit\"));\r\n\r\n let imageData = viewer.activeImageLabelPaths();\r\n let labelJSON = JSON.stringify(jsonData, null, 4);\r\n let imageJSON = JSON.stringify(imageData, null, 4);\r\n\r\n try {\r\n fs.writeFileSync(tempImagePath, imageJSON);\r\n fs.writeFileSync(tempCocoPath, labelJSON);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-export-failed\"));\r\n\r\n setTraining(false);\r\n return;\r\n }\r\n\r\n forceInitialProgress();\r\n\r\n let pythonName = isOrthoLabel\r\n ? \"image_training_orthomosaic\"\r\n : \"image_training_panoramic\";\r\n\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--image_paths_txt\", tempImagePath,\r\n \"--output_folder\", outputPath,\r\n \"--coco_data_file\", tempCocoPath,\r\n \"--solver_max_iterations\", numIterations,\r\n \"--batch_size_per_image\", 256,\r\n \"--run_on_cpu\", runOnCPU,\r\n \"--model_title\", modelName\r\n ];\r\n\r\n if (isOrthoLabel) {\r\n commands = [\r\n ...commands,\r\n \"--image_tile_size\", imageTileSize,\r\n ];\r\n }\r\n\r\n if (pretrainedModelPath) {\r\n commands = [\r\n ...commands,\r\n \"--pretrained_model_pth\", pretrainedModelPath\r\n ];\r\n }\r\n\r\n setTrainClassifyExe(exe);\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (jsonData.cudaError){\r\n cudaErrorDialog(jsonData.cudaError);\r\n } else if (jsonData.noMlResources){\r\n mlResourceErrorDialog();\r\n } else if (jsonData.gpu_memory_error) {\r\n toast.error(t(\"toast.labels-train-error-memory\"));\r\n } else if (jsonData.model_diverge_error){\r\n toast.error(t(\"toast.labels-train-error-diverge\"));\r\n } else if (jsonData.label_bounds_error){\r\n toast.error(t(\"toast.labels-train-error-bounds\"));\r\n } else if (jsonData.progress) {\r\n setTrainClassifyProgress(jsonData.progress);\r\n } else if (jsonData.model_file_path) {\r\n modelPath = jsonData.model_file_path;\r\n } else if (jsonData.url) {\r\n setTrainingURL(jsonData.url);\r\n showTrainingWindow(jsonData.url);\r\n } else if (jsonData.class_number_mismatch) {\r\n toast.error(t(\"toast.labels-train-error-class\", {\r\n oldClasses: jsonData.old_classes.join(\", \"),\r\n newClasses: jsonData.new_classes.join(\", \")\r\n }));\r\n }\r\n },\r\n onClose: () => {\r\n if (modelPath) {\r\n toast.success(t(\"toast.labels-train-complete\", {\r\n path: modelPath\r\n }));\r\n } else {\r\n toast.warning(t(\"toast.labels-train-incomplete\"));\r\n }\r\n\r\n stopTrainingWindow();\r\n resetExecutableValues();\r\n }\r\n });\r\n }\r\n catch (err ){\r\n console.log(err);\r\n setTraining(false);\r\n toast.error(t(\"toast.labels-train-error\"));\r\n }\r\n };\r\n\r\n const runTextDetection = (score, spellcheck) => {\r\n resetExecutableValues();\r\n setTextDetection(true);\r\n\r\n let spellcheckCommand = spellcheck\r\n ? t('general.true')\r\n : t('general.false');\r\n\r\n let tempCocoPath = getTemporaryFile(\"3dl\");\r\n let tempImagePath = getTemporaryFile(\"txt\");\r\n\r\n try {\r\n const jsonData = viewer?.labelObject();\r\n if (!checkTrainingData(jsonData)) {\r\n setTextDetection(false);\r\n return;\r\n }\r\n\r\n let imageData = viewer.activeImageLabelPaths();\r\n let labelJSON = JSON.stringify(jsonData, null, 4);\r\n let imageJSON = JSON.stringify(imageData, null, 4);\r\n\r\n try {\r\n fs.writeFileSync(tempImagePath, imageJSON);\r\n fs.writeFileSync(tempCocoPath, labelJSON);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.labels-export-failed\"));\r\n\r\n setTextDetection(false);\r\n return;\r\n }\r\n\r\n let pythonName = \"text_from_image\";\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--image_paths_txt\", tempImagePath,\r\n \"--coco_data_file\", tempCocoPath,\r\n \"--score_threshold\", score,\r\n \"--spell_check\", spellcheckCommand\r\n ];\r\n\r\n forceInitialProgress();\r\n\r\n let importData;\r\n let exe = new PythonExecutable();\r\n setTrainClassifyExe(exe);\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n\r\n if (jsonData.cudaError){\r\n cudaErrorDialog(jsonData.cudaError);\r\n }\r\n\r\n if (jsonData.noMlResources){\r\n mlResourceErrorDialog();\r\n }\r\n\r\n if (jsonData.progress) {\r\n setTrainClassifyProgress(jsonData.progress);\r\n } else if (jsonData.coco_data) {\r\n importData = jsonData.coco_data;\r\n }\r\n },\r\n onClose: async () => {\r\n if (importData) {\r\n toast.success(t(\"toast.labels-text-loading\"));\r\n\r\n await viewer.loadImageLabelData(\r\n importData,\r\n setLabelLoadProgress,\r\n true,\r\n false\r\n );\r\n\r\n toast.success(t(\"toast.labels-text-loaded\"));\r\n } else {\r\n toast.error(t(\"toast.labels-text-error\"));\r\n }\r\n\r\n resetExecutableValues();\r\n }\r\n });\r\n } catch {\r\n setTextDetection(false);\r\n toast.error(t(\"toast.labels-classify-error\"));\r\n }\r\n };\r\n\r\n const canRunAerialToLas = () => {\r\n const LASfiles = pointCloudFiles.filter(x => x.type === AssetType.LAS);\r\n const visibleClouds = LASfiles.filter(x => x.visible);\r\n\r\n if (visibleClouds.length === 0) {\r\n toast.warning(t(\"toast.labels-no-clouds\"));\r\n }\r\n\r\n if (!isModified) {\r\n toast.warning(t(\"toast.labels-no-categories\"));\r\n }\r\n\r\n return isModified && (visibleClouds.length > 0);\r\n };\r\n\r\n const onFindPosition = () => {\r\n contextMenu.handleClose();\r\n setLabelExportOpen(true);\r\n };\r\n\r\n const onClassifyPoints = () => {\r\n contextMenu.handleClose();\r\n setClassifyPointsPanoOpen(true);\r\n };\r\n\r\n\r\n useEffect(() => {\r\n /** Keep track if a tool is currently being used */\r\n setActiveToolOpen(imageLabelDialog.open);\r\n }, [imageLabelDialog.open]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n imageLabelDialog.handleClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-label-ortho\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n imageLabelDialog.handleOpen(\"ortho\");\r\n });\r\n\r\n registerEvent(\"open-label-scene\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n imageLabelDialog.handleOpen(\"scene\");\r\n });\r\n }, [activeToolOpen]);\r\n\r\n useEffect(() => {\r\n if (!imageLabelDialog.open) return;\r\n\r\n const onKeyDown = event => {\r\n if (event.target instanceof HTMLInputElement) {\r\n return;\r\n }\r\n\r\n viewer?.labelHotkey(event);\r\n };\r\n\r\n window.addEventListener('keydown', onKeyDown, false);\r\n\r\n return () => {\r\n window.removeEventListener('keydown', onKeyDown, false);\r\n };\r\n }, [imageLabelDialog.open]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setActiveLabelType(labelType);\r\n\r\n if (isOrthoLabel) {\r\n dispatch(changeSwitched(true));\r\n } else if (isSceneLabel) {\r\n dispatch(changeSwitched(false));\r\n }\r\n }, [viewer, labelType]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n setLabelType(imageLabelDialog.data);\r\n }, [viewer, imageLabelDialog.data]);\r\n\r\n useEffect(() => {\r\n if (classifyImage) {\r\n setProcessType(\"labels.image-classification\");\r\n } else if (training) {\r\n setProcessType(\"labels.training\");\r\n } else if (textDetection) {\r\n setProcessType(\"labels.text-detection\");\r\n }\r\n\r\n if (trainClassifyProgress === 100) {\r\n setTrainClassifyProgress(0);\r\n setProcessType(\"\");\r\n }\r\n }, [\r\n trainClassifyProgress,\r\n classifyImage,\r\n training,\r\n textDetection\r\n ]);\r\n\r\n const isModified = categoryList.length !== 0;\r\n const exportDisabled = viewer?.anyLabelSelected();\r\n const trainingLinkDisabled = trainingURL === null;\r\n const hasTrainingArea = trainingArea.length > 0;\r\n\r\n const noLabels = viewer?.numLabels === 0;\r\n const noImages = (isSceneLabel) && (cameraFiles.length === 0);\r\n\r\n const labelDisabled = (labelLoadProgress > 0)\r\n || training\r\n || classifyImage\r\n || textDetection;\r\n\r\n const labelDisabledNoLabels = labelDisabled || noLabels || noImages;\r\n const labelDisabledNoImages = labelDisabled || noImages;\r\n const localizedProcessType = t(processType);\r\n\r\n const modalName = isOrthoLabel\r\n ? t('labels.orthomosaic-training-classification')\r\n : t('labels.panoramic-training-classification');\r\n\r\n const downloadTooltip = t('labels.running-process-on-dataset', {\r\n process: localizedProcessType\r\n });\r\n\r\n return (\r\n \r\n \r\n {/* Label toolbar icons */}\r\n \r\n\r\n {/* Add category */}\r\n handleCategoryChange(true)}\r\n success\r\n />\r\n\r\n {/* Enable training areas */}\r\n {\r\n viewer?.addTrainingArea();\r\n }}\r\n />\r\n\r\n {/* Disable training areas */}\r\n {\r\n viewer?.deleteTrainingArea();\r\n }}\r\n />\r\n\r\n {/* Run Training */}\r\n {\r\n setTrainingPrompt(true);\r\n }}\r\n disabled={labelDisabledNoLabels}\r\n />\r\n\r\n {/* Run Classification */}\r\n {\r\n if (!canRunClassification()) {\r\n return;\r\n }\r\n\r\n setClassificationPrompt(true);\r\n }}\r\n disabled={labelDisabledNoImages}\r\n />\r\n\r\n {/* Classify Las from Classes */}\r\n {\r\n if (!canRunAerialToLas()) {\r\n return;\r\n }\r\n\r\n setClassifyLasPrompt(true);\r\n }}\r\n visible={isOrthoLabel}\r\n disabled={labelDisabledNoLabels}\r\n />\r\n\r\n {/* Import label file */}\r\n \r\n\r\n {/* Export Label file */}\r\n \r\n\r\n {/* Open Label Analysis Menus */}\r\n \r\n\r\n \r\n\r\n \r\n\r\n {(trainClassifyProgress > 0) && (\r\n\r\n
\r\n\r\n {/** Training/Classification progress */}\r\n \r\n
\r\n \r\n
\r\n
\r\n\r\n {/** Tensorbard training link */}\r\n {training && (\r\n {\r\n showTrainingWindow(trainingURL);\r\n }}\r\n />\r\n )}\r\n\r\n {/** Training/Classification cancel button */}\r\n \r\n
\r\n\r\n\r\n
)}\r\n\r\n \r\n \r\n {/** Training areas */}\r\n {hasTrainingArea && (\r\n \r\n {trainingArea.map(areas =>\r\n )}\r\n \r\n\r\n \r\n )}\r\n\r\n {/** Standard categories */}\r\n \r\n {categoryList.map(category =>\r\n )}\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n {/* Close modal */}\r\n setClosePrompt(false)}\r\n onSubmit={() => {\r\n handleClose();\r\n setClosePrompt(false);\r\n }}\r\n title={t('labels.close-classification-window')}\r\n prompt={t('labels.do-you-want-to-close-the-window', {\r\n name: modalName\r\n })}\r\n button={t('buttons.close')}\r\n />\r\n\r\n {/* Set training parameters */}\r\n \r\n\r\n {/* Set classification parameters */}\r\n \r\n\r\n {/* Set classify from las parameters */}\r\n \r\n\r\n {/* Image label import percent dialog */}\r\n 0}\r\n text={t('labels.applying_point_cloud_classification')}\r\n percent={classifyAerialProgress}\r\n />\r\n\r\n {/* Image label import percent dialog */}\r\n 0}\r\n text={t('labels.importing-image-labels')}\r\n percent={labelLoadProgress}\r\n />\r\n\r\n \r\n \r\n \r\n {t('labels.reading-label-file')} \r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n {/** Downloading resources (modal) */}\r\n {(downloadResourcesDialog === \"download\") && (\r\n \r\n {t('labels.downloading-resources')} \r\n \r\n )}\r\n\r\n {/** Extracting resources (modal) */}\r\n {(downloadResourcesDialog === \"extract\") && (\r\n \r\n {t('labels.extracting-resources')} \r\n \r\n )}\r\n\r\n \r\n \r\n\r\n {/* Modal for importing linework data */}\r\n \r\n\r\n {/* Import/Export menu */}\r\n \r\n \r\n {t('labels.classify-point-cloud-from-labels')}\r\n \r\n\r\n \r\n {t('labels.find-positions-labels')}\r\n \r\n \r\n\r\n {/* Modal for exporting label intersections */}\r\n \r\n\r\n {/* Modal for classifying point clouds from labels */}\r\n \r\n\r\n
\r\n );\r\n});\r\n","import React, { memo } from 'react';\r\nimport { Theme, useTheme } from \"@mui/material/styles\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {useDispatch, useSelector} from 'react-redux';\r\nimport {List, ListItemButton, Typography} from '@mui/material';\r\nimport { DynamicScrollbar } from '../components';\r\nimport {settingsDrawerWidth} from \"../settings\";\r\nimport {\r\n selectAllFolders\r\n} from '../redux/folders-slice';\r\nimport {\r\n selectAllAssets,\r\n setVisibleFolder\r\n} from '../redux/assets-slice';\r\nimport { headerHeight } from '../app';\r\nimport clsx from 'clsx';\r\nimport { useTranslation } from 'react-i18next';\r\nimport LocalScene, { SceneCoordinate } from '../viewer/projections';\r\nimport {\r\n changeCameraState,\r\n initialSceneState,\r\n SceneCameraState\r\n} from '../redux/camera-slice';\r\nimport { getLocalizedFolderName } from '../utilities';\r\nimport { useGlobalSettings, useViewer } from '../hooks';\r\nimport { CameraImage } from '../viewer/cameras';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n parent: {\r\n position: \"absolute\",\r\n right: theme.spacing(1),\r\n pointerEvents: \"none\",\r\n display: \"flex\",\r\n height: \"100%\",\r\n alignItems: \"center\"\r\n },\r\n offset: {\r\n right: `calc(${settingsDrawerWidth}px + ${theme.spacing(1)})`\r\n },\r\n list: {\r\n zoom: 0.85,\r\n marginTop: `${headerHeight/2}px`,\r\n background: \"white\",\r\n borderRadius: theme.spacing(0.5),\r\n borderRight: `${theme.spacing(1)} solid ${theme.palette.primary.main}`,\r\n pointerEvents: \"auto\",\r\n boxShadow: \"0px 0px 5px 2px rgb(0 0 0 / 25%)\"\r\n },\r\n listItem: {\r\n padding: theme.spacing(1, 1.5)\r\n },\r\n title: {\r\n textAlign: \"center\",\r\n padding: theme.spacing(1, 1.5),\r\n fontWeight: \"bold\",\r\n zoom: 0.95\r\n }\r\n })\r\n);\r\n\r\ninterface QuickNavProps {\r\n settingsDrawerState: boolean;\r\n}\r\n\r\nexport const QuickNav = memo((props: QuickNavProps) => {\r\n const {settingsDrawerState} = props;\r\n\r\n const dispatch = useDispatch();\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const globalSettings = useGlobalSettings();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const folders = useSelector(selectAllFolders);\r\n\r\n const getFolderAssets = (folderID) => {\r\n const folderAssets = assets.filter(asset => (asset.folderID === folderID));\r\n return folderAssets.map(folderAsset => folderAsset.id);\r\n };\r\n\r\n const getBestSceneState = (cameras: CameraImage[]) : SceneCameraState => {\r\n const currentPosition = viewer.camera.position;\r\n\r\n const data = cameras.map(camera => {\r\n const cameraPosition = camera.position.scene;\r\n const dx = cameraPosition.x - currentPosition.x;\r\n const dy = cameraPosition.y - currentPosition.y;\r\n const distance = Math.sqrt(dx*dx + dy*dy);\r\n\r\n return {\r\n camera,\r\n distance\r\n };\r\n });\r\n\r\n data.sort((a,b) => a.distance - b.distance);\r\n\r\n const closestCamera = data[0].camera;\r\n const closestPosition = closestCamera.position.scene;\r\n\r\n const lookatScene = [\r\n currentPosition.x,\r\n currentPosition.y,\r\n closestPosition.z\r\n ];\r\n\r\n const lookat = new SceneCoordinate(lookatScene)\r\n .toDataProjection()\r\n .toArray();\r\n\r\n return {\r\n ...initialSceneState,\r\n camera: closestCamera.id,\r\n lookat\r\n } as SceneCameraState;\r\n };\r\n\r\n const onClick = (folderID) => {\r\n if (!viewer) return;\r\n\r\n const cameras = viewer.getCamerasByFolder(folderID);\r\n const hasCameras = cameras.length > 0;\r\n\r\n if (hasCameras) {\r\n if (LocalScene.initialized) {\r\n const sceneState = getBestSceneState(cameras);\r\n viewer.setInitialStateFlag(false);\r\n dispatch(changeCameraState(sceneState));\r\n }\r\n } else {\r\n const folderAssetIds = getFolderAssets(folderID);\r\n viewer.snapToFolder(folderAssetIds);\r\n }\r\n\r\n dispatch(setVisibleFolder(folderID));\r\n };\r\n\r\n const isSelected = (folderID) => {\r\n const folderAssets = assets.filter(x => x.folderID === folderID);\r\n const numFolderAssets = folderAssets.length;\r\n const numVisible = folderAssets.filter(x => x.visible).length;\r\n const numAssetsVisible = assets.filter(x => x.visible).length;\r\n\r\n return (numFolderAssets === numVisible)\r\n && (numVisible === numAssetsVisible);\r\n };\r\n\r\n // Only folders with assets inside are visible\r\n const folderOptions = folders.filter(folder => {\r\n const items = assets.filter(x => x.folderID === folder.id);\r\n return items.length > 0;\r\n });\r\n\r\n const openNav = globalSettings.openQuickNav\r\n && (folderOptions.length > 1);\r\n\r\n return (\r\n \r\n {openNav && (\r\n
\r\n
\r\n \r\n \r\n {t(\"quick-nav.title\")}\r\n \r\n\r\n \r\n {folderOptions.map((folder, index) => {\r\n const localizedFolderName = getLocalizedFolderName(folder.name);\r\n\r\n return (\r\n onClick(folder.id)}\r\n selected={isSelected(folder.id)}\r\n >\r\n {localizedFolderName}\r\n \r\n );\r\n })}\r\n \r\n \r\n
\r\n
\r\n )}\r\n
\r\n );\r\n});","import {app, fs, fse, isDevMode} from '../../electron-modules';\r\nimport path from \"path\";\r\nimport {pathWithExtension} from \"../../utilities\";\r\nimport LocalScene from \"../../viewer/projections\";\r\nimport slash from \"slash\";\r\nimport {Asset, AssetType, CameraData} from \"../../redux/assets-slice\";\r\nimport {t} from \"../../localization\";\r\nimport { PythonExecutable } from '../../executable';\r\n\r\nexport const deleteFolder = async (folderPath: string) => {\r\n try {\r\n await fse.remove(folderPath);\r\n } catch {}\r\n};\r\n\r\nexport const createNewFolder = async (folderPath: string) => {\r\n await deleteFolder(folderPath);\r\n await fse.mkdirs(folderPath);\r\n};\r\n\r\nexport const moveCameraData = async (asset: Asset, dataPath: string) => {\r\n const imagesPath = path.join(dataPath, asset.id);\r\n\r\n await createNewFolder(imagesPath);\r\n\r\n const imagesData = asset.data as CameraData[];\r\n for (let i= 0; i < imagesData.length; i++) {\r\n const imageData = imagesData[i];\r\n const imageName = path.basename(imageData.path);\r\n const newImagePath = path.join(imagesPath, imageName);\r\n\r\n if (fs.existsSync(imageData.path)) {\r\n await fse.copy(imageData.path, newImagePath);\r\n }\r\n }\r\n};\r\n\r\n/** Execute python function to copy folders instead. Nodejs is\r\n * very slow and has issues with large files */\r\nexport const moveStreamablePointsData = async (asset: Asset,\r\n dataPath: string, exe: PythonExecutable) => {\r\n const inputPath = asset.path;\r\n const outputPath = path.join(dataPath, asset.id);\r\n\r\n return new Promise((resolve) => {\r\n let commands = [\r\n \"-p\", \"copy_folder\",\r\n \"--input_folder\", inputPath,\r\n \"--output_folder\", outputPath\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n onClose: async () => {\r\n resolve(true);\r\n }\r\n });\r\n });\r\n};\r\n\r\nexport const moveGenericPointCloud = async (asset: Asset, dataPath: string,\r\n exe: PythonExecutable, onLogs, singleFileOutput: boolean) => {\r\n const inputPath = asset.path;\r\n const pointPath = path.join(dataPath, asset.id);\r\n\r\n return new Promise((resolve) => {\r\n let commands = [\r\n \"-p\", \"process_las\",\r\n \"--input_path\", inputPath,\r\n \"--output_folder\", pointPath,\r\n \"--single_file\", singleFileOutput,\r\n \"--units\", LocalScene.dataProjectionUnits\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLogs: onLogs,\r\n onClose: async () => {\r\n resolve(true);\r\n }\r\n });\r\n });\r\n};\r\n\r\nexport const getBuildPath = () => {\r\n const appPath = slash(app.getAppPath());\r\n\r\n return isDevMode\r\n ? path.join(appPath, \"build\")\r\n : path.join(path.dirname(appPath), \"app.asar.unpacked\", \"build\");\r\n};\r\n\r\nexport const getMiniViewerPath = () => {\r\n const appPath = slash(app.getAppPath());\r\n return isDevMode\r\n ? path.join(appPath, \"miniviewer.exe\")\r\n : path.join(path.dirname(appPath), \"app.asar.unpacked\", \"miniviewer.exe\");\r\n};\r\n\r\nexport const moveModelData = async (asset: Asset, dataPath: string, onExportError) => {\r\n const outputFolder = path.join(dataPath, asset.id);\r\n const modelName = path.basename(asset.path);\r\n const copyToFile = async (asset, inputPath, outputPath) => {\r\n try {\r\n await fse.copy(inputPath, outputPath);\r\n } catch {\r\n onExportError(\r\n t(\"dialog.general-error-title\"),\r\n t(\"dialog.export-error-generic\", {name: asset.name})\r\n );\r\n return;\r\n }\r\n };\r\n\r\n await createNewFolder(outputFolder);\r\n\r\n if (asset.type === AssetType.SHP) {\r\n const shpInput = pathWithExtension(asset.path, \"shp\");\r\n const shpOutput = path.join(outputFolder, pathWithExtension(modelName, \"shp\"));\r\n await copyToFile(asset, shpInput, shpOutput);\r\n\r\n const dbfInput = pathWithExtension(asset.path, \"dbf\");\r\n const dbfOutput = path.join(outputFolder, pathWithExtension(modelName, \"dbf\"));\r\n await copyToFile(asset, dbfInput, dbfOutput);\r\n } else {\r\n const inputPath = asset.path;\r\n const outputPath = path.join(outputFolder, modelName);\r\n await copyToFile(asset, inputPath, outputPath);\r\n }\r\n};","import path from \"path\";\r\nimport {Asset, AssetType} from \"../../redux/assets-slice\";\r\nimport {fse} from \"../../electron-modules\";\r\nimport {isModelFile, isRawPointsFile, isStreamablePointsFile} from \"../utils/misc\";\r\nimport {\r\n moveCameraData,\r\n moveModelData,\r\n moveGenericPointCloud,\r\n moveStreamablePointsData\r\n} from \"./utils\";\r\nimport { PythonExecutable } from \"../../executable\";\r\nimport { asyncTimeout } from \"../../utilities\";\r\n\r\nconst assetsFolder = \"assets\";\r\nconst processTimeout = 1000;\r\n\r\nconst getAssetIndex = (state, asset) => {\r\n const assetIds = state.assets.map(x => x.id);\r\n return assetIds.indexOf(asset.id);\r\n};\r\n\r\nexport const updateCameraDataState = (asset, state) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n const imagesData = asset.data;\r\n imagesData.forEach((imageData, imageIndex) => {\r\n const imageName = path.basename(imageData.path);\r\n const finalPath = path.join(assetsFolder, asset.id, imageName);\r\n state.assets[assetIndex].data[imageIndex].path = `./${finalPath}`;\r\n });\r\n};\r\n\r\nexport const updateModelDataState = (asset, state) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n const modelName = path.basename(asset.path);\r\n const finalPath = path.join(assetsFolder, asset.id, modelName);\r\n state.assets[assetIndex].path = `./${finalPath}`;\r\n};\r\n\r\nexport const updateStreamablePointsState = (asset, state) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n const finalPath = path.join(assetsFolder, asset.id);\r\n state.assets[assetIndex].path = `./${finalPath}`;\r\n};\r\n\r\nexport const updateRawPointsState = (asset, state, singleFileOutput) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n\r\n const finalPath = singleFileOutput\r\n ? path.join(assetsFolder, asset.id)\r\n : path.join(assetsFolder, asset.id, \"points\");\r\n\r\n state.assets[assetIndex].path = `./${finalPath}`;\r\n state.assets[assetIndex].type = singleFileOutput\r\n ? AssetType.Potree\r\n : AssetType.Encompass;\r\n};\r\n\r\nexport const updateCameraTransformPath = (state, outputPath) => {\r\n const dataPath = path.join(outputPath, assetsFolder);\r\n\r\n const outputName = \"camera.4x4\";\r\n const matrixPath = state.camera.transform;\r\n const newImagePath = path.join(dataPath, outputName);\r\n\r\n if (matrixPath) {\r\n fse.copy(matrixPath, newImagePath);\r\n const finalPath = path.join(assetsFolder, outputName);\r\n state.camera.transform = `./${finalPath}`;\r\n }\r\n};\r\n\r\nexport const moveAssetData = async (asset: Asset, outputPath: string,\r\n exe: PythonExecutable, onLogs, singleFileOutput, handleExportError) => {\r\n const dataPath = path.join(outputPath, assetsFolder);\r\n\r\n if (isStreamablePointsFile(asset)) {\r\n await moveStreamablePointsData(asset, dataPath, exe);\r\n } else if (isRawPointsFile(asset)) {\r\n await moveGenericPointCloud(asset, dataPath, exe, onLogs, singleFileOutput);\r\n } else if (asset.type === AssetType.Panoramic) {\r\n await moveCameraData(asset, dataPath);\r\n } else if (asset.type === AssetType.Planar) {\r\n await moveCameraData(asset, dataPath);\r\n } else if (isModelFile(asset)) {\r\n await moveModelData(asset, dataPath, handleExportError);\r\n }\r\n\r\n await asyncTimeout(processTimeout);\r\n};","import {createNewFolder, deleteFolder, getBuildPath, getMiniViewerPath} from \"./utils\";\r\nimport path from \"path\";\r\nimport {t} from \"../../localization\";\r\nimport {fs, fse} from \"../../electron-modules\";\r\nimport {Asset, AssetType} from \"../../redux/assets-slice\";\r\nimport {\r\n moveAssetData,\r\n updateCameraDataState, updateCameraTransformPath,\r\n updateModelDataState,\r\n updateRawPointsState,\r\n updateStreamablePointsState\r\n} from \"./state\";\r\nimport {isModelFile, isRawPointsFile, isStreamablePointsFile} from \"../utils/misc\";\r\nimport { cloneDeep } from \"lodash\";\r\nimport { PythonExecutable } from \"../../executable\";\r\nimport { ProjectType } from \"../../types/project\";\r\nimport { GlobalSettingsState } from \"../../providers\";\r\n\r\n\r\ninterface ExporterOpts {\r\n name: string;\r\n outputPath: string;\r\n assets: Asset[];\r\n singleFileOutput: boolean;\r\n state: any;\r\n globalSettings: GlobalSettingsState;\r\n onError?(title: string, message: string): void;\r\n onUpdate?(message: string): void;\r\n onLogs?(message: string): void;\r\n onProgress?(percent: number): void;\r\n onFinish?(): void;\r\n onCancel?(): void;\r\n}\r\n\r\nconst exporterOptsDefaults = {\r\n onError: () => {},\r\n onUpdate: () => {},\r\n onLogs: () => {},\r\n onProgress: () => {},\r\n onFinish: () => {},\r\n onCancel: () => {}\r\n};\r\nconst assetsFolder = \"assets\";\r\n\r\nexport const getStaticExporter = (): [(opts: ExporterOpts) => Promise, () => Promise] => {\r\n const exe = new PythonExecutable();\r\n const buildPath = getBuildPath();\r\n let cancelFlag = false;\r\n\r\n const cancel = async (webOutputPath) => {\r\n await deleteFolder(webOutputPath);\r\n cancelFlag = false;\r\n };\r\n\r\n const startExport = async (opts: ExporterOpts) => {\r\n opts = {...exporterOptsDefaults, ...opts};\r\n\r\n const rootOutputPath = path.join(opts.outputPath, opts.name);\r\n const webOutputPath = path.join(rootOutputPath, \"web\");\r\n const dataPath = path.join(webOutputPath, assetsFolder);\r\n\r\n opts.onUpdate(t('export.creating-output-folder'));\r\n await createNewFolder(rootOutputPath);\r\n await createNewFolder(webOutputPath);\r\n\r\n opts.onUpdate(t('export.copy-html-files-output-folder'));\r\n try {\r\n await fse.copy(buildPath, webOutputPath);\r\n } catch(err) {\r\n opts.onError(t(\"dialog.general-error-title\"), t(\"dialog.export-error-static\"));\r\n return;\r\n }\r\n\r\n opts.onUpdate(t('export.preparing-data-to-export'));\r\n await createNewFolder(dataPath);\r\n\r\n for (const [index, asset] of opts.assets.entries()) {\r\n opts.onUpdate(t(\"export.processing-data\", {name: asset.name}));\r\n\r\n await moveAssetData(asset, webOutputPath, exe, opts.onLogs,\r\n opts.singleFileOutput, opts.onError);\r\n\r\n const percent = 100.0 * (index + 1) / opts.assets.length;\r\n opts.onProgress(percent);\r\n\r\n if (cancelFlag) {\r\n await cancel(webOutputPath);\r\n opts.onCancel();\r\n return;\r\n }\r\n }\r\n\r\n opts.onUpdate(t('export.export-project-state'));\r\n\r\n const state = cloneDeep(opts.state);\r\n\r\n // Update project type\r\n state.project.type = ProjectType.Static;\r\n\r\n opts.assets.forEach(asset => {\r\n if (isStreamablePointsFile(asset)) {\r\n updateStreamablePointsState(asset, state);\r\n } else if (isRawPointsFile(asset)) {\r\n updateRawPointsState(asset, state, opts.singleFileOutput);\r\n } else if (asset.type === AssetType.Panoramic || asset.type === AssetType.Planar) {\r\n updateCameraDataState(asset, state);\r\n } else if (isModelFile(asset)) {\r\n updateModelDataState(asset, state);\r\n }\r\n });\r\n\r\n // Update camera transform path\r\n updateCameraTransformPath(state, webOutputPath);\r\n\r\n const miniViewerPath = getMiniViewerPath();\r\n const exeOutputPath = path.join(rootOutputPath, path.basename(miniViewerPath));\r\n fs.copyFileSync(miniViewerPath, exeOutputPath);\r\n\r\n // Write global settings\r\n const globalSettingsPath = path.join(\r\n webOutputPath, \"global-settings.json\");\r\n const content = JSON.stringify(opts.globalSettings, null, 2);\r\n fs.writeFileSync(globalSettingsPath, content);\r\n\r\n // Write final config file\r\n try {\r\n const projectJson = JSON.stringify(state, null, 2);\r\n const projectPath = path.join(webOutputPath, \"static.json\");\r\n await fse.writeFile(projectPath, projectJson);\r\n } catch (err) {\r\n opts.onError(t(\"dialog.general-error-title\"), t(\"dialog.export-error-static\"));\r\n return;\r\n }\r\n\r\n if (!cancelFlag) {\r\n opts.onFinish();\r\n } else {\r\n await cancel(webOutputPath);\r\n opts.onCancel();\r\n }\r\n };\r\n\r\n const cancelExport = async () => {\r\n cancelFlag = true;\r\n exe.destroy();\r\n };\r\n\r\n return [startExport, cancelExport];\r\n};","import React from 'react';\r\nimport { useTheme, ListItem } from \"@mui/material\";\r\nimport WarningIcon from '@mui/icons-material/Warning';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport {\r\n AssetType,\r\n CameraData,\r\n getCameraFileAssets,\r\n getLandXMLAssets,\r\n getModelAssets,\r\n getOrthoAssets,\r\n getPointCloudAssets,\r\n getTagAssets,\r\n getWebMapAssets,\r\n selectAllAssets,\r\n TagData\r\n} from \"../redux/assets-slice\";\r\nimport { ArrowTooltip } from '../components';\r\nimport { useSelector } from 'react-redux';\r\n\r\ninterface BulletListItemProps {\r\n children: React.ReactNode\r\n}\r\n\r\nconst BulletListItem = (props: BulletListItemProps) => {\r\n const theme = useTheme();\r\n\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport const NewProjectInfo = () => {\r\n const assets = useSelector(selectAllAssets);\r\n const orthoFiles = getOrthoAssets(assets);\r\n const pointClouds = getPointCloudAssets(assets);\r\n const cameraFiles = getCameraFileAssets(assets);\r\n const modelFiles = getModelAssets(assets);\r\n const landXMLFiles = getLandXMLAssets(assets);\r\n const webmapSources = getWebMapAssets(assets);\r\n const tagFiles = getTagAssets(assets);\r\n\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n\r\n const numGenericPointCloud = pointClouds.filter(asset => {\r\n return (asset.type === AssetType.LAS)\r\n || (asset.type === AssetType.E57Points);\r\n }).length;\r\n\r\n let numberOfImages = 0;\r\n cameraFiles.forEach(cameraAsset => {\r\n const images = (cameraAsset.data as CameraData[]);\r\n numberOfImages += images.length;\r\n });\r\n\r\n let numberOfTags = 0;\r\n tagFiles.forEach(tagAsset => {\r\n const tags = (tagAsset.data as TagData).items;\r\n numberOfTags += tags.length;\r\n });\r\n\r\n return (\r\n \r\n {(pointClouds.length > 0) && (\r\n \r\n {t(\"export.asset-points\", {\r\n count: pointClouds.length\r\n })}\r\n\r\n {(numGenericPointCloud > 0) && (\r\n \r\n \r\n \r\n )}\r\n \r\n )}\r\n\r\n {(numberOfImages > 0) && (\r\n \r\n {t(\"export.asset-camera\", {\r\n count: numberOfImages\r\n })}\r\n \r\n )}\r\n\r\n {(numberOfTags > 0) && (\r\n \r\n {t(\"export.asset-tags\", {\r\n count: numberOfTags\r\n })}\r\n \r\n )}\r\n\r\n {(orthoFiles.length > 0) && (\r\n \r\n {t(\"export.asset-orthos\", {\r\n count: orthoFiles.length\r\n })}\r\n \r\n )}\r\n\r\n {(modelFiles.length > 0) && (\r\n \r\n {t(\"export.asset-models\", {\r\n count: modelFiles.length\r\n })}\r\n \r\n )}\r\n\r\n {(webmapSources.length > 0) && (\r\n \r\n {t(\"export.asset-webmap\", {\r\n count: webmapSources.length\r\n })}\r\n \r\n )}\r\n\r\n {(landXMLFiles.length > 0) && (\r\n \r\n {t(\"export.asset-landxml\", {\r\n count: landXMLFiles.length\r\n })}\r\n \r\n )}\r\n\r\n \r\n );\r\n};\r\n","import React, {useCallback, useEffect, useMemo, useState} from 'react';\r\nimport {dialog, registerEvent} from '../../electron-modules';\r\nimport {store} from '../../redux/store';\r\nimport {\r\n AssetType,\r\n getCameraFileAssets,\r\n getModelAssets,\r\n getPointCloudAssets,\r\n selectAllAssets\r\n} from '../../redux/assets-slice';\r\nimport {trackToolUsage} from '../../executable';\r\nimport {useSelector} from 'react-redux';\r\nimport {\r\n Button,\r\n CircularProgress,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n Grid,\r\n Theme,\r\n Typography,\r\n useTheme,\r\n} from '@mui/material';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n AlertDialog,\r\n CheckboxWithLabel,\r\n FolderWithLabel,\r\n LinearProgressWithLabel,\r\n SimpleDialog,\r\n} from '../../components';\r\nimport sanitize from \"sanitize-filename\";\r\nimport {selectProjectName} from '../../redux/project-slice';\r\nimport {toast} from '../../app';\r\nimport {useTranslation} from 'react-i18next';\r\nimport {getStaticExporter} from \"./exporter\";\r\nimport {useDialog, useGlobalSettings} from \"../../hooks\";\r\nimport {getLocalizedProjectName} from '../../utilities';\r\nimport {throttle} from 'throttle-debounce';\r\nimport { NewProjectInfo } from '../common';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n warning: {\r\n color: theme.palette.warning.main\r\n },\r\n exportText: {\r\n padding: theme.spacing(1)\r\n },\r\n contentCenter: {\r\n textAlign: \"center\"\r\n },\r\n cancelProgress: {\r\n marginRight: theme.spacing(1)\r\n },\r\n cancelContent: {\r\n paddingBottom: theme.spacing(3)\r\n },\r\n paddingTop: {\r\n paddingTop: theme.spacing(3)\r\n },\r\n listItem: {\r\n width: '100%',\r\n marginTop: theme.spacing(2)\r\n },\r\n switchLabel: {\r\n display: \"inline-block\",\r\n maxWidth: \"calc(100% - 50px)\"\r\n },\r\n switchElement: {\r\n float: \"right\"\r\n },\r\n outputFolder: {\r\n marginTop: theme.spacing(2)\r\n },\r\n dropdown: {\r\n width: \"40%\"\r\n },\r\n header: {\r\n marginTop: theme.spacing(1)\r\n }\r\n }),\r\n);\r\n\r\nexport const StaticExporter = () => {\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const {t} = useTranslation();\r\n const exporterDialog = useDialog();\r\n const messageDialog = useDialog();\r\n const successDialog = useDialog();\r\n const cancelDialog = useDialog();\r\n\r\n const projectName = useSelector(selectProjectName);\r\n const assets = useSelector(selectAllAssets);\r\n const pointClouds = getPointCloudAssets(assets);\r\n const camerasFiles = getCameraFileAssets(assets);\r\n const modelFiles = getModelAssets(assets);\r\n\r\n const [outputPath, setOutputPath] = useState(null);\r\n const [singleFileOutput, setSingleFileOutput] = useState(true);\r\n const [exportTopMessage, setExportTopMessage] = useState(\"\");\r\n const [exportBottomMessage, setExportBottomMessage] = useState(\"\");\r\n const [exportPercent, updateExportPercent] = useState(0);\r\n const [isExportRunning, setIsExportRunning] = useState(false);\r\n const globalSettings = useGlobalSettings();\r\n\r\n const [startExport, cancelExport] = useMemo(getStaticExporter, []);\r\n\r\n const progressThrottleMilliseconds = 100;\r\n\r\n const setExportPercent = useCallback(throttle(\r\n progressThrottleMilliseconds, (value) => {\r\n updateExportPercent(value);\r\n }), []);\r\n\r\n const canExport = assets.length > 0;\r\n\r\n const numGenericPointCloud = pointClouds.filter(asset => {\r\n return (asset.type === AssetType.LAS)\r\n || (asset.type === AssetType.E57Points);\r\n }).length;\r\n\r\n const onExportFinished = () => {\r\n setIsExportRunning(false);\r\n messageDialog.handleClose();\r\n };\r\n\r\n const handleExportCancel = () => {\r\n onExportFinished();\r\n cancelDialog.handleOpen();\r\n cancelExport();\r\n };\r\n\r\n const handleExport = () => {\r\n exporterDialog.handleClose();\r\n exportToStatic();\r\n };\r\n\r\n const setExportMessage = (top = \"\", bottom = \"\") => {\r\n setExportTopMessage(top);\r\n setExportBottomMessage(bottom);\r\n };\r\n\r\n const exportToStatic = async () => {\r\n trackToolUsage(\"exporter\");\r\n\r\n setExportPercent(0);\r\n setExportMessage();\r\n messageDialog.handleOpen();\r\n\r\n const assets = [\r\n ...pointClouds,\r\n ...camerasFiles,\r\n ...modelFiles\r\n ];\r\n\r\n await startExport({\r\n name: exportName,\r\n outputPath: outputPath,\r\n assets: assets,\r\n singleFileOutput: singleFileOutput,\r\n state: store.getState(),\r\n globalSettings: globalSettings.getState(),\r\n onUpdate: setExportMessage,\r\n onLogs: setExportBottomMessage,\r\n onProgress: setExportPercent,\r\n onError: (title, message) => {\r\n onExportFinished();\r\n dialog.showErrorBox(title, message);\r\n },\r\n onFinish: () => {\r\n onExportFinished();\r\n successDialog.handleOpen();\r\n },\r\n onCancel: () => {\r\n setIsExportRunning(false);\r\n cancelDialog.handleClose();\r\n }\r\n });\r\n };\r\n\r\n const resetDefaults = () => {\r\n setOutputPath(null);\r\n setSingleFileOutput(true);\r\n };\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-static-export\", () => {\r\n if (!canExport) return toast.error(t(\"toast.no-data-loaded\"));\r\n exporterDialog.handleOpen();\r\n });\r\n }, [canExport]);\r\n\r\n useEffect(() => {\r\n if (!exporterDialog.open) return;\r\n resetDefaults();\r\n }, [exporterDialog.open]);\r\n\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n const sanitizedName = sanitize(localizedProjectName);\r\n const exportName = t('export.export-name', {name: sanitizedName});\r\n\r\n return (\r\n \r\n {/* Exporting dialog */}\r\n \r\n {t('export.export-status')}\r\n\r\n \r\n \r\n {exportTopMessage}\r\n \r\n\r\n \r\n {exportBottomMessage}\r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n {t('export.cancel-export')}\r\n \r\n \r\n \r\n\r\n {/* Main dialog */}\r\n \r\n \r\n\r\n {/* Export file type(s) info */}\r\n \r\n \r\n\r\n \r\n \r\n\r\n {/* Point cloud export version */}\r\n {(numGenericPointCloud > 0) && (\r\n \r\n \r\n \r\n )}\r\n\r\n {/* Output Folder */}\r\n \r\n \r\n \r\n\r\n \r\n \r\n\r\n {/* Cancelling dialog */}\r\n \r\n {t('export.data-export')}\r\n \r\n \r\n \r\n {t('export.cancelling-export')}\r\n \r\n \r\n \r\n\r\n {/* Success dialog */}\r\n \r\n \r\n {t('export.successfully-exported-data')}\r\n \r\n \r\n \r\n );\r\n};","import {Asset, AssetType, TagData, WebSourceAsset, XMLData} from \"../../redux/assets-slice\";\r\nimport { Bookmark } from \"../../redux/bookmarks-slice\";\r\nimport {t} from \"../../localization\";\r\nimport path from \"path\";\r\nimport LocalScene from \"../../viewer/projections\";\r\nimport { fse, getTemporaryFile } from \"../../electron-modules\";\r\nimport { PythonExecutable } from \"../../executable\";\r\nimport { getLocalizedProjectName, getMatrixValues, pathWithExtension } from \"../../utilities\";\r\nimport { engineCloudURL } from \"../../urls\";\r\nimport { CustomURL } from \"../../redux/custom-links-slice\";\r\nimport {\r\n getBaseAsset,\r\n getTagsData,\r\n getImageData,\r\n getModelLayers,\r\n getWebmapLayers,\r\n withOriginalID\r\n} from \"../utils/misc\";\r\nimport manifest from \"../../../package.json\";\r\nimport { GlobalSettingsState } from \"../../providers\";\r\nimport { Folder } from \"../../redux/folders-slice\";\r\n\r\nconst SHP_FILE_TYPES = [\"shp\", \"dbf\"];\r\nconst POTREE_FILES = ['hierarchy.bin', 'octree.bin', 'metadata.json'];\r\n\r\ninterface ExporterOpts {\r\n name: string;\r\n assets: Asset[];\r\n state: any;\r\n globalSettings: GlobalSettingsState;\r\n update: boolean;\r\n appCode: string;\r\n onError?(title: string, message: string): void;\r\n onStart?(statuses: {}): void;\r\n onUpdate?(statuses: {}): void;\r\n onProgress?(percent: number): void;\r\n onFinish?(projectID: string): void;\r\n}\r\n\r\nconst exporterOptsDefaults = {\r\n onError: () => {},\r\n onStart: () => {},\r\n onUpdate: () => {},\r\n onProgress: () => {},\r\n onFinish: () => {}\r\n};\r\n\r\nconst createProject = async (state, globalSettings: GlobalSettingsState, update: boolean): Promise => {\r\n const folders = state.folders.map((folder: Folder) => {\r\n const assets = state.assets\r\n .filter(asset => asset.folderID === folder.id) as Asset[];\r\n\r\n const tags = assets\r\n .filter(asset => asset.type === AssetType.Tag)\r\n .map(tagAsset => ({\r\n ...getBaseAsset(tagAsset),\r\n texture: (tagAsset.data as TagData).texture,\r\n size: (tagAsset.data as TagData).size,\r\n tags: getTagsData(tagAsset)\r\n }));\r\n\r\n const panoramics = assets\r\n .filter(asset => asset.type === AssetType.Panoramic)\r\n .map(panoAsset => ({\r\n ...getBaseAsset(panoAsset),\r\n images: getImageData(panoAsset)\r\n }));\r\n\r\n const planars = assets\r\n .filter(asset => asset.type === AssetType.Planar)\r\n .map(panoAsset => ({\r\n ...getBaseAsset(panoAsset),\r\n images: getImageData(panoAsset)\r\n }));\r\n\r\n const pointClouds = assets\r\n .filter(asset => {\r\n return (asset.type === AssetType.LAS)\r\n || (asset.type === AssetType.E57Points)\r\n || (asset.type === AssetType.Potree);\r\n })\r\n .map(pointCloudAsset => ({\r\n ...getBaseAsset(pointCloudAsset),\r\n type: AssetType.Potree\r\n }));\r\n\r\n const orthomosaics = assets\r\n .filter(asset => asset.type === AssetType.OrthoMosaic)\r\n .map(orthoAsset => ({\r\n ...getBaseAsset(orthoAsset),\r\n imageData: orthoAsset.data\r\n }));\r\n\r\n const landxmls = assets\r\n .filter(asset => asset.type === AssetType.LandXML)\r\n .map(landXMLAsset => ({\r\n ...getBaseAsset(landXMLAsset),\r\n ...(landXMLAsset.data as XMLData)\r\n }));\r\n\r\n const ifcFiles = assets\r\n .filter(asset => asset.type === AssetType.IFC)\r\n .map(ifcAsset => ({\r\n ...getBaseAsset(ifcAsset),\r\n fileName: path.basename(ifcAsset.path)\r\n }));\r\n\r\n const shpFiles = assets\r\n .filter(asset => asset.type === AssetType.SHP)\r\n .map(shpAsset => ({\r\n ...getBaseAsset(shpAsset),\r\n fileName: path.basename(shpAsset.path),\r\n layers: getModelLayers(shpAsset)\r\n }));\r\n\r\n const dxfFiles = assets\r\n .filter(asset => asset.type === AssetType.DXF)\r\n .map(dxfAsset => ({\r\n ...getBaseAsset(dxfAsset),\r\n fileName: path.basename(dxfAsset.path),\r\n layers: getModelLayers(dxfAsset)\r\n }));\r\n\r\n const webmapSources = assets\r\n .filter(asset => asset.type === AssetType.Webmap)\r\n .map((webmapAsset: WebSourceAsset) => ({\r\n ...getBaseAsset(webmapAsset),\r\n url: webmapAsset.data.url,\r\n map_type: webmapAsset.data.type,\r\n public: webmapAsset.data.public,\r\n layers: getWebmapLayers(webmapAsset)\r\n }));\r\n\r\n return {\r\n name: folder.name,\r\n originalId: folder.id,\r\n default: folder.default,\r\n allowAnonViewers: folder.allowAnonViewers,\r\n assets: {\r\n tags,\r\n panoramics,\r\n planars,\r\n pointClouds,\r\n orthomosaics,\r\n landxmls,\r\n ifcFiles,\r\n shpFiles,\r\n dxfFiles,\r\n webmapSources\r\n }\r\n };\r\n });\r\n\r\n const projections = {\r\n data: {\r\n type: state.projections.data.type,\r\n name: state.projections.data.name,\r\n default: state.projections.data.default,\r\n string: state.projections.data.string,\r\n transform: state.projections.data.transform\r\n },\r\n view: {\r\n type: state.projections.view.type,\r\n name: state.projections.view.name,\r\n default: state.projections.view.default,\r\n string: state.projections.view.string,\r\n transform: state.projections.view.transform\r\n }\r\n };\r\n\r\n const bookmarks = state.bookmarks.map((bookmark: Bookmark) => {\r\n return withOriginalID(bookmark);\r\n });\r\n\r\n const customLinks = state.custom_links.map((link: CustomURL) => {\r\n return withOriginalID(link);\r\n });\r\n\r\n const {success, rotation, offset}\r\n = await getMatrixValues(state.camera.transform);\r\n\r\n const transform = success ? {\r\n rotation: rotation.toArray(),\r\n translation: offset.toArray()\r\n } : null;\r\n\r\n const adjustments = Object.keys(state.camera.adjustments).map(camera => {\r\n const rotation = state.camera.adjustments[camera];\r\n return {camera, rotation};\r\n });\r\n\r\n const cameraState = {\r\n transform: transform,\r\n adjustments: adjustments,\r\n height: state.camera.height,\r\n aerialState: state.camera.aerialState,\r\n sceneState: state.camera.sceneState\r\n };\r\n\r\n const method = update ? \"PUT\" : \"POST\";\r\n const localizedProjectName = getLocalizedProjectName(state.project.name);\r\n\r\n const projectState = JSON.stringify({\r\n name: localizedProjectName,\r\n originalId: state.project.id,\r\n settings: state.settings,\r\n appVersion: manifest.version,\r\n configVersion: state.project.configVersion,\r\n measurementUnits: state.projections.measureUnits,\r\n folders,\r\n bookmarks,\r\n customLinks,\r\n projections,\r\n cameraState,\r\n globalSettings\r\n });\r\n\r\n const body = new Blob([projectState], {\r\n type: 'text/plain'\r\n });\r\n\r\n const request = await fetch(`${engineCloudURL}/api/projects`, {\r\n method,\r\n body,\r\n headers: {\r\n 'Content-Type': 'application/json'\r\n }\r\n });\r\n\r\n const response = await request.json();\r\n\r\n return response;\r\n};\r\n\r\ninterface UploadItem {\r\n id: string;\r\n url: string;\r\n paths: string[];\r\n name: string;\r\n processPoints?: boolean;\r\n units?: string;\r\n}\r\n\r\nconst getAssetsToUpload = (project, opts) => {\r\n const projectID = project.id;\r\n const uploadList: UploadItem[] = [];\r\n\r\n project.uploads.forEach(({uploadId, originalId}) => {\r\n const asset = opts.state.assets.find(asset => asset.id === originalId);\r\n\r\n if ((asset.type === AssetType.Panoramic) || (asset.type === AssetType.Planar)) {\r\n asset.data.forEach(image => {\r\n uploadList.push({\r\n id: image.id,\r\n url: getUploadURL(projectID, uploadId),\r\n paths: [image.path],\r\n name: image.name\r\n });\r\n });\r\n }\r\n\r\n if ((asset.type === AssetType.LAS) || (asset.type === AssetType.E57Points)) {\r\n uploadList.push({\r\n id: asset.id,\r\n url: getUploadURL(projectID, uploadId),\r\n paths: [asset.path],\r\n name: asset.name,\r\n processPoints: true,\r\n units: LocalScene.dataProjectionUnits\r\n });\r\n }\r\n\r\n if (asset.type === AssetType.Potree) {\r\n uploadList.push({\r\n id: asset.id,\r\n url: getUploadURL(projectID, uploadId),\r\n paths: POTREE_FILES.map(filePath => `${asset.path}/${filePath}`),\r\n name: asset.name,\r\n });\r\n }\r\n\r\n if ((asset.type === AssetType.IFC) || (asset.type === AssetType.DXF)) {\r\n uploadList.push({\r\n id: asset.id,\r\n url: getUploadURL(projectID, uploadId),\r\n paths: [asset.path],\r\n name: asset.name\r\n });\r\n }\r\n\r\n if (asset.type === AssetType.SHP) {\r\n uploadList.push({\r\n id: asset.id,\r\n url: getUploadURL(projectID, uploadId),\r\n paths: SHP_FILE_TYPES.map(fileType => pathWithExtension(asset.path, fileType)),\r\n name: asset.name,\r\n });\r\n }\r\n });\r\n\r\n return uploadList;\r\n};\r\n\r\nconst getUploadURL = (projectID, assetID) => {\r\n return `${engineCloudURL}/api/projects/${projectID}/assets/${assetID}/files`;\r\n};\r\n\r\nexport const getCloudExporter = () => {\r\n let projectID;\r\n let statuses = {};\r\n\r\n const exe = new PythonExecutable();\r\n\r\n const startExport = async (opts: ExporterOpts) => {\r\n opts = {...exporterOptsDefaults, ...opts};\r\n\r\n const response = await createProject(\r\n opts.state, opts.globalSettings, opts.update);\r\n\r\n if (response.detail) {\r\n // Error creating project (incorrect values in project state)\r\n opts.onError(t(\"dialog.general-error-title\"), t(\"dialog.export-error-cloud\"));\r\n return;\r\n }\r\n\r\n if (response.version_mismatch) {\r\n // Config version is lower than required server version\r\n opts.onError(t(\"dialog.general-error-title\"), t('export.version_mismatch', {\r\n current: manifest.version,\r\n server: response.minimum_version\r\n }));\r\n return;\r\n }\r\n\r\n projectID = response.id;\r\n\r\n const assets = getAssetsToUpload(response, opts);\r\n if (assets.length === 0) {\r\n opts.onFinish(projectID);\r\n return;\r\n }\r\n\r\n // Save assets to temporary json file\r\n const tempOutputPath = getTemporaryFile(\"json\");\r\n const text = JSON.stringify(assets, null, 2);\r\n await fse.writeFile(tempOutputPath, text);\r\n\r\n let commands = [\r\n \"-p\", \"upload_engine_assets\",\r\n \"--engine_cloud_url\", engineCloudURL,\r\n \"--input_path\", tempOutputPath,\r\n \"--app_code\", opts.appCode\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (jsonData.progress) {\r\n opts.onProgress(jsonData.progress);\r\n }\r\n\r\n if (jsonData.start) {\r\n statuses = jsonData.start;\r\n opts.onStart(statuses);\r\n }\r\n\r\n if (jsonData.update) {\r\n const status = jsonData.update;\r\n\r\n try {\r\n statuses[status.id].status_code = status.status_code;\r\n opts.onUpdate(statuses);\r\n } catch {\r\n console.warn(\"Error updating status row\");\r\n }\r\n }\r\n },\r\n onClose: (error) => {\r\n if (error) return;\r\n opts.onFinish(projectID);\r\n }\r\n });\r\n };\r\n\r\n const cancelExport = (update: boolean) => {\r\n exe.destroy();\r\n\r\n if (update || !projectID) {\r\n return;\r\n }\r\n\r\n fetch(`${engineCloudURL}/api/projects/${projectID}`, {\r\n method: 'DELETE',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n }).then(() => {\r\n projectID = null;\r\n });\r\n };\r\n\r\n return {\r\n startExport,\r\n cancelExport\r\n };\r\n};","export enum StatusCode {\r\n Preparing = 0,\r\n Uploading = 1,\r\n Queued = 2,\r\n Uploaded = 3,\r\n Errored = 4\r\n}","import React, {useCallback, useEffect, useMemo, useState} from 'react';\r\nimport {dialog, registerEvent} from '../../electron-modules';\r\nimport {store} from '../../redux/store';\r\nimport {\r\n getCameraFileAssets,\r\n getModelAssets,\r\n getPointCloudAssets,\r\n selectAllAssets\r\n} from '../../redux/assets-slice';\r\nimport {trackToolUsage} from '../../executable';\r\nimport {useSelector} from 'react-redux';\r\nimport {\r\n Button,\r\n CircularProgress,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n Grid,\r\n Theme,\r\n Typography,\r\n useTheme,\r\n} from '@mui/material';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n DenseDivider,\r\n EnhancedTable,\r\n LinearProgressWithLabel,\r\n SimpleDialog,\r\n TypographyLink\r\n} from '../../components';\r\nimport sanitize from \"sanitize-filename\";\r\nimport {selectProjectID, selectProjectName} from '../../redux/project-slice';\r\nimport {toast} from '../../app';\r\nimport {useTranslation} from 'react-i18next';\r\nimport {useAuth, useDialog, useGlobalSettings} from \"../../hooks\";\r\nimport {getCloudExporter} from \"./exporter\";\r\nimport {getLocalizedProjectName} from '../../utilities';\r\nimport {throttle} from 'throttle-debounce';\r\nimport {getLocalizedURL} from '../../localization';\r\nimport { engineCloudURL } from '../../urls';\r\nimport { useTableState } from '../../hooks/use-table-state';\r\nimport { NewProjectInfo } from '../common';\r\nimport { StatusCode } from '../../types/cloud-export';\r\n\r\ninterface AssetStatus {\r\n filename: string;\r\n status_code: number;\r\n}\r\n\r\ninterface AssetStatuses {\r\n [key: string]: AssetStatus;\r\n}\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n contentCenter: {\r\n textAlign: \"center\"\r\n },\r\n cancelProgress: {\r\n marginRight: theme.spacing(1)\r\n },\r\n cancelContent: {\r\n paddingBottom: theme.spacing(3)\r\n }\r\n }),\r\n);\r\n\r\ninterface LinkedProjectProps {\r\n name: string\r\n}\r\n\r\nconst LinkedProjectInfo = (props: LinkedProjectProps) => {\r\n const {name} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst AssetStatusText = (props: {status: AssetStatus}) => {\r\n const {status} = props;\r\n\r\n const theme = useTheme();\r\n const {t} = useTranslation();\r\n\r\n const getColor = (status_code: StatusCode) => {\r\n switch (status_code) {\r\n case StatusCode.Uploaded:\r\n return theme.palette.success.main;\r\n case StatusCode.Uploading:\r\n case StatusCode.Preparing:\r\n return theme.palette.info.main;\r\n case StatusCode.Errored:\r\n return theme.palette.error.main;\r\n case StatusCode.Queued:\r\n default:\r\n return theme.palette.primary.main;\r\n }\r\n };\r\n\r\n const getText = (status_code: StatusCode) => {\r\n switch (status_code) {\r\n case StatusCode.Uploaded:\r\n return t(`export.uploaded`);\r\n case StatusCode.Uploading:\r\n return t(`export.uploading`);\r\n case StatusCode.Preparing:\r\n return t(`export.preparing`);\r\n case StatusCode.Errored:\r\n return t(`export.errored`);\r\n case StatusCode.Queued:\r\n default:\r\n return t(`export.queued`);\r\n }\r\n };\r\n\r\n return (\r\n \r\n {getText(status.status_code)}\r\n \r\n );\r\n};\r\n\r\nexport const CloudExporter = () => {\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const {i18n, t} = useTranslation();\r\n\r\n const tableState = useTableState({defaultSort: \"status_text\"});\r\n\r\n const exporterDialog = useDialog();\r\n const messageDialog = useDialog();\r\n const cancelDialog = useDialog();\r\n\r\n const projectID = useSelector(selectProjectID);\r\n const projectName = useSelector(selectProjectName);\r\n const assets = useSelector(selectAllAssets);\r\n const pointClouds = getPointCloudAssets(assets);\r\n const camerasFiles = getCameraFileAssets(assets);\r\n const modelFiles = getModelAssets(assets);\r\n\r\n const [assetStatuses, setAssetStatuses] = useState({});\r\n const [exportPercent, setExportPercent] = useState(0);\r\n const [isExportRunning, setIsExportRunning] = useState(false);\r\n const [isExportFinished, setIsExportFinished] = useState(false);\r\n const [projectExists, setProjectExists] = useState(false);\r\n const [projectURL, setProjectURL] = useState(\"\");\r\n\r\n const {linkAccount, checkVersion, loggedIn, getAppCode} = useAuth();\r\n const globalSettings = useGlobalSettings();\r\n const {startExport, cancelExport} = useMemo(getCloudExporter, []);\r\n\r\n const percentThrottleMilliseconds = 250;\r\n const onProgress = useCallback(throttle(\r\n percentThrottleMilliseconds, (value) => {\r\n setExportPercent(value);\r\n }), []);\r\n\r\n const updateThrottleMilliseconds = 250;\r\n const onUpdate = useCallback(throttle(\r\n updateThrottleMilliseconds, (statuses) => {\r\n setAssetStatuses({...statuses});\r\n }), []);\r\n\r\n const canExport = assets.length > 0;\r\n\r\n const getRows = (assetStatuses: AssetStatuses) => {\r\n return Object.keys(assetStatuses).map(key => {\r\n const assetStatus = assetStatuses[key];\r\n\r\n return {\r\n id: key,\r\n filename: assetStatus.filename,\r\n status_code: assetStatus.status_code,\r\n status_text: \r\n };\r\n });\r\n };\r\n\r\n const reset = () => {\r\n setExportPercent(0);\r\n setAssetStatuses({});\r\n setIsExportFinished(false);\r\n setProjectURL(\"\");\r\n };\r\n\r\n const onExportFinished = () => {\r\n setIsExportRunning(false);\r\n setIsExportFinished(true);\r\n setExportPercent(100);\r\n };\r\n\r\n const handleExportCancel = () => {\r\n reset();\r\n messageDialog.handleClose();\r\n cancelExport(projectExists);\r\n };\r\n\r\n const handleExport = () => {\r\n exporterDialog.handleClose();\r\n exportToCloud();\r\n };\r\n\r\n const checkProject = async (originalID): Promise => {\r\n try {\r\n const url = `${engineCloudURL}/api/projects/${originalID}/exists`;\r\n const response = await fetch(url);\r\n return response.status === 200;\r\n } catch {\r\n return false;\r\n }\r\n };\r\n\r\n const exportToCloud = async() => {\r\n trackToolUsage(\"exporter\");\r\n\r\n reset();\r\n messageDialog.handleOpen();\r\n\r\n const assets = [\r\n ...pointClouds,\r\n ...camerasFiles,\r\n ...modelFiles\r\n ];\r\n\r\n await startExport({\r\n name: exportName,\r\n assets: assets,\r\n update: projectExists,\r\n state: store.getState(),\r\n globalSettings: globalSettings.getState(),\r\n appCode: await getAppCode(true),\r\n onStart: setAssetStatuses,\r\n onUpdate: onUpdate,\r\n onProgress: onProgress,\r\n onError: (title, message) => {\r\n dialog.showErrorBox(title, message);\r\n handleExportCancel();\r\n },\r\n onFinish: (projectID) => {\r\n setProjectURL(getLocalizedURL(\r\n `${engineCloudURL}/viewer/${projectID}`, i18n.language));\r\n onExportFinished();\r\n }\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-cloud-export\", async () => {\r\n if (!canExport) return toast.error(t(\"toast.no-data-loaded\"));\r\n\r\n if (!loggedIn) {\r\n const success = await linkAccount();\r\n if (!success) return;\r\n }\r\n\r\n const valid = await checkVersion();\r\n if (!valid) {\r\n dialog.showErrorBox(t('version_check.title'), t('version_check.description'));\r\n return;\r\n }\r\n\r\n const exists = await checkProject(projectID);\r\n setProjectExists(exists);\r\n exporterDialog.handleOpen();\r\n });\r\n }, [loggedIn, projectID, canExport]);\r\n\r\n const uploadMessage = useMemo(() => {\r\n if (!isExportFinished) return;\r\n\r\n let hasError = false;\r\n\r\n for (let key of Object.keys(assetStatuses)) {\r\n if (assetStatuses[key].status_code === StatusCode.Errored) {\r\n hasError = true;\r\n break;\r\n }\r\n }\r\n\r\n if (projectExists) {\r\n return hasError\r\n ? t(\"export.project_updated_with_errors\")\r\n : t(\"export.project-updated-successfully\");\r\n }\r\n\r\n return hasError\r\n ? t(\"export.project_uploaded_with_errors\")\r\n : t(\"export.project-uploaded-successfully\");\r\n }, [projectExists, isExportFinished, assetStatuses]);\r\n\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n const sanitizedName = sanitize(localizedProjectName);\r\n const exportName = t('export.export-name', {name: sanitizedName});\r\n\r\n const columns = [\r\n {\r\n id: 'filename',\r\n label: t(\"export.filename\")\r\n },\r\n {\r\n id: 'status_text',\r\n label: t(\"export.status\"),\r\n sortBy: \"status_code\"\r\n }\r\n ];\r\n\r\n const rows = useMemo(() => {\r\n return getRows(assetStatuses);\r\n }, [assetStatuses]);\r\n\r\n return (\r\n \r\n {/* Exporting dialog */}\r\n \r\n {t('export.export-status')}\r\n\r\n \r\n {isExportFinished && (\r\n <>\r\n \r\n {uploadMessage}\r\n \r\n\r\n \r\n\r\n \r\n \r\n )}\r\n\r\n \r\n\r\n {(rows.length > 0) && (\r\n
\r\n \r\n
\r\n )}\r\n
\r\n\r\n \r\n {!isExportFinished && (\r\n \r\n {t('export.cancel-export')}\r\n \r\n )}\r\n\r\n {isExportFinished && (\r\n \r\n {t(\"export.close\")}\r\n \r\n )}\r\n \r\n \r\n\r\n {/* Main dialog */}\r\n \r\n \r\n\r\n {/* Export file type(s) info */}\r\n \r\n\r\n {/** Existing cloud project */}\r\n {projectExists && }\r\n\r\n {/** New cloud project */}\r\n {!projectExists && \r\n \r\n\r\n \r\n }\r\n \r\n \r\n \r\n\r\n {/* Cancelling dialog */}\r\n \r\n {t('export.data-export')}\r\n \r\n \r\n \r\n {t('export.cancelling-export')}\r\n \r\n \r\n \r\n
\r\n );\r\n};","import React, {useEffect, useState, memo} from 'react';\r\nimport {\r\n Box,\r\n Button,\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n Grid,\r\n List,\r\n ListItem,\r\n MenuItem,\r\n Select,\r\n Theme,\r\n Typography,\r\n} from '@mui/material';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n DraggableDialog,\r\n ProgressDialog,\r\n PromptDialog,\r\n DenseDivider,\r\n IconToolBar,\r\n SlimScrollbar,\r\n ToolBarButton,\r\n EnhancedIconButton,\r\n DropDownDialog,\r\n TextDialog,\r\n CheckboxWithLabel\r\n} from '../components';\r\nimport { fs, getTemporaryFile, registerEvent } from '../electron-modules';\r\nimport { FolderWithLabel } from '../components';\r\nimport DeleteIcon from '@mui/icons-material/Delete';\r\nimport ZoomInIcon from '@mui/icons-material/ZoomIn';\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\r\nimport ExpandLessIcon from '@mui/icons-material/ExpandLess';\r\nimport AddToPhotosIcon from '@mui/icons-material/AddToPhotos';\r\nimport RefreshIcon from '@mui/icons-material/Refresh';\r\nimport { useSelector } from 'react-redux';\r\nimport {\r\n addAsset,\r\n Asset,\r\n AssetType,\r\n deleteAsset,\r\n getPointCloudAssets,\r\n selectAllAssets\r\n} from '../redux/assets-slice';\r\nimport { PythonExecutable } from '../executable';\r\nimport path from 'path';\r\nimport { asyncTimeout, useAssetTools } from '../utilities';\r\nimport { toast } from '../app';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { classifications } from '../classifications';\r\nimport { textToColor } from '../viewer/labelling';\r\nimport { createFolder } from '../redux/folders-slice';\r\nimport { ClippingBox, ClippingGroup, OperationType } from '../viewer/markup';\r\nimport {\r\n useDialog,\r\n useUniqueProjectID,\r\n useViewer,\r\n useActiveTool\r\n} from '../hooks';\r\nimport { useAppDispatch } from '../redux/store';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n card: {\r\n margin: theme.spacing(2),\r\n marginTop: theme.spacing(0),\r\n padding: theme.spacing(1),\r\n userSelect: \"none\"\r\n },\r\n cardHeader: {\r\n padding: theme.spacing(1)\r\n },\r\n cardContent: {\r\n padding: `${theme.spacing(2)} !important`\r\n },\r\n cardButtons: {\r\n marginTop: 0,\r\n alignSelf: \"center\"\r\n },\r\n headerTitle: {\r\n fontWeight: \"bold\"\r\n },\r\n clippingBoxParent: {\r\n display: \"flex\",\r\n justifyContent: \"space-between\"\r\n },\r\n clippingBoxButtons: {\r\n color: \"green\"\r\n },\r\n folderList: {\r\n padding: \"0px\",\r\n overflow: \"auto\",\r\n flex: 1,\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n operationList: {\r\n flex: 1,\r\n overflow: \"hidden\",\r\n overflowY: \"auto\"\r\n },\r\n mixedDataWarning: {\r\n padding: theme.spacing(1.0),\r\n color: theme.palette.warning.main,\r\n textAlign: \"center\"\r\n },\r\n boxOrientation: {\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n paddingBottom: theme.spacing(1.5),\r\n fontSize: \"0.85em\",\r\n \"&:last-child\": {\r\n paddingBottom: theme.spacing(0)\r\n }\r\n },\r\n dropdownRoot: {\r\n minWidth: \"40%\"\r\n },\r\n dropdownSelect: {\r\n paddingTop: theme.spacing(0),\r\n paddingBottom: theme.spacing(0),\r\n fontSize: \"0.85em\"\r\n }\r\n })\r\n);\r\n\r\ninterface CategoryExpandProps {\r\n expanded: boolean;\r\n setExpanded: React.Dispatch;\r\n}\r\n\r\nconst CategoryExpand = (props: CategoryExpandProps) => {\r\n const {setExpanded, expanded} = props;\r\n\r\n const {t} = useTranslation();\r\n\r\n return ( {\r\n event.stopPropagation();\r\n setExpanded(!expanded);\r\n }}\r\n >\r\n {expanded && }\r\n {!expanded && }\r\n );\r\n};\r\n\r\ninterface PointMarkupBoxProps {\r\n index: number;\r\n clippingBox: ClippingBox\r\n}\r\n\r\nconst PointMarkupBox = (props: PointMarkupBoxProps) => {\r\n const {clippingBox, index} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [deletePrompt, setDeletePrompt] = useState(false);\r\n\r\n const handleDelete = () => {\r\n setDeletePrompt(false);\r\n viewer.pointMarkupDeleteBox(clippingBox.id);\r\n };\r\n\r\n const onMouseOver = () => {\r\n viewer.setPointMarkupHover(clippingBox.id, true);\r\n };\r\n\r\n const onMouseLeave = () => {\r\n viewer.setPointMarkupHover(clippingBox.id, false);\r\n };\r\n\r\n return (\r\n \r\n \r\n {t('point-markup.bounding_box_index', {\r\n index: index+1\r\n })}\r\n \r\n\r\n
\r\n {/* Zoom to extent */}\r\n {\r\n viewer.pointMarkupZoom(clippingBox.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Reset rotation */}\r\n {\r\n viewer.resetPointMarkupRotation(clippingBox.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Delete bounding box */}\r\n {\r\n setDeletePrompt(true);\r\n }}\r\n >\r\n \r\n \r\n
\r\n\r\n {/* Delete Dialog */}\r\n {\r\n setDeletePrompt(false);\r\n }}\r\n title={t('point-markup.delete_bounding_box')}\r\n prompt={t('point-markup.do_you_want_to_delete_this_bounding_box')}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n \r\n );\r\n};\r\n\r\ninterface PointMarkupGroupProps {\r\n operation: ClippingGroup\r\n}\r\n\r\nconst PointMarkupGroup = (props: PointMarkupGroupProps) => {\r\n const {operation} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [expanded, setExpanded] = useState(false);\r\n const [editPrompt, setEditPrompt] = useState(false);\r\n const [deletePrompt, setDeletePrompt] = useState(false);\r\n const [newClassification, setNewClassification] = useState(0);\r\n\r\n const isDelete = operation.type === OperationType.Delete;\r\n const isClassify = operation.type === OperationType.Classify;\r\n const isSplit = operation.type === OperationType.Split;\r\n\r\n const color = textToColor(operation.name);\r\n const newBoxDisabled = viewer?.pointMarkupActive();\r\n const operationBoxes = operation.clippingBoxes;\r\n\r\n const defaultIgnoreValue = isSplit ? -1 : 2;\r\n const [ignoredClassification, setIgnoredClassification]\r\n = useState(defaultIgnoreValue);\r\n\r\n const handleDelete = () => {\r\n setDeletePrompt(false);\r\n viewer.pointMarkupDeleteGroup(operation.id);\r\n };\r\n\r\n const handleRename = (name) => {\r\n if (viewer.pointMarkupNameExists(name)) {\r\n toast.error(t('toast.filename_already_exists'));\r\n return;\r\n }\r\n\r\n setEditPrompt(false);\r\n viewer.updatePointMarkupName(operation.id, name);\r\n };\r\n\r\n const addThenExpand = () => {\r\n viewer.setPointMarkupActive(operation.id);\r\n setExpanded(true);\r\n };\r\n\r\n useEffect(() => {\r\n viewer.setPointMarkupNewClassification(operation.id, newClassification);\r\n }, [viewer, newClassification]);\r\n\r\n useEffect(() => {\r\n viewer.setPointMarkupIgnoredClassification(operation.id, ignoredClassification);\r\n }, [viewer, ignoredClassification]);\r\n\r\n let classOptions = [];\r\n for (let i=0; i<32; i++) {\r\n const {id, name} = classifications[i];\r\n const displayName = `${name} (${id})`;\r\n classOptions.push({displayName});\r\n };\r\n\r\n return (\r\n \r\n \r\n {/* Header */}\r\n \r\n {/* Expand/collapse areas */}\r\n \r\n\r\n {/* Edit output name */}\r\n {\r\n setEditPrompt(true);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Add new bounding box */}\r\n \r\n \r\n \r\n\r\n {/* Delete operation box */}\r\n {\r\n setDeletePrompt(true);\r\n }}\r\n >\r\n \r\n \r\n \r\n }\r\n disableTypography={true}\r\n title={\r\n \r\n {operation.name}\r\n \r\n }\r\n subheader={\r\n \r\n {t('point-markup.bounding_boxes', {\r\n count: operationBoxes.length\r\n })}\r\n \r\n }\r\n />\r\n\r\n {expanded && (\r\n {/** Ignore Classification */}\r\n {(isClassify || isDelete) && (\r\n
\r\n {t('point-markup.ignore_classification')}\r\n {\r\n setIgnoredClassification(event.target.value);\r\n }}\r\n >\r\n {t('point-markup.use_all_classes')}\r\n {classOptions}\r\n \r\n
\r\n
)}\r\n\r\n {/** New classification */}\r\n {isClassify && (\r\n
\r\n {t('point-markup.new_classification')}\r\n {\r\n setNewClassification(event.target.value);\r\n }}\r\n >\r\n {classOptions}\r\n \r\n
\r\n
)}\r\n\r\n {(operationBoxes.length > 0) && (\r\n \r\n\r\n {/** Bounding boxes */}\r\n \r\n {operationBoxes.map((clippingBox, index) =>\r\n \r\n )}\r\n \r\n )}\r\n\r\n
)}\r\n \r\n\r\n {/* Delete Dialog */}\r\n {\r\n setDeletePrompt(false);\r\n }}\r\n title={t('point-markup.delete_bounding_boxes')}\r\n prompt={t('point-markup.do_you_want_to_delete_this_operation_including_all_bounding_boxes')}\r\n button={t('buttons.delete')}\r\n />\r\n\r\n {/* Output Name Dialog */}\r\n setEditPrompt(false)}\r\n onSubmit={handleRename}\r\n title={t('point-markup.edit_output_file')}\r\n prompt={t('point-markup.enter_new_filename')}\r\n placeholder={operation.name}\r\n label={t('point-markup.output_file')}\r\n />\r\n \r\n );\r\n};\r\n\r\ninterface DataExportSplitProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n setProgress: React.Dispatch;\r\n markupGroups: ClippingGroup[]\r\n visibleClouds: Asset[];\r\n}\r\n\r\nconst DataExportSplit = (props: DataExportSplitProps) => {\r\n const {open, setOpen, setProgress, markupGroups, visibleClouds} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useAppDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const {addAssetPaths} = useAssetTools();\r\n\r\n const [exportPoints, setExportPoints] = useState(true);\r\n const [exportImages, setExportImages] = useState(true);\r\n const [outputPath, setOutputPath] = useState(null);\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n setExportPoints(true);\r\n setExportImages(true);\r\n setOutputPath(null);\r\n setProgress(0.0);\r\n };\r\n\r\n const handleSubmit = () => {\r\n if (visibleClouds.length === 0) {\r\n toast.warning(t(\"toast.no-point-clouds\"));\r\n return;\r\n }\r\n\r\n const operationData = markupGroups.map(operation => {\r\n const operationBoxes = operation.clippingBoxes;\r\n const attributes = operationBoxes.map(x => x.attributes);\r\n\r\n return {\r\n name: operation.name,\r\n data: attributes\r\n };\r\n });\r\n\r\n const cameras = viewer.getAllCameras();\r\n const cameraData = cameras.map(camera => {\r\n const position = camera.position.value\r\n .toArray();\r\n\r\n const rotation = camera.rotation.degrees\r\n .toArray()\r\n .slice(0,3);\r\n\r\n return {\r\n name: camera.name,\r\n path: camera.path,\r\n position,\r\n rotation\r\n };\r\n });\r\n\r\n const jsonData = {\r\n operationData,\r\n outputPath,\r\n inputPaths: exportPoints ? inputPaths : [],\r\n imageData: exportImages ? cameraData : [],\r\n };\r\n\r\n // Write file to temp path\r\n const text = JSON.stringify(jsonData, null, 4);\r\n const tempTextPath = getTemporaryFile(\"txt\");\r\n\r\n try {\r\n fs.writeFileSync(tempTextPath, text);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.markup-failed\"));\r\n\r\n return;\r\n }\r\n\r\n toast.success(t(\"toast.markup-submit\"));\r\n\r\n let outputPaths = null;\r\n let processTimeout = 500;\r\n\r\n const exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", \"apply_data_splitting\",\r\n \"--input_json\", tempTextPath\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (jsonData.progress) {\r\n setProgress(jsonData.progress);\r\n } else if (jsonData.output_paths) {\r\n outputPaths = jsonData.output_paths;\r\n }\r\n },\r\n onClose: async () => {\r\n if (!outputPaths) {\r\n toast.error(t(\"toast.markup-failed\"));\r\n handleClose();\r\n return;\r\n }\r\n\r\n await asyncTimeout(processTimeout);\r\n viewer.clearPointMarkup();\r\n toast.success(t(\"toast.markup-import\"));\r\n\r\n for (let outputPath of outputPaths) {\r\n const folder = await dispatch(createFolder(outputPath.name));\r\n await addAssetPaths(outputPath.paths, folder.id);\r\n }\r\n\r\n handleClose();\r\n }\r\n });\r\n };\r\n\r\n let canSubmit = false;\r\n let pathOverlap = false;\r\n\r\n const inputPaths = visibleClouds.map(x => x.path);\r\n const inputFoldersPoints = inputPaths.map(x => path.dirname(x));\r\n\r\n if (viewer) {\r\n const cameras = viewer.getAllCameras();\r\n const inputFolderCameras = viewer.getCameraFolders(cameras);\r\n\r\n const inputFolders = new Set([\r\n ...inputFoldersPoints,\r\n ...inputFolderCameras\r\n ]);\r\n\r\n pathOverlap = inputFolders.has(outputPath);\r\n\r\n canSubmit = !pathOverlap\r\n && (outputPath !== null)\r\n && (exportImages || exportPoints);\r\n }\r\n\r\n return (\r\n \r\n {t('point-markup.point-markup-export')}\r\n\r\n \r\n \r\n\r\n {pathOverlap && (\r\n \r\n {t('point-markup.output-folder-must-be-different')}\r\n \r\n )}\r\n\r\n {/* Include images in export */}\r\n \r\n \r\n \r\n\r\n {/* Include points in export */}\r\n \r\n \r\n \r\n\r\n {/* Output folder */}\r\n \r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n\r\n \r\n );\r\n};\r\n\r\ninterface DataExportMarkupProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n setProgress: React.Dispatch;\r\n markupGroups: ClippingGroup[]\r\n visibleClouds: Asset[];\r\n}\r\n\r\nconst DataExportMarkup = (props: DataExportMarkupProps) => {\r\n const {open, setOpen, setProgress, markupGroups, visibleClouds} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useAppDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [overwriteFile, setOverwriteFile] = useState(false);\r\n const [outputPath, setOutputPath] = useState(null);\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n setOverwriteFile(false);\r\n setOutputPath(null);\r\n setProgress(0.0);\r\n };\r\n\r\n const handleSubmit = () => {\r\n if (visibleClouds.length === 0) {\r\n toast.warning(t(\"toast.no-point-clouds\"));\r\n return;\r\n }\r\n\r\n let boundingBoxes = markupGroups.map(operation => {\r\n const operationBoxes = operation.clippingBoxes;\r\n const attributes = operationBoxes.map(x => x.attributes);\r\n return attributes;\r\n }).flat();\r\n\r\n const jsonData = {\r\n inputPaths,\r\n outputPath,\r\n boundingBoxes,\r\n overwriteFile\r\n };\r\n\r\n // Write file to temp path\r\n const text = JSON.stringify(jsonData, null, 4);\r\n const tempTextPath = getTemporaryFile(\"txt\");\r\n\r\n try {\r\n fs.writeFileSync(tempTextPath, text);\r\n } catch(err) {\r\n console.log(err);\r\n toast.error(t(\"toast.markup-failed\"));\r\n\r\n return;\r\n }\r\n\r\n toast.success(t(\"toast.markup-submit\"));\r\n\r\n let newCloudPaths = null;\r\n let processTimeout = 500;\r\n\r\n const exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", \"apply_point_markup\",\r\n \"--input_json\", tempTextPath\r\n ];\r\n\r\n exe.run({\r\n commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n if (jsonData.progress) {\r\n setProgress(jsonData.progress);\r\n } else if (jsonData.output_paths) {\r\n newCloudPaths = jsonData.output_paths;\r\n }\r\n },\r\n onClose: async () => {\r\n if (!newCloudPaths) {\r\n toast.error(t(\"toast.markup-failed\"));\r\n handleClose();\r\n return;\r\n }\r\n\r\n await asyncTimeout(processTimeout);\r\n viewer.clearPointMarkup();\r\n toast.success(t(\"toast.markup-import\"));\r\n\r\n visibleClouds.forEach((asset, index) => {\r\n\r\n const assetPath = newCloudPaths[index];\r\n\r\n // Add new pointcloud\r\n dispatch(addAsset({\r\n folderID: asset.folderID,\r\n name: path.basename(assetPath),\r\n path: assetPath,\r\n type: asset.type\r\n }));\r\n\r\n // Remove old pointcloud\r\n dispatch(deleteAsset(asset.id));\r\n });\r\n\r\n handleClose();\r\n }\r\n });\r\n };\r\n\r\n const inputPaths = visibleClouds.map(x => x.path);\r\n const inputFolders = inputPaths.map(x => path.dirname(x));\r\n\r\n let canSubmit = true;\r\n\r\n let pathOverlap = inputFolders.includes(outputPath);\r\n if (pathOverlap) {\r\n canSubmit = false;\r\n }\r\n\r\n if (!overwriteFile && (outputPath === null)) {\r\n canSubmit = false;\r\n }\r\n\r\n return (\r\n \r\n {t('point-markup.point-markup-export')}\r\n\r\n \r\n \r\n\r\n {pathOverlap && (\r\n \r\n {t('point-markup.output-folder-must-be-different')}\r\n \r\n )}\r\n\r\n {/* Setting layer default */}\r\n \r\n {\r\n setOverwriteFile(value);\r\n setOutputPath(null);\r\n }}\r\n />\r\n \r\n\r\n {/* Output folder */}\r\n {!overwriteFile && (\r\n \r\n )}\r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n \r\n \r\n\r\n \r\n );\r\n};\r\n\r\ninterface PointMarkupProps {\r\n markupGroups: ClippingGroup[]\r\n}\r\n\r\nexport const PointMarkup = memo((props: PointMarkupProps) => {\r\n const {markupGroups} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const pointMarkupDialog = useDialog();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {activeToolOpen, setActiveToolOpen} = useActiveTool();\r\n\r\n const [toolType, setToolType] = useState(null);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [exportPromptMarkup, setExportPromptMarkup] = useState(false);\r\n const [exportPromptSplit, setExportPromptSplit] = useState(false);\r\n const [newOperationPrompt, setNewOperationPrompt] = useState(false);\r\n const [newOutputPrompt, setNewOutputPrompt] = useState(false);\r\n const [conversionProgress, setConversionProgress] = useState(0);\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const pointClouds = getPointCloudAssets(assets);\r\n const LASfiles = pointClouds.filter(x => x.type === AssetType.LAS);\r\n const visibleClouds = LASfiles.filter(x => x.visible);\r\n\r\n const checkClose = () => {\r\n if (isModified) {\r\n setClosePrompt(true);\r\n } else {\r\n pointMarkupDialog.handleClose();\r\n }\r\n };\r\n\r\n const addNewOperation = (operationType) => {\r\n setNewOperationPrompt(false);\r\n\r\n if (operationType === OperationType.Delete) {\r\n viewer.addPointMarkupOperation(operationType, t('point-markup.delete_point_data'));\r\n } else if (operationType === OperationType.Classify) {\r\n viewer.addPointMarkupOperation(operationType, t('point-markup.classify_point_data'));\r\n }\r\n };\r\n\r\n const addNewOutputFolder = (name) => {\r\n if (viewer.pointMarkupNameExists(name)) {\r\n toast.error(t('toast.filename_already_exists'));\r\n return;\r\n }\r\n\r\n setNewOutputPrompt(false);\r\n\r\n const operationType = OperationType.Split;\r\n viewer.addPointMarkupOperation(operationType, name);\r\n };\r\n\r\n useEffect(() => {\r\n /** Keep track if a tool is currently being used */\r\n setActiveToolOpen(pointMarkupDialog.open);\r\n }, [pointMarkupDialog.open]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n pointMarkupDialog.handleClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-point-markup\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n pointMarkupDialog.handleOpen(\"markup\");\r\n });\r\n\r\n registerEvent(\"open-data-splitting\", () => {\r\n if (activeToolOpen) return toast.warning(t('toast.one_tool_only'));\r\n pointMarkupDialog.handleOpen(\"split\");\r\n });\r\n }, [activeToolOpen]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.pointMarkupToggle(pointMarkupDialog.open);\r\n }, [viewer, pointMarkupDialog.open]);\r\n\r\n useEffect(() => {\r\n setToolType(pointMarkupDialog.data);\r\n }, [pointMarkupDialog.data]);\r\n\r\n const isPointMarkup = toolType === \"markup\";\r\n const isFolderSplit = toolType === \"split\";\r\n const isModified = markupGroups.length > 0;\r\n const mixedData = pointClouds.length !== LASfiles.length;\r\n\r\n const dialogTitle = isPointMarkup\r\n ? t('point-markup.point-cloud-markup')\r\n : t('point-markup.data-splitting');\r\n\r\n return (\r\n \r\n \r\n\r\n {/* Label toolbar icons */}\r\n \r\n {/* Add new operation */}\r\n {\r\n setNewOperationPrompt(true);\r\n }}\r\n success\r\n />\r\n\r\n {/* Add new output file */}\r\n {\r\n setNewOutputPrompt(true);\r\n }}\r\n success\r\n />\r\n\r\n {/* Apply changes to las file */}\r\n {\r\n if (isPointMarkup) {\r\n setExportPromptMarkup(true);\r\n } else {\r\n setExportPromptSplit(true);\r\n }\r\n }}\r\n />\r\n \r\n\r\n \r\n\r\n {mixedData && (\r\n \r\n {t('point-markup.will-only-to-las-files')}\r\n \r\n )}\r\n\r\n \r\n \r\n \r\n {markupGroups.map(operation =>\r\n \r\n )}\r\n \r\n \r\n \r\n\r\n \r\n\r\n {/* Close modal */}\r\n setClosePrompt(false)}\r\n onSubmit={() => {\r\n pointMarkupDialog.handleClose();\r\n setClosePrompt(false);\r\n }}\r\n title={t('point-markup.close-window')}\r\n prompt={t('point-markup.want-to-close')}\r\n button={t('point-markup.close')}\r\n />\r\n\r\n {/* Add new operation */}\r\n {\r\n setNewOperationPrompt(false);\r\n }}\r\n onSubmit={addNewOperation}\r\n title={t('point-markup.add_new_operation')}\r\n prompt={t('point-markup.select_operation_type')}\r\n defaultValue={OperationType.Delete}\r\n options={[\r\n [OperationType.Delete, t('point-markup.delete_point_data')],\r\n [OperationType.Classify, t('point-markup.classify_point_data')]\r\n ]}\r\n />\r\n\r\n {/* Add output folder */}\r\n {\r\n setNewOutputPrompt(false);\r\n }}\r\n onSubmit={addNewOutputFolder}\r\n title={t('point-markup.create_new_output')}\r\n prompt={t('point-markup.enter_new_file_name')}\r\n label={t('point-markup.output_file_name')}\r\n />\r\n\r\n {/* Conversion percent dialog */}\r\n 0}\r\n text={t('point-markup.applying-point-cloud-markup')}\r\n percent={conversionProgress}\r\n />\r\n\r\n {/* Point markup export */}\r\n {exportPromptMarkup && ()}\r\n\r\n {/* Data splitting export */}\r\n {exportPromptSplit && ()}\r\n\r\n \r\n );\r\n});\r\n","import React, {useEffect, useState, memo, useMemo, useCallback} from 'react';\r\nimport {\r\n Button,\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n FormControlLabel,\r\n IconButton,\r\n InputLabel,\r\n List,\r\n ListSubheader,\r\n MenuItem,\r\n Radio,\r\n RadioGroup,\r\n Select,\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableContainer,\r\n TableHead,\r\n TableRow,\r\n Theme,\r\n Typography,\r\n useTheme,\r\n} from '@mui/material';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport clsx from 'clsx';\r\nimport RotateRightIcon from '@mui/icons-material/RotateRight';\r\nimport {\r\n AerialAreaMeasurement, AerialLengthMeasurement,\r\n HeightMeasurement,\r\n Measurement,\r\n Measurement3D, MeasurementArea, MeasurementPoint,\r\n MeasurementVolume, StationMeasurement\r\n} from '../viewer/measurements';\r\nimport DeleteIcon from '@mui/icons-material/Delete';\r\nimport EditIcon from '@mui/icons-material/Edit';\r\nimport ExpandMoreIcon from '@mui/icons-material/ExpandMore';\r\nimport ExpandLessIcon from '@mui/icons-material/ExpandLess';\r\nimport 'font-awesome/css/font-awesome.css';\r\nimport { dialog, fs, isElectronApp, isStaticSite } from \"../electron-modules\";\r\nimport slash from 'slash';\r\nimport fileDialog from 'file-dialog';\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport { selectMeasureUnits, changeMeasureUnits, selectDataProjection } from '../redux/projections-slice';\r\nimport LocalScene from '../viewer/projections';\r\nimport {\r\n ArrowTooltip,\r\n PromptDialog,\r\n TextDialog,\r\n DenseDivider,\r\n IconToolBar,\r\n SlimScrollbar,\r\n ToolBarButton,\r\n ToolBarDivider,\r\n DraggableDialog,\r\n DenseMenu\r\n} from '../components';\r\nimport { toast } from '../app';\r\nimport { measureDataFilter, measureDataFormat } from '../file-extensions';\r\nimport { useTranslation } from 'react-i18next';\r\nimport {selectAllAssets, getLandXMLAssets, XMLData} from \"../redux/assets-slice\";\r\nimport {\r\n useDialog,\r\n useUniqueProjectID,\r\n useViewer,\r\n useActiveTool,\r\n useContextMenu,\r\n useGlobalSettings\r\n} from '../hooks';\r\nimport { nanoid } from '@reduxjs/toolkit';\r\nimport { VolumeType, SamplingRate, MeasureType, AerialMeasureType, MeasureExportType } from '../types/measurements';\r\nimport copyTextToClipboard from \"copy-to-clipboard\";\r\nimport { Units } from '../types/project';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n copyClipboard: {\r\n cursor: \"pointer\"\r\n },\r\n userWarning: {\r\n display: \"block\",\r\n padding: theme.spacing(1, 0),\r\n color: theme.palette.warning.main,\r\n textAlign: \"center\"\r\n },\r\n cardButtons: {\r\n marginTop: 0,\r\n alignSelf: \"center\"\r\n },\r\n card: {\r\n margin: theme.spacing(2),\r\n marginTop: theme.spacing(0),\r\n padding: theme.spacing(1),\r\n userSelect: \"none\"\r\n },\r\n cardHeader: {\r\n padding: theme.spacing(1)\r\n },\r\n cardContent: {\r\n padding: `${theme.spacing(2)} !important`\r\n },\r\n footerDiv: {\r\n width: \"100%\",\r\n boxShadow: \"0px 10px 10px 2px\",\r\n zIndex: 1,\r\n textAlign: \"center\"\r\n },\r\n measurementUnitsParent: {\r\n justifyContent: \"space-between\",\r\n padding: theme.spacing(0, 2),\r\n flexWrap: \"nowrap\"\r\n },\r\n measurementUnits: {\r\n margin: theme.spacing(0)\r\n },\r\n measurementUnitsRadio: {\r\n padding: theme.spacing(0.5),\r\n margin: theme.spacing(0)\r\n },\r\n imageOnlyInfoButton: {\r\n marginLeft: theme.spacing(1)\r\n },\r\n marginside: {\r\n margin: 0,\r\n padding: \"10px\"\r\n },\r\n actions: {\r\n padding: \"5px\"\r\n },\r\n expandText: {\r\n width: \"100%\",\r\n display: \"block\",\r\n textAlign: \"center\",\r\n cursor: \"pointer\",\r\n userSelect: \"none\",\r\n paddingBottom: \"5px\",\r\n paddingTop: \"5px\"\r\n },\r\n bold: {\r\n fontWeight: \"bold\"\r\n },\r\n row: {\r\n display: \"flex\",\r\n width: \"100%\",\r\n alignItems: \"baseline\"\r\n },\r\n alignmentSelect: {\r\n alignSelf: \"center\",\r\n width: \"90%\"\r\n },\r\n cell: {\r\n padding: theme.spacing(0.5),\r\n fontSize: \"0.85em !important\"\r\n },\r\n tableCell: {\r\n fontSize: \"0.8rem !important\",\r\n textAlign: \"center\"\r\n },\r\n cellParent: {\r\n flex: 1,\r\n display: \"flex\",\r\n alignItems: \"baseline\",\r\n justifyContent: \"space-between\",\r\n padding: theme.spacing(0, 0.5)\r\n },\r\n measureTable: {\r\n width: \"fit-content\",\r\n margin: \"0px auto\",\r\n marginTop: theme.spacing(1.5)\r\n },\r\n headerTitle: {\r\n fontWeight: \"bold\",\r\n cursor: \"pointer\"\r\n },\r\n calculateButton: {\r\n padding: theme.spacing(0),\r\n fontSize: \"0.7rem\"\r\n },\r\n recalculate: {\r\n display: \"flex\",\r\n flexDirection: \"row-reverse\",\r\n alignItems: \"center\"\r\n },\r\n recalculateButton: {\r\n padding: theme.spacing(0),\r\n marginRight: theme.spacing(1)\r\n },\r\n })\r\n);\r\n\r\ninterface ExportDialogProps {\r\n open: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nconst ExportDialog = (props: ExportDialogProps) => {\r\n const {open, onClose} = props;\r\n\r\n const theme = useTheme();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [exportType, setExportType] = useState(MeasureExportType.CSV);\r\n const [ordering, setOrdering] = useState(\"xyz\");\r\n\r\n const onSubmit = () => {\r\n viewer?.exportMeasurements(exportType, ordering);\r\n onClose();\r\n };\r\n\r\n return (\r\n \r\n \r\n {t('measure.measurements-export')}\r\n \r\n\r\n \r\n {/* Export type */}\r\n {t('measure.export-type')}\r\n {\r\n const value = event.target.value;\r\n setExportType(value as MeasureExportType);\r\n }}\r\n >\r\n \r\n {t('measure.csv-file')}\r\n \r\n\r\n {isElectronApp && \r\n {t('measure.measure-shp')}\r\n }\r\n\r\n {isElectronApp && \r\n {t('measure.measure-dxf')}\r\n }\r\n\r\n \r\n {t('measure.measure-data')}\r\n \r\n \r\n\r\n {exportType === MeasureExportType.CSV && (\r\n \r\n {/* Ordering */}\r\n {t('measure.ordering')}\r\n {\r\n setOrdering(event.target.value as string);\r\n }}\r\n >\r\n {t('measure.easting-northing-elevation')}\r\n {t('measure.northing-easting-elevation')}\r\n \r\n \r\n )}\r\n\r\n {exportType === MeasureExportType.Data && (\r\n \r\n {t('measure.data-export-info')}\r\n \r\n )}\r\n \r\n\r\n \r\n \r\n\r\n \r\n {t('buttons.export')}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\ninterface MeasureTypeIconProps {\r\n icon: string;\r\n title: string;\r\n type: MeasureType;\r\n measureType: MeasureType;\r\n setMeasureType: React.Dispatch;\r\n}\r\n\r\nconst MeasureTypeIcon = (props: MeasureTypeIconProps) => {\r\n const {type, title, icon, measureType, setMeasureType} = props;\r\n\r\n const onClick = useCallback(() => {\r\n setMeasureType(type);\r\n }, []);\r\n\r\n const color = (measureType === type)\r\n ? \"secondary\"\r\n : \"primary\";\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface ImportExportMeasureIconProps {\r\n icon: string;\r\n onClick: (event, data?) => void\r\n}\r\n\r\nconst ImportExportMeasureIcon = (props: ImportExportMeasureIconProps) => {\r\n const {icon, onClick} = props;\r\n const {t} = useTranslation();\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface ClipboardCopyProps {\r\n text: string;\r\n className: string;\r\n children: React.ReactNode;\r\n}\r\n\r\nconst ClipboardCopy = (props: ClipboardCopyProps) => {\r\n const {text, className} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n return (\r\n {\r\n event.stopPropagation();\r\n copyTextToClipboard(text);\r\n toast.success(t(\"toast.copied-to-clipboard\"));\r\n }}\r\n >\r\n \r\n {props.children as any}\r\n \r\n \r\n );\r\n};\r\n\r\nconst MeasurementInfo3DLength = (props: {measurement: Measurement3D}) => {\r\n const {measurement} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n return \r\n
\r\n {/** 2D Distance */}\r\n
\r\n
\r\n {t('measure.row-distance-2d')}\r\n
\r\n\r\n
\r\n {formatter.formatLength(measurement.distance2D)}\r\n
\r\n
\r\n\r\n {/** Grade */}\r\n
\r\n
\r\n {t('measure.row-grade')}\r\n
\r\n\r\n
\r\n {formatter.formatGrade(measurement.grade)}\r\n
\r\n
\r\n
\r\n\r\n
\r\n {/** 3D Distance */}\r\n
\r\n
\r\n {t('measure.row-distance-3d')}\r\n
\r\n\r\n
\r\n {formatter.formatLength(measurement.distance3D)}\r\n
\r\n
\r\n\r\n {/** Angle */}\r\n
\r\n
\r\n {t('measure.row-angle')}\r\n
\r\n\r\n
\r\n {formatter.formatAngle(measurement.angle)}\r\n
\r\n
\r\n
\r\n
;\r\n};\r\n\r\nconst MeasurementInfoHeight = (props: {measurement: HeightMeasurement}) => {\r\n const {measurement} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n return (\r\n
\r\n {/** Height */}\r\n
\r\n
\r\n {t('measure.row-height')}\r\n
\r\n\r\n
\r\n {formatter.formatLength(measurement.height)}\r\n
\r\n
\r\n\r\n {/** Blank div */}\r\n
\r\n
\r\n );\r\n};\r\n\r\nconst MeasurementInfo3DArea = (props: {measurement: MeasurementArea}) => {\r\n const {measurement} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n const isVolume = measurement instanceof MeasurementVolume;\r\n\r\n const getVolumeComponent = (measurement: MeasurementVolume) => {\r\n if (!measurement.valid) {\r\n return measurement.invalidVolumeMessage;\r\n }\r\n\r\n if (measurement.calculated) {\r\n const value = formatter.formatVolume(measurement);\r\n\r\n return (\r\n
\r\n
\r\n \r\n {\r\n event.stopPropagation();\r\n measurement.calculateVolume();\r\n }}\r\n size=\"large\">\r\n \r\n \r\n \r\n
\r\n );\r\n }\r\n\r\n return (\r\n \r\n {t('measure.calculating')}\r\n \r\n );\r\n };\r\n\r\n const {area, valid} = measurement.area;\r\n\r\n return (\r\n
\r\n {/** Area */}\r\n
\r\n
\r\n {t('measure.row-area')}\r\n
\r\n\r\n
\r\n
\r\n\r\n {/** Volume */}\r\n {isVolume && (
\r\n
\r\n {t('measure.row-volume')}\r\n
\r\n\r\n
\r\n {getVolumeComponent(measurement as MeasurementVolume)}\r\n
\r\n
)}\r\n\r\n {/** Blank div */}\r\n {!isVolume && (
)}\r\n
\r\n );\r\n};\r\n\r\nconst MeasurementInfo2DArea = (props: {measurement: AerialAreaMeasurement}) => {\r\n const {measurement} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const {aerialMeasureType} = useGlobalSettings();\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n const measureTypeText = useMemo(() => {\r\n if (aerialMeasureType === AerialMeasureType.Spherical) {\r\n return t('measure.aerial_spherical');\r\n } else if (aerialMeasureType === AerialMeasureType.Planar) {\r\n return t('measure.aerial_planar');\r\n }\r\n\r\n return t('general.unknown');\r\n }, [aerialMeasureType]);\r\n\r\n const {area, valid} = measurement.area;\r\n\r\n return (\r\n
\r\n {/** Area */}\r\n
\r\n
\r\n {measurement.header}\r\n
\r\n
\r\n
\r\n\r\n {/** Measurement type */}\r\n
\r\n
\r\n {t(\"measure.type\")}\r\n
\r\n
\r\n {measureTypeText}\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nconst MeasurementInfo2DLength = (props: {measurement: AerialLengthMeasurement}) => {\r\n const {measurement} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const {aerialMeasureType} = useGlobalSettings();\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n const measureTypeText = useMemo(() => {\r\n if (aerialMeasureType === AerialMeasureType.Spherical) {\r\n return t('measure.aerial_spherical');\r\n } else if (aerialMeasureType === AerialMeasureType.Planar) {\r\n return t('measure.aerial_planar');\r\n }\r\n\r\n return t('general.unknown');\r\n }, [aerialMeasureType]);\r\n\r\n return (\r\n
\r\n {/** 2D Distance */}\r\n
\r\n
\r\n {t('measure.row-distance-2d')}\r\n
\r\n
\r\n {formatter.formatLength(measurement.distance2D)}\r\n
\r\n
\r\n\r\n {/** Measurement type */}\r\n
\r\n
\r\n {t(\"measure.type\")}\r\n
\r\n
\r\n {measureTypeText}\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\nconst MeasurementInfoVolume = () => {\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const {volumeType, volumeSampleRate} = useGlobalSettings();\r\n\r\n const volumeMethodText = useMemo(() => {\r\n if (volumeType === VolumeType.LowestPlane)\r\n return t('measure.volume_lowest_plane');\r\n if (volumeType === VolumeType.MultiPlane)\r\n return t('measure.volume_multi_plane');\r\n\r\n return t('general.unknown');\r\n }, [volumeType]);\r\n\r\n const volumeRateText = useMemo(() => {\r\n if (volumeSampleRate === SamplingRate.High)\r\n return t('general.high');\r\n if (volumeSampleRate === SamplingRate.Medium)\r\n return t('general.medium');\r\n if (volumeSampleRate === SamplingRate.Low)\r\n return t('general.low');\r\n\r\n return t('general.unknown');\r\n }, [volumeSampleRate]);\r\n\r\n return (\r\n
\r\n\r\n {/** Volume Type */}\r\n
\r\n
\r\n {t('measure.method')}\r\n
\r\n\r\n
\r\n {volumeMethodText}\r\n
\r\n
\r\n\r\n {/** Sampling Rate */}\r\n
\r\n
\r\n {t('measure.sampling_rate')}\r\n
\r\n\r\n
\r\n {volumeRateText}\r\n
\r\n
\r\n\r\n
\r\n );\r\n};\r\n\r\nconst MeasurementInfoStation = (props: {measurement: StationMeasurement}) => {\r\n const {measurement} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n return (\r\n
\r\n {/** Station*/}\r\n
\r\n
\r\n {t('measure.station-distAlong')}\r\n
\r\n\r\n
\r\n {formatter.formatStation(measurement)}\r\n
\r\n
\r\n\r\n {/** Offset */}\r\n
\r\n
\r\n {t('measure.station-distAcross')}\r\n
\r\n\r\n
\r\n {formatter.formatOffset(measurement)}\r\n
\r\n
\r\n
\r\n );\r\n};\r\n\r\ninterface MeasurementCardProps {\r\n first: boolean;\r\n measurement: Measurement;\r\n}\r\n\r\nconst MeasurementCard = (props: MeasurementCardProps) => {\r\n const {measurement, first} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const renameDialog = useDialog();\r\n const deleteDialog = useDialog();\r\n\r\n const [expanded, setExpanded] = useState(false);\r\n const formatter = viewer.getMeasurementFormatter();\r\n\r\n const onMouseOver = () => {\r\n viewer?.updateMeasureHover(measurement, true);\r\n };\r\n\r\n const onMouseLeave = () => {\r\n viewer?.updateMeasureHover(measurement, false);\r\n };\r\n\r\n const generateVertexPositions = () => {\r\n if (!(measurement instanceof Measurement3D)) {\r\n return ();\r\n }\r\n\r\n const precision = formatter.getVectorPrecision(LocalScene.viewProjection);\r\n const verticesReprojected = measurement.vertices.map(vertex => {\r\n return vertex.toViewProjection();\r\n });\r\n\r\n const singlePoint = verticesReprojected.length === 1;\r\n\r\n if (singlePoint) {\r\n const x = verticesReprojected[0].x.toFixed(precision.x);\r\n const y = verticesReprojected[0].y.toFixed(precision.y);\r\n const z = verticesReprojected[0].z.toFixed(precision.z);\r\n const text = `(${x}, ${y}, ${z})`;\r\n\r\n return (\r\n
\r\n {/** Single point */}\r\n
\r\n
\r\n {t('measure.position')}\r\n
\r\n\r\n \r\n
{text}
\r\n
\r\n
\r\n
\r\n );\r\n }\r\n\r\n return (\r\n \r\n \r\n\r\n \r\n \r\n \r\n {t('measure.measurement_positions_xyz')}\r\n \r\n \r\n \r\n\r\n \r\n {verticesReprojected.map((vertex, index) => {\r\n const x = vertex.x.toFixed(precision.x);\r\n const y = vertex.y.toFixed(precision.y);\r\n const z = vertex.z.toFixed(precision.z);\r\n const text = `(${x}, ${y}, ${z})`;\r\n\r\n return (\r\n \r\n \r\n \r\n
{text}
\r\n
\r\n
\r\n
\r\n );\r\n\r\n })}\r\n
\r\n\r\n
\r\n
\r\n );\r\n };\r\n\r\n const handleRenameSubmit = name => {\r\n renameDialog.handleClose();\r\n viewer?.renameMeasurement(measurement, name);\r\n };\r\n\r\n const handleDeleteSubmit = () => {\r\n deleteDialog.handleClose();\r\n viewer?.deleteMeasurement(measurement);\r\n };\r\n\r\n useEffect(() => {\r\n setExpanded(first);\r\n }, [first]);\r\n\r\n const positions = generateVertexPositions();\r\n\r\n const is3DPoint = measurement instanceof MeasurementPoint;\r\n const is3DArea = measurement instanceof MeasurementArea;\r\n const isVolume = measurement instanceof MeasurementVolume;\r\n const is2DArea = measurement instanceof AerialAreaMeasurement;\r\n const is3DLength = measurement instanceof Measurement3D && !is3DPoint && !is3DArea;\r\n const is2DLength = measurement instanceof AerialLengthMeasurement;\r\n const hasHeight = measurement instanceof HeightMeasurement;\r\n const isStationMeasurement = measurement instanceof StationMeasurement;\r\n\r\n return (\r\n \r\n \r\n {/* Header */}\r\n \r\n {/* Expand/collapse measurement */}\r\n \r\n {\r\n event.stopPropagation();\r\n setExpanded(!expanded);\r\n }}\r\n >\r\n {expanded && }\r\n {!expanded && }\r\n \r\n \r\n\r\n {/* Rename measurement */}\r\n \r\n {\r\n event.stopPropagation();\r\n renameDialog.handleOpen();\r\n }}\r\n >\r\n \r\n \r\n \r\n\r\n {/* Delete measurement */}\r\n \r\n {\r\n event.stopPropagation();\r\n deleteDialog.handleOpen();\r\n }}\r\n >\r\n \r\n \r\n \r\n\r\n \r\n }\r\n title={measurement.title}\r\n titleTypographyProps={{\r\n variant: \"body2\",\r\n className: classes.headerTitle\r\n }}\r\n subheader={t('measure.total-vertices-measurement', {\r\n count: measurement.numVertices\r\n })}\r\n subheaderTypographyProps={{\r\n variant: \"caption\"\r\n }}\r\n />\r\n\r\n {/* Expandable content */}\r\n {expanded && (\r\n \r\n\r\n {is3DLength && }\r\n\r\n {hasHeight && }\r\n\r\n {is3DArea && }\r\n\r\n {is2DArea && }\r\n\r\n {is2DLength && }\r\n\r\n {isVolume && }\r\n\r\n {isStationMeasurement && }\r\n\r\n {positions}\r\n\r\n \r\n )}\r\n \r\n\r\n {/* Delete Dialog */}\r\n \r\n\r\n {/* Rename Dialog */}\r\n \r\n
\r\n );\r\n};\r\n\r\ninterface MeasurementsProps {\r\n open: boolean;\r\n onClose: () => void;\r\n measurements: Measurement[];\r\n}\r\n\r\nexport const Measurements = memo((props: MeasurementsProps) => {\r\n const {open, onClose, measurements} = props;\r\n\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const dispatch = useDispatch();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n const contextMenu = useContextMenu();\r\n const exportDialog = useDialog();\r\n const uniqueProjectID = useUniqueProjectID();\r\n const {setActiveToolOpen} = useActiveTool();\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const xmlAssets = getLandXMLAssets(assets);\r\n\r\n const dataProjection = useSelector(selectDataProjection);\r\n const measurementUnits = useSelector(selectMeasureUnits);\r\n\r\n const [activeMeasurePrompt, setActiveMeasurePrompt] = useState(false);\r\n const [measureType, setMeasureType] = useState(MeasureType.None);\r\n const [alignmentChoice, setAlignmentChoice] = useState(\"\");\r\n const [measureUnits, setMeasureUnits] = useState(Units.Meters);\r\n\r\n const loadImportData = (text) => {\r\n let encoded = decodeURIComponent(text);\r\n let data = JSON.parse(encoded);\r\n viewer.loadMeasurementData(data);\r\n };\r\n\r\n const openImportElectron = () => {\r\n dialog.showOpenDialog({\r\n filters: measureDataFilter,\r\n properties: ['openFile']\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n if (result.filePaths) {\r\n const filePath = slash(result.filePaths[0]);\r\n fs.readFile(filePath, 'utf-8', (err, text) => {\r\n if (err) {\r\n dialog.showErrorBox(t('dialog.measure-load-title'),\r\n t('dialog.measure-load-message'));\r\n }\r\n\r\n loadImportData(text);\r\n });\r\n }\r\n }).catch(() => {\r\n dialog.showErrorBox(t(\"dialog.general-error-title\"),\r\n t(\"dialog.file-load-error\"));\r\n });\r\n };\r\n\r\n const openImportBrowser = () => {\r\n fileDialog({accept: `.${measureDataFormat}`})\r\n .then(files => {\r\n if (files.length === 0) {\r\n return;\r\n }\r\n\r\n let reader = new FileReader();\r\n reader.onload = event => {\r\n let text = event.target.result;\r\n loadImportData(text);\r\n };\r\n reader.readAsText(files[0]);\r\n });\r\n };\r\n\r\n const onExport = () => {\r\n contextMenu.handleClose();\r\n exportDialog.handleOpen();\r\n };\r\n\r\n const onImport = () => {\r\n contextMenu.handleClose();\r\n\r\n if (isStaticSite) {\r\n openImportBrowser();\r\n } else {\r\n openImportElectron();\r\n }\r\n };\r\n\r\n const handleUnitsChange = (event) => {\r\n const value = event.target.value;\r\n dispatch(changeMeasureUnits(value));\r\n };\r\n\r\n const onModalClose = () => {\r\n setActiveMeasurePrompt(false);\r\n };\r\n\r\n const checkClose = () => {\r\n if (measurements.length > 0) {\r\n setActiveMeasurePrompt(true);\r\n return;\r\n }\r\n\r\n onClose();\r\n };\r\n\r\n /** Update the default dropdown value if no alignment is selected */\r\n const updateDefaultDropdown = () => {\r\n const xmlAlignments = xmlAssets.map(asset => {\r\n const alignments = (asset.data as XMLData).alignments;\r\n return alignments.map(alignment => alignment.id);\r\n }).flat();\r\n\r\n if (xmlAlignments.includes(alignmentChoice)) return;\r\n setAlignmentChoice(xmlAlignments[0]);\r\n };\r\n\r\n useEffect(() => {\r\n /** Keep track if a tool is currently being used */\r\n setActiveToolOpen(open);\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n /** Close dialog when new project is loaded */\r\n onClose();\r\n }, [uniqueProjectID]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.toggleMeasurements(open);\r\n viewer.setMeasurementType(measureType);\r\n }, [viewer, open]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setMeasurementType(measureType);\r\n }, [viewer, measureType]);\r\n\r\n useEffect(() => {\r\n if (!measurementUnits) return;\r\n\r\n setMeasureUnits(measurementUnits);\r\n viewer?.setMeasurementUnits(measurementUnits);\r\n }, [viewer, measurementUnits]);\r\n\r\n useEffect(() => {\r\n onClose();\r\n }, [dataProjection]);\r\n\r\n useEffect(() => {\r\n if (!viewer) return;\r\n viewer.setActiveAlignment(alignmentChoice);\r\n }, [viewer, alignmentChoice]);\r\n\r\n useEffect(() => {\r\n if (xmlAssets.length === 0) {\r\n setAlignmentChoice(\"\");\r\n if (!isStationMeasurement) return;\r\n setMeasureType(MeasureType.Length);\r\n } else {\r\n updateDefaultDropdown();\r\n }\r\n }, [xmlAssets]);\r\n\r\n const reversed = [...measurements].reverse();\r\n const iconProps = {classes, measureType, setMeasureType};\r\n\r\n const exportDisabled = measurements.length === 0;\r\n const importDisabled = viewer?.hasCameras || viewer?.hasPoints;\r\n const isImageOnly = viewer?.isImageOnly;\r\n\r\n const isStationMeasurement = (measureType === MeasureType.Station);\r\n const allowStationMeasurements = xmlAssets.length > 0;\r\n\r\n return (\r\n \r\n \r\n {/* Measurement icons */}\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n {(isImageOnly === false) && ()}\r\n\r\n {(isImageOnly === false) && ()}\r\n\r\n {(isImageOnly === false) && ()}\r\n\r\n \r\n\r\n {(isImageOnly === false) && ()}\r\n\r\n {(allowStationMeasurements) && ()}\r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n {/* Alignment dropdown */}\r\n {isStationMeasurement && allowStationMeasurements && \r\n \r\n {t(\"measure.alignment\")}\r\n \r\n\r\n {\r\n let value = event.target.value as any;\r\n setAlignmentChoice(value);\r\n }}\r\n >\r\n {xmlAssets.map(asset => {\r\n const alignments = (asset.data as XMLData).alignments;\r\n\r\n return [\r\n \r\n {asset.name}\r\n ,\r\n\r\n ...alignments.map(alignment =>\r\n \r\n {alignment.name}\r\n \r\n )\r\n ];\r\n }).flat()}\r\n \r\n }\r\n\r\n \r\n\r\n {/* Measurement list */}\r\n \r\n {measurements.length === 0 && (\r\n {t('measure.no-measurements-have-been-added')}\r\n )}\r\n\r\n \r\n {reversed.map((measurement, index) =>\r\n \r\n )}\r\n \r\n \r\n\r\n {/* Measurement footer */}\r\n
\r\n\r\n {/* Measurement units */}\r\n
\r\n \r\n }\r\n label={{t('units.meters')}}\r\n />\r\n\r\n }\r\n label={{t('units.feet')}}\r\n />\r\n\r\n }\r\n label={{t('units.survey-feet')}}\r\n />\r\n \r\n
\r\n\r\n
\r\n \r\n\r\n {/* Import/Export menu */}\r\n \r\n \r\n {t('measure.export-measurements')}\r\n \r\n\r\n \r\n {t('measure.import-measurements')}\r\n \r\n \r\n\r\n {/* Export Measurements */}\r\n \r\n\r\n {/* Discard measurements dialog */}\r\n {\r\n onModalClose();\r\n onClose();\r\n }}\r\n title={t('asset.discard-measurements')}\r\n prompt={t('asset.active-measurements-found')}\r\n button={t('buttons.discard')}\r\n />\r\n\r\n
\r\n );\r\n});\r\n","import React, {useEffect, useState, memo} from \"react\";\r\nimport { Button, Theme } from \"@mui/material\";\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport {\r\n CursorTooltip,\r\n DraggableDialog,\r\n PromptDialog\r\n} from \"../components\";\r\nimport { MultiImageOptions } from \"../viewer/controls\";\r\nimport LocalScene from \"../viewer/projections\";\r\nimport { roundDigit, UnitConverter } from \"../viewer/utilities\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useViewer } from \"../hooks\";\r\nimport { Units } from \"../types/project\";\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n buttonParentLeft: {\r\n position: \"absolute\",\r\n bottom: \"0px\",\r\n },\r\n buttonParentRight: {\r\n position: \"absolute\",\r\n bottom: \"0px\",\r\n right: \"0px\"\r\n },\r\n smallButton: {\r\n padding: theme.spacing(0.5, 1),\r\n margin: theme.spacing(0.75),\r\n fontSize: \"0.6rem\"\r\n },\r\n buttonRight: {\r\n float: \"right\"\r\n },\r\n multiImageHeader: {\r\n position: \"absolute\",\r\n display: \"inline-block\",\r\n background: \"rgba(255,255,255,0.75)\",\r\n boxShadow: \"5px 5px 5px rgb(0 0 0 / 25%)\",\r\n margin: \"10px\",\r\n padding: \"10px\",\r\n top: \"0px\",\r\n borderRadius: \"3px\",\r\n fontSize: \"0.8em\",\r\n userSelect: \"none\",\r\n fontFamily: theme.typography.fontFamily,\r\n \"& div:not(:last-child)\": {\r\n paddingBottom: theme.spacing(0.75)\r\n }\r\n }\r\n }),\r\n);\r\n\r\ninterface WindowButtonProps {\r\n text: string;\r\n hidden?: boolean;\r\n disabled: boolean;\r\n onClick: () => void;\r\n color: \"inherit\" | \"primary\" | \"secondary\" | \"error\" | \"info\" | \"success\" | \"warning\"\r\n}\r\n\r\nconst WindowButton = (props: WindowButtonProps) => {\r\n const {text, hidden=false, disabled, onClick, color} = props;\r\n\r\n const classes = useStyles();\r\n\r\n return (\r\n \r\n {!hidden && ({text})}\r\n \r\n );\r\n};\r\n\r\ninterface MultiImageInfoProps {\r\n state: MultiImageOptions\r\n}\r\n\r\nconst MultiImageInfo = (props: MultiImageInfoProps) => {\r\n const {state} = props;\r\n\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n\r\n const clampedColor = (value, minValue, midValue) => {\r\n if (value < minValue) {\r\n return \"green\";\r\n }\r\n\r\n if (value < midValue) {\r\n return \"#f89406\";\r\n }\r\n\r\n return \"red\";\r\n };\r\n\r\n const {coordinates, intersect} = state;\r\n const {error, distances, calculated, valid, message} = intersect;\r\n const units = LocalScene.dataProjectionUnits;\r\n const converter = new UnitConverter();\r\n\r\n const observationStyle1 = {color: coordinates[0] ? \"green\" : \"red\"};\r\n const observationStyle2 = {color: coordinates[1] ? \"green\" : \"red\"};\r\n\r\n const observationText1 = coordinates[0]\r\n ? t('measure.selected')\r\n : t('measure.not-selected');\r\n\r\n const observationText2 = coordinates[1]\r\n ? t('measure.selected')\r\n : t('measure.not-selected');\r\n\r\n const errorStyle = {color: clampedColor(error, 0.1, 0.25)};\r\n const errorValue = roundDigit(converter.convert(error, Units.Meters, units), 4);\r\n const errorElement = {errorValue}{units};\r\n\r\n const distanceStyle1 = {color: clampedColor(distances[0], 0.1, 0.25)};\r\n const distanceValue1 = roundDigit(converter.convert(distances[0], Units.Meters, units), 2);\r\n const distanceElement1 = {distanceValue1}{units};\r\n\r\n const distanceStyle2 = {color: clampedColor(distances[1], 0.1, 0.25)};\r\n const distanceValue2 = roundDigit(converter.convert(distances[1], Units.Meters, units), 2);\r\n const distanceElement2 = {distanceValue2}{units};\r\n\r\n return (\r\n
\r\n\r\n {/* Calculated information */}\r\n {calculated && (\r\n
\r\n {`${t('measure.estimated-error')}: `}\r\n {errorElement}\r\n
\r\n\r\n
\r\n {`${t('measure.camera-distance-1')}: `}\r\n {distanceElement1}\r\n
\r\n\r\n
\r\n {`${t('measure.camera-distance-2')}: `}\r\n {distanceElement2}\r\n
\r\n
)}\r\n\r\n {/* Observation status */}\r\n {!calculated && (\r\n\r\n
\r\n {`${t('measure.observation-1')}: `}\r\n {observationText1}\r\n
\r\n\r\n
\r\n {`${t('measure.observation-2')}: `}\r\n {observationText2}\r\n
\r\n
)}\r\n\r\n {/* Status message */}\r\n {!valid && (
\r\n {`${t('measure.status')}: `}\r\n {message}\r\n
)}\r\n\r\n\r\n
\r\n );\r\n};\r\n\r\ninterface MultiImageWindowProps {\r\n open: boolean;\r\n setOpen: React.Dispatch;\r\n state: MultiImageOptions;\r\n}\r\n\r\nexport const MultiImageWindow = memo((props: MultiImageWindowProps) => {\r\n const {state, open, setOpen} = props;\r\n\r\n const classes = useStyles();\r\n const {viewer} = useViewer();\r\n const {t} = useTranslation();\r\n\r\n const [customPromptOpen, setCustomPromptOpen] = useState(false);\r\n const [customPromptState, setCustomPromptState] = useState({\r\n title: null,\r\n text: null,\r\n callback: () => {}\r\n });\r\n\r\n const onClose = () => {\r\n const result = viewer.multiImageOnClose();\r\n\r\n if (result) {\r\n setCustomPromptState({...result});\r\n setCustomPromptOpen(true);\r\n } else {\r\n setOpen(false);\r\n }\r\n };\r\n\r\n const onRefModified = (container) => {\r\n if (!container) return;\r\n viewer.initMultiImageContainer(container);\r\n };\r\n\r\n const onNextImage = () => {\r\n viewer.multiImageNextImage();\r\n };\r\n\r\n const onPreviousImage = () => {\r\n viewer.multiImagePreviousImage();\r\n };\r\n\r\n const onComplete = () => {\r\n viewer.multiImageOnComplete();\r\n };\r\n\r\n const onAddPoint = () => {\r\n viewer.multiImageOnAddPoint();\r\n };\r\n\r\n useEffect(() => {\r\n viewer?.toggleMultiImageWindow(open);\r\n }, [open]);\r\n\r\n const {canAddMore, canComplete, disableAddMore, disableComplete,\r\n disablePreviousImage, disableNextImage} = state;\r\n\r\n const textLines = [\r\n t('measure.click-to-add-observation-2')\r\n ];\r\n\r\n return (\r\n \r\n \r\n {/* Canvas element */}\r\n \r\n \r\n \r\n\r\n {state.intersect && ()}\r\n\r\n
\r\n\r\n {/* Previous Image */}\r\n \r\n\r\n {/* Next Image */}\r\n \r\n\r\n
\r\n\r\n
\r\n\r\n {/* Add Point */}\r\n
\r\n\r\n \r\n\r\n {/* Custom close prompt */}\r\n {\r\n setCustomPromptOpen(false);\r\n }}\r\n onSubmit={() => {\r\n setOpen(false);\r\n setCustomPromptOpen(false);\r\n customPromptState.callback();\r\n }}\r\n title={customPromptState.title}\r\n prompt={customPromptState.text}\r\n button={t('buttons.discard')}\r\n />\r\n
\r\n );\r\n});","export default __webpack_public_path__ + \"static/media/solv3d-logo.f4dfa411.png\";","import React, {useEffect} from \"react\";\r\nimport {registerEvent} from \"./electron-modules\";\r\nimport {Dialog, DialogContent, DialogTitle, Link, Paper, Typography} from \"@mui/material\";\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport logoPath from \"./viewer/textures/misc/solv3d-logo.png\";\r\nimport manifest from \"../package.json\";\r\nimport clsx from 'clsx';\r\nimport CloseIcon from \"@mui/icons-material/Close\";\r\nimport IconButton from \"@mui/material/IconButton\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useDialog } from \"./hooks\";\r\n\r\nconst useStyles = makeStyles((theme) => ({\r\n dependencies: {\r\n fontSize: \"18px\",\r\n fontWeight: 500\r\n },\r\n dialog: {\r\n overflowY: \"auto\",\r\n },\r\n dialogDiv: {\r\n position: \"fixed\",\r\n overflowY: \"auto\",\r\n display: \"block\"\r\n },\r\n dialogContent: {\r\n textAlign: \"center\",\r\n lineHeight: 1,\r\n fontFamily: \"sans-serif\",\r\n overflowY: \"initial\"\r\n },\r\n dialogPaper: {\r\n overflowY: \"initial\",\r\n maxHeight: \"fit-content\",\r\n top: \"65px\"\r\n },\r\n divContent: {\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center'\r\n },\r\n iconButton: {\r\n position: 'absolute',\r\n right: 8,\r\n top: 8\r\n },\r\n indent: {\r\n paddingLeft: \"2px\"\r\n },\r\n links: {\r\n color: \"#5c76c0\",\r\n display: \"block\",\r\n padding: theme.spacing(0.5)\r\n },\r\n listItems: {\r\n fontSize: \"14px\",\r\n },\r\n logoImage: {\r\n width: \"400px\",\r\n maxWidth: \"50%\"\r\n },\r\n paper: {\r\n overflowY: \"initial\"\r\n },\r\n support: {\r\n fontSize: \"14px\",\r\n fontWeight: 700\r\n },\r\n titleParent: {\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n },\r\n title: {\r\n userSelect: \"none\",\r\n flex: \"1 !important\"\r\n },\r\n close: {\r\n color: theme.palette.grey[500],\r\n marginRight: theme.spacing(1)\r\n }\r\n})\r\n);\r\n\r\nexport const AboutDialog = () => {\r\n const classes = useStyles();\r\n const {t} = useTranslation();\r\n const helpDialog = useDialog();\r\n\r\n const javascriptDependencies = {\r\n jquery: manifest.dependencies.jquery,\r\n ol: manifest.dependencies.ol,\r\n react: manifest.dependencies.react,\r\n three: manifest.dependencies.three,\r\n typescript: manifest.dependencies.typescript,\r\n electron: manifest.devDependencies.electron\r\n };\r\n\r\n // Python packages\r\n const pythonDependencies = {\r\n numpy:'1.17.1',\r\n scipy: '1.1.0',\r\n 'scikit-learn': '0.20.3',\r\n matplotlib: '2.2.4',\r\n pykml: '0.1.3',\r\n lxml: '4.4.1'\r\n };\r\n\r\n const miscDependancies = [\r\n {\r\n \"name\": \"detectron2\",\r\n \"version\": \"2.0\",\r\n \"href\": 'https://github.com/facebookresearch/detectron2'\r\n }, {\r\n \"name\": \"PotreeConvertor.exe\",\r\n \"version\": \"2.1.1\",\r\n \"href\": 'https://github.com/potree/PotreeConverter'\r\n }, {\r\n \"name\": \"laszip-cli.exe\",\r\n \"version\": \"3.2.9\",\r\n \"href\": 'https://github.com/LASzip/LASzip'\r\n }, {\r\n \"name\": \"pytorch\",\r\n \"version\": \"1.7.0\",\r\n \"href\": 'https://pytorch.org/'\r\n }, {\r\n \"name\": \"tensorboard\",\r\n \"version\": \"2.3.0\",\r\n \"href\": 'https://www.tensorflow.org/tensorboard'\r\n }\r\n ];\r\n\r\n const getDependencies = () => {\r\n let jsDependencies = Object.keys(javascriptDependencies).map(key => {\r\n let data = javascriptDependencies[key];\r\n let version = data.replace('^', '');\r\n\r\n return {\r\n \"name\": key,\r\n \"version\": version,\r\n \"href\": `https://www.npmjs.com/package/${key}`\r\n };\r\n });\r\n\r\n let pyDependencies = Object.keys(pythonDependencies).map(key => {\r\n let version = pythonDependencies[key].replace('^', '');\r\n\r\n return {\r\n \"name\": key,\r\n \"version\": version,\r\n \"href\": `https://pypi.python.org/pypi/${key}`\r\n };\r\n });\r\n\r\n let final = [\r\n ...jsDependencies,\r\n ...pyDependencies,\r\n ...miscDependancies\r\n ];\r\n\r\n // Sort data by key\r\n final.sort((a, b) => {\r\n return a.name.toLowerCase() > b.name.toLowerCase() ? 1 : -1;\r\n });\r\n\r\n return final;\r\n };\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-about\", () => {\r\n helpDialog.handleOpen();\r\n });\r\n }, [helpDialog]);\r\n\r\n const dependencies = getDependencies();\r\n\r\n return (\r\n
\r\n \r\n
\r\n \r\n {t(\"about.title\")}\r\n \r\n\r\n {/* Close button */}\r\n \r\n \r\n \r\n
\r\n\r\n \r\n \r\n {\"Solv3D\r\n \r\n\r\n

{manifest.productName} v{manifest.version}

\r\n SOLV3D Inc. Support
\r\n\r\n \r\n help@solv3d.com\r\n \r\n\r\n \r\n solv3d.com\r\n \r\n\r\n \r\n {t(\"about.licence\")}\r\n \r\n\r\n

\r\n {t(\"about.heading\")}\r\n

\r\n\r\n {dependencies.map((item, index) => (\r\n
\r\n \r\n {item.name}\r\n \r\n ({item.version})\r\n
\r\n ))}\r\n\r\n
\r\n \r\n
\r\n );\r\n};","import React, {\r\n useState,\r\n useEffect,\r\n useRef,\r\n} from \"react\";\r\nimport CloseIcon from '@mui/icons-material/Close';\r\nimport { Theme, Dialog, DialogTitle, IconButton, List, ListItem, ListItemText } from \"@mui/material\";\r\nimport makeStyles from '@mui/styles/makeStyles';\r\nimport createStyles from '@mui/styles/createStyles';\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { useTaskQueue } from \"./hooks\";\r\nimport { TaskStatus } from \"./providers\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n consoleDialogHeader: {\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n },\r\n consoleDialogTitle: {\r\n userSelect: \"none\",\r\n flex: 1,\r\n paddingBottom: \"2px\",\r\n paddingTop: \"2px\"\r\n },\r\n consoleDialogClose: {\r\n color: theme.palette.grey[500],\r\n paddingBottom: \"2px\",\r\n paddingTop: \"2px\"\r\n },\r\n consoleHeight: {\r\n background: \"black\",\r\n height: \"min(50vh, 300px)\",\r\n color: \"white\",\r\n overflowY: \"scroll\"\r\n },\r\n consoleLine: {\r\n padding: theme.spacing(0, 1),\r\n wordBreak: \"break-all\"\r\n }\r\n })\r\n);\r\n\r\nexport const TaskQueue = () => {\r\n /**\r\n * NOTE: this will be selectable from a seperate ui later, but now it\r\n * gets automatically set to the current running task. Move this to some other file\r\n * when the final ui is made.\r\n **/\r\n\r\n const {taskQueue} = useTaskQueue();\r\n const runningTask = taskQueue\r\n .find(task => task.status === TaskStatus.Running);\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\ninterface ConsoleWindowProps {\r\n selectedTaskID: string;\r\n}\r\n\r\nconst ConsoleWindow = (props: ConsoleWindowProps) => {\r\n const {selectedTaskID} = props;\r\n\r\n const classes = useStyles();\r\n const listRef = useRef(null);\r\n const {t} = useTranslation();\r\n\r\n const [lineData, setLineData] = useState([]);\r\n const {taskQueue, stopRunningTask} = useTaskQueue();\r\n\r\n const textUpdateMilliseconds = 100;\r\n const activeTask = taskQueue\r\n .find(task => task.id === selectedTaskID);\r\n\r\n // NOTE: when this is selecteable from an ui, the close button wont actually\r\n // kill the process, it will only set the selectedTaskID to null\r\n const onCancel = () => {\r\n stopRunningTask(selectedTaskID);\r\n };\r\n\r\n useEffect(() => {\r\n if (!activeTask) return;\r\n\r\n // Initial exe logs\r\n setLineData(activeTask.exe.logText);\r\n\r\n const interval = setInterval(() => {\r\n // Check for new data if the exe is still running\r\n if (!activeTask || !activeTask.exe.running) return;\r\n setLineData([...activeTask.exe.logText]);\r\n }, textUpdateMilliseconds);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [activeTask]);\r\n\r\n useEffect(() => {\r\n if (!listRef.current) return;\r\n\r\n // Auto-scroll to bottom when new data is read\r\n const height = listRef.current.scrollHeight;\r\n listRef.current.scrollTop = height;\r\n }, [listRef, lineData]);\r\n\r\n return (\r\n \r\n
\r\n \r\n {t('console.output_logs')}\r\n \r\n\r\n {/* Close button */}\r\n \r\n \r\n \r\n
\r\n\r\n
\r\n
\r\n \r\n {lineData.map((line, index) =>\r\n \r\n \r\n {line}\r\n \r\n )\r\n }\r\n \r\n
\r\n
\r\n\r\n \r\n );\r\n};\r\n","import { useCallback, useState } from \"react\";\r\nimport { t } from \"../localization\";\r\nimport { ItemSearchState, SortBy, SortDir, SortOption } from \"../types/search\";\r\n\r\nexport const getSortOptions = () => {\r\n const sortOptions: SortOption[] = [\r\n {\r\n label: t('item-search.name_ascending'),\r\n value: {\r\n sortDir: 'asc',\r\n sortBy: 'name'\r\n }\r\n },\r\n {\r\n label: t('item-search.name_descending'),\r\n value: {\r\n sortDir: 'desc',\r\n sortBy: 'name'\r\n }\r\n },\r\n {\r\n label: t('item-search.date_ascending'),\r\n value: {\r\n sortDir: 'asc',\r\n sortBy: 'date'\r\n }\r\n },\r\n {\r\n label: t('item-search.date_descending'),\r\n value: {\r\n sortDir: 'desc',\r\n sortBy: 'date'\r\n }\r\n }\r\n ];\r\n\r\n return sortOptions;\r\n};\r\n\r\nexport const useItemsSearch = () => {\r\n const [state, setState] = useState({\r\n sortDir: \"asc\",\r\n sortBy: \"name\",\r\n query: \"\"\r\n });\r\n\r\n const handleSearchChange = useCallback((query: string): void => {\r\n setState((prevState) => ({...prevState, query}));\r\n }, []);\r\n\r\n const handleSortChange = useCallback((sortDir: SortDir, sortBy: SortBy): void => {\r\n setState((prevState) => ({...prevState, sortDir, sortBy}));\r\n }, []);\r\n\r\n const sortByDate = (items: any[], sortDir: SortDir) => {\r\n return [...items].sort((a, b) => {\r\n const dateA = new Date(a.timeCreated);\r\n const dateB = new Date(b.timeCreated);\r\n\r\n return (sortDir === \"asc\")\r\n ? (dateA > dateB ? 1 : -1)\r\n : (dateB > dateA ? 1 : -1);\r\n });\r\n };\r\n\r\n const sortByName = (items: any[], sortDir: SortDir) => {\r\n return [...items].sort((a, b) => {\r\n const nameA = a.name as string;\r\n const nameB = b.name as string;\r\n\r\n return (sortDir === \"asc\")\r\n ? nameA.localeCompare(nameB)\r\n : nameB.localeCompare(nameA);\r\n });\r\n };\r\n\r\n const handleSearch = (items: any[]) => {\r\n const query = state.query;\r\n if (!query) return items;\r\n\r\n const queryParts = query\r\n .split(\" \")\r\n .map(x => x.toLowerCase());\r\n\r\n return items.filter(project => {\r\n const nameParts = project.name\r\n .split(\" \")\r\n .map(x => x.toLowerCase());\r\n\r\n return queryParts.filter(text => {\r\n return nameParts.filter(x => x.includes(text)).length > 0;\r\n }).length === queryParts.length;\r\n });\r\n };\r\n\r\n const handleSort = (items: any[]) => {\r\n const {sortDir, sortBy} = state;\r\n if (!sortDir) return items;\r\n\r\n // Initial sorting by date is always applied\r\n let initialSort = sortByDate(items, \"asc\");\r\n\r\n if (sortBy === \"date\") {\r\n return sortByDate(initialSort, sortDir);\r\n }\r\n\r\n return sortByName(initialSort, sortDir);\r\n };\r\n\r\n return {\r\n handleSearch,\r\n handleSearchChange,\r\n handleSort,\r\n handleSortChange,\r\n state\r\n };\r\n};","import React, { useEffect, useState } from \"react\";\r\nimport {\r\n Box,\r\n List,\r\n ListItemButton,\r\n ListItemText,\r\n MenuItem,\r\n TextField,\r\n Typography\r\n} from \"@mui/material\";\r\nimport { useTheme } from \"@mui/material/styles\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { SimpleDialog } from \"./components\";\r\nimport { dialog, registerEvent } from \"./electron-modules\";\r\nimport { useAuth, useDialog, useGlobalSettings, useWebSockets } from \"./hooks\";\r\nimport { SortOption } from \"./types/search\";\r\nimport stc from \"string-to-color\";\r\nimport { getSortOptions, useItemsSearch } from \"./hooks/use-item-search\";\r\nimport { clearWindowHash, loadProjectJSON, toLocaleString } from \"./utilities\";\r\nimport { hideBackdrop, showBackdrop, toast } from \"./app\";\r\nimport { engineCloudURL } from \"./urls\";\r\n\r\ninterface CloudProject {\r\n id: string;\r\n name: string;\r\n timeCreated: string\r\n}\r\n\r\ninterface ProjectListRowProps {\r\n project: CloudProject;\r\n onClose: () => void;\r\n}\r\n\r\nconst ProjectListRow = (props: ProjectListRowProps) => {\r\n const {project, onClose} = props;\r\n\r\n const {i18n, t} = useTranslation();\r\n const theme = useTheme();\r\n const websockets = useWebSockets();\r\n const globalSettings = useGlobalSettings();\r\n\r\n const onClick = async () => {\r\n onClose();\r\n\r\n showBackdrop();\r\n\r\n toast.success(t(\"toast.load-cloud-project\", {name: project.name}));\r\n\r\n const url = `${engineCloudURL}/viewer/${project.id}`;\r\n\r\n // Load project config\r\n const projectResponse = await fetch(`${url}/static.json`);\r\n const config = await projectResponse.json();\r\n\r\n // Load global settings\r\n const settingsResponse = await fetch(`${url}/global-settings.json`);\r\n const settingsJSON = await settingsResponse.json();\r\n globalSettings.update(settingsJSON);\r\n\r\n clearWindowHash();\r\n loadProjectJSON(config);\r\n\r\n const projectID = config.project.id;\r\n websockets.joinRoom(projectID);\r\n\r\n hideBackdrop();\r\n };\r\n\r\n const dateString = toLocaleString(project.timeCreated, i18n.language);\r\n const accentColor = stc(project.name);\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const CloudProjectList = () => {\r\n const {t} = useTranslation();\r\n const {linkAccount, checkVersion, loggedIn} = useAuth();\r\n const projectDialog = useDialog();\r\n const theme = useTheme();\r\n\r\n const [userProjects, setUserProjects] = useState([]);\r\n const itemsSearch = useItemsSearch();\r\n const sortOptions = getSortOptions();\r\n\r\n const getUserProjects = async () => {\r\n try {\r\n const url = `${engineCloudURL}/api/projects`;\r\n const response = await fetch(url);\r\n const data = await response.json();\r\n\r\n const projects = data\r\n .filter(project => project.isAdmin)\r\n .map(project => {\r\n return {\r\n id: project.id,\r\n name: project.name as string,\r\n timeCreated: project.timeCreated as string\r\n } as CloudProject;\r\n });\r\n\r\n setUserProjects(projects);\r\n } catch {\r\n setUserProjects([]);\r\n }\r\n };\r\n\r\n const onSearchChange = event => {\r\n const query = event.target.value;\r\n itemsSearch.handleSearchChange(query);\r\n };\r\n\r\n const onSortChange = event => {\r\n const {sortDir, sortBy} = JSON.parse(event.target.value);\r\n itemsSearch.handleSortChange(sortDir, sortBy);\r\n };\r\n\r\n useEffect(() => {\r\n registerEvent(\"open-cloud-projects\", async () => {\r\n if (!loggedIn) {\r\n const success = await linkAccount();\r\n if (!success) return;\r\n }\r\n\r\n const valid = await checkVersion();\r\n if (!valid) {\r\n dialog.showErrorBox(t('version_check.title'), t('version_check.description'));\r\n return;\r\n }\r\n\r\n projectDialog.handleOpen();\r\n });\r\n }, [loggedIn]);\r\n\r\n useEffect(() => {\r\n if (!projectDialog.open) return;\r\n getUserProjects();\r\n }, [projectDialog.open]);\r\n\r\n let projects = [...userProjects];\r\n projects = itemsSearch.handleSearch(projects);\r\n projects = itemsSearch.handleSort(projects);\r\n\r\n const hasProjects = projects.length > 0;\r\n\r\n const sortValue = JSON.stringify({\r\n sortDir: itemsSearch.state.sortDir,\r\n sortBy: itemsSearch.state.sortBy\r\n });\r\n\r\n return (\r\n \r\n \r\n \r\n\r\n {/** Search text */}\r\n \r\n\r\n {/** Sort by dropdown */}\r\n \r\n {sortOptions.map((option: SortOption, index) => (\r\n \r\n {option.label}\r\n \r\n ))}\r\n \r\n\r\n \r\n\r\n {!hasProjects && \r\n \r\n \r\n {t('project-list.no_projects_found')}\r\n \r\n \r\n }\r\n\r\n {hasProjects && (\r\n \r\n {projects.map(project =>\r\n \r\n )}\r\n \r\n )}\r\n\r\n \r\n \r\n );\r\n};\r\n","import {MainAppHeader, MainAppFooter} from \"./app-bar\";\r\nimport React, {useEffect, useState} from \"react\";\r\nimport {GlobalSettings, SettingsDrawer, settingsDrawerWidth} from \"./settings\";\r\nimport {AssetDrawer, assetDrawerWidth} from \"./asset-drawer\";\r\nimport {ProjectionsDetector, ProjectionsManager} from \"./projections\";\r\nimport {ImageAlignerAdvanced, ImageAlignerBasic, LocalAligner} from \"./alignment\";\r\nimport {ImageLabelling} from \"./labelling\";\r\nimport {QuickNav} from \"./navigation\";\r\nimport {SceneViewer} from \"./viewer/viewer\";\r\nimport { Backdrop, Box, CircularProgress, DialogContentText, useTheme } from \"@mui/material\";\r\nimport {useDispatch, useSelector} from 'react-redux';\r\nimport {changeAssetDrawerState} from \"./redux/settings-slice\";\r\nimport {app, dialog, isCloudSite, isDevMode, isElectronApp, isStaticSite, remote} from \"./electron-modules\";\r\nimport slash from \"slash\";\r\nimport {isConfigFile, loadProjectJSON, useAssetTools} from \"./utilities\";\r\nimport {CloudExporter, StaticExporter} from \"./export\";\r\nimport {PythonExecutable, WorkflowExecutable} from \"./executable\";\r\nimport {PointMarkup} from \"./markup\";\r\nimport {Measurements, MultiImageWindow} from \"./measurements\";\r\nimport {AboutDialog} from \"./about\";\r\nimport {sendCustomEvent} from \"./events\";\r\nimport {PointProfile} from \"./point-profile\";\r\nimport {useTranslation} from \"react-i18next\";\r\nimport {assetFolderClass, TagDetailsDialog} from \"./folder\";\r\nimport {selectDefaultFolder} from \"./redux/folders-slice\";\r\nimport {TaskQueue} from \"./task-queue\";\r\nimport {useAuth, useDialog, useViewer, useWebSockets} from \"./hooks\";\r\nimport {CustomContextURL} from \"./context-menu\";\r\nimport {toast as hotToast} from 'react-hot-toast';\r\nimport {AlertDialog, Toaster} from \"./components\";\r\nimport {CloudProjectList} from \"./cloud-projects\";\r\nimport {parseURLParams} from \"./viewer/utilities\";\r\nimport {openExternalLink, redirectToLogin, setEngineCloudURL} from \"./urls\";\r\nimport {getLocalizedURL} from \"./localization\";\r\nimport { MultiImageOptions } from \"./viewer/controls\";\r\nimport manifest from \"../package.json\";\r\n\r\ninterface JSONData {\r\n license_check: {\r\n valid: boolean;\r\n expired: boolean;\r\n locked: boolean;\r\n offline: boolean;\r\n message: string;\r\n engineCloudURL?: string;\r\n }\r\n}\r\n\r\nexport const headerHeight = 48;\r\nexport const footerHeight = 24;\r\n\r\ninterface DragDropLoaderProps {\r\n children: React.ReactNode\r\n}\r\n\r\nconst DragDropLoader = (props: DragDropLoaderProps) => {\r\n const dispatch = useDispatch();\r\n const {addFilePaths} = useAssetTools();\r\n const defaultFolder = useSelector(selectDefaultFolder);\r\n\r\n const handleDrawerOpen = () => {\r\n dispatch(changeAssetDrawerState(true));\r\n };\r\n\r\n const handleDrop = event => {\r\n if (isStaticSite) return;\r\n\r\n // Drag and drop on specific folder is handled in folder.tsx\r\n const isFolder = !!event.target.closest(`.${assetFolderClass}`);\r\n if (isFolder) return;\r\n\r\n const filePaths = [...event.dataTransfer.files]\r\n .map(file => slash(file.path));\r\n\r\n const configs = filePaths.filter(isConfigFile);\r\n if (configs.length === 0) {\r\n handleDrawerOpen();\r\n }\r\n\r\n addFilePaths(filePaths, defaultFolder.id);\r\n };\r\n\r\n const handleDragOver = event => {\r\n if (isStaticSite) return;\r\n\r\n event.stopPropagation();\r\n event.preventDefault();\r\n };\r\n\r\n return (\r\n \r\n {props.children}\r\n
\r\n );\r\n};\r\n\r\nconst ProjectLoader = () => {\r\n const defaultFolder = useSelector(selectDefaultFolder);\r\n const {addFilePaths} = useAssetTools();\r\n const websockets = useWebSockets();\r\n\r\n const getAllFileArgs = () => {\r\n try {\r\n\r\n let rawArgs = remote.process.argv;\r\n let fileArgs = rawArgs.slice(1, rawArgs.length);\r\n return fileArgs.map((arg) => slash(arg.toString()));\r\n } catch {\r\n return null;\r\n }\r\n };\r\n\r\n /** Load files from launch arguments */\r\n const loadFromCompiledExe = () => {\r\n const filePaths = getAllFileArgs();\r\n addFilePaths(filePaths, defaultFolder.id);\r\n };\r\n\r\n /** Load project json from relative location */\r\n const loadFromStaticSite = async () => {\r\n // Block browser context menu\r\n window.oncontextmenu = event => {\r\n event.preventDefault();\r\n };\r\n\r\n showBackdrop();\r\n\r\n const cache = Date.now();\r\n const parameters = parseURLParams(window.location.href);\r\n const configRoot = isCloudSite ? window.location.pathname : \".\";\r\n const configURL = `${configRoot}/static.json?cache=${cache}`;\r\n\r\n try {\r\n const response = await fetch(configURL);\r\n const projectJSON = await response.json();\r\n loadProjectJSON(projectJSON, parameters);\r\n\r\n if (isCloudSite) {\r\n const cloudProject = projectJSON.project;\r\n websockets.joinRoom(cloudProject.id);\r\n }\r\n } catch {\r\n console.error(\"Error reading static config\");\r\n }\r\n\r\n hideBackdrop();\r\n };\r\n\r\n useEffect(() => {\r\n if (isStaticSite) {\r\n loadFromStaticSite();\r\n } else {\r\n loadFromCompiledExe();\r\n }\r\n }, []);\r\n\r\n return ;\r\n};\r\n\r\nconst AppBackdrop = () => {\r\n const theme = useTheme();\r\n\r\n const [backdropOpen, setBackdropOpen] = useState(false);\r\n\r\n /** Backdrop state event listener */\r\n useEffect(() => {\r\n const callback = (event) => {\r\n const {visible} = event.detail;\r\n setBackdropOpen(visible);\r\n };\r\n\r\n document.addEventListener(\"backdrop-state\", callback);\r\n\r\n return () => {\r\n document.removeEventListener(\"backdrop-state\", callback);\r\n };\r\n }, []);\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const AppWithAuth = () => {\r\n const [appAccess, setAppAccess] = useState(false);\r\n\r\n const {i18n, t} = useTranslation();\r\n const accessDialog = useDialog();\r\n const { initialized, loggedIn, permissions } = useAuth();\r\n\r\n useEffect(() => {\r\n if (!initialized) return;\r\n\r\n if (permissions.access) {\r\n setAppAccess(true);\r\n } else {\r\n accessDialog.handleOpen();\r\n }\r\n }, [initialized]);\r\n\r\n const onClose = () => {\r\n accessDialog.handleClose();\r\n\r\n if (loggedIn) {\r\n window.location.href = getLocalizedURL(\"/projects\", i18n.language);\r\n } else {\r\n redirectToLogin();\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n \r\n\r\n {appAccess && }\r\n\r\n \r\n \r\n {loggedIn && t('project_access.you_have_invalid_permissions')}\r\n {!loggedIn && t('project_access.you_have_invalid_viewonly')}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst App = () => {\r\n const {signOut} = useAuth();\r\n const {t} = useTranslation();\r\n\r\n const {viewer} = useViewer();\r\n const measurementsDialog = useDialog();\r\n const customURLDialog = useDialog();\r\n\r\n const [settingsDrawerState, setSettingsDrawerState] = useState(false);\r\n const [measurements, setMeasurements] = useState([]);\r\n const [localObservations, setLocalObservations] = useState([]);\r\n const [alignerObservations, setAlignerObservations] = useState([]);\r\n const [categoryList, setCategoryList] = useState([]);\r\n const [markupGroups, setMarkupGroups] = useState([]);\r\n const [trainingArea, setTrainingArea] = useState([]);\r\n const [multiImageOpen, setMultiImageOpen] = useState(false);\r\n const [pointProfileOpen, setPointProfileOpen] = useState(false);\r\n const [multiImageState, setMultiImageState] = useState({});\r\n\r\n /** Add a target to links that do not already have one */\r\n const handleLinkWithoutTargets = (event) => {\r\n const element = event.target;\r\n if (!element.href || element.target) return;\r\n event.preventDefault();\r\n openExternalLink(element.href);\r\n };\r\n\r\n useEffect(() => {\r\n document.addEventListener(\"click\", handleLinkWithoutTargets);\r\n\r\n return () => {\r\n document.removeEventListener(\"click\", handleLinkWithoutTargets);\r\n };\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isDevMode || isStaticSite) return;\r\n\r\n new PythonExecutable().run({\r\n commands: ['--check-tool', 'viewer'],\r\n onLine: (jsonData: JSONData) => {\r\n if (!jsonData.license_check) {\r\n return;\r\n }\r\n\r\n if (jsonData.license_check.engineCloudURL) {\r\n const modified = setEngineCloudURL(jsonData.license_check.engineCloudURL);\r\n\r\n if (modified) {\r\n signOut();\r\n }\r\n }\r\n\r\n const {valid, message} = jsonData.license_check;\r\n if (valid) return;\r\n\r\n const mainWindow = remote.getCurrentWindow();\r\n\r\n dialog.showMessageBox(mainWindow, {\r\n title: t(\"dialog.invalid-license-title\"),\r\n message: t(\"dialog.invalid-license-message\", {\r\n message,\r\n name: manifest.workflowName\r\n }),\r\n buttons: [\r\n t(\"buttons.exit\"),\r\n t(\"buttons.open-engine\")\r\n ],\r\n type: 'error',\r\n noLink: true\r\n })\r\n .then(selection => {\r\n if (selection.response === 1) {\r\n new WorkflowExecutable().run({\r\n commands: []\r\n });\r\n }\r\n\r\n app.quit();\r\n });\r\n },\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n let width = settingsDrawerState ? settingsDrawerWidth : 0;\r\n viewer?.updateCompassOffset(width);\r\n }, [viewer, settingsDrawerState]);\r\n\r\n return (\r\n \r\n \r\n\r\n \r\n {isElectronApp && <>\r\n \r\n \r\n \r\n }\r\n\r\n \r\n\r\n \r\n\r\n {\r\n setSettingsDrawerState(false);\r\n }}\r\n />\r\n\r\n \r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n \r\n\r\n \r\n \r\n\r\n \r\n\r\n \r\n\r\n \r\n\r\n {/* Debug stats panel */}\r\n
\r\n\r\n \r\n\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\n/** Global method for toast messages */\r\nexport const toast = {\r\n success: (message) => {\r\n hotToast.success(message);\r\n },\r\n error: (message) => {\r\n hotToast.error(message);\r\n },\r\n warning: (message) => {\r\n hotToast(message, {\r\n icon: \"⚠️\"\r\n });\r\n },\r\n static: (message) => {\r\n hotToast(message, {\r\n icon: \"🔔\",\r\n id: \"static\"\r\n });\r\n }\r\n};\r\n\r\n/** Global method for showing backdrop */\r\nexport const showBackdrop = () => {\r\n sendCustomEvent(\"backdrop-state\", {visible: true});\r\n};\r\n\r\n/** Global method for hiding backdrop */\r\nexport const hideBackdrop = () => {\r\n sendCustomEvent(\"backdrop-state\", {visible: false});\r\n};\r\n"],"sourceRoot":""}