{"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","initialPositionX","initialPositionY","headerHeight","resizeElementID","useMemo","paperPropID","mouseDown","setMouseDown","dialogSize","setDialogSize","setPosition","interval","setInterval","element","dialogWidth","clientWidth","dialogHeight","clientHeight","parentWidth","innerWidth","parentHeight","dialogLeft","dialogBottom","dialogRight","newPosition","isEqual","checkOutOfBounds","clearInterval","newDialogSize","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","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","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","setProj","matchedProjection","setMatchedProjection","imported","setImported","setProjections","cameraTransform","setCameraTransform","setErrors","correction","projectHeight","basicAdjustments","unknownTextMeters","unknownTextFeet","onCorrectionRemove","onMatrixChange","localizedProjectName","importedProjection","userProjection","handleImported","sortedProjections","name1","name2","selectedProjection","getNewProjection","toMeters","hasBasicAlignment","localizedProjectionName","getLocalizedProjectionName","getTransformValues","hasUserProjections","noWrap","ListSubheader","disableSticky","conflict","resetBasicAlignerCamera","trimmedName","emptyName","emptyHeight","emptyProjection","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","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","minAngle","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","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","oldProjection","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","downloadingResources","setDownloadingResources","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","updateDownloadingResources","spellcheckCommand","labelJSON","imageJSON","exportDisabled","trainingLinkDisabled","noLabels","noImages","labelDisabledNoLabels","labelDisabledNoImages","localizedProcessType","modalName","downloadTooltip","imagePaths","canClassify","canRunClassification","canRunAerialToLas","combinedExtension","CircularProgress","areas","pretrainedModelPath","gpu_memory_error","model_diverge_error","model_file_path","class_number_mismatch","old_classes","new_classes","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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,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,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA1B,OAA0B,+DCA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,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,yDpM4gGvC,uBqM5gGa,IAA0B,iDrM6gGvC,uBsM7gGa,IAA0B,iDtM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","file":"static/js/main.d61cb028.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 = () => {\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 resolve();\r\n };\r\n\r\n const onClose = () => {\r\n dialog.handleClose();\r\n setNeedsCheck(!neverAsk);\r\n\r\n const resolve = dialog.data;\r\n resolve();\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\nexport const DraggableDialog = (props: DraggableDialogProps) => {\r\n const {open, title, resize=true, initialHeight, initialWidth, onClose} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const initialPositionX = themeSpacing * 2;\r\n const initialPositionY = headerHeight + (themeSpacing * 2);\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 x: initialWidth ? initialWidth : \"450px\",\r\n y: initialHeight ? initialHeight : \"fit-content\"\r\n });\r\n const [position, setPosition] = useState({\r\n x: initialPositionX,\r\n y: initialPositionY\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 setPosition({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 = position.x;\r\n const dialogTop = position.y;\r\n const dialogBottom = dialogTop + dialogHeight;\r\n const dialogRight = dialogLeft + dialogWidth;\r\n\r\n const newPosition = {...position};\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(position, newPosition)) {\r\n setPosition(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, position]);\r\n\r\n /** Remember resized dimensions */\r\n useEffect(() => {\r\n if (open) return;\r\n\r\n let element = document.getElementById(resizeElementID);\r\n if (!element) return;\r\n\r\n const newDialogSize = {\r\n x: `${element.clientWidth}px`,\r\n y: `${element.clientHeight}px`\r\n };\r\n\r\n setDialogSize(newDialogSize);\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 setTagID(null);\r\n detailsDialog.handleClose();\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 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 savedAnnotations = tag\r\n ? tag.annotations ? [...tag.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 (tag) {\r\n viewer.toggleTagAnnotations(true);\r\n viewer.loadTagAnnotations(savedAnnotations);\r\n viewer.setTagSelected(tag.id);\r\n } else {\r\n viewer.toggleTagAnnotations(false);\r\n viewer.setTagSelected(null);\r\n setEditing(false);\r\n }\r\n }, [viewer, tag]);\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 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 [proj, setProj] = 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 [errors, setErrors] = useState({\r\n name: false,\r\n height: false,\r\n projection: false,\r\n correction: false\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 getNewProjection = () => {\r\n let newProjection = null;\r\n\r\n if (proj === unknownTextMeters) {\r\n newProjection = unknownProjectionMeters;\r\n } else if (proj === unknownTextFeet) {\r\n newProjection = unknownProjectionFeet;\r\n } else if (imported && (proj === imported.name)) {\r\n newProjection = imported;\r\n } else {\r\n const results = projections.filter(x => x.name === proj);\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 setErrors({...errors, name: false});\r\n setName(value);\r\n };\r\n\r\n const updateHeight = (event) => {\r\n const value = event.target.value;\r\n setErrors({...errors, height: false});\r\n setHeight(value);\r\n };\r\n\r\n const updateProj = (event) => {\r\n const value = event.target.value;\r\n if (!value) {\r\n return;\r\n }\r\n\r\n setErrors({...errors, projection: false});\r\n setProj(value);\r\n };\r\n\r\n const onSubmit = async () => {\r\n const trimmedName = name.trim();\r\n const emptyName = trimmedName === \"\";\r\n const emptyHeight = (height as any) === \"\";\r\n const emptyProjection = proj === \"\";\r\n\r\n setErrors({\r\n name: emptyName,\r\n height: emptyHeight,\r\n projection: emptyProjection,\r\n correction: false\r\n });\r\n\r\n if (emptyName || emptyProjection || emptyHeight) {\r\n return;\r\n }\r\n\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\r\n const localizedProjectName = getLocalizedProjectName(projectName);\r\n setName(localizedProjectName);\r\n\r\n setProj(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 = getNewProjection();\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 {rotation, offset} = getTransformValues();\r\n const hasUserProjections = projections.length > 0;\r\n updateTitle(localizedProjectName);\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', {units})}\r\n \r\n \r\n {t('project-settings.camera-height-description')}\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.size/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.size,\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\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 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 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 => camera.name === name);\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 on saved camera id\r\n const camera = this.getCameraByID(activeCamera);\r\n\r\n if (camera) {\r\n savedcameraID = activeCamera;\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 const normal = eigen[2].vector;\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 true;\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 [downloadingResources, setDownloadingResources] = useState(\"\");\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 setDownloadingResources(\"\");\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 updateDownloadingResources = (jsonData) => {\r\n if (jsonData.downloading_resources) {\r\n setDownloadingResources(\"download\");\r\n } else if (jsonData.extracting_resources) {\r\n setDownloadingResources(\"extract\");\r\n } else {\r\n setDownloadingResources(\"\");\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 updateDownloadingResources(jsonData);\r\n\r\n if (jsonData.cudaError){\r\n cudaErrorDialog(jsonData.cudaError);\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 updateDownloadingResources(jsonData);\r\n if (jsonData.cudaError){\r\n cudaErrorDialog(jsonData.cudaError);\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 updateDownloadingResources(jsonData);\r\n\r\n if (jsonData.cudaError){\r\n cudaErrorDialog(jsonData.cudaError);\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 = downloadingResources\r\n ? \"\"\r\n : 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 {/** Downloading resources */}\r\n {(downloadingResources === \"download\") && (\r\n \r\n {t('labels.downloading-resources')} \r\n \r\n )}\r\n\r\n {/** Extracting resources */}\r\n {(downloadingResources === \"extract\") && (\r\n \r\n {t('labels.extracting-resources')} \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":""}