{"version":3,"sources":["viewer/js/file-system-loader.ts","redux/assets-slice.ts","redux/project-slice.ts","projections/projections.tsx","redux/projections-slice.ts","dialogs.tsx","redux/folders-slice.ts","executable.ts","viewer/js/misc.ts","viewer/js/projections.ts","asset-utils.ts","dense-icon.tsx","tooltips.tsx","folder/asset.tsx","folder/folder.tsx","toolbar.tsx","folder/folder-list.tsx","tabs.tsx","viewer/js/utilities/polygon.ts","viewer/js/measurements/measurement.ts","viewer/js/controls/orbit-controls.ts","viewer/textures/colormaps/classifications.png","viewer/js/classifications.ts","viewer/js/shaders/index.ts","viewer/js/shaders/pointcloud_v.ts","viewer/js/shaders/pointcloud_f.ts","viewer/js/shaders/panoramic_v.ts","viewer/js/shaders/panoramic_f.ts","viewer/js/shaders/edl_v.ts","viewer/js/shaders/edl_f.ts","viewer/js/shaders/opacity_v.ts","viewer/js/shaders/opacity_f.ts","viewer/js/shaders/image_v.ts","viewer/js/shaders/image_f.ts","viewer/js/shaders/markers_v.ts","viewer/js/shaders/markers_f.ts","viewer/js/shaders/utilities_v.ts","viewer/js/shaders/gpu_picker_f.ts","viewer/textures/colormaps/index.ts","viewer/textures/colormaps/heat-map.png","viewer/textures/colormaps/awesome-green.png","viewer/textures/colormaps/pastel-shades.png","viewer/textures/colormaps/blue-orange.png","viewer/textures/colormaps/black-orange.png","viewer/textures/colormaps/blue-hue.png","viewer/textures/colormaps/blue-red.png","viewer/textures/colormaps/jet.png","viewer/textures/colormaps/grayscale.png","classifications.ts","viewer/js/materials.ts","viewer/js/pointcloud/cloud-node.ts","viewer/js/pointcloud/raw-pointcloud-node.ts","viewer/js/pointcloud/point-cloud.ts","viewer/js/pointcloud/raw-pointcloud.ts","viewer/js/pointcloud/encompass-pointcloud-node.ts","viewer/js/worker.ts","viewer/js/pointcloud/encompass-pointcloud.ts","viewer/js/binary-heap.ts","redux/settings-slice.ts","viewer/js/utilities/index.ts","viewer/js/cameras/cameras.ts","viewer/js/aerial/orthos.ts","redux/camera-slice.ts","viewer/js/aerial/map.ts","viewer/js/pointcloud/point-loader.ts","viewer/textures/arrow.png","viewer/textures/arrow-shadow.png","viewer/js/markers/markers.ts","viewer/events.ts","viewer/js/utilities/change-detection.ts","viewer/js/gpu-picker.ts","viewer/js/labelling/categories.ts","viewer/js/labelling/image-label.ts","viewer/js/labelling/ortho-label.ts","viewer/js/labelling/scene-label.ts","viewer/js/utilities/unit-converter.ts","viewer/js/measurements/measurement-aerial-view.ts","viewer/js/measurements/measurement-constructor.ts","viewer/js/measurements/measurement-formatter.ts","viewer/js/measurements/measurement-group.ts","viewer/js/measurements/measurement-group-exporter.ts","viewer/js/measurements/measurement-scene-view.ts","viewer/js/measurements/measurement-controller.ts","stats.module.js","viewer/js/main.ts","viewer/js/image-aligner/image-aligner.ts","viewer/js/controls/controls.ts","postprocessing/shaders/CopyShader.js","postprocessing/Pass.js","postprocessing/ShaderPass.js","postprocessing/MaskPass.js","postprocessing/EffectComposer.js","postprocessing/SSAARenderPass.js","viewer/js/controls/compass.ts","viewer/js/measurements/image-only.ts","measurements/measurements.tsx","asset-drawer.tsx","camera-utils.ts","app-bar.tsx","settings-drawer.tsx","enhanced-table.tsx","projections/manager.tsx","redux/store.ts","project-utils.tsx","alignment/aligner-advanced.tsx","alignment/aligner-basic.tsx","progress.tsx","buttons.tsx","labelling/image-labelling.tsx","viewer/context-menu.tsx","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/layer-switcher.tsx","viewer/viewer.tsx","static-export.tsx","app.tsx","index.tsx","electron-modules.ts"],"names":["readFileJSON","path","staticFile","Promise","resolve","reject","readJsonFromURL","readJsonElectron","readFileBuffer","readFileBufferFromURL","readFileBufferElectron","fetch","headers","then","res","json","data","catch","fs","readFile","err","JSON","parse","status","Error","arrayBuffer","byteLength","buffer","AssetType","defaultProjectTitle","currentConfigVersion","projectSlice","createSlice","name","initialState","newProject","modified","Date","toISOString","configVersion","reducers","refreshModified","state","action","changeName","payload","changePath","actions","selectName","project","selectProjectModified","unknownTextMeters","unknownTextFeet","unknownProjectionMeters","type","string","unknownProjectionFeet","defaultProjection","defaultTransform","origin","Array","fill","translation","rotation","scale","generateID","text","replace","projections","this","load","id","map","x","indexOf","isDuplicate","push","storage","set","result","get","obj","stringify","index","splice","projectionsSlice","view","measureUnits","changeData","changeView","changeMeasureUnits","selectView","selectData","selectMeasureUnits","useStyles","makeStyles","theme","createStyles","draggableTitleClose","color","palette","grey","marginRight","spacing","draggableTitleMinimize","draggableContent","padding","paddingTop","height","width","maxWidth","marginTop","headerHeight","draggableContentSlim","draggableContentLeft","marginLeft","draggableTopDiv","display","alignItems","draggableBackdropPaper","draggableBackdropRounded","borderRadius","draggableRoundCorner","backgroundColor","draggableTitle","userSelect","cursor","flex","draggableTitleDown","progressContent","progressNoTransition","transition","PromptDialog","props","open","title","prompt","button","onCancel","onSubmit","Dialog","onClose","aria-labelledby","aria-describedby","DialogTitle","DialogContent","DialogContentText","DialogActions","Button","onClick","AlertDialog","handleClose","children","TextDialog","useState","default","setText","disabled","setDisabled","useEffect","trim","handleSubmit","trimmedText","clear","TextField","onChange","event","target","value","onKeyDown","key","autoFocus","placeholder","margin","label","fullWidth","DraggableDialog","narrow","onMinimize","classes","mouseDown","setMouseDown","handle","fullScreen","className","clsx","paperFullScreen","scrollPaper","BackdropProps","onMouseDown","onMouseUp","IconButton","aria-label","fontSize","ProgressDialog","percent","noTransition","toFixed","LinearProgress","variant","bar","getAssetPayload","folderID","assetPath","slash","assetData","ext","extension","extname","slice","encompassFileFormat","dirname","nanoid","basename","date","lasFileFormat","LAS","Encompass","imageListFormats","Panoramic","planarListFormats","Planar","orthoFormats","OrthoMosaic","Unknown","visible","fromJSON","assetsSlice","addAsset","reducer","prepare","addAssets","forEach","assetsList","assetItem","changeFolder","assetID","asset","find","toggleVisibility","toggleFolderVisibility","filter","deleteAsset","deleteAssets","selectAllAssets","assets","getPointCloudAssets","getCameraFileAssets","getOrthoAssets","foldersSlice","isDefault","addFolder","deleteFolder","folder","renameFolder","selectDefaultFolder","folders","engineMessageTypeJSON","Executable","exePath","exeName","running","child","developerKey","spawnDetached","logText","showStatus","message","console","log","pid","commands","i","length","join","opts","defaults","parseLineData","parseJSON","saveLogs","command","onData","onLine","options","parseCommandsList","executablePath","cwd","spawn","env","process","PYTHONUNBUFFERED","NODEJS","detached","error","copyPasteCommands","copyableCommands","statusMessage","on","commandIndex","commandName","stderr","stdout","parseLines","callback","toString","split","line","messageType","messageData","jsonData","startsWith","kill","lines","execSync","subprocessToKill","rootProcessID","parentProcessID","parseInt","processID","cmdPath","engineSubprocess","engineExecutable","subprocessID","basePath","appPath","app","getAppPath","isDevMode","contents","readFileSync","PythonExecutable","window","onbeforeunload","destroy","stdin","write","WorkflowExecutable","logPrefix","a","maxLogFiles","promises","mkdir","logDirectoryPath","dateString","replaceAll","logPath","logs","writeFile","readdir","filenames","oldest","filename","filePath","stat","stats","birthtime","oldestFilePath","unlink","TouchEventFirstTouch","TouchEventTouching","TouchEventPinchStart","isMobile","test","navigator","userAgent","toLowerCase","randomHexColor","Math","random","closestPowerOfTwo","power","ceil","pow","roundDigit","num","digits","multiplyFactor","round","Number","EPSILON","windowSafeDateISO","chunkedArray","array","size","tmp","results","coordinatesToArray","points","numPoints","newPoints","y","interp1D","start","end","steps","linspace","unitsToValue","lonLatProjection","verifyProjection","info","transform","projection","isLonLatProjection","toUpperCase","verifyProj4String","hasOwnProperty","origin_east","origin_north","origin_elevation","translation_east","translation_north","translation_elevation","scale_factor_h","Object","assign","verifyTransformObject","ScenePointConverter","_sceneShift","_sceneScale","_dataProjection","_viewProjection","proj4String","scale_factor_v","resetSceneShift","Vector3","offset","clone","isLonLatProject","dx","haversineDistance","dy","checkForOffset","add","sub","ProjectedCoordinate","toLonLat","positionLonLat","_dataToLonLat","position","copy","divide","divideScalar","dataToMeters","multiplyScalar","multiply","SceneCoordinate","dataProjection","_sceneToData","dataLonLat","_sceneToLonLat","GeocentricCoordinate","fromLonLat","pointData","toProjection","_dataToScene","infoToMeters","projectionUnits","Coordinate","z","isVector3","LocalScene","_dataToAerial","_sceneToGeocentric","lon","PI","lat","alt","b","e","sqrt","N","sin","cos","viewProjection","_geocentricToScene","ep","p","th","atan2","abs","vector","_proj4Transform","trans","scaleVector","angle","axis","applyAxisAngle","lonlat","isLonLat1","isLonLat2","distanceTo","DataProjectionCoordinate","SphericalPosition","radius","_theta","_phi","limits","precision","divisor","pivot","orbit","theta","MathUtils","radToDeg","dist2d","phi","max","min","degToRad","isValidProjection","projectionString","proj4","getInvertedEuler","euler","inverseQuaternion","Quaternion","setFromEuler","inverse","Euler","setFromQuaternion","calculatePointsPCA","vertices","returnFlat","mean","vertex","toArray","eigen","logger","response","executeWithoutLogging","PCA","getEigenVectors","matrix","Matrix4","makeBasis","fromArray","transpose","point","applyMatrix4","pointsFlat","units","proj","Proj","convert","sphereRaycast","raycaster","intersects","geometry","matrixWorld","testSphere","Sphere","boundingSphere","ray","intersectsSphere","distance","object","position1","position2","diffLat","diffLng","arc","distance2d","proj1","proj2","projToMeters1","proj2m","reprojected","forward","pointCloudFileFormats","pointCloudFilter","extensions","imageOrthoFilter","imageCSVFilter","imagePlanarFilter","isPanoramicFile","isPlanarFile","isPointCloudFile","isOrthomosaicFile","addAssetFolder","showMessage","dispatch","paths","cloudPaths","file","panoramicPaths","orthoPaths","planarPaths","numClouds","numImageFiles","addPlanarFiles","planarFilesAdded","addCameraFiles","panoramicFilesAdded","pointsAdded","addPointCloudFiles","addOrthoFiles","orthosAdded","totalAdded","addedPlural","assetPaths","assetList","pointPath","showBackdrop","addOrthoBatch","numAdded","hideBackdrop","addCameraFile","success","fileName","parseMessage","pathMessage","pathError","autoHideDuration","addPlanarFile","exe","run","geotiff","file_path","corners","base64","scale_x","scale_y","imageBounds","imageData","imageSize","imageSizeOriginal","width_original","height_original","imagePath","scaleX","scaleY","fsPromises","encoding","decoded","config","cameras","numCameras","cameraNames","detectImagePath","pathFound","imageExt","hasImageExt","cameraData","camera","buildFilePath","roll","pitch","yaw","userPath","getPath","engineStyleProjection","openDialogMulti","dialog","showOpenDialog","filters","properties","canceled","filePaths","showErrorBox","openDialogFile","parseDirectory","directoryPath","withFileTypes","entries","files","entry","isFile","directories","isDirectory","directory","checkImagePath","suffix","depth","duplicate","singleFolder","dirSeperator","subset","filenameQuery","globPath","glob","sync","root","singleImageValid","multiImageValid","imageNames","testImageExt","includes","showOpenDialogSync","manual","icon","minWidth","paddingRight","centered","DenseIcon","other","ListItemIcon","hidden","opacity","ArrowTooltip","Tooltip","arrow","CursorTooltip","React","undefined","setPosition","dangerouslySetInnerHTML","__html","placement","popper","onMouseMove","pageX","pageY","PopperProps","anchorEl","clientHeight","clientWidth","getBoundingClientRect","top","left","right","bottom","mouseX","mouseY","itemList","paddingLeft","itemText","wordBreak","overflow","assetMargins","assetError","main","fontWeight","assetWarning","warning","assetInfo","assetCheckbox","checkboxParent","percentLabel","textAlign","LinearProgressWithLabel","Fragment","Box","mr","Typography","AssetItem","viewer","useDispatch","useSelector","renameOpen","setRenameOpen","deleteOpen","setDeleteOpen","menuState","setMenuState","isPanoramic","isPlanar","isEncompassCloud","isRawPointcloud","isOrtho","isCamera","isPointCloud","handleAssetExport","outputName","showSaveDialog","defaultPath","csvPath","csvOut","getCamerasForCSV","eulerDegrees","csv","writeToPath","menuOpen","isStaticSite","anchorPosition","canExportCSV","cloudPercent","getCloudPercent","cloudMissing","getCloudMissing","cloudLoading","showLargeWarning","getCloudIsLarge","ListItem","onContextMenu","preventDefault","clientX","clientY","draggable","onDragStart","dataTransfer","setData","snapToOrtho","snapToPointCloud","snapToImages","ListItemText","primary","ListItemSecondaryAction","Checkbox","edge","checked","keepMounted","anchorReference","MenuItem","AssetFolder","handleAssetMove","expanded","setExpanded","dragDropHover","setDragDropHover","numVisible","numHidden","onDragOver","onDragLeave","onDrop","getData","selected","indeterminate","List","component","disablePadding","dense","verticalDivider","icons","iconButton","iconSize","DenseDivider","Divider","style","marginBottom","IconToolBar","ToolBarDivider","ToolBarButton","isVisible","tooltipText","colorFin","Icon","colorPrimary","SlimScrollbar","autoHide","autoHideTimeout","addItem","paddingBottom","folderList","FolderList","useSnackbar","enqueueSnackbar","defaultFolder","defaultFolderHasAssets","dialogOpen","setDialogOpen","contextState","setContextState","secondary","folderName","TabPanel","panel","box","role","TabProps","PanelProps","simplepolygon","require","pointInPolygon","numberOfVertices","insidePolygon","j","verti","vertj","dy1","dy2","cond1","cond2","planeFromVectors","directions","normal","setLength","Plane","checkValidPolygon","coordinates","shifted","features","Measurement","controller","dbType","databaseID","displayType","timeCreated","startClick","cancelClick","finishClick","tooltipStatic","more","floor","getTime","isoTime","formatter","Measurement3D","maxVertexLength","minVertexRequired","finished","addedPoint","fromScene","oldVertex","added","valid","MeasurementArea","ignoreHeight","vertexA","vertexB","toScene","getLineDistance","lastIndex","firstPoint","lastPoint","NaN","atan","rise","distance2D","MeasurementLine","moreTooltip","MeasurementPoint","surfaceGenerator","areaInvalidMessage","SurfaceGenerator","generate","indices","area","MeasurementVolume","volumeHelper","invalidVolumeMessage","calculate","stopCalculation","pointCloud","pointclouds","VolumeHelper","init","setVolume","destroyWorker","calculated","calculatingVolume","SnapMeasurement","parent","snapResult","snap","finalHeight","validHeights","pos","heights","pointsInRadius","SnapDownMeasurement","reduce","acc","curr","SnapUpMeasurement","AerialMeasurement","polygon","flatCoordinates","totalPoints","ecef","geometryToArray","getCoordinates","AerialLengthMeasurement","getLength","LineString","AerialAreaMeasurement","getArea","Polygon","measurement","sigma","minNeighbours","maxNeighbours","neighbourPercent","maxHeightDelta","worker","bounds","groundHeight","pointcloudmesh","pointswireframe","updateValue","localVertices3D","getCalculatedBounds","sum","calculateVolume","arr","xMin","xMax","yMin","yMax","zMin","zMax","center","Worker","onmessage","postMessage","terminate","positions","Float32Array","BufferGeometry","setAttribute","BufferAttribute","material","PointsMaterial","Points","scene","triangles","Geometry","MeshBasicMaterial","side","DoubleSide","tri","faces","Face3","mesh","Mesh","geo","EdgesGeometry","mat","LineBasicMaterial","wireframe","LineSegments","volume","p1","p2","p3","signedTetrahedronVolume","dot","cross","reverse","from","v1","v","v2","v3","final","validTriangles","triangle","Triangle","getMidpoint","reverseWinding","delaunay","Delaunator","generateTriangleArray","removeInvalidTriangles","refreshMeasurementList","denseBounds","getDensePolygon","filterByHeight","pointsInPolygon","getSampledPoints","gridX","gridY","removeOutliersAsync","asyncFinished","webWorkerFinished","pointsArray","concat","trianglesUpper","getDenaunayTriangles","trianglesLower","trianglesCombined","drawMesh","getVolume","updateAreaShaders","remove","changeRequired","renderInScene","meshes","removeMeshesFromScene","hexColor","geom","getNormal","c","triangleIndices","verticesModified","numIndices","triIndexA","triA","triB","triIndexB","vertSet","Set","allVerts","sharedVerts","uniqueVerts","modTriA","modTriB","t1","t2","oldArea","t3","t4","newArea","optimize","numVertices","earcut","deviation","numTriangles","triVertices","generateMesh","addMeshesToScene","densePolygonTemp","nextIndex","direction","vectorLength","increment","directionIncrement","densePolygon","old","CustomOrbitControls","domElement","document","flyMode","flyForcedRadius","flyPreviousRadius","flyPreviousDampening","flyPreviousRotateSpeed","flySpeed","flyRatio","minFlySpeed","maxFlySpeed","saveSpeedTimeout","tick","enabled","focused","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","flyModeOffset","enablePan","panSpeed","panningMode","keyPanSpeed","autoRotate","autoRotateSpeed","enableKeys","keys","LEFT","UP","RIGHT","BOTTOM","SPACE","PLUS","MINUS","NUMPAD_PLUS","NUMPAD_MINUS","mouseButtons","ORBIT","MOUSE","ZOOM","MIDDLE","PAN","target0","position0","zoom0","zoom","isMoving","panOffset","sphericalDelta","setFlySpeed","increaseFlySpeed","scope","decreaseFlySpeed","toggleFlyMode","showToast","clearSphericalDelta","clearPanOffset","getPolarAngle","spherical","getAzimuthalAngle","saveState","reset","updateProjectionMatrix","dispatchEvent","changeEvent","update","STATE","NONE","quat","setFromUnitVectors","up","quatInverse","lastPosition","lastQuaternion","millisecondsElapsed","distancePerFrame","applyQuaternion","setFromVector3","rotateLeft","makeSafe","setFromSpherical","lookAt","zoomChanged","distanceToSquared","EPS","quaternion","dispose","removeEventListener","onMouseWheel","onTouchStart","onTouchEnd","onTouchMove","onMouseFocus","startEvent","endEvent","ROTATE","DOLLY","TOUCH_ROTATE","TOUCH_DOLLY","TOUCH_PAN","Spherical","rotateStart","Vector2","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","getZoomScale","rotateUp","panLeft","objectMatrix","setFromMatrixColumn","panUp","crossVectors","pan","deltaX","deltaY","element","body","isPerspectiveCamera","targetDistance","tan","fov","isOrthographicCamera","warn","dollyIn","dollyScale","dollyOut","handleMouseDownRotate","handleMouseDownDolly","handleMouseDownPan","addEventListener","subVectors","handleMouseMoveRotate","handleMouseMoveDolly","handleMouseMovePan","stopPropagation","handleMouseWheel","keyCode","handleKeyDown","touches","handleTouchStartRotate","handleTouchStartDolly","handleTouchStartPan","handleTouchMoveRotate","handleTouchMoveDolly","handleTouchMovePan","prototype","create","EventDispatcher","constructor","classificationTexture","TextureLoader","classifications","shaders","pointcloud","vert","frag","panoramic","edl","image","markers","utilities","gpu_picker","colorMaps","numberOfClassifications","BaseMaterial","uniforms","defineProperty","ShaderMaterial","PointCloudMaterial","params","gpuPicker","color_map","color_type","dynamic_size","circularPoints","visibleNodesTexture","dynamic_cloud","screenHeight","screenwidth","octree_spacing","octree_size","octree_corner","intensity_range","rgb_max","height_range","channels","Color","Uint8Array","r","g","format","RGBFormat","RGBAFormat","texture","DataTexture","minFilter","NearestFilter","magFilter","needsUpdate","generateDataTexture","colorMapTexture","colorMap","classificationVisible","areaClipData","maxAreaTriangles","volumeStatus","Uniform","minSize","maxSize","colorType","heightClamp","intensityClamp","dynamicSize","defines","maxTriangles","fragmentShader","vertexShader","setValues","vertexColors","transparent","depthWrite","initProperties","EDLMaterial","screenWidth","edlStrength","neighbours","neighbourCount","lightDir","normalize","uniform","WIDTH","HEIGHT","near","far","expScale","tDepth","OpacityMaterial","ImageMaterial","PanoramicMaterial","tEquirect","MarkerMaterial","orbitMode","camera_position","mtrx_x","mtrx_y","mtrx_z","marker_size","currentIndex","CloudNode","cloud","pointsScene","pointsPicker","boundingBox","loaded","loading","sizeTight","_center","_sphere","tightBoundingBox","item","removeFromScene","disposeGeometry","picker","boundingBoxVisibility","intensity","classification","colors","gpu_index","computeBoundingBox","shift","RawPointCloudNode","xyz_min","xyz_max","addChildNode","offsetToScene","updateBoundingBox","updateRootNode","setGeometry","updateClassifications","updateColorLimits","updateIntensityRange","intensity_min","intensity_max","materialScene","materialPicker","generateEdgeMesh","addCloudData","getGeometry","RawPointCloudRootNode","node","PointCloud","uniqueClassifications","rgbArray","maxColor","intensityRange","identifier","empty","fileMissing","materials","_tightBoundingBox","debugBoxColor","sizeX","sizeY","sizeZ","vertexArray","edgeVertices","boxGeometry","boxMaterial","materialDefaults","changed","updateMinimapExtent","nodes","getVisibleNodes","setState","nodeCondition","visibleNodes","stack","combined","mergeBoundingBoxes","intensityMin","intensityMax","rgbMax","closestValue","sort","arrMax","midpoint","gpuPickers","current","RawPointCloud","workerExe","header","loadStart","timeEnd","byteCutoffSize","pointsDataParsed","pointsDataArray","numSampledPoints","minNumNodes","minPointSize","generatingChunks","canReadData","updatePercent","performance","now","elapsed","maxDataChunks","number_of_chunks","updateSizeInfo","addPointCloud","setIdentifier","setVisibility","fileLoadStart","fileLoadFinish","fileLoadCancel","lasFilePath","projectionsUnits","dataProjectionUnits","isValid","keyword","pushToWorkerQueue","parseHeaderResponse","parsePointsResponse","fileLoadFinished","isLargeFile","isLastChunk","fileLoadProgress","addNodeFromData","bbox","estimatedBoundingBox","zoomToExtent","Int32Array","loadFromData","apply","maxs","mins","remote","number_of_bytes","EncompassPointCloudNode","level","_children","dataPath","getDataPath","isRemoteFile","sendToWorker","removeChildNode","workerPool","getWorker","returnWorker","sendMessage","childName","getChildNameAtIndex","childSize","childLevel","childCenter","clearChildNodes","getBinaryData","getChildAtIndex","WorkerPool","workerPath","numDefaultWorkers","workers","createDefaultWorkers","transferables","pop","newWorkers","WorkerQueue","workerURL","numWorkers","waitForExit","pool","maxAsyncWorkers","numRunning","queue","workerData","workerCallback","workerFinished","finish","EncompassPointCloud","structure","nodeCacheSize","cloudInfo","numberOfPoints","_shift","terminateWorkers","dataDir","folderDepth","dirs","match","RegExp","setName","decodeIndexData","hierarchy_step_size","point_offset","point_scale","availableNodes","node_structure","total_points","tight_bounding_box","nodeSize","parseFloat","nodeCenter","buildTreeLegacy","setBoundingBox","BinaryHeap","scoreFunction","content","bubbleUp","sinkDown","peek","n","score","parentN","elemScore","child2N","child1N","swap","child1","child1Score","child2","ColorType","MarkerNavType","getProjFactor","projFactor","setPointScale","computeBoundingSphere","eventToPixel","uv","offsetX","offsetY","layerX","layerY","ImagePosition","_value","setFromMatrixPosition","_euler","applyEuler","eulerCSV","toAerial","ImageRotation","angles","adjustment","rotationWithTransform","multiplyRotations","rotationWithAdjustment","setFromRotationMatrix","degrees","CameraImage","cameraList","img","ctx","canvas","directionToCameraAngle","positionToCameraAngle","cameraPos","sphere","fromVectors","pixel","u","controls","Image","arrayBufferView","blob","Blob","mimeType","src","URL","createObjectURL","setNormalCamera","setCameraParameters","minimap","setActiveCamera","onLoaded","generateObject","setObjectVisible","grabImageFromPath","clearImages","setWaitForCameras","setCameraPosition","loadImageData","setOrbitCamera","finally","updateArrowNavigation","angleEuler","tempRotation","PanoramicImage","imageWidth","imageHeight","imageDirection","planarSize","plane","planar","projectPoint","allX","allY","interpolated","xyz","xyzTemp","xyz1","xyz2","_x","_y","_z","interpTemp","xyzNoDups","previous","imageTexture","Texture","LinearFilter","setTexture","BoxGeometry","PlanarImage","fx","fy","centerOffset","outOfBounds","flipY","PlaneGeometry","objectOffset","Object3D","fovY","cy","fovX","cx","CameraList","adjustments","aligned","waitForCameras","initScene","initEvents","Scene","softlight","AmbientLight","incrementCamera","setOrbitState","addedIndex","newCameras","cameraConfig","assetType","cameraInfo","newCamera","getNewCamera","toRemove","remaining","has","removeCameraMarkers","cameraID","getByID","cameraName","loadCamera","currentCamera","count","nextCamera","loadImage","recalculateAllMarkers","elements","newMatrix","equals","applyMatrixToCameras","extentFromPoints","rotationA","rotationB","matrixA","makeRotationFromEuler","matrixB","multiplyMatrices","OrthoImageLayer","ImageLayer","orthosList","layer","imageBase64","extent","pixelMaxSpread","pixelMaxValue","calculateExtent","addMapLayer","aerialMap","setMapExtent","transformExtent","coordinatesTransformed","coordinate","coordTransformed","addLayer","onload","parseImageData","createElement","context","getContext","drawImage","getImageData","base","putImageData","source","Static","url","toDataURL","imageExtent","imageSmoothing","setSource","setOpacity","setVisible","removeLayer","dataProjectionName","getVisible","x_scale","y_scale","x_offset","y_offset","x_skew","y_skew","OrthoMosaicList","orthos","orthoID","ortho","initialAerialState","resolution","basemap","initialSceneState","isValidAerialState","cameraStateSlice","aerialState","sceneState","changeCameraTransform","changeCameraState","changeCameraHeight","changeBasicAdjustments","changeSavedAerialState","selectCameraHeight","selectActiveCamera","selectCameraState","selectCameraTransform","selectBasicAdjustments","selectSavedAerialState","BasemapLayer","Tile","BaseCameraFeature","Feature","PanoramicFeature","PlanarFeature","ViewTriangle","aerial","feature","generateSource","VectorSource","wrapX","noWrap","addFeature","VectorLayer","Style","stroke","Stroke","Fill","setZIndex","lookat","ring","generateMarkerCoordinates","getTargetElement","coneAngle","coneLength","getView","getResolution","v0","changeDetector","initialized","rotateViewMarker","AerialMap","container","containerElement","orthoList","maxLayerZoom","maxMapZoomLevel","styleCache","pointsSource","boundsSource","activeCamera","activeCameraLayer","clusterDistance","clusterCircleSize","camerasToIterate","camerasCalculated","chunkedArraySize","calculating","setAerialState","mapSystem","initMap","initDataLayers","resetView","validExtent","fit","setResolution","setRotation","setVisibleBasemap","setCenter","setZoom","defaultID","basemapLayers","attribution","Attribution","collapsible","Map","layers","defaultLayers","fractionalZoom","defaultControls","rotate","extend","View","forEachFeatureAtPixel","getZoom","boundingExtent","mapSize","getSize","nearest","duration","updateSavedState","clusterSource","Cluster","clusterLayer","clusterStyle","boundsLayer","Point","styleGenerator","interactions","interaction","DragPan","setActive","getRotation","toDataProjection","cornersAerial","calculatingSceneMarkers","cameraIndex","addFeatures","centerOnImages","remainingCameras","remainingFeatures","addCameraMarkers","active","square","strokeColor","textColor","fillColor","circleImage","CircleStyle","squareImage","RegularShapeStyle","Text","numSquares","numCircles","styleKey","basemapID","mapPosition","getSource","getFeatures","setStyle","setTarget","calculateCameras","orbitState","hasPoints","cameraSelected","arcGISBase","OSM","XYZ","attributions","scrollWidth","scrollHeight","getLayers","array_","reproject","xPositions","yPositions","PointCloudManager","clouds","workerQueue","visiblePointsTarget","maxloadedToGPUPerFrame","maxNodeAsyncLoad","maxRawAsyncLoad","maxDecodeWorkers","exeLaunchTimeout","lastExeLaunched","numLoadedPoints","numVisiblePoints","numSceneNodesVisible","fovDifferencePercent","minPixelPercent","loadedOnce","transparency","rawJsonResponse","setLoadedOnce","updateMeasureList","delete","measurements","defaultKey","materialKey","classification_visible","smooth","boxSize","boxMean","boundSize","maxHeight","orbitWithAngle","fromValues","toVector3","combinedBoundingBox","updateCloudExtent","ignoreConditions","camerasExist","newPosition","orbitPositionFromBounds","frustum","priorityQueue","weight","MAX_VALUE","unloadedGeometry","loadedToGPUThisFrame","maxNodeDistance","measurePoint","getCameraTarget","isRawPointCloud","newPointsTarget","bounds2d","camera2d","isGeometryNode","isTreeNode","isLoaded","addToScene","cameraPosition","childDistance","childRadius","maxFov","maxFOV","screenPixelRadius","insideSphere","maxLoad","subScalar","maxValue","sampledPoints","setDrawRange","attributes","drawRange","totalVisibleNodes","unusedNodes","totalUnusedNodes","totalNumberNodes","maxNodesAllowed","numberToDelete","nodeIndex","childIndex","substr","vArrayIndex","areaGeometry","areaMeasureData","area_measure_data","volume_status","max_triangles","triangleNumber","triangleIndex","vertexIndex","vIndex","updateShaderVertex","numLoading","cloudsToParse","cloudsToExecute","rawPointClouds","timeNow","launchExecutable","parseAvailableChunks","getX","getY","getZ","highest","keyfunc","samples","dtmPoints","Frustum","cameraViewProjectionMatrix","updateMatrixWorld","matrixWorldInverse","getInverse","projectionMatrix","setFromProjectionMatrix","loadAvailableLasData","hideDescendants","updateVisibility","manageNodeCache","updateMaterialDefaults","updateVisibilityTexture","updateCloudSampling","calculatePointsVisible","defaultClassifications","available","saveSettingsDefaults","cloneDeep","applySavedDefaults","loadSavedDefaults","settingsSlice","Height","arrowMarkers","Arrows","activeTab","cloudMaxPoints","cloudDistance","cloudSize","switched","drawerOpen","heightClip","intensityClip","orthoOpacity","changeDefaultSettings","changeOpacity","changeOrthoOpacity","changeCloudDistance","changeCloudMaxPoints","changeCloudSize","changeHeightClip","changeIntensityClip","changeColorMap","changeColorType","changeDynamicSize","changeCircularPoints","changeAvailableClassifications","availableClassifications","changeClassificationVisibility","changeAllClassificationVisibility","changeSwitched","changeSelectedTab","changeDrawerOpen","changeArrowMarkers","selectOpacity","settings","selectOrthoOpacity","selectCloudDistance","selectCloudMaxPoints","selectCloudSize","selectHeightClip","selectIntensityClip","selectColorMap","selectColorType","selectDynamicSize","selectCircularPoints","selectViewerSwitched","selectSelectedTab","selectDrawerOpen","selectArrowMarkers","selectAvailableClassifications","selectClassificationVisibilities","CameraMarkers","arrowNavigation","markerNavigation","navigationType","modifier","initKeyDown","MarkerNavigation","ArrowNavigation","onKeyUp","bind","drawCameraMarkers","updatePicker","updateNavigation","clearNavigation","markerID","mouseClick","mouse","movement","which","isArrows","isOrbitMode","isHidden","isMarkers","setEnabled","None","Markers","markerMesh","pickingMesh","standardMaterial","pickingMaterial","verticesPerCamera","uvs","selectedID","markerPositions","initGeometry","markerShape","cameraIndices","cameraShape","numUvs","uvIndex","updateGeometry","camera_index","marker","numCorners","corner","cornerIndex","updatePickers","arrIndex","cameraPickerID","markCameraSelected","mtrx4","makeRotationFromQuaternion","mtrx3","Matrix3","setFromMatrix4","shader","ArrowMarker","textures","section","addMesh","geometryStandard","materialStandard","alphaTest","userData","numSections","sections","defaultScale","zoomedScale","loadTextures","initMeshObject","sectionToAngle","loader","arrowPathStandard","arrowPathShadow","validCameras","markerPos","tooClose","tooFar","angleToSection","setCamera","setScale","getIntersect","targets","RayCaster","intersectObjects","sectionID","binds","ChangeDetector","previousFov","previousZoom","previousLookat","previousCamera","previousHeight","previousOrbit","lookatChanged","fovChanged","cameraChanged","heightChanged","orbitChanged","newLookat","newFov","newZoom","newHeight","newOrbit","GPUPicker","debug","_needsUpdate","WebGLRenderTarget","LinearEncoding","generateMipmaps","clearSections","tX","tY","sectionWidth","sectionHeight","sectionX","sectionY","sectionIndex","pixelIndex","timeStart","startX","startY","pixelBuffer","renderer","readRenderTargetPixels","time","mouseResult","pickerID","updateBaseIDs","oldRenderTarget","getRenderTarget","oldClearColor","getClearColor","oldClearAlpha","getClearAlpha","newClearColor","setRenderTarget","setClearColor","render","setClearAlpha","currentBaseID","setSize","getSelectedObject","getObjectPosition","minIndex","maxIndex","parseHex","textToColor","textToColorArray","colorHash","createHash","hash","digest","h","s","l","ImageLabel","category","completed","editing","drawable","highlighted","stateChanged","draw","complete","highlight","LabelCategory","labels","labelID","drawLabel","getLabelByID","labelIDs","setHighlighted","updateColor","hasEnoughPoints","unSelectAll","unSelect","select","ImageLabelTools","orthoLabels","sceneLabels","activeLabeler","categories","setCategoryList","setTrainingArea","currentCategory","hotkeyEnabled","contextMenuOpen","AerialLabelTools","SceneLabelTools","setCategories","activeLabel","completeLabel","deletePoint","addLabel","trainingArea","deleteAllCategories","setDragState","activeImagePaths","loadedImagePaths","updateCategories","getNewCategory","setTrainingAreas","categoryID","getCategoryByID","updateName","deleteCategory","deleteTrainingArea","addNewLabel","unSelectLabels","selectLabel","deleteLabel","resetToolTipText","pointID","deleteSpecificPoint","unHighlightAll","zoomToLabel","unHighlight","deleteLabels","resetTemporaryPoint","tolerance","highQuality","newPointsPolygon","turfPolygon","simplified","turfSimplify","simplePolygon","labelsToMerge","mergedLabels","firstLabel","isPlanarImage","isPanoramicImage","mergeLabel","points1","coords","points2","matches","point1","index1","matchFound","point2","index2","dist","polygonPoints1","polygonPoints2","union","turfUnion","coord","addPoint","remainingLabels","mergeTrainingLabels","simplifyPolygon","images","progressData","addedLabel","isTrainingArea","labelAddTimeout","image_id","segmentation","skippedLabels","pointsToAerial","getByName","file_name","pointsToPixels","newLabel","addTrainingAreaLabel","setKnownImageSize","labelTotal","labelIndex","progress","setTimeout","importLabelData","mergeID","merge_id","progressCallback","annotations","trainingAreas","numLabelsTotal","trainingAreaCategory","addTrainingArea","addCategoryLabels","mergeList","newLabels","category_id","newCategory","addCategory","simplifyPanoramicLabels","setDrawable","drawAll","supercategory","jsonLabelsObj","jsonObj","jsonImageObj","sectionsFromIntersection","intersection","removeDuplicate","intersectPoints","annotationFromPolygon","imageID","trainingAreaIdx","segment","flat","annotation","iscrowd","areaFromPolygon","trainingAreaId","contour","ShapeUtils","LabelPoint","LabelPolygon","OrthoLabel","minCoordinates","minPixelDistance","featureStyle","editingStyle","checkDefaultStyle","defaultStyleParams","getLayerStyle","checkDuplicate","newPoint","oldPoint","pixelNew","getPixelFromCoordinate","pixelOld","dU","dV","temporaryPoint","completedSource","editingSource","polygonPointsOnly","validPolygon","drawPoints","drawPolygon","setFeatureStyle","sources","hasFeature","removeFeature","featuresLayer","editingLayer","getLayerFromCache","OrthoCategory","aerialTools","addMapLayers","pointColor","categoryColor","dark","lineDash","darkenedColor","VectorImageLayer","updateWhileInteracting","updateWhileAnimating","clearStyleCache","setPointDelete","setPointAdd","setAerialTooltipText","dragObject","contextMenuClick","startTooltip","dragTooltip","highlightTooltip","polygonInImage","polygonPoints","imageList","imageIds","imagesWithPolygon","imageIdsFinal","polyPointRing","trainingAreaInPixels","idx","pointsOriginalProj","polygonInPixels","calculatePolygonPixels","metadata","turfIntersect","trainingAreaInImage","imagesWithTrainingArea","trainingAreaIds","validTrainingAreas","trainingAreaUsed","imageId","imageInPixels","originalSize","areaId","trainingAreaPoints","trainingAreaRing","trainingAreaOriginalProj","pixelPolygon","pixelPoint","markLastPointDraggable","pointFeatures","setDragObject","setPointGrabTooltip","setHighlightTooltip","setToolTipText","drawActiveLabel","dragging","updatePoint","checkFeatureHover","isRightClick","noneHighlighted","numHighlighted","oneHighlighted","ctrlKey","highlightLabel","highlightedFeature","isPoint","highlightedLabel","featurePoint","getFeatureAtPixel","pointFeaturesForExtent","featurePoly","polygonFeaturesForExtent","mousePixel","mouseCoord","mouseBuffer","getCoordinateFromPixel","values_","pointExtent","getExtent","intersectsCoordinate","pointRadius","helpMsg","invalidTooltip","getFeaturesAtPixel","removePoint","removeSpecificPoint","visibleOrthos","imageIndex","orthoName","mergeIndex","polygonsInside","mergeable","pointCount","getFeaturesInExtent","_direction","_position","updateValues","pixelToDirection","SceneLabel","_imageWidth","_imageHeight","standardMeshes","opacityMeshes","pointGeometry","pointMaterial","lineGeometry","lineMaterial","lineDashedMaterial","polygonMaterial","minPoleAngle","SphereGeometry","updateMaterials","standardColor","LineDashedMaterial","dashSize","gapSize","standardScene","setFromPoints","Line","computeLineDistances","pixels","coordinates3d","directionsToPlanar","oldState","coordinates2d","polygonAtPoles","coordinatesFlat","face","opacityScene","drawLines","drawPolygons","pointsAtPole","acos","minAngle","maxAngle","booleanContains","turfPoint","average","fovRequired","angleTo","setCameraVisible","getCameraBestFit","SceneCategory","numberOfLabels","setViewerTooltipText","polygonHover","movingEndpoint","vectorFromEvent","getClickedDirection","directionToPixel","drawing","intersectedTargets","getImagePixel","labelPoints","targetPoly","objects","polygons","setPolygonHover","hovering","labelHighlighted","mouseMoved","down","isLeftClick","checkPointSelected","updateDraggablePoint","setPolygonHoverTooltip","imageBorders","horizontalShift","getHorizontalShift","interpolatePixels","imageBordersLeft","intersectionLeft","imageBordersRight","intersectionRight","minSpread","spread","calculatePlanarSections","calculatePanoramicSections","visibleCameras","getCameraSize","deleteUnfinishedLabel","visited","metresToSurveyFeetRatio","metresToFeetRatio","allowedUnits","fromUnits","toUnits","isNaN","convertedValue","MinimapMeasure","sourceStandard","vectorStandard","sourceHover","vectorHover","pointerMoveHandler","measurementType","sketch","measureTooltipElement","measureTooltip","setAsLength","setAsArea","setAsNull","reloadInteraction","removeInteraction","setTooltipText","addInteraction","mapElement","innerHTML","setOffset","$","createMeasureTooltip","listener","editable","Draw","condition","originalEvent","getTooltipValues","output","tooltipCoord","setMeasureTooltipInfo","unByKey","addAerialMeasurement","measureParent","parentNode","removeChild","Overlay","positioning","addOverlay","hover","measurementID","formatArea","getInteriorPoint","formatLength","getLastCoordinate","canFinish","MeasurementConstructor","MeasurementClass","isFinished","builderType","setController","finishedMeasurement","MeasurementFormatter","emptyValue","nullValue","metersCutoff","squareMetersCutoff","formatterPrecision","vectorPrecisionLonLat","vectorPrecisionStandard","TypeError","setUnits","finalValue","metresToFeet","isSurveyFeet","feet","inches","metresToMiles","metresToKiloMetres","volumeValue","cubicMetresToCubicYards","squareMetresToSquareMiles","squareMetresToSquareFeet","squareMetresToSquareKilometres","maxGrade","isFinite","precisionX","precisionY","precisionZ","isMetric","isSurveryFeet","metres","squareMetres","val","cubicMetres","metresToYards","MeasurementGroup","collectionID","save","updateMeasurements","removeFromArray","removeAll","measure3D","measurements3D","newMeasurement","timestamp","time_created","generateSurface","loadExistingVolume","measure2D","measurements2D","loadFromCoordinates","renderMeasurement","resetDragObject","names","getProjectedVertices","getAreaMeasurements","measureGeometry","getMeasurementByType","measureClass","MeasurementGroupExporter","lineDelimiter","columnDelimiter","measureExportFormat","csvExportFilter","dataExportFilter","measurementGroup","version","ordering","getVectorPrecision","export3D","export2D","created","projectName","downloadDataExport","mapProjection","getHeaderValues2D","row","convertUnits","getValue","toGeocentric","toViewProjection","downloadCSVFile","getHeaderValues3D","areaValue","area3D","distance3D","formatGrade","grade","formatAngle","downloadFileBrowser","downloadFileElectron","savePath","writeFileSync","contentType","encodeURIComponent","appendChild","click","measurementVertices","areaUnits","volumeUnits","MeasureEndpoint","measurementVertex","TemporaryEndpoint","MeasurementSceneView","sphereBuffer","sphereRadius","sphereGeometry","sphereMaterialStandard","sphereMaterialHover","lineMaterialStandard","lineMaterialHover","temporaryEndpoints","temporaryLines","hoveredPoint","dragValid","stopVolumeCalculation","removeByID","measurementBuilder","activeMeasurement","sortByRay","restrictOrbitMovement","morepoints","endTooltipCount","endTooltip","createTempEndpoint","temporaryLine","createLine","raycast","createEndpoint","temporaryEndpoint","MeasurementController","imageOnlyType","measureType","measureSceneView","measurementAerialView","measurementGroupExporter","setMeasurements","createNewMeasurementGroup","stopDrawingItems","hideTooltip","disable","light","currentProjection","loadMeasurements","$maxMeasureDistance","isImageOnly","GroundPlaneMeasurement","maxDistance2D","maxMeasureDistance","unitConverter","getPosition","getPlanePosition","getPickerResults","getCoordinate","addTemporaryPoint","updateMeasureText","finishMeasurement","cancelMeasurement","checkEndpointSelected","measuring","addActiveEndpoint","updateMeasureEndpoint","getMeasurement","removeTemporaryObjects","measureEndpoints","redrawAerialGeometry","measureGrabFinished","getAreaGeometry","updateAreaVertices","checkMorePoints","setMeasurementType","setBuilder","getMeasurements2D","measurement_","loadGeometry","clearViews","exportCSV","exportDAT","exportLinework","updateMaxMeasureDistance","reload","updateMaterial","Boolean","Stats","mode","addPanel","dom","showPanel","cssText","beginTime","prevTime","frames","fpsPanel","Panel","msPanel","self","memory","memPanel","REVISION","begin","usedJSHeapSize","jsHeapSizeLimit","setMode","fg","bg","PR","devicePixelRatio","TEXT_X","TEXT_Y","GRAPH_X","GRAPH_Y","GRAPH_WIDTH","GRAPH_HEIGHT","font","textBaseline","fillStyle","fillRect","fillText","globalAlpha","Viewer","viewContainer","mapContainer","defaultFarPlane","defaultNearPlane","screenPass","imageMaterial","texture2DDepth","opacityMaterial","texture2DImage","texture2DOpacity","imageLabels","compass","setCameraState","drawPickerScene","timingDebug","labelObject","anyLabelSelected","checkIfSelected","getByCSV","createScene","initGpuPickers","initResize","initMaterials","initViewEvents","CompassControls","PanoControls","StatsPanel","addContainerElements","debounce","calculateUpdatedValues","handleWindowResize","animate","setClassification","clamp","updateClamping","colorMapKey","textureData","setNavigationType","off","removeContainerElements","destroyViewEvents","newProjection","setDataProjection","enable","setViewProjection","orbitDefaultApplied","cameraAlignerAdv","updateRenderColor","setTitle","export","measureExportType","loadMeasurementData","loadImageLabelData","setActiveLabelType","checkIfActive","deleteHighlighted","editCategoryName","currentCategoryName","categoryName","checkUniqueName","addRow","errors","setErrors","getError","deleteRow","getImageObs","getPointObs","getCamPose","numEntries","getCamId","cameraAlignerBasic","values","getCamName","setObservationType","rowNum","setCurrentRow","flashObservations","hideCurrentObservation","getObservationPosition","updateOffset","cloudList","camerasFiles","cameraHeight","cameraAdjustments","savedCameraState","existingCameras","allCameras","cameraFile","currentCameras","camerasToLoad","camerasToDelete","numRemoved","numChanged","deleteCameras","addCameras","clearArrowNavigation","setOrbitDefault","cameraLoaded","pointClouds","currentPointClouds","newPointClouds","pointCloudsToLoad","pointCloudsToDelete","deletePointCloud","cloudDetails","loadFile","loadNodes","currentOrthos","newOrthos","orthosToLoad","deleteOrtho","orthoInfo","addNewOrtho","setCameraHeights","setCameraAdjustments","setCameraMatrix","redrawImageObsMarkers","resetCameraMatrix","updateSize","PerspectiveCamera","WebGLRenderer","antialias","alpha","logarithmicDepthBuffer","powerPreference","isWebGL2","autoClear","RenderPass","stencilBuffer","EDLSupport","depthBuffer","texturePrecision","FloatType","UnsignedIntType","depthTexture","DepthTexture","resizeCanvas","aspect","w","resizeTarget","scenes","renderTarget","renderMaterial","renderTargetAttrs","clearDepth","renderWithTransparency","renderInFront","alignerScene","getPositionValues","resizeRenderTargets","updateSceneElements","renderPickerScene","renderPanoramic","renderSceneObjects","showCompassElement","requestAnimationFrame","offsetWidth","offsetHeight","isEmpty","hasCameras","capabilities","maxVaryings","floatFragmentTextures","show","isPointsOnly","screenScene","screenQuad","PlaneBufferGeometry","depthTest","Camera","nodesVisible","pointsVisible","getElementsByClassName","classList","drawExpandedState","getElementById","indexToShow","onclick","numberNodes","visiblePoints","maxPoints","childCount","ImageObservation","PointObservation","pointObsColor","imageObsColor","CameraAlignerAdv","setAddObservations","resetObservationType","currentRow","observationType","sceneObs","pointIdxAdd","imageIdxAdd","imageObsInterval","pointObsInterval","emptyObservation","imageObs","imageMesh","imageHidden","pointObs","pointMesh","pointHidden","imageIdentifier","pose","pointIdx","imageIdx","observation","imageName","getMeshName","pointName","removeMarker","enabled3dMode","getImageIdx","imageDir","addImageObservationMesh","getPointIdx","addPointObservationMesh","observationToAdd","clickScene","clickImage","resetHiddenState","updateAllMeshes","sphereMaterial","defaultColor","numberOfFlashes","interval","setInterval","setHex","clearInterval","obs","clearFlashIntervals","flashObservation","rotations","meshPos","eulerCsvInvert","currentID","CameraAlignerBasic","cameraAngles","setSingleAlignment","updateAlignment","code","applyTempRotation","minFOV","flyControls","wheelDelta","phiDelta","thetaDelta","assetSelected","moveEvent","zooming","OrbitController","FlyMoveControls","MouseConfig","touchHandler","addEventListeners","onMouseDoubleClick","toggleMouseMove","alignerLight","setUpVector","pivotLocation","smoothTransition","rotateLength","setPositionValues","setMeshVisible","updatePickerCamera","upEnabled","getClosestCoordinate","newEvent","MouseEvent","bubbles","cancelable","detail","screenX","changedPointers","screenY","altKey","shiftKey","metaKey","pointer","moveEnabled","aligner","moveEnd","mouseMoveDistance","moveStart","moveDistance","moveDelta","updateSelectionText","toggle","finishMouseUp","cancelLabel","highlightOnClick","selecting","cancelAlignment","scrolling","clearTimeout","wheelTimeout","wheelDelay","delta","flyModeEnabled","removeMouseUp","orbitObject","pivotLength","approxDistance","getCameraDistance","mouseEvent","changedTouches","first","eventType","pinchMove","sign","touchToMouse","adjustLookat","timeElapsed","withPerformanceMeasure","checkMovement","move","updateView","moveTolerance","endTimeout","endDelay","rotating","moveTick","moveInterval","panoControls","maxSteps","heightAbove","step","initial","addHeight","totalIntervals","sphereStart","sphereFinish","dRadius","dPhi","dTheta","upVector","orbitMovement","defaultRaycaster","threshold","intersectObject","distanceToRay","raycastDirection","vec","unproject","Raycaster","CopyShader","Pass","needsSwap","renderToScreen","FullScreenQuad","OrthographicCamera","_mesh","ShaderPass","textureID","call","UniformsUtils","fsQuad","writeBuffer","readBuffer","autoClearColor","autoClearDepth","autoClearStencil","MaskPass","writeValue","clearValue","buffers","setMask","setLocked","stencil","setTest","setOp","REPLACE","setFunc","ALWAYS","setClear","EQUAL","KEEP","ClearMaskPass","EffectComposer","parameters","_pixelRatio","getPixelRatio","_width","_height","renderTarget1","renderTarget2","passes","copyPass","clock","Clock","swapBuffers","addPass","pass","insertPass","isLastEnabledPass","passIndex","deltaTime","getDelta","currentRenderTarget","maskActive","il","NOTEQUAL","effectiveWidth","effectiveHeight","setPixelRatio","pixelRatio","SSAARenderPass","clearColor","clearAlpha","sampleLevel","unbiased","copyShader","copyUniforms","copyMaterial","premultipliedAlpha","blending","AdditiveBlending","sampleRenderTarget","jitterOffsets","JitterVectors","getHex","baseSampleWeight","jitterOffset","setViewOffset","sampleWeight","clearViewOffset","TextMaterial","MeshPhongMaterial","composer","sizeRatioLarge","sizeRatioSmall","lightPosition","cube","cubeSize","cubeColorStandard","cubeColorHover","cubeEdgeColor","cubeTextColor","cubeMaterials","donutSize","donutColor","donutTextColor","north","west","east","south","initAntiAliasing","setCanvasStyle","addObjects","addLights","cameraDistance","ssaaRenderPass","Group","addRotationCube","addCompassRing","addCompassLetters","ambientLight","spotLight","SpotLight","castShadow","cubeGeometry","BoxBufferGeometry","getTextMaterial","donutGeometry","donutMaterial","getCircleMaterial","getDirectionMesh","canvasSize","border","outlineSize","cubeColor","translate","lineWidth","strokeStyle","strokeText","letter","beginPath","textHeight","geometryUpper","materialUpper","getLetterMaterial","FrontSide","meshUpper","geometryLower","materialLower","BackSide","meshLower","checkMouseHover","resetCamera","getSelectedSide","togglePointer","offsetLeft","offsetTop","setFromCamera","intersect","materialIndex","faceIndex","setCubeMaterials","hoverIndex","pointA","pointB","zenith","startLat","destLat","startLng","destLng","brng","ratio","setContainerCursor","lookatLocal","lookatLonLat","yPosLocal","yPosLonLat","cameraLocal","cameraLatLon","groupYaw","bearing","groupPitch","rotateLetters","cubeYaw","calculateRotations","lineStart","lineEnd","Line3","setFromNormalAndCoplanarPoint","intersectLine","copyTextToClipboard","vertexWrapped","float","textField","userWarning","cardButtons","alignSelf","card","footerDiv","boxShadow","zIndex","measurementUnitsParent","justifyContent","measurementUnitsFlex","measurementUnitsRadio","imageOnlyInfoButton","marginside","expandText","bold","tableContent","cardHeader","cell","headerTitle","calculateButton","recalculate","flexDirection","recalculateButton","copyClipboard","measureList","lastTableRow","borderBottom","ExportDialog","exportType","setExportType","setOrdering","InputLabel","Select","exportMeasurements","MeasureTypeIcon","setMeasureType","m","ImportExportIcon","MeasurementCard","setHover","updateMeasureHover","rows","formatVolume","getVolumeResults","verticesReprojected","generateVertexPositions","generateMeasurementRows","Card","onMouseOver","onMouseLeave","raised","CardHeader","titleTypographyProps","subheader","subheaderTypographyProps","CardContent","TableContainer","Table","TableBody","isLastRow","TableRow","TableCell","align","deleteMeasurement","renameMeasurement","Measurements","useTheme","measurementUnits","exportModalOpen","setExportModalOpen","setMeasureUnits","loadImportData","encoded","decodeURIComponent","closeExportMenu","toggleMeasurements","updateMeasureType","setMeasurementUnits","reversed","iconProps","imageOnlyWarningOpen","setImageOnlyWarningOpen","exportDisabled","importDisabled","imageDistanceText","RadioGroup","FormControlLabel","control","Radio","fileType","getMeasureExportType","fileDialog","accept","reader","FileReader","readAsText","openImportBrowser","fileFilter","openImportElectron","assetDrawerWidth","backdrop","inside","drawer","drawerPaper","modal","tab","tabGrow","AssetDrawer","assetDrawerState","setTabValue","tabsEnabled","setDefaultTab","setAssetDrawerState","activeMeasurePrompt","setActiveMeasurePrompt","newTabValue","setNewTabValue","closeDrawer","setCloseDrawer","measurementsOpen","hasMeasurements","Drawer","anchor","transitionDuration","paper","AppBar","indicatorColor","Tab","cameraMatrixFilter","saveMatrixFile","cameraTransformPath","copyFile","readTransformFile","errorResponse","cols","col","menuButton","flexGrow","mixins","toolbar","projectionText","transformMatrix","matrixColumn","buttonDiv","slimButton","dropdown","matrixAndButtons","verticalButtons","MatrixTextField","inputProps","number","multiplier","trunc","truncate","MatrixRepresentation","cameraTransform","ProjectDetails","setOpen","warnOpen","setWarnOpen","setHeight","setProj","imported","setImported","setCameraTransform","correction","projectHeight","basicAdjustments","handleWarnClose","toMeters","existing","handleCollisions","name1","name2","matchingProjection","selectedProjection","getNewProjection","hasBasicAlignment","FormControl","FormHelperText","InputLabelProps","shrink","ListSubheader","conflict","resetBasicAlignerCamera","trimmedName","emptyName","emptyHeight","emptyProjection","heightInMeters","projName","MainAppBar","handleAssetDrawerOpen","handleSettingsDrawerOpen","Toolbar","drawerWidth","asterisk","drawerHeader","list","background","listItem","formControl","switch","colorPreview","objectFit","classificationPreview","borderColor","borderStyle","borderWidth","switchLabel","switchElement","boldTypography","SettingsDrawer","classificationVisibilities","classificationColors","setClassificationColors","orthoFiles","dispatchInterval","opacitySliderValue","setOpacitySlider","saveOpacity","useCallback","orthoOpacitySliderValue","setOrthoOpacitySlider","saveOrthoOpacity","distanceSliderValue","setDistanceSlider","saveCloudDistance","maxPointsSlider","setMaxPointsSlider","saveCloudMaxPoints","cloudSizeSlider","setCloudSizeSlider","saveCloudSize","heightClipSlider","setHeightClipSlider","saveHeightClip","intensityClipSlider","setIntensityClipSlider","saveIntensityClip","updateOpacity","setPointCloudOpacity","updateOrthoOpacity","setOrthoOpacity","updateDistance","setPointCloudDistance","updateMaxPoints","setPointCloudMaxPoints","updateCloudSize","setPointCloudSize","updateHeightClip","setPointCloudHeightClip","updateIntensityClip","setPointCloudIntensityClip","setVisibleClassifications","setPointCloudColorMap","setPointCloudColorType","setPointCloudDynamicSize","setPointCloudCircularPoints","red","green","blue","padStart","classificationsShader","isIntensity","isHeightmap","colorMapRequired","gutterBottom","renderValue","Avatar","Slider","valueLabelDisplay","_","subtitle2","Switch","togglePickerDebug","every","denseCell","footerDense","minHeight","hiddenSort","clip","noSelect","rowDisabled","break","rowHover","EnhancedTableHead","order","orderBy","onRequestSort","columns","deletable","isDense","isSortable","cellClassName","TableHead","column","sortDirection","TableSortLabel","property","EnhancedTable","rowType","onRowClick","onDeleteClick","pageSize","defaultSort","sortable","numRowsPerPage","setOrder","setOrderBy","selectedRow","setSelectedRow","page","setPage","rowsPerPage","setRowsPerPage","descendingComparator","compA","compB","maxPage","getComparator","sliced","footerClassName","cellContent","Paper","isItemSelected","tabIndex","numeric","showHover","TablePagination","rowsPerPageOptions","onChangePage","newPage","onChangeRowsPerPage","titleClose","adornedEnd","utmButton","selectMargin","UserProjectionPanel","loadProjectionToEdit","setActiveTab","option","custom","user","EditPanel","customProjection","updateEditableValues","transformCheckbox","setTransformCheckbox","clearProjectionValues","existingName","projString","updateString","updateOrigin","updateTranslation","labelId","String","multiline","InputProps","startAdornment","InputAdornment","Grid","xs","nameTrim","stringTrim","nameError","stringError","SearchPanel","setType","searchTerm","setSearchTerm","hemisphere","setHemisphere","searching","setSearching","searchResults","setSearchResults","handleString","getProjections","searchText","pageNumber","previousResults","maxPageNumber","parsed","epsg","ProjectionsManager","projectionsOpen","setProjectionsOpen","setExistingName","setNewProjection","setCustomProjection","clearAllErrors","projectionData","dataCopy","hasTransform","transformCopy","ipcRenderer","tabLabel","scroll","dividers","newactiveTab","newValues","appReducer","combineReducers","projectReducer","cameraReducer","foldersReducer","projectionsReducer","settingsReducer","assetsReducer","store","configureStore","loadConfig","configInit","middleware","thunk","projectFileType","filterFilter","saveProjectAs","getState","nameWithoutExt","writeProject","saveProject","allowSaveAs","loadProjectJSON","projectJSON","loadProjectFile","jsonConfigVersion","versionOld","alert","projectString","saved","exit","hasChanged","isEqual","send","minHeightContent","toggleOptionParent","toggleOptionCheckbox","toggleOptionFlex","imageObservationSuccess","pointObservationSuccess","errorLow","errorMedium","errorHigh","checkboxPadding","PointObservationIcon","ObservationIcon","ImageObservationIcon","colorSecondary","colorInherit","ResidualError","ImageAlignerAdvanced","addObservations","setTabsEnabled","alignerAdvOpen","alignerBasicOpen","setAlignerAdvOpen","setRows","setCsvPath","encompassCsvPath","setEncompassCsvPath","setAligned","alignmentConfirm","setAlignmentConfirm","alignerMatrixPath","setAlignerMatrixPath","setValid","tableNonEmpty","setTableNonEmpty","closePrompt","setClosePrompt","isAligned","setIsAligned","alertOpen","setAlertOpen","askRemoveOpen","setAskRemoveOpen","alignPosition","setAlignPosition","alignRotation","setAlignRotation","handleOpen","resetRowsAndMesh","generateRows","parseResiduals","resArray","rounded","obs_num","img_obs","pc_obs","resetCameraAligner","rowsTemp","addRowCameraAligner","updateRows","tempRows","getErrorCameraAligner","resetRowIcons","hasImageObs","getImageObsCameraAligner","hasPointObs","getPointObsCameraAligner","cancelCurrentAlignment","checkRowsValid","getNumEntriesCameraAligner","validCheck","nonEmpty","imgCheck","pointCheck","removeAllListeners","removed","noCameras","setObservationTypeCameraAligner","toggleCameraAligner","csvEncompassPath","csvEncompassOut","getCamPoseCameraAligner","checkIfAligned","setCurrentRowCameraAligner","camID","getCamIdFromAligner","deleteRowCameraAligner","rowAdd","addRows","isConverted","camPoseEntry","largeResiduals","initialPath","correctionName","correctionPath","residualsTemp","setErrorsCameraAligner","titleTop","AlignerShortcuts","ImageAlignerBasic","singleAlignment","setAlignerBasicOpen","setHasTransform","hasActiveCamera","setBasicAlignerState","savedAngle","activeCameraName","getCurrentCameraName","alignment","isModified","epsilon","dz","checkDataModified","updated","EnhancedIconButton","labelFilter","modelFilter","dxfFilter","titleInfo","titleMin","listContent","labelFixedHeight","labelTitle","labelTitleWarning","labelTitleError","progressToolbar","toolbarLinear","toolbarProgressCenter","downloadMargin","downloadResourceDialog","mixedDataWarning","Label","isScrolling","labelName","TrainingArea","scrollingDivLength","useScrollingDiv","scrollingDivHeight","deletePrompt","setDeletePrompt","trainingAreaID","disableTypography","useIsScrolling","itemCount","itemSize","deleteTrainingAreas","Category","isValidCategory","editPrompt","setEditPrompt","addNewLabelDisabled","addNewlabelTooltip","ImageLabelling","categoryList","imageLabelOpen","setImageLabelOpen","labelType","setLabelType","minimized","setMinimized","setAddCategory","importData","setImportData","modalName","setModalName","labelLoadProgress","setLabelLoadProgress","trainClassifyProgress","setTrainClassifyProgress","trainClassifyExe","setTrainClassifyExe","predOrTrain","setPredOrTrain","training","setTraining","trainingURL","setTrainingURL","downloadingResources","setDownloadingResources","downloadResourcesDialog","setDownloadResourcesDialog","trainingPrompt","setTrainingPrompt","classificationPrompt","setClassificationPrompt","cameraFiles","isOrthoLabel","isSceneLabel","importPrompt","importCategories","numPanoramics","numPlanars","numImportLabels","resetExecutableValues","handleCancelProgress","handleImport","checkCategoryUniqueness","handleCategoryChange","handleViewTraining","importLabelsPTH","downloading_resources","extracting_resources","coco_data","importLabels3DL","forceInitialProgress","updateDownloadingResources","runClassification","modelPath","loadedImageLabelPaths","runTraining","numIterations","cocoPath","outputPath","modelName","activeImageLabelPaths","gpu_memory_error","model_diverge_error","label_bounds_error","model_file_path","HTMLInputElement","labelHotkey","isTraining","labelDisabled","trainingLinkDisabled","sceneTrainingDisabled","categoryListDisabled","noAnnotations","noImages","canRunTraining","exportJSON","canExportDXF","tempCocoPath","runExportDXF","CircularProgress","areas","iterations","validChar","iterNumber","validIterations","scoreNumber","validScore","menuItem","ContextMenu","labelActive","toggleCamera","getMenuItems","onEnter","buttonParent","heading","preview","LayerSwitcher","setAnchorEl","clearTooltipText","basemapIds","activeBasemap","previews","currentTarget","Popover","anchorOrigin","vertical","horizontal","transformOrigin","layerID","large","small","offsetSmall","borderTop","offsetLarge","gradient","ViewSwitcher","handleSwitched","SceneViewer","setViewer","orthoLabelOpen","setOrthoLabelOpen","closeAllTools","projectModifiedDate","viewerSwitched","savedAerialState","divRef","useRef","mapRef","viewerTooltipText","updateViewerTooltipText","aerialTooltipText","updateAerialTooltipText","customAlertHTML","setCustomAlertHTML","cameraState","throttle","triggerWindowResize","Event","addAllAssets","checkShiftReset","reconcileCameras","reconcilePointClouds","reconcileOrthos","resetDefaultAerialState","resetDefaultOrbitState","validOrbit","validCamera","isValidCameraState","setProjectName","removeInteractions","getAvailableClassifications","viewerProps","viewerRef","THREE","defs","register","resetLoadedOnce","viewProjectionUnits","mapClasses","viewerClasses","classLarge","classSmall","getClasses","ref","processTimeout","dataPathName","pointsFolder","imagesFolder","dialogTitle","exportText","contentCenter","cancelProgress","cancelContent","rootOutputPath","webOutputPath","numAssets","StaticExporter","exportName","setExportName","dataExportOpen","setDataExportOpen","runnable","setRunnable","successOpen","setSuccessOpen","cancelOpen","setCancelOpen","cancelling","setCancelling","finishing","setFinishing","runningExe","setRunningExe","exportTopMessage","setExportTopMessage","exportBottomMessage","setExportBottomMessage","exportPercent","setExportPercent","exportAssets","setExportAssets","numOrthos","canExport","numRawPointcloud","setNewRunningExe","setExportMessage","getAssetIndex","createNewFolder","folderPath","existsSync","rmdir","recursive","moveCameraData","imagesPath","imagesData","newImagePath","moveEncompassData","inputPath","copydir","moveRawPointcloud","updateCameraDataState","assetIndex","finalPath","moveAssetData","finishExport","updateEncompassDataState","updateRawPointcloudDataState","matrixPath","updateCameraTransformPath","projectJson","projectPath","miniViewerPath","getMiniViewerPath","exeOutputPath","copyFileSync","exportToHtml","buildPath","getBuildPath","outputFolder","sanitize","toProcess","processNextAsset","pointListItem","cameraListItem","orthoListItem","createMuiTheme","appBar","snackbar","tooltip","overrides","MuiPopover","MuiTooltip","backdropText","DragDropLoader","addFilePathsFunc","handleDrop","BackdropToggle","backdropOpen","setBackdropOpen","Backdrop","App","projectDrawerState","projectActiveTab","setDrawerState","settingsDrawerState","setSettingsDrawerState","setSelectedTab","addFilePaths","configs","loadFromCompiledExe","rawArgs","argv","arg","getAllFileArgs","showMessageBox","buttons","noLink","selection","quit","oncontextmenu","cache","loadFromStaticSite","updateCompassOffset","ThemeProvider","sendToMainWindow","mainWindow","getCurrentWindow","webContents","fileMenu","submenu","helpMenu","shell","openPath","toolsMenu","debugMenu","setToolAvailability","toolName","Menu","getApplicationMenu","items","checkAllowedMenuItems","template","generateTemplateList","menu","buildFromTemplate","setApplicationMenu","MessageProvider","messageRef","onMessageClose","closeSnackbar","maxSnack","TransitionComponent","Zoom","ReactDOM","electron","isPackaged"],"mappings":"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","file":"static/js/main.9b62ba5c.chunk.js","sourcesContent":["import {fs} from '../../electron-modules';\r\nimport path from 'path';\r\n\r\nconst bytesPerMegabyte = 1024**2;\r\nconst byteReadSize = 5 * bytesPerMegabyte;\r\n\r\nexport const readBufferChunks = (filePath, byteStart, chunkSize, maxChunks): Promise => {\r\n return new Promise((resolve, reject) => {\r\n const debugMessages = false;\r\n const timeStart = performance.now();\r\n\r\n const stats = fs.statSync(filePath);\r\n const fileSizeInBytes = stats.size;\r\n\r\n // No more data can be found\r\n if (byteStart >= fileSizeInBytes) {\r\n resolve({buffers: []});\r\n return;\r\n }\r\n\r\n if (debugMessages) {\r\n console.log(`[BufferReader]: byte start: ${byteStart}`);\r\n }\r\n\r\n // Initialize our results buffer (slightly larger than required)\r\n let bytesRead = 0;\r\n let size = (maxChunks + 1) * chunkSize;\r\n let data = Buffer.alloc(size);\r\n\r\n /** Append file chunks to our data buffer when new data is received */\r\n const onDataEvent = chunk => {\r\n let buffer = chunk.slice(0, chunk.length);\r\n data.set(buffer, bytesRead);\r\n bytesRead += chunk.length;\r\n };\r\n\r\n /** Send our data to our viewer after finishing reading */\r\n const onEndEvent = () => {\r\n let response = {\r\n file: baseFileEvent(filePath),\r\n buffers: chunksFromBuffer(),\r\n bufferChunkSize: chunkSize,\r\n numBytes: fileSizeInBytes,\r\n maxchunks: maxChunks\r\n };\r\n\r\n if (debugMessages) {\r\n let timeEnd = performance.now();\r\n let timeElapsed = timeEnd - timeStart;\r\n timeElapsed = Math.round(timeElapsed * 100) / 100;\r\n console.log(`[BufferReader]: read file buffer: ${timeElapsed}ms`);\r\n console.log(response.buffers);\r\n }\r\n\r\n resolve(response);\r\n };\r\n\r\n /** Convert full buffer to arraybuffer chunks */\r\n const chunksFromBuffer = () => {\r\n let chunks = [];\r\n let buffer = data.slice(0, bytesRead).buffer;\r\n\r\n for (let i = 0; i < maxChunks; i++) {\r\n let start = i * chunkSize;\r\n if (start >= bytesRead) {\r\n break;\r\n }\r\n\r\n let finish = start + chunkSize;\r\n finish = Math.min(bytesRead, finish);\r\n let chunk = buffer.slice(start, finish);\r\n chunks.push(chunk);\r\n }\r\n\r\n return chunks;\r\n };\r\n\r\n const initReader = () => {\r\n const bytesToRead = maxChunks * chunkSize;\r\n const safeReadSize = Math.min(byteReadSize * 0.5, bytesToRead);\r\n\r\n fs.createReadStream(filePath, {\r\n highWaterMark: safeReadSize,\r\n start: byteStart,\r\n end: byteStart + bytesToRead\r\n }).on(\"end\", () => {\r\n onEndEvent();\r\n }).on(\"data\", chunk => {\r\n onDataEvent(chunk);\r\n });\r\n };\r\n\r\n initReader();\r\n });\r\n};\r\n\r\nexport const readFileJSON = (path: string, staticFile=false): Promise => {\r\n return new Promise((resolve, reject) => {\r\n if (staticFile) {\r\n readJsonFromURL(resolve, reject, path);\r\n } else {\r\n readJsonElectron(resolve, reject, path);\r\n }\r\n });\r\n};\r\n\r\nexport const readFileBuffer = (path: string, staticFile=false): Promise => {\r\n return new Promise(((resolve, reject) => {\r\n if (staticFile) {\r\n readFileBufferFromURL(resolve, reject, path);\r\n } else {\r\n readFileBufferElectron(resolve, reject, path);\r\n }\r\n }));\r\n};\r\n\r\nexport const baseFileEvent = filePath => ({\r\n name: path.basename(filePath),\r\n path: filePath,\r\n visible: true,\r\n local: false\r\n});\r\n\r\nconst readJsonFromURL = (resolve, reject, path) => {\r\n fetch(path, {\r\n headers: {'Content-Type': 'application/json'}\r\n })\r\n .then(res => res.json())\r\n .then(data => {\r\n resolve(data);\r\n })\r\n .catch(() => {\r\n reject('Error reading file as json');\r\n });\r\n};\r\n\r\nconst readJsonElectron = (resolve, reject, path) => {\r\n fs.readFile(path, 'utf-8', (err, data) => {\r\n if (err) {\r\n reject('Error reading file as json');\r\n return;\r\n }\r\n\r\n resolve(JSON.parse(data));\r\n });\r\n};\r\n\r\nconst readFileBufferFromURL = (resolve, reject, path) => {\r\n fetch(path)\r\n .then(res => {\r\n if (res.status === 404) {\r\n throw new Error(\"File Not Found\");\r\n }\r\n return res.arrayBuffer();\r\n })\r\n .then(data => {\r\n if (data.byteLength === 0) {\r\n throw new Error(\"File Not Found\");\r\n }\r\n resolve(data);\r\n })\r\n .catch(() => {\r\n reject('Error reading file as arraybuffer');\r\n });\r\n};\r\n\r\nconst readFileBufferElectron = (resolve, reject, path) => {\r\n fs.readFile(path, (err, data) => {\r\n if (err) {\r\n reject('Error reading file as arraybuffer');\r\n return;\r\n }\r\n\r\n resolve(data.buffer);\r\n });\r\n};\r\n","import {createSlice, nanoid, PayloadAction} from '@reduxjs/toolkit';\r\nimport path from 'path';\r\nimport slash from 'slash';\r\nimport {\r\n encompassFileFormat,\r\n imageListFormats,\r\n lasFileFormat,\r\n orthoFormats,\r\n planarListFormats\r\n} from '../asset-utils';\r\n\r\nexport interface CameraData {\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?: object\r\n}\r\n\r\ninterface PointCloudData {\r\n path: string;\r\n}\r\n\r\nexport interface OrthoData {\r\n imageBounds: [];\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 Asset {\r\n id: string;\r\n name: string;\r\n fromJSON: boolean;\r\n date: string;\r\n visible: boolean;\r\n folderID: string;\r\n type: AssetType;\r\n data: PointCloudData | CameraData[] | OrthoData;\r\n}\r\n\r\nexport interface AssetListItem {\r\n folderID: string,\r\n assetPath: string\r\n data?: CameraData[] | OrthoData;\r\n}\r\n\r\n// NOTE: Always add new asset types to bottom of list\r\nexport enum AssetType {\r\n LAS,\r\n Encompass,\r\n Panoramic,\r\n Unknown,\r\n OrthoMosaic,\r\n Planar\r\n}\r\n\r\nexport const assetTypeFromExtension = (ext: string): AssetType => {\r\n if (ext === lasFileFormat) {\r\n return AssetType.LAS;\r\n }\r\n\r\n if (ext === encompassFileFormat) {\r\n return AssetType.Encompass;\r\n }\r\n\r\n if (imageListFormats.indexOf(ext) !== -1) {\r\n return AssetType.Panoramic;\r\n }\r\n\r\n if (planarListFormats.indexOf(ext) !== -1) {\r\n return AssetType.Planar;\r\n }\r\n\r\n if (orthoFormats.indexOf(ext) !== -1) {\r\n return AssetType.OrthoMosaic;\r\n }\r\n\r\n return AssetType.Unknown;\r\n};\r\n\r\nconst getAssetPayload = (folderID: string, assetPath: string, data?: CameraData[] | OrthoData): Asset => {\r\n assetPath = slash(assetPath);\r\n const extension = path.extname(assetPath).slice(1);\r\n\r\n let assetData;\r\n\r\n if (data) {\r\n assetData = data;\r\n } else {\r\n assetData = {\r\n path: extension === encompassFileFormat\r\n ? path.dirname(assetPath)\r\n : assetPath\r\n };\r\n }\r\n\r\n const payload = {\r\n id: nanoid(),\r\n name: path.basename(assetPath),\r\n date: new Date().toISOString(),\r\n type: assetTypeFromExtension(extension),\r\n folderID,\r\n visible: true,\r\n fromJSON: false,\r\n data: assetData\r\n } as Asset;\r\n\r\n return payload;\r\n};\r\n\r\nexport const assetsSlice = createSlice({\r\n name: 'assets',\r\n initialState: [] as Asset[],\r\n reducers: {\r\n addAsset: {\r\n reducer: (state, action: PayloadAction) => {\r\n state.push(action.payload);\r\n },\r\n prepare: (folderID: string, assetPath: string, data?: CameraData[] | OrthoData): {payload: Asset} => {\r\n const payload = getAssetPayload(folderID, assetPath, data);\r\n return {payload};\r\n }\r\n },\r\n addAssets: {\r\n /** Add multiple assets at once. Much faster than adding single assets */\r\n reducer: (state, action: PayloadAction) => {\r\n action.payload.forEach(payload => {\r\n state.push(payload);\r\n });\r\n },\r\n prepare: (assetsList: AssetListItem[]): {payload: Asset[]} => {\r\n const payload = assetsList.map(assetItem => {\r\n const {folderID, assetPath, data} = assetItem;\r\n return getAssetPayload(folderID, assetPath, data);\r\n });\r\n\r\n return {payload};\r\n }\r\n },\r\n changeFolder: (state, action: PayloadAction<{folderID: string, assetID: string}>) => {\r\n const {assetID, folderID} = action.payload;\r\n const asset = state.find(asset => asset.id === assetID);\r\n\r\n if (asset) {\r\n asset.folderID = folderID;\r\n }\r\n },\r\n changeName: (state, action) => {\r\n const {assetID, name} = action.payload;\r\n const asset = state.find(asset => asset.id === assetID);\r\n\r\n if (asset) {\r\n asset.name = name;\r\n }\r\n },\r\n toggleVisibility: (state, action) => {\r\n const assetID = action.payload;\r\n const asset = state.find(asset => asset.id === assetID);\r\n\r\n if (asset) {\r\n asset.visible = !asset.visible;\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 deleteAsset: (state, action) =>\r\n state.filter(asset => asset.id !== action.payload),\r\n deleteAssets: (state, action) =>\r\n state.filter(asset => asset.folderID !== action.payload)\r\n }\r\n});\r\n\r\nexport default assetsSlice.reducer;\r\n\r\nexport const {\r\n addAsset,\r\n addAssets,\r\n changeFolder,\r\n toggleVisibility,\r\n toggleFolderVisibility,\r\n changeName,\r\n deleteAsset,\r\n deleteAssets,\r\n} = assetsSlice.actions;\r\n\r\nexport const selectAllAssets = state =>\r\n state.assets;\r\n\r\nexport const getPointCloudAssets = assets =>\r\n assets.filter(asset => asset.type === AssetType.Encompass || asset.type === AssetType.LAS);\r\n\r\nexport const getCameraFileAssets = assets =>\r\n assets.filter(asset => asset.type === AssetType.Panoramic || asset.type === AssetType.Planar);\r\n\r\nexport const getOrthoAssets = assets =>\r\n assets.filter(asset => asset.type === AssetType.OrthoMosaic);\r\n\r\nexport const selectAssetsByFolderID = folderID => state =>\r\n state.assets.filter(asset => asset.folderID === folderID);\r\n\r\nexport const selectAssetByID = assetID => state =>\r\n state.assets.find(asset => asset.id === assetID);","import {createSlice} from '@reduxjs/toolkit';\r\n\r\nexport const defaultProjectTitle = 'Untitled Project';\r\ninterface ProjectState {\r\n name: string;\r\n modified: string;\r\n path: string;\r\n newProject: boolean;\r\n configVersion: number;\r\n}\r\n\r\nexport const currentConfigVersion = 3.4;\r\n\r\nexport const projectSlice = createSlice({\r\n name: 'project',\r\n initialState: {\r\n path: '',\r\n newProject: true,\r\n name: defaultProjectTitle,\r\n modified: new Date().toISOString(),\r\n configVersion: currentConfigVersion\r\n } as ProjectState,\r\n reducers: {\r\n refreshModified: (state, action) => {\r\n state.modified = new Date().toISOString();\r\n },\r\n changeName: (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 refreshModified,\r\n changeName,\r\n changePath\r\n} = projectSlice.actions;\r\n\r\nexport default projectSlice.reducer;\r\n\r\nexport const selectName = state => state.project.name;\r\nexport const selectProjectModified = state => state.project.modified;","import {Projection, Transform} from '../redux/projections-slice';\r\nimport {storage} from \"../electron-modules\";\r\n\r\nexport const unknownTextMeters = \"Unknown Projection (m)\";\r\nexport const unknownTextFeet = \"Unknown Projection (ft)\";\r\n\r\nexport const unknownProjectionMeters = {\r\n type: 'proj4',\r\n name: unknownTextMeters,\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 name: unknownTextFeet,\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 generateID = (text) => {\r\n return text.replace(/\\s/g, '.');\r\n};\r\n\r\nclass Projections {\r\n public data: Projection[] = [];\r\n\r\n constructor() {\r\n this.load();\r\n }\r\n\r\n isDuplicate(data) {\r\n const id = data.name;\r\n const ids = this.data.map(x => x.name);\r\n return ids.indexOf(id) !== -1;\r\n }\r\n\r\n save(data) {\r\n if (this.isDuplicate(data)) {\r\n return false;\r\n }\r\n\r\n this.data.push(data);\r\n const result = storage.set('projection', this.data);\r\n if (result.status) {\r\n this.load();\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n load() {\r\n const result = storage.get(\"projection\");\r\n if (result.status === false) {\r\n return;\r\n }\r\n\r\n // Data has get/set methods instead of raw values\r\n // so we dump and load json values to get raw data\r\n this.data = result.data.map(obj => {\r\n return JSON.parse(JSON.stringify(obj));\r\n });\r\n }\r\n\r\n delete(id) {\r\n const rows = this.data.map(x => x.name);\r\n const index = rows.indexOf(id);\r\n this.data.splice(index, 1);\r\n const result = storage.set('projection', this.data);\r\n if (result.status) {\r\n this.load();\r\n }\r\n }\r\n}\r\n\r\nconst projections = new Projections();\r\nexport default projections;\r\n","import {createSlice, PayloadAction} from '@reduxjs/toolkit';\r\nimport {unknownProjectionMeters} from '../projections/projections';\r\n\r\nexport interface Projection {\r\n type: string,\r\n name?: string,\r\n string: string,\r\n imported?: 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: string\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: \"m\"\r\n } as ProjectionData,\r\n reducers: {\r\n changeData: (state, action: PayloadAction) => {\r\n state.data = action.payload;\r\n },\r\n changeView: (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 changeData,\r\n changeView,\r\n changeMeasureUnits\r\n} = projectionsSlice.actions;\r\n\r\nexport default projectionsSlice.reducer;\r\n\r\nexport const selectView = state => state.projections.view;\r\nexport const selectData = state => state.projections.data;\r\nexport const selectMeasureUnits = state => state.projections.measureUnits;","import {\r\n Button,\r\n createStyles,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n IconButton,\r\n LinearProgress,\r\n makeStyles,\r\n TextField,\r\n Theme\r\n} from \"@material-ui/core\";\r\nimport clsx from 'clsx';\r\nimport React, {useEffect, useState} from \"react\";\r\nimport CloseIcon from '@material-ui/icons/Close';\r\nimport RemoveIcon from '@material-ui/icons/Remove';\r\nimport Draggable from \"react-draggable\";\r\nimport { headerHeight } from \"./app\";\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 draggableTitleMinimize: {\r\n color: theme.palette.grey[500],\r\n },\r\n draggableContent: {\r\n padding: theme.spacing(0),\r\n paddingTop: \"0px !important\",\r\n height: \"fit-content\",\r\n width: \"500px\",\r\n maxWidth: \"500px\",\r\n marginTop: `${headerHeight + theme.spacing(1)}px`\r\n },\r\n draggableContentSlim: {\r\n height: \"min(75vh, 600px)\",\r\n width: \"400px\",\r\n maxWidth: \"400px\"\r\n },\r\n draggableContentLeft: {\r\n marginLeft: theme.spacing(1)\r\n },\r\n draggableTopDiv: {\r\n display: \"flex\",\r\n alignItems: \"center\"\r\n },\r\n draggableBackdropPaper: {\r\n height: \"inherit\"\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\r\n },\r\n draggableTitleDown: {\r\n cursor: \"grabbing\"\r\n },\r\n progressContent: {\r\n padding: `${theme.spacing(3)}px !important`,\r\n },\r\n progressNoTransition: {\r\n transition: \"none\"\r\n }\r\n }),\r\n);\r\n\r\nexport const PromptDialog = props => {\r\n const {open, title, prompt, button, onCancel, onSubmit} = props;\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 {button}\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const AlertDialog = props => {\r\n const {open, title, handleClose} = props;\r\n\r\n return (\r\n \r\n \r\n {title}\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\nexport const TextDialog = props => {\r\n const [text, setText] = useState(props.default);\r\n const [disabled, setDisabled] = useState(true);\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 const handleCancel = () => {\r\n props.onCancel();\r\n setText(props.default);\r\n };\r\n\r\n const handleSubmit = () => {\r\n const trimmedText = text.trim();\r\n\r\n props.onSubmit(trimmedText);\r\n\r\n if (props.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 {props.prompt}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const DraggableDialog = props => {\r\n const {open, title, narrow, onClose, onMinimize} = props;\r\n const classes = useStyles();\r\n\r\n const [mouseDown, setMouseDown] = useState(false);\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 return (\r\n \r\n \r\n \r\n {/* Draggable title */}\r\n \r\n {title}\r\n \r\n\r\n {/* Optional minimize button */}\r\n {onMinimize && (\r\n \r\n )}\r\n\r\n {/* Close button */}\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\nexport const ProgressDialog = props => {\r\n const {open, text, percent, noTransition} = 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","import {createSlice, nanoid, PayloadAction} from '@reduxjs/toolkit';\r\n\r\ninterface Folder {\r\n name: string;\r\n id: string;\r\n date: string;\r\n isDefault: boolean;\r\n}\r\n\r\nexport const foldersSlice = createSlice({\r\n name: 'folders',\r\n initialState: [\r\n {\r\n name: 'Default',\r\n id: nanoid(),\r\n date: new Date().toISOString(),\r\n isDefault: true\r\n } as Folder\r\n ],\r\n reducers: {\r\n addFolder: {\r\n reducer: (state, action: PayloadAction) => {\r\n state.push(action.payload);\r\n },\r\n prepare: (name: string) => {\r\n const id = nanoid();\r\n const date = new Date().toISOString();\r\n return {payload: {id, name, date, isDefault: false}};\r\n }\r\n },\r\n deleteFolder: (state, action) =>\r\n state.filter(folder => folder.id !== action.payload || folder.isDefault),\r\n renameFolder: (state, action) => {\r\n const folder = state.find(folder => folder.id === action.payload.id);\r\n\r\n if (folder) {\r\n folder.name = action.payload.name;\r\n }\r\n }\r\n }\r\n});\r\n\r\nexport const {\r\n addFolder,\r\n deleteFolder,\r\n renameFolder\r\n} = foldersSlice.actions;\r\nexport default foldersSlice.reducer;\r\n\r\nexport const selectDefaultFolder = state => state.folders.find(folder => folder.isDefault);","import {\r\n isDevMode,\r\n app,\r\n fs,\r\n child,\r\n process,\r\n logDirectoryPath\r\n} from \"./electron-modules\";\r\nimport path from \"path\";\r\nimport slash from \"slash\";\r\n\r\nconst engineMessageTypeJSON = \"NODEJSJSONDATA\";\r\n\r\nclass Executable {\r\n public exePath: string;\r\n public exeName: string;\r\n public running: boolean;\r\n public child;\r\n public developerKey: string;\r\n public spawnDetached: boolean;\r\n private 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.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 if (!isDevMode) {\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 } else {\r\n // grab full path from config file\r\n const contents = fs.readFileSync(`${appPath}/develop.env`);\r\n const env = JSON.parse(contents);\r\n executablePath = env[this.developerKey];\r\n }\r\n\r\n return executablePath;\r\n }\r\n\r\n statusMessage(message) {\r\n if (!this.showStatus) {\r\n return;\r\n }\r\n\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(opts = {}) {\r\n if (this.running) {\r\n console.log(\"Cannot launch multiple instances\");\r\n return;\r\n }\r\n\r\n const defaults = {\r\n parseLineData: true,\r\n parseJSON: true,\r\n showStatus: true,\r\n saveLogs: false,\r\n command: null,\r\n onClose: null,\r\n onData: null,\r\n onLine: null\r\n };\r\n\r\n let options = {...defaults, ...opts};\r\n\r\n this.running = true;\r\n this.showStatus = options.showStatus;\r\n\r\n let commands = this.parseCommandsList(options.command);\r\n let executablePath = this.path;\r\n\r\n let cwd = path.dirname(executablePath);\r\n this.child = child.spawn(executablePath, commands, {\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 (options.onClose) {\r\n options.onClose();\r\n }\r\n\r\n return;\r\n }\r\n\r\n let copyPasteCommands = this.copyableCommands(commands);\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 (options.saveLogs) {\r\n let commandIndex = commands.indexOf(\"-p\") + 1;\r\n if (commandIndex > 0) {\r\n let commandName = commands[commandIndex];\r\n saveLogs(commandName, this.logText);\r\n }\r\n }\r\n this.running = false;\r\n this.child = null;\r\n\r\n if (options.onClose) {\r\n options.onClose();\r\n }\r\n });\r\n\r\n if (options.onData) {\r\n this.child.stderr.on('data', (data) => {\r\n options.onData(data, engineMessageTypeJSON);\r\n });\r\n\r\n this.child.stdout.on('data', (data) => {\r\n options.onData(data, engineMessageTypeJSON);\r\n });\r\n }\r\n\r\n if (options.onLine || options.saveLogs) {\r\n this.child.stderr.on('data', (data) => {\r\n this.parseLines(data, options);\r\n });\r\n\r\n this.child.stdout.on('data', (data) => {\r\n this.parseLines(data, options);\r\n });\r\n }\r\n\r\n return this.child;\r\n }\r\n\r\n /** @private */\r\n parseLines(data, opts) {\r\n let callback = opts.onLine ? opts.onLine : () => {};\r\n let parseLineData = opts.parseLineData;\r\n\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 if (!parseLineData) {\r\n // Execute callback with raw line response\r\n callback(line);\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 if (opts.parseJSON) {\r\n let jsonData = JSON.parse(messageData);\r\n callback(jsonData);\r\n } else {\r\n callback(messageData);\r\n }\r\n } catch {\r\n callback(null);\r\n }\r\n } else {\r\n // NOTE: can be removed once everything uses engineMessageTypeJSON\r\n if (!messageType.startsWith(\"NODEJS\")) {\r\n this.logText.push(line);\r\n }\r\n }\r\n });\r\n }\r\n\r\n destroy() {\r\n if (this.running === false) {\r\n return;\r\n }\r\n\r\n this.running = false;\r\n\r\n // Kill original process id\r\n this.statusMessage(`force kill process`);\r\n process.kill(this.child.pid);\r\n\r\n try {\r\n let text = `wmic process get processid,parentprocessid,executablepath|find \"${this.child.pid}\"`;\r\n let stdout = child.execSync(text);\r\n let lines = stdout.toString().split(\"\\n\");\r\n\r\n let subprocessToKill = [];\r\n lines.forEach(line => {\r\n line = line.replace(/\\s\\s+/g, ' ');\r\n line = line.replace(\"\\n\", \"\");\r\n if (line.length === 0) {\r\n return;\r\n }\r\n\r\n line = line.split(\" \");\r\n\r\n let rootProcessID = this.child.pid;\r\n let parentProcessID = parseInt(line.slice(-3)[0]);\r\n let processID = parseInt(line.slice(-2)[0]);\r\n line.splice(-3);\r\n\r\n // Wrong process (wrong parent id)\r\n if (parentProcessID !== rootProcessID) {\r\n return;\r\n }\r\n\r\n // Wrong process (processID == rootProcessID)\r\n if (processID === rootProcessID) {\r\n return;\r\n }\r\n\r\n // Check launch path (engine.exe and known executables)\r\n let cmdPath = slash(line.join(\" \"));\r\n let engineSubprocess = cmdPath.indexOf(this.exeName) !== -1;\r\n let engineExecutable = cmdPath.indexOf(\"engine/executables\") !== -1;\r\n\r\n if (engineSubprocess || engineExecutable) {\r\n // Add our sub-process to the list of ones to stop\r\n subprocessToKill.push(processID);\r\n }\r\n });\r\n\r\n // Kill all of the child processes that may have spawned\r\n subprocessToKill.forEach(subprocessID => {\r\n this.statusMessage(`kill sub-process ${subprocessID}`);\r\n process.kill(subprocessID);\r\n });\r\n } catch (err) {\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(\"../\", \"SOLV3D engine.exe\");\r\n this.developerKey = \"exe-main\";\r\n this.spawnDetached = true;\r\n }\r\n}\r\n\r\nconst saveLogs = async (logPrefix, logText) => {\r\n const maxLogFiles = 50;\r\n\r\n await fs.promises.mkdir(logDirectoryPath)\r\n .catch(() => {});\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 fs.promises.writeFile(logPath, logs);\r\n\r\n const filenames = await fs.promises.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 fs.promises.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 await fs.promises.unlink(oldestFilePath)\r\n .catch(() => {});\r\n};\r\n","import linspace from \"exact-linspace\";\r\nimport * as shuffleArray from \"shuffle-array\";\r\n\r\nlet TouchEventFirstTouch = false;\r\nlet TouchEventTouching = 0;\r\nlet TouchEventPinchStart = null;\r\nlet TouchEventPinchEnd = null;\r\n\r\nexport const isMobile = () => {\r\n return (/android|webos|iphone|ipad|ipod|blackberry|playbook|BB10|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));\r\n};\r\n\r\nexport const touchToMouse = (controls, event, type: any = 'move') => {\r\n let touches = event.changedTouches;\r\n\r\n // The only event allowed during 3d mode is touchend (mouseup). Since we only allow this\r\n // event to be passed along we need to pretend that we pressed down first\r\n if (controls.orbit.status) {\r\n if (event.type !== \"touchend\") {\r\n return;\r\n }\r\n controls.mouse.upEnabled = true;\r\n }\r\n\r\n if (type === \"move\") {\r\n // touchstart will increment TouchEventTouching\r\n if (event.type === \"touchstart\") {\r\n if (TouchEventTouching === 0) {\r\n TouchEventFirstTouch = true;\r\n TouchEventTouching = TouchEventTouching + 1;\r\n } else {\r\n TouchEventFirstTouch = false;\r\n }\r\n }\r\n\r\n // touchend will decrement TouchEventTouching\r\n if (event.type === \"touchend\") {\r\n TouchEventTouching = Math.max(0, TouchEventTouching - 1);\r\n }\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 (type === \"move\") {\r\n if (event.type === \"touchmove\") {\r\n if (!TouchEventFirstTouch) {\r\n return null;\r\n }\r\n }\r\n }\r\n\r\n let first = touches[0];\r\n let eventType: any = \"\";\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 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 (TouchEventPinchStart === null) {\r\n TouchEventPinchStart = dist;\r\n } else {\r\n TouchEventPinchEnd = dist;\r\n let pinchMove = TouchEventPinchStart - TouchEventPinchEnd;\r\n let sign = pinchMove / (Math.abs(pinchMove));\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 TouchEventPinchStart = null;\r\n return event;\r\n }\r\n }\r\n }\r\n\r\n return null;\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 mergeTypedArray = (first, second) => {\r\n let firstLength = first.length;\r\n let secondLength = second.length;\r\n let arrayConstructor = first.constructor;\r\n let result = new arrayConstructor(firstLength + secondLength);\r\n result.set(first);\r\n result.set(second, firstLength);\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 let range = new Array(numPoints);\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","import proj4 from \"proj4\";\r\nimport {transform} from 'ol/proj';\r\nimport {Projection, Transform} from '../../redux/projections-slice';\r\nimport PCA from 'pca-js';\r\nimport { executeWithoutLogging } from './misc';\r\nimport {\r\n Euler,\r\n MathUtils,\r\n Matrix4,\r\n Quaternion,\r\n Sphere,\r\n Vector3\r\n} from 'three';\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\nconst lonLatProjection = {\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\nconst verifyProjection = (info) => {\r\n const data = {\r\n type: info.type,\r\n name: info.name,\r\n string: info.string,\r\n transform: info.transform\r\n } as Projection;\r\n\r\n if (data.type === \"proj4\") {\r\n data.string = verifyProj4String(data);\r\n }\r\n\r\n data.transform = verifyTransformObject(data);\r\n\r\n return data;\r\n};\r\n\r\n/* Mostly used indirectly inside other coordinate type */\r\nclass ScenePointConverter {\r\n protected _sceneShift;\r\n protected _sceneScale;\r\n protected _dataProjection: Projection;\r\n protected _viewProjection: Projection;\r\n\r\n get origin() {\r\n return this._sceneShift;\r\n }\r\n\r\n get initialized() {\r\n return this._sceneShift !== null;\r\n }\r\n\r\n /** Scale from data projection to meters (local scene coordinates) */\r\n get dataToMeters() {\r\n return infoToMeters(this._dataProjection);\r\n }\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 dataProjectionUnits() {\r\n return projectionUnits(this._dataProjection);\r\n }\r\n\r\n get viewProjectionUnits() {\r\n return projectionUnits(this._viewProjection);\r\n }\r\n\r\n get isLonLatProject() {\r\n return isLonLatProjection(this._dataProjection);\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 currentProjection(name) {\r\n return (this._dataProjection.name === name) ||\r\n (this._viewProjection.name === name);\r\n }\r\n\r\n setDataProjection(info) {\r\n this._dataProjection = verifyProjection(info);\r\n this.resetSceneShift();\r\n }\r\n\r\n setViewProjection(info) {\r\n this._viewProjection = verifyProjection(info);\r\n }\r\n\r\n resetSceneShift() {\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) {\r\n if (this._sceneShift === null) {\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\r\n offsetToScene(offset) {\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 let positionLonLat = this._dataToLonLat(value);\r\n return transform([positionLonLat.x, positionLonLat.y],\r\n 'EPSG:4326', 'EPSG:3857');\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.origin)\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 let position = new Vector3()\r\n .copy(value)\r\n .multiplyScalar(this.dataToMeters);\r\n\r\n this.checkForOffset(position);\r\n position.sub(this.origin);\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 lonlat */\r\n _sceneToLonLat(value) {\r\n let dataProjection = this._sceneToData(value);\r\n return this._dataToLonLat(dataProjection);\r\n }\r\n\r\n /** @private */\r\n _sceneToGeocentric(value) {\r\n let dataLonLat = this._sceneToLonLat(value);\r\n return new GeocentricCoordinate().fromLonLat(dataLonLat);\r\n }\r\n\r\n /** @private */\r\n _geocentricToScene(value) {\r\n let pointData = new GeocentricCoordinate(value).toProjection(this._dataProjection);\r\n return this._dataToScene(pointData);\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[2];\r\n }\r\n }\r\n\r\n super(x,y,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._dataToAerial(this);\r\n }\r\n\r\n toLonLat() {\r\n return LocalScene._sceneToLonLat(this);\r\n }\r\n\r\n toDataProjection() {\r\n return LocalScene._sceneToData(this);\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 fromScene(value) {\r\n return LocalScene._sceneToGeocentric(value);\r\n }\r\n\r\n fromLonLat(value) {\r\n if (!value.isVector3) {\r\n value = new Vector3(...value);\r\n }\r\n\r\n let lon = value.x * Math.PI / 180.0;\r\n let lat = value.y * Math.PI / 180.0;\r\n let alt = value.z; // must be in meters!\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\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 this.x = x;\r\n this.y = y;\r\n this.z = z;\r\n\r\n return this;\r\n }\r\n\r\n toGeocentric() {\r\n return this;\r\n }\r\n\r\n toDataProjection() {\r\n return this.toProjection(LocalScene.dataProjection);\r\n }\r\n\r\n toViewProjection() {\r\n return this.toProjection(LocalScene.viewProjection);\r\n }\r\n\r\n toScene() {\r\n return LocalScene._geocentricToScene(this);\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 let lonlat = this.toLonLat();\r\n let vector = _proj4Transform(lonlat, lonLatProjection, projection);\r\n\r\n if (projection.transform) {\r\n var origin = new Vector3(...projection.transform.origin);\r\n var trans = new Vector3(...projection.transform.translation);\r\n var scale = projection.transform.scale;\r\n var scaleVector = new Vector3(scale, scale, 1.0);\r\n var angle = projection.transform.rotation * Math.PI / 180.0;\r\n let axis = new Vector3(0, 0, 1);\r\n\r\n vector = vector.sub(origin)\r\n .multiply(scaleVector)\r\n .applyAxisAngle(axis, angle)\r\n .add(trans);\r\n }\r\n\r\n return new ProjectedCoordinate(vector, projection);\r\n }\r\n\r\n get closestUtmZone() {\r\n let lonlat = this.toLonLat();\r\n return Math.ceil((180 + lonlat.x) / 6);\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 return new GeocentricCoordinate()\r\n .fromLonLat(this.toLonLat());\r\n }\r\n\r\n toLonLat() {\r\n const transform = this.projection.transform;\r\n\r\n let vector;\r\n if (transform) {\r\n let origin = new Vector3(...transform.origin);\r\n let trans = new Vector3(...transform.translation);\r\n let scale = transform.scale;\r\n let scaleVector = new Vector3(scale, scale, 1.0);\r\n let angle = transform.rotation * Math.PI / 180.0;\r\n let axis = new Vector3(0, 0, 1);\r\n\r\n vector = new Vector3()\r\n .add(this)\r\n .sub(trans)\r\n .applyAxisAngle(axis, -1 * angle)\r\n .divide(scaleVector)\r\n .add(origin);\r\n } else {\r\n vector = this;\r\n }\r\n\r\n let lonlat = _proj4Transform(vector, this.projection, lonLatProjection);\r\n return lonlat;\r\n }\r\n\r\n toScene() {\r\n let value = this.projection.name !== LocalScene.dataProjection.name\r\n ? this.toProjection(LocalScene.dataProjection)\r\n : this;\r\n\r\n return LocalScene._dataToScene(value);\r\n }\r\n\r\n toProjection(projection) {\r\n let vector = _proj4Transform(this, this.projection, projection);\r\n return new ProjectedCoordinate(vector, projection);\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.distanceTo(value);\r\n }\r\n\r\n return this.distanceTo(value);\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: any;\r\n private _theta: any;\r\n private _phi: any;\r\n private limits: any;\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 = (projectionString) => {\r\n // Check for valid projection string\r\n try {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n let valid = proj4(projectionString);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport const getInvertedEuler = (euler) => {\r\n let inverseQuaternion = new Quaternion()\r\n .setFromEuler(euler)\r\n .inverse();\r\n\r\n let eulerOriginalInverse = new Euler()\r\n .setFromQuaternion(inverseQuaternion);\r\n\r\n return eulerOriginalInverse;\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 GeocentricCoordinate().fromLonLat(lonlat);\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\nexport const calculatePointsPCA = (vertices, returnFlat) => {\r\n let mean = new Vector3();\r\n vertices.forEach(vertex => {\r\n mean.add(vertex);\r\n });\r\n mean.divideScalar(vertices.length);\r\n\r\n let points = vertices.map(vertex => {\r\n return new Vector3()\r\n .add(vertex)\r\n .sub(mean)\r\n .toArray();\r\n });\r\n\r\n let eigen = executeWithoutLogging(() => {\r\n return PCA.getEigenVectors(points);\r\n });\r\n\r\n let matrix = new Matrix4();\r\n matrix.makeBasis(\r\n new Vector3().fromArray(eigen[0].vector),\r\n new Vector3().fromArray(eigen[1].vector),\r\n new Vector3().fromArray(eigen[2].vector)\r\n );\r\n matrix.transpose();\r\n\r\n points = points.map(point => {\r\n return new Vector3()\r\n .fromArray(point).applyMatrix4(matrix);\r\n });\r\n\r\n if (returnFlat) {\r\n let pointsFlat = [];\r\n points.forEach(point => {\r\n pointsFlat = [...pointsFlat, ...point.toArray()];\r\n });\r\n points = pointsFlat;\r\n }\r\n\r\n return points;\r\n};\r\n\r\nexport const projectionUnits = (projection: Projection) => {\r\n const unitLength = infoToMeters(projection);\r\n\r\n let units;\r\n switch (unitLength) {\r\n case unitsToValue['m']:\r\n units = \"m\";\r\n break;\r\n case unitsToValue['ft']:\r\n units = \"ft\";\r\n break;\r\n case unitsToValue['us-ft']:\r\n units = \"sft\";\r\n break;\r\n default:\r\n units = \"m\";\r\n break;\r\n }\r\n\r\n return units;\r\n};\r\n\r\nexport const infoToMeters = (projection: Projection) => {\r\n if (!projection) {\r\n return 1.0;\r\n }\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 }\r\n\r\n if (\"to_meter\" in proj) {\r\n return proj['to_meter'];\r\n }\r\n\r\n if (\"units\" in proj) {\r\n const units = proj['units'];\r\n return unitsToValue[units];\r\n }\r\n\r\n return 1.0;\r\n};\r\n\r\n// NOTE: Will fail if converted to an es6 function\r\nexport function sphereRaycast(raycaster, intersects) {\r\n let geometry = this.geometry;\r\n let matrixWorld = this.matrixWorld;\r\n\r\n let testSphere = new Sphere();\r\n testSphere.copy(geometry.boundingSphere);\r\n testSphere.applyMatrix4(matrixWorld);\r\n\r\n if (raycaster.ray.intersectsSphere(testSphere) === false) {\r\n return;\r\n }\r\n\r\n let origin = raycaster.ray.origin;\r\n let 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\nexport function isLonLatProjection(projection) {\r\n const proj = proj4.Proj(projection.string);\r\n return proj['projName'] === \"longlat\";\r\n}\r\n\r\nfunction haversineDistance(position1, position2) {\r\n let earthRadius = 6371000;\r\n\r\n let diffLat = (position2.y - position1.y) * Math.PI / 180;\r\n let diffLng = (position2.x - position1.x) * Math.PI / 180;\r\n\r\n let arc = Math.cos(position1.y * Math.PI / 180)\r\n * Math.cos(position2.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 = position2.z - position1.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\nfunction 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\nfunction verifyProj4String(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\n/** @private */\r\nfunction _proj4Transform(data, proj1, proj2) {\r\n if (data.isVector3) {\r\n data = data.toArray();\r\n }\r\n\r\n if (proj1 === proj2) {\r\n return new Vector3(...data);\r\n }\r\n\r\n let projToMeters1 = infoToMeters(proj1);\r\n let projToMeters2 = infoToMeters(proj2);\r\n let proj2m = projToMeters2 / projToMeters1;\r\n\r\n let transform = proj4(proj1.string, proj2.string);\r\n let reprojected = transform.forward(data);\r\n reprojected = new Vector3(...reprojected);\r\n\r\n // Height scaling is not applied by library\r\n reprojected.z /= proj2m;\r\n\r\n return reprojected;\r\n}\r\n\r\n\r\nconst LocalScene = new ScenePointConverter();\r\nexport default LocalScene;\r\n","import {addAsset, addAssets, CameraData, OrthoData} from \"./redux/assets-slice\";\r\nimport {addFolder} from './redux/folders-slice';\r\nimport {app, dialog, fsPromises, glob} from \"./electron-modules\";\r\nimport path from 'path';\r\nimport slash from 'slash';\r\nimport {hideBackdrop, showBackdrop} from \"./app\";\r\nimport {PythonExecutable} from \"./executable\";\r\nimport LocalScene from \"./viewer/js/projections\";\r\nimport { chunkedArray } from \"./viewer/js/misc\";\r\n\r\nexport const lasFileFormat = \"las\";\r\nexport const encompassFileFormat = \"idx\";\r\nexport const imageListFormats = ['csv', 'txt'];\r\nexport const planarListFormats = ['plnr'];\r\nexport const orthoFormats = ['tif', 'tiff'];\r\n\r\nconst pointCloudFileFormats = [lasFileFormat, encompassFileFormat];\r\n\r\nexport const pointCloudFilter = [{name: 'Point Clouds', extensions: pointCloudFileFormats}];\r\nexport const imageOrthoFilter = [{name: 'Orthomosaic File', extensions: orthoFormats}];\r\nexport const imageCSVFilter = [{name: 'Image CSV', extensions: imageListFormats}];\r\nexport const imagePlanarFilter = [{name: 'Planar Image File', extensions: planarListFormats}];\r\n\r\ninterface ImageDetectResults {\r\n readonly pathFound: boolean;\r\n readonly imagePath: string;\r\n readonly imageExt: string;\r\n readonly hasImageExt: boolean;\r\n}\r\n\r\nexport const isAssetFile = (filename) => {\r\n return isPanoramicFile(filename)\r\n || isPlanarFile(filename)\r\n || isPointCloudFile(filename)\r\n || isOrthomosaicFile(filename);\r\n};\r\n\r\nexport const isPanoramicFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return imageListFormats.indexOf(extension) !== -1;\r\n};\r\n\r\nexport const isPlanarFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return planarListFormats.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 isOrthomosaicFile = (filename) => {\r\n const extension = path.extname(filename).slice(1);\r\n return orthoFormats.indexOf(extension) !== -1;\r\n};\r\n\r\nexport const addAssetFolder = async (showMessage, dispatch, paths, folderID = null) => {\r\n const cloudPaths = paths.filter(file => isPointCloudFile(file));\r\n const panoramicPaths = paths.filter(file => isPanoramicFile(file));\r\n const orthoPaths = paths.filter(file => isOrthomosaicFile(file));\r\n const planarPaths = paths.filter(file => isPlanarFile(file));\r\n\r\n const numClouds = cloudPaths.length;\r\n const numImageFiles = panoramicPaths.length\r\n + orthoPaths.length\r\n + planarPaths.length;\r\n\r\n // Nothing to add, exit early\r\n if (numClouds === 0 && numImageFiles === 0) {\r\n return;\r\n }\r\n\r\n if (!folderID) {\r\n // No folder has been provided, so a new folder is created instead\r\n const action = dispatch(addFolder(\"New Folder\"));\r\n folderID = action.payload.id;\r\n }\r\n\r\n // Add all panoramic data\r\n const planarFilesAdded = await addPlanarFiles(showMessage,\r\n dispatch, planarPaths, folderID);\r\n\r\n // Add all planar data\r\n const panoramicFilesAdded = await addCameraFiles(showMessage,\r\n dispatch, panoramicPaths, folderID);\r\n\r\n // Add all pointclouds\r\n const pointsAdded = addPointCloudFiles(dispatch, cloudPaths, folderID);\r\n\r\n // Add orthomosaic data\r\n const orthosAdded = await addOrthoFiles(showMessage, dispatch,\r\n orthoPaths, folderID);\r\n\r\n const totalAdded = pointsAdded\r\n + panoramicFilesAdded\r\n + planarFilesAdded\r\n + orthosAdded;\r\n\r\n if (totalAdded === 0) {\r\n return;\r\n }\r\n\r\n let addedPlural = totalAdded === 1 ? \"\" : \"s\";\r\n showMessage(`Added [${totalAdded}] file${addedPlural} to project`, {\r\n variant: \"success\"\r\n });\r\n};\r\n\r\nexport const addPointCloudFiles = (dispatch, assetPaths, folderID) => {\r\n let assetList = assetPaths.map(pointPath => {\r\n return {folderID, assetPath: pointPath};\r\n });\r\n\r\n dispatch(addAssets(assetList));\r\n return assetPaths.length;\r\n};\r\n\r\nexport const addOrthoFiles = async (showMessage, dispatch, assetPaths, folderID) => {\r\n showBackdrop();\r\n\r\n let numAdded = await addOrthoBatch(showMessage, dispatch, assetPaths, folderID);\r\n\r\n hideBackdrop();\r\n\r\n return numAdded;\r\n};\r\n\r\nexport const addCameraFiles = async (showMessage, dispatch, assetPaths, folderID) => {\r\n showBackdrop();\r\n\r\n let numAdded = 0;\r\n\r\n for (const assetPath of assetPaths) {\r\n const response = await addCameraFile(dispatch, assetPath, folderID);\r\n\r\n if (response.success) {\r\n numAdded += 1;\r\n } else {\r\n const fileName = path.basename(assetPath);\r\n\r\n let parseMessage = `\r\n Unable to parse ${fileName}. Please ensure that the CSV matches\r\n one of the supported formats listed in the user guide, or that it\r\n contains the following columns: Filename, X, Y, Z, Roll, Pitch, Yaw.\r\n `;\r\n\r\n let pathMessage = `Error loading camera file: ${fileName}.`;\r\n\r\n let message = response.pathError ? pathMessage : parseMessage;\r\n\r\n showMessage(message, {\r\n variant: \"error\",\r\n autoHideDuration: 10000,\r\n });\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n return numAdded;\r\n};\r\n\r\nexport const addPlanarFiles = async (showMessage, dispatch, assetPaths, folderID) => {\r\n showBackdrop();\r\n\r\n let numAdded = 0;\r\n for (const assetPath of assetPaths) {\r\n const added = await addPlanarFile(dispatch, assetPath, folderID);\r\n if (added) {\r\n numAdded += 1;\r\n } else {\r\n const fileName = path.basename(assetPath);\r\n\r\n showMessage(`Error loading planar camera file: ${fileName}`, {\r\n variant: \"error\"\r\n });\r\n }\r\n }\r\n\r\n hideBackdrop();\r\n\r\n return numAdded;\r\n};\r\n\r\nexport const addOrthoBatch = async (showMessage, dispatch, assetPaths, folderID): 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 ];\r\n\r\n let numAdded = 0;\r\n\r\n exe.run({\r\n command: 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 = [];\r\n response.forEach(geotiff => {\r\n const assetPath = slash(geotiff.file_path);\r\n\r\n if (geotiff.error) {\r\n showMessage(`${geotiff.error}: ${path.basename(assetPath)}`, {\r\n variant: \"error\"\r\n });\r\n return;\r\n }\r\n\r\n const {corners, base64, width, height,\r\n scale_x, scale_y, width_original, height_original} = geotiff;\r\n\r\n const data = {\r\n imageBounds: corners,\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({folderID, assetPath, data});\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, assetPath, folderID): Promise => {\r\n return new Promise(async resolve => {\r\n const text = await fsPromises.readFile(assetPath, {encoding: 'utf8'});\r\n\r\n let config;\r\n let cameras;\r\n\r\n try {\r\n let decoded = JSON.parse(text);\r\n config = decoded.config;\r\n cameras = decoded.data;\r\n } catch {\r\n resolve(false);\r\n return;\r\n }\r\n\r\n const numCameras = cameras.length;\r\n if (numCameras === 0) {\r\n resolve(false);\r\n return;\r\n }\r\n\r\n let cameraNames = cameras.map(x => x[0]);\r\n let {pathFound, imagePath, imageExt, hasImageExt}\r\n = await detectImagePath(assetPath, cameraNames);\r\n\r\n if (!pathFound) {\r\n resolve(false);\r\n return;\r\n }\r\n\r\n let cameraData: CameraData[] = [];\r\n\r\n for (let i=0;i => {\r\n const response = {\r\n success: false,\r\n pathError: false\r\n };\r\n\r\n return new Promise(resolve => {\r\n const userPath = app.getPath('userData');\r\n const exe = new PythonExecutable();\r\n\r\n let cameraData;\r\n const inputPath = assetPath;\r\n const outputPath = path.join(userPath, \"inputCsvTemp.csv\");\r\n const projection = LocalScene.engineStyleProjection(LocalScene.dataProjection);\r\n\r\n let commands = [\r\n \"-p\", \"convert_encompass_csv\",\r\n \"--input_file\", inputPath,\r\n \"--output_file\", outputPath,\r\n \"--projection\", projection\r\n ];\r\n\r\n exe.run({\r\n command: commands,\r\n onLine: jsonData => {\r\n cameraData = jsonData;\r\n },\r\n onClose: async () => {\r\n if (!cameraData) {\r\n resolve(response);\r\n return;\r\n }\r\n\r\n const numCameras = cameraData.length;\r\n if (numCameras === 0) {\r\n resolve(response);\r\n return;\r\n }\r\n\r\n let cameraNames = cameraData.map(x => x.name);\r\n let {pathFound, imagePath, imageExt, hasImageExt}\r\n = await detectImagePath(assetPath, cameraNames);\r\n\r\n if (!pathFound) {\r\n resolve({...response, pathError: true});\r\n return;\r\n }\r\n\r\n // Update final camera data path / filenames\r\n for (let i=0;i => {\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('Error', 'An error occurred while loading the specified file.');\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('Error', 'An error occurred while loading the specified file.');\r\n return null;\r\n });\r\n};\r\n\r\nexport const openDialogFolder = () => {\r\n return dialog.showOpenDialog({\r\n properties: ['openDirectory']\r\n }).then(result => {\r\n if (result.canceled) {\r\n return {\r\n directoryPath: '',\r\n assetPaths: Promise.resolve([])\r\n };\r\n }\r\n\r\n const filePath = slash(result.filePaths[0]);\r\n\r\n return {\r\n directoryPath: filePath,\r\n assetPaths: parseDirectory(filePath)\r\n };\r\n }).catch(() => {\r\n dialog.showErrorBox('Error', 'An error occurred while loading the specified file.');\r\n return null;\r\n });\r\n};\r\n\r\nexport const exportDialogCSV = (filename): Promise => {\r\n return dialog.showSaveDialog( {\r\n defaultPath: `${filename}.csv`,\r\n filters: imageCSVFilter\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n\r\n const savePath = slash(result.filePath);\r\n return savePath;\r\n }).catch(() => {\r\n dialog.showErrorBox('Error', 'An error occurred while exporting the specified file.');\r\n return null;\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 fsPromises.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\r\nconst checkImagePath = (directory, filenames, suffix, depth = 3) => {\r\n const results = {\r\n success: false,\r\n duplicate: false,\r\n imagePath: null,\r\n imageExt: null\r\n };\r\n\r\n const singleFolder = depth === 1;\r\n\r\n let dirSeperator = \"\";\r\n for (var i = 0; i < depth; i++) {\r\n if (i > 0) {\r\n dirSeperator += \"/*\";\r\n }\r\n\r\n let paths;\r\n\r\n if (singleFolder) {\r\n for (let subset of chunkedArray(filenames, 500)) {\r\n const filenameQuery = `{${subset.join(\",\")}}`;\r\n const globPath = `${dirSeperator}/${filenameQuery}${suffix}`;\r\n paths = glob.sync(globPath, {\r\n cwd: directory,\r\n root: directory\r\n });\r\n\r\n if (paths.length > 0) {\r\n break;\r\n }\r\n }\r\n } else {\r\n const globPath = `${dirSeperator}/${filenames[0]}${suffix}`;\r\n paths = glob.sync(globPath, {\r\n cwd: directory,\r\n root: directory\r\n });\r\n }\r\n\r\n let singleImageValid = paths.length === 1;\r\n let multiImageValid = singleFolder && (paths.length > 0);\r\n\r\n if (singleImageValid || multiImageValid) {\r\n results.success = true;\r\n results.imagePath = path.dirname(paths[0]);\r\n results.imageExt = path.extname(paths[0]);\r\n return results;\r\n } else if (paths.length >= 2) {\r\n results.duplicate = true;\r\n }\r\n\r\n }\r\n\r\n return results;\r\n};\r\n\r\nexport const buildFilePath = (imagePath, filename, imageExt, hasImageExt) => {\r\n let filePath = hasImageExt ?\r\n path.join(imagePath, filename) :\r\n path.join(imagePath, `${filename}${imageExt}`);\r\n\r\n // Fix for windows UNC paths\r\n const isNetworkPath = imagePath.indexOf(\"//\") === 0;\r\n if (isNetworkPath) {\r\n filePath = `/${filePath}`;\r\n }\r\n\r\n return filePath;\r\n};\r\n\r\nexport const detectImagePath = async (assetPath: string, imageNames: string[]): Promise => {\r\n const directory = path.dirname(assetPath);\r\n const testImageExt = path.extname(imageNames[0]).toLowerCase();\r\n const hasImageExt = [\".jpg\", \".png\", \".jpeg\"].includes(testImageExt);\r\n const suffix = hasImageExt ? \"\" : \".{png,jpg,jpeg}\";\r\n\r\n let response = {\r\n pathFound: false,\r\n imagePath: null,\r\n imageExt: null,\r\n hasImageExt\r\n };\r\n\r\n // Search for image directory using csv path\r\n let {success, duplicate, imagePath, imageExt}\r\n = checkImagePath(directory, imageNames, suffix);\r\n\r\n // Update response values\r\n response.pathFound = success;\r\n response.imagePath = imagePath;\r\n response.imageExt = imageExt;\r\n\r\n console.log(\"Detected image path: \", imagePath);\r\n\r\n if (!response.pathFound) {\r\n if (duplicate) {\r\n dialog.showErrorBox(assetPath, \"Multiple image paths found. Image directory must be selected manually\");\r\n } else {\r\n dialog.showErrorBox(assetPath, \"Image path not found. Image directory must be selected manually\");\r\n }\r\n\r\n const results = dialog.showOpenDialogSync({\r\n title: \"Select Image Path\",\r\n properties: ['openDirectory']\r\n });\r\n\r\n if (results) {\r\n // Search for image directory using selected folder\r\n imagePath = slash(results[0]);\r\n let manual = checkImagePath(imagePath, imageNames, suffix, 1);\r\n\r\n // Update response values\r\n response.pathFound = manual.success;\r\n response.imagePath = imagePath;\r\n response.imageExt = manual.imageExt;\r\n\r\n if (!manual.success) {\r\n dialog.showErrorBox(imagePath, \"Images not found in manual folder\");\r\n }\r\n }\r\n }\r\n\r\n return response;\r\n};\r\n","import {createStyles, ListItemIcon, makeStyles, Theme} from \"@material-ui/core\";\r\nimport React from \"react\";\r\nimport clsx from 'clsx';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n icon: {\r\n minWidth: theme.spacing(0),\r\n paddingRight: \"10px\"\r\n },\r\n centered: {\r\n alignItems: \"center\"\r\n }\r\n })\r\n);\r\n\r\nexport const DenseIcon = (props) => {\r\n const classes = useStyles();\r\n const {children, centered, ...other} = props;\r\n\r\n return (\r\n \r\n {children}\r\n \r\n );\r\n};","import {createStyles, makeStyles, Theme, Tooltip} from \"@material-ui/core\";\r\nimport React from \"react\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n hidden: {\r\n opacity: 0\r\n }\r\n }),\r\n);\r\n\r\nexport const ArrowTooltip = (props) => {\r\n return (\r\n \r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nexport const CursorTooltip = (props) => {\r\n const classes = useStyles();\r\n\r\n const {text} = props;\r\n const [position, setPosition] = React.useState({\r\n x: undefined,\r\n y: undefined\r\n });\r\n\r\n const createMarkup = () => {\r\n return text ?\r\n (
) :\r\n \"\";\r\n };\r\n\r\n const hidden = text === \"\";\r\n\r\n return (\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};\r\n\r\nexport const PanelProps = (value, index) => {\r\n return {\r\n value: value,\r\n index: index\r\n };\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 {\r\n calculatePointsPCA,\r\n GeocentricCoordinate,\r\n geometryToArray,\r\n} from '../projections';\r\nimport MeasurementController from './measurement-controller';\r\nimport {getArea, getLength} from 'ol/sphere';\r\nimport {LineString, Polygon} from 'ol/geom';\r\nimport Delaunator from 'delaunator';\r\nimport earcut from 'earcut';\r\nimport {isMobile, randomHexColor} from '../misc';\r\nimport {nanoid} from '@reduxjs/toolkit';\r\nimport { pointInPolygon } from '../utilities/polygon';\r\nimport {\r\n Vector3,\r\n BufferGeometry,\r\n BufferAttribute,\r\n PointsMaterial,\r\n Points,\r\n Geometry,\r\n MeshBasicMaterial,\r\n Face3,\r\n Mesh,\r\n EdgesGeometry,\r\n LineBasicMaterial,\r\n LineSegments,\r\n Triangle,\r\n DoubleSide,\r\n MathUtils\r\n} from 'three';\r\n\r\nexport class Measurement {\r\n public controller: MeasurementController;\r\n public id = nanoid();\r\n public dbType = null;\r\n public databaseID = null;\r\n public displayType = 'Measurement';\r\n public title = 'Measurement';\r\n public timeCreated = new Date();\r\n public startClick = isMobile() ? \"Tap\" : \"Click\";\r\n public cancelClick = isMobile() ? \"Long-press\" : \"Right-click\";\r\n public finishClick = isMobile() ? \"Double-tap\" : \"Double-click\";\r\n public tooltipStatic = {\r\n start: null,\r\n end: null,\r\n more: null\r\n };\r\n\r\n setController(controller) {\r\n this.controller = controller;\r\n }\r\n\r\n get timestamp() {\r\n return Math.floor(this.timeCreated.getTime() / 1000);\r\n }\r\n\r\n set timestamp(isoTime) {\r\n this.timeCreated = new Date(isoTime);\r\n }\r\n\r\n get startTooltip() {\r\n return this.tooltipStatic.start;\r\n }\r\n\r\n get moreTooltip() {\r\n return this.tooltipStatic.more;\r\n }\r\n\r\n get endTooltip() {\r\n return this.tooltipStatic.end;\r\n }\r\n\r\n get viewer() {\r\n return this.controller.viewer;\r\n }\r\n\r\n get valid() {\r\n return true;\r\n }\r\n\r\n get formatter() {\r\n return this.controller.formatter;\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\r\n constructor() {\r\n super();\r\n\r\n this.displayType = '3D Measurement';\r\n this.title = '3D Measurement';\r\n this.dbType = \"length\";\r\n\r\n this.tooltipStatic.start =`${this.startClick} to start line`;\r\n }\r\n\r\n get numVertices() {\r\n return this.coordinates.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, parent=null) {\r\n let finished = false;\r\n let addedPoint = false;\r\n vertex = new GeocentricCoordinate().fromScene(vertex);\r\n\r\n if (this.vertices.length === 0) {\r\n this.vertices.push(vertex);\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(vertex) > 0.10) {\r\n // New point is far enough away from previous point\r\n this.vertices.push(vertex);\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 MeasurementLine extends Measurement3D {\r\n constructor() {\r\n super();\r\n\r\n this.maxVertexLength = 16;\r\n }\r\n\r\n get moreTooltip() {\r\n return `\r\n ${this.startClick} to add more points (${this.vertices.length})\r\n
${this.finishClick} to finish\r\n
${this.cancelClick} to cancel\r\n `;\r\n }\r\n\r\n get endTooltip() {\r\n return this.moreTooltip;\r\n }\r\n}\r\n\r\nexport class MeasurementPoint extends Measurement3D {\r\n constructor() {\r\n super();\r\n\r\n this.displayType = '3D Point';\r\n this.title = '3D Point';\r\n this.dbType = 'point';\r\n this.maxVertexLength = 1;\r\n this.minVertexRequired = 1;\r\n\r\n this.tooltipStatic.start = 'Click for single point';\r\n }\r\n}\r\n\r\nexport class MeasurementArea extends Measurement3D {\r\n public surfaceGenerator;\r\n public areaInvalidMessage;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.displayType = '3D Area';\r\n this.title = '3D Area';\r\n this.dbType = 'area';\r\n this.maxVertexLength = 16;\r\n this.minVertexRequired = 3;\r\n this.areaInvalidMessage = \"Invalid Area\";\r\n\r\n this.tooltipStatic.start = `${this.startClick} to start area`;\r\n }\r\n\r\n get moreTooltip() {\r\n return `\r\n ${this.startClick} to add more points (${this.vertices.length})\r\n
${this.cancelClick} to cancel\r\n `;\r\n }\r\n\r\n get endTooltip() {\r\n return `\r\n ${this.startClick} to add more points (${this.vertices.length})\r\n
${this.finishClick} to finish\r\n
${this.cancelClick} to cancel\r\n `;\r\n }\r\n\r\n get localVertices3D() {\r\n return this.vertices.map(vertex => {\r\n let vertexLocal = vertex.toScene();\r\n return vertexLocal;\r\n });\r\n }\r\n\r\n get indices() {\r\n return this.surfaceGenerator.indices;\r\n }\r\n\r\n get area3D() {\r\n return this.surfaceGenerator.area;\r\n }\r\n\r\n get valid() {\r\n return this.surfaceGenerator.valid;\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() {\r\n this.surfaceGenerator.clear();\r\n this.surfaceGenerator.generate();\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;\r\n public invalidVolumeMessage;\r\n\r\n constructor() {\r\n super();\r\n\r\n this.displayType = '3D Volume';\r\n this.title = '3D Volume';\r\n this.dbType = 'volume';\r\n this.invalidVolumeMessage = \"Invalid Volume\";\r\n\r\n this.tooltipStatic.start = `${this.startClick} to start volume`;\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 volumeValue() {\r\n return this.volumeHelper.value;\r\n }\r\n\r\n calculate() {\r\n this.volumeHelper.calculate();\r\n }\r\n\r\n recalculate() {\r\n this.volumeHelper.clear();\r\n this.volumeHelper.calculate();\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\r\n let pointCloud = controller.pointclouds;\r\n this.volumeHelper = new VolumeHelper(this);\r\n this.volumeHelper.init(pointCloud);\r\n this.surfaceGenerator = new SurfaceGenerator(this);\r\n }\r\n\r\n loadExistingVolume(value) {\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 SnapMeasurement extends Measurement3D {\r\n constructor() {\r\n super();\r\n }\r\n\r\n add(vertex, parent) {\r\n let valid = false;\r\n let added = false;\r\n let pointCloud = parent.pointCloud;\r\n let snapResult = this.snap(vertex, pointCloud);\r\n this.vertices.push(new GeocentricCoordinate().fromScene(vertex));\r\n\r\n if (snapResult) {\r\n valid = true;\r\n added = true;\r\n this.vertices.push(new GeocentricCoordinate().fromScene(snapResult));\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, pointCloud) {\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 = pointCloud.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 this.tooltipStatic.start = `${this.startClick} to snap up`;\r\n }\r\n}\r\n\r\nexport class SnapDownMeasurement extends SnapMeasurement {\r\n constructor() {\r\n super();\r\n\r\n this.tooltipStatic.start = `${this.startClick} to snap down`;\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.geometry = geometry;\r\n this.title = null;\r\n this.displayType = '2D Measurement';\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 getValue() {}\r\n\r\n loadFromCoordinates(coordinates) {}\r\n}\r\n\r\nexport class AerialLengthMeasurement extends AerialMeasurement {\r\n constructor(geometry = null) {\r\n super(geometry);\r\n this.title = '2D Length';\r\n this.displayType = 'Length';\r\n this.dbType = \"length\";\r\n }\r\n\r\n getValue() {\r\n return getLength(this.geometry);\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 constructor(geometry = null) {\r\n super(geometry);\r\n this.title = '2D Area';\r\n this.displayType = 'Area';\r\n this.dbType = \"area\";\r\n }\r\n\r\n getValue() {\r\n return getArea(this.geometry);\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 calculatingVolume = false;\r\n private calculated = false;\r\n private measurement: MeasurementVolume;\r\n private spacing = 0.5;\r\n private sigma = 1.0;\r\n private minNeighbours = 20;\r\n private maxNeighbours = 100;\r\n private neighbourPercent = 0.05;\r\n private maxHeightDelta = 999.0;\r\n private worker;\r\n private vertices;\r\n private bounds;\r\n private groundHeight;\r\n private pointCloud;\r\n private pointcloudmesh;\r\n private pointswireframe;\r\n private value;\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 //return measurement.viewer.pointclouds.scene;\r\n }\r\n\r\n calculate(updateValue = true) {\r\n if (this.calculatingVolume) {\r\n return;\r\n }\r\n\r\n this.vertices = this.measurement.localVertices3D;\r\n this.bounds = this.getCalculatedBounds();\r\n\r\n // Calculate average ground height\r\n const heights = this.vertices.map(vertex => vertex.z);\r\n const sum = heights.reduce((a, b) => a + b, 0);\r\n this.groundHeight = (sum / heights.length) || 0;\r\n\r\n this.calculateVolume(updateValue);\r\n }\r\n\r\n init(pointCloud) {\r\n this.pointCloud = pointCloud;\r\n this.clear();\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 filterByHeight(points) {\r\n return points.filter(point => {\r\n let height = Math.abs(point.z - this.groundHeight);\r\n return height < this.maxHeightDelta;\r\n });\r\n }\r\n\r\n removeOutliersAsync(points, callback) {\r\n const workerURL = \"workers/sparse-outliers.js\";\r\n let worker = new Worker(`${process.env.PUBLIC_URL}/${workerURL}`);\r\n\r\n worker.onmessage = event => {\r\n callback(event.data);\r\n };\r\n\r\n // Remove any sparse outliers\r\n worker.postMessage({\r\n points: points,\r\n sigma: this.sigma,\r\n minNeighbours: this.minNeighbours,\r\n maxNeighbours: this.maxNeighbours,\r\n neighbourPercent: this.neighbourPercent\r\n });\r\n\r\n this.worker = worker;\r\n }\r\n\r\n destroyWorker() {\r\n if (this.worker) {\r\n this.worker.terminate();\r\n this.worker = undefined;\r\n }\r\n }\r\n\r\n drawDebugPoints(points) {\r\n let positions = new Float32Array(points.length * 3);\r\n for (var i = 0; i < points.length; i++) {\r\n positions[3 * i + 0] = points[i].x;\r\n positions[3 * i + 1] = points[i].y;\r\n positions[3 * i + 2] = points[i].z;\r\n }\r\n let geometry = new BufferGeometry();\r\n geometry.setAttribute('position', new BufferAttribute(positions, 3));\r\n let material = new PointsMaterial({\r\n color: 0x00ff00,\r\n size: 0.1\r\n });\r\n this.pointcloudmesh = new Points( geometry, material );\r\n this.scene.add(this.pointcloudmesh);\r\n }\r\n\r\n drawMesh(points, triangles) {\r\n // mesh\r\n let vertices = points;\r\n let geometry = new Geometry();\r\n let material = new MeshBasicMaterial({\r\n color: 0xffffff,\r\n side: DoubleSide\r\n });\r\n geometry.vertices = vertices;\r\n triangles.forEach(tri => {\r\n geometry.faces.push(new Face3(\r\n tri[0], tri[1], tri[2]\r\n ));\r\n });\r\n let mesh = new Mesh( geometry, material );\r\n\r\n // wireframe\r\n let geo = new EdgesGeometry(mesh.geometry);\r\n let mat = new LineBasicMaterial({\r\n color: 0xf2f2f2,\r\n });\r\n let wireframe = new LineSegments(geo, mat);\r\n mesh.add(wireframe);\r\n\r\n this.pointswireframe = mesh;\r\n this.scene.add(this.pointswireframe);\r\n }\r\n\r\n setVolume(value) {\r\n this.calculated = true;\r\n this.value = value;\r\n //this.calculate(false);\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 getDenaunayTriangles(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 calculateVolume(updateValue) {\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.spacing);\r\n\r\n // Query points for this bounding box\r\n let points = this.pointCloud.pointsInRadius(this.bounds.center,\r\n this.bounds.size / 2.0);\r\n\r\n // Quick filter by heights\r\n points = this.filterByHeight(points);\r\n\r\n // Get the points inside a polygon only\r\n points = this.pointCloud.pointsInPolygon(points, this.vertices);\r\n\r\n // Calculate DTM for points, in a 2d grid\r\n points = this.pointCloud.getSampledPoints(points, true, point => {\r\n let gridX = Math.floor(point.x / this.spacing);\r\n let gridY = Math.floor(point.y / this.spacing);\r\n let key = `${gridX}-${gridY}`;\r\n return key;\r\n });\r\n\r\n // Remove sparse outliers and continue\r\n this.removeOutliersAsync(points, points => {\r\n this.asyncFinished(points, denseBounds, updateValue);\r\n });\r\n }\r\n\r\n asyncFinished(points, denseBounds = [], updateValue = true) {\r\n this.destroyWorker();\r\n\r\n if (points.length !== 0) {\r\n this.webWorkerFinished(points, denseBounds, updateValue);\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, updateValue) {\r\n let points = [];\r\n pointsArray.forEach(point => {\r\n points.push(new Vector3().copy(point));\r\n });\r\n\r\n // Combine highest points + dense boundary\r\n points = denseBounds.concat(points);\r\n\r\n // Calculate upper mesh with reverse winding order\r\n let trianglesUpper = this.getDenaunayTriangles(points, true);\r\n\r\n // Calculate lower mesh\r\n let trianglesLower = this.getDenaunayTriangles(denseBounds, false);\r\n\r\n // Combine upper and lower triangles\r\n let trianglesCombined = [];\r\n trianglesCombined = trianglesCombined.concat(trianglesLower);\r\n trianglesCombined = trianglesCombined.concat(trianglesUpper);\r\n\r\n // this.drawDebugPoints(points);\r\n this.drawMesh(points, trianglesUpper);\r\n\r\n this.calculated = true;\r\n\r\n if (updateValue) {\r\n let volume = this.getVolume(points, trianglesCombined);\r\n this.value = volume;\r\n }\r\n\r\n // Update shaders (hide area highlight)\r\n this.measurement.controller.updateAreaShaders();\r\n }\r\n\r\n /** @private */\r\n stopCalculation() {\r\n if (this.calculatingVolume) {\r\n this.asyncFinished([]);\r\n }\r\n }\r\n\r\n clear() {\r\n this.scene.remove(this.pointswireframe);\r\n this.scene.remove(this.pointcloudmesh);\r\n this.pointswireframe = null;\r\n this.pointcloudmesh = null;\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 private indices = [];\r\n private meshes = [];\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 area() {\r\n let area = 0;\r\n let vertices = this.measurement.localVertices3D;\r\n\r\n this.indices.forEach(indices => {\r\n let triangle = new Triangle(\r\n vertices[indices[0]],\r\n vertices[indices[1]],\r\n vertices[indices[2]]\r\n );\r\n area += triangle.getArea();\r\n });\r\n\r\n return area;\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 var geom = new Geometry();\r\n var normal = new Vector3();\r\n triangle.getNormal(normal);\r\n geom.vertices.push(triangle.a);\r\n geom.vertices.push(triangle.b);\r\n geom.vertices.push(triangle.c);\r\n geom.faces.push(new Face3(0, 1, 2, normal));\r\n var mesh = new Mesh(\r\n geom, new MeshBasicMaterial({\r\n color: hexColor,\r\n side: DoubleSide\r\n })\r\n );\r\n\r\n return mesh;\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() {\r\n let vertices = this.measurement.localVertices3D;\r\n let numVertices = 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(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(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 vertices[indices[0]],\r\n vertices[indices[1]],\r\n 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 }\r\n}\r\n\r\nconst getDensePolygon = (vertices, spacing) => {\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","/**\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 MOUSE,\r\n Quaternion,\r\n Spherical,\r\n Vector2,\r\n Vector3\r\n} from \"three\";\r\n\r\nconst screenSpacePanning = 0;\r\nconst horizontalPanning = 1;\r\n\r\nconst CustomOrbitControls = function(object, domElement ) {\r\n this.object = object;\r\n\r\n // Persistent toast that we update while loading\r\n //this.toast = new PersistentToast();\r\n\r\n this.domElement = ( domElement !== undefined ) ? domElement : document;\r\n\r\n // Fly mode variables\r\n this.flyMode = false;\r\n this.flyForcedRadius = 0.005;\r\n this.flyPreviousRadius = null;\r\n this.flyPreviousDampening = false;\r\n this.flyPreviousRotateSpeed = 0.0;\r\n this.flySpeed = 50.0;\r\n this.flyRatio = 1.10;\r\n this.minFlySpeed = 0.10;\r\n this.maxFlySpeed = 1000;\r\n this.saveSpeedTimeout = null;\r\n this.tick = 0;\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 this.flyModeOffset = 0.05;\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 };\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\r\n this.isMoving = function() {\r\n if (this.flyMode) {\r\n return true;\r\n } else if (panOffset.length() > 0) {\r\n return true;\r\n } else if ((sphericalDelta.theta !== 0) || (sphericalDelta.phi !== 0)) {\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n this.setFlySpeed = function (value) {\r\n this.flySpeed = Math.min(this.maxFlySpeed, Math.max(this.minFlySpeed, value));\r\n };\r\n\r\n this.increaseFlySpeed = function () {\r\n this.setFlySpeed(scope.flySpeed * this.flyRatio);\r\n /*let speedFormatted = scope.flySpeed.toFixed(2);\r\n scope.toast.show(\"Fly Mode Speed Increased:\", speedFormatted);*/\r\n };\r\n\r\n this.decreaseFlySpeed = function () {\r\n this.setFlySpeed(scope.flySpeed / this.flyRatio);\r\n /*let speedFormatted = scope.flySpeed.toFixed(2);\r\n scope.toast.show(\"Fly Mode Speed Decreased\", speedFormatted);*/\r\n };\r\n\r\n this.toggleFlyMode = function (state, showToast) {\r\n this.flyMode = state;\r\n\r\n var position = this.object.position;\r\n var offset = new Vector3().copy(position).sub(scope.target);\r\n\r\n if (state === false) {\r\n offset.setLength(this.flyPreviousRadius);\r\n this.clearSphericalDelta();\r\n this.clearPanOffset();\r\n } else {\r\n this.flyPreviousRadius = offset.length();\r\n offset.setLength(this.flyModeOffset);\r\n }\r\n\r\n if (showToast) {\r\n //this.toast.show(\"Fly Mode\", state ? \"Enabled\" : \"Disabled\");\r\n }\r\n\r\n offset.multiplyScalar(-1);\r\n this.target.copy(position).add(offset);\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.reset = function () {\r\n scope.target.copy( scope.target0 );\r\n scope.object.position.copy( scope.position0 );\r\n scope.object.zoom = scope.zoom0;\r\n\r\n scope.object.updateProjectionMatrix();\r\n scope.dispatchEvent( changeEvent );\r\n\r\n scope.update();\r\n\r\n state = STATE.NONE;\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().inverse();\r\n\r\n var lastPosition = new Vector3();\r\n var lastQuaternion = new Quaternion();\r\n\r\n return function update() {\r\n var position = scope.object.position;\r\n\r\n offset.copy( position ).sub( scope.target );\r\n\r\n if (scope.flyMode) {\r\n let millisecondsElapsed = this.tick;\r\n let distancePerFrame = scope.flySpeed * millisecondsElapsed / 1000;\r\n let direction = new Vector3().copy(offset)\r\n .multiplyScalar(-1.0).setLength(distancePerFrame);\r\n scope.target.add(direction);\r\n position.add(direction);\r\n }\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 spherical.theta += sphericalDelta.theta;\r\n spherical.phi += sphericalDelta.phi;\r\n\r\n // restrict theta to be between desired limits\r\n spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );\r\n\r\n // restrict phi to be between desired limits\r\n spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\r\n\r\n spherical.makeSafe();\r\n\r\n if (scope.flyMode) {\r\n spherical.radius = scope.flyForcedRadius;\r\n } else {\r\n spherical.radius *= scale;\r\n spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));\r\n }\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 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\r\n return true;\r\n }\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 };\r\n\r\n //\r\n // internals\r\n //\r\n\r\n var scope = this;\r\n\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 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 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 var element = scope.domElement === document ? scope.domElement.body : scope.domElement;\r\n\r\n if ( scope.object.isPerspectiveCamera ) {\r\n // perspective\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 } else if ( scope.object.isOrthographicCamera ) {\r\n // orthographic\r\n panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );\r\n panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );\r\n } else {\r\n // camera neither orthographic nor perspective\r\n console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\r\n scope.enablePan = false;\r\n }\r\n };\r\n }());\r\n\r\n function dollyIn( dollyScale ) {\r\n if ( scope.object.isPerspectiveCamera ) {\r\n scale /= dollyScale;\r\n } else if ( scope.object.isOrthographicCamera ) {\r\n scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\r\n scope.object.updateProjectionMatrix();\r\n zoomChanged = true;\r\n } else {\r\n console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\r\n scope.enableZoom = false;\r\n }\r\n }\r\n\r\n function dollyOut( dollyScale ) {\r\n if ( scope.object.isPerspectiveCamera ) {\r\n scale *= dollyScale;\r\n } else if ( scope.object.isOrthographicCamera ) {\r\n scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );\r\n scope.object.updateProjectionMatrix();\r\n zoomChanged = true;\r\n } else {\r\n console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\r\n scope.enableZoom = false;\r\n }\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 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\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 function handleMouseWheel( event ) {\r\n // console.log( 'handleMouseWheel' );\r\n\r\n if (scope.flyMode) {\r\n if ( event.deltaY < 0 ) {\r\n scope.increaseFlySpeed(scope.flySpeed);\r\n } else if ( event.deltaY > 0 ) {\r\n scope.decreaseFlySpeed(scope.flySpeed);\r\n }\r\n } else {\r\n if ( event.deltaY < 0 ) {\r\n dollyOut( getZoomScale() );\r\n } else if ( event.deltaY > 0 ) {\r\n dollyIn( getZoomScale() );\r\n }\r\n scope.update();\r\n }\r\n }\r\n\r\n function handleKeyDown( event ) {\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 event.preventDefault();\r\n scope.toggleFlyMode(!scope.flyMode, true);\r\n break;\r\n\r\n case scope.keys.PLUS:\r\n scope.increaseFlySpeed();\r\n break;\r\n\r\n case scope.keys.NUMPAD_PLUS:\r\n scope.increaseFlySpeed();\r\n break;\r\n\r\n case scope.keys.MINUS:\r\n scope.decreaseFlySpeed();\r\n break;\r\n\r\n case scope.keys.NUMPAD_MINUS:\r\n scope.decreaseFlySpeed();\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 switch ( event.button ) {\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\r\n if ( scope.enableRotate === false ) return;\r\n\r\n handleMouseMoveRotate( event );\r\n\r\n break;\r\n\r\n case STATE.DOLLY:\r\n if (scope.flyMode) return;\r\n if (scope.enableZoom === false) return;\r\n\r\n handleMouseMoveDolly( event );\r\n\r\n break;\r\n\r\n case STATE.PAN:\r\n if (scope.flyMode) return;\r\n if (scope.enablePan === false) return;\r\n\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 document.removeEventListener( 'mousemove', onMouseMove, false );\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 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\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\nexport {CustomOrbitControls};\r\n","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAOwAAADsABataJCQAAABl0RVh0U29mdHdhcmUAcGFpbnQubmV0IDQuMC4xMK0KCsAAAAA0SURBVDhPY/gPBvXGDAz1bgxnChj+9zQ0NHz7z/D/BgPDlP+bGEDoPwMDhDGKRtGwQgz/AdMXsIuNsuecAAAAAElFTkSuQmCC\"","import { TextureLoader } from 'three';\r\nimport classifications from '../textures/colormaps/classifications.png';\r\n\r\n// Load classification texture\r\nconst loader = new TextureLoader();\r\nexport const classificationTexture = loader.load(classifications);\r\n","import edlFragmentShader from \"./edl_f\";\r\nimport edlVertexShader from \"./edl_v\";\r\nimport opacityFragmentShader from \"./opacity_f\";\r\nimport opacityVertexShader from \"./opacity_v\";\r\nimport pointCloudFragmentShader from \"./pointcloud_f\";\r\nimport pointCloudVertexShader from \"./pointcloud_v\";\r\nimport panoramicFragmentShader from \"./panoramic_f\";\r\nimport panoramicVertexShader from \"./panoramic_v\";\r\nimport imageFragmentShader from \"./image_f\";\r\nimport imageVertexShader from './image_v';\r\nimport markersFragmentShader from \"./markers_f\";\r\nimport markersVertexShader from './markers_v';\r\nimport utilitiesVertexShader from './utilities_v';\r\nimport gpuPickerFragmentShader from './gpu_picker_f';\r\n\r\nconst shaders = {\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 edl: {\r\n vert: edlVertexShader,\r\n frag: edlFragmentShader\r\n },\r\n opacity: {\r\n vert: opacityVertexShader,\r\n frag: opacityFragmentShader\r\n },\r\n image: {\r\n vert: imageVertexShader,\r\n frag: imageFragmentShader\r\n },\r\n markers: {\r\n vert: markersVertexShader,\r\n frag: markersFragmentShader\r\n },\r\n utilities: {\r\n vert: utilitiesVertexShader\r\n },\r\n gpu_picker: {\r\n frag: gpuPickerFragmentShader\r\n }\r\n};\r\n\r\nexport default shaders;","const shader = `\r\n#define PRECISION 0.0001\r\n#define DISTANCE_FROM_PLANE 0.5\r\n\r\nattribute float intensity;\r\nattribute float classification;\r\nattribute int gpu_index;\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 distance;\r\nuniform vec3 origin;\r\nuniform float screenHeight;\r\nuniform float fov;\r\nuniform float size_min;\r\nuniform float size_max;\r\nuniform float octree_size;\r\nuniform vec3 octree_corner;\r\nuniform float octree_spacing;\r\n\r\nuniform sampler2D color_map;\r\nuniform float color_type;\r\nuniform bool dynamic_size;\r\nuniform bool dynamic_cloud;\r\nuniform vec2 height_range;\r\nuniform vec2 height_clamp;\r\nuniform vec2 intensity_range;\r\nuniform vec2 intensity_clamp;\r\nuniform float rgb_max;\r\n\r\nuniform sampler2D visible_nodes;\r\nuniform sampler2D classification_data;\r\nuniform bool classification_visible[NUMBER_OF_CLASSIFICATIONS];\r\n\r\nuniform vec3 area_measure_data[AREA_VERTICES_TOTAL];\r\nuniform float volume_status[AREA_TRIANGLES_TOTAL];\r\n\r\nvarying vec4 vGPUColor;\r\nvarying vec3 vColor;\r\nvarying vec2 vUv;\r\nvarying float vAlpha;\r\nvarying vec3 vViewPosition;\r\n\r\nfloat sign (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\nbool compareFloat(float floatOne, float floatTwo) {\r\n return abs(floatOne - floatTwo) < PRECISION;\r\n}\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\nint checkPointInTriangle(vec3 point) {\r\n // Return values:\r\n // 0: not in polygon\r\n // 1: in polygon, volume not enabled\r\n // 2: in polygon, volume enabled\r\n\r\n for (int i=0;i 0.5;\r\n bool volumeActive = compareFloat(volumeStatus, 2.0);\r\n\r\n vec3 v1 = area_measure_data[baseIndex];\r\n vec3 v2 = area_measure_data[baseIndex + 1];\r\n vec3 v3 = area_measure_data[baseIndex + 2];\r\n\r\n // Empty set of vertices\r\n if (length(v1 - v2) < PRECISION) {\r\n if (length(v3 - v1) < PRECISION) {\r\n break;\r\n }\r\n }\r\n\r\n vec3 N = cross(v2 - v1, v3 - v1);\r\n N = N / length(N);\r\n\r\n\r\n vec3 v1_p, v2_p, v3_p, point_p;\r\n\r\n if (isVolume == 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 v1_p = pointOnPlane(v1, v1, N);\r\n v2_p = pointOnPlane(v1, v2, N);\r\n v3_p = pointOnPlane(v1, v3, N);\r\n point_p = pointOnPlane(v1, point, N);\r\n } else {\r\n // Dont reproject our points\r\n v1_p = v1;\r\n v2_p = v2;\r\n v3_p = v3;\r\n point_p = point;\r\n }\r\n\r\n float d1 = sign(point_p, v1_p, v2_p);\r\n float d2 = sign(point_p, v2_p, v3_p);\r\n float d3 = sign(point_p, v3_p, v1_p);\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 if (insideTriangle) {\r\n if (volumeActive) {\r\n return 2;\r\n } else {\r\n return 1;\r\n }\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\nbool classificationIsHidden(float classification) {\r\n return classification_visible[int(classification)] == false;\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(classification_data, vec2(x, 0.5));\r\n return value.rgb;\r\n}\r\n\r\nfloat clampedValue(float data, vec2 data_range, vec2 data_clamp) {\r\n float scaled = (data - data_range.x) / (data_range.y - data_range.x);\r\n float clamped = (scaled - data_clamp.x) / (data_clamp.y - data_clamp.x);\r\n return clamped;\r\n}\r\n\r\nvec3 calculateOppositeColor(float color_type, vec3 color_value){\r\n vec3 result;\r\n vec3 opp = vec3(1.0, 1.0, 1.0);\r\n opp = opp - color_value;\r\n\r\n bool isIntensity = compareFloat(color_type, 0.0);\r\n bool isRGB = compareFloat(color_type, 1.0);\r\n bool isHeight = compareFloat(color_type, 2.0);\r\n bool isClassification = compareFloat(color_type, 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 color_type, vec3 pos_world) {\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(color_type, 0.0);\r\n bool isRGB = compareFloat(color_type, 1.0);\r\n bool isHeight = compareFloat(color_type, 2.0);\r\n bool isClassification = compareFloat(color_type, 3.0);\r\n\r\n if (isRGB) {\r\n // Color by RGB values\r\n color = rgb / rgb_max;\r\n } else if (isIntensity) {\r\n // Intensity colors with clamping\r\n float pc_intens = clampedValue(intensity, intensity_range, intensity_clamp);\r\n color = texture2D(color_map, vec2(pc_intens, 0.5)).rgb;\r\n } else if (isHeight) {\r\n // Height based coloring with clamping\r\n float height = pos_world.z;\r\n float pc_height = clampedValue(height, height_range, height_clamp);\r\n color = texture2D(color_map, vec2(pc_height, 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\nfloat round(float number){\r\n\treturn floor(number + 0.5);\r\n}\r\n\r\nbool isBitSet(int number, int index){\r\n int powi = int(round(pow(2.0, float(index))));\r\n\tint ndp = number / powi;\r\n float mod_remainder = mod(float(ndp), 2.0);\r\n\treturn !compareFloat(mod_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\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 = octree_size / pow(2.0, i);\r\n\r\n // Find the child index that we would belong to. We will test if it\r\n // actually exists w/ isBitSet(childrenNodes, index).\r\n vec3 index3d = (positionOctree - offset) / nodeSizeAtLevel;\r\n\t\tindex3d = floor(index3d + 0.5);\r\n int index = int(round(index3d.x + 2.0 * index3d.y + 4.0 * index3d.z));\r\n\r\n // Grab our values\r\n\t\tvec4 value = texture2D(visible_nodes, vec2(float(iOffset) / 2048.0, 0.0));\r\n\r\n // Offet from our current node to its first child node\r\n int firstChildOffset = int(round(value.g * 255.0));\r\n\r\n // Bit representation of existing children\r\n // ex: child nodes: [0,1,4,7], childrenNodes = [10010011]\r\n int childrenNodes = int(round(value.r * 255.0));\r\n\r\n // Offset from the child node to the one we belong to\r\n // ex: child nodes: [0,1,4,7], index = 7 --> offsetToChildIndex = 3\r\n int offsetToChildIndex = numberOfOnes(childrenNodes, index - 1);\r\n\r\n // True if our suspected child exists\r\n bool childExists = isBitSet(childrenNodes, index);\r\n\r\n\t\tif (childExists) {\r\n\t\t\t// there are more visible child nodes at this position\r\n\t\t\tiOffset = iOffset + firstChildOffset + offsetToChildIndex;\r\n depth++;\r\n\t\t} else {\r\n\t\t\t// no more visible child nodes at this position\r\n\t\t\treturn depth;\r\n\t\t}\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 pos_world){\r\n vec3 positionOctree = pos_world - octree_corner;\r\n\treturn pow(1.9, getLocalTreeDepth(positionOctree));\r\n}\r\n\r\nvoid main() {\r\n vUv = uv;\r\n vAlpha = 1.0;\r\n vGPUColor = makeColor(gpu_index);\r\n\r\n vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);\r\n vViewPosition = -mvPosition.xyz;\r\n gl_Position = projectionMatrix * mvPosition;\r\n\r\n // Position in viewer coordinates (including offset)\r\n\tvec3 pos_world = (modelMatrix * vec4( position, 1.0 )).xyz;\r\n float x = pos_world.x - origin.x;\r\n float y = pos_world.y - origin.y;\r\n float distance2D = sqrt(x * x + y * y);\r\n\r\n // Hide based on distance\r\n if (distance2D > distance) {\r\n vAlpha = 0.0;\r\n }\r\n\r\n // Check if classification is hidden\r\n if (classificationIsHidden(classification)) {\r\n vAlpha = 0.0;\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, vViewPosition.z);\r\n\r\n if (dynamic_size && dynamic_cloud){\r\n // Dynamic sizing (based on node density)\r\n \tfloat r = octree_spacing * 1.5;\r\n float pointAttenuation = getPointSizeAttenuation(pos_world);\r\n \tfloat worldSpaceSize = 0.7 * size * r / pointAttenuation;\r\n \tpointSize = 0.50 * worldSpaceSize * projFactor;\r\n } else {\r\n // Static point size\r\n pointSize = 0.05 * size * projFactor;\r\n }\r\n\r\n pointSize = max(size_min, pointSize);\r\n pointSize = min(size_max, pointSize);\r\n\r\n // ---------------------\r\n\t// POINT COLOR\r\n\t// ---------------------\r\n vColor = getCloudColor(color_type, pos_world);\r\n\r\n // ---------------------\r\n // CROSS SECTION\r\n // ---------------------\r\n bool inCrossSection = false; //checkForCrossSection(pos_world.xyz);\r\n\r\n // ---------------------\r\n // POINT IN POLYGON (MEASUREMENT AREA/VOLUME)\r\n // ---------------------\r\n int returnValue = checkPointInTriangle(pos_world.xyz);\r\n bool insidePolygon = returnValue > 0;\r\n bool volumeEnabled = returnValue == 2;\r\n\r\n if (inCrossSection || insidePolygon) {\r\n vColor = calculateOppositeColor(color_type, vColor);\r\n }\r\n\r\n if (volumeEnabled) {\r\n pointSize = pointSize * 0.5;\r\n // vAlpha = 0.0;\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 gl_PointSize = pointSize;\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\n#define PRECISION 0.0001\r\n\r\nuniform bool gpuPicker;\r\nuniform bool circularPoints;\r\n\r\nvarying vec3 vColor;\r\nvarying float vAlpha;\r\nvarying vec2 vUv;\r\nvarying vec4 vGPUColor;\r\n\r\nvoid main(void) {\r\n vec4 point_color = vec4(vColor, vAlpha);\r\n vec4 color = point_color;\r\n\r\n // Discard if not visible\r\n if (color.a < PRECISION) {\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 = color;\r\n }\r\n\r\n gl_FragColor = final;\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\nvarying vec3 vWorldDirection;\r\n\r\nvoid main() {\r\n mat3 mtrx = mat3(\r\n vec3(1.0, 0.0, 0.0),\r\n vec3(0.0, 0.0, -1.0),\r\n vec3(0.0, 1.0, 0.0)\r\n );\r\n\r\n vWorldDirection = normalize(mtrx * position);\r\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\n#define RECIPROCAL_PI 0.3183098861837907\r\n#define RECIPROCAL_PI2 0.15915494309189535\r\n\r\nuniform sampler2D tEquirect;\r\nvarying vec3 vWorldDirection;\r\n\r\nvec2 equirectUv( in vec3 dir ) {\r\n\t// dir is assumed to be unit length\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 vec3 direction = normalize(vWorldDirection);\r\n vec2 sampleUV = equirectUv( direction );\r\n gl_FragColor = texture2D( tEquirect, sampleUV );\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\nvarying vec2 vUv;\r\nvoid main() {\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\n#include \r\n#define NEIGHBOUR_COUNT 4\r\n#define PRECISION 0.0001\r\n\r\nuniform sampler2D colorMap;\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 expScale;\r\nuniform float edlStrength;\r\nuniform float radius;\r\n\r\nvarying vec2 vUv;\r\n\r\nfloat readDepth(sampler2D depthSampler, vec2 coord) {\r\n float fragCoordZ = texture2D(depthSampler, coord).x;\r\n float viewZ = perspectiveDepthToViewZ(fragCoordZ, near, far);\r\n return far * viewZToOrthographicDepth(viewZ, near, far);\r\n}\r\n\r\nfloat ztransform(float linearDepth) {\r\n return 1.0 - (linearDepth - near) / (far - near);\r\n}\r\n\r\nfloat obscurance(float z, float dist) {\r\n float value = max(0.0, z) / dist;\r\n return 0.5 * value;\r\n}\r\n\r\nfloat computeObscurance(float linearDepth) {\r\n vec4 P = vec4(0, 0, 1, -ztransform(linearDepth));\r\n vec2 uvRadius = radius / vec2(screenWidth, screenHeight);\r\n\r\n float sum = 0.0;\r\n for (int c = 0; c < NEIGHBOUR_COUNT; c++) {\r\n vec2 N_rel_pos = uvRadius * neighbours[c];\r\n vec2 N_abs_pos = vUv + N_rel_pos;\r\n\r\n float neighbourDepth = readDepth(tDepth, N_abs_pos);\r\n if (neighbourDepth != 0.0) {\r\n float Zn = ztransform(neighbourDepth);\r\n float Znp = dot(vec4(N_rel_pos, Zn, 1.0), P);\r\n sum += obscurance(Znp, 0.05 * linearDepth);\r\n }\r\n }\r\n return sum;\r\n}\r\n\r\nvoid main() {\r\n vec4 color = texture2D(colorMap, vUv);\r\n float linearDepth = readDepth(tDepth, vUv);\r\n float f = computeObscurance(linearDepth);\r\n\r\n if (color.a <= PRECISION && f <= PRECISION) {\r\n discard;\r\n }\r\n\r\n f = exp(-expScale * f * edlStrength);\r\n gl_FragColor = vec4(color.rgb * f, opacity);\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\nvarying vec2 vUv;\r\nvoid main() {\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\nuniform sampler2D colorMap;\r\nuniform float opacity;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n vec4 color = texture2D( colorMap, vUv );\r\n float new_alpha = min(color.a, opacity);\r\n gl_FragColor = vec4(color.rgb,new_alpha);\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\nvarying vec2 vUv;\r\nvoid main() {\r\n\tvUv = uv;\r\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\nuniform sampler2D colorMap;\r\nuniform float brightness;\r\nuniform float contrast;\r\n\r\nvarying vec2 vUv;\r\n\r\nvoid main() {\r\n\r\n\tgl_FragColor = texture2D( colorMap, vUv );\r\n\r\n\tgl_FragColor.rgb += brightness;\r\n\r\n\tif (contrast > 0.0) {\r\n\t\tgl_FragColor.rgb = (gl_FragColor.rgb - 0.5) / (1.0 - contrast) + 0.5;\r\n\t}\r\n\telse {\r\n\t\tgl_FragColor.rgb = (gl_FragColor.rgb - 0.5) * (1.0 + contrast) + 0.5;\r\n\t}\r\n\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\n#define PRECISION 0.0001\r\n#define MIN_CAMERA_DIST 0.5\r\n\r\nattribute float selected;\r\nattribute int gpu_index;\r\nattribute int camera_index;\r\nattribute float visible;\r\nattribute float marker_shape;\r\n\r\nuniform float marker_size;\r\nuniform vec3 camera_position;\r\nuniform bool orbitMode;\r\nuniform vec3 mtrx_x;\r\nuniform vec3 mtrx_y;\r\nuniform vec3 mtrx_z;\r\nuniform float screenHeight;\r\nuniform int currentIndex;\r\nuniform float fov;\r\n\r\nvarying vec2 vUv;\r\nvarying float vSelected;\r\nvarying vec4 vGPUColor;\r\nvarying float vHidden;\r\nvarying float vVisible;\r\nvarying float vMarkerShape;\r\n\r\nbool compareFloat(float floatOne, float floatTwo) {\r\n return abs(floatOne - floatTwo) < PRECISION;\r\n}\r\n\r\nmat3 scaleMatrix(float scale_x,float scale_y,float scale_z){\r\n return mat3(\r\n vec3(scale_x, 0.0, 0.0),\r\n vec3(0.0, scale_y, 0.0),\r\n vec3(0.0, 0.0, scale_z)\r\n );\r\n}\r\n\r\nfloat getDistance3D(vec3 offset) {\r\n float cam_x = offset.x - camera_position.x;\r\n float cam_y = offset.y - camera_position.y;\r\n float cam_z = offset.z - camera_position.z;\r\n float camera_distance_3d = sqrt(cam_x*cam_x + cam_y*cam_y + cam_z*cam_z);\r\n return camera_distance_3d;\r\n}\r\n\r\nfloat getDistance2D(vec3 offset) {\r\n float cam_x = offset.x - camera_position.x;\r\n float cam_y = offset.y - camera_position.y;\r\n float camera_distance_2d = sqrt(cam_x*cam_x + cam_y*cam_y);\r\n return camera_distance_2d;\r\n}\r\n\r\nvoid main() {\r\n vUv = uv;\r\n vSelected = selected;\r\n vGPUColor = makeColor(gpu_index);\r\n vVisible = visible;\r\n vMarkerShape = marker_shape;\r\n\r\n float hidden = 0.0;\r\n bool isSelected = compareFloat(vSelected, 1.0);\r\n\r\n float selected_scale = 0.8;\r\n if (isSelected) {\r\n selected_scale = 1.0;\r\n }\r\n\r\n // Global scaling for smaller markers\r\n selected_scale = 0.5 * selected_scale;\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 offset = vec3(x,y,z);\r\n\r\n float distance3D = getDistance3D(offset);\r\n float distance2D = getDistance2D(offset);\r\n float height = abs(offset.z - camera_position.z);\r\n\r\n float projFactor = getProjFactor(fov, screenHeight, height);\r\n float markerSize = 30.0 / projFactor;\r\n markerSize = max(1.0, markerSize);\r\n markerSize = min(10.0, markerSize);\r\n\r\n float scale_x = markerSize*selected_scale;\r\n float scale_y = markerSize*selected_scale;\r\n float scale_z = markerSize*selected_scale;\r\n\r\n // Hide marker based on distance\r\n if (distance3D < MIN_CAMERA_DIST) {\r\n hidden = 1.0;\r\n }\r\n\r\n // Hide the current camera if we arent in orbit mode\r\n bool currentCamera = currentIndex == camera_index;\r\n if ((orbitMode == false) && currentCamera) {\r\n hidden = 1.0;\r\n }\r\n\r\n // Move position to center of marker\r\n vec3 pos_offset = position - offset;\r\n\r\n // Rotate using camera quaternion matrix\r\n mat3 rot = mat3(mtrx_x, mtrx_y, mtrx_z);\r\n vec3 pos_rotated = pos_offset * rot;\r\n\r\n // Apply scaling based on selected or not\r\n mat3 scale_matrix = scaleMatrix(scale_x, scale_y, scale_z);\r\n vec3 pos_scaled = pos_rotated * scale_matrix;\r\n\r\n // Add back our offset values\r\n vec3 pos_real = pos_scaled + offset;\r\n\r\n // Apply final position\r\n gl_Position = projectionMatrix * modelViewMatrix * vec4(pos_real, 1.0);\r\n\r\n // We hide the marker for various reasons\r\n vHidden = hidden;\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\r\n#define PRECISION 0.0001\r\n\r\nuniform bool gpuPicker;\r\n\r\nvarying vec2 vUv;\r\nvarying float vSelected;\r\nvarying vec4 vGPUColor;\r\nvarying float vHidden;\r\nvarying float vVisible;\r\nvarying float vMarkerShape;\r\n\r\nbool compareFloat(float floatOne, float floatTwo) {\r\n return abs(floatOne - floatTwo) < PRECISION;\r\n}\r\n\r\nvoid main() {\r\n vec2 uv = vUv;\r\n uv = 2.0 * uv - 1.0;\r\n\r\n bool isHidden = compareFloat(vHidden, 1.0);\r\n bool isSelected = compareFloat(vSelected, 1.0);\r\n bool isVisible = compareFloat(vVisible, 1.0);\r\n bool isCircle = compareFloat(vMarkerShape, 0.0);\r\n bool isSquare = compareFloat(vMarkerShape, 1.0);\r\n\r\n if (isHidden) {\r\n discard;\r\n }\r\n\r\n if (!isVisible) {\r\n discard;\r\n }\r\n\r\n // All markers are gray-ish\r\n vec4 colorStandard = vec4(255, 255, 255, 255) / 255.0;\r\n vec4 colorSelected = vec4(255, 195, 0, 255) / 255.0;\r\n float border_thickness = 0.1;\r\n\r\n vec4 final;\r\n if (gpuPicker) {\r\n final = vGPUColor;\r\n } else {\r\n if (isSelected) {\r\n final = colorSelected;\r\n }\r\n else {\r\n final = colorStandard;\r\n }\r\n }\r\n\r\n // Circular markers\r\n if (isCircle) {\r\n // Circle shape\r\n float circle = sqrt(uv.x * uv.x + uv.y * uv.y);\r\n float circle_bounds = 1.0;\r\n if (circle > 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 final.a = 1.0;\r\n }\r\n\r\n gl_FragColor = final;\r\n}\r\n`;\r\n\r\nexport default shader;","const shader = `\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\n\r\nexport default shader;","const shader = `\r\n#define FLOAT_OFFSET 0.25\r\n\r\nvec4 makeColor(int index) {\r\n vec4 color = vec4(\r\n float(index >> 24 & 255),\r\n float(index >> 16 & 255),\r\n float(index >> 8 & 255),\r\n float(index & 255)\r\n );\r\n\r\n return (color + FLOAT_OFFSET) / 255.0;\r\n}\r\n`;\r\n\r\nexport default shader;","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\n\r\ninterface ColorMap {\r\n id: ColorMapKey;\r\n name: string;\r\n image: string;\r\n}\r\n\r\nexport const colorMaps: ColorMap[] = [\r\n {\r\n id: 'heat-map',\r\n name: 'Heat Map',\r\n image: heatMap\r\n },\r\n {\r\n id: 'awesome-green',\r\n name: 'Green',\r\n image: awesomeGreen\r\n },\r\n {\r\n id: 'pastel-shades',\r\n name: 'Pastel',\r\n image: pastelShades\r\n },\r\n {\r\n id: 'blue-orange',\r\n name: 'Blue/Orange',\r\n image: blueOrange\r\n },\r\n {\r\n id: 'black-orange',\r\n name: 'Black/Orange',\r\n image: blackOrange\r\n },\r\n {\r\n id: 'blue-hue',\r\n name: 'Blue',\r\n image: blueHue\r\n },\r\n {\r\n id: 'blue-red',\r\n name: 'Blue/Red',\r\n image: blueRed\r\n },\r\n {\r\n id: 'jet',\r\n name: 'Rainbow',\r\n image: jet\r\n },\r\n {\r\n id: 'grayscale',\r\n name: 'Grayscale',\r\n image: grayScale\r\n },\r\n];","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZDMzMzNEJDOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZDMzMzNEJEOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MkEzRjRDN0Y5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MkEzRjRDODA5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz53bCn1AAAAd0lEQVR42pyQWQ6AMAhEWf68/0k8oFurQGWoiQkZH+N0gxdamXYmauolIyDdJHGH4NyqyTlVL7WA+RZ+g+UfiL4Hwqphc3hcPPfJgKuOmp/pPJkYJ+5jp/bxkgIkgLWCWlhat1qAfpn/fkGY37AqRpxnBaHVIcAAYkN//MPKatUAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZDMzMzNEM0OTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZDMzMzNEM1OTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkMzMzM0QzI5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NkMzMzM0QzM5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7eN8REAAAAUUlEQVR42mJksHBggABGJArKxi0OF6REhAwuIyNRUkhsRkZGFNtxKMPOZkSzhSAb1RAiNZJkC7pFZGskjg0PQAJaUFMIPilSuBSJEJWYAQIMAGSSASAboJt0AAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjZDMzMzNEMwOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjZDMzMzNEMxOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkMzMzM0QkU5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NkMzMzM0QkY5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz57rwGxAAAAqUlEQVR42nSQ0QHDIAhE8Vyyf91/CaggXKmxhpB3iBgY8nqPtURGfNaDDbHwhfSE9YIRsgMKSl7YcyYSDjmRaQWILULLwZhRc2Ydyrxr7uIJVeHgPFj/3GH8xmMyZBSv6aFmhWBPk5QxVUH4bZ3LLMFMKM29uDeJuHsHSzjY9MKqTaposdI32LsH32WdovzhRzKLPCNXaXZe1HvR3g47+jOBp3FoIh8BBgBdQemDiUpBTQAAAABJRU5ErkJggg==\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjJBM0Y0Qzc5OTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjJBM0Y0QzdBOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MkEzRjRDNzc5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MkEzRjRDNzg5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5sYFSgAAAAkElEQVR42oxSQQ6AIAxrPfoTn+T/H4JABnRjGjWauq4FXHmdNwC2p7S34XoXwfUqJLTTmtmpCJrcwLTqYJpPN1LkfS3RGjWE8knTwlVWXTsR68EnZbOeKNmEW/Fw1MsSSdFRR7qlr7Oku/1xwI3F54/NJ0UNSTapMG6fEIQM5EFack2mi/EI5AjwMtcYPwIMAFqNWn3HA2aBAAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjMxMTc0NkZCOTk3RjExRTM5NkIyQkQ4NDk0QjFBNDc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjMxMTc0NkZDOTk3RjExRTM5NkIyQkQ4NDk0QjFBNDc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NkMzMzM0QzY5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MzExNzQ2RkE5OTdGMTFFMzk2QjJCRDg0OTRCMUE0NzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz60/6QNAAAAeklEQVR42oyRiw0AIQhDKcO4/4ZcTlEB8WOIKY+SgKKUAvoPaqzCBpEg4y34AiV4+C6EM76B8ux0w/DjPJB1x8qzfR2U4AHM88I8+NDwzsChH2FS9dByj6q7U3P/dZtOmKVJrwodj45doTpmc56jnu2htEsNadVPgAEAbNIKfJUbq1UAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjJBM0Y0QzdEOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjJBM0Y0QzdFOTk3RDExRTM5NkIyQkQ4NDk0QjFBNDc5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MkEzRjRDN0I5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MkEzRjRDN0M5OTdEMTFFMzk2QjJCRDg0OTRCMUE0NzkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6Y40aYAAAAiklEQVR42nxSaxqAIAhj1+2MHa4vBbeh1Y/EPZCaiOuOCCDGs9ZAronJlhCWturBLdX7VrZRE2gUvL9bwAJR+jRYw4F+g2I5gNW8KNau32R5EJL5psre6vWvjkYdj5P8UJCGm+z4UX3mNoMpLbs9buZuwWkcHoRkqtTckaKQrNRibteVl9tkjwADAFtgAm39YPP3AAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjFDQjFDMTc5OUE2NjExRTNBOEY0Rjk5N0IxMzQ3M0Q5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjFDQjFDMTdBOUE2NjExRTNBOEY0Rjk5N0IxMzQ3M0Q5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUNCMUMxNzc5QTY2MTFFM0E4RjRGOTk3QjEzNDczRDkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MUNCMUMxNzg5QTY2MTFFM0E4RjRGOTk3QjEzNDczRDkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz5cZSRIAAAARElEQVR42mJkYPjPyPCfgYEBK4mLi8zAw8bk4hGkOmJi+Ee8OJog2VzS2UDyH1WMopBLRqBRHRGTWggmPPxJF40ECDAA7VjoAcudFgkAAAAASUVORK5CYII=\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAIAAAC+O+cgAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACpSURBVDhPfY0JDoMwEAPdcj28r+YIdMCwCqGpZFmDYy8v6SN1UiO1DxHyZED9BWZyv4bIi6TVu3JjOPze3UVY9J9hbRsq+v4pn3ENp2AoRBjbDlsaJTRobA/uNBtw2FAorwFRy7eh2pEYol6TwfnPPqHvo7O/rUrSpN1zWKT5gkKE41Vz3yF9A17bxhAVP+UV/3MkajFMWtOJruPw84YXsbvfuOX5dpf0BQz6ooH2nDFQAAAAAElFTkSuQmCC\"","export default \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAAMElEQVQ4T2NkYGD4z8TExAACo/TAhAMjIyMDCMPCf6jwYe6khIalO5gZQ5U/VPMPAPmjA/6Q8LQDAAAAAElFTkSuQmCC\"","import classificationsShader from \"./viewer/textures/colormaps/classifications.png\";\r\n\r\nexport interface Classification {\r\n id: number;\r\n name: string;\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 },\r\n {\r\n id: 1,\r\n name: \"Unassigned\"\r\n },\r\n {\r\n id: 2,\r\n name: \"Ground\"\r\n },\r\n {\r\n id: 3,\r\n name: \"Low Vegetation\"\r\n },\r\n {\r\n id: 4,\r\n name: \"Medium Vegetation\"\r\n },\r\n {\r\n id: 5,\r\n name: \"High Vegetation\"\r\n },\r\n {\r\n id: 6,\r\n name: \"Building\"\r\n },\r\n {\r\n id: 7,\r\n name: \"Noise\"\r\n },\r\n {\r\n id: 8,\r\n name: 'Model Key/Reserved'\r\n },\r\n {\r\n id: 9,\r\n name: \"Water\"\r\n },\r\n {\r\n id: 10,\r\n name: \"Rail\"\r\n },\r\n {\r\n id: 11,\r\n name: \"Road Surface\"\r\n },\r\n {\r\n id: 12,\r\n name: 'Overlap/Reserved'\r\n },\r\n {\r\n id: 13,\r\n name: \"Wire - Guard\"\r\n },\r\n {\r\n id: 14,\r\n name: \"Wire - Conductor\"\r\n },\r\n {\r\n id: 15,\r\n name: \"Transmission Tower\"\r\n },\r\n {\r\n id: 16,\r\n name: \"Wire - Connector\"\r\n },\r\n {\r\n id: 17,\r\n name: \"Bridge Deck\"\r\n },\r\n {\r\n id: 18,\r\n name: \"High Noise\"\r\n },\r\n ...Array.from(Array(numberOfClassifications - numberOfDefinedClassifications).keys()).map(key => ({id: key + numberOfDefinedClassifications, name: 'Reserved'}))\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 {classificationTexture} from './classifications';\r\nimport shaders from './shaders';\r\nimport {colorMaps} from '../textures/colormaps';\r\nimport {Viewer} from \"./main\";\r\nimport {\r\n Color, DataTexture, NearestFilter, DoubleSide,\r\n RGBAFormat, RGBFormat, ShaderMaterial,\r\n Uniform, Vector2, Vector3, TextureLoader\r\n} from \"three\";\r\nimport {numberOfClassifications} from \"../../classifications\";\r\n\r\nexport class BaseMaterial extends ShaderMaterial {\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\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 distance: any\r\n size: number\r\n colorMap: string\r\n classification: object\r\n}\r\n\r\nexport class PointCloudMaterial extends BaseMaterial {\r\n public size;\r\n public distance;\r\n public color_map;\r\n public color_type;\r\n public dynamic_size;\r\n public circularPoints;\r\n public visibleNodesTexture: any;\r\n public dynamic_cloud: boolean;\r\n public origin: any;\r\n public screenHeight: number;\r\n public screenwidth: number;\r\n public fov: number;\r\n public octree_spacing: any;\r\n public octree_size: number;\r\n public octree_corner: Vector3;\r\n public intensity_range: Vector2;\r\n public rgb_max: number;\r\n public height_range: Vector2;\r\n\r\n constructor(viewer: Viewer, params: PointCloudMaterialParams, gpuPicker) {\r\n super();\r\n\r\n // Node depth texture for dynamic sizing\r\n this.visibleNodesTexture = generateDataTexture(2048, 1, 3);\r\n\r\n // Load colormap texture\r\n const loader = new TextureLoader();\r\n const colorMapTexture = loader.load(colorMaps.find(colorMap => colorMap.id === params.colorMap).image);\r\n\r\n // Generate classification visibility array\r\n const classificationVisible = new Array(numberOfClassifications).fill(true);\r\n classificationTexture.minFilter = NearestFilter;\r\n classificationTexture.magFilter = NearestFilter;\r\n\r\n // Initialize area data\r\n const maxTriangles = 256;\r\n let maxAreaTriangles = maxTriangles;\r\n let maxAreaVertices = maxTriangles * 3;\r\n let areaClipData = new Float32Array(maxAreaTriangles * 3 * 3).fill(0.0);\r\n let volumeStatus = new Float32Array(maxAreaTriangles).fill(0.0);\r\n\r\n let uniforms = {\r\n gpuPicker: new Uniform(gpuPicker),\r\n circularPoints: new Uniform(params.circularPoints),\r\n \"depth\": new Uniform(1.0),\r\n \"sphere\": new Uniform(viewer.camera.position),\r\n \"origin\": new Uniform(viewer.camera.position),\r\n \"size\": new Uniform(params.size),\r\n \"size_min\": new Uniform(params.minSize),\r\n \"size_max\": new Uniform(params.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 \"distance\": new Uniform(params.distance),\r\n \"octree_size\": new Uniform(0.0),\r\n \"octree_spacing\": new Uniform(0.0),\r\n \"octree_corner\": new Uniform(viewer.camera.position),\r\n \"color_type\": new Uniform(params.colorType),\r\n \"height_range\": new Uniform(new Vector2(0, 1)),\r\n \"height_clamp\": new Uniform(params.heightClamp),\r\n \"intensity_range\": new Uniform(new Vector2(0, 1)),\r\n \"intensity_clamp\": new Uniform(params.intensityClamp),\r\n \"rgb_max\": new Uniform(0),\r\n \"color_map\": new Uniform(colorMapTexture),\r\n \"dynamic_size\": new Uniform(params.dynamicSize),\r\n \"dynamic_cloud\": new Uniform(false),\r\n \"classification_data\": new Uniform(classificationTexture),\r\n \"classification_visible\": new Uniform(classificationVisible),\r\n \"visible_nodes\": new Uniform(this.visibleNodesTexture),\r\n \"volume_status\": new Uniform(volumeStatus),\r\n \"max_triangles\": new Uniform(maxTriangles),\r\n \"area_measure_data\": new Uniform(areaClipData)\r\n };\r\n\r\n let defines = [\r\n `#define NUMBER_OF_CLASSIFICATIONS ${numberOfClassifications}`,\r\n `#define AREA_TRIANGLES_TOTAL ${maxAreaTriangles}`,\r\n `#define AREA_VERTICES_TOTAL ${maxAreaVertices}`\r\n ].join(\"\\n\");\r\n\r\n let fragmentShader = shaders.pointcloud.frag;\r\n\r\n let vertexShader = [\r\n defines,\r\n shaders.gpu_picker.frag,\r\n shaders.utilities.vert,\r\n shaders.pointcloud.vert\r\n ].join(\"\\n\");\r\n\r\n this.setValues({\r\n uniforms: uniforms,\r\n vertexShader: vertexShader,\r\n fragmentShader: 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\r\nexport class EDLMaterial extends BaseMaterial {\r\n public screenWidth: any;\r\n public screenHeight: any;\r\n public edlStrength: any;\r\n\r\n constructor(parent) {\r\n super();\r\n\r\n let vertexShader = shaders.edl.vert;\r\n let fragmentShader = shaders.edl.frag;\r\n\r\n let neighbourCount = 4;\r\n let neighbours = new Float32Array(neighbourCount * 2);\r\n for (let c = 0; c < neighbourCount; c++) {\r\n neighbours[2 * c] = Math.cos(2 * c * Math.PI / neighbourCount);\r\n neighbours[2 * c + 1] = Math.sin(2 * c * Math.PI / neighbourCount);\r\n }\r\n\r\n let lightDir = new Vector3(0.0, 0.0, 1.0).normalize();\r\n let uniform = {\r\n screenWidth: {type: \"f\", value: parent.WIDTH},\r\n screenHeight: {type: \"f\", value: parent.HEIGHT},\r\n near: {type: \"f\", value: parent.camera.near},\r\n far: {type: \"f\", value: parent.camera.far},\r\n opacity: {type: \"f\", value: 1.0},\r\n expScale: {type: \"f\", value: parent.camera.far},\r\n edlStrength: {type: \"f\", value: 1.0},\r\n radius: {type: \"f\", value: 1.0},\r\n lightDir: {type: \"v3\", value: lightDir},\r\n neighbours: {type: \"2fv\", value: neighbours},\r\n colorMap: {type: \"t\", value: null},\r\n tDepth: {type: \"t\", value: null}\r\n };\r\n\r\n this.setValues({\r\n uniforms: uniform,\r\n vertexShader: vertexShader,\r\n fragmentShader: fragmentShader,\r\n transparent: true\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class OpacityMaterial extends BaseMaterial {\r\n constructor() {\r\n super();\r\n\r\n let vertexShader = shaders.opacity.vert;\r\n let fragmentShader = shaders.opacity.frag;\r\n\r\n let uniform = {\r\n \"colorMap\": {type: \"t\", value: null},\r\n \"opacity\": {type: \"f\", value: 1.0}\r\n };\r\n\r\n this.setValues({\r\n uniforms: uniform,\r\n vertexShader: vertexShader,\r\n fragmentShader: fragmentShader,\r\n transparent: true\r\n });\r\n\r\n this.initProperties();\r\n }\r\n}\r\n\r\nexport class ImageMaterial extends BaseMaterial {\r\n constructor() {\r\n super();\r\n\r\n let vertexShader = shaders.image.vert;\r\n let fragmentShader = shaders.image.frag;\r\n\r\n let uniform = {\r\n \"colorMap\": {\r\n type: \"t\",\r\n value: null\r\n },\r\n \"brightness\": {\r\n type: \"f\",\r\n value: 0\r\n },\r\n \"contrast\": {\r\n type: \"f\",\r\n value: 0\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 PanoramicMaterial extends BaseMaterial {\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 uniform = {\r\n \"tEquirect\": {\r\n type: \"t\",\r\n value: null\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 setTexture(texture) {\r\n this.uniforms.tEquirect.value = texture;\r\n }\r\n}\r\n\r\nexport class MarkerMaterial extends BaseMaterial {\r\n constructor(viewer: Viewer, gpuPicker) {\r\n super();\r\n\r\n let fragmentShader = shaders.markers.frag;\r\n\r\n let vertexShader = [\r\n shaders.gpu_picker.frag,\r\n shaders.utilities.vert,\r\n shaders.markers.vert\r\n ].join(\"\\n\");\r\n\r\n let uniform = {\r\n gpuPicker: new Uniform(gpuPicker),\r\n orbitMode: new Uniform(false),\r\n camera_position: new Uniform(new Vector3(0, 1, 0)),\r\n mtrx_x: new Uniform(new Vector3(1, 0, 0)),\r\n mtrx_y: new Uniform(new Vector3(0, 1, 0)),\r\n mtrx_z: new Uniform(new Vector3(0, 0, 1)),\r\n marker_size: new Uniform(1.0),\r\n fov: new Uniform(viewer.camera.fov * Math.PI / 180.0),\r\n screenHeight: new Uniform(viewer.height),\r\n currentIndex: new Uniform(0)\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}","import { PointCloud } from \"./point-cloud\";\r\nimport {\r\n BufferAttribute,\r\n BufferGeometry,\r\n LineSegments,\r\n Points,\r\n Sphere,\r\n Vector3\r\n} from \"three\";\r\n\r\nexport class CloudNode {\r\n protected cloud: PointCloud;\r\n public name = null;\r\n public parent: CloudNode;\r\n public pointsScene: Points = null;\r\n public pointsPicker: Points = null;\r\n protected boundingBox: LineSegments = null;\r\n protected loaded: boolean;\r\n protected loading: boolean;\r\n protected size: any;\r\n protected sizeTight = new Vector3();\r\n protected data = null;\r\n protected _center = null;\r\n protected _sphere = null;\r\n public visible = false;\r\n protected numPoints = null;\r\n protected geometry = null;\r\n protected tightBoundingBox = null;\r\n\r\n constructor() {\r\n this.loaded = false;\r\n this.loading = false;\r\n }\r\n\r\n /** Return bounding sphere in viewer coordinates */\r\n get boundingSphere() {\r\n if (this._sphere === null) {\r\n this._sphere = new Sphere(this.center, this.radius);\r\n }\r\n\r\n return this._sphere;\r\n }\r\n\r\n get shift() {\r\n return new Vector3();\r\n }\r\n\r\n /** Return node center in viewer coordinates */\r\n get center() {\r\n return new Vector3().add(this._center).add(this.shift);\r\n }\r\n\r\n /** Return bounding sphere radius */\r\n get radius() {\r\n return Math.sqrt(3) * this.size / 2.0;\r\n }\r\n\r\n isLoaded() {\r\n return this.loaded;\r\n }\r\n\r\n isGeometryNode() {\r\n return this.pointsScene === null;\r\n }\r\n\r\n isTreeNode() {\r\n return this.pointsScene !== null;\r\n }\r\n\r\n removeFromScene(item) {\r\n if (!item) {\r\n return;\r\n }\r\n\r\n let index = this.cloud.scene.children.indexOf(item);\r\n let loaded = index !== -1;\r\n if (loaded) {\r\n this.cloud.scene.remove(item);\r\n }\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.cloud.picker.remove(this.pointsPicker);\r\n this.disposeGeometry(this.pointsPicker);\r\n this.pointsPicker = null;\r\n\r\n if (this.boundingBox) {\r\n this.removeFromScene(this.boundingBox);\r\n this.disposeGeometry(this.boundingBox);\r\n this.boundingBox = null;\r\n }\r\n\r\n if (this.geometry) {\r\n this.geometry.dispose();\r\n }\r\n this.geometry = null;\r\n\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, boundingBoxVisibility) {\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.boundingBox) {\r\n this.boundingBox.visible = boundingBoxVisibility;\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 this.geometry = geometry;\r\n }\r\n\r\n addCloudData(pointsPicker, pointsScene, boundingBox) {\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.cloud.scene.add(this.pointsScene);\r\n this.cloud.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.boundingBox = boundingBox;\r\n this.cloud.scene.add(this.boundingBox);\r\n }\r\n }\r\n}","import {CloudNode} from \"./cloud-node\";\r\nimport LocalScene from '../projections';\r\nimport { RawPointCloud } from '.';\r\nimport {\r\n LineSegments,\r\n Points,\r\n Vector3\r\n} from 'three';\r\n\r\nexport class RawPointCloudNode extends CloudNode {\r\n protected cloud: RawPointCloud;\r\n public parent: RawPointCloudRootNode;\r\n protected children = [];\r\n\r\n constructor(cloud: RawPointCloud, parent = null) {\r\n super();\r\n\r\n this.cloud = cloud;\r\n this.parent = parent;\r\n }\r\n\r\n loadFromData(data) {\r\n this.data = data;\r\n\r\n this.numPoints = data.numPoints;\r\n this.tightBoundingBox = {\r\n min: data.xyz_min,\r\n max: data.xyz_max\r\n };\r\n\r\n // Calculate bounding box size\r\n let size: any = new Vector3()\r\n .add(data.xyz_max)\r\n .sub(data.xyz_min);\r\n\r\n // Calculate bounding box center\r\n let center = new Vector3()\r\n .add(data.xyz_min)\r\n .add(data.xyz_max)\r\n .divideScalar(2.0)\r\n .sub(data.offset);\r\n\r\n this.sizeTight.copy(size);\r\n this.size = Math.max(size.x, size.y, size.z);\r\n this._center = 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 LocalScene.offsetToScene(this.data.offset);\r\n this.cloud.updateBoundingBox(this.tightBoundingBox);\r\n this.cloud.updateRootNode();\r\n }\r\n\r\n get shift() {\r\n return LocalScene.offsetToScene(this.data.offset);\r\n }\r\n\r\n getGeometry(data) {\r\n this.setGeometry(data);\r\n\r\n // Update unique values and min/max values\r\n this.cloud.updateClassifications(data.classification);\r\n this.cloud.updateColorLimits(data.rgb_max);\r\n this.cloud.updateIntensityRange(data.intensity_min, data.intensity_max);\r\n }\r\n\r\n addToScene() {\r\n // Create the pointcloud\r\n let pointsScene = new Points(this.geometry,\r\n this.cloud.materialScene);\r\n let pointsPicker = new Points(this.geometry,\r\n this.cloud.materialPicker);\r\n\r\n // Create bounding box object;\r\n let boundingBox = this.cloud.generateEdgeMesh(\r\n this.sizeTight.x, this.sizeTight.y, this.sizeTight.z);\r\n\r\n this.addCloudData(pointsPicker, pointsScene, boundingBox);\r\n }\r\n\r\n load() {\r\n if ((this.loaded) || (this.loading)) {\r\n return;\r\n }\r\n\r\n this.getGeometry(this.data);\r\n this.loaded = true;\r\n this.loading = false;\r\n }\r\n}\r\n\r\n/* Placeholder root node to handle our required format */\r\nexport class RawPointCloudRootNode extends RawPointCloudNode {\r\n constructor(cloud) {\r\n super(cloud);\r\n\r\n this.numPoints = 0;\r\n this.boundingBox = new LineSegments();\r\n this._center = new Vector3();\r\n this.size = 0;\r\n }\r\n\r\n get center() {\r\n return this._center;\r\n }\r\n\r\n /** Function override */\r\n dispose() {\r\n this.pointsScene = null;\r\n this.pointsPicker = null;\r\n this.boundingBox = null;\r\n }\r\n\r\n updateSizeInfo(data) {\r\n // Calculate bounding box size\r\n let size: any = new Vector3()\r\n .add(data.max)\r\n .sub(data.min);\r\n this.size = Math.max(size.x, size.y, size.z);\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._center = center;\r\n\r\n // Reset our sphere to null (so we re-calculate next time)\r\n this._sphere = null;\r\n }\r\n\r\n getGeometry() {\r\n return;\r\n }\r\n\r\n addChildNode(node) {\r\n this.children.push(node);\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","import {BufferAttribute, BufferGeometry, LineBasicMaterial, LineSegments, Vector3} from 'three';\r\nimport { isDevMode } from '../../../electron-modules';\r\nimport { PointCloudMaterial } from '../materials';\r\nimport {closestPowerOfTwo, randomHexColor} from \"../misc\";\r\nimport { CloudNode } from './cloud-node';\r\nimport {PointCloudManager} from \"./point-loader\";\r\nimport { RawPointCloudRootNode } from './raw-pointcloud-node';\r\n\r\nexport class PointCloud {\r\n public uniqueClassifications: Set;\r\n private readonly rgbArray: any = [];\r\n public maxColor: any = null;\r\n public intensityRange: any = null;\r\n private name: any = null;\r\n public identifier: any = null;\r\n private empty: boolean = false;\r\n public fileMissing: boolean = false;\r\n protected enabled: boolean = true;\r\n public visible: boolean = true;\r\n public materialScene: PointCloudMaterial = null;\r\n public materialPicker: PointCloudMaterial = null;\r\n public materials: PointCloudMaterial[];\r\n public root: any = null;\r\n protected pointclouds: PointCloudManager;\r\n protected _tightBoundingBox: any = null;\r\n public debugBoxColor = randomHexColor();\r\n\r\n constructor(pointclouds) {\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.points;\r\n }\r\n\r\n /** Get bounding box with global shift applied */\r\n get tightBoundingBox() {\r\n if (this._tightBoundingBox === null) {\r\n return this._tightBoundingBox;\r\n }\r\n\r\n let boundingBox = {\r\n min: new Vector3().add(this._tightBoundingBox.min).add(this.shift),\r\n max: new Vector3().add(this._tightBoundingBox.max).add(this.shift)\r\n };\r\n\r\n return boundingBox;\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 setEmpty(state) {\r\n this.empty = state;\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 /** @private */\r\n destroyWorker() {\r\n console.warn(\"Not implemented\");\r\n }\r\n\r\n dispose() {\r\n let nodes = this.getVisibleNodes();\r\n this.setState(false);\r\n nodes.forEach(node => {\r\n node.visible = false;\r\n node.dispose();\r\n });\r\n\r\n this.destroyWorker();\r\n }\r\n\r\n getVisibleNodes(nodeCondition = null) : CloudNode[] {\r\n let visibleNodes = [];\r\n if (!this.root) {\r\n return visibleNodes;\r\n }\r\n\r\n let stack = [this.root];\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 if (nodeCondition) {\r\n if (nodeCondition(object) === false) {\r\n continue;\r\n }\r\n }\r\n\r\n if ((object instanceof RawPointCloudRootNode) === false) {\r\n visibleNodes.push(object);\r\n }\r\n\r\n object.children.forEach(child => {\r\n stack.push(child);\r\n });\r\n }\r\n\r\n return visibleNodes;\r\n }\r\n\r\n updateBoundingBox(boundingBox) {\r\n let combined = mergeBoundingBoxes(this._tightBoundingBox, boundingBox);\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 updateClassifications(classification) {\r\n classification = new Set(classification);\r\n classification.forEach(item => {\r\n this.uniqueClassifications.add(item);\r\n });\r\n }\r\n\r\n generateEdgeMesh = (sizeX, sizeY, sizeZ) => {\r\n if (!isDevMode) {\r\n // Only generated in developer mode\r\n return null;\r\n }\r\n\r\n let vertexArray = [\r\n -0.5, 0.5, -0.5,\r\n -0.5, 0.5, 0.5,\r\n 0.5, 0.5, 0.5,\r\n 0.5, 0.5, -0.5,\r\n -0.5, -0.5, 0.5,\r\n -0.5, -0.5, -0.5,\r\n 0.5, -0.5, -0.5,\r\n 0.5, -0.5, 0.5,\r\n -0.5, 0.5, 0.5,\r\n -0.5, -0.5, 0.5,\r\n 0.5, 0.5, 0.5,\r\n -0.5, 0.5, 0.5,\r\n -0.5, -0.5, 0.5,\r\n 0.5, -0.5, 0.5,\r\n 0.5, -0.5, 0.5,\r\n 0.5, 0.5, 0.5,\r\n 0.5, 0.5, -0.5,\r\n 0.5, -0.5, -0.5,\r\n -0.5, 0.5, -0.5,\r\n 0.5, 0.5, -0.5,\r\n 0.5, -0.5, -0.5,\r\n -0.5, -0.5, -0.5,\r\n -0.5, -0.5, -0.5,\r\n -0.5, 0.5, -0.5\r\n ];\r\n\r\n const edgeVertices = new Float32Array(vertexArray.length);\r\n vertexArray.forEach((v,index) => {\r\n let scale;\r\n switch(index % 3) {\r\n case 0:\r\n scale = sizeX;\r\n break;\r\n case 1:\r\n scale = sizeY;\r\n break;\r\n case 2:\r\n scale = sizeZ;\r\n break;\r\n default:\r\n scale = 1.0;\r\n }\r\n\r\n edgeVertices[index] = v * scale;\r\n });\r\n\r\n const boxGeometry = new BufferGeometry();\r\n boxGeometry.setAttribute('position',\r\n new BufferAttribute(edgeVertices, 3));\r\n boxGeometry.center();\r\n\r\n let boxMaterial = new LineBasicMaterial({color: this.debugBoxColor});\r\n let boundingBox = new LineSegments(boxGeometry, boxMaterial);\r\n\r\n boundingBox.visible = false;\r\n\r\n return boundingBox;\r\n }\r\n}\r\n\r\nexport const mergeBoundingBoxes = (combined, current) => {\r\n if (!current) {\r\n return combined;\r\n }\r\n\r\n if (combined === null) {\r\n combined = {\r\n min: current.min.clone(),\r\n max: current.max.clone()\r\n };\r\n } else {\r\n combined = {\r\n min: new Vector3(\r\n Math.min(combined.min.x, current.min.x),\r\n Math.min(combined.min.y, current.min.y),\r\n Math.min(combined.min.z, current.min.z)\r\n ),\r\n max: new Vector3(\r\n Math.max(combined.max.x, current.max.x),\r\n Math.max(combined.max.y, current.max.y),\r\n Math.max(combined.max.z, current.max.z)\r\n )\r\n };\r\n }\r\n\r\n return combined;\r\n};","import {PointCloud} from './point-cloud';\r\nimport {RawPointCloudRootNode, RawPointCloudNode} from './raw-pointcloud-node';\r\nimport LocalScene from '../projections';\r\nimport { PythonExecutable } from '../../../executable';\r\nimport { Vector3 } from 'three';\r\n\r\nexport class RawPointCloud extends PointCloud {\r\n private workerExe: PythonExecutable;\r\n\r\n private file: any = null;\r\n private header: any = null;\r\n public loaded: any = false;\r\n private loading: boolean;\r\n private loadStart: any;\r\n private timeEnd: any;\r\n private byteCutoffSize = 10 * 1024**3;\r\n private pointsDataParsed = 0;\r\n private pointsDataArray = [];\r\n private numSampledPoints = 5 * 1000000;\r\n private minNumNodes = 100;\r\n private minPointSize;\r\n public generatingChunks: Boolean = false;\r\n public canReadData: Boolean = false;\r\n public percent;\r\n\r\n constructor(pointclouds) {\r\n super(pointclouds);\r\n\r\n this.minPointSize = Math.floor(this.numSampledPoints/this.minNumNodes);\r\n this.workerExe = new PythonExecutable();\r\n }\r\n\r\n get shift() {\r\n return LocalScene.origin;\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() {\r\n let box = this._tightBoundingBox;\r\n if (box === null) {\r\n return box;\r\n }\r\n\r\n let boundingBox = {\r\n min: new Vector3().add(box.min).sub(this.shift),\r\n max: new Vector3().add(box.max).sub(this.shift)\r\n };\r\n\r\n return boundingBox;\r\n }\r\n\r\n /** Get estimated bounding box using header information */\r\n get estimatedBoundingBox() {\r\n return {\r\n max: new Vector3(...this.header.maxs).sub(this.shift),\r\n min: new Vector3(...this.header.mins).sub(this.shift)\r\n };\r\n }\r\n\r\n get isRemoteFile() {\r\n return this.file.remote;\r\n }\r\n\r\n get fromJSON() {\r\n return this.file.fromJSON;\r\n }\r\n\r\n get isLargeFile() {\r\n let isLargeFile = this.header\r\n ? this.header.number_of_bytes > this.byteCutoffSize\r\n : false;\r\n\r\n return isLargeFile;\r\n }\r\n\r\n /** @private */\r\n destroyWorker() {\r\n this.workerExe.destroy();\r\n }\r\n\r\n fileLoadStart() {\r\n this.loading = true;\r\n this.loaded = false;\r\n this.updatePercent(0);\r\n }\r\n\r\n fileLoadFinish() {\r\n this.loading = false;\r\n this.loaded = true;\r\n this.timeEnd = performance.now();\r\n this.updatePercent(100);\r\n const elapsed = (this.timeEnd - this.loadStart) / 1000;\r\n console.log(`Point cloud loaded: ${this.file.name}. ${elapsed.toFixed(2)}s`);\r\n }\r\n\r\n fileLoadCancel() {\r\n this.loading = false;\r\n this.loaded = false;\r\n }\r\n\r\n fileLoadProgress() {\r\n let maxDataChunks = this.header.number_of_chunks;\r\n let percent = this.pointsDataParsed / maxDataChunks;\r\n percent = Math.round(percent * 1000) / 10.0;\r\n percent = Math.min(100, percent);\r\n this.updatePercent(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 loadFile(file) {\r\n this.file = file;\r\n\r\n this.pointsDataParsed = 0;\r\n this.pointsDataArray = [];\r\n this.canReadData = true;\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\r\n this.fileLoadStart();\r\n }\r\n\r\n fileLoadFinished(success) {\r\n if (success) {\r\n this.fileLoadFinish();\r\n } else {\r\n this.fileLoadCancel();\r\n }\r\n }\r\n\r\n launchExecutable() {\r\n this.loadStart = performance.now();\r\n this.generatingChunks = true;\r\n\r\n const lasFilePath = this.file.path;\r\n const projectionsUnits = LocalScene.dataProjectionUnits;\r\n\r\n let isValid = false;\r\n let commands = [\r\n \"-p\", \"convert_engine_las\",\r\n \"--input_file\", lasFilePath,\r\n \"--units\", projectionsUnits,\r\n \"--min_chunk_size\", this.minPointSize,\r\n \"--max_points\", this.numSampledPoints\r\n ];\r\n\r\n this.workerExe.run({\r\n command: commands,\r\n parseJSON: false,\r\n onData: (buffer, keyword) => {\r\n const callback = response => {\r\n let {type, data} = response;\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\r\n // Decode buffer data asynchronously\r\n let payload = {buffer: buffer.buffer, keyword};\r\n this.pointclouds.pushToWorkerQueue(payload, callback);\r\n\r\n isValid = true;\r\n },\r\n onClose: () => {\r\n if (isValid) {\r\n return;\r\n }\r\n\r\n console.error(`Error loading point cloud: ${this.file.path}`);\r\n this.viewer.showMessage(`Error loading point cloud: ${this.file.name}`, {\r\n variant: \"error\"\r\n });\r\n this.fileMissing = true;\r\n this.fileLoadFinished(true);\r\n }\r\n });\r\n }\r\n\r\n parseHeaderResponse(data) {\r\n this.header = data;\r\n this.root = new RawPointCloudRootNode(this);\r\n\r\n if (!this.isLargeFile) {\r\n return;\r\n }\r\n\r\n console.warn(`Loading large point cloud: ${this.file.path}`);\r\n this.viewer.showMessage(`Large point cloud file detected: ${this.file.name}`, {\r\n variant: \"warning\"\r\n });\r\n }\r\n\r\n parsePointsResponse(data) {\r\n this.pointsDataArray.push(data);\r\n }\r\n\r\n parseAvailableChunks() {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n if (this.pointsDataArray.length === 0) {\r\n return;\r\n }\r\n\r\n const maxDataChunks = this.header?.number_of_chunks;\r\n const isLastChunk = (this.pointsDataParsed + 1) === maxDataChunks;\r\n const data = this.pointsDataArray.shift();\r\n this.pointsDataParsed += 1;\r\n\r\n // Update loaded percent\r\n this.fileLoadProgress();\r\n\r\n // Add new node from json response\r\n this.addNodeFromData(data);\r\n\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n this.pointclouds.updateMinimapExtent();\r\n\r\n if (!this.fromJSON) {\r\n let bbox = this.estimatedBoundingBox;\r\n this.pointclouds.zoomToExtent(bbox, false, false);\r\n }\r\n\r\n if (isLastChunk) {\r\n this.fileLoadFinished(true);\r\n }\r\n }\r\n\r\n addNodeFromData(data) {\r\n // Convert array to vector\r\n data.offset = new Vector3(...data.offset);\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 data.gpu_index = new Int32Array(data.numPoints);\r\n\r\n if (this.enabled) {\r\n // Add new node to pointcloud\r\n let node = new RawPointCloudNode(this, this.root);\r\n node.loadFromData(data);\r\n }\r\n }\r\n}\r\n","import {CloudNode} from \"./cloud-node\";\r\nimport {readFileBuffer} from \"../file-system-loader\";\r\nimport { EncompassPointCloud } from '.';\r\nimport {\r\n Points,\r\n Vector3\r\n} from 'three';\r\n\r\nexport class EncompassPointCloudNode extends CloudNode {\r\n protected cloud: EncompassPointCloud;\r\n public parent: EncompassPointCloudNode;\r\n private level: any;\r\n private _children = null;\r\n\r\n constructor(cloud: EncompassPointCloud, parent, name, level, center, size) {\r\n super();\r\n\r\n this.cloud = cloud;\r\n this.parent = parent;\r\n this.name = name;\r\n this.level = level;\r\n this.size = size;\r\n this._center = center;\r\n }\r\n\r\n /** Get children nodes if they exist, or assume all 8 children exist */\r\n get children() {\r\n if (this._children === null) {\r\n this.clearChildNodes();\r\n\r\n for (var i = 0; i < 8; i++) {\r\n let child = this.getChildAtIndex(i);\r\n this.addChildNode(child);\r\n }\r\n }\r\n\r\n return this._children;\r\n }\r\n\r\n get shift() {\r\n return this.cloud.shift;\r\n }\r\n\r\n get precision() {\r\n return this.cloud.precision;\r\n }\r\n\r\n addToScene() {\r\n // Create pointcloud object\r\n let pointsScene = new Points(this.geometry,\r\n this.cloud.materialScene);\r\n let pointsPicker = new Points(this.geometry,\r\n this.cloud.materialPicker);\r\n\r\n pointsScene.visible = false;\r\n pointsPicker.visible = false;\r\n\r\n // Create bounding box object;\r\n let boundingBox = this.cloud.generateEdgeMesh(\r\n this.size, this.size, this.size);\r\n\r\n this.addCloudData(pointsPicker, pointsScene, boundingBox);\r\n }\r\n\r\n getGeometry(data) {\r\n this.setGeometry(data);\r\n\r\n this.numPoints = data.numPoints;\r\n this.tightBoundingBox = {\r\n min: data.xyz_min,\r\n max: data.xyz_max\r\n };\r\n\r\n // Update unique values and min/max values\r\n this.cloud.updateClassifications(data.classification);\r\n this.cloud.updateColorLimits(data.rgb_max);\r\n this.cloud.updateIntensityRange(data.intensity_min, data.intensity_max);\r\n this.cloud.updateBoundingBox(this.tightBoundingBox);\r\n\r\n this.loaded = true;\r\n this.loading = false;\r\n\r\n // console.log(`Loaded geometry [${this.name}]`);\r\n }\r\n\r\n getBinaryData() {\r\n let dataPath = this.cloud.getDataPath(this.name);\r\n\r\n let onSuccess = (data: Buffer) => {\r\n this.sendToWorker({\r\n buffer: data,\r\n precision: this.precision,\r\n shift: this.shift\r\n });\r\n };\r\n\r\n let onError = () => {\r\n if (this.level === 1) {\r\n return;\r\n }\r\n\r\n this.parent.removeChildNode(this);\r\n };\r\n\r\n let path = `${dataPath}/${this.name}`;\r\n\r\n // Read node data\r\n readFileBuffer(path, this.cloud.isRemoteFile)\r\n .then(onSuccess)\r\n .catch(onError);\r\n }\r\n\r\n sendToWorker(data) {\r\n let workerPool = this.cloud.workerPool;\r\n\r\n let worker = workerPool.getWorker();\r\n\r\n worker.onmessage = event => {\r\n const data = event.data;\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 this.getGeometry(data);\r\n workerPool.returnWorker(worker);\r\n };\r\n\r\n workerPool.sendMessage(worker, data, [data.buffer]);\r\n }\r\n\r\n getChildNameAtIndex(index) {\r\n return `${this.name}${index}`;\r\n }\r\n\r\n getChildAtIndex(index) {\r\n let childName = this.getChildNameAtIndex(index);\r\n let childSize = this.size / 2.0;\r\n let childLevel = this.level + 1;\r\n\r\n let z = Math.floor(index / 4);\r\n let y = Math.floor((index - (4 * z)) / 2);\r\n let x = Math.floor(index % 2);\r\n\r\n let childCenter = new Vector3(\r\n this._center.x + (x - 0.5) * childSize,\r\n this._center.y + (y - 0.5) * childSize,\r\n this._center.z + (z - 0.5) * childSize\r\n );\r\n\r\n return new EncompassPointCloudNode(this.cloud, this, childName,\r\n childLevel, childCenter, childSize);\r\n }\r\n\r\n addChildNode(node) {\r\n this._children.push(node);\r\n }\r\n\r\n clearChildNodes() {\r\n if (this._children) {\r\n this._children.forEach(child => {\r\n child = null;\r\n });\r\n }\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 load() {\r\n if ((this.loaded) || (this.loading)) {\r\n return;\r\n }\r\n\r\n this.loading = true;\r\n this.getBinaryData();\r\n }\r\n}\r\n","import { isDevMode } from \"../../electron-modules\";\r\n\r\nexport class WorkerPool {\r\n private path;\r\n private workers = [];\r\n\r\n constructor(workerPath, numDefaultWorkers=1) {\r\n this.path = workerPath;\r\n this.createDefaultWorkers(numDefaultWorkers);\r\n }\r\n\r\n sendMessage(worker, data, transferables=null) {\r\n worker.postMessage(data, transferables);\r\n }\r\n\r\n getWorker() {\r\n if (this.workers.length === 0) {\r\n let worker = new Worker(this.path);\r\n this.returnWorker(worker);\r\n }\r\n\r\n let worker = this.workers.pop();\r\n\r\n return worker;\r\n }\r\n\r\n returnWorker(worker) {\r\n try {\r\n this.workers.push(worker);\r\n } catch (error) {\r\n return;\r\n }\r\n }\r\n\r\n\r\n createDefaultWorkers(numDefaultWorkers) {\r\n let newWorkers = [];\r\n for (let i=0; i {\r\n this.returnWorker(worker);\r\n });\r\n }\r\n\r\n terminateWorkers() {\r\n this.workers.forEach(worker => {\r\n worker.terminate();\r\n });\r\n\r\n this.workers = [];\r\n }\r\n}\r\n\r\nexport class WorkerQueue {\r\n private pool: WorkerPool;\r\n private maxAsyncWorkers;\r\n private waitForExit = false;\r\n public numRunning = 0;\r\n private queue = [];\r\n\r\n constructor(workerURL, numWorkers, waitForExit=false) {\r\n let workerPath = `${process.env.PUBLIC_URL}/${workerURL}`;\r\n this.pool = new WorkerPool(workerPath, numWorkers);\r\n this.maxAsyncWorkers = numWorkers;\r\n this.waitForExit = waitForExit;\r\n\r\n if (waitForExit && isDevMode) {\r\n console.warn(\"WorkerQueue requires {workerFinished: true} message to stop\");\r\n }\r\n }\r\n\r\n get running() {\r\n return this.numRunning > 0;\r\n }\r\n\r\n push(data, callback, transferables=[]) {\r\n this.queue.push([data, callback, transferables]);\r\n }\r\n\r\n /** @private */\r\n finish(worker) {\r\n this.numRunning = this.numRunning - 1;\r\n this.pool.returnWorker(worker);\r\n }\r\n\r\n process() {\r\n if (this.numRunning >= this.maxAsyncWorkers) {\r\n return;\r\n }\r\n\r\n if (this.queue.length === 0) {\r\n return;\r\n }\r\n\r\n this.numRunning = this.numRunning + 1;\r\n\r\n // Grab queue values\r\n let [workerData, workerCallback, transferables] = this.queue.shift();\r\n\r\n // Grab next available worker\r\n let worker = this.pool.getWorker();\r\n\r\n worker.onmessage = event => {\r\n let data = event.data;\r\n\r\n if (this.waitForExit) {\r\n if (data.workerFinished) {\r\n // Return worker to queue\r\n this.finish(worker);\r\n return;\r\n } else {\r\n // Execute callback\r\n workerCallback(event.data);\r\n }\r\n } else {\r\n // Execute callback\r\n workerCallback(event.data);\r\n\r\n // Return worker to queue\r\n this.finish(worker);\r\n }\r\n };\r\n\r\n // Submit data to webworker\r\n this.pool.sendMessage(worker, workerData, transferables);\r\n }\r\n}\r\n","import {PointCloud} from './point-cloud';\r\nimport {EncompassPointCloudNode} from \"./encompass-pointcloud-node\";\r\nimport {readFileJSON} from \"../file-system-loader\";\r\nimport LocalScene from '../projections';\r\nimport { Vector3 } from 'three';\r\nimport { WorkerPool } from '../worker';\r\n\r\nexport class EncompassPointCloud extends PointCloud {\r\n public workerPool: WorkerPool;\r\n private structure = null;\r\n public nodeCacheSize = 200;\r\n private cloudInfo: any;\r\n private numberOfPoints: any;\r\n private _shift: any;\r\n\r\n constructor(parent) {\r\n super(parent);\r\n\r\n const workerURL = \"workers/pointcloud-decoder-node.js\";\r\n let workerPath = `${process.env.PUBLIC_URL}/${workerURL}`;\r\n this.workerPool = new WorkerPool(workerPath);\r\n }\r\n\r\n get dataDir() {\r\n return this.structure.path;\r\n }\r\n\r\n get precision() {\r\n return this.cloudInfo.precision;\r\n }\r\n\r\n get folderDepth() {\r\n return this.cloudInfo.folderDepth;\r\n }\r\n\r\n get spacing() {\r\n return this.cloudInfo.spacing;\r\n }\r\n\r\n get isRemoteFile() {\r\n return this.structure.remote;\r\n }\r\n\r\n get fromJSON() {\r\n return this.structure.fromJSON;\r\n }\r\n\r\n get size() {\r\n return this.root.size;\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 /** @private */\r\n destroyWorker() {\r\n this.workerPool.terminateWorkers();\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 setBoundingBox(boundingBox) {\r\n if (!boundingBox) {\r\n return;\r\n }\r\n\r\n this._tightBoundingBox = boundingBox;\r\n }\r\n\r\n loadNodes(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 let path = `${structure.path}/r.idx`;\r\n\r\n // Read index data\r\n readFileJSON(path, this.isRemoteFile)\r\n .then(data => {\r\n // Decode our root info\r\n this.decodeIndexData(data);\r\n })\r\n .catch(() => {\r\n this.fileMissing = true;\r\n console.error(`Error loading point cloud: ${structure.path}`);\r\n this.viewer.showMessage(`Error loading point cloud: ${structure.name}`, {\r\n variant: \"error\"\r\n });\r\n });\r\n }\r\n\r\n decodeIndexData(data) {\r\n // Decode our root index file and store info about our local projection\r\n let cloudInfo = {\r\n spacing: data.hasOwnProperty('spacing') ? data.spacing : Math.sqrt(2) * data.size / 250.0,\r\n folderDepth: data.hasOwnProperty('hierarchy_step_size') ? data.hierarchy_step_size : null,\r\n precision: data.hasOwnProperty('precision') ? data.precision : 0.005,\r\n offset: new Vector3(...data.point_offset),\r\n scale: data.point_scale\r\n };\r\n\r\n let offset = cloudInfo.offset;\r\n let availableNodes = data.hasOwnProperty('node_structure') ? data.node_structure : null;\r\n let numberOfPoints = data.hasOwnProperty('total_points') ? data.total_points : null;\r\n\r\n // Get our tight bounding box if available\r\n let tightBoundingBox = null;\r\n if (\"tight_bounding_box\" in data) {\r\n let box = data.tight_bounding_box;\r\n tightBoundingBox = {\r\n min: new Vector3(...box.min).sub(offset),\r\n max: new Vector3(...box.max).sub(offset)\r\n };\r\n }\r\n\r\n // Setting some cloud metadata\r\n this.numberOfPoints = numberOfPoints;\r\n this.cloudInfo = cloudInfo;\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 this.root = new EncompassPointCloudNode(this, null, \"r\", 1,\r\n nodeCenter, nodeSize);\r\n\r\n this.buildTreeLegacy(availableNodes);\r\n this.setBoundingBox(tightBoundingBox);\r\n this.pointclouds.updateMinimapExtent();\r\n\r\n if (!this.fromJSON) {\r\n let bbox = this.tightBoundingBox;\r\n this.pointclouds.zoomToExtent(bbox, false, false);\r\n }\r\n }\r\n\r\n /** Legacy code for older pointclouds. Should be removed eventually */\r\n buildTreeLegacy(availableNodes) {\r\n // Old file format. Fallback method will add child nodes as needed\r\n if (!availableNodes) {\r\n return;\r\n }\r\n\r\n // Too slow, dont bother.\r\n // NOTE: remove completely soon. very slow past this cutoff, but\r\n // causes weird artifacts if removed completely\r\n let keys = Object.keys(availableNodes);\r\n let cutoff = 50000;\r\n if (keys.length > cutoff) {\r\n return;\r\n }\r\n\r\n // Make sure our root node was passed in\r\n let rootNodeExists = \"r\" in availableNodes;\r\n if (!rootNodeExists) {\r\n return;\r\n }\r\n\r\n let totalAdded = 1;\r\n let stack = [this.root];\r\n\r\n while (stack.length > 0) {\r\n let object = stack.shift();\r\n object.clearChildNodes();\r\n object.numPoints = availableNodes[object.name];\r\n\r\n for (var i = 0; i < 8; i++) {\r\n let childName = object.getChildNameAtIndex(i);\r\n let childExists = childName in availableNodes;\r\n\r\n if (childExists) {\r\n // This node exists in our structure, so we push to the child array\r\n // of the parent node, and append to our stack\r\n let child = object.getChildAtIndex(i);\r\n object.addChildNode(child);\r\n stack.push(child);\r\n totalAdded++;\r\n }\r\n }\r\n }\r\n\r\n console.log(`Point cloud hierarchy loaded. ${totalAdded} nodes found`);\r\n }\r\n}\r\n","// Binary heap implementation from:\r\n// http://eloquentjavascript.net/appendix2.html\r\n\r\nexport function BinaryHeap(scoreFunction) {\r\n this.content = [];\r\n this.scoreFunction = scoreFunction;\r\n}\r\n\r\nBinaryHeap.prototype = {\r\n push: function (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: function () {\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: function() {\r\n return this.content[0];\r\n },\r\n\r\n remove: function (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 size: function () {\r\n return this.content.length;\r\n },\r\n\r\n bubbleUp: function (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: function (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};\r\n","import {createSlice, PayloadAction} from '@reduxjs/toolkit';\r\nimport {Classification, classifications} from \"../classifications\";\r\nimport {storage} from \"../electron-modules\";\r\nimport {cloneDeep} from 'lodash';\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 Settings {\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 cloudSize: number;\r\n cloudMaxPoints: number;\r\n cloudDistance: number;\r\n classifications: ClassificationSetting[];\r\n switched: boolean;\r\n orthoOpacity: number;\r\n}\r\n\r\nconst defaultIntensityClip = {min: 0, max: 1};\r\n\r\nconst defaultHeightClip = {min: 0, max: 1};\r\n\r\nconst defaultClassifications = classifications.map(classification => ({\r\n visible: true,\r\n available: false,\r\n ...classification\r\n}));\r\n\r\nconst loadSavedDefaults = () => {\r\n const result = storage.get(\"default-settings\");\r\n return result.status ? result.data : {};\r\n};\r\n\r\nconst saveSettingsDefaults = (state) => {\r\n const copy = cloneDeep(state);\r\n delete copy['classifications'];\r\n storage.set(\"default-settings\", copy);\r\n};\r\n\r\nconst applySavedDefaults = (state) => {\r\n const defaults = loadSavedDefaults();\r\n const keys = Object.keys(defaults);\r\n keys.forEach(key => {\r\n if (state.hasOwnProperty(key)) {\r\n state[key] = defaults[key];\r\n }\r\n });\r\n};\r\n\r\nexport const settingsSlice = createSlice({\r\n name: 'settings',\r\n initialState: {\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: 5000000,\r\n cloudDistance: 100,\r\n cloudSize: 1.5,\r\n switched: false,\r\n drawerOpen: true,\r\n heightClip: defaultHeightClip,\r\n intensityClip: defaultIntensityClip,\r\n classifications: defaultClassifications,\r\n orthoOpacity: 1.0\r\n } as Settings,\r\n reducers: {\r\n applySavedDefaults: (state, action) => {\r\n applySavedDefaults(state);\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 changeOrthoOpacity: (state, action: PayloadAction) => {\r\n state.orthoOpacity = 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 changeCloudSize: (state, action: PayloadAction) => {\r\n state.cloudSize = 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 changeDrawerOpen: (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 changeOrthoOpacity,\r\n changeCloudDistance,\r\n changeCloudMaxPoints,\r\n changeCloudSize,\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 changeDrawerOpen,\r\n changeArrowMarkers\r\n} = settingsSlice.actions;\r\n\r\nexport default settingsSlice.reducer;\r\n\r\nexport const selectOpacity = state => state.settings.opacity;\r\nexport const selectOrthoOpacity = state => state.settings.orthoOpacity;\r\nexport const selectCloudDistance = state => state.settings.cloudDistance;\r\nexport const selectCloudMaxPoints = state => state.settings.cloudMaxPoints;\r\nexport const selectCloudSize = state => state.settings.cloudSize;\r\nexport const selectHeightClip = state => state.settings.heightClip;\r\nexport const selectIntensityClip = state => state.settings.intensityClip;\r\nexport const selectColorMap = state => state.settings.colorMap;\r\nexport const selectColorType = state => state.settings.colorType;\r\nexport const selectDynamicSize = state => state.settings.dynamicSize;\r\nexport const selectCircularPoints = state => state.settings.circularPoints;\r\nexport const selectViewerSwitched = state => state.settings.switched;\r\nexport const selectSelectedTab = state => state.settings.activeTab;\r\nexport const selectDrawerOpen = state => state.settings.drawerOpen;\r\nexport const selectArrowMarkers = state => state.settings.arrowMarkers;\r\nexport const selectAvailableClassifications = state => state.settings.classifications\r\n .filter(classification => classification.available);\r\nexport const selectClassificationVisibilities = state => state.settings.classifications\r\n .map(classification => ({\r\n visible: classification.visible,\r\n id: classification.id\r\n }));\r\n\r\n","import { MathUtils } from \"three/src/math/MathUtils\";\r\nimport { Vector3 } from \"three/src/math/Vector3\";\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 setPointScale = (viewer, mesh, buffer = 1.0) => {\r\n if (!mesh) {\r\n return;\r\n }\r\n\r\n const fov = MathUtils.degToRad(Math.max(60, viewer.camera.fov));\r\n const screenHeight = viewer.height;\r\n\r\n const distance = Math.max(1.0, mesh.position.distanceTo(viewer.camera.position));\r\n const projFactor = getProjFactor(fov, distance, screenHeight);\r\n const scale = 50 / projFactor;\r\n\r\n mesh.scale.set(scale, scale, scale);\r\n mesh.geometry.computeBoundingSphere();\r\n mesh.geometry.boundingSphere.radius *= buffer;\r\n};\r\n\r\nexport const toScreenPosition = (viewer, position) => {\r\n var vector = new Vector3();\r\n vector.set(position.x, position.y, position.z);\r\n vector.project(viewer.camera);\r\n\r\n vector.x = Math.round((vector.x + 1) * viewer.width / 2);\r\n vector.y = Math.round((-vector.y + 1) * viewer.height / 2);\r\n vector.z = 0;\r\n\r\n return vector;\r\n};\r\n\r\nexport const eventToPixel = (event) => {\r\n let uv = new Vector3();\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 return uv;\r\n};\r\n","import { readFileBuffer } from \"../file-system-loader\";\r\nimport {\r\n DataProjectionCoordinate,\r\n getInvertedEuler,\r\n SceneCoordinate,\r\n SphericalPosition\r\n} from '../projections';\r\nimport { Viewer } from '../main';\r\nimport { isStaticSite } from '../../../electron-modules';\r\nimport { AssetType } from '../../../redux/assets-slice';\r\nimport { extentFromPoints } from '../aerial/map';\r\nimport slash from 'slash';\r\nimport {\r\n AmbientLight,\r\n BoxGeometry,\r\n DoubleSide,\r\n Euler,\r\n LinearFilter,\r\n MathUtils,\r\n Matrix4,\r\n Mesh,\r\n MeshBasicMaterial,\r\n Object3D,\r\n PlaneGeometry,\r\n Scene,\r\n Texture,\r\n Vector2,\r\n Vector3\r\n} from 'three';\r\nimport { interp1D, roundDigit } from \"../misc\";\r\nimport { planeFromVectors } from \"../utilities/polygon\";\r\nimport { PanoramicMaterial } from \"../materials\";\r\n\r\nexport interface ImagePixel {\r\n u: number,\r\n v: number\r\n}\r\n\r\nexport interface CameraLoadOptions {\r\n onLoaded?: Function\r\n fov?: number\r\n angles?: [number, number]\r\n position?: SceneCoordinate\r\n direction?: Vector3\r\n}\r\n\r\nclass ImagePosition {\r\n private _value;\r\n private image: CameraImage;\r\n\r\n constructor(image: CameraImage, position) {\r\n this.image = image;\r\n this._value = 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 height() {\r\n return this.image.height;\r\n }\r\n\r\n get uncorrectedEuler() {\r\n return this.image.rotation._euler;\r\n }\r\n\r\n get value() {\r\n let offset = new Vector3()\r\n .copy(this.offset)\r\n .applyEuler(this.image.rotation.eulerCSV);\r\n\r\n let position = new Vector3()\r\n .copy(this._value)\r\n .add(offset);\r\n\r\n return position;\r\n }\r\n\r\n get viewer() {\r\n return new DataProjectionCoordinate(this.value).toScene();\r\n }\r\n\r\n get marker() {\r\n const offset = new Vector3(0, 0, this.height);\r\n return this.viewer.sub(offset);\r\n }\r\n\r\n get aerial() {\r\n return new SceneCoordinate(this.value).toAerial();\r\n }\r\n}\r\n\r\nclass ImageRotation {\r\n private array: [];\r\n public _euler: THREE.Euler;\r\n private image: CameraImage;\r\n\r\n constructor(image: CameraImage, rotation) {\r\n this.image = image;\r\n this.array = rotation;\r\n this._euler = new Euler(\r\n -1 * MathUtils.degToRad(rotation[0]),\r\n -1 * MathUtils.degToRad(rotation[1]),\r\n -1 * MathUtils.degToRad(rotation[2])\r\n );\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 const angles = this.image.adjustment;\r\n return 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\r\n get euler() {\r\n let rotationWithTransform = multiplyRotations(this._euler, this.matrix);\r\n let rotationWithAdjustment = multiplyRotations(rotationWithTransform, this.adjustment);\r\n\r\n let euler = new Euler()\r\n .setFromRotationMatrix(rotationWithAdjustment);\r\n\r\n return euler;\r\n }\r\n\r\n get viewer() {\r\n return new Euler().copy(this.euler);\r\n }\r\n\r\n get eulerCSV() {\r\n return this._euler;\r\n }\r\n\r\n get eulerDegrees() {\r\n let degrees = new Euler();\r\n degrees.x = -1 * MathUtils.radToDeg(this.euler.x);\r\n degrees.y = -1 * MathUtils.radToDeg(this.euler.y);\r\n degrees.z = -1 * MathUtils.radToDeg(this.euler.z);\r\n return degrees;\r\n }\r\n\r\n get eulerCsvInvert() {\r\n return getInvertedEuler(this.eulerCSV);\r\n }\r\n}\r\n\r\nexport class CameraImage {\r\n public id;\r\n public csv;\r\n public name;\r\n public path;\r\n public height;\r\n public config;\r\n public adjustment;\r\n public isRemoteFile;\r\n public object;\r\n public enabled;\r\n public loaded = false;\r\n public loading = false;\r\n public img;\r\n public ctx;\r\n public canvas;\r\n public materials;\r\n public geometry;\r\n public fromJSON: boolean;\r\n\r\n public cameraList: CameraList;\r\n public position: ImagePosition;\r\n public rotation: ImageRotation;\r\n\r\n constructor(cameraList, data) {\r\n this.cameraList = cameraList;\r\n\r\n this.id = data.id;\r\n this.csv = data.csv;\r\n this.name = data.name;\r\n this.path = data.path;\r\n this.height = data.height;\r\n this.adjustment = data.adjustment;\r\n this.isRemoteFile = data.remote;\r\n this.config = data.config;\r\n this.fromJSON = data.fromJSON;\r\n\r\n this.position = new ImagePosition(this, data.position);\r\n this.rotation = new ImageRotation(this, data.rotation);\r\n\r\n this.reset();\r\n }\r\n\r\n get scene() {\r\n return this.cameraList.scene;\r\n }\r\n\r\n get camera() {\r\n return this.cameraList.camera;\r\n }\r\n\r\n get matrix() {\r\n return this.cameraList.matrix;\r\n }\r\n\r\n get minimap() {\r\n return this.cameraList.minimap;\r\n }\r\n\r\n get mimeType() {\r\n let extension = this.name.split(\".\").slice(-1)[0].toLowerCase();\r\n let imageTypes = {\r\n \"jpg\": \"image/jpeg\",\r\n \"jpeg\": \"image/jpeg\",\r\n \"png\": \"image/png\"\r\n };\r\n\r\n return imageTypes[extension] || null;\r\n }\r\n\r\n get viewer() {\r\n return this.cameraList.viewer;\r\n }\r\n\r\n get controls() {\r\n return this.cameraList.controls;\r\n }\r\n\r\n get imageWidth() {\r\n return this.img ? this.img.width : 0;\r\n }\r\n\r\n get imageHeight() {\r\n return this.img ? this.img.height : 0;\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) : [boolean, ImagePixel] {\r\n console.warn(\"Not implemented\");\r\n return [true, {u: 0, v: 0}];\r\n }\r\n\r\n /** @private */\r\n setCameraPosition() {\r\n this.camera.position.copy(this.position.viewer);\r\n this.object.position.copy(this.position.viewer);\r\n this.object.rotation.copy(this.rotation.viewer);\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.angles) {\r\n this.controls.angles = opts.angles;\r\n } else if (opts.direction) {\r\n this.controls.angles = this.directionToCameraAngle(\r\n opts.direction);\r\n } else if (opts.position) {\r\n this.controls.angles = this.positionToCameraAngle(\r\n this.object.position, opts.position);\r\n }\r\n }\r\n\r\n /** @private */\r\n directionToCameraAngle = (direction) : [number, number] => {\r\n return this.positionToCameraAngle(new Vector3(), direction);\r\n };\r\n\r\n /** @private */\r\n positionToCameraAngle = (cameraPos, position) : [number, number] => {\r\n let sphere = new SphericalPosition()\r\n .fromVectors(cameraPos, position);\r\n\r\n return [\r\n MathUtils.degToRad(sphere.theta),\r\n MathUtils.degToRad(90 - sphere.phi),\r\n ] as [number, number];\r\n };\r\n\r\n\r\n /** @private */\r\n grabImageFromPath() {\r\n return new Promise((resolve, reject) => {\r\n this.img = new Image();\r\n\r\n this.img.addEventListener('load', () => {\r\n resolve(true);\r\n });\r\n\r\n let onSuccess = buffer => {\r\n // Load image source from buffer\r\n let arrayBufferView = new Uint8Array(buffer);\r\n let blob = new Blob([arrayBufferView], {\r\n type: this.mimeType\r\n });\r\n this.img.src = URL.createObjectURL(blob);\r\n };\r\n\r\n let onError = () => {\r\n reject();\r\n };\r\n\r\n readFileBuffer(this.path, this.isRemoteFile)\r\n .then(onSuccess)\r\n .catch(onError);\r\n });\r\n }\r\n\r\n setObjectVisible(state) {\r\n this.object.visible = state;\r\n }\r\n\r\n loadCamera(opts: CameraLoadOptions) {\r\n if (this.enabled) {\r\n this.cameraList.setNormalCamera();\r\n this.setCameraParameters(opts);\r\n this.minimap.setActiveCamera(this.id);\r\n\r\n if (opts.onLoaded) {\r\n opts.onLoaded();\r\n }\r\n\r\n return;\r\n }\r\n\r\n this.enabled = true;\r\n this.loaded = false;\r\n this.loading = true;\r\n\r\n this.generateObject();\r\n this.setObjectVisible(false);\r\n this.object.visible = false;\r\n\r\n this.grabImageFromPath()\r\n .then(async () => {\r\n // Clear current camera, move to new position\r\n this.cameraList.clearImages(this);\r\n this.cameraList.setNormalCamera();\r\n this.cameraList.setWaitForCameras(false);\r\n\r\n this.setCameraPosition();\r\n this.setCameraParameters(opts);\r\n this.loadImageData();\r\n this.setObjectVisible(true);\r\n\r\n this.minimap.setActiveCamera(this.id);\r\n\r\n this.loaded = true;\r\n this.loading = false;\r\n\r\n if (opts.onLoaded) {\r\n opts.onLoaded();\r\n }\r\n })\r\n .catch(() => {\r\n this.reset();\r\n\r\n console.error(`Error loading image: ${this.path}`);\r\n this.viewer.showMessage(`Error loading image: ${this.name}`, {\r\n variant: \"error\"\r\n });\r\n\r\n if (!this.cameraList.current) {\r\n // Nothing to fall back to, so just go to orbit\r\n this.cameraList.setOrbitCamera();\r\n }\r\n })\r\n .finally(() => {\r\n this.cameraList.setWaitForCameras(false);\r\n this.cameraList.updateArrowNavigation();\r\n });\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.eulerCSV, angleEuler);\r\n const euler = new Euler()\r\n .setFromRotationMatrix(tempRotation);\r\n\r\n this.object.rotation.copy(euler);\r\n }\r\n\r\n /** @private */\r\n generateObject() {\r\n console.warn(\"Not implemented\");\r\n }\r\n\r\n /** @private */\r\n loadImageData() {\r\n console.warn(\"Not implemented\");\r\n }\r\n\r\n destroy() {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n if (this.object) {\r\n this.scene.remove(this.object);\r\n }\r\n\r\n this.materials.forEach(material => {\r\n if (material.map) {\r\n material.map.dispose();\r\n }\r\n material.dispose();\r\n });\r\n\r\n if (this.geometry) {\r\n this.geometry.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.materials = [];\r\n this.geometry = null;\r\n }\r\n}\r\n\r\nexport class PanoramicImage extends CameraImage {\r\n constructor(cameraList, data) {\r\n super(cameraList, data);\r\n }\r\n\r\n pixelToDirection(pixel: ImagePixel) : Vector3 {\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) : [boolean, ImagePixel] {\r\n const inverse = getInvertedEuler(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 [true, {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 = interp1D(xyz1[0], xyz2[0], steps);\r\n let _y = interp1D(xyz1[1], xyz2[1], steps);\r\n let _z = interp1D(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 /** @private */\r\n loadImageData() {\r\n let imageTexture = new Texture();\r\n imageTexture.image = this.img;\r\n imageTexture.minFilter = LinearFilter;\r\n imageTexture.needsUpdate = true;\r\n\r\n this.object.material\r\n .setTexture(imageTexture);\r\n }\r\n\r\n /** @private */\r\n generateObject() {\r\n const material = new PanoramicMaterial();\r\n const geometry = new BoxGeometry(10, 10, 10);\r\n const mesh = new Mesh(geometry, material);\r\n this.object = mesh;\r\n this.scene.add(this.object);\r\n }\r\n}\r\n\r\nexport class PlanarImage extends CameraImage {\r\n constructor(cameraList, data) {\r\n super(cameraList, data);\r\n }\r\n\r\n get fovX() {\r\n return 2.0 * Math.atan((this.config.width / 2) / this.config.fx);\r\n }\r\n\r\n get fovY() {\r\n return 2.0 * Math.atan((this.config.height / 2) / this.config.fy);\r\n }\r\n\r\n get centerOffset() : Euler {\r\n /** Calculate the rotation causes by non-centered planars */\r\n let x = this.fovY * (this.config.cy - this.config.height / 2)\r\n / this.config.height;\r\n\r\n let y = this.fovX * (this.config.cx - this.config.width / 2)\r\n / this.config.width;\r\n\r\n return new Euler(x, y, 0);\r\n }\r\n\r\n pixelToDirection(pixel: ImagePixel) : Vector3 {\r\n let x = -1 * (pixel.u - this.config.width/2) / this.config.fx;\r\n let y = (pixel.v - this.config.height/2) / this.config.fy;\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.centerOffset)\r\n .applyEuler(this.rotation.euler);\r\n\r\n return direction;\r\n }\r\n\r\n directionToPixel(direction: Vector3, margin=50) : [boolean, ImagePixel] {\r\n const offset = getInvertedEuler(this.centerOffset);\r\n const inverse = getInvertedEuler(this.rotation.euler);\r\n\r\n const imageDirection = direction.clone()\r\n .applyEuler(inverse)\r\n .applyEuler(offset);\r\n\r\n let xyz = new Vector3()\r\n .copy(imageDirection)\r\n .divideScalar(imageDirection.z);\r\n\r\n let u = -xyz.x * this.config.fx + this.config.width/2;\r\n let v = xyz.y * this.config.fy + this.config.height/2;\r\n\r\n let outOfBounds = (u < -margin)\r\n || (v < -margin)\r\n || (u > (this.config.width + margin))\r\n || (v > (this.config.height + margin));\r\n\r\n if (outOfBounds) {\r\n return [false, {u: 0, v: 0}];\r\n }\r\n\r\n return [true, {u, v}];\r\n }\r\n\r\n /** @private */\r\n loadImageData() {\r\n let imageTexture = new Texture();\r\n imageTexture.image = this.img;\r\n imageTexture.flipY = true;\r\n imageTexture.needsUpdate = true;\r\n\r\n this.materials[0].map = imageTexture;\r\n this.materials[0].map.needsUpdate = true;\r\n this.materials[0].needsUpdate = true;\r\n }\r\n\r\n /** @private */\r\n generateObject() {\r\n const sizeX = this.config.width / this.config.fx;\r\n const sizeY = this.config.height / this.config.fy;\r\n\r\n this.geometry = new PlaneGeometry(sizeX, sizeY, 1, 1);\r\n this.geometry.vertices.forEach(vertex => {\r\n vertex.z = -1;\r\n });\r\n\r\n this.materials = [new MeshBasicMaterial({side: DoubleSide})];\r\n const image = new Mesh(this.geometry, this.materials);\r\n\r\n // Apply the corrective rotation to our object\r\n const objectOffset = new Object3D();\r\n objectOffset.rotation.copy(this.centerOffset);\r\n objectOffset.add(image);\r\n\r\n // Final object that will have full rotation\r\n // and position applied to it\r\n this.object = new Object3D();\r\n this.object.add(objectOffset);\r\n\r\n this.scene.add(this.object);\r\n }\r\n}\r\n\r\nexport class CameraList {\r\n public viewer: Viewer;\r\n public scene: any;\r\n public props;\r\n public cameras: CameraImage[] = [];\r\n public matrix = new Matrix4();\r\n public adjustments = {};\r\n public aligned = false;\r\n public waitForCameras = false;\r\n\r\n constructor(viewer) {\r\n this.viewer = viewer;\r\n\r\n this.initScene();\r\n this.initEvents();\r\n }\r\n\r\n get count() {\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 markers() {\r\n return this.viewer.markers;\r\n }\r\n\r\n get current() {\r\n let cameras = this.cameras.filter(camera => camera.enabled);\r\n return cameras.length > 0 ? cameras[0] : null;\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 imageExtent() {\r\n let positions = this.cameras.map(camera => {\r\n return camera.position.value;\r\n });\r\n\r\n return extentFromPoints(positions);\r\n }\r\n\r\n get isEmpty() {\r\n return this.cameras.length === 0;\r\n }\r\n\r\n initEvents() {\r\n return;\r\n }\r\n\r\n initScene() {\r\n const scene = new Scene();\r\n const softlight = new AmbientLight(0xFFFFFF);\r\n scene.add(softlight);\r\n this.scene = scene;\r\n }\r\n\r\n onKeyDown(event) {\r\n if (event.key === \"ArrowUp\") {\r\n this.incrementCamera(1);\r\n } else if (event.key === \"ArrowDown\") {\r\n this.incrementCamera(-1);\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 let controls = this.controls;\r\n controls.setOrbitState(false);\r\n }\r\n\r\n /** @private */\r\n setOrbitCamera() {\r\n let controls = this.controls;\r\n controls.setOrbitState(true);\r\n }\r\n\r\n addCameras(cameras, adjustments, height) {\r\n if (cameras.length === 0) {\r\n return;\r\n }\r\n\r\n // Get a list of new cameras\r\n let addedIndex = 0;\r\n let newCameras = new Array(cameras.length);\r\n\r\n cameras.forEach(camera => {\r\n const rotation = [\r\n camera.roll,\r\n camera.pitch,\r\n camera.yaw\r\n ];\r\n\r\n const position = [\r\n camera.x,\r\n camera.y,\r\n camera.z\r\n ];\r\n\r\n const adjustment = camera.id in adjustments\r\n ? adjustments[camera.id]\r\n : [0, 0, 0];\r\n\r\n const cameraConfig = camera.config\r\n ? camera.config\r\n : {};\r\n\r\n const assetType = camera.assetType;\r\n\r\n const cameraInfo = {\r\n id: camera.id,\r\n csv: camera.csv,\r\n name: camera.name,\r\n path: slash(camera.path),\r\n rotation: rotation,\r\n position: position,\r\n height: height,\r\n adjustment: adjustment,\r\n config: cameraConfig,\r\n remote: isStaticSite,\r\n fromJSON: camera.fromJSON\r\n };\r\n\r\n // Add new camera from info\r\n let newCamera = this.getNewCamera(cameraInfo, assetType);\r\n if (camera) {\r\n newCameras[addedIndex] = newCamera;\r\n addedIndex += 1;\r\n }\r\n });\r\n\r\n if (addedIndex === 0) {\r\n return;\r\n }\r\n\r\n this.cameras = [...this.cameras, ...newCameras.slice(0, addedIndex)];\r\n }\r\n\r\n deleteCameras(cameras) {\r\n if (cameras.length === 0) {\r\n return;\r\n }\r\n\r\n cameras.forEach(camera => {\r\n camera.destroy();\r\n });\r\n\r\n // Update camera array\r\n const toRemove = new Set(cameras.map(x => x.id));\r\n const remaining = this.cameras.filter(x => !toRemove.has(x.id));\r\n this.cameras = [...remaining];\r\n\r\n // Update camera markers\r\n this.minimap.removeCameraMarkers(cameras);\r\n this.markers.removeCameraMarkers(cameras);\r\n }\r\n\r\n /** @private */\r\n getNewCamera(data, assetType) {\r\n let cameraID = data.id;\r\n if (this.getByID(cameraID)) {\r\n // Camera already exists\r\n return;\r\n }\r\n\r\n let camera;\r\n if (assetType === AssetType.Panoramic) {\r\n camera = new PanoramicImage(this, data);\r\n } else if (assetType === AssetType.Planar) {\r\n camera = new PlanarImage(this, data);\r\n } else {\r\n return; // Unknown camera type\r\n }\r\n\r\n return camera;\r\n }\r\n\r\n getByID(cameraID) {\r\n let cameras = this.cameras.filter(camera => camera.id === cameraID);\r\n return cameras.length === 1 ? cameras[0] : null;\r\n }\r\n\r\n getByName(cameraName) {\r\n let cameras = this.cameras.filter(camera => camera.name === cameraName);\r\n return cameras.length === 1 ? cameras[0] : null;\r\n }\r\n\r\n getByCSV(id) {\r\n return this.cameras.filter(camera => camera.csv === id);\r\n }\r\n\r\n loadImage(cameraID, opts:CameraLoadOptions = {}) {\r\n let camera = this.getByID(cameraID);\r\n if (!camera) {\r\n return;\r\n }\r\n\r\n //console.log(`Load camera: ${camera.name}`);\r\n camera.loadCamera(opts);\r\n }\r\n\r\n updateArrowNavigation() {\r\n this.viewer.markers.updateArrowNavigation();\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 incrementCamera(increment) {\r\n if (!this.current) {\r\n return;\r\n }\r\n\r\n let cameraIndex = this.currentIndex;\r\n let nextIndex = cameraIndex + increment;\r\n nextIndex = (nextIndex + this.count) % this.count ;\r\n let nextCamera = this.cameras[nextIndex];\r\n this.loadImage(nextCamera.id);\r\n }\r\n\r\n setCameraHeights(height) {\r\n this.cameras.forEach(camera => {\r\n camera.height = height;\r\n });\r\n this.markers.recalculateAllMarkers();\r\n }\r\n\r\n setCameraAdjustments(adjustments) {\r\n this.cameras.forEach(camera => {\r\n const adjustment = camera.id in adjustments\r\n ? adjustments[camera.id]\r\n : [0, 0, 0];\r\n camera.adjustment = adjustment;\r\n });\r\n }\r\n\r\n setCameraMatrix(elements) {\r\n const newMatrix = new Matrix4().fromArray(elements);\r\n if (!this.matrix.equals(newMatrix)) {\r\n this.matrix = newMatrix;\r\n this.applyMatrixToCameras();\r\n this.aligned = true;\r\n }\r\n }\r\n\r\n /** Reset to identity matrix */\r\n resetCameraMatrix() {\r\n this.matrix = new Matrix4();\r\n this.applyMatrixToCameras();\r\n this.aligned = false;\r\n }\r\n\r\n applyMatrixToCameras() {\r\n this.minimap.recalculateAllMarkers();\r\n this.markers.recalculateAllMarkers();\r\n\r\n if (this.current) {\r\n this.setNormalCamera();\r\n this.current.setCameraPosition();\r\n }\r\n\r\n this.markers.updateArrowNavigation();\r\n }\r\n\r\n update() {\r\n return;\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","import 'ol/ol.css';\r\nimport Map from 'ol/Map';\r\nimport Static from 'ol/source/ImageStatic';\r\nimport {Image as ImageLayer} from 'ol/layer';\r\nimport {transformExtent, transform} from 'ol/proj';\r\nimport LocalScene from '../projections';\r\nimport { AerialMap } from './map';\r\n\r\nclass OrthoImageLayer extends ImageLayer {\r\n constructor(opts) {\r\n super(opts);\r\n }\r\n}\r\n\r\nclass OrthoMosaic {\r\n public id;\r\n private layer: ImageLayer;\r\n private corners = [];\r\n private scaleX: number;\r\n private scaleY: number;\r\n private imageBase64: string;\r\n private name: string;\r\n private imageSize: [Number, Number];\r\n private imageSizeOriginal: [Number, Number];\r\n private imagePath: string;\r\n private fromJSON: boolean;\r\n private extent = [];\r\n private orthosList: OrthoMosaicList;\r\n private pixelMaxSpread = 10;\r\n private pixelMaxValue = 245;\r\n\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.imageSizeOriginal = data.imageSizeOriginal;\r\n this.fromJSON = data.fromJSON;\r\n this.imagePath = data.imagePath;\r\n this.scaleX = data.scaleX;\r\n this.scaleY = data.scaleY;\r\n\r\n this.calculateExtent();\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 visible() {\r\n return this.layer.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 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 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 // Add layer immediately to map\r\n this.layer = new OrthoImageLayer({opacity: this.opacity});\r\n this.map.addLayer(this.layer);\r\n\r\n let image = new Image();\r\n image.onload = () => {\r\n this.parseImageData(image);\r\n };\r\n image.src = this.imageBase64;\r\n }\r\n\r\n /** @private */\r\n parseImageData(image) {\r\n // Grab pixel data from image canvas\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 const data = imageData.data;\r\n\r\n // Set white-ish pixels to transparent\r\n for (var i=0; i this.pixelMaxSpread) {\r\n continue;\r\n }\r\n\r\n // Make sure the mean is within a certain range\r\n let pixel_mean = (r + g + b) / 3;\r\n let visible = pixel_mean < this.pixelMaxValue;\r\n data[base + 3] = visible ? 255 : 0;\r\n }\r\n\r\n context.putImageData(imageData, 0, 0);\r\n\r\n let source = new Static({\r\n url: canvas.toDataURL(\"image/png\"),\r\n imageExtent: this.corners,\r\n projection: this.projection,\r\n imageSmoothing: true\r\n });\r\n\r\n this.layer.setSource(source);\r\n\r\n if (!this.fromJSON) {\r\n this.zoomToExtent();\r\n }\r\n }\r\n\r\n setOpacity() {\r\n this.layer.setOpacity(this.opacity);\r\n }\r\n\r\n setVisibility(visible) {\r\n this.layer.setVisible(visible);\r\n }\r\n\r\n destroy() {\r\n if (!this.layer) {\r\n return;\r\n }\r\n\r\n this.map.removeLayer(this.layer);\r\n this.imageBase64 = 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\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 addNewOrtho(data) {\r\n let cameraID = data.id;\r\n if (this.getByID(cameraID)) {\r\n // Ortho already exists\r\n return false;\r\n }\r\n\r\n let ortho = new OrthoMosaic(this, data);\r\n this.orthos.push(ortho);\r\n }\r\n\r\n deleteOrtho(orthoID) {\r\n let ortho = this.getByID(orthoID);\r\n if (!ortho) {\r\n return;\r\n }\r\n\r\n ortho.destroy();\r\n const index = this.orthos.indexOf(ortho);\r\n this.orthos.splice(index, 1);\r\n }\r\n\r\n getByID(orthoID) {\r\n let orthos = this.orthos.filter(ortho => ortho.id === orthoID);\r\n return orthos.length === 1 ? orthos[0] : null;\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","import {createSlice} from '@reduxjs/toolkit';\r\n\r\nexport interface AerialViewState {\r\n extent: object;\r\n resolution: 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, 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 extent: null,\r\n resolution: null,\r\n rotation: null,\r\n basemap: null\r\n} as AerialViewState;\r\n\r\nexport const initialSceneState = {\r\n camera: null,\r\n fov: null,\r\n angles: null,\r\n orbit: null,\r\n pivot: null\r\n} as SceneCameraState;\r\n\r\nexport const isValidCameraState = (state) => {\r\n let validOrbit = (state.orbit !== null) && (state.pivot !== null);\r\n let validCamera = state.camera !== null;\r\n let validState = validOrbit || validCamera;\r\n return validState;\r\n};\r\n\r\nexport const isValidAerialState = (state) => {\r\n return state.extent !== null\r\n && state.resolution !== null\r\n && state.rotation !== null\r\n && state.basemap !== null;\r\n};\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 }\r\n});\r\n\r\nexport const {\r\n changeCameraState,\r\n changeCameraTransform,\r\n changeCameraHeight,\r\n changeBasicAdjustments,\r\n changeSavedAerialState\r\n} = cameraStateSlice.actions;\r\n\r\nexport default cameraStateSlice.reducer;\r\n\r\nexport const selectCameraHeight = state => state.camera.height;\r\nexport const selectActiveCamera = state => state.camera.sceneState.camera;\r\nexport const selectCameraState = state => state.camera.sceneState;\r\nexport const selectCameraTransform = state => state.camera.transform;\r\nexport const selectBasicAdjustments = state => state.camera.adjustments;\r\nexport const selectSavedAerialState = state => state.camera.aerialState;","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 {PanoramicImage, PlanarImage} from '../cameras';\r\nimport {Cluster, Vector as VectorSource} from \"ol/source\";\r\nimport {Vector as VectorLayer} from \"ol/layer\";\r\nimport {\r\n Circle as CircleStyle,\r\n RegularShape as RegularShapeStyle,\r\n Fill, Stroke, Style, Text\r\n} from \"ol/style\";\r\nimport {Point, Polygon} from \"ol/geom\";\r\nimport {Feature} from \"ol\";\r\nimport {boundingExtent} from 'ol/extent';\r\nimport LocalScene, { DataProjectionCoordinate, SceneCoordinate } from '../projections';\r\nimport {Vector3} from 'three';\r\nimport { Projection } from '../../../redux/projections-slice';\r\nimport { OrthoMosaicList } from './orthos';\r\nimport { CameraImage } from '../cameras/cameras';\r\nimport { AerialViewState, isValidAerialState } from '../../../redux/camera-slice';\r\nimport { chunkedArray } from '../misc';\r\nexport type Basemap = 'open-street-maps' | 'arcgis-world' | 'arcgis-street';\r\n\r\n\r\nconst BasemapLayer = (id: Basemap, text, source) => {\r\n return new Tile({\r\n id: id,\r\n text: text,\r\n type: 'basemap',\r\n source: source\r\n });\r\n};\r\n\r\nclass BaseCameraFeature extends Feature {\r\n public cameraID;\r\n public fromJSON;\r\n\r\n constructor(opts) {\r\n super(opts);\r\n this.cameraID = opts.cameraID;\r\n this.fromJSON = opts.fromJSON;\r\n }\r\n}\r\n\r\nclass PanoramicFeature extends BaseCameraFeature {\r\n constructor(opts) {\r\n super(opts);\r\n }\r\n}\r\n\r\nclass PlanarFeature extends BaseCameraFeature {\r\n constructor(opts) {\r\n super(opts);\r\n }\r\n}\r\n\r\nclass ViewTriangle {\r\n private aerial: AerialMap;\r\n private viewer: Viewer;\r\n private map: Map;\r\n private feature;\r\n private layer;\r\n\r\n constructor(parent, map, viewer) {\r\n this.aerial = parent;\r\n this.viewer = viewer;\r\n this.map = map;\r\n\r\n this.generateSource();\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 noWrap: true\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 type: \"triangle\",\r\n source: source,\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 layer.setZIndex(1);\r\n layer.setVisible(false);\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) {\r\n if (!LocalScene.initialized) {\r\n return;\r\n }\r\n\r\n const update = changeDetector.changed;\r\n if (!update) {\r\n return;\r\n }\r\n\r\n // Update view marker geometry\r\n this.rotateViewMarker(this.viewer.lookat);\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 triangle;\r\n private maxLayerZoom = 20;\r\n private maxMapZoomLevel = 23;\r\n private styleCache = {};\r\n private pointsSource;\r\n private boundsSource;\r\n public activeCamera: PanoramicImage;\r\n private activeCameraLayer;\r\n private clusterDistance = 10;\r\n private clusterCircleSize = 5.0;\r\n private camerasToIterate = [];\r\n private camerasCalculated = [];\r\n private chunkedArraySize = 500;\r\n public calculating = false;\r\n private features = [];\r\n private cameras = [];\r\n private setAerialState;\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, props) {\r\n const {setAerialState} = props;\r\n\r\n this.viewer = viewer;\r\n this.containerElement = container;\r\n this.setAerialState = setAerialState;\r\n\r\n this.initMap();\r\n this.initEvents();\r\n this.initDataLayers();\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 BasemapLayer(\"open-street-maps\", \"OpenStreetMaps\", new OSM({\r\n maxZoom: this.maxLayerZoom\r\n })),\r\n\r\n BasemapLayer(\"arcgis-world\", \"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 BasemapLayer(\"arcgis-world\", \"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 BasemapLayer(\"arcgis-street\", \"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 cameraList() {\r\n return this.viewer.cameraList;\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 basemapIds() {\r\n let layers = [];\r\n this.basemapLayers.forEach(layer => {\r\n let id = layer.get(\"id\");\r\n let text = layer.get(\"text\");\r\n let ids = layers.map(x => x.id);\r\n if (ids.indexOf(id) !== -1) {\r\n return;\r\n }\r\n layers.push({id, text});\r\n });\r\n\r\n return layers;\r\n }\r\n\r\n get basemapLayers() {\r\n let layers = this.map.getLayers();\r\n return layers.array_.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 reset(state = null) {\r\n this.resetView(state);\r\n }\r\n\r\n resetView(state = null) {\r\n const view = this.map.getView();\r\n const validExtent = state && isValidAerialState(state);\r\n\r\n if (validExtent) {\r\n view.fit(state.extent);\r\n view.setResolution(state.resolution);\r\n view.setRotation(state.rotation);\r\n this.setVisibleBasemap(state.basemap);\r\n } else {\r\n const center = transform([0, 0], 'EPSG:4326', 'EPSG:3857');\r\n view.setCenter(center);\r\n view.setZoom(0);\r\n view.setRotation(0);\r\n\r\n let defaultID = this.basemapLayers[0].get(\"id\");\r\n this.setVisibleBasemap(defaultID);\r\n }\r\n\r\n this.setActiveCamera();\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 fractionalZoom: false,\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.triangle = new ViewTriangle(this, this.map, this.viewer);\r\n this.resetView();\r\n }\r\n\r\n initEvents() {\r\n this.map.on('click', event => {\r\n this.map.forEachFeatureAtPixel(event.pixel, (feature, layer) => {\r\n let features = feature.get('features');\r\n if ((feature.length === 0) || (!features)) {\r\n return;\r\n }\r\n\r\n if (features.length === 1) {\r\n // Load specific image\r\n let cameraID = features[0].cameraID;\r\n this.cameraList.loadImage(cameraID);\r\n return;\r\n }\r\n\r\n // Multiple projects. Zoom in further\r\n let coordinates = [];\r\n features.forEach(feature => {\r\n let position = feature.get(\"position\");\r\n coordinates.push(position);\r\n });\r\n\r\n // Max zoom already reached, load the first camera\r\n // in our cluster of cameras\r\n let currentZoom = Math.ceil(this.map.getView().getZoom());\r\n if (currentZoom === this.maxMapZoomLevel) {\r\n let cameraID = features[0].get(\"cameraID\");\r\n this.cameraList.loadImage(cameraID);\r\n return;\r\n }\r\n\r\n // Zoom to our extent with 50% boundary\r\n let ext = boundingExtent(coordinates);\r\n let mapSize = this.map.getSize();\r\n this.map.getView().fit(ext, {\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 });\r\n\r\n this.map.on('moveend', () => {\r\n this.updateSavedState();\r\n });\r\n }\r\n\r\n initDataLayers() {\r\n // Create cluster layer for images\r\n this.pointsSource = new VectorSource({\r\n wrapX: false,\r\n noWrap: true\r\n });\r\n\r\n let clusterSource = new Cluster({\r\n distance: this.clusterDistance,\r\n source: this.pointsSource,\r\n });\r\n\r\n let clusterLayer = new VectorLayer({\r\n source: clusterSource,\r\n style: feature => {\r\n return this.clusterStyle(feature);\r\n },\r\n });\r\n\r\n this.map.addLayer(clusterLayer);\r\n\r\n // Create geometry layer for pointcloud bounds\r\n this.boundsSource = new VectorSource({\r\n wrapX: false,\r\n noWrap: true\r\n });\r\n\r\n let boundsLayer = new VectorLayer({\r\n source: this.boundsSource,\r\n style: new Style({\r\n fill: new Fill({\r\n color: 'rgba(51, 153, 204, 0.1)'\r\n }),\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\n\r\n this.map.addLayer(boundsLayer);\r\n\r\n // Activate camera source\r\n this.activeCameraLayer = new VectorLayer({\r\n visible: false,\r\n source: new VectorSource({\r\n wrapX: false,\r\n noWrap: true,\r\n features: [new Feature({\r\n geometry: new Point([0,0])\r\n })]\r\n }),\r\n style: this.styleGenerator(1, true)\r\n });\r\n\r\n this.map.addLayer(this.activeCameraLayer);\r\n }\r\n\r\n setDragState(state) {\r\n this.map.interactions.forEach(interaction => {\r\n if (interaction instanceof DragPan) {\r\n interaction.setActive(state);\r\n }\r\n });\r\n }\r\n\r\n centerOnImages() {\r\n if (this.cameraList.count === 0) {\r\n return;\r\n }\r\n\r\n this.setMapExtent(this.cameraList.imageExtent);\r\n }\r\n\r\n updateSavedState() {\r\n let view = this.map.getView();\r\n let rotation = view.getRotation();\r\n let resolution = view.getResolution();\r\n let extent = view.calculateExtent();\r\n let basemap = this.basemapLayers\r\n .find(x => x.getVisible())\r\n .get(\"id\");\r\n\r\n this.setAerialState({\r\n extent: extent,\r\n resolution: resolution,\r\n rotation: rotation,\r\n basemap: basemap\r\n } as AerialViewState);\r\n }\r\n\r\n updateCloudExtent(boundingBox=null) {\r\n if (!boundingBox) {\r\n this.boundsSource.clear();\r\n return;\r\n }\r\n\r\n let min = new SceneCoordinate(boundingBox.min).toDataProjection();\r\n let max = new SceneCoordinate(boundingBox.max).toDataProjection();\r\n\r\n let corners = [\r\n [min.x, min.y],\r\n [max.x, min.y],\r\n [max.x, max.y],\r\n [min.x, max.y]\r\n ];\r\n\r\n let cornersAerial = corners.map(value => {\r\n return new SceneCoordinate(value).toAerial();\r\n });\r\n\r\n let feature = new Feature({\r\n geometry: new Polygon([cornersAerial])\r\n });\r\n\r\n this.boundsSource.clear();\r\n this.boundsSource.addFeature(feature);\r\n }\r\n\r\n addCameraMarkers(cameras: Array) {\r\n let newCameras = cameras.filter(x => !this.cameras.includes(x));\r\n this.cameras = [...this.cameras, ...newCameras];\r\n\r\n // Clear previous data\r\n this.features = [];\r\n this.pointsSource.clear();\r\n\r\n // Reset chunked arrays\r\n this.camerasToIterate = chunkedArray(this.cameras, this.chunkedArraySize);\r\n this.camerasCalculated = [];\r\n this.calculating = this.cameras.length > 0;\r\n }\r\n\r\n calculateCameras() {\r\n if (this.viewer.calculatingSceneMarkers) {\r\n return;\r\n }\r\n\r\n if (this.camerasToIterate.length === 0) {\r\n return;\r\n }\r\n\r\n // Get next set of cameras in chunked array\r\n const cameras = this.camerasToIterate.shift();\r\n\r\n // Calculate position data\r\n this.camerasCalculated = [\r\n ...this.camerasCalculated,\r\n ...cameras.map(x => {\r\n let position = x.position.aerial;\r\n let point = new Point([position[0], position[1]]);\r\n return [position, point];\r\n })\r\n ];\r\n\r\n // If we have more data to parse exit early\r\n // and wait until next iteration\r\n if (this.camerasToIterate.length !== 0) {\r\n return;\r\n }\r\n\r\n let features = new Array(this.cameras.length);\r\n this.camerasCalculated.forEach((data, cameraIndex) => {\r\n let [position, point] = data;\r\n let camera = this.cameras[cameraIndex];\r\n\r\n const opts = {\r\n geometry: point,\r\n cameraID: camera.id,\r\n position: position,\r\n fromJSON: camera.fromJSON\r\n };\r\n\r\n let feature;\r\n if (camera instanceof PanoramicImage) {\r\n feature = new PanoramicFeature(opts);\r\n } else if (camera instanceof PlanarImage) {\r\n feature = new PlanarFeature(opts);\r\n }\r\n\r\n features[cameraIndex] = feature;\r\n });\r\n\r\n this.features = features;\r\n this.pointsSource.clear();\r\n this.pointsSource.addFeatures(this.features);\r\n this.calculating = false;\r\n\r\n const updateExtent = this.features\r\n .filter(x => x.fromJSON).length === 0;\r\n\r\n if (!updateExtent) {\r\n return;\r\n }\r\n\r\n this.centerOnImages();\r\n }\r\n\r\n removeCameraMarkers(cameras: CameraImage[]) {\r\n const toRemove = new Set(cameras.map(x => x.id));\r\n\r\n const remainingCameras = this.cameras.filter(x => !toRemove.has(x.id));\r\n this.cameras = [...remainingCameras];\r\n\r\n const remainingFeatures = this.features.filter(x => !toRemove.has(x.cameraID));\r\n this.features = [...remainingFeatures];\r\n }\r\n\r\n recalculateAllMarkers() {\r\n const cameras = [...this.cameras];\r\n this.removeCameraMarkers(cameras);\r\n this.addCameraMarkers(cameras);\r\n }\r\n\r\n styleGenerator(size, active, square = false) {\r\n const strokeColor = 'rgba(0, 0, 0, 1.0)';\r\n const textColor = 'rgba(0, 0, 0, 1.0)';\r\n const fillColor = active\r\n ? 'rgba(255, 195, 0, 0.8)'\r\n : 'rgba(255, 255, 255, 0.8)';\r\n\r\n const scale = (1 + 0.25 * Math.log(size));\r\n const radius = this.clusterCircleSize * scale;\r\n\r\n const circleImage = new CircleStyle({\r\n radius: radius,\r\n stroke: new Stroke({\r\n color: strokeColor\r\n }),\r\n fill: new Fill({\r\n color: fillColor\r\n }),\r\n });\r\n\r\n const squareImage = new RegularShapeStyle({\r\n radius: radius * 1.3,\r\n stroke: new Stroke({\r\n color: strokeColor,\r\n width: Math.sqrt(2.0) * 0.95\r\n }),\r\n fill: new Fill({\r\n color: fillColor\r\n }),\r\n angle: Math.PI / 4,\r\n points: 4\r\n });\r\n\r\n return new Style({\r\n image: square ? squareImage : circleImage,\r\n text: new Text({\r\n text: size > 1 ? size.toString() : \"\",\r\n fill: new Fill({color: textColor}),\r\n }),\r\n });\r\n }\r\n\r\n clusterStyle(feature) {\r\n let features = feature.get('features');\r\n\r\n let numSquares = 0;\r\n let numCircles = 0;\r\n features.forEach(feature => {\r\n numSquares += (feature instanceof PlanarFeature) ? 1 : 0;\r\n numCircles += (feature instanceof PanoramicFeature) ? 1 : 0;\r\n });\r\n\r\n let square = (numSquares > 0) && (numCircles === 0);\r\n\r\n let size = features.length;\r\n let styleKey = `${features.length}-${square ? \"square\" : \"circle\"}`;\r\n let style = this.styleCache[styleKey];\r\n\r\n if (!style) {\r\n style = this.styleGenerator(size, false, square);\r\n this.styleCache[styleKey] = style;\r\n }\r\n return style;\r\n }\r\n\r\n setVisibleBasemap(basemapID) {\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 setActiveCamera(cameraID = null) {\r\n let camera = this.cameras.find(x => x.id === cameraID);\r\n if (!camera) {\r\n this.activeCamera = null;\r\n this.activeCameraLayer?.setVisible(false);\r\n return;\r\n }\r\n\r\n const mapPosition = camera.position.aerial;\r\n const point = new Point([mapPosition[0], mapPosition[1]]);\r\n let feature = this.activeCameraLayer.getSource().getFeatures()[0];\r\n feature.setGeometry(point);\r\n this.activeCamera = camera;\r\n\r\n if (camera instanceof PanoramicImage) {\r\n // Force circle style\r\n feature.setStyle(this.styleGenerator(1, true, false));\r\n } else if (camera instanceof PlanarImage) {\r\n // Force square style\r\n feature.setStyle(this.styleGenerator(1, true, true));\r\n }\r\n\r\n this.activeCameraLayer.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, this.map.getSize());\r\n view.setZoom(view.getZoom() - 1.0);\r\n }\r\n\r\n destroy() {\r\n this.map.setTarget(null);\r\n }\r\n\r\n update(changeDetector) {\r\n this.calculateCameras();\r\n\r\n if (this.viewer.orbitState) {\r\n this.triangle.clear();\r\n return;\r\n }\r\n\r\n if (this.viewer.hasPoints || this.viewer.cameraSelected) {\r\n this.triangle.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};\r\n","import {BinaryHeap} from \"../binary-heap\";\r\nimport {RawPointCloudNode} from \"./raw-pointcloud-node\";\r\nimport {RawPointCloud} from \"./raw-pointcloud\";\r\nimport {closestPowerOfTwo} from \"../misc\";\r\nimport { mergeBoundingBoxes, PointCloud } from \"./point-cloud\";\r\nimport {PointCloudMaterialParams} from \"../materials\";\r\nimport {Viewer} from \"../main\";\r\nimport { getProjFactor } from \"../utilities\";\r\nimport { EncompassPointCloud } from \"./encompass-pointcloud\";\r\nimport { SceneCoordinate, SphericalPosition } from \"../projections\";\r\nimport { extentFromPoints } from \"../aerial/map\";\r\nimport { pointInPolygon } from \"../utilities/polygon\";\r\nimport {\r\n BufferGeometry,\r\n Frustum,\r\n MathUtils,\r\n Matrix4,\r\n Points,\r\n Scene,\r\n Vector2,\r\n Vector3\r\n} from \"three\";\r\nimport { WorkerQueue } from \"../worker\";\r\n\r\nexport class PointCloudManager {\r\n public viewer: Viewer;\r\n public scene: Scene;\r\n public materialDefaults: PointCloudMaterialParams;\r\n public clouds: (RawPointCloud | EncompassPointCloud)[] = [];\r\n public workerQueue: WorkerQueue;\r\n public visiblePointsTarget = 0;\r\n private maxloadedToGPUPerFrame = 3;\r\n private maxNodeAsyncLoad = 4;\r\n private maxRawAsyncLoad = 2;\r\n private maxDecodeWorkers = 6;\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 fovDifferencePercent = 0.5;\r\n private minPixelPercent = 0.20;\r\n private boundingBoxVisibility = false;\r\n private loadedOnce = false;\r\n public transparency = 1.0;\r\n public rawJsonResponse = [];\r\n\r\n constructor(parent: Viewer) {\r\n this.viewer = parent;\r\n\r\n // Material defaults\r\n this.materialDefaults = {\r\n minSize: 1.0,\r\n maxSize: 50.0,\r\n colorMap: \"heat-map\",\r\n colorType: 2,\r\n distance: this.viewer.far,\r\n size: 1.0,\r\n dynamicSize: true,\r\n circularPoints: true,\r\n classification: {},\r\n heightClamp: new Vector2(0, 1),\r\n intensityClamp: new Vector2(0, 1),\r\n };\r\n\r\n this.scene = new Scene();\r\n this.setLoadedOnce(false);\r\n\r\n const workerURL = \"workers/pointcloud-decoder-buffer.js\";\r\n this.workerQueue = new WorkerQueue(workerURL,\r\n this.maxDecodeWorkers, true);\r\n }\r\n\r\n get cameraList() {\r\n return this.viewer.cameraList;\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 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 let boundingBox = null;\r\n this.clouds.forEach(cloud => {\r\n if (!cloud.visible) {\r\n return;\r\n }\r\n\r\n boundingBox = mergeBoundingBoxes(boundingBox,\r\n cloud.tightBoundingBox);\r\n });\r\n return boundingBox;\r\n }\r\n\r\n get isEmpty() {\r\n return this.clouds.length === 0;\r\n }\r\n\r\n get rawPointClouds() : Array {\r\n let clouds = this.clouds.filter(x => x instanceof RawPointCloud);\r\n return clouds as Array;\r\n }\r\n\r\n getByID(id){\r\n const pointCloud = this.clouds.filter(pointCloud => pointCloud.identifier === id);\r\n return pointCloud.length === 1 ? pointCloud[0] : null;\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: RawPointCloud | EncompassPointCloud) {\r\n this.clouds.push(cloud);\r\n this.updateMeasureList();\r\n }\r\n\r\n deletePointCloud(identifier) {\r\n const clouds = new Set(this.clouds);\r\n const toRemove = this.clouds.filter(cloud => cloud.identifier === identifier);\r\n\r\n toRemove.forEach(cloud => {\r\n // console.log(`Remove pointcloud [id = ${cloud.identifier}]`);\r\n cloud.dispose();\r\n clouds.delete(cloud);\r\n });\r\n\r\n this.clouds = [...clouds];\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 toggleBoundingBox() {\r\n this.boundingBoxVisibility = !this.boundingBoxVisibility;\r\n console.log(\"Bounding box visible: \", this.boundingBoxVisibility);\r\n }\r\n\r\n hideDescendants(cloud) {\r\n if (!cloud.root) {\r\n return;\r\n }\r\n\r\n let stack = [cloud.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\r\n object.children.forEach(child => {\r\n stack.push(child);\r\n });\r\n }\r\n }\r\n\r\n updateClamping(defaultKey, materialKey, data) {\r\n if (data.max <= data.min) {\r\n return;\r\n }\r\n\r\n let value = new Vector2(data.min, data.max);\r\n this.materialDefaults[defaultKey] = value;\r\n this.clouds.forEach(cloud => {\r\n cloud.materials.forEach(material => {\r\n material[materialKey] = value;\r\n });\r\n });\r\n }\r\n\r\n setClassification(classification, visible) {\r\n this.materialDefaults.classification[classification] = visible;\r\n\r\n this.clouds.forEach(cloud => {\r\n cloud.materials.forEach(material => {\r\n let uniforms = material.uniforms;\r\n let visibilityArray = uniforms.classification_visible.value;\r\n visibilityArray[classification] = visible;\r\n });\r\n });\r\n }\r\n\r\n orbitPositionFromBounds(bbox, side, smooth) {\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.25);\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 position = this.orbitWithAngle(pivot, radius, side);\r\n\r\n return {position, 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 updateMinimapExtent() {\r\n let boundingBox = this.combinedBoundingBox;\r\n this.minimap.updateCloudExtent(boundingBox);\r\n }\r\n\r\n setLoadedOnce(state) {\r\n this.loadedOnce = state;\r\n }\r\n\r\n zoomToExtent(boundingBox, ignoreConditions, smooth) {\r\n let camerasExist = this.cameraList.current !== null;\r\n\r\n if (!ignoreConditions) {\r\n if (camerasExist) {\r\n return;\r\n }\r\n\r\n if (this.loadedOnce) {\r\n return;\r\n }\r\n }\r\n\r\n // Zoom to 3d mode extent\r\n this.setLoadedOnce(true);\r\n let newPosition = this.orbitPositionFromBounds(\r\n boundingBox, \"top\", smooth);\r\n this.controls.setOrbitState(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 }\r\n\r\n updateVisibility(frustum, cloud: PointCloud) {\r\n if (!cloud.root) {\r\n return;\r\n }\r\n\r\n if (this.cameraList.waitForCameras) {\r\n return;\r\n }\r\n\r\n let priorityQueue = new BinaryHeap(x => 1 / x.weight);\r\n priorityQueue.push({\r\n node: cloud.root,\r\n weight: Number.MAX_VALUE\r\n });\r\n\r\n let unloadedGeometry = [];\r\n let numLoadedPoints = 0;\r\n let loadedToGPUThisFrame = 0;\r\n\r\n let maxNodeDistance = cloud.materialScene.distance;\r\n let controls = this.viewer.controls;\r\n let measurePoint = controls.getCameraTarget();\r\n\r\n while (priorityQueue.size() > 0) {\r\n let element = priorityQueue.pop();\r\n let node = element.node;\r\n\r\n // Raw pointclouds dont require certain steps\r\n let isRawPointCloud = node instanceof RawPointCloudNode;\r\n\r\n let newPointsTarget = numLoadedPoints;\r\n if (node.numPoints !== null) {\r\n newPointsTarget += node.numPoints;\r\n }\r\n\r\n // Ignore nodes based on our view frustrum\r\n let visible = frustum.intersectsSphere(node.boundingSphere);\r\n\r\n if (!isRawPointCloud) {\r\n // Make sure we dont exceeed our points limit\r\n visible = visible && (newPointsTarget < this.visiblePointsTarget);\r\n }\r\n\r\n if (!visible) {\r\n continue;\r\n }\r\n\r\n // Ignore nodes based on distance slider\r\n let bounds2d = new Vector2().copy(node.center);\r\n let camera2d = new Vector2().copy(measurePoint);\r\n let nodeDistance = bounds2d.distanceTo(camera2d);\r\n if (nodeDistance > (node.radius + maxNodeDistance)) {\r\n continue;\r\n }\r\n\r\n if (node.isGeometryNode() && (!node.parent || node.parent.isTreeNode())) {\r\n if (node.isLoaded() && loadedToGPUThisFrame < this.maxloadedToGPUPerFrame) {\r\n node.addToScene(node);\r\n loadedToGPUThisFrame++;\r\n } else {\r\n unloadedGeometry.push(node);\r\n }\r\n }\r\n\r\n if (node.isTreeNode()) {\r\n node.setVisibility(true, this.boundingBoxVisibility);\r\n numLoadedPoints += node.numPoints;\r\n }\r\n\r\n let cameraPosition = this.viewer.camera.position;\r\n node.children.forEach(child => {\r\n let childDistance = child.center.distanceTo(cameraPosition);\r\n let childRadius = child.radius;\r\n\r\n // Modify the fov range so we dont load too many points while zooming\r\n let maxFov = this.viewer.controls.maxFOV;\r\n let fov = this.viewer.camera.fov;\r\n fov = maxFov - (maxFov - fov) * this.fovDifferencePercent;\r\n fov = MathUtils.degToRad(fov);\r\n\r\n const screenHeight = this.viewer.height;\r\n let projFactor = getProjFactor(fov, childDistance, screenHeight);\r\n let screenPixelRadius = childRadius * projFactor;\r\n\r\n let insideSphere = childDistance < childRadius;\r\n\r\n if (!isRawPointCloud) {\r\n // Pixel size based filtering\r\n let minPixelSize = this.viewer.height * this.minPixelPercent;\r\n let validPixelSize = screenPixelRadius >= minPixelSize;\r\n if (!validPixelSize) {\r\n return;\r\n }\r\n }\r\n\r\n let weight = screenPixelRadius;\r\n if (insideSphere) {\r\n weight = Number.MAX_VALUE;\r\n }\r\n\r\n priorityQueue.push({\r\n node: child,\r\n weight: weight\r\n });\r\n });\r\n }\r\n\r\n let maxLoad = Math.min(this.maxNodeAsyncLoad, unloadedGeometry.length);\r\n for (let i = 0; i < maxLoad; i++) {\r\n unloadedGeometry[i].load();\r\n }\r\n\r\n this.numLoadedPoints += numLoadedPoints;\r\n }\r\n\r\n updateMaterialDefaults(cloud: PointCloud, camera) {\r\n if (!cloud.root) {\r\n return;\r\n }\r\n\r\n cloud.materials.forEach(material => {\r\n\r\n if (!material) {\r\n return;\r\n }\r\n\r\n let controls = this.viewer.controls;\r\n let cameraPosition = controls.getCameraTarget();\r\n\r\n material.dynamic_cloud = !(cloud instanceof RawPointCloud);\r\n material.origin = cameraPosition;\r\n material.screenHeight = this.viewer.height;\r\n material.screenwidth = this.viewer.width;\r\n material.fov = camera.fov * Math.PI / 180.0;\r\n\r\n if (cloud instanceof EncompassPointCloud) {\r\n material.octree_spacing = cloud.spacing;\r\n material.octree_size = parseFloat(cloud.root.size);\r\n material.octree_corner = new Vector3()\r\n .add(cloud.root.center)\r\n .subScalar(cloud.root.size / 2.0);\r\n }\r\n\r\n let intensityRange = cloud.intensityRange;\r\n if (intensityRange) {\r\n let intensity = new Vector2(intensityRange.min,\r\n intensityRange.max);\r\n material.intensity_range = intensity;\r\n }\r\n\r\n let maxColor = cloud.maxColor;\r\n if (maxColor) {\r\n let maxValue = closestPowerOfTwo(maxColor);\r\n material.rgb_max = maxValue;\r\n }\r\n\r\n let tightBoundingBox = this.combinedBoundingBox;\r\n if (tightBoundingBox) {\r\n let height = new Vector2(tightBoundingBox.min.z,\r\n tightBoundingBox.max.z);\r\n material.height_range = height;\r\n }\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 RawPointCloud)) {\r\n // Only applicable to raw pointclouds\r\n return;\r\n }\r\n\r\n if (!cloud.visible) {\r\n return;\r\n }\r\n\r\n if (!cloud.root) {\r\n return;\r\n }\r\n\r\n cloud.root.children.forEach(child => {\r\n if (!child.geometry) {\r\n return;\r\n }\r\n\r\n let numPoints = child.numPoints;\r\n let sampledPoints = Math.floor(numPoints*percent);\r\n child.geometry.setDrawRange(0, sampledPoints);\r\n });\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 manageNodeCache(cloud: EncompassPointCloud) {\r\n if (!cloud.root) {\r\n return;\r\n }\r\n\r\n let stack = [cloud.root];\r\n\r\n let totalVisibleNodes = 0;\r\n let unusedNodes = [];\r\n\r\n while (stack.length > 0) {\r\n let object = stack.shift();\r\n\r\n if (object.visible) {\r\n totalVisibleNodes++;\r\n } else if (object.loaded) {\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 let totalUnusedNodes = unusedNodes.length;\r\n let totalNumberNodes = totalVisibleNodes + totalUnusedNodes;\r\n let maxNodesAllowed = cloud.nodeCacheSize;\r\n\r\n if (totalNumberNodes < maxNodesAllowed) {\r\n return;\r\n }\r\n\r\n // console.log(`${totalNumberNodes}/${maxNodesAllowed} Nodes loaded. Visible: ${totalVisibleNodes}, Cached: ${totalUnusedNodes}`);\r\n\r\n // We delete from our list of unused nodes plus an extra percentage of the total\r\n let numberToDelete = totalNumberNodes - maxNodesAllowed + maxNodesAllowed * 0.20;\r\n numberToDelete = Math.min(numberToDelete, totalUnusedNodes);\r\n if (numberToDelete === 0) {\r\n return;\r\n }\r\n\r\n // console.log(`Dispose ${numberToDelete} cached nodes`);\r\n\r\n // Delete unused nodes, starting at the highest detail level we have\r\n unusedNodes.reverse();\r\n unusedNodes.forEach((node, index) => {\r\n if (index >= numberToDelete) {\r\n return;\r\n }\r\n\r\n node.dispose();\r\n });\r\n }\r\n\r\n updateVisibilityTexture(cloud: EncompassPointCloud) {\r\n // Material not created yet\r\n cloud.materials.forEach(material => {\r\n if (!material) {\r\n return;\r\n }\r\n\r\n // Static sizing, exit the function\r\n if (!material.dynamic_size) {\r\n return;\r\n }\r\n\r\n let visibleNodes = cloud.getVisibleNodes();\r\n let texture = material.visibleNodesTexture;\r\n let data = texture.image.data;\r\n\r\n visibleNodes.forEach((node, nodeIndex) => {\r\n data[nodeIndex * 3 + 0] = 0; // indicate which of the 8 children are visible\r\n data[nodeIndex * 3 + 1] = 0; // relative offset to the node’s first child.\r\n data[nodeIndex * 3 + 2] = 0; // empty\r\n\r\n // The children nodes that are visible from our original array\r\n let children = visibleNodes.filter(child => {\r\n return child.parent === node;\r\n });\r\n\r\n children.forEach((child, childIndex) => {\r\n let index = parseInt(child.name.substr(-1));\r\n\r\n // Set the bit that represents this node to true\r\n data[nodeIndex * 3 + 0] += Math.pow(2, index);\r\n\r\n if (childIndex === 0) {\r\n // Save the offset to our first child node\r\n let vArrayIndex = visibleNodes.indexOf(child);\r\n data[nodeIndex * 3 + 1] = vArrayIndex - nodeIndex;\r\n }\r\n });\r\n });\r\n\r\n texture.needsUpdate = true;\r\n });\r\n }\r\n\r\n updateShaderVertex(array, index, vertex) {\r\n array.value[index] = vertex.x;\r\n array.value[index + 1] = vertex.y;\r\n array.value[index + 2] = vertex.z;\r\n }\r\n\r\n updateAreaVertices(areaGeometry) {\r\n this.clouds.forEach(cloud => {\r\n cloud.materials.forEach(material => {\r\n let areaMeasureData = material.uniforms.area_measure_data;\r\n let volumeStatus = material.uniforms.volume_status;\r\n let maxTriangles = material.uniforms.max_triangles.value;\r\n\r\n areaMeasureData.value.fill(0.0);\r\n volumeStatus.value.fill(0.0);\r\n\r\n let triangleNumber = 0;\r\n areaGeometry.forEach(data => {\r\n data.indices.forEach(triangleIndex => {\r\n if (triangleNumber >= maxTriangles) {\r\n return;\r\n }\r\n\r\n let base = triangleNumber * 9;\r\n volumeStatus.value[triangleNumber] = data.volumeStatus;\r\n\r\n triangleIndex.forEach((vertexIndex, index) => {\r\n let vertex = data.vertices[vertexIndex];\r\n let vIndex = base + index * 3;\r\n this.updateShaderVertex(areaMeasureData, vIndex, vertex);\r\n });\r\n\r\n triangleNumber = triangleNumber + 1;\r\n });\r\n });\r\n\r\n material.needsUpdate = true;\r\n });\r\n });\r\n }\r\n\r\n pushToWorkerQueue(data, callback) {\r\n this.workerQueue.push(data, callback, [data.buffer]);\r\n }\r\n\r\n loadAvailableLasData() {\r\n let numLoading = 0;\r\n let cloudsToParse = [];\r\n let cloudsToExecute = [];\r\n\r\n // Execute next available in worker queue\r\n this.workerQueue.process();\r\n\r\n this.rawPointClouds.forEach(cloud => {\r\n if ((!cloud.canReadData) || (!cloud.visible) || (cloud.loaded)) {\r\n return;\r\n }\r\n\r\n if (numLoading >= this.maxRawAsyncLoad) {\r\n return;\r\n }\r\n\r\n if (cloud.generatingChunks) {\r\n cloudsToParse.push(cloud);\r\n } else {\r\n let timeNow = performance.now();\r\n let timeSinceLaunch = timeNow - this.lastExeLaunched;\r\n if (timeSinceLaunch > this.exeLaunchTimeout) {\r\n this.lastExeLaunched = timeNow;\r\n cloudsToExecute.push(cloud);\r\n }\r\n }\r\n\r\n numLoading += 1;\r\n });\r\n\r\n if (cloudsToExecute.length > 0) {\r\n let cloud = cloudsToExecute.shift();\r\n cloud.launchExecutable();\r\n return;\r\n }\r\n\r\n for (let cloud of cloudsToParse) {\r\n cloud.parseAvailableChunks();\r\n }\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 => {\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.size) || (dy > node.size));\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 if (highest) {\r\n data.reverse();\r\n }\r\n dtmPoints.push(data[0]);\r\n });\r\n\r\n console.log(`Sampled points: ${points.length} => ${dtmPoints.length}`);\r\n return dtmPoints;\r\n }\r\n\r\n update() {\r\n // Set up our frustum\r\n let frustum = new Frustum();\r\n let cameraViewProjectionMatrix = new Matrix4();\r\n this.viewer.camera.updateProjectionMatrix();\r\n this.viewer.camera.updateMatrixWorld(true);\r\n this.viewer.camera.matrixWorldInverse.getInverse(this.viewer.camera.matrixWorld);\r\n cameraViewProjectionMatrix.multiplyMatrices(\r\n this.viewer.camera.projectionMatrix,\r\n this.viewer.camera.matrixWorldInverse\r\n );\r\n frustum.setFromProjectionMatrix(cameraViewProjectionMatrix);\r\n\r\n this.numLoadedPoints = 0;\r\n\r\n // Keep loading raw pointcloud data\r\n this.loadAvailableLasData();\r\n\r\n // Iterate each pointcloud and figure out what to show\r\n this.clouds.forEach(cloud => {\r\n this.hideDescendants(cloud);\r\n if (!cloud.visible) {\r\n return;\r\n }\r\n\r\n this.updateVisibility(frustum, cloud);\r\n\r\n if (cloud instanceof EncompassPointCloud) {\r\n this.manageNodeCache(cloud);\r\n }\r\n\r\n this.updateMaterialDefaults(cloud, this.viewer.camera);\r\n\r\n if (cloud instanceof EncompassPointCloud) {\r\n this.updateVisibilityTexture(cloud);\r\n }\r\n\r\n });\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}","export default __webpack_public_path__ + \"static/media/arrow.81f0ce35.png\";","export default __webpack_public_path__ + \"static/media/arrow-shadow.7243bcb0.png\";","import {\r\n BufferGeometry,\r\n BufferAttribute,\r\n Vector3,\r\n Mesh,\r\n Matrix4,\r\n Matrix3,\r\n Scene,\r\n Object3D,\r\n Texture,\r\n TextureLoader,\r\n PlaneGeometry,\r\n MeshBasicMaterial,\r\n DoubleSide,\r\n MathUtils\r\n} from \"three\";\r\nimport {Viewer} from '../main';\r\nimport {MarkerMaterial} from \"../materials\";\r\nimport { CameraImage, PlanarImage } from \"../cameras/cameras\";\r\nimport arrowPathStandard from '../../textures/arrow.png';\r\nimport arrowPathShadow from '../../textures/arrow-shadow.png';\r\nimport { RayCaster } from \"../controls\";\r\nimport { chunkedArray } from \"../misc\";\r\nimport { MarkerNavType } from \"../../../redux/settings-slice\";\r\n\r\nexport class CameraMarkers {\r\n private viewer: Viewer;\r\n private arrowNavigation: ArrowNavigation;\r\n public markerNavigation: MarkerNavigation;\r\n private navigationType: MarkerNavType;\r\n public cameras = [];\r\n public modifier = false;\r\n public scene: Scene = null;\r\n\r\n constructor(viewer) {\r\n this.viewer = viewer;\r\n this.initScene();\r\n this.initKeyDown();\r\n\r\n this.markerNavigation = new MarkerNavigation(viewer, this);\r\n this.arrowNavigation = new ArrowNavigation(viewer, this);\r\n }\r\n\r\n get controls() {\r\n return this.viewer.controls;\r\n }\r\n\r\n get cameraList() {\r\n return this.viewer.cameraList;\r\n }\r\n\r\n get renderInFront() {\r\n return this.viewer.orbitState || this.arrowNavigation.visible;\r\n }\r\n\r\n get opacity() {\r\n return this.arrowNavigation.visible ? 1.0 : 0.5;\r\n }\r\n\r\n get calculating() {\r\n return this.markerNavigation.calculating;\r\n }\r\n\r\n get isHidden() {\r\n return this.navigationType === MarkerNavType.None;\r\n }\r\n\r\n get isArrows() {\r\n return this.navigationType === MarkerNavType.Arrows;\r\n }\r\n\r\n get isMarkers() {\r\n return this.navigationType === MarkerNavType.Markers;\r\n }\r\n\r\n initScene() {\r\n this.scene = new Scene();\r\n }\r\n\r\n initKeyDown() {\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 addCameraMarkers(cameras: Array) {\r\n // Add new cameras to array\r\n let newCameras = cameras.filter(x => !this.cameras.includes(x));\r\n this.cameras = [...this.cameras, ...newCameras];\r\n\r\n // Draw markers for marker navigation\r\n this.markerNavigation.drawCameraMarkers(this.cameras);\r\n }\r\n\r\n setNavigationType(state) {\r\n this.navigationType = state;\r\n this.markerNavigation.updatePicker();\r\n }\r\n\r\n removeCameraMarkers(cameras: CameraImage[]) {\r\n // Remove cameras from array\r\n const toRemove = new Set(cameras.map(x => x.id));\r\n const remaining = this.cameras.filter(x => !toRemove.has(x.id));\r\n this.cameras = [...remaining];\r\n }\r\n\r\n recalculateAllMarkers() {\r\n const cameras = [...this.cameras];\r\n this.removeCameraMarkers(cameras);\r\n this.addCameraMarkers(cameras);\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 mouseClick(event) {\r\n let markerID = this.markerNavigation.mouseClick(event);\r\n if (markerID !== null) {\r\n let camera = this.cameras[markerID];\r\n this.cameraList.loadImage(camera.id);\r\n return true;\r\n }\r\n\r\n let cameraID = this.arrowNavigation.mouseClick(event);\r\n if (cameraID !== null) {\r\n this.cameraList.loadImage(cameraID);\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n onMouseMove(event, mouse) {\r\n if (mouse.movement) {\r\n return;\r\n }\r\n\r\n // Mouse move for arrow navigation\r\n this.arrowNavigation.onMouseMove(event);\r\n\r\n // Moues move for standard navigation\r\n this.markerNavigation.onMouseMove(event);\r\n }\r\n\r\n\r\n onKeyUp(event) {\r\n if (event.which !== 17) {\r\n return;\r\n }\r\n\r\n this.modifier = false;\r\n }\r\n\r\n onKeyDown(event) {\r\n if (event.which !== 17) {\r\n return;\r\n }\r\n\r\n if (!this.modifier && this.isArrows) {\r\n this.markerNavigation.updatePicker();\r\n }\r\n\r\n this.modifier = true;\r\n }\r\n\r\n update() {\r\n let isOrbitMode = this.viewer.orbitState;\r\n\r\n if (this.isHidden) {\r\n this.markerNavigation.setVisible(false);\r\n this.arrowNavigation.setVisible(false);\r\n } else {\r\n if (this.isMarkers) {\r\n this.markerNavigation.setVisible(true);\r\n this.arrowNavigation.setVisible(false);\r\n } else if (this.isArrows) {\r\n if (isOrbitMode) {\r\n this.markerNavigation.setVisible(true);\r\n this.arrowNavigation.setVisible(false);\r\n } else {\r\n this.markerNavigation.setVisible(this.modifier);\r\n this.arrowNavigation.setVisible(!this.modifier);\r\n }\r\n }\r\n }\r\n\r\n this.markerNavigation.setEnabled(this.isArrows || this.isMarkers);\r\n this.arrowNavigation.setEnabled(this.isArrows);\r\n\r\n this.markerNavigation.update();\r\n this.arrowNavigation.update();\r\n }\r\n}\r\n\r\nclass MarkerNavigation {\r\n private viewer: Viewer;\r\n private markers: CameraMarkers;\r\n private markerMesh: any = null;\r\n private pickingMesh: any = null;\r\n private standardMaterial: MarkerMaterial = null;\r\n private pickingMaterial: MarkerMaterial = null;\r\n public enabled = false;\r\n public visible = false;\r\n private geometry;\r\n private verticesPerCamera = 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 camerasToIterate = [];\r\n private camerasCalculated = [];\r\n private selectedID = null;\r\n private chunkedArraySize = 500;\r\n public markerPositions = [];\r\n public calculating = false;\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(viewer: Viewer, markers: CameraMarkers) {\r\n this.markers = markers;\r\n this.viewer = viewer;\r\n\r\n this.initGeometry();\r\n }\r\n\r\n get scene() {\r\n return this.markers.scene;\r\n }\r\n\r\n get meshes() {\r\n return [this.markerMesh, this.pickingMesh];\r\n }\r\n\r\n get materials() {\r\n return [this.standardMaterial, this.pickingMaterial];\r\n }\r\n\r\n get picker() {\r\n return this.viewer.gpuPickers.markers;\r\n }\r\n\r\n initGeometry() {\r\n if (this.markerMesh) {\r\n this.scene.remove(this.markerMesh);\r\n }\r\n\r\n if (this.pickingMesh) {\r\n this.picker.remove(this.pickingMesh);\r\n }\r\n\r\n let geometry = new BufferGeometry();\r\n geometry.setAttribute('selected', new BufferAttribute(new Float32Array(0), 1));\r\n geometry.setAttribute('visible', new BufferAttribute(new Float32Array(0), 1));\r\n geometry.setAttribute('gpu_index', new BufferAttribute(new Int32Array(0), 1));\r\n geometry.setAttribute('camera_index', new BufferAttribute(new Int32Array(0), 1));\r\n geometry.setAttribute('position', new BufferAttribute(new Float32Array(0), 3));\r\n geometry.setAttribute('uv', new BufferAttribute(new Float32Array(0), 2));\r\n\r\n this.standardMaterial = new MarkerMaterial(this.viewer, false);\r\n this.markerMesh = new Mesh(geometry, this.standardMaterial);\r\n this.scene.add(this.markerMesh);\r\n\r\n this.pickingMaterial = new MarkerMaterial(this.viewer, true);\r\n this.pickingMesh = new Mesh(geometry, this.pickingMaterial);\r\n this.picker.add(this.pickingMesh);\r\n }\r\n\r\n setEnabled(state) {\r\n this.enabled = state;\r\n }\r\n\r\n setVisible(state) {\r\n this.visible = state;\r\n }\r\n\r\n updatePicker() {\r\n this.picker.needsUpdate = true;\r\n }\r\n\r\n drawCameraMarkers(cameras) {\r\n let numCameras = cameras.length;\r\n let selected = new Float32Array(numCameras * this.verticesPerCamera);\r\n let visible = new Float32Array(numCameras * this.verticesPerCamera);\r\n let markerShape = new Float32Array(numCameras * this.verticesPerCamera);\r\n let positions = new Float32Array(numCameras * this.verticesPerCamera * 3);\r\n let uvs = new Float32Array(numCameras * this.verticesPerCamera * 2);\r\n let indices = new Int32Array(numCameras * this.verticesPerCamera);\r\n let cameraIndices = new Int32Array(numCameras * this.verticesPerCamera);\r\n\r\n cameras.forEach((camera, cameraIndex) => {\r\n // Set the marker shape. Default is circlular\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.verticesPerCamera;\r\n for (var i = 0; i < this.verticesPerCamera; 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 let 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 this.geometry = geometry;\r\n\r\n // Reset chunked arrays\r\n this.camerasToIterate = chunkedArray(cameras, this.chunkedArraySize);\r\n this.camerasCalculated = [];\r\n this.calculating = cameras.length > 0;\r\n\r\n if (numCameras === 0) {\r\n this.updateGeometry();\r\n }\r\n }\r\n\r\n markCameraSelected(markerID) {\r\n this.meshes.forEach(mesh => {\r\n let attributes = mesh.geometry.attributes;\r\n attributes.selected.array.fill(0.0);\r\n\r\n let index = attributes.camera_index.array.indexOf(markerID);\r\n if (index !== -1) {\r\n for (var i = 0; i < this.verticesPerCamera; i++) {\r\n attributes.selected.array[index + i] = 1.00;\r\n }\r\n }\r\n\r\n attributes.selected.needsUpdate = true;\r\n });\r\n\r\n if (this.selectedID !== markerID) {\r\n // Update picker if selected marker changed\r\n this.updatePicker();\r\n }\r\n\r\n this.selectedID = markerID;\r\n }\r\n\r\n calculateCameras() {\r\n if (this.camerasToIterate.length === 0) {\r\n return;\r\n }\r\n\r\n // Get next set of cameras in chunked array\r\n const cameras = this.camerasToIterate.shift();\r\n\r\n // Calculate position data\r\n this.camerasCalculated = [\r\n ...this.camerasCalculated,\r\n ...cameras.map(x => x.position.marker)\r\n ];\r\n\r\n // If we have more data to parse exit early\r\n // and wait until next iteration\r\n if (this.camerasToIterate.length !== 0) {\r\n return;\r\n }\r\n\r\n let numCameras = this.camerasCalculated.length;\r\n let positions = new Float32Array(numCameras * this.verticesPerCamera * 3);\r\n\r\n this.markerPositions = new Array(numCameras);\r\n this.camerasCalculated.forEach((position, cameraIndex) => {\r\n // Setting our positions array\r\n const numCorners = this.corners.length;\r\n this.markerPositions[cameraIndex] = position;\r\n this.corners.forEach((corner, cornerIndex) => {\r\n let index = (numCorners * cameraIndex) + cornerIndex;\r\n var points = this.vertices[corner];\r\n positions[(index * 3)] = points.x + position.x;\r\n positions[(index * 3) + 1] = points.y + position.y;\r\n positions[(index * 3) + 2] = points.z + position.z;\r\n });\r\n });\r\n\r\n this.geometry.setAttribute('position', new BufferAttribute(positions, 3));\r\n this.geometry.attributes.position.needsUpdate = true;\r\n\r\n this.calculating = false;\r\n this.updateGeometry();\r\n }\r\n\r\n updateGeometry() {\r\n this.meshes.forEach(mesh => {\r\n mesh.geometry.dispose();\r\n mesh.geometry.copy(this.geometry);\r\n mesh.geometry.needsUpdate = true;\r\n });\r\n\r\n this.viewer.updatePickers();\r\n }\r\n\r\n cameraPickerID(event) {\r\n try {\r\n // Update gpu picker if required\r\n this.picker.update();\r\n\r\n // Grab our index and marker id\r\n const index = this.picker.value(event);\r\n\r\n if (index === null) {\r\n return null;\r\n }\r\n\r\n const attributes = this.pickingMesh.geometry.attributes;\r\n const arrIndex = attributes.gpu_index.array.indexOf(index);\r\n const markerID = attributes.camera_index.array[arrIndex];\r\n\r\n return markerID;\r\n }\r\n catch (e) {\r\n console.log(\"Prevented framebuffer exception: \");\r\n console.log(e);\r\n\r\n return null;\r\n }\r\n }\r\n\r\n onMouseMove(event) {\r\n let markerID = this.cameraPickerID(event);\r\n this.markCameraSelected(markerID);\r\n }\r\n\r\n mouseClick(event) {\r\n let markerID = this.cameraPickerID(event);\r\n return markerID;\r\n }\r\n\r\n update() {\r\n let position = this.viewer.camera.position;\r\n let quat = this.viewer.camera.quaternion;\r\n let mtrx4 = new Matrix4().makeRotationFromQuaternion(quat);\r\n let mtrx3 = new Matrix3().setFromMatrix4(mtrx4);\r\n mtrx3.getInverse(mtrx3);\r\n let elements = mtrx3.elements;\r\n\r\n // Set meshes visibility\r\n this.meshes.forEach(mesh => {\r\n mesh.visible = this.visible;\r\n });\r\n\r\n // Update shader parameters\r\n this.materials.forEach(shader => {\r\n let uniforms = shader.uniforms;\r\n uniforms.mtrx_x.value = new Vector3(elements[0], elements[1], elements[2]);\r\n uniforms.mtrx_y.value = new Vector3(elements[3], elements[4], elements[5]);\r\n uniforms.mtrx_z.value = new Vector3(elements[6], elements[7], elements[8]);\r\n uniforms.camera_position.value = position;\r\n uniforms.screenHeight.value = this.viewer.height;\r\n uniforms.currentIndex.value = this.viewer.cameraList.currentIndex;\r\n uniforms.orbitMode.value = this.viewer.orbitState;\r\n uniforms.fov.value = this.viewer.camera.fov * Math.PI / 180.0;\r\n shader.needsUpdate = true;\r\n });\r\n\r\n this.calculateCameras();\r\n }\r\n}\r\n\r\nclass ArrowMarker {\r\n public camera: CameraImage;\r\n private radius = 1.5\r\n private height = -1.0;\r\n private size = 0.5;\r\n public object: Object3D;\r\n\r\n constructor(textures, section, angle) {\r\n this.object = new Object3D();\r\n this.object.rotation.z = 1 * MathUtils.degToRad(angle);\r\n this.addMesh(section, textures[0], this.height);\r\n this.addMesh(section, textures[1], this.height * 1.03);\r\n }\r\n\r\n get visible() {\r\n return this.object.visible;\r\n }\r\n\r\n get enabled() {\r\n return this.camera !== null;\r\n }\r\n\r\n clear() {\r\n this.camera = null;\r\n this.setVisible(false);\r\n }\r\n\r\n setVisible(state) {\r\n this.object.visible = state;\r\n }\r\n\r\n setCamera(camera: CameraImage) {\r\n this.camera = camera;\r\n }\r\n\r\n setScale(scale) {\r\n this.object.children.forEach(x => {\r\n x.scale.copy(scale);\r\n });\r\n }\r\n\r\n addMesh(section, texture, height) {\r\n // Add standard marker mesh\r\n const geometryStandard = new PlaneGeometry(this.size * 0.75, this.size);\r\n const materialStandard = new MeshBasicMaterial({\r\n map: texture,\r\n side: DoubleSide,\r\n transparent: true,\r\n alphaTest: 0.5\r\n });\r\n\r\n const mesh = new Mesh(geometryStandard, materialStandard);\r\n mesh.userData = {section};\r\n mesh.position.x = this.radius;\r\n mesh.position.z = height;\r\n mesh.rotation.z = -1 * MathUtils.degToRad(90);\r\n this.object.add(mesh);\r\n }\r\n}\r\n\r\nclass ArrowNavigation {\r\n private viewer: Viewer;\r\n private markers: CameraMarkers;\r\n private object: Object3D;\r\n private textures: Texture[] = [];\r\n public enabled = false;\r\n public visible = false;\r\n private minDistance = 5.0;\r\n private maxDistance = 40.0;\r\n private numSections = 8;\r\n private needsUpdate;\r\n private sections: ArrowMarker[] = [];\r\n private defaultScale = new Vector3(1.0, 1.0, 1.0);\r\n private zoomedScale = new Vector3(1.2, 1.2, 1.2);\r\n\r\n constructor(viewer: Viewer, markers: CameraMarkers) {\r\n this.markers = markers;\r\n this.viewer = viewer;\r\n\r\n this.loadTextures();\r\n this.initMeshObject();\r\n this.clearNavigation();\r\n }\r\n\r\n get scene() {\r\n return this.markers.scene;\r\n }\r\n\r\n initMeshObject() {\r\n this.object = new Object3D();\r\n\r\n for (let section=0;section {\r\n arrow.clear();\r\n });\r\n }\r\n\r\n calculateCameras() {\r\n const calculating = this.viewer.calculatingSceneMarkers;\r\n if (calculating || !this.visible || !this.needsUpdate) {\r\n return;\r\n }\r\n\r\n this.needsUpdate = false;\r\n\r\n // Positions are precalculated when adding scene view markers\r\n let positions = this.markers.markerNavigation.markerPositions;\r\n\r\n this.clearNavigation();\r\n\r\n const cameraPos = this.viewer.camera.position;\r\n\r\n const validCameras = [];\r\n positions.forEach((markerPos, cameraIndex) => {\r\n let x = markerPos.x - cameraPos.x;\r\n let y = markerPos.y - cameraPos.y;\r\n\r\n const distance = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));\r\n\r\n // Calculate min and max distance from camera;\r\n let tooClose = distance < this.minDistance;\r\n let tooFar = distance > this.maxDistance;\r\n if (tooClose || tooFar) {\r\n return;\r\n }\r\n\r\n // Calculate section\r\n let angle = Math.atan2(y, x) * 180 / Math.PI;\r\n let section = this.angleToSection(angle);\r\n\r\n let camera = this.markers.cameras[cameraIndex];\r\n validCameras.push({camera, distance, section});\r\n });\r\n\r\n // Sort by distance\r\n validCameras.sort((a, b) => {\r\n return a.distance - b.distance;\r\n });\r\n\r\n validCameras.forEach(({camera, section}) => {\r\n if (this.sections[section].enabled) {\r\n return;\r\n }\r\n\r\n this.sections[section].setCamera(camera);\r\n this.sections[section].setVisible(true);\r\n });\r\n\r\n // Update mesh position\r\n this.object.position.copy(cameraPos);\r\n }\r\n\r\n onMouseMove(event) {\r\n this.sections.forEach(arrow => {\r\n arrow.setScale(this.defaultScale);\r\n });\r\n\r\n let object = this.getIntersect(event);\r\n if (!object) {\r\n return;\r\n }\r\n\r\n object.setScale(this.zoomedScale);\r\n }\r\n\r\n mouseClick(event) {\r\n let object = this.getIntersect(event);\r\n if (!object || !object.camera) {\r\n return null;\r\n }\r\n\r\n this.sections.forEach(arrow => {\r\n arrow.setVisible(false);\r\n });\r\n\r\n return object.camera.id;\r\n }\r\n\r\n /** @private */\r\n getIntersect(event) : ArrowMarker {\r\n if (!this.visible) {\r\n return;\r\n }\r\n\r\n let targets = this.sections.map(arrow => {\r\n return arrow.object.children[0];\r\n });\r\n\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let intersects = raycaster.intersectObjects(targets);\r\n if (intersects.length === 0) {\r\n return;\r\n }\r\n\r\n const intersect = intersects[0].object;\r\n const sectionID = intersect.userData.section;\r\n const object = this.sections[sectionID];\r\n\r\n return object;\r\n }\r\n\r\n update() {\r\n if (!this.object) {\r\n return;\r\n }\r\n\r\n this.calculateCameras();\r\n this.object.visible = this.visible;\r\n }\r\n}\r\n","import $ from 'jquery';\r\n\r\nlet binds = [];\r\n\r\nexport const bindWindowEvent = (name, callback) => {\r\n $(window).off(name);\r\n $(window).on(name, callback);\r\n binds.push(name);\r\n};\r\n\r\nexport const destroyWindowEvents = () => {\r\n binds.forEach(bind => {\r\n $(window).off(bind);\r\n });\r\n binds = [];\r\n};\r\n\r\n","import {Vector3} from \"three\";\r\nimport { CameraImage } from \"../cameras/cameras\";\r\nimport {Viewer} from \"../main\";\r\n\r\nclass ChangeDetector {\r\n private viewer;\r\n private previousFov = 0;\r\n private previousZoom = 0;\r\n private previousLookat = new Vector3();\r\n private previousCamera: CameraImage;\r\n private previousHeight = 0;\r\n private previousOrbit = false;\r\n public lookatChanged = false;\r\n public fovChanged = false;\r\n public zoomChanged = false;\r\n public cameraChanged = false;\r\n public heightChanged = false;\r\n public orbitChanged = false;\r\n public enabled = false;\r\n\r\n constructor(viewer: Viewer) {\r\n this.viewer = viewer;\r\n }\r\n\r\n get changed() {\r\n return this.lookatChanged\r\n || this.fovChanged\r\n || this.zoomChanged\r\n || this.cameraChanged\r\n || this.heightChanged\r\n || this.orbitChanged;\r\n }\r\n\r\n get map() {\r\n return this.viewer.minimap.map;\r\n }\r\n\r\n get camera() {\r\n return this.viewer.camera;\r\n }\r\n\r\n get newFov() {\r\n return this.camera.fov;\r\n }\r\n\r\n get newZoom() {\r\n return this.map.getView().getZoom();\r\n }\r\n\r\n get newLookat() {\r\n return this.viewer.lookat;\r\n }\r\n\r\n get newCamera() {\r\n return this.viewer.minimap.activeCamera;\r\n }\r\n\r\n get newHeight() {\r\n return this.viewer.height;\r\n }\r\n\r\n get newOrbit() {\r\n return this.viewer.orbitState;\r\n }\r\n\r\n update() {\r\n try {\r\n this.lookatChanged = !this.previousLookat.equals(this.newLookat);\r\n this.fovChanged = this.newFov !== this.previousFov;\r\n this.zoomChanged = this.newZoom !== this.previousZoom;\r\n this.cameraChanged = this.previousCamera !== this.newCamera;\r\n this.heightChanged = this.previousHeight !== this.newHeight;\r\n this.orbitChanged = this.previousOrbit !== this.newOrbit;\r\n\r\n this.previousZoom = this.newZoom;\r\n this.previousFov = this.newFov;\r\n this.previousLookat = this.newLookat;\r\n this.previousCamera = this.newCamera;\r\n this.previousHeight = this.newHeight;\r\n this.previousOrbit = this.newOrbit;\r\n } catch {\r\n // Nothing\r\n }\r\n };\r\n}\r\n\r\nexport default ChangeDetector;","import { BufferGeometry, Color, Points, Vector3 } from \"three\";\r\nimport { Camera } from \"three/src/cameras/Camera\";\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 { Viewer } from \"./main\";\r\nimport { eventToPixel } from \"./utilities\";\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, debug=false) {\r\n this.name = name;\r\n this.debug = debug;\r\n\r\n this.viewer = viewer;\r\n this.scene = new Scene();\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 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 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) {\r\n return null;\r\n }\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) {\r\n return;\r\n }\r\n\r\n this.clearSections();\r\n this.updateBaseIDs();\r\n\r\n this.needsUpdate = false;\r\n\r\n let oldRenderTarget = this.renderer.getRenderTarget();\r\n let oldClearColor = this.renderer.getClearColor();\r\n let oldClearAlpha = this.renderer.getClearAlpha();\r\n let newClearColor = new Color(0xffffff);\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: any) => {\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) {\r\n return;\r\n }\r\n\r\n if (child instanceof Points) {\r\n let geometry = child.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 ((index < minIndex) || (index > maxIndex)) {\r\n return;\r\n }\r\n\r\n // Use the returned index to get the xyz location\r\n let arrIndex = indices.indexOf(index);\r\n if (arrIndex === -1) {\r\n return;\r\n }\r\n\r\n object = child;\r\n }\r\n });\r\n\r\n return object;\r\n }\r\n\r\n getObjectPosition(mesh, index) {\r\n let coordinate = null;\r\n\r\n if (mesh instanceof Points) {\r\n let geometry = mesh.geometry as BufferGeometry;\r\n let indices = geometry.attributes.gpu_index.array as Array;\r\n let arrIndex = indices.indexOf(index);\r\n let positions = geometry.attributes.position;\r\n\r\n coordinate = new Vector3(\r\n positions.getX(arrIndex) + mesh.position.x,\r\n positions.getY(arrIndex) + mesh.position.y,\r\n positions.getZ(arrIndex) + mesh.position.z\r\n );\r\n }\r\n\r\n return coordinate;\r\n }\r\n}\r\n","import { createHash } from \"crypto\";\r\nimport { Color } from \"three\";\r\n\r\nconst parseHex = (text, min, max) => {\r\n return parseInt(text.slice(min, max), 16);\r\n};\r\n\r\nexport const textToColor = (text, opacity=1.0) => {\r\n let [r,g,b,a] = textToColorArray(text, opacity);\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","import { Viewer } from \"../main\";\r\nimport { SceneLabelTools, AerialLabelTools } from \".\";\r\nimport { nanoid } from \"@reduxjs/toolkit\";\r\nimport LocalScene, { isValidProjection } from \"../projections\";\r\nimport { textToColorArray } from \"./categories\";\r\nimport { ShapeUtils, Vector2 } from \"three\";\r\nimport {\r\n polygon as turfPolygon,\r\n simplify as turfSimplify,\r\n union as turfUnion\r\n} from '@turf/turf';\r\nimport { coordinatesToArray } from \"../misc\";\r\nimport { PanoramicImage, PlanarImage } from \"../cameras\";\r\n\r\nexport interface CocoCategory {\r\n supercategory: string,\r\n id: number,\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 trainingAreaId: 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\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 zoom() {\r\n console.warn(\"Not Implemented\");\r\n }\r\n\r\n setHighlighted(highlight) {\r\n console.warn(\"Not Implemented\");\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\r\nexport class LabelCategory {\r\n public id;\r\n public name;\r\n public labels: ImageLabel[] = [];\r\n\r\n constructor(name) {\r\n this.id = nanoid();\r\n this.name = name;\r\n }\r\n\r\n getLabelByID(labelID) {\r\n return this.labels.find(label => label.id === labelID);\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 featuresLayer() {\r\n console.warn(\"Not implemented\");\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.clear();\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 const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n label.clear();\r\n const index = this.labels.indexOf(label);\r\n this.labels.splice(index, 1);\r\n });\r\n }\r\n\r\n zoomToLabel(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n label.setHighlighted(true);\r\n label.zoom();\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 completeLabel(labelID) {\r\n const label = this.getLabelByID(labelID);\r\n if (!label) {\r\n return;\r\n }\r\n\r\n if (!label.hasEnoughPoints) {\r\n return false;\r\n }\r\n\r\n this.unSelectAll();\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 }\r\n\r\n}\r\n\r\nexport class ImageLabelTools {\r\n viewer: Viewer;\r\n public orthoLabels: AerialLabelTools;\r\n public sceneLabels: SceneLabelTools;\r\n private activeLabeler: AerialLabelTools | SceneLabelTools;\r\n //public trainingArea: LabelCategory;\r\n public categories: LabelCategory[] = [];\r\n private setCategoryList: Function;\r\n private setTrainingArea: Function;\r\n private currentCategory;\r\n private hotkeyEnabled = true;\r\n public contextMenuOpen = false;\r\n\r\n constructor(viewer: Viewer, props) {\r\n const {setCategoryList, setTrainingArea} = props;\r\n\r\n this.viewer = viewer;\r\n this.orthoLabels = new AerialLabelTools(this, props);\r\n this.sceneLabels = new SceneLabelTools(this, props);\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 return;\r\n }\r\n\r\n onKeyDown(event) {\r\n if (this.activeLabeler instanceof AerialLabelTools) {\r\n this.contextMenuOpen=false;\r\n }\r\n\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 this.addLabel(this.currentCategory.id);\r\n return;\r\n }\r\n }\r\n\r\n }\r\n\r\n 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 if (this.trainingArea) {\r\n this.trainingArea.labels.forEach(label => {\r\n if (label.highlighted) {\r\n count++;\r\n }\r\n });\r\n }\r\n\r\n return count;\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 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 checkIfActive() {\r\n if (!this.activeLabeler) {\r\n return false;\r\n }\r\n return true;\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) {\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 setCategories() {\r\n this.setCategoryList([...this.categories]);\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 addCategory(name, updateCategories=true) {\r\n if (!this.activeLabeler) {\r\n return;\r\n }\r\n\r\n let category = this.activeLabeler.getNewCategory(name);\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 if (updateCategories) {\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.getNewCategory(\"Training Area\");\r\n this.activeLabeler.setTrainingAreas(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.clear();\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 deleteAllCategories() {\r\n let categories = [...this.categories];\r\n categories.forEach(category => {\r\n this.deleteCategory(category.id);\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 AerialLabelTools)) {\r\n return;\r\n }\r\n\r\n\r\n this.activeLabeler.deleteTrainingArea();\r\n this.setCategories();\r\n }\r\n\r\n addTrainingAreaLabel(drawLabel=true, updateCategories=true) {\r\n if (this.activeLabeler instanceof SceneLabelTools) {\r\n return;\r\n }\r\n if (!this.trainingArea) {\r\n return;\r\n }\r\n\r\n const trainingArea = this.trainingArea;\r\n\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 if (updateCategories) {\r\n this.setCategories();\r\n }\r\n\r\n return label;\r\n }\r\n\r\n addLabel(categoryID, drawLabel=true, updateCategories=true) {\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 let label = category.addNewLabel(drawLabel);\r\n this.unSelectLabels();\r\n category.selectLabel(label.id);\r\n\r\n if (updateCategories) {\r\n this.setCategories();\r\n }\r\n\r\n return label;\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 if (this.trainingArea) {\r\n this.trainingArea.deleteLabel(labelID);\r\n }\r\n\r\n this.setCategories();\r\n this.activeLabeler.resetToolTipText();\r\n }\r\n\r\n deletePoint(pointID) {\r\n this.activeLabeler.deleteSpecificPoint(pointID);\r\n this.activeLabeler.contextMenuOpen = false;\r\n }\r\n\r\n zoomToLabel(labelID) {\r\n this.unHighlightAll();\r\n this.categories.forEach(category => {\r\n category.zoomToLabel(labelID);\r\n });\r\n if (this.trainingArea) {\r\n this.trainingArea.zoomToLabel(labelID);\r\n }\r\n }\r\n\r\n unHighlight(labelID) {\r\n this.categories.forEach(category => {\r\n category.unHighlight(labelID);\r\n });\r\n if (this.trainingArea) {\r\n this.trainingArea.unHighlight(labelID);\r\n }\r\n this.setCategories();\r\n this.activeLabeler.contextMenuOpen = false;\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 if (this.trainingArea) {\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 this.activeLabeler.contextMenuOpen = false;\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 if (this.trainingArea) {\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\r\n this.setCategories();\r\n this.activeLabeler.contextMenuOpen = false;\r\n }\r\n\r\n completeLabel(labelID) {\r\n let success = false;\r\n this.categories.forEach(category => {\r\n success = success || category.completeLabel(labelID);\r\n });\r\n\r\n if (this.trainingArea) {\r\n success = success || this.trainingArea.completeLabel(labelID);\r\n }\r\n\r\n this.setCategories();\r\n if (!success) {\r\n return;\r\n }\r\n\r\n this.activeLabeler.resetToolTipText();\r\n this.viewer.showMessage(\"Added label\", {\r\n variant: \"success\"\r\n });\r\n\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 if (this.trainingArea) {\r\n this.trainingArea.unHighlight(labelID);\r\n this.trainingArea.selectLabel(labelID);\r\n }\r\n\r\n this.activeLabeler.resetTemporaryPoint();\r\n this.setCategories();\r\n this.activeLabeler.contextMenuOpen = false;\r\n }\r\n\r\n unSelectLabels() {\r\n this.categories.forEach(category => {\r\n category.unSelectAll();\r\n });\r\n\r\n if (this.trainingArea) {\r\n this.trainingArea.unSelectAll();\r\n }\r\n\r\n }\r\n\r\n simplifyPolygon(points, tolerance=2, highQuality=false) {\r\n let newPoints = [...points, points[0]];\r\n\r\n let newPointsPolygon = turfPolygon([newPoints]);\r\n let options = {tolerance: tolerance, highQuality: highQuality};\r\n\r\n let simplified = turfSimplify(newPointsPolygon, options);\r\n let simplePolygon = simplified.geometry.coordinates[0];\r\n\r\n // console.log(`Simplify geometry: ${newPoints.length} => ${simplePolygon.length}`);\r\n\r\n simplePolygon.pop(); // remove duplicate point\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 < 2) {\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 let union = turfUnion(\r\n turfPolygon([polygonPoints1]),\r\n turfPolygon([polygonPoints2])\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 importLabelData(label, category, images, projection, progressData, isTrainingArea=false): Promise {\r\n let labelAddTimeout = 5;\r\n let addedLabel;\r\n\r\n return new Promise(async resolve => {\r\n let cameras = this.viewer.cameraList;\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 if (points.length < 3) {\r\n progressData.skippedLabels += 1;\r\n return;\r\n }\r\n\r\n if (this.activeLabeler instanceof AerialLabelTools) {\r\n // Simplify pixels and convert from image space to map coordinates\r\n points = this.simplifyPolygon(points);\r\n points = this.activeLabeler.pointsToAerial(\r\n points, imageData, projection);\r\n } else if (this.activeLabeler instanceof SceneLabelTools) {\r\n // Planar images cant be immediately simplified\r\n let camera = cameras.getByName(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;\r\n if (isTrainingArea) {\r\n newLabel = this.addTrainingAreaLabel(false, false);\r\n } else {\r\n newLabel = this.addLabel(category.id, false, false);\r\n }\r\n\r\n if (this.activeLabeler instanceof SceneLabelTools) {\r\n // Camera is required for scene tools\r\n\r\n let camera = cameras.getByName(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 // Update loading progress\r\n const {labelTotal, labelIndex} = progressData;\r\n progressData.progress = Math.min(100, (labelIndex+1)/labelTotal * 100);\r\n progressData.callback(progressData.progress);\r\n progressData.labelIndex += 1;\r\n\r\n setTimeout(() => {\r\n resolve(addedLabel);\r\n }, labelAddTimeout);\r\n });\r\n }\r\n\r\n addCategoryLabels(labels, category, images, projection, progressData, isTrainingArea=false): Promise {\r\n return new Promise(async resolve => {\r\n let labelsToMerge = {};\r\n\r\n // Add all new labels\r\n for (let label of labels) {\r\n let addedLabel = await this.importLabelData(label, category, images,\r\n projection, progressData, isTrainingArea);\r\n\r\n if (addedLabel) {\r\n const mergeID = label.merge_id;\r\n if (mergeID) {\r\n let previous = labelsToMerge[mergeID];\r\n labelsToMerge[mergeID] = previous\r\n ? [...previous, addedLabel]\r\n : [addedLabel];\r\n }\r\n }\r\n }\r\n\r\n labelsToMerge = Object.keys(labelsToMerge)\r\n .map(x => labelsToMerge[x]);\r\n\r\n resolve(labelsToMerge);\r\n });\r\n }\r\n\r\n async loadImageLabelData(data, progressCallback) {\r\n this.deleteAllCategories();\r\n\r\n let projection = data.projection;\r\n let categories = data.categories;\r\n let labels = data.annotations;\r\n let trainingAreas;\r\n if (data.hasOwnProperty('trainingAreas')) {\r\n trainingAreas = data.trainingAreas;\r\n }\r\n\r\n // Check for valid projection string\r\n let validProjection = isValidProjection(projection.string);\r\n if (!validProjection) {\r\n this.viewer.showMessage(\"Invalid projection string\", {\r\n variant: \"error\"\r\n });\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 if (trainingAreas) {\r\n let trainingAreaCategory = this.addTrainingArea();\r\n\r\n let areasToMerge = await this.addCategoryLabels(trainingAreas, trainingAreaCategory,\r\n images, projection, progressData, true);\r\n\r\n // Merge training data was 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 // Add new category\r\n let newCategory = this.addCategory(category.name, false);\r\n\r\n let labelsToMerge = await this.addCategoryLabels(newLabels, newCategory,\r\n images, projection, progressData);\r\n\r\n console.log(`Import labels for category ${newCategory.name}`);\r\n\r\n // Merge training data was was previously connected\r\n labelsToMerge.forEach(mergeList => {\r\n this.mergeTrainingLabels(newCategory, mergeList);\r\n });\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 [...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 // Complete all labels\r\n newCategory.labels.forEach(label => {\r\n newCategory.completeLabel(label.id);\r\n });\r\n\r\n };\r\n\r\n // Set labels to drawable\r\n this.categories.forEach(category => {\r\n category.labels.forEach(label => {\r\n label.setDrawable(true);\r\n });\r\n });\r\n\r\n if (this.trainingArea) {\r\n this.trainingArea.labels.forEach(label => {\r\n label.setDrawable(true);\r\n });\r\n }\r\n\r\n // Draw all new labels\r\n this.activeLabeler.drawAll();\r\n\r\n if (progressData.skippedLabels > 0) {\r\n this.viewer.showMessage(`Skipped ${progressData.skippedLabels} labels`, {\r\n variant: \"error\"\r\n });\r\n }\r\n\r\n setTimeout(() => {\r\n this.setCategories();\r\n progressCallback(0);\r\n this.activeLabeler.resetToolTipText();\r\n }, 500);\r\n }\r\n\r\n update(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 name: category.name,\r\n color: color\r\n } as CocoCategory;\r\n });\r\n\r\n\r\n let [annotations, trainingAreas] = this.activeLabeler.jsonLabelsObj();\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 };\r\n let newJsonObj;\r\n if (trainingAreas.length > 0) {\r\n newJsonObj = {...jsonObj, trainingAreas: trainingAreas}\r\n } else {\r\n newJsonObj = {...jsonObj}\r\n }\r\n\r\n return newJsonObj;\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(intersectPoints => {\r\n if (geometry.type === \"MultiPolygon\") {\r\n intersectPoints = intersectPoints[0];\r\n }\r\n\r\n if (removeDuplicate) {\r\n intersectPoints.pop(0);\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, trainingAreaIdx, mergeID) => {\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\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 trainingAreaId: trainingAreaIdx\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","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 { ProjectedCoordinate } from '../projections';\r\nimport {Feature} from \"ol\";\r\nimport {\r\n Circle as CircleStyle,\r\n Fill, Stroke, Style\r\n} from \"ol/style\";\r\nimport { AerialMap, extentFromPoints } from '../aerial/map';\r\nimport { textToColor } from './categories';\r\nimport { checkValidPolygon } from \"../utilities/polygon\";\r\nimport { transform } from 'ol/proj';\r\nimport { ImageLabelTools } from '.';\r\nimport {\r\n annotationFromPolygon,\r\n CocoImage,\r\n ImageLabel,\r\n LabelCategory,\r\n sectionsFromIntersection\r\n} from './image-label';\r\nimport { Color } from 'three';\r\nimport {\r\n polygon as turfPolygon,\r\n intersect as turfIntersect\r\n} from '@turf/turf';\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 private 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\nclass OrthoLabel extends ImageLabel {\r\n public features = [];\r\n public category: OrthoCategory\r\n private coordinates: Coordinate[] = [];\r\n public aerialMap: AerialMap;\r\n private minCoordinates = 3;\r\n private minPixelDistance = 5;\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 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 && oldPoint) {\r\n // Check for distance from previous point\r\n let pixelNew = this.map.getPixelFromCoordinate(newPoint.point);\r\n let pixelOld = this.map.getPixelFromCoordinate(oldPoint.point);\r\n\r\n let dU = pixelNew[0] - pixelOld[0];\r\n let dV = pixelNew[1] - pixelOld[1];\r\n let distance = Math.sqrt(dU**2 + dV**2);\r\n\r\n if (distance < this.minPixelDistance) {\r\n return true;\r\n }\r\n }\r\n\r\n this.coordinates.push(newPoint);\r\n return false;\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\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) {\r\n if (!this.drawable) {\r\n return;\r\n }\r\n\r\n this.clear();\r\n this.drawPoints(temporaryPoint);\r\n this.drawPolygon(temporaryPoint);\r\n this.setFeatureStyle();\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() {\r\n let positions = [...this.polygonPointsOnly];\r\n let extent = extentFromPoints(positions, false);\r\n this.aerialMap.setMapExtent(extent);\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\nclass 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 else if (this.name === \"Training Area\"){\r\n return `rgba(${0}, ${0}, ${0}, ${opacity})`;\r\n }\r\n else {\r\n return textToColor(this.name, opacity);\r\n }\r\n }\r\n\r\n getLayerStyle(valid=true, completed=true, highlighted=false) {\r\n let opacity = valid ? 0.2 : 0.0;\r\n opacity = (this.name === \"Training Area\") ? 0.0 : opacity;\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 source: new VectorSource({\r\n features: [],\r\n wrapX: false,\r\n noWrap: true\r\n }),\r\n style: this.getLayerStyle(),\r\n updateWhileInteracting: false,\r\n updateWhileAnimating: false\r\n });\r\n\r\n this.featuresLayer.setZIndex(1);\r\n this.map.addLayer(this.featuresLayer);\r\n\r\n this.editingLayer = new VectorLayer({\r\n source: new VectorSource({\r\n features: [],\r\n wrapX: false,\r\n noWrap: true\r\n }),\r\n style: this.getLayerStyle(),\r\n updateWhileInteracting: false,\r\n updateWhileAnimating: false\r\n });\r\n\r\n this.editingLayer.setZIndex(1);\r\n this.map.addLayer(this.editingLayer);\r\n }\r\n\r\n setCategories() {\r\n this.aerialTools.parent.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(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 parent: ImageLabelTools;\r\n public setPointDelete;\r\n public setPointAdd;\r\n public setCategoryList;\r\n public setAerialTooltipText;\r\n public contextMenuOpen = false;\r\n private dragObject: LabelPoint;\r\n private temporaryPoint: Coordinate;\r\n private contextMenuClick;\r\n public trainingAreas: OrthoCategory[] = [];\r\n\r\n\r\n private startTooltip = \"Click to start drawing polygon\";\r\n\r\n private dragTooltip = `Click and hold to move vertex\r\n
Right Click to delete point`;\r\n\r\n private highlightTooltip = `Right Click to select label\r\n
CTRL + Right Click to select multiple labels`;\r\n\r\n constructor(parent: ImageLabelTools, props) {\r\n const {setCategoryList, setAerialTooltipText, contextMenuClick} = props;\r\n\r\n this.parent = parent;\r\n this.setCategoryList = setCategoryList;\r\n this.setAerialTooltipText = setAerialTooltipText;\r\n this.contextMenuClick = contextMenuClick;\r\n\r\n this.init();\r\n }\r\n\r\n get categories() {\r\n return this.parent.categories\r\n .filter(x => x instanceof OrthoCategory) as OrthoCategory[];\r\n }\r\n\r\n get trainingArea() {\r\n return (this.trainingAreas.length > 0) ? this.trainingAreas[0] : null;\r\n }\r\n\r\n get viewer() {\r\n return this.parent.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 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 if (this.trainingArea) {\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 Click to add more points (${this.numPoints})\r\n
Delete Key to remove last point\r\n ${(this.numPoints > 1) ? \"
Double-click to finish\" : \"\"}\r\n
Right-click to remove label\r\n `;\r\n }\r\n\r\n get invalidTooltip() {\r\n return `\r\n Polygon is invalid due to self-intersection\r\n
Click to add more points (${this.numPoints})\r\n
Delete Key to remove last point\r\n ${(this.numPoints > 1) ? \"
Double-click to finish\" : \"\"}\r\n
Right-click to remove label\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 if (this.trainingArea) {\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 if (this.trainingArea) {\r\n this.trainingArea.labels.forEach(label =>\r\n selected = (selected || label.selected)\r\n );\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 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 init() {\r\n this.map.on('click', event => {\r\n this.mouseClick(event);\r\n });\r\n\r\n this.map.on('dblclick', event => {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n });\r\n\r\n // Check for mouse move\r\n this.map.on('pointermove', event => {\r\n this.onMouseMove(event);\r\n });\r\n\r\n // Check for right click\r\n window.addEventListener('mouseup', event => {\r\n this.onMouseUp(event);\r\n }, false);\r\n }\r\n\r\n completeLabel(label: OrthoLabel) {\r\n this.resetTemporaryPoint();\r\n this.parent.completeLabel(label.id);\r\n this.markLastPointDraggable(label);\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.setDragObject(lastPoint);\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n this.resetToolTipText();\r\n }\r\n\r\n setDragObject(object) {\r\n if (object instanceof LabelPoint) {\r\n this.dragObject = object;\r\n this.aerialMap.setDragState(false);\r\n this.setPointGrabTooltip();\r\n } else if (object instanceof LabelPolygon) {\r\n this.setHighlightTooltip();\r\n } else {\r\n this.dragObject = object;\r\n this.aerialMap.setDragState(true);\r\n this.resetToolTipText();\r\n }\r\n }\r\n\r\n setTrainingAreas(area: OrthoCategory) {\r\n this.trainingAreas = [area];\r\n }\r\n\r\n deleteTrainingArea() {\r\n this.trainingArea.labels.forEach(label => {\r\n label.clear();\r\n });\r\n\r\n this.trainingAreas.splice(0, 1);\r\n }\r\n\r\n mouseClick(event) {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n let label = this.activeLabel;\r\n if (!label) {\r\n return;\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;\r\n }\r\n\r\n this.setToolTipText();\r\n this.resetTemporaryPoint();\r\n this.drawActiveLabel();\r\n }\r\n\r\n onMouseMove(event) {\r\n if (!this.enabled) {\r\n return;\r\n }\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 // Dragging existing point\r\n if (event.dragging) {\r\n if (this.dragObject) {\r\n let {label, index} = this.dragObject;\r\n label.updatePoint(event.coordinate, index);\r\n label.draw();\r\n }\r\n\r\n return;\r\n }\r\n\r\n this.checkFeatureHover(event);\r\n }\r\n\r\n onMouseUp(event) {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n if (event.button === 0) {\r\n this.contextMenuOpen = false;\r\n }\r\n\r\n let label = this.activeLabel;\r\n const isRightClick = (event.button === 2);\r\n const noneHighlighted = (this.parent.numHighlighted() === 0);\r\n const oneHighlighted = (this.parent.numHighlighted() === 1);\r\n\r\n if (!label && !this.selected && isRightClick) {\r\n if (noneHighlighted && !event.ctrlKey && !this.contextMenuOpen) {\r\n let highlightedFeature = this.highlightLabel(event);\r\n\r\n if (highlightedFeature) {\r\n let isPoint = (highlightedFeature instanceof LabelPoint) ? highlightedFeature.index : null;\r\n let highlightedLabel = highlightedFeature.label;\r\n this.contextMenuClick(event, isPoint, highlightedLabel.id);\r\n this.contextMenuOpen = true;\r\n }\r\n }\r\n\r\n else if (oneHighlighted && !event.ctrlKey && !this.contextMenuOpen) {\r\n this.parent.unHighlightAll();\r\n let highlightedFeature = this.highlightLabel(event);\r\n\r\n if (highlightedFeature) {\r\n let isPoint = (highlightedFeature instanceof LabelPoint) ? highlightedFeature.index : null;\r\n let highlightedLabel = highlightedFeature.label;\r\n this.contextMenuClick(event, isPoint, highlightedLabel.id);\r\n this.contextMenuOpen = true;\r\n }\r\n }\r\n\r\n else if (event.ctrlKey && !this.contextMenuOpen) {\r\n this.highlightLabel(event);\r\n }\r\n\r\n else {\r\n this.contextMenuClick(event);\r\n this.contextMenuOpen = true;\r\n }\r\n\r\n }\r\n\r\n else if (isRightClick && (this.selected)) {\r\n this.parent.deleteLabel(label.id);\r\n }\r\n\r\n else {\r\n return;\r\n }\r\n }\r\n\r\n checkFeatureHover(event) {\r\n let featurePoint = this.getFeatureAtPixel(event,\r\n this.pointFeaturesForExtent);\r\n\r\n if (featurePoint) {\r\n this.setDragObject(featurePoint);\r\n return;\r\n }\r\n\r\n let featurePoly = this.getFeatureAtPixel(event,\r\n this.polygonFeaturesForExtent);\r\n\r\n if (featurePoly) {\r\n this.setDragObject(featurePoly);\r\n return;\r\n }\r\n\r\n this.setDragObject(null);\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 setToolTipText() {\r\n const started = (this.numPoints === 0);\r\n let helpMsg = started ? this.startTooltip : this.moreTooltip;\r\n helpMsg = this.activeLabel.valid ? helpMsg : this.invalidTooltip;\r\n this.setAerialTooltipText(helpMsg);\r\n }\r\n\r\n highlightLabel(event) {\r\n let pixel = [event.offsetX, event.offsetY];\r\n let features = this.map.getFeaturesAtPixel(pixel).filter(x => {\r\n return (x instanceof LabelPoint) || (x instanceof LabelPolygon);\r\n });\r\n if (features.length === 0) {\r\n return;\r\n }\r\n\r\n features = features.filter(x => {\r\n return (x.label.category.name !== \"Training Area\");\r\n });\r\n\r\n if (features.length === 0) {\r\n return;\r\n }\r\n\r\n let label = features[0].label;\r\n label.setHighlighted(!label.highlighted);\r\n this.parent.setCategories();\r\n\r\n return features[0];\r\n }\r\n\r\n resetToolTipText() {\r\n this.setAerialTooltipText(\"\");\r\n }\r\n\r\n setPointGrabTooltip() {\r\n this.setAerialTooltipText(this.dragTooltip);\r\n }\r\n\r\n setHighlightTooltip() {\r\n this.setAerialTooltipText(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);\r\n });\r\n });\r\n if (this.trainingArea) {\r\n this.trainingArea.labels.forEach(label => {\r\n label.draw(this.temporaryPoint);\r\n });\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 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.parent.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.parent.unHighlight(label.id);\r\n }\r\n })\r\n );\r\n\r\n if (this.trainingArea) {\r\n this.trainingArea.labels.forEach(label => {\r\n if (label.highlighted && (label.numPoints > 3)) {\r\n label.removeSpecificPoint(id);\r\n this.parent.unHighlight(label.id);\r\n }\r\n });\r\n }\r\n\r\n this.parent.setCategories();\r\n }\r\n\r\n resetTemporaryPoint() {\r\n this.temporaryPoint = null;\r\n }\r\n\r\n polygonInImage = (polygonPoints, trainingAreas, imageList, imageIds) => {\r\n let imagesWithPolygon = [];\r\n let imageIdsFinal = [];\r\n let polyPointRing = [...polygonPoints, polygonPoints[0]];\r\n\r\n trainingAreas.forEach((trainingAreaInPixels, idx) => {\r\n\r\n let image = imageList[imageIds[idx]];\r\n let pointsOriginalProj = image.transform(polyPointRing);\r\n const polygonInPixels = this.calculatePolygonPixels(\r\n pointsOriginalProj, image.metadata);\r\n\r\n let intersection = turfIntersect(\r\n turfPolygon([polygonInPixels]),\r\n turfPolygon([trainingAreaInPixels])\r\n );\r\n\r\n let intersectionData = sectionsFromIntersection(intersection);\r\n intersectionData.forEach((arr) => {\r\n imagesWithPolygon.push(arr);\r\n imageIdsFinal.push(imageIds[idx]);\r\n });\r\n });\r\n\r\n return [imagesWithPolygon, imageIdsFinal];\r\n }\r\n\r\n trainingAreaInImage = (imageList) => {\r\n let imagesWithTrainingArea = [];\r\n let imageIds = [];\r\n let trainingAreaIds = [];\r\n let validTrainingAreas = [];\r\n let trainingAreaUsed = false;\r\n\r\n if (this.trainingArea) {\r\n validTrainingAreas = this.trainingArea.labels.filter(label => label.isValid);\r\n trainingAreaUsed = (validTrainingAreas.length > 0) ? true : false;\r\n }\r\n\r\n imageList.forEach((image, imageId) => {\r\n\r\n let imageInPixels = [\r\n [0, 0],\r\n [0, image.originalSize[1]],\r\n [image.originalSize[0], image.originalSize[1]],\r\n [image.originalSize[0], 0],\r\n [0, 0]\r\n ];\r\n\r\n\r\n if (trainingAreaUsed) {\r\n validTrainingAreas.forEach((label, areaId) => {\r\n\r\n // Get trainingArea where it is inside the image\r\n let trainingAreaPoints = label.polygonPointsOnly;\r\n\r\n let trainingAreaRing = [...trainingAreaPoints, trainingAreaPoints[0]];\r\n let trainingAreaOriginalProj = image.transform(trainingAreaRing);\r\n const trainingAreaInPixels = this.calculatePolygonPixels(\r\n trainingAreaOriginalProj, image.metadata);\r\n\r\n let intersection = turfIntersect(\r\n turfPolygon([trainingAreaInPixels]),\r\n turfPolygon([imageInPixels])\r\n );\r\n\r\n let intersectionData = sectionsFromIntersection(intersection, false);\r\n intersectionData.forEach((arr) => {\r\n imagesWithTrainingArea.push(arr);\r\n imageIds.push(imageId);\r\n trainingAreaIds.push(areaId+1);\r\n });\r\n\r\n });\r\n }\r\n else {\r\n imagesWithTrainingArea.push(imageInPixels);\r\n imageIds.push(imageId);\r\n }\r\n });\r\n return [imagesWithTrainingArea, imageIds, trainingAreaIds];\r\n }\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 pointsToAerial(points, image, 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\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 jsonLabelsObj() {\r\n let labelIndex = 1;\r\n let mergeIndex = 1;\r\n let annotations = [];\r\n let trainingAreas = [];\r\n\r\n let [trainingAreaInImage, imageIds, trainingAreaIds] = this.trainingAreaInImage(this.visibleOrthos);\r\n\r\n let trainingAreaUsed = trainingAreaIds.length > 0;\r\n\r\n trainingAreaInImage.forEach((polygon, index) => {\r\n let trainingAreaIdx = null;\r\n if (trainingAreaUsed) {\r\n trainingAreaIdx = trainingAreaIds[index]\r\n }\r\n\r\n let trainingArea = annotationFromPolygon(\r\n polygon,\r\n labelIndex,\r\n 0,\r\n imageIds[index],\r\n index,\r\n trainingAreaUsed ? trainingAreaIds[index] : null\r\n );\r\n\r\n trainingAreas.push(trainingArea);\r\n labelIndex++;\r\n });\r\n\r\n this.categories.forEach((category, categoryID) => {\r\n category.labels.forEach(label => {\r\n if (!label.valid) {\r\n return;\r\n }\r\n\r\n let [polygonsInside, imageIdsFinal] = this.polygonInImage(\r\n label.polygonPointsOnly, trainingAreaInImage, this.visibleOrthos, imageIds);\r\n\r\n let uniqueIds = Array.from(new Set(imageIds));\r\n let mergeable = uniqueIds.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 imageIdsFinal[index],\r\n index,\r\n mergeable ? mergeIndex : null\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 if (trainingAreaUsed){\r\n return [annotations, trainingAreas];\r\n } else {\r\n return [annotations, []];\r\n }\r\n\r\n };\r\n}\r\n","import { RayCaster } from \"../controls\";\r\nimport { setPointScale } from '../utilities';\r\nimport earcut from 'earcut';\r\nimport {\r\n BufferGeometry,\r\n Color,\r\n DoubleSide,\r\n Face3,\r\n Geometry,\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/polygon\";\r\nimport { textToColor } from \"./categories\";\r\nimport {\r\n CameraImage,\r\n CameraLoadOptions,\r\n ImagePixel,\r\n PanoramicImage,\r\n PlanarImage\r\n} from \"../cameras/cameras\";\r\nimport { ImageLabelTools } from \".\";\r\nimport {\r\n annotationFromPolygon,\r\n CocoImage,\r\n ImageLabel,\r\n LabelCategory,\r\n sectionsFromIntersection\r\n} from \"./image-label\";\r\nimport {\r\n booleanContains,\r\n intersect as turfIntersect,\r\n point as turfPoint,\r\n polygon as turfPolygon\r\n} from \"@turf/turf\";\r\nimport { Viewer } from \"../main\";\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\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.viewer;\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 opacityMeshes = [];\r\n private pointGeometry: SphereGeometry;\r\n private pointMaterial: MeshBasicMaterial;\r\n private lineGeometry: BufferGeometry;\r\n private lineMaterial: LineBasicMaterial;\r\n private lineDashedMaterial: LineDashedMaterial;\r\n private polygonMaterial: MeshBasicMaterial;\r\n private minPixelDistance = 5;\r\n private minPoleAngle = 25;\r\n\r\n constructor(category: SceneCategory, camera: CameraImage) {\r\n super();\r\n this.category = category;\r\n this.pointGeometry = new SphereGeometry(0.05, 20, 20);\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 opacityScene() {\r\n return this.category.sceneLabels.opacityScene;\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.pointMaterial = 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 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 /** @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.pointGeometry,\r\n this.pointMaterial, 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 setPointScale(this.viewer, 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 this.valid = checkValidPolygon(coordinates2d);\r\n\r\n // Panoramic images arent valid at the poles\r\n if (this.camera instanceof PanoramicImage) {\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 > 1E-6) {\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 geom = new Geometry();\r\n\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 geom.vertices.push(\r\n positions[indices[3 * i]],\r\n positions[indices[3 * i + 1]],\r\n positions[indices[3 * i + 2]]\r\n );\r\n let face = new Face3(0, 1, 2);\r\n geom.faces.push(face);\r\n\r\n let mesh = new LabelPolygon(geom, this.polygonMaterial, this);\r\n this.opacityMeshes.push(mesh);\r\n this.opacityScene.add(mesh);\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 this.drawPoints(temporaryPoint);\r\n this.drawLines(temporaryPoint);\r\n this.drawPolygons(temporaryPoint);\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 && oldPoint) {\r\n // Check for distance from previous point\r\n let dU = newPoint.pixel.u - oldPoint.pixel.u;\r\n let dV = newPoint.pixel.v - oldPoint.pixel.v;\r\n let distance = Math.sqrt(dU**2 + dV**2);\r\n\r\n if (distance < this.minPixelDistance) {\r\n return true;\r\n }\r\n }\r\n\r\n this.coordinates.push(newPoint);\r\n return false;\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 return booleanContains(\r\n turfPolygon([polyPointRing]),\r\n turfPoint([0, 0])\r\n );\r\n }\r\n\r\n getCameraBestFit(): CameraLoadOptions {\r\n // Calculate average direction vector\r\n let average = new Vector3();\r\n this.directions.forEach(x => average.add(x));\r\n average.divideScalar(this.directions.length);\r\n\r\n let fovRequired = this.directions.map(direction => {\r\n let angle = direction.angleTo(average);\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 let fov = Math.max(...fovRequired) * 1.10;\r\n\r\n return {fov, direction: average};\r\n }\r\n\r\n clear() {\r\n this.standardMeshes.forEach(mesh => {\r\n this.standardScene.remove(mesh);\r\n mesh.geometry.dispose();\r\n mesh.material.dispose();\r\n });\r\n\r\n this.opacityMeshes.forEach(mesh => {\r\n this.opacityScene.remove(mesh);\r\n mesh.geometry.dispose();\r\n mesh.material.dispose();\r\n });\r\n\r\n this.standardMeshes = [];\r\n this.opacityMeshes = [];\r\n }\r\n\r\n zoom() {\r\n // The camera must be loaded before we are able to\r\n // calculate the best fit position, so we calculate\r\n // these values in the loaded callback\r\n const cameraID = this.camera.id;\r\n\r\n // Load camera and set position in callback\r\n this.viewer.setCameraVisible(cameraID, {\r\n onLoaded: () => {\r\n let opts = this.getCameraBestFit();\r\n this.viewer.setCameraVisible(cameraID, opts);\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.parent.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(drawLabel);\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 parent: ImageLabelTools;\r\n public standardScene: Scene;\r\n public opacityScene: Scene;\r\n private setViewerTooltipText;\r\n public enabled = false;\r\n public opacity = 0.2;\r\n public contextMenuOpen = false;\r\n private contextMenuClick;\r\n private polygonHover = false;\r\n\r\n private temporaryPoint: Coordinate;\r\n public movingEndpoint = false;\r\n public draggable = false;\r\n private dragObject: LabelPoint = null;\r\n\r\n private startTooltip = \"Click to start drawing polygon\";\r\n\r\n private dragTooltip = `Click and hold to move vertex\r\n
Right Click to select point`;\r\n\r\n private highlightTooltip = `Right Click to select label\r\n
CTRL + Right Click to select multiple labels`;\r\n\r\n constructor(parent: ImageLabelTools, props) {\r\n const {setViewerTooltipText, contextMenuClick} = props;\r\n\r\n this.parent = parent;\r\n this.standardScene = new Scene();\r\n this.opacityScene = new Scene();\r\n this.setViewerTooltipText = setViewerTooltipText;\r\n this.contextMenuClick = contextMenuClick;\r\n\r\n window.addEventListener('keydown', event => {\r\n this.onKeyDown(event);\r\n }, false);\r\n }\r\n\r\n get categories() {\r\n return this.parent.categories\r\n .filter(x => x instanceof SceneCategory) as SceneCategory[];\r\n }\r\n\r\n get viewer() {\r\n return this.parent.viewer;\r\n }\r\n\r\n get cameraList() {\r\n return this.viewer.cameraList;\r\n }\r\n\r\n get currentCamera() {\r\n let current = this.cameraList.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 Click to add more points (${this.activeLabel.numPoints})\r\n
Delete Key to remove last point\r\n ${(this.activeLabel.numPoints > 1) ? \"
Double-click to finish\" : \"\"}\r\n
Right-click to remove label\r\n `;\r\n }\r\n\r\n get invalidTooltip() {\r\n let isPanoramic = this.activeLabel.camera instanceof PanoramicImage;\r\n let extraText = isPanoramic ? \"or closeness to poles\" : \"\";\r\n\r\n return `\r\n Polygon is invalid due to self-intersection ${extraText}\r\n
Click to add more points (${this.activeLabel.numPoints})\r\n ${(this.activeLabel.numPoints > 1) ? \"
Double-click to finish\" : \"\"}\r\n
Right-click to remove label\r\n `;\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 loadedImagePaths() {\r\n let imageList = this.viewer.cameraList;\r\n return imageList.cameras.map(image => image.path);\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n this.resetToolTipText();\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.vectorFromEvent(event);\r\n return direction;\r\n }\r\n\r\n getImagePixel(event): [boolean, ImagePixel] {\r\n const direction = this.getClickedDirection(event);\r\n const [valid, pixel] = this.currentCamera\r\n .directionToPixel(direction);\r\n\r\n return [valid, pixel];\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.parent.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.parent.unHighlight(label.id);\r\n }\r\n })\r\n );\r\n this.contextMenuOpen = false;\r\n this.parent.setCategories();\r\n }\r\n\r\n highlightLabel(event) {\r\n if (this.drawing) {\r\n return;\r\n }\r\n\r\n let targets = [\r\n ...this.standardScene.children.filter(x => (x instanceof LabelPoint)),\r\n ...this.opacityScene.children.filter(x => (x instanceof LabelPolygon))\r\n ];\r\n\r\n if (targets.length === 0) {\r\n return;\r\n }\r\n\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let intersectedTargets = raycaster.intersectObjects(targets);\r\n if (intersectedTargets.length === 0) {\r\n return;\r\n }\r\n\r\n let selected = intersectedTargets[0].object;\r\n let label = selected.label;\r\n label.setHighlighted(!label.highlighted);\r\n this.parent.setCategories();\r\n\r\n return selected;\r\n }\r\n\r\n mouseClick(event) {\r\n\r\n if (!this.currentCamera) {\r\n return;\r\n }\r\n\r\n let label = this.activeLabel;\r\n if (!label) {\r\n return;\r\n }\r\n\r\n let [valid, point] = this.getImagePixel(event);\r\n if (!valid) {\r\n return;\r\n }\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.parent.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.setDragObject(lastPoint);\r\n }\r\n\r\n cancelLabel() {\r\n let label = this.activeLabel;\r\n if (!label) {\r\n return;\r\n }\r\n\r\n this.parent.deleteLabel(label.id);\r\n this.setToolTipText();\r\n this.drawAll();\r\n }\r\n\r\n checkPointSelected(event) {\r\n if (this.drawing) {\r\n return;\r\n }\r\n\r\n let targetPoly = this.opacityScene.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 dragObject = null;\r\n let polygonHover = false;\r\n\r\n if (targets.length > 0) {\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let objects = raycaster.intersectObjects(targets);\r\n objects = objects.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 let draggable = points.length > 0;\r\n dragObject = draggable ? points[0] : null;\r\n\r\n polygonHover = (polygons.length > 0);\r\n }\r\n\r\n this.setPolygonHover(polygonHover);\r\n this.setDragObject(dragObject);\r\n }\r\n\r\n updateDraggablePoint(event) {\r\n let coordinate = this.dragObject.coordinate;\r\n let [valid, point] = this.getImagePixel(event);\r\n if (!valid) {\r\n return;\r\n }\r\n\r\n coordinate.updateValues(point);\r\n this.drawAll();\r\n }\r\n\r\n setDragObject(dragObject) {\r\n this.dragObject = dragObject;\r\n\r\n if (dragObject) {\r\n this.setPointGrabTooltip();\r\n }\r\n }\r\n\r\n setPolygonHover(hovering) {\r\n this.polygonHover = hovering;\r\n }\r\n\r\n setToolTipText() {\r\n if (!this.activeLabel) {\r\n this.resetToolTipText();\r\n return;\r\n }\r\n\r\n let text = \"\";\r\n if (this.drawing) {\r\n text = this.activeLabel.valid\r\n ? this.moreTooltip\r\n : this.invalidTooltip;\r\n } else {\r\n if (this.currentCamera) {\r\n text = this.startTooltip;\r\n }\r\n }\r\n\r\n this.setViewerTooltipText(text);\r\n }\r\n\r\n resetToolTipText() {\r\n this.setViewerTooltipText(\"\");\r\n }\r\n\r\n setPointGrabTooltip() {\r\n this.setViewerTooltipText(this.dragTooltip);\r\n }\r\n\r\n setPolygonHoverTooltip() {\r\n this.setViewerTooltipText(this.highlightTooltip);\r\n }\r\n\r\n resetTemporaryPoint() {\r\n this.temporaryPoint = null;\r\n }\r\n\r\n highlightOnClick(event) {\r\n\r\n let labelHighlighted = false;\r\n const noneHighlighted = (this.parent.numHighlighted() === 0);\r\n const oneHighlighted = (this.parent.numHighlighted() === 1);\r\n\r\n if (noneHighlighted && !event.ctrlKey && !this.contextMenuOpen) {\r\n let highlightedFeature = this.highlightLabel(event);\r\n\r\n if (highlightedFeature) {\r\n labelHighlighted = true;\r\n let isPoint = (highlightedFeature instanceof LabelPoint) ? highlightedFeature.index : null;\r\n let highlightedLabel = highlightedFeature.label;\r\n this.contextMenuClick(event, isPoint, highlightedLabel.id);\r\n this.contextMenuOpen = true;\r\n }\r\n }\r\n\r\n else if (oneHighlighted && !event.ctrlKey && !this.contextMenuOpen) {\r\n this.parent.unHighlightAll();\r\n let highlightedFeature = this.highlightLabel(event);\r\n\r\n if (highlightedFeature) {\r\n labelHighlighted = true;\r\n let isPoint = (highlightedFeature instanceof LabelPoint) ? highlightedFeature.index : null;\r\n let highlightedLabel = highlightedFeature.label;\r\n this.contextMenuClick(event, isPoint, highlightedLabel.id);\r\n this.contextMenuOpen = true;\r\n }\r\n }\r\n\r\n else if (event.ctrlKey && !this.contextMenuOpen) {\r\n let highlightedFeature = this.highlightLabel(event);\r\n\r\n if (highlightedFeature) {\r\n labelHighlighted = true;\r\n }\r\n }\r\n\r\n return labelHighlighted;\r\n }\r\n\r\n onMouseMove(event, mouse = null) {\r\n const mouseMoved = mouse ? mouse.movement : false;\r\n const mouseDown = mouse ? mouse.down : false;\r\n const isLeftClick = mouse ? mouse.button === 0 : false;\r\n\r\n this.resetTemporaryPoint();\r\n this.movingEndpoint = false;\r\n\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n if (!mouseMoved && !mouseDown) {\r\n this.checkPointSelected(event);\r\n }\r\n\r\n if (mouse === null) {\r\n return;\r\n }\r\n\r\n if (this.drawing) {\r\n let [valid, point] = this.getImagePixel(event);\r\n if (!valid) {\r\n return;\r\n }\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.dragObject) {\r\n this.setPointGrabTooltip();\r\n if (mouseDown) {\r\n if (isLeftClick) {\r\n this.updateDraggablePoint(event);\r\n }\r\n this.movingEndpoint = true;\r\n return;\r\n }\r\n }\r\n else if (this.polygonHover) {\r\n this.setPolygonHoverTooltip();\r\n }\r\n else {\r\n this.setToolTipText();\r\n }\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.parent.completeLabel(label.id);\r\n }\r\n }\r\n }\r\n\r\n drawAll() {\r\n this.standardScene.clear();\r\n this.opacityScene.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(\r\n 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 // Compute sections for left polygon\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 intersectionLeft = turfIntersect(\r\n turfPolygon([polyPointRing]),\r\n turfPolygon([imageBordersLeft]),\r\n );\r\n\r\n let intersectionDataLeft = sectionsFromIntersection(intersectionLeft);\r\n intersectionDataLeft.forEach((arr) => {\r\n sections.push(arr);\r\n });\r\n\r\n // Compute sections for right polygon\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 let intersectionRight = turfIntersect(\r\n turfPolygon([polyPointRing]),\r\n turfPolygon([imageBordersRight]),\r\n );\r\n\r\n let intersectionDataRight = sectionsFromIntersection(intersectionRight);\r\n intersectionDataRight.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 horizontalShift = 0;\r\n\r\n for (var i=0;i {\r\n return (x[0] + i) % imageWidth;\r\n });\r\n\r\n let spread = Math.max(...x) - Math.min(...x);\r\n if (spread < minSpread) {\r\n horizontalShift = i;\r\n minSpread = spread;\r\n }\r\n }\r\n\r\n return horizontalShift;\r\n }\r\n\r\n polygonInImage(label: SceneLabel) {\r\n let sections = [];\r\n\r\n let pixels = label.pixels;\r\n let image = label.camera;\r\n\r\n let imageWidth = label.imageWidth;\r\n let imageHeight = label.imageHeight;\r\n\r\n let coordinates = pixels.map(x => [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 sections = this.calculatePanoramicSections(\r\n polyPointRing, image, imageWidth, imageHeight);\r\n } else {\r\n return sections;\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 jsonLabelsObj() {\r\n let labelIndex = 1;\r\n let mergeIndex = 1;\r\n let annotations = [];\r\n\r\n this.categories.forEach((category, categoryID) => {\r\n category.labels.forEach(label => {\r\n if (!label.valid) {\r\n return;\r\n }\r\n\r\n const imageID = this.visibleCameras.indexOf(label.camera);\r\n const polygonsInside = this.polygonInImage(label);\r\n\r\n let 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 index,\r\n mergeable ? mergeIndex : null\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 update(changeDetector) {\r\n const update = changeDetector.changed;\r\n if (!update) {\r\n return;\r\n }\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 setPointScale(this.viewer, mesh);\r\n }\r\n });\r\n }\r\n}\r\n\r\n","class UnitConverter {\r\n private metresToSurveyFeetRatio = 1200 / 3937;\r\n private metresToFeetRatio = 0.3048;\r\n private allowedUnits = new Set(['ft', 'sft', 'm']);\r\n\r\n public convert(value, fromUnits, toUnits) {\r\n if (!this.allowedUnits.has(fromUnits) || !this.allowedUnits.has(toUnits)) {\r\n throw new Error('Units must either be \"m\", \"sft\", or \"ft\"');\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 if (fromUnits === toUnits) {\r\n return value;\r\n }\r\n\r\n let convertedValue = value;\r\n\r\n if (fromUnits === 'ft' || fromUnits === 'sft') {\r\n convertedValue *= (fromUnits === 'ft' ? this.metresToFeetRatio : this.metresToSurveyFeetRatio);\r\n }\r\n\r\n if (toUnits === 'ft' || toUnits === 'sft') {\r\n convertedValue /= (toUnits === 'ft' ? this.metresToFeetRatio : this.metresToSurveyFeetRatio);\r\n }\r\n\r\n return convertedValue;\r\n }\r\n}\r\n\r\nexport default new UnitConverter();\r\n","import $ from 'jquery';\r\nimport MeasurementController from \"./measurement-controller\";\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 {getArea, getLength} from 'ol/sphere';\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 './aerial-tooltip.css';\r\n\r\nexport default class MinimapMeasure {\r\n private controller: MeasurementController;\r\n private sourceStandard: VectorSource;\r\n private vectorStandard: VectorLayer;\r\n private sourceHover: VectorSource\r\n private vectorHover: VectorLayer\r\n\r\n private pointerMoveHandler;\r\n public enabled = false;\r\n public measurementType = null;\r\n public sketch = null;\r\n private measureTooltipElement = null;\r\n private measureTooltip = null;\r\n private draw = null;\r\n private initialized = false;\r\n\r\n constructor(controller) {\r\n this.controller = controller;\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 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 === \"Polygon\")\r\n ? numPoints > 2\r\n : true;\r\n\r\n return `\r\n Click to add more points (${numPoints})\r\n ${canFinish ? \"
Double-click to finish\" : \"\"}\r\n
Right-click to cancel\r\n `;\r\n }\r\n\r\n get startTooltip() {\r\n if (this.measurementType === \"LineString\") {\r\n return \"Click to start drawing line\";\r\n }\r\n\r\n if (this.measurementType === \"Polygon\") {\r\n return \"Click to start drawing polygon\";\r\n }\r\n\r\n return \"Invalid measure type\";\r\n }\r\n\r\n setMeasurementType(measurementType) {\r\n // Only standard and area and valid for aerial\r\n if (measurementType === 'standard') {\r\n this.setAsLength();\r\n } else if (measurementType === 'area') {\r\n this.setAsArea();\r\n } else {\r\n this.setAsNull();\r\n }\r\n }\r\n\r\n setAsLength() {\r\n this.measurementType = \"LineString\";\r\n this.reloadInteraction();\r\n }\r\n\r\n setAsArea() {\r\n this.measurementType = \"Polygon\";\r\n this.reloadInteraction();\r\n }\r\n\r\n setAsNull() {\r\n this.measurementType = null;\r\n this.reloadInteraction();\r\n this.removeInteraction();\r\n }\r\n\r\n init() {\r\n if (this.initialized) {\r\n return;\r\n }\r\n\r\n let fill = new Fill({\r\n color: 'rgba(255, 255, 255, 0.2)'\r\n });\r\n\r\n let image = new CircleStyle({\r\n radius: 7,\r\n fill: new Fill({\r\n color: '#008B8B'\r\n })\r\n });\r\n\r\n this.sourceStandard = new VectorSource({\r\n wrapX: false,\r\n noWrap: true\r\n });\r\n\r\n this.vectorStandard = new VectorLayer({\r\n type: 'measure',\r\n source: this.sourceStandard,\r\n style: new Style({\r\n fill: fill,\r\n image: image,\r\n stroke: new Stroke({\r\n color: '#008B8B',\r\n width: 2\r\n })\r\n })\r\n });\r\n\r\n this.sourceHover = new VectorSource({\r\n wrapX: false,\r\n noWrap: true\r\n });\r\n\r\n this.vectorHover = new VectorLayer({\r\n type: 'measure',\r\n source: this.sourceHover,\r\n style: new Style({\r\n fill: fill,\r\n image: image,\r\n stroke: new Stroke({\r\n color: '#ffcc33',\r\n width: 2\r\n })\r\n })\r\n });\r\n\r\n this.vectorStandard.setZIndex(1);\r\n this.vectorHover.setZIndex(1);\r\n\r\n this.pointerMoveHandler = event => {\r\n if (event.dragging || !this.controller.enabled) {\r\n return;\r\n }\r\n\r\n let helpMsg = this.sketch ? this.moreTooltip : this.startTooltip;\r\n this.setTooltipText(helpMsg);\r\n };\r\n\r\n this.map.addLayer(this.vectorStandard);\r\n this.map.addLayer(this.vectorHover);\r\n\r\n this.map.on('pointermove', this.pointerMoveHandler);\r\n this.addInteraction();\r\n\r\n this.mapElement.addEventListener('mouseenter', () => {\r\n if (this.controller.enabled) {\r\n this.addInteraction();\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 this.initialized = true;\r\n }\r\n\r\n setTooltipText(message) {\r\n this.controller.setAerialTooltipText(message);\r\n }\r\n\r\n setMeasureTooltipInfo(message, coordinates, offset = null) {\r\n this.measureTooltipElement.innerHTML = message;\r\n this.measureTooltip.setPosition(coordinates);\r\n if (offset) {\r\n this.measureTooltip.setOffset(offset);\r\n }\r\n }\r\n\r\n hideTooltip() {\r\n this.controller.setAerialTooltipText(\"\");\r\n }\r\n\r\n reloadInteraction() {\r\n if (this.map) {\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\r\n clear() {\r\n if (!this.initialized) {\r\n return;\r\n }\r\n\r\n $('.tooltip-minimap').remove();\r\n\r\n if (this.sourceStandard) {\r\n this.sourceStandard.clear();\r\n }\r\n\r\n if (this.sourceHover) {\r\n this.sourceHover.clear();\r\n }\r\n\r\n this.removeInteraction();\r\n\r\n this.sketch = null;\r\n\r\n this.createMeasureTooltip();\r\n this.addInteraction();\r\n }\r\n\r\n removeInteraction() {\r\n if (this.draw) {\r\n this.map.removeInteraction(this.draw);\r\n }\r\n }\r\n\r\n addInteraction() {\r\n if (this.measurementType === null || this.map === null) {\r\n return;\r\n }\r\n\r\n if (!this.controller.editable) {\r\n return;\r\n }\r\n\r\n this.removeInteraction();\r\n\r\n this.draw = new Draw({\r\n source: this.sourceStandard,\r\n type: this.measurementType,\r\n condition: event => {\r\n if (event.originalEvent.button === 0) {\r\n return true;\r\n }\r\n\r\n if (event.originalEvent.button === 2) {\r\n if (this.controller.enabled) {\r\n this.reloadInteraction();\r\n this.setTooltipText(this.startTooltip);\r\n }\r\n }\r\n\r\n return false;\r\n },\r\n style: 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 this.map.addInteraction(this.draw);\r\n this.createMeasureTooltip();\r\n\r\n let listener;\r\n\r\n this.draw.on('drawstart', event => {\r\n this.sketch = event.feature;\r\n\r\n listener = this.sketch.getGeometry().on('change', event => {\r\n let geometry = event.target;\r\n let [output, tooltipCoord] = this.getTooltipValues(geometry);\r\n this.setMeasureTooltipInfo(output, tooltipCoord);\r\n });\r\n }, this);\r\n\r\n this.draw.on('drawend', (event) => {\r\n this.measureTooltipElement.className = 'tooltip tooltip-minimap tooltip-static';\r\n this.measureTooltip.setOffset([0, -7]);\r\n this.sketch = null;\r\n this.measureTooltipElement = null;\r\n this.createMeasureTooltip();\r\n unByKey(listener);\r\n\r\n this.controller.addAerialMeasurement(event.feature.getGeometry());\r\n this.setTooltipText(this.startTooltip);\r\n }, this);\r\n }\r\n\r\n createMeasureTooltip() {\r\n if (this.measureTooltipElement) {\r\n let measureParent = this.measureTooltipElement.parentNode;\r\n if (measureParent) {\r\n measureParent.removeChild(this.measureTooltipElement);\r\n }\r\n }\r\n\r\n this.measureTooltipElement = document.createElement('div');\r\n this.measureTooltipElement.className = 'tooltip tooltip-minimap tooltip-measure';\r\n this.measureTooltip = new Overlay({\r\n element: this.measureTooltipElement,\r\n offset: [0, -15],\r\n positioning: 'bottom-center'\r\n });\r\n this.map.addOverlay(this.measureTooltip);\r\n }\r\n\r\n loadGeometry(measurement, hover = false) {\r\n let geometry = measurement.geometry;\r\n let feature = new Feature(geometry);\r\n feature.measurementID = measurement.id;\r\n\r\n if (hover) {\r\n this.sourceHover.addFeature(feature);\r\n } else {\r\n this.sourceStandard.addFeature(feature);\r\n }\r\n\r\n let [output, tooltipCoord] = this.getTooltipValues(geometry);\r\n\r\n this.createMeasureTooltip();\r\n this.measureTooltipElement.className = 'tooltip tooltip-minimap tooltip-static';\r\n this.setMeasureTooltipInfo(output, tooltipCoord, [0, -7]);\r\n this.measureTooltipElement = null;\r\n\r\n this.createMeasureTooltip();\r\n }\r\n\r\n getTooltipValues(geometry) {\r\n let output;\r\n let tooltipCoord;\r\n\r\n let formatter = this.controller.formatter;\r\n\r\n if (geometry instanceof Polygon) {\r\n let area = getArea(geometry);\r\n output = formatter.formatArea(area);\r\n tooltipCoord = geometry.getInteriorPoint().getCoordinates();\r\n } else {\r\n let length = getLength(geometry);\r\n output = formatter.formatLength(length);\r\n tooltipCoord = geometry.getLastCoordinate();\r\n }\r\n return [output, tooltipCoord];\r\n }\r\n}\r\n","import {PointCloudManager} from \"../pointcloud\";\r\nimport MeasurementController from \"./measurement-controller\";\r\nimport {\r\n MeasurementArea,\r\n MeasurementLine,\r\n MeasurementPoint,\r\n MeasurementVolume,\r\n SnapDownMeasurement,\r\n SnapUpMeasurement,\r\n} from \"./measurement\";\r\n\r\nexport default class MeasurementConstructor {\r\n private controller: MeasurementController;\r\n private pointCloud: PointCloudManager;\r\n private MeasurementClass\r\n public measurement;\r\n private type = null;\r\n public isFinished = false;\r\n\r\n constructor(controller, pointCloud) {\r\n this.controller = controller;\r\n this.pointCloud = pointCloud;\r\n\r\n this.MeasurementClass = MeasurementLine;\r\n this.measurement = new this.MeasurementClass();\r\n }\r\n\r\n get activeMeasurement() {\r\n return this.measurement.vertices.length > 0;\r\n }\r\n\r\n setBuilder(builderType) {\r\n this.type = builderType;\r\n\r\n if (builderType === 'snap-up') {\r\n this.MeasurementClass = SnapUpMeasurement;\r\n } else if (builderType === 'snap-down') {\r\n this.MeasurementClass = SnapDownMeasurement;\r\n } else if (builderType === 'single-point') {\r\n this.MeasurementClass = MeasurementPoint;\r\n } else if (builderType === 'area') {\r\n this.MeasurementClass = MeasurementArea;\r\n } else if (builderType === 'volume') {\r\n this.MeasurementClass = MeasurementVolume;\r\n } else {\r\n this.MeasurementClass = MeasurementLine;\r\n }\r\n\r\n this.measurement = new this.MeasurementClass();\r\n this.measurement.setController(this.controller);\r\n }\r\n\r\n getMeasurement() {\r\n if (this.isFinished) {\r\n let finishedMeasurement = this.measurement;\r\n\r\n this.measurement = new this.MeasurementClass();\r\n this.measurement.setController(this.controller);\r\n\r\n this.isFinished = false;\r\n\r\n return finishedMeasurement;\r\n }\r\n\r\n return this.measurement;\r\n }\r\n\r\n reset() {\r\n this.isFinished = false;\r\n this.measurement.vertices = [];\r\n }\r\n\r\n add(vertex) {\r\n if (!this.isFinished) {\r\n let result = this.measurement.add(vertex, this);\r\n this.isFinished = result.finished;\r\n return result;\r\n }\r\n return {\r\n added: false,\r\n valid: false\r\n };\r\n }\r\n}\r\n","import { isLonLatProjection } from \"../projections\";\r\n\r\nexport default class MeasurementFormatter {\r\n public units;\r\n public emptyValue = \"\";\r\n public nullValue = \"N/A\";\r\n private metersCutoff = 500;\r\n private squareMetersCutoff = 250000;\r\n private formatterPrecision = 1;\r\n private vectorPrecisionLonLat = 6; // ~0.1m\r\n private vectorPrecisionStandard = 1; // 0.1m\r\n\r\n constructor(units) {\r\n if (units !== 'ft' && units !== 'm' && units !== \"sft\") {\r\n throw TypeError('units must be \"ft\", \"sft\" or \"m\"');\r\n }\r\n\r\n this.setUnits(units);\r\n }\r\n\r\n get isMetric() {\r\n return this.units === \"m\";\r\n }\r\n\r\n get isSurveyFeet() {\r\n return this.units === \"sft\";\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) {\r\n this.units = units;\r\n }\r\n\r\n formatLength(value) {\r\n let units;\r\n let finalValue = value;\r\n\r\n if ((this.units === 'ft') || (this.units === \"sft\")) {\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 if (this.formatterPrecision) {\r\n finalValue = finalValue.toFixed(this.formatterPrecision);\r\n }\r\n\r\n finalValue = parseFloat(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 if (this.formatterPrecision) {\r\n finalValue = finalValue.toFixed(this.formatterPrecision);\r\n }\r\n\r\n return `${finalValue} ${units}`;\r\n }\r\n\r\n formatVolume(measurement) {\r\n let units;\r\n let finalValue = measurement.volumeValue;\r\n\r\n if ((this.units === 'ft') || (this.units === \"sft\")) {\r\n units = \"yd3\";\r\n finalValue = MeasurementFormatter.cubicMetresToCubicYards(finalValue);\r\n } else {\r\n units = \"m3\";\r\n }\r\n\r\n if (this.formatterPrecision) {\r\n finalValue = finalValue.toFixed(this.formatterPrecision);\r\n }\r\n\r\n return `${finalValue} ${units}`;\r\n }\r\n\r\n formatArea(value) {\r\n let units;\r\n let finalValue = value;\r\n\r\n if ((this.units === 'ft') || (this.units === \"sft\")) {\r\n if (value > this.squareMetersCutoff) {\r\n units = \"mi2\";\r\n finalValue = MeasurementFormatter.squareMetresToSquareMiles(finalValue, this.isSurveyFeet);\r\n } else {\r\n units = \"ft2\";\r\n finalValue = MeasurementFormatter.squareMetresToSquareFeet(finalValue, this.isSurveyFeet);\r\n }\r\n } else {\r\n if (value > this.squareMetersCutoff) {\r\n units = \"km2\";\r\n finalValue = MeasurementFormatter.squareMetresToSquareKilometres(finalValue);\r\n } else {\r\n units = \"m2\";\r\n }\r\n }\r\n\r\n if (this.formatterPrecision) {\r\n finalValue = finalValue.toFixed(this.formatterPrecision);\r\n }\r\n\r\n return `${finalValue} ${units}`;\r\n }\r\n\r\n formatAngle(value, format = true) {\r\n if (!isNaN(value)) {\r\n if (format) {\r\n return `${value.toFixed(this.formatterPrecision)}°`;\r\n }\r\n return value.toFixed(this.formatterPrecision);\r\n }\r\n return this.nullValue;\r\n }\r\n\r\n formatGrade(value, format = true) {\r\n let maxGrade = 1000000;\r\n if (isFinite(value) && (value < maxGrade)) {\r\n if (format) {\r\n return `${value.toFixed(this.formatterPrecision)}%`;\r\n }\r\n return value.toFixed(this.formatterPrecision);\r\n }\r\n return this.nullValue;\r\n }\r\n\r\n convertUnits(value, type = \"\") {\r\n if ((this.units === 'ft') || (this.units === \"sft\")) {\r\n if (type === \"area\") {\r\n value = MeasurementFormatter.squareMetresToSquareFeet(value, this.isSurveyFeet);\r\n } else if (type === \"volume\") {\r\n value = MeasurementFormatter.cubicMetresToCubicYards(value);\r\n } else {\r\n value = MeasurementFormatter.metresToFeet(value, this.isSurveyFeet);\r\n }\r\n }\r\n if (this.formatterPrecision) {\r\n value = value.toFixed(this.formatterPrecision);\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 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 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 { GeocentricCoordinate } from '../projections';\r\nimport {\r\n AerialLengthMeasurement,\r\n AerialMeasurement,\r\n Measurement3D,\r\n MeasurementArea,\r\n MeasurementLine,\r\n MeasurementPoint,\r\n MeasurementVolume,\r\n} from './measurement';\r\nimport {Vector3} from \"three\";\r\nimport MeasurementController from './measurement-controller';\r\n\r\nexport default class MeasurementGroup {\r\n public controller: MeasurementController;\r\n public name = 'Untitled Measurement Group';\r\n public measurements = [];\r\n public databaseID = null;\r\n public collectionID = null;\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\r\n if (this.databaseID) {\r\n measurement.save(this.databaseID);\r\n }\r\n\r\n this.updateMeasurements();\r\n }\r\n\r\n removeByID(id) {\r\n if (this.databaseID) {\r\n this.measurements.find(measurement => measurement.id === id).delete();\r\n }\r\n\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.databaseID = null;\r\n this.collectionID = null;\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;\r\n\r\n if (measurement.type === 'point') {\r\n newMeasurement = new MeasurementPoint();\r\n } else if (measurement.type === 'area') {\r\n newMeasurement = new MeasurementArea();\r\n } else if (measurement.type === 'volume') {\r\n newMeasurement = new MeasurementVolume();\r\n } else {\r\n newMeasurement = new MeasurementLine();\r\n }\r\n\r\n newMeasurement.setController(this.controller);\r\n newMeasurement.title = measurement.title;\r\n newMeasurement.databaseID = measurement.id;\r\n newMeasurement.timestamp = measurement.time_created;\r\n\r\n measurement.coordinates.forEach(vertex => {\r\n vertex = new Vector3().fromArray(vertex);\r\n if (vertex.length() === 0) {\r\n 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 (measurement.volume) {\r\n newMeasurement.loadExistingVolume(measurement.volume);\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;\r\n\r\n if (measurement.type === 'length') {\r\n newMeasurement = new AerialLengthMeasurement();\r\n } else {\r\n newMeasurement = new AerialLengthMeasurement();\r\n }\r\n\r\n newMeasurement.loadFromCoordinates(measurement.coordinates);\r\n newMeasurement.setController(this.controller);\r\n newMeasurement.title = measurement.title;\r\n newMeasurement.databaseID = measurement.id;\r\n newMeasurement.timestamp = 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 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() {\r\n let measurements = this.getAreaMeasurements();\r\n let measureGeometry = [];\r\n measurements.forEach(measurement => {\r\n if (measurement.valid === false) {\r\n return;\r\n }\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.localVertices3D,\r\n indices: measurement.indices,\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 getAreaMeasurements() {\r\n return this.getMeasurementByType(MeasurementArea);\r\n }\r\n\r\n getMeasurements2D() {\r\n return this.getMeasurementByType(AerialMeasurement);\r\n }\r\n\r\n getMeasurementByType(measureClass) {\r\n return this.measurements.filter(measurement => {\r\n return measurement instanceof measureClass;\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} from './measurement';\r\nimport MeasurementController from './measurement-controller';\r\nimport {dialog, fs, isStaticSite} from \"../../../electron-modules\";\r\nimport slash from 'slash';\r\nimport { windowSafeDateISO } from '../misc';\r\nimport { Vector3 } from 'three';\r\n\r\nexport default class MeasurementGroupExporter {\r\n private controller: MeasurementController;\r\n private lineDelimiter = \"\\n\";\r\n private columnDelimiter = ',';\r\n private measureExportFormat = \"3dm\";\r\n private csvExportFilter = [{name: 'Measurement CSV', extensions: ['csv']}];\r\n public dataExportFilter = [{name: 'Measurement Data', extensions: [this.measureExportFormat]}];\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 exportLinework(measurementGroup, type, version) {\r\n //let lines = measurementGroup.getLineCoordinates();\r\n //let points = measurementGroup.getPointCoordinates();\r\n //let name = `${measurementGroup.name} (${type}).zip`;\r\n\r\n // Need to implement dxf/shp javascript write\r\n }\r\n\r\n exportCSV(measurementGroup, ordering) {\r\n const precision = this.formatter.getVectorPrecision(LocalScene.viewProjection);\r\n this.export3D(measurementGroup, this.formatter, ordering, precision);\r\n this.export2D(measurementGroup, this.formatter, ordering, precision);\r\n }\r\n\r\n exportDAT(measurementGroup) {\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 created = measurement.timeCreated.toISOString().split('.')[0];\r\n let title = measurement.title;\r\n let type = measurement.dbType;\r\n let coordinates = measurement.coordinates;\r\n\r\n let info = {\r\n id: null,\r\n coordinates: coordinates,\r\n time_created: created,\r\n title: title,\r\n type: type,\r\n volume: 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\r\n data.measurements.measurements3D.push(info);\r\n }\r\n\r\n data.count += 1;\r\n });\r\n\r\n // Download data export file\r\n const name = this.viewer.projectName;\r\n this.downloadDataExport(name, data);\r\n }\r\n\r\n export2D(measurementGroup, formatter, ordering, precision) {\r\n let measurements = measurementGroup.measurements.filter(measurement =>\r\n measurement instanceof AerialMeasurement\r\n );\r\n\r\n if (measurements.length === 0) {\r\n return;\r\n }\r\n\r\n let mapProjection = this.viewer.minimap.mapSystem;\r\n\r\n let header = this.getHeaderValues2D(measurements, ordering, formatter);\r\n let nullValue = formatter.nullValue;\r\n\r\n let csv = [\r\n header.join(this.columnDelimiter)\r\n ];\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 value = formatter.convertUnits(measurement.getValue(), measurement.dbType);\r\n row = [measurement.title, \"Area\", nullValue, value];\r\n } else {\r\n value = formatter.convertUnits(measurement.getValue(), measurement.dbType);\r\n row = [measurement.title, \"Length\", value, nullValue];\r\n }\r\n\r\n let vertices = [];\r\n let coordinates = measurement.geometry.flatCoordinates;\r\n for (var i = 0; i < (coordinates.length / 2.0); 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 csv.push(row.join(this.columnDelimiter));\r\n });\r\n\r\n const name = this.viewer.projectName;\r\n this.downloadCSVFile(`${name} measurements (2D) ${windowSafeDateISO()}`, csv);\r\n }\r\n\r\n export3D(measurementGroup, formatter, ordering, precision) {\r\n let measurements = measurementGroup.measurements.filter(measurement =>\r\n measurement instanceof Measurement3D\r\n );\r\n\r\n if (measurements.length === 0) {\r\n return;\r\n }\r\n\r\n let header = this.getHeaderValues3D(measurements, ordering, formatter);\r\n let nullValue = formatter.nullValue;\r\n\r\n let csv = [\r\n header.join(this.columnDelimiter)\r\n ];\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 ];\r\n } else if (measurement instanceof MeasurementArea) {\r\n let areaValue;\r\n let volumeValue = nullValue;\r\n\r\n if (measurement.valid) {\r\n areaValue = formatter.convertUnits(measurement.area3D, measurement.dbType);\r\n } else {\r\n areaValue = measurement.areaInvalidMessage;\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 = formatter.convertUnits(measurement.volumeValue, measurement.dbType);\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 ];\r\n } else {\r\n row = [\r\n measurement.title,\r\n formatter.convertUnits(measurement.distance2D, measurement.dbType),\r\n formatter.convertUnits(measurement.distance3D, measurement.dbType),\r\n nullValue,\r\n nullValue,\r\n formatter.formatGrade(measurement.grade, false),\r\n formatter.formatAngle(measurement.angle, false)\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 // 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 vertex.z.toFixed(precision.z)\r\n ]);\r\n });\r\n\r\n csv.push(row.join(this.columnDelimiter));\r\n });\r\n\r\n const name = this.viewer.projectName;\r\n this.downloadCSVFile(`${name} measurements (3D) ${windowSafeDateISO()}`, csv);\r\n }\r\n\r\n downloadDataExport(filename, data) {\r\n let name = `${filename}.${this.measureExportFormat}`;\r\n let string = JSON.stringify(data, null, 2);\r\n\r\n if (isStaticSite) {\r\n this.downloadFileBrowser(name, string, \"plain\");\r\n } else {\r\n this.downloadFileElectron(name, string, this.dataExportFilter);\r\n }\r\n }\r\n\r\n downloadCSVFile(filename, data) {\r\n let name = `${filename}.csv`;\r\n let string = data.join(this.lineDelimiter);\r\n\r\n if (isStaticSite) {\r\n this.downloadFileBrowser(name, string, \"csv\");\r\n } else {\r\n this.downloadFileElectron(name, string, this.csvExportFilter);\r\n }\r\n }\r\n\r\n downloadFileElectron(name, data, filter) {\r\n console.log(\"Download file (electron)\") ;\r\n\r\n dialog.showSaveDialog({\r\n title: 'Save Project',\r\n defaultPath: name,\r\n filters: filter,\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.writeFileSync(savePath, data);\r\n }\r\n });\r\n }\r\n\r\n downloadFileBrowser(name, data, type) {\r\n console.log(\"Download file (browser\");\r\n let contentType = `data:text/${type};charset=utf-8`;\r\n let content = `${contentType},${encodeURIComponent(data)}`;\r\n console.log(\"Download file (browser)\") ;\r\n let element = document.createElement('a');\r\n element.setAttribute('href', content);\r\n if (name) {\r\n element.setAttribute('download', name);\r\n }\r\n element.style.display = 'none';\r\n document.body.appendChild(element);\r\n element.target = \"_blank\";\r\n element.click();\r\n document.body.removeChild(element);\r\n }\r\n\r\n getHeaderValues2D(measurements, ordering, formatter) {\r\n let header = [\r\n \"Notes\", \"Measure Type\",\r\n `Length (${formatter.units})`,\r\n `Area (${formatter.units}^2)`\r\n ];\r\n\r\n let numVertices = 0;\r\n measurements.forEach(measurement => {\r\n let measurementVertices = measurement.geometry.flatCoordinates.length / 2.0;\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}`]);\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, formatter) {\r\n let header = [\r\n \"Notes\",\r\n `Distance 2D (${formatter.units})`,\r\n `Distance 3D (${formatter.units})`,\r\n `Area 3D (${formatter.areaUnits})`,\r\n `Volume 3D (${formatter.volumeUnits})`,\r\n \"Grade (%)\",\r\n \"Angle (Deg)\",\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","import { RayCaster } from '../controls';\r\nimport { GeocentricCoordinate, sphereRaycast } from '../projections';\r\nimport { setPointScale } from '../utilities';\r\nimport { MeasurementArea, MeasurementVolume } from './measurement';\r\nimport MeasurementController from './measurement-controller';\r\nimport {\r\n Mesh,\r\n Scene,\r\n SphereGeometry,\r\n MeshBasicMaterial,\r\n LineBasicMaterial,\r\n Geometry,\r\n Line\r\n} from 'three';\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\r\nexport class TemporaryEndpoint extends Mesh {\r\n constructor(geometry, material) {\r\n super(geometry, material);\r\n }\r\n}\r\n\r\nexport default class MeasurementSceneView {\r\n private controller: MeasurementController;\r\n private scene: Scene;\r\n\r\n private sphereBuffer = 1.2;\r\n private sphereRadius = 0.05;\r\n private sphereGeometry = new SphereGeometry(this.sphereRadius, 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 lineMaterialHover = new LineBasicMaterial({color: 0xffcc33});\r\n\r\n private measurements = [];\r\n private temporaryEndpoints = [];\r\n private temporaryLines = [];\r\n public hoveredPoint = 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 updateMeasureEndpoint(coordinate) {\r\n if (!this.dragObject) {\r\n return;\r\n }\r\n\r\n if (!coordinate) {\r\n return;\r\n }\r\n\r\n let id = this.dragObject.measurementID;\r\n let vertexIndex = this.dragObject.measurementVertex;\r\n let measurement = this.controller.measurementGroup.measurements.find(\r\n measurement => measurement.id === id\r\n );\r\n\r\n if (!measurement) {\r\n return;\r\n }\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 GeocentricCoordinate().fromScene(coordinate);\r\n measurement.vertices[vertexIndex] = vertex;\r\n\r\n // Remove + redraw the line\r\n this.removeByID(id);\r\n this.draw(measurement);\r\n }\r\n\r\n measureGrabFinished() {\r\n if ((!this.dragObject) || (!this.dragValid)) {\r\n return;\r\n }\r\n\r\n this.controller.refreshMeasurementList();\r\n }\r\n\r\n checkEndpointSelected(event) {\r\n let controller = this.controller;\r\n if (!controller.editable) {\r\n return;\r\n }\r\n\r\n if (controller.measurementBuilder.activeMeasurement) {\r\n return;\r\n }\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 this.dragObject = dragObject;\r\n\r\n let draggable = dragObject ? true : false;\r\n let controls = this.controller.controls;\r\n controls.restrictOrbitMovement(!draggable);\r\n\r\n if (dragObject) {\r\n this.setPointGrabTooltip();\r\n }\r\n }\r\n\r\n hideTooltip() {\r\n this.controller.setViewerTooltipText(\"\");\r\n }\r\n\r\n setPointGrabTooltip() {\r\n this.controller.setViewerTooltipText(\"Click and hold to move vertex\");\r\n }\r\n\r\n setRestrictedPointTooltip() {\r\n this.controller.setViewerTooltipText(\"Unable to move this measurement type\");\r\n }\r\n\r\n setTooltipText(measurement, morepoints = false) {\r\n let text = \"\";\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 text = measurement.moreTooltip;\r\n } else {\r\n text = measurement.endTooltip;\r\n }\r\n } else {\r\n text = measurement.startTooltip;\r\n }\r\n\r\n this.controller.setViewerTooltipText(text);\r\n }\r\n\r\n setPointScale(mesh) {\r\n setPointScale(this.viewer, mesh, 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(coordinate) {\r\n if (coordinate === null) {\r\n return;\r\n }\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 // Remove all previous lines\r\n for (let temporaryLine of this.temporaryLines) {\r\n this.scene.remove(temporaryLine);\r\n }\r\n this.temporaryLines = [];\r\n\r\n // Re-draw the entire temporary line\r\n let points = [...this.temporaryEndpoints, this.hoveredPoint];\r\n for (var i=1;i measurement.id === id);\r\n if (measurement) {\r\n for (let object of measurement.lines) {\r\n material = hover ? this.lineMaterialHover : this.lineMaterialStandard;\r\n object.material = material;\r\n object.material.needsUpdate = true;\r\n }\r\n for (let object of measurement.points) {\r\n material = hover ? this.sphereMaterialHover : this.sphereMaterialStandard;\r\n object.material = material;\r\n object.material.needsUpdate = true;\r\n }\r\n }\r\n }\r\n\r\n draw(measurement) {\r\n let lines = [];\r\n let points = [];\r\n let point;\r\n let line;\r\n let vertices = measurement.vertices;\r\n\r\n for (var i = 0; i < vertices.length; i++) {\r\n let vertexA = measurement.vertices[i].toScene();\r\n point = this.createEndpoint(vertexA, i, measurement.id);\r\n this.scene.add(point);\r\n points.push(point);\r\n\r\n if (i >= 1) {\r\n let vertexB = measurement.vertices[i - 1].toScene();\r\n line = this.createLine(vertexA, vertexB);\r\n this.scene.add(line);\r\n lines.push(line);\r\n }\r\n }\r\n\r\n // Extra steps for area (close polygon + calculate surface)\r\n if (measurement instanceof MeasurementArea) {\r\n let vertexA = measurement.vertices[vertices.length - 1].toScene();\r\n let vertexB = measurement.vertices[0].toScene();\r\n line = this.createLine(vertexA, vertexB);\r\n this.scene.add(line);\r\n lines.push(line);\r\n\r\n measurement.generateSurface();\r\n }\r\n\r\n this.measurements.push({\r\n id: measurement.id,\r\n lines: lines,\r\n points: points\r\n });\r\n\r\n // Update area measurement shader\r\n this.controller.updateAreaShaders();\r\n }\r\n\r\n removeTemporaryObjects() {\r\n for (let temporaryEndpoint of this.temporaryEndpoints) {\r\n this.scene.remove(temporaryEndpoint);\r\n }\r\n\r\n for (let temporaryLine of this.temporaryLines) {\r\n this.scene.remove(temporaryLine);\r\n }\r\n\r\n if (this.hoveredPoint) {\r\n this.scene.remove(this.hoveredPoint);\r\n }\r\n\r\n this.temporaryEndpoints = [];\r\n this.temporaryLines = [];\r\n this.hoveredPoint = null;\r\n\r\n }\r\n\r\n removeByID(id) {\r\n let measurement = this.measurements.find(measurement => measurement.id === id);\r\n if (measurement) {\r\n for (let object of measurement.lines) {\r\n this.scene.remove(object);\r\n }\r\n for (let object of measurement.points) {\r\n this.scene.remove(object);\r\n }\r\n this.measurements = this.measurements.filter(measurement => measurement.id !== id);\r\n }\r\n\r\n let measurementGroup = this.controller.measurementGroup;\r\n let measurementObject = measurementGroup.measurements.find(\r\n measurement => measurement.id === id\r\n );\r\n\r\n measurementObject.clear();\r\n }\r\n\r\n removeAll() {\r\n for (let measurement of this.measurements) {\r\n for (let object of measurement.lines) {\r\n this.scene.remove(object);\r\n }\r\n for (let object of measurement.points) {\r\n this.scene.remove(object);\r\n }\r\n }\r\n this.measurements = [];\r\n }\r\n\r\n update(changeDetector) {\r\n if (changeDetector === null) {\r\n return;\r\n }\r\n\r\n const update = changeDetector.changed;\r\n if (!update) {\r\n return;\r\n }\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 $ from 'jquery';\r\nimport { AmbientLight, Scene } from 'three';\r\nimport { Viewer } from '../main';\r\nimport { roundDigit } from '../misc';\r\nimport LocalScene from '../projections';\r\nimport unitConverter from '../utilities/unit-converter';\r\nimport { GroundPlaneMeasurement } from './image-only';\r\nimport { AerialAreaMeasurement, AerialLengthMeasurement, Measurement3D, MeasurementArea} from './measurement';\r\nimport MinimapMeasure from './measurement-aerial-view';\r\nimport MeasurementConstructor from './measurement-constructor';\r\nimport MeasurementFormatter from './measurement-formatter';\r\nimport MeasurementGroup from './measurement-group';\r\nimport MeasurementGroupExporter from './measurement-group-exporter';\r\nimport MeasurementSceneView, { MeasureEndpoint } from './measurement-scene-view';\r\n\r\nexport default class MeasurementController {\r\n public viewer: Viewer;\r\n public enabled = false;\r\n private imageOnlyType = \"plane\";\r\n public measureType = \"standard\";\r\n public movingEndpoint = false;\r\n\r\n public formatter: MeasurementFormatter;\r\n public measureSceneView: MeasurementSceneView;\r\n public measurementAerialView: MinimapMeasure;\r\n public measurementBuilder: MeasurementConstructor;\r\n public measurementGroupExporter: MeasurementGroupExporter;\r\n public measurementGroup: MeasurementGroup;\r\n public setViewerTooltipText;\r\n public setAerialTooltipText;\r\n public setMeasurements;\r\n public scene: Scene;\r\n\r\n constructor(viewer: Viewer, props) {\r\n const {setViewerTooltipText, setAerialTooltipText, setMeasurements} = props;\r\n\r\n this.viewer = viewer;\r\n this.setViewerTooltipText = setViewerTooltipText;\r\n this.setAerialTooltipText = setAerialTooltipText;\r\n this.setMeasurements = setMeasurements;\r\n\r\n this.initScene();\r\n\r\n this.formatter = new MeasurementFormatter(\"m\");\r\n this.measureSceneView = new MeasurementSceneView(this, this.scene);\r\n this.measurementAerialView = new MinimapMeasure(this);\r\n this.measurementBuilder = new MeasurementConstructor(this, this.pointclouds);\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.activeMeasurement;\r\n }\r\n\r\n get drawing() {\r\n return this.measurementBuilder.activeMeasurement;\r\n }\r\n\r\n get notEmpty() {\r\n return this.measurementGroup.measurements.length > 0;\r\n }\r\n\r\n get saved() {\r\n return Boolean(this.measurementGroup.databaseID);\r\n }\r\n\r\n get dragObject() {\r\n return this.measureSceneView.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 measureExportType() {\r\n return this.measurementGroupExporter.dataExportFilter;\r\n }\r\n\r\n get hoveredPoint() {\r\n return this.measureSceneView.hoveredPoint;\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 clear() {\r\n this.measureSceneView.removeAll();\r\n this.measurementAerialView.clear();\r\n }\r\n\r\n disable() {\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.measurementAerialView.hideTooltip();\r\n this.measureSceneView.hideTooltip();\r\n\r\n this.updateAreaShaders();\r\n }\r\n\r\n reset() {\r\n this.clear();\r\n this.disable();\r\n }\r\n\r\n initScene() {\r\n const scene = new Scene();\r\n const light = new AmbientLight(0xFFFFFF);\r\n scene.add(light);\r\n this.scene = scene;\r\n }\r\n\r\n loadMeasurementData(data) {\r\n try {\r\n const projection = data.projection;\r\n const sameProjection = LocalScene.currentProjection(projection.name);\r\n\r\n if (!sameProjection) {\r\n return {\r\n success: false,\r\n message: `Projection mismatch. Projection used was '${projection.name}'`\r\n };\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 return {\r\n success: true,\r\n message: `Loaded ${data.count} measurements`\r\n };\r\n } catch {\r\n this.createNewMeasurementGroup();\r\n\r\n return {\r\n success: false,\r\n message: \"Error loading measurement group\"\r\n };\r\n }\r\n }\r\n\r\n updateMaxMeasureDistance(units) {\r\n let $maxMeasureDistance = $(\"#max-measure-distance\");\r\n\r\n if (!this.isImageOnly) {\r\n $maxMeasureDistance.text('');\r\n return;\r\n }\r\n\r\n let distance = new GroundPlaneMeasurement(this.viewer).maxDistance2D;\r\n let maxMeasureDistance = unitConverter.convert(distance, 'm', units);\r\n maxMeasureDistance = roundDigit(maxMeasureDistance, 2).toFixed(2);\r\n let message = `Maximum Measure Distance from Position: ${maxMeasureDistance} ${units}`;\r\n\r\n $maxMeasureDistance.text(message);\r\n }\r\n\r\n cancelMeasurement(event) {\r\n this.stopDrawingItems();\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 getPlanePosition(event) {\r\n let groundPlane = new GroundPlaneMeasurement(this.viewer);\r\n let coordinate = groundPlane.getPosition(event);\r\n return coordinate;\r\n }\r\n\r\n getCoordinate(event) {\r\n let coordinate = null;\r\n\r\n if (this.isImageOnly) {\r\n if (this.imageOnlyType === \"plane\") {\r\n coordinate = this.getPlanePosition(event);\r\n }\r\n } else {\r\n // Check for collection data (esri features)\r\n coordinate = this.controls.getPickerResults(event);\r\n }\r\n\r\n return coordinate;\r\n }\r\n\r\n mouseClick(event) {\r\n if (!this.editable) {\r\n return;\r\n }\r\n\r\n // Send position to measurements\r\n let coordinate = this.hoveredPoint\r\n ? this.hoveredPoint.position\r\n : this.getCoordinate(event);\r\n\r\n if (!coordinate) {\r\n return;\r\n }\r\n\r\n let result = this.measurementBuilder.add(coordinate);\r\n\r\n if (!result.valid) {\r\n this.cancelMeasurement(event);\r\n return;\r\n }\r\n\r\n if (result.added) {\r\n this.measureSceneView.addTemporaryPoint(coordinate);\r\n this.updateMeasureText();\r\n }\r\n\r\n if (this.measurementBuilder.isFinished) {\r\n this.finishMeasurement();\r\n }\r\n }\r\n\r\n onMouseMove(event, mouse = null) {\r\n const mouseMoved = mouse ? mouse.movement : false;\r\n const mouseDown = mouse ? mouse.down : false;\r\n const isLeftClick = mouse ? mouse.button === 0 : false;\r\n\r\n this.movingEndpoint = false;\r\n\r\n if (!mouseMoved && !mouseDown) {\r\n this.measureSceneView.checkEndpointSelected(event);\r\n }\r\n\r\n if (mouse === null) {\r\n return;\r\n }\r\n\r\n if (this.enabled) {\r\n if (this.measuring) {\r\n let coordinate = this.getCoordinate(event);\r\n this.measureSceneView.addActiveEndpoint(coordinate);\r\n }\r\n\r\n if (this.dragObject) {\r\n this.setPointGrabTooltip();\r\n\r\n if (mouseDown) {\r\n if (isLeftClick) {\r\n let coordinate = this.getCoordinate(event);\r\n this.measureSceneView.updateMeasureEndpoint(coordinate);\r\n }\r\n this.movingEndpoint = true;\r\n\r\n return;\r\n }\r\n } else {\r\n this.updateMeasureText();\r\n }\r\n }\r\n\r\n return false;\r\n }\r\n\r\n resetDragObject() {\r\n this.measureSceneView.setDragObject(null);\r\n }\r\n\r\n finishMeasurement() {\r\n this.updateMeasureText();\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 this.measureSceneView.removeTemporaryObjects();\r\n this.measurementGroup.add(measurement);\r\n this.renderMeasurement(measurement);\r\n this.markLastPointDraggable(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.measureSceneView.setDragObject(lastPoint);\r\n }\r\n\r\n stopDrawingItems() {\r\n this.measurementBuilder.reset();\r\n this.measureSceneView.removeTemporaryObjects();\r\n\r\n if (this.measurementAerialView.sketch !== null) {\r\n this.measurementAerialView.clear();\r\n this.redrawAerialGeometry();\r\n }\r\n\r\n this.updateMeasureText(false);\r\n }\r\n\r\n setPointGrabTooltip() {\r\n this.measureSceneView.setPointGrabTooltip();\r\n }\r\n\r\n measureGrabFinished() {\r\n this.measureSceneView.measureGrabFinished();\r\n }\r\n\r\n updateAreaShaders() {\r\n let areaGeometry = this.measurementGroup.getAreaGeometry();\r\n let pointcloud = this.viewer.pointclouds;\r\n pointcloud.updateAreaVertices(areaGeometry);\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 let morepoints = false;\r\n let measurement = this.measurementBuilder.measurement;\r\n\r\n if (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.measureSceneView.setTooltipText(measurement, morepoints);\r\n }\r\n\r\n addAerialMeasurement(geometry) {\r\n let measurement;\r\n\r\n if (this.measurementAerialView.measurementType === 'LineString') {\r\n measurement = new AerialLengthMeasurement(geometry);\r\n } else {\r\n measurement = new AerialAreaMeasurement(geometry);\r\n }\r\n\r\n measurement.setController(this);\r\n this.measurementGroup.add(measurement);\r\n }\r\n\r\n createNewMeasurementGroup() {\r\n this.measurementAerialView.clear();\r\n this.measureSceneView.removeAll();\r\n this.measurementGroup = new MeasurementGroup(this);\r\n this.setMeasurementType(this.measureType);\r\n this.updateAreaShaders();\r\n }\r\n\r\n setMeasurementType(measurementType) {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n this.measureType = measurementType;\r\n this.measurementBuilder.setBuilder(measurementType);\r\n this.measureSceneView.removeTemporaryObjects();\r\n\r\n let measurement = this.measurementBuilder.measurement;\r\n this.measureSceneView.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.measureSceneView.removeByID(id);\r\n this.measurementGroup.removeByID(id);\r\n\r\n this.measurementAerialView.clear();\r\n this.redrawAerialGeometry();\r\n\r\n // Update area measurement shader\r\n this.updateAreaShaders();\r\n\r\n this.measureSceneView.hideTooltip();\r\n }\r\n\r\n setTitle(id, title) {\r\n const measurements = this.measurementGroup.measurements;\r\n const measurement = measurements.find(measurement => measurement.id === id);\r\n if (measurement) {\r\n measurement.title = title;\r\n this.refreshMeasurementList();\r\n }\r\n\r\n this.measureSceneView.hideTooltip();\r\n }\r\n\r\n redrawAerialGeometry(measurement = null, hover = false) {\r\n if (measurement) {\r\n this.measurementGroup.getMeasurements2D().forEach(measurement_ => {\r\n if (measurement_.id === measurement.id) {\r\n this.measurementAerialView.loadGeometry(measurement_, hover);\r\n } else {\r\n this.measurementAerialView.loadGeometry(measurement_);\r\n }\r\n });\r\n } else {\r\n this.measurementGroup.getMeasurements2D().forEach(measurement => {\r\n this.measurementAerialView.loadGeometry(measurement);\r\n });\r\n }\r\n }\r\n\r\n clearByID(id) {\r\n this.measureSceneView.removeByID(id);\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.measureSceneView.removeAll();\r\n this.measurementAerialView.clear();\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 }\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 /* Not implemented */\r\n exportLinework(type, projection, version) {\r\n this.measurementGroupExporter\r\n .exportLinework(this.measurementGroup, type, version);\r\n }\r\n\r\n setUnits(units) {\r\n this.formatter.setUnits(units);\r\n this.updateMaxMeasureDistance(units);\r\n\r\n if (this.measurementGroup) {\r\n this.reload();\r\n }\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 updateRenderColor(measurement, hover = false) {\r\n if (measurement instanceof Measurement3D) {\r\n this.measureSceneView.updateMaterial(measurement.id, hover);\r\n } else {\r\n this.measurementAerialView.clear();\r\n this.redrawAerialGeometry(measurement, hover);\r\n }\r\n }\r\n\r\n renderMeasurement(measurement) {\r\n if (measurement instanceof Measurement3D) {\r\n this.measureSceneView.draw(measurement);\r\n } else {\r\n this.measurementAerialView.loadGeometry(measurement);\r\n }\r\n }\r\n\r\n update(changeDetector) {\r\n this.measureSceneView.update(changeDetector);\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 {OpacityMaterial, EDLMaterial, ImageMaterial} from './materials';\r\nimport {EncompassPointCloud, PointCloudManager, RawPointCloud} from './pointcloud';\r\nimport {CompassControls, PanoControls} from './controls';\r\nimport {CameraList} from './cameras';\r\nimport {CameraMarkers} from './markers';\r\nimport {destroyWindowEvents, bindWindowEvent} from \"../events\";\r\nimport {AerialMap} from './aerial';\r\nimport {AssetType} from \"../../redux/assets-slice\";\r\nimport {Clamp, ColorMapKey, ColorType, MarkerNavType} from '../../redux/settings-slice';\r\nimport LocalScene, { DataProjectionCoordinate } from './projections';\r\nimport {nanoid} from '@reduxjs/toolkit';\r\nimport {colorMaps} from \"../textures/colormaps\";\r\nimport { Measurement } from './measurements/measurement';\r\nimport ChangeDetector from './utilities/change-detection';\r\nimport { isDevMode, isStaticSite } from '../../electron-modules';\r\nimport slash from 'slash';\r\nimport GPUPicker from './gpu-picker';\r\nimport { extentFromPoints } from './aerial/map';\r\nimport { debounce } from 'throttle-debounce';\r\nimport { SceneCameraState } from '../../redux/camera-slice';\r\nimport { ImageLabelTools } from './labelling';\r\nimport {\r\n AmbientLight,\r\n Camera,\r\n DepthTexture,\r\n FloatType,\r\n Vector3,\r\n Mesh,\r\n MeshBasicMaterial,\r\n NearestFilter,\r\n LinearFilter,\r\n PerspectiveCamera,\r\n PlaneBufferGeometry,\r\n RGBAFormat,\r\n Scene,\r\n UnsignedIntType,\r\n WebGLRenderer,\r\n WebGLRenderTarget,\r\n TextureLoader\r\n} from \"three\";\r\nimport MeasurementController from './measurements/measurement-controller';\r\nimport { CameraLoadOptions } from './cameras/cameras';\r\nimport Stats from '../../stats.module.js';\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 private id = nanoid();\r\n public camera: PerspectiveCamera;\r\n private light: AmbientLight;\r\n public renderer: WebGLRenderer;\r\n private screenPass: RenderPass;\r\n private imageMaterial: ImageMaterial;\r\n private texture2DDepth: WebGLRenderTarget;\r\n private opacityMaterial: OpacityMaterial;\r\n private texture2DImage: any;\r\n private texture2DOpacity: WebGLRenderTarget;\r\n public gpuPickers: {\r\n markers: GPUPicker,\r\n points: GPUPicker\r\n };\r\n public imageLabels: ImageLabelTools;\r\n private EDLMaterial: EDLMaterial;\r\n private canvas: any;\r\n private changeDetector: ChangeDetector;\r\n public compass: CompassControls;\r\n public controls: PanoControls;\r\n public pointclouds: PointCloudManager;\r\n public cameraList: CameraList;\r\n public minimap: AerialMap;\r\n public markers: CameraMarkers;\r\n public measurements: MeasurementController;\r\n private stats: StatsPanel;\r\n private updateSavedState: Function;\r\n public showMessage: Function;\r\n private setCameraState: Function;\r\n private enabled = true;\r\n private focused = false;\r\n private drawPickerScene = false;\r\n public projectName;\r\n\r\n public timingDebug = {\r\n \"markers\": false,\r\n \"scene\": false\r\n };\r\n\r\n constructor(viewContainer, mapContainer, props) {\r\n const {showMessage, setCameraState} = props;\r\n\r\n this.containerElement = viewContainer;\r\n\r\n this.createScene();\r\n this.initGpuPickers();\r\n this.initResize();\r\n this.initMaterials();\r\n this.initViewEvents();\r\n\r\n this.showMessage = showMessage;\r\n this.setCameraState = setCameraState;\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.cameraList = new CameraList(this);\r\n this.minimap = new AerialMap(this, mapContainer, props);\r\n this.imageLabels = new ImageLabelTools(this, props);\r\n this.markers = new CameraMarkers(this);\r\n this.changeDetector = new ChangeDetector(this);\r\n this.stats = new StatsPanel(this);\r\n\r\n // Add canvas elements to container\r\n this.addContainerElements();\r\n\r\n // Need to debounce to update ui smoothly\r\n this.updateSavedState = debounce(100, () => {\r\n this.calculateUpdatedValues();\r\n });\r\n\r\n // Force initial resize event\r\n this.handleWindowResize();\r\n\r\n // Start our animation loop\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 orthoList() {\r\n return this.minimap.orthoList;\r\n }\r\n\r\n get lookat() {\r\n let lookat = new Vector3(0,0, -1);\r\n let quat = this.camera.quaternion;\r\n lookat.applyQuaternion(quat);\r\n return lookat;\r\n }\r\n\r\n get renderTargetAttrs() {\r\n return {\r\n tDepth: this.renderTarget.depthTexture,\r\n colorMap: this.renderTarget.texture,\r\n };\r\n }\r\n\r\n get renderTarget() {\r\n return this.EDLSupport ? this.texture2DDepth : this.texture2DOpacity;\r\n }\r\n\r\n get renderMaterial() {\r\n return this.EDLSupport ? this.EDLMaterial : this.opacityMaterial;\r\n }\r\n\r\n get orbitState() {\r\n return this.controls.orbit.state;\r\n }\r\n\r\n get cameraSelected() {\r\n return this.cameraList.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.cameraList.isEmpty;\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 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 isWebGL2(): boolean {\r\n let capabilities = this.renderer.capabilities;\r\n return capabilities.isWebGL2;\r\n }\r\n\r\n get expanded(): boolean {\r\n return this.width > this.minimap.width;\r\n }\r\n\r\n get calculatingSceneMarkers() {\r\n return this.markers.calculating;\r\n }\r\n\r\n get calculatingAerialMarkers() {\r\n return this.minimap.calculating;\r\n }\r\n\r\n get showCompassElement() {\r\n if (!LocalScene.initialized) {\r\n return false;\r\n }\r\n\r\n let show;\r\n\r\n if (this.isPointsOnly) {\r\n // Points only dataset. Always okay to show\r\n show = true;\r\n } else if (this.hasCameras) {\r\n // Current camera is done loading (or there is no\r\n // camera selected)\r\n let currentCamera = this.cameraList.current;\r\n show = currentCamera\r\n ? currentCamera.loaded || currentCamera.loading\r\n : true;\r\n } else {\r\n // Conditions not met, hide navigation\r\n show = false;\r\n }\r\n\r\n return show;\r\n }\r\n\r\n /** Exposed Global Methods */\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) {\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 classifications.forEach(classification => {\r\n this.pointclouds.setClassification(classification.id, classification.visible);\r\n });\r\n }\r\n\r\n setPointCloudOpacity(opacity: number) {\r\n this.pointclouds.transparency = opacity;\r\n }\r\n\r\n setPointCloudSize(size: number) {\r\n this.pointclouds.materialDefaults.size = size;\r\n this.pointclouds.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.size = size;\r\n });\r\n });\r\n }\r\n\r\n setPointCloudMaxPoints(points: number) {\r\n this.pointclouds.visiblePointsTarget = points;\r\n }\r\n\r\n setPointCloudDistance(distance: number) {\r\n let value = (distance === 100) ? this.far : distance * 10;\r\n this.pointclouds.materialDefaults.distance = value;\r\n this.pointclouds.clouds.forEach(pointCloud => {\r\n pointCloud.materials.forEach(material => {\r\n material.distance = value;\r\n });\r\n });\r\n }\r\n\r\n setPointCloudHeightClip(clamp: Clamp) {\r\n this.pointclouds.updateClamping('heightClamp', 'height_clamp', clamp);\r\n }\r\n\r\n setPointCloudIntensityClip(clamp: Clamp) {\r\n this.pointclouds.updateClamping('intensityClamp', 'intensity_clamp', clamp);\r\n }\r\n\r\n setPointCloudColorMap(colorMapKey: ColorMapKey) {\r\n const textureData = colorMaps.find(colorMap => colorMap.id === 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.color_map = texture;\r\n material.color_map.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.color_type = 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.dynamic_size = 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 setNavigationType(state: MarkerNavType) {\r\n this.markers.setNavigationType(state);\r\n }\r\n\r\n /** NOTE: Temporary(?) solution for the viewer being created over and over again */\r\n destroy() {\r\n destroyWindowEvents();\r\n\r\n // Destroy viewer elements\r\n this.enabled = false;\r\n this.camera = null;\r\n this.removeContainerElements();\r\n this.destroyViewEvents();\r\n\r\n // Destroy minimap dom element\r\n this.minimap.destroy();\r\n\r\n // TODO: destroy other things\r\n }\r\n\r\n setDataProjection(newProjection) {\r\n LocalScene.setDataProjection(newProjection);\r\n\r\n // Reset all measurements (not able to convert easily. would be easier if we changed\r\n // the encompass style data to be written in its original units, and converted on the fly\r\n if (this.controls.measurements.enabled) {\r\n this.controls.measurements.reset();\r\n this.controls.measurements.enable();\r\n }\r\n }\r\n\r\n setViewProjection(newProjection) {\r\n LocalScene.setViewProjection(newProjection);\r\n }\r\n\r\n setMeasurementUnits(units) {\r\n this.controls.measurements.setUnits(units);\r\n }\r\n\r\n setCameraVisible(cameraID, opts:CameraLoadOptions = {}) {\r\n this.cameraList.loadImage(cameraID, opts);\r\n }\r\n\r\n resetDefaultOrbitState() {\r\n this.controls.orbitDefaultApplied = false;\r\n }\r\n\r\n setOrbitDefault(numAdded, state: SceneCameraState) {\r\n if ((numAdded === 0) || this.controls.orbitDefaultApplied) {\r\n // Orbit state not applicable\r\n return false;\r\n }\r\n\r\n this.controls.orbitDefaultApplied = true;\r\n\r\n // Missing orbit rotation values\r\n if ((state.orbit === null) || (state.pivot === null)) {\r\n return false;\r\n }\r\n\r\n let orbit = new DataProjectionCoordinate(state.orbit)\r\n .toScene();\r\n\r\n let pivot = new DataProjectionCoordinate(state.pivot)\r\n .toScene();\r\n\r\n this.controls.setOrbitState(true, {\r\n position: orbit,\r\n pivot: pivot\r\n });\r\n\r\n return true;\r\n }\r\n\r\n toggleMeasurements(state) {\r\n if (state) {\r\n this.controls.measurements.enable();\r\n } else {\r\n this.controls.measurements.clear();\r\n this.controls.measurements.disable();\r\n }\r\n }\r\n\r\n toggleCameraAligner(state) {\r\n this.controls.cameraAlignerAdv.setState(state);\r\n }\r\n\r\n updateMeasureType(measureType) {\r\n this.controls.measurements.setMeasurementType(measureType);\r\n }\r\n\r\n updateMeasureHover(measurement: Measurement, state) {\r\n this.controls.measurements.updateRenderColor(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 getMeasureExportType() {\r\n return this.controls.measurements.measureExportType;\r\n }\r\n\r\n loadMeasurementData(data) {\r\n return this.controls.measurements.loadMeasurementData(data);\r\n }\r\n\r\n /* Ortho Viewer Function Calls */\r\n setOrthoOpacity(value) {\r\n this.orthoList.setOpacity(value);\r\n }\r\n\r\n /* Labelling/Annotation function calls */\r\n activeImageLabelPaths() {\r\n return this.imageLabels.activeImagePaths();\r\n }\r\n\r\n loadedImageLabelPaths() {\r\n return this.imageLabels.loadedImagePaths();\r\n }\r\n\r\n async loadImageLabelData(data, progressCallback) {\r\n await this.imageLabels.loadImageLabelData(data, progressCallback);\r\n }\r\n\r\n setActiveLabelType(state) {\r\n this.imageLabels.setActiveLabelType(state);\r\n }\r\n\r\n checkIfActive() {\r\n return this.imageLabels.checkIfActive();\r\n }\r\n\r\n checkIfSelected() {\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 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 addTrainingArea() {\r\n this.imageLabels.addTrainingArea();\r\n }\r\n\r\n deleteHighlighted() {\r\n this.imageLabels.deleteHighlighted();\r\n }\r\n\r\n /*addPolygon(polygon) {\r\n this.imageLabels.orthoLabels.drawPoly(polygon);\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 deleteTrainingAreas() {\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 deletePoint(id) {\r\n this.imageLabels.deletePoint(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 selectLabel(id) {\r\n this.imageLabels.selectLabel(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 numHighlighted() {\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 anyLabelSelected = () => {\r\n return this.imageLabels.checkIfSelected();\r\n }\r\n\r\n /* Asset Click functions */\r\n snapToOrtho(id) {\r\n const ortho = this.minimap.orthoList.getByID(id);\r\n if (!ortho) {\r\n return;\r\n }\r\n\r\n ortho.zoomToExtent();\r\n }\r\n\r\n snapToPointCloud(id) {\r\n const pointCloud = this.pointclouds.getByID(id);\r\n if (!pointCloud) {\r\n return;\r\n }\r\n\r\n let tightBoundingBox = pointCloud.tightBoundingBox;\r\n if (!tightBoundingBox) {\r\n return;\r\n }\r\n\r\n this.pointclouds.setLoadedOnce(false);\r\n this.pointclouds.zoomToExtent(tightBoundingBox, true, true);\r\n }\r\n\r\n snapToImages(id) {\r\n const cameras = this.cameraList.getByCSV(id);\r\n if (cameras.length === 0) {\r\n return;\r\n }\r\n\r\n let positions = cameras.map(camera => {\r\n return camera.position.value;\r\n });\r\n\r\n let extent = extentFromPoints(positions);\r\n this.minimap.setMapExtent(extent);\r\n }\r\n\r\n /* Camera Aligner Function Calls */\r\n resetCameraAligner() {\r\n this.controls.cameraAlignerAdv.reset();\r\n }\r\n\r\n checkIfAligned() {\r\n return this.cameraList.aligned;\r\n }\r\n\r\n addRowCameraAligner() {\r\n this.controls.cameraAlignerAdv.addRow();\r\n }\r\n\r\n setErrorsCameraAligner(errors) {\r\n this.controls.cameraAlignerAdv.setErrors(errors);\r\n }\r\n\r\n getErrorCameraAligner(i) {\r\n return this.controls.cameraAlignerAdv.getError(i);\r\n }\r\n\r\n deleteRowCameraAligner(i) {\r\n this.controls.cameraAlignerAdv.deleteRow(i);\r\n }\r\n\r\n getImageObsCameraAligner(i) {\r\n return this.controls.cameraAlignerAdv.getImageObs(i);\r\n }\r\n\r\n getPointObsCameraAligner(i) {\r\n return this.controls.cameraAlignerAdv.getPointObs(i);\r\n }\r\n\r\n getCamPoseCameraAligner(i) {\r\n return this.controls.cameraAlignerAdv.getCamPose(i);\r\n }\r\n\r\n getNumEntriesCameraAligner() {\r\n return this.controls.cameraAlignerAdv.numEntries;\r\n }\r\n\r\n getCamIdFromAligner(i) {\r\n return this.controls.cameraAlignerAdv.getCamId(i);\r\n }\r\n\r\n setBasicAlignerState(state) {\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 getCamName(i) {\r\n return this.controls.cameraAlignerAdv.getCamName(i);\r\n }\r\n\r\n getCurrentCameraName() {\r\n return this.cameraList.current?.name;\r\n }\r\n\r\n setObservationTypeCameraAligner(type) {\r\n this.controls.cameraAlignerAdv.setObservationType(type);\r\n }\r\n\r\n setCurrentRowCameraAligner(rowNum) {\r\n this.controls.cameraAlignerAdv.setCurrentRow(rowNum);\r\n }\r\n\r\n flashObservations(rowNum) {\r\n this.controls.cameraAlignerAdv.flashObservations(rowNum);\r\n }\r\n\r\n hideCurrentObservation(type, rowNum) {\r\n this.controls.cameraAlignerAdv.hideCurrentObservation(type, rowNum);\r\n }\r\n\r\n getObservationPosition(rowNum) {\r\n return this.controls.cameraAlignerAdv.getObservationPosition(rowNum);\r\n }\r\n\r\n /* End - Camera Aligner Function Calls */\r\n\r\n updateCompassOffset(offset) {\r\n this.compass.updateOffset(offset);\r\n }\r\n\r\n getCamerasForCSV = (assetID) => {\r\n return this.cameraList.getByCSV(assetID);\r\n }\r\n\r\n getCloudPercent(identifier) {\r\n let cloud = this.pointclouds.getByID(identifier);\r\n if (cloud && cloud instanceof RawPointCloud) {\r\n return cloud.percent;\r\n }\r\n\r\n return 0.0;\r\n }\r\n\r\n getCloudMissing(identifier) {\r\n let cloud = this.pointclouds.getByID(identifier);\r\n if (cloud) {\r\n return cloud.fileMissing;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n getCloudIsLarge(identifier) {\r\n let cloud = this.pointclouds.getByID(identifier);\r\n if (cloud && cloud instanceof RawPointCloud) {\r\n return cloud.isLargeFile;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n checkShiftReset() {\r\n const cameraList = this.cameraList.cameras;\r\n const cloudList = this.pointclouds.clouds;\r\n\r\n if ((cameraList.length === 0) && (cloudList.length === 0)) {\r\n LocalScene.resetSceneShift();\r\n }\r\n }\r\n\r\n reconcileCameras(camerasFiles, cameraHeight, cameraAdjustments, savedCameraState: SceneCameraState) {\r\n const existingCameras = this.cameraList.cameras;\r\n const allCameras = camerasFiles.map(cameraFile => {\r\n if (!cameraFile.visible) {\r\n return [];\r\n }\r\n\r\n return cameraFile.data.map(camera => {\r\n return {\r\n ...camera,\r\n id: `${cameraFile.id}-${camera.name}`,\r\n csv: cameraFile.id,\r\n assetType: cameraFile.type,\r\n fromJSON: cameraFile.fromJSON,\r\n };\r\n });\r\n }).flat();\r\n\r\n const activeCamera = savedCameraState.camera;\r\n const newCameras = new Set(allCameras.map(camera => camera.id));\r\n const currentCameras = new Set(existingCameras.map(camera => camera.id));\r\n const camerasToLoad = allCameras.filter(camera => !currentCameras.has(camera.id));\r\n const camerasToDelete = existingCameras.filter(camera => !newCameras.has(camera.id));\r\n\r\n const numRemoved = camerasToDelete.length;\r\n const numAdded = camerasToLoad.length;\r\n const numChanged = numRemoved + numAdded;\r\n\r\n // Delete existing cameras\r\n this.cameraList.deleteCameras(camerasToDelete);\r\n\r\n // Add all new cameras\r\n this.cameraList.addCameras(camerasToLoad,\r\n cameraAdjustments, cameraHeight);\r\n\r\n // Load saved camera from cameras state\r\n if (camerasToLoad.find(x => x.id === activeCamera)) {\r\n this.cameraList.setWaitForCameras(true);\r\n this.setCameraVisible(activeCamera, savedCameraState);\r\n }\r\n\r\n const cameraList = this.cameraList.cameras;\r\n const numCameras = cameraList.length;\r\n\r\n // Redraw cameras in scene and aerial view after changes\r\n if ((numRemoved > 0) || (numAdded > 0)) {\r\n this.minimap.addCameraMarkers(cameraList);\r\n this.markers.addCameraMarkers(cameraList);\r\n this.controls.measurements.refreshMeasurementList();\r\n }\r\n\r\n // Update arrow marker navigation\r\n if ((numRemoved > 0) || ((numAdded > 0) && (numAdded < numCameras))) {\r\n this.markers.updateArrowNavigation();\r\n }\r\n\r\n // All cameras have been removed\r\n if ((numCameras === 0) && (numRemoved > 0)) {\r\n this.cameraList.setOrbitCamera();\r\n this.minimap.setActiveCamera();\r\n this.markers.clearArrowNavigation();\r\n return;\r\n }\r\n\r\n // Apply default orbit position if possible\r\n if (this.setOrbitDefault(numAdded, savedCameraState)) {\r\n return;\r\n }\r\n\r\n // Camera changed (added or removed) and nothing visible.\r\n // Switch to the first camera in our new camera list instead\r\n if ((numChanged > 0) && (!this.cameraList.cameraLoaded)) {\r\n if (cameraList.length > 0) {\r\n this.cameraList.setWaitForCameras(true);\r\n this.setCameraVisible(cameraList[0].id);\r\n }\r\n }\r\n }\r\n\r\n reconcilePointClouds(pointClouds, savedCameraState: SceneCameraState) {\r\n const cloudList = this.pointclouds.clouds;\r\n const currentPointClouds = new Set(cloudList.map(cloud => cloud.identifier));\r\n const newPointClouds = new Set(pointClouds.map(cloud => cloud.id));\r\n\r\n const pointCloudsToLoad = pointClouds.filter(cloud => !currentPointClouds.has(cloud.id));\r\n const pointCloudsToDelete = cloudList.filter(cloud => !newPointClouds.has(cloud.identifier));\r\n\r\n const numRemoved = pointCloudsToDelete.length;\r\n const numAdded = pointCloudsToLoad.length;\r\n\r\n // Delete clouds that need to be removed\r\n pointCloudsToDelete.forEach(pointCloud => {\r\n this.pointclouds.deletePointCloud(pointCloud.identifier);\r\n });\r\n\r\n // Add new pointclouds\r\n pointCloudsToLoad.forEach(pointCloud => {\r\n const cloudDetails = {\r\n name: pointCloud.name,\r\n identifier: pointCloud.id,\r\n path: slash(pointCloud.data.path),\r\n visible: pointCloud.visible,\r\n remote: isStaticSite,\r\n fromJSON: pointCloud.fromJSON\r\n };\r\n\r\n if (pointCloud.type === AssetType.LAS) {\r\n let pointCloud = new RawPointCloud(this.pointclouds);\r\n pointCloud.loadFile(cloudDetails);\r\n } else if (pointCloud.type === AssetType.Encompass) {\r\n let pointCloud = new EncompassPointCloud(this.pointclouds);\r\n pointCloud.loadNodes(cloudDetails);\r\n }\r\n });\r\n\r\n // Toggle proper visibility for each cloud\r\n pointClouds.forEach(pointCloud => {\r\n this.pointclouds.toggleVisibility(pointCloud.id, pointCloud.visible);\r\n });\r\n\r\n const numClouds = this.pointclouds.clouds.length;\r\n const numCameras = this.cameraList.cameras.length;\r\n\r\n // Apply default orbit position if possible\r\n if (this.setOrbitDefault(numAdded, savedCameraState)) {\r\n return;\r\n }\r\n\r\n // No cloud remain. Exit 3d mode if cameras exist\r\n if ((numClouds === 0) && (numRemoved > 0) && (numCameras > 0)) {\r\n this.controls.setOrbitState(false);\r\n }\r\n }\r\n\r\n reconcileOrthos(orthos) {\r\n const orthosList = this.orthoList.orthos;\r\n const currentOrthos = new Set(orthosList.map(ortho => ortho.id));\r\n const newOrthos = new Set(orthos.map(ortho => ortho.id));\r\n\r\n const orthosToLoad = orthos.filter(ortho => !currentOrthos.has(ortho.id));\r\n const orthosToDelete = orthosList.filter(ortho => !newOrthos.has(ortho.id));\r\n\r\n // Delete orthos that need to be removed\r\n orthosToDelete.forEach(ortho => {\r\n this.orthoList.deleteOrtho(ortho.id);\r\n });\r\n\r\n // Add new orthos\r\n orthosToLoad.forEach(ortho => {\r\n const {imageBounds, imageData, imageSize, imageSizeOriginal, imagePath,\r\n scaleX, scaleY} = ortho.data;\r\n\r\n const orthoInfo = {\r\n id: ortho.id,\r\n name: ortho.name,\r\n corners: imageBounds,\r\n base64: imageData,\r\n imageSize: imageSize,\r\n imageSizeOriginal: imageSizeOriginal,\r\n fromJSON: ortho.fromJSON,\r\n imagePath: imagePath,\r\n scaleX: scaleX,\r\n scaleY: scaleY\r\n };\r\n\r\n this.orthoList.addNewOrtho(orthoInfo);\r\n });\r\n\r\n // Toggle proper visibility for each ortho\r\n orthos.forEach(ortho => {\r\n this.orthoList.toggleVisibility(ortho.id, ortho.visible);\r\n });\r\n }\r\n\r\n setCameraHeights(height) {\r\n this.cameraList.setCameraHeights(height);\r\n }\r\n\r\n setCameraAdjustments(adjustments) {\r\n this.cameraList.setCameraAdjustments(adjustments);\r\n }\r\n\r\n setCameraMatrix(matrix) {\r\n this.cameraList.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.cameraList.resetCameraMatrix();\r\n if (this.controls.cameraAlignerAdv.enabled){\r\n this.controls.cameraAlignerAdv.redrawImageObsMarkers();\r\n }\r\n }\r\n\r\n resetLoadedOnce() {\r\n this.pointclouds.setLoadedOnce(false);\r\n }\r\n\r\n resetDefaultAerialState(state) {\r\n this.minimap.map.updateSize();\r\n this.minimap.reset(state);\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) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n this.cameraList.onKeyDown(event);\r\n this.controls.cameraAlignerBasic.onKeyDown(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 }\r\n }\r\n\r\n initViewEvents() {\r\n this.onMouseFocus = this.onMouseFocus.bind(this);\r\n this.onKeyDown = this.onKeyDown.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 }\r\n\r\n destroyViewEvents() {\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 }\r\n\r\n updatePickers() {\r\n Object.keys(this.gpuPickers).forEach(name => {\r\n this.updatePicker(name);\r\n });\r\n }\r\n\r\n updatePicker(name) {\r\n this.gpuPickers[name].needsUpdate = true;\r\n }\r\n\r\n updatePickerCamera() {\r\n const pickers = Object.values(this.gpuPickers);\r\n pickers.forEach(picker => {\r\n picker.setCamera(this.camera);\r\n });\r\n }\r\n\r\n createScene() {\r\n this.camera = new PerspectiveCamera(90, 1.0,\r\n this.defaultNearPlane, this.defaultFarPlane);\r\n\r\n this.renderer = new WebGLRenderer({\r\n antialias: false,\r\n alpha: true,\r\n logarithmicDepthBuffer: false,\r\n powerPreference: \"high-performance\"\r\n });\r\n\r\n if (this.isWebGL2) {\r\n console.log(\"WebGL2 Detected\");\r\n }\r\n\r\n this.renderer.autoClear = false;\r\n }\r\n\r\n initGpuPickers() {\r\n this.gpuPickers = {\r\n markers: new GPUPicker(this, \"markers\", false),\r\n points: new GPUPicker(this, \"points\", false)\r\n };\r\n\r\n for (const picker of Object.values(this.gpuPickers)) {\r\n picker.setCamera(this.camera);\r\n }\r\n }\r\n\r\n initMaterials() {\r\n // Create our render pass\r\n this.screenPass = new RenderPass();\r\n\r\n // Default render target / material\r\n this.opacityMaterial = new OpacityMaterial();\r\n this.texture2DOpacity = new WebGLRenderTarget(\r\n this.width, this.height, {\r\n format: RGBAFormat,\r\n minFilter: NearestFilter,\r\n magFilter: NearestFilter,\r\n stencilBuffer: false\r\n }\r\n );\r\n\r\n // Material for rendering panoramic as background\r\n this.imageMaterial = new ImageMaterial();\r\n this.texture2DImage = new WebGLRenderTarget(\r\n this.width, this.height, {\r\n minFilter: LinearFilter,\r\n magFilter: LinearFilter,\r\n format: RGBAFormat,\r\n stencilBuffer: false\r\n }\r\n );\r\n\r\n if (!this.EDLSupport) {\r\n console.log(\"EDL Not Supported\");\r\n return;\r\n }\r\n\r\n // EDL render target / material\r\n console.log(\"EDL Supported\");\r\n this.EDLMaterial = new EDLMaterial(this);\r\n this.texture2DDepth = new WebGLRenderTarget(\r\n this.width, this.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\r\n let texturePrecision = this.isWebGL2 ? FloatType : UnsignedIntType;\r\n this.texture2DDepth.depthTexture = new DepthTexture(0, 0);\r\n this.texture2DDepth.depthTexture.type = texturePrecision;\r\n }\r\n\r\n initResize() {\r\n bindWindowEvent('resize', () => {\r\n this.handleWindowResize();\r\n });\r\n }\r\n\r\n handleWindowResize() {\r\n let width = this.containerElement.clientWidth;\r\n let height = this.containerElement.clientHeight;\r\n this.resizeCanvas(width, height);\r\n this.updatePickers();\r\n }\r\n\r\n resizeCanvas(width, height) {\r\n let aspect = width / height;\r\n\r\n this.camera.aspect = aspect;\r\n this.camera.updateProjectionMatrix();\r\n this.renderer.setSize(width, height);\r\n this.compass.setSize(width, height);\r\n\r\n if (this.EDLSupport) {\r\n this.EDLMaterial.screenWidth = width;\r\n this.EDLMaterial.screenHeight = height;\r\n }\r\n }\r\n\r\n resizeRenderTargets() {\r\n let width = this.width;\r\n let height = this.height;\r\n\r\n\r\n // Resize render targets\r\n let canvas = [\r\n this.texture2DDepth,\r\n this.texture2DOpacity,\r\n ];\r\n\r\n canvas.forEach(c => {\r\n if (!c) {\r\n return;\r\n }\r\n\r\n let w = c.width;\r\n let h = c.height;\r\n if ((w !== width) || (h !== height)) {\r\n c.dispose();\r\n c.setSize(width, height);\r\n }\r\n });\r\n\r\n // Resize gpu picker targets\r\n const pickers = Object.values(this.gpuPickers);\r\n pickers.forEach(picker => {\r\n picker.resizeTarget(width, height);\r\n });\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 setRenderTarget(target, clear = false) {\r\n this.renderer.setRenderTarget(target);\r\n if (clear) {\r\n this.renderer.clear();\r\n }\r\n }\r\n\r\n renderWithTransparency(scenes, opacity, clear=true) {\r\n this.setRenderTarget(this.renderTarget, clear);\r\n scenes.forEach(scene => {\r\n if (!scene) {\r\n return;\r\n }\r\n\r\n this.renderer.render(scene, this.camera);\r\n });\r\n\r\n this.updateMaterial(this.renderMaterial, {\r\n ...this.renderTargetAttrs, opacity: opacity\r\n });\r\n this.screenPass.render(this.renderer, this.renderMaterial);\r\n }\r\n\r\n renderPanoramic() {\r\n // Render panoramic image\r\n this.setRenderTarget(this.texture2DImage, true);\r\n this.renderer.render(this.cameraList.scene, this.camera);\r\n\r\n // Update material texture with results\r\n this.updateMaterial(this.imageMaterial, {\r\n colorMap: this.texture2DImage.texture\r\n });\r\n\r\n // Render to screen and clear depth\r\n this.screenPass.render(this.renderer, this.imageMaterial);\r\n this.renderer.clearDepth();\r\n }\r\n\r\n renderSceneObjects() {\r\n // Render objects at full opacity\r\n this.renderWithTransparency([\r\n this.markers.renderInFront ? null : this.markers.scene\r\n ], 1.0);\r\n\r\n // Render pointcloud with transparency\r\n this.renderWithTransparency([this.pointclouds.scene],\r\n this.pointclouds.transparency, false);\r\n\r\n // Render scene labels (mixed opacity)\r\n let sceneLabels = this.imageLabels.sceneLabels;\r\n this.renderWithTransparency([sceneLabels.opacityScene],\r\n sceneLabels.opacity);\r\n this.renderWithTransparency([sceneLabels.standardScene], 1.0);\r\n\r\n // Semi-transparent markers sometimes rendered on top of everything\r\n if (this.markers.renderInFront) {\r\n this.renderWithTransparency([this.markers.scene],\r\n this.markers.opacity);\r\n }\r\n\r\n // Items here are rendered on top of everything, so they can always be seen\r\n this.renderWithTransparency([\r\n this.measurements.scene,\r\n this.controls.alignerScene\r\n ], 1.0);\r\n }\r\n\r\n renderPickerScene() {\r\n this.gpuPickers.points.needsUpdate = true;\r\n this.gpuPickers.points.update();\r\n this.setRenderTarget(null, true);\r\n this.renderer.render(this.gpuPickers.points.scene, this.camera);\r\n }\r\n\r\n updateSceneElements() {\r\n this.changeDetector.update();\r\n this.pointclouds.update();\r\n this.measurements.update(this.changeDetector);\r\n this.controls.update(this.changeDetector);\r\n this.cameraList.update();\r\n this.minimap.update(this.changeDetector);\r\n this.markers.update();\r\n this.imageLabels.update(this.changeDetector);\r\n }\r\n\r\n calculateUpdatedValues() {\r\n let state = {\r\n camera: null,\r\n fov: 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.orbit\r\n .getPositionValues();\r\n\r\n state = {\r\n ...state,\r\n orbit: orbit,\r\n pivot: pivot\r\n };\r\n } else if (this.cameraList.current) {\r\n // Update for standard camera\r\n state = {\r\n ...state,\r\n camera: this.cameraList.current.id,\r\n fov: this.controls.fov,\r\n angles: this.controls.angles\r\n };\r\n }\r\n\r\n this.setCameraState(state);\r\n }\r\n\r\n animate() {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n this.stats.begin();\r\n\r\n this.resizeRenderTargets();\r\n this.updateSceneElements();\r\n\r\n if (this.changeDetector.changed) {\r\n this.updateSavedState();\r\n }\r\n\r\n if (this.drawPickerScene) {\r\n this.renderPickerScene();\r\n } else {\r\n this.renderPanoramic();\r\n this.renderSceneObjects();\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.stats.end();\r\n\r\n requestAnimationFrame(() => {\r\n this.animate();\r\n });\r\n }\r\n}\r\n\r\nclass 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, 0);\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 to screen. Note that our render target is changed after using this function */\r\n render(renderer, 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\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 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) {\r\n return;\r\n }\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.drawExpandedState();\r\n\r\n document.getElementById(\"debug-placeholder\")\r\n .appendChild(this.stats.dom);\r\n\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.left = \"\";\r\n this.stats.dom.style.bottom = \"0px\";\r\n this.stats.dom.style['z-index'] = \"\";\r\n }\r\n\r\n begin() {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n this.stats.begin();\r\n }\r\n\r\n end() {\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n let pointCloud = this.viewer.pointclouds;\r\n let numberNodes = pointCloud.numSceneNodesVisible;\r\n let visiblePoints = pointCloud.numVisiblePoints;\r\n let maxPoints = pointCloud.visiblePointsTarget;\r\n\r\n this.pointsVisible.update(\r\n visiblePoints / 1000,\r\n maxPoints / 1000\r\n );\r\n\r\n this.nodesVisible.update(numberNodes, 500);\r\n\r\n this.stats.end();\r\n }\r\n}\r\n\r\n\r\nexport const withPerformanceMeasure = (name, callback) => {\r\n let response;\r\n\r\n if (isDevMode) {\r\n let timeStart = performance.now();\r\n\r\n response = callback();\r\n\r\n let timeFinish = performance.now();\r\n let timeElapsed = timeFinish - timeStart;\r\n let timeUntilWarning = 10;\r\n if (timeElapsed > timeUntilWarning) {\r\n console.warn(`Slow rendering detected: ${name} took ${timeElapsed}ms`);\r\n }\r\n } else {\r\n response = callback();\r\n }\r\n\r\n return response;\r\n};\r\n","import { PanoControls, RayCaster } from '../controls';\r\nimport { SceneCoordinate } from '../projections';\r\nimport { setPointScale } from '../utilities';\r\nimport { debounce } from 'throttle-debounce';\r\nimport { CameraImage } from '../cameras/cameras';\r\nimport {\r\n Mesh,\r\n Scene,\r\n SphereGeometry,\r\n MeshBasicMaterial,\r\n Vector3\r\n} from 'three';\r\n\r\nclass ImageObservation extends Mesh {\r\n\r\n constructor(geometry, material, row) {\r\n super(geometry, material);\r\n this.name = \"image_\" + row.toString();\r\n }\r\n}\r\n\r\nclass PointObservation extends Mesh {\r\n\r\n constructor(geometry, material, row) {\r\n super(geometry, material);\r\n this.name = \"point_\" + row.toString();\r\n }\r\n}\r\n\r\nexport const pointObsColor = 0xe6e600;\r\nexport const imageObsColor = 0x9900cc;\r\nconst flashColor = 0xffffff;\r\n\r\nexport class CameraAlignerAdv {\r\n private controls;\r\n private setAddObservations;\r\n private setViewerTooltipText;\r\n private resetObservationType;\r\n private currentRow=-1;\r\n private observationType=\"none\";\r\n public enabled = false;\r\n public scene: Scene;\r\n private sceneObs=[];\r\n private pointIdxAdd = 0;\r\n private imageIdxAdd = 0;\r\n private imageObsInterval = null;\r\n private pointObsInterval = null;\r\n private sphereGeometry = new SphereGeometry(0.05, 20, 20);\r\n\r\n constructor(controls, scene, props) {\r\n const {setAddObservations, setViewerTooltipText, resetObservationType} = props;\r\n\r\n this.scene = scene;\r\n this.controls = controls;\r\n this.setAddObservations = setAddObservations;\r\n this.setViewerTooltipText = setViewerTooltipText;\r\n this.resetObservationType = resetObservationType;\r\n }\r\n\r\n get numEntries() {\r\n return this.sceneObs.length;\r\n }\r\n\r\n get viewer() {\r\n return this.controls.viewer;\r\n }\r\n\r\n get selecting() {\r\n const type = this.observationType;\r\n return ((type === \"point\") || (type === \"image\"));\r\n }\r\n\r\n get enabled3dMode() {\r\n return this.controls.orbit.status;\r\n }\r\n\r\n setState(state) {\r\n this.enabled = state;\r\n }\r\n\r\n reset() {\r\n for (let observation of this.sceneObs) {\r\n this.scene.remove(observation.imageMesh);\r\n this.scene.remove(observation.pointMesh);\r\n }\r\n\r\n this.sceneObs = [];\r\n this.pointIdxAdd = 0;\r\n this.imageIdxAdd = 0;\r\n }\r\n\r\n addRow() {\r\n this.sceneObs.push(this.emptyObservation());\r\n }\r\n\r\n setErrors(errors) {\r\n for (let i = 0; iRight-click to cancel`;\r\n this.setViewerTooltipText(text);\r\n } else {\r\n this.setViewerTooltipText(\"\");\r\n }\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 this.sceneObs[this.currentRow].pointIdx);\r\n\r\n this.scene.add(mesh);\r\n this.sceneObs[this.currentRow].pointMesh = mesh;\r\n this.sceneObs[this.currentRow].pointHidden = 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 addImageObservationMesh(position) {\r\n let sphereMaterial = new MeshBasicMaterial({color: imageObsColor});\r\n let mesh = new ImageObservation(this.sphereGeometry, sphereMaterial,\r\n this.sceneObs[this.currentRow].imageIdx);\r\n\r\n this.scene.add(mesh);\r\n this.sceneObs[this.currentRow].imageMesh = mesh;\r\n this.sceneObs[this.currentRow].imageHidden = 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.sceneObs.forEach(obs => {\r\n obs.imageMesh?.material.color.setHex(imageObsColor);\r\n obs.pointMesh?.material.color.setHex(pointObsColor);\r\n });\r\n }\r\n\r\n flashObservations(rowNum) {\r\n this.clearFlashIntervals();\r\n\r\n const imageMesh = this.sceneObs[rowNum].imageMesh;\r\n if (imageMesh) {\r\n this.imageObsInterval = this.flashObservation(\r\n imageMesh, imageObsColor);\r\n }\r\n\r\n const pointMesh = this.sceneObs[rowNum].pointMesh;\r\n if (pointMesh) {\r\n this.pointObsInterval = this.flashObservation(\r\n pointMesh, pointObsColor);\r\n }\r\n };\r\n\r\n hideCurrentObservation(type, rowNum) {\r\n this.resetHiddenState();\r\n\r\n if (type === 'image') {\r\n this.sceneObs[rowNum].imageHidden = true;\r\n } else {\r\n this.sceneObs[rowNum].pointHidden = true;\r\n }\r\n\r\n this.updateAllMeshes();\r\n }\r\n\r\n getObservationPosition(rowNum) {\r\n return this.sceneObs[rowNum].imageMesh?.position;\r\n }\r\n\r\n resetHiddenState() {\r\n this.sceneObs.forEach(obs => {\r\n obs.imageHidden = false;\r\n obs.pointHidden = false;\r\n });\r\n }\r\n\r\n emptyObservation = () => {\r\n return {\r\n imageObs: null,\r\n imageMesh: null,\r\n imageHidden: false,\r\n pointObs: null,\r\n pointMesh: null,\r\n pointHidden: false,\r\n imageIdentifier: \"\",\r\n name: \"No File\",\r\n pose: [],\r\n error: 0,\r\n pointIdx: -1,\r\n imageIdx: -1\r\n };\r\n }\r\n\r\n removeMarker(name) {\r\n this.scene.children.forEach(child => {\r\n if (child.name === name){\r\n this.scene.remove(child);\r\n }\r\n });\r\n }\r\n\r\n redrawImageObsMarkers() {\r\n if (this.sceneObs === null || this.sceneObs.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.pointHidden;\r\n }\r\n\r\n // Resize image ibservations and set visibility\r\n if (obs.imageMesh && this.viewer.cameraList.current){\r\n const currentID = this.viewer.cameraList.current.id;\r\n const matchingCamera = obs.imageIdentifier === currentID;\r\n\r\n if (matchingCamera && !this.enabled3dMode) {\r\n this.setPointScale(obs.imageMesh);\r\n obs.imageMesh.visible = !obs.imageHidden;\r\n } else {\r\n obs.imageMesh.visible = false;\r\n }\r\n }\r\n });\r\n }\r\n\r\n update(changeDetector) {\r\n if (changeDetector === null) {\r\n return;\r\n }\r\n\r\n const update = changeDetector.changed;\r\n if (!update) {\r\n return;\r\n }\r\n\r\n if (!this.enabled){\r\n return;\r\n }\r\n\r\n this.updateAllMeshes();\r\n }\r\n}\r\n\r\nexport class CameraAlignerBasic {\r\n public enabled = false;\r\n private increment = 0.10;\r\n private cameraAngles = [0, 0, 0];\r\n private controls: PanoControls\r\n private setSingleAlignment;\r\n\r\n constructor(controls: PanoControls, props) {\r\n const {setSingleAlignment} = props;\r\n\r\n this.controls = controls;\r\n\r\n // Need to debounce to update ui smoothly\r\n this.setSingleAlignment = debounce(10, (value) => {\r\n setSingleAlignment(value);\r\n });\r\n\r\n this.reset();\r\n }\r\n\r\n get currentCamera() : CameraImage {\r\n return this.controls.cameraList?.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) {\r\n return;\r\n }\r\n\r\n if (event.code === \"Numpad7\") {\r\n this.cameraAngles[0] -= this.increment;\r\n } else if (event.code === \"Numpad9\") {\r\n this.cameraAngles[0] += this.increment;\r\n } else if (event.code === \"Numpad4\") {\r\n this.cameraAngles[1] -= this.increment;\r\n } else if (event.code === \"Numpad6\") {\r\n this.cameraAngles[1] += this.increment;\r\n } else if (event.code === \"Numpad1\") {\r\n this.cameraAngles[2] -= this.increment;\r\n } else if (event.code === \"Numpad3\") {\r\n this.cameraAngles[2] += this.increment;\r\n }\r\n\r\n this.updateAlignment();\r\n }\r\n\r\n updateAlignment() {\r\n this.setSingleAlignment([...this.cameraAngles]);\r\n this.currentCamera?.applyTempRotation(this.cameraAngles);\r\n }\r\n}","import {touchToMouse} from \"../misc\";\r\nimport {CustomOrbitControls} from \"./orbit-controls\";\r\nimport {Viewer, withPerformanceMeasure} from '../main';\r\nimport { CameraAlignerAdv, CameraAlignerBasic } from '../image-aligner/image-aligner';\r\nimport { eventToPixel } from '../utilities';\r\nimport { SceneCoordinate, SphericalPosition } from '../projections';\r\nimport {\r\n AmbientLight,\r\n MathUtils,\r\n Raycaster,\r\n Scene,\r\n Vector2,\r\n Vector3,\r\n} from 'three';\r\n\r\nexport class PanoControls {\r\n public viewer: Viewer;\r\n public object: any;\r\n public domElement: any;\r\n public cameraAlignerAdv: CameraAlignerAdv;\r\n public cameraAlignerBasic: CameraAlignerBasic;\r\n private minFOV = 10;\r\n public maxFOV = 90;\r\n public orbitDefaultApplied = false;\r\n private time: any;\r\n private enabled: any;\r\n private rotateSpeed: any;\r\n public direction: Vector3;\r\n private up: any;\r\n public orbit: any;\r\n public flyControls: any;\r\n private mouse: any;\r\n private wheelDelta: any;\r\n private phiDelta: any;\r\n private thetaDelta: any;\r\n private assetSelected: any;\r\n private moveEvent: any;\r\n private zooming: any;\r\n private contextMenuClick;\r\n public alignerScene: THREE.Scene\r\n\r\n constructor(viewer, object, domElement, props) {\r\n const {contextMenuClick} = props;\r\n\r\n this.viewer = viewer;\r\n this.object = object;\r\n this.domElement = (domElement !== undefined) ? domElement : document;\r\n this.contextMenuClick = contextMenuClick;\r\n\r\n this.time = performance.now();\r\n\r\n this.enabled = true;\r\n this.rotateSpeed = 1.0;\r\n this.direction = new Vector3(0, 0, 0);\r\n this.up = new Vector3(0, 0, 1);\r\n\r\n this.orbit = new OrbitController(this, this.up);\r\n this.flyControls = new FlyMoveControls(this);\r\n this.mouse = new MouseConfig();\r\n\r\n // Used for touch controls\r\n this.touchHandler = this.touchHandler.bind(this);\r\n\r\n this.initScene();\r\n\r\n this.cameraAlignerAdv = new CameraAlignerAdv(this, this.alignerScene, props);\r\n this.cameraAlignerBasic = new CameraAlignerBasic(this, props);\r\n\r\n // Rotation/wheel movement\r\n this.wheelDelta = 0.0;\r\n this.phiDelta = 0;\r\n this.thetaDelta = 0;\r\n this.addEventListeners();\r\n\r\n this.update(null);\r\n }\r\n\r\n get mobile() {\r\n return (/android|webos|iphone|ipad|ipod|blackberry|playbook|BB10|iemobile|opera mini/i\r\n .test(navigator.userAgent.toLowerCase()));\r\n }\r\n\r\n get cameraList() {\r\n return this.viewer.cameraList;\r\n }\r\n\r\n get sceneLabels() {\r\n return this.viewer.imageLabels.sceneLabels;\r\n }\r\n\r\n get markers() {\r\n return this.viewer.markers;\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.points;\r\n }\r\n\r\n get fov(): number {\r\n return this.object.fov;\r\n }\r\n\r\n set fov(value) {\r\n let fov = Math.max(this.minFOV,\r\n Math.min(this.maxFOV, value));\r\n\r\n this.object.fov = fov;\r\n }\r\n\r\n get angles(): [number, 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\r\n addEventListeners() {\r\n let dom = this.domElement;\r\n\r\n // Add all event listeners\r\n dom.addEventListener('mousedown', this.onMouseDown.bind(this), false);\r\n dom.addEventListener('mouseup', this.onMouseUp.bind(this), false);\r\n dom.addEventListener('wheel', this.onMouseWheel.bind(this), false);\r\n dom.addEventListener('dblclick', this.onMouseDoubleClick.bind(this), false);\r\n dom.addEventListener('mousemove', this.toggleMouseMove.bind(this), false);\r\n\r\n // All touchevents get turned into mouse events\r\n dom.addEventListener('touchstart', this.touchHandler, true);\r\n dom.addEventListener('touchmove', this.touchHandler, true);\r\n dom.addEventListener('touchend', this.touchHandler, true);\r\n dom.addEventListener('touchcancel', this.touchHandler, true);\r\n }\r\n\r\n initEvents() {\r\n }\r\n\r\n initScene() {\r\n // Scene for aligner\r\n const alignerScene = new Scene();\r\n const alignerLight = new AmbientLight(0xFFFFFF);\r\n alignerScene.add(alignerLight);\r\n this.alignerScene = alignerScene;\r\n }\r\n\r\n rotateLeft(angle) {\r\n this.thetaDelta += angle;\r\n }\r\n\r\n rotateUp(angle) {\r\n this.phiDelta += angle;\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\r\n resetData() {\r\n this.orbit.controls.enabled = false;\r\n this.thetaDelta = 0;\r\n this.phiDelta = 0;\r\n this.orbit.state = false;\r\n this.direction = new Vector3(0, 0, 0);\r\n this.orbit.setUpVector(this.up);\r\n this.assetSelected = false;\r\n }\r\n\r\n updateFarPlane(far) {\r\n this.object.far = far;\r\n this.orbit.camera.far = far;\r\n }\r\n\r\n getCameraTarget() {\r\n let cameraPosition;\r\n if (this.orbit.controls.enabled) {\r\n cameraPosition = this.orbit.controls.target;\r\n } else {\r\n cameraPosition = this.object.position;\r\n }\r\n return cameraPosition;\r\n }\r\n\r\n setOrbitState(state, position = null) {\r\n this.viewer.updatePickers();\r\n\r\n if (!position) {\r\n // Value is somehow forced to become what it already is...\r\n if ((this.orbit.state) && (state)) {\r\n return;\r\n }\r\n if ((!this.orbit.state) && (!state)) {\r\n return;\r\n }\r\n }\r\n\r\n let newPosition;\r\n let pivotLocation;\r\n let smoothTransition = false;\r\n\r\n this.enabled = false;\r\n if (state) {\r\n // Set our orbit controls position and target\r\n if (!position) {\r\n newPosition = this.object.position;\r\n pivotLocation = new Vector3(0, 0, -1 * this.orbit.rotateLength);\r\n pivotLocation.applyQuaternion(this.object.quaternion);\r\n pivotLocation.add(newPosition);\r\n } else {\r\n newPosition = position.position;\r\n pivotLocation = position.pivot;\r\n smoothTransition = position.smooth;\r\n }\r\n\r\n this.orbit.setPositionValues(newPosition, pivotLocation,\r\n state, smoothTransition);\r\n\r\n this.viewer.camera = this.orbit.camera;\r\n\r\n if (!smoothTransition) {\r\n this.flyControls.disable();\r\n }\r\n } else {\r\n this.orbit.controls.toggleFlyMode(false, false);\r\n this.orbit.controls.enabled = state;\r\n this.viewer.camera = this.object;\r\n }\r\n\r\n this.orbit.state = state;\r\n this.enabled = true;\r\n\r\n // Set panoramic visibility\r\n if (this.cameraList) {\r\n this.cameraList.setMeshVisible(!state);\r\n }\r\n\r\n this.viewer.handleWindowResize();\r\n this.viewer.updatePickerCamera();\r\n }\r\n\r\n // Only ever called from other functions\r\n removeMouseUp() {\r\n this.mouse.upEnabled = false;\r\n }\r\n\r\n getPickerResults(event) {\r\n // Update gpu picker if required\r\n this.picker.update();\r\n\r\n // Grab our geometry index\r\n const index = this.picker.value(event);\r\n if (index === null) {\r\n return null;\r\n }\r\n\r\n // Convert index to closest coordinate\r\n const coordinate = this.picker.getClosestCoordinate(index);\r\n\r\n return coordinate;\r\n }\r\n\r\n onLongPress(event) {\r\n let newEvent = 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, // event.screenX,\r\n screenY: event.changedPointers[0].screenY, // event.screenY,\r\n clientX: event.changedPointers[0].clientX, // event.clientX,\r\n clientY: event.changedPointers[0].clientY, // event.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 this.domElement.dispatchEvent(newEvent);\r\n }\r\n\r\n onDoubleTap(event) {\r\n let pointer = event.changedPointers[0];\r\n let newEvent = 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 this.domElement.dispatchEvent(newEvent);\r\n }\r\n\r\n resetCamera(side=\"top\") {\r\n let clouds = this.pointclouds;\r\n let bbox = clouds.combinedBoundingBox;\r\n if (!bbox) {\r\n return;\r\n }\r\n\r\n let newPosition = clouds.orbitPositionFromBounds(bbox, side, true);\r\n this.setOrbitState(true, newPosition);\r\n }\r\n\r\n toggleCamera() {\r\n let checked = this.orbit.status;\r\n this.setOrbitState(!checked);\r\n }\r\n\r\n toggleMouseMove(event) {\r\n this.mouse.moveEnabled = true;\r\n this.moveEvent = event;\r\n }\r\n\r\n onMouseMove(event) {\r\n if (!this.mouse.moveEnabled) {\r\n return;\r\n }\r\n\r\n const markers = this.markers;\r\n const sceneLabels = this.sceneLabels;\r\n const measurements = this.measurements;\r\n const aligner = this.cameraAlignerAdv;\r\n const compass = this.viewer.compass;\r\n\r\n let element = this.domElement === document ? this.domElement.body : this.domElement;\r\n this.mouse.moveEnabled = false;\r\n\r\n if (this.mouse.down) {\r\n this.mouse.moveEnd.set(event.clientX, event.clientY);\r\n let mouseMoveDistance = this.mouse.moveStart.distanceTo(this.mouse.moveEnd);\r\n this.mouse.moveDistance += mouseMoveDistance;\r\n this.mouse.moveDelta.subVectors(this.mouse.moveEnd, this.mouse.moveStart);\r\n this.mouse.moveStart.copy(this.mouse.moveEnd);\r\n this.mouse.movement = this.mouse.moveDistance > 0;\r\n }\r\n\r\n // Compass mousemove\r\n let hovering = compass.onMouseMove(event);\r\n if (hovering) {\r\n return;\r\n }\r\n\r\n // Marker mousemove\r\n markers.onMouseMove(event, this.mouse);\r\n\r\n // Measurements mousemove\r\n measurements.onMouseMove(event, this.mouse);\r\n if (measurements.movingEndpoint) {\r\n return;\r\n }\r\n\r\n // Scene labels mousemove\r\n sceneLabels.onMouseMove(event, this.mouse);\r\n if (sceneLabels.movingEndpoint) {\r\n return;\r\n }\r\n\r\n if (aligner.enabled) {\r\n aligner.updateSelectionText();\r\n }\r\n\r\n if (!this.mouse.movement) {\r\n return;\r\n }\r\n\r\n // Exit here if we are in 3d mode (or measurements are disabled somehow)\r\n if (!this.enabled || this.orbit.state) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n\r\n // Set the rotation\r\n let rotateDelta = new Vector2().copy(this.mouse.moveDelta);\r\n\r\n // Lessen the rotation when zoomed in\r\n rotateDelta.multiplyScalar(this.object.fov / 90);\r\n\r\n // Rotating across whole screen goes 360 degrees around\r\n this.rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * this.rotateSpeed);\r\n\r\n // Rotating up and down along whole screen attempts to go 360, but limited to 180\r\n this.rotateUp(Math.PI * rotateDelta.y / element.clientHeight * this.rotateSpeed);\r\n }\r\n\r\n onMouseDown(event) {\r\n event.preventDefault();\r\n this.mouse.down = true;\r\n this.mouse.button = event.button;\r\n\r\n // We always want the mouseup event to happen\r\n this.mouse.upEnabled = true;\r\n\r\n // Start rotation and listen to mousemove events\r\n this.mouse.moveStart.set(event.clientX, event.clientY);\r\n this.mouse.moveDistance = 0;\r\n }\r\n\r\n onMouseUp(event) {\r\n const measurements = this.measurements;\r\n const sceneLabels = this.sceneLabels;\r\n const aligner = this.cameraAlignerAdv;\r\n const compass = this.viewer.compass;\r\n\r\n this.mouse.down = false;\r\n\r\n // We are no longer grabbing measurement endpoints\r\n measurements.measureGrabFinished();\r\n\r\n // Might have been turned off while adjusting measurements\r\n this.orbit.toggle(true);\r\n\r\n if (!this.mouse.upEnabled || !this.enabled) {\r\n return;\r\n }\r\n\r\n let isRightClick = event.button === 2;\r\n let isLeftClick = event.button === 0;\r\n\r\n if (this.mouse.movement) {\r\n this.finishMouseUp();\r\n return;\r\n }\r\n\r\n if (isLeftClick) {\r\n let markerClicked = this.markers.mouseClick(event);\r\n if (markerClicked) {\r\n this.finishMouseUp();\r\n return;\r\n }\r\n\r\n let compassClicked = compass.mouseClick(event);\r\n if (compassClicked) {\r\n this.finishMouseUp();\r\n return;\r\n }\r\n }\r\n\r\n if (sceneLabels.enabled) {\r\n sceneLabels.contextMenuOpen = false;\r\n if (isLeftClick) {\r\n sceneLabels.mouseClick(event);\r\n } else if (isRightClick) {\r\n if (sceneLabels.drawing) {\r\n // Cancel scene labels\r\n sceneLabels.cancelLabel();\r\n } else {\r\n // Check if highlighting should happen\r\n const highlightSuccess = sceneLabels.highlightOnClick(event);\r\n if (!highlightSuccess) {\r\n // If not open contextMenu normally.\r\n this.contextMenuClick(event);\r\n sceneLabels.contextMenuOpen = true;\r\n }\r\n }\r\n }\r\n } else if (measurements.enabled) {\r\n if (isLeftClick) {\r\n measurements.mouseClick(event);\r\n } else if (isRightClick) {\r\n if (measurements.measuring) {\r\n // Cancel measurement\r\n measurements.cancelMeasurement(event);\r\n } else {\r\n // Show context menu\r\n this.contextMenuClick(event);\r\n }\r\n }\r\n } else {\r\n if (isLeftClick) {\r\n // Get direction vector\r\n if (aligner.enabled) {\r\n aligner.mouseClick(event);\r\n }\r\n } else if (isRightClick) {\r\n if (aligner.selecting) {\r\n // Cancel observation selection\r\n aligner.cancelAlignment();\r\n } else {\r\n // Show context menu\r\n this.contextMenuClick(event);\r\n }\r\n }\r\n }\r\n\r\n this.finishMouseUp();\r\n }\r\n\r\n onMouseWheel(event) {\r\n this.zooming = true;\r\n this.viewer.updatePickers();\r\n\r\n // Remember if we are scrolling (to stop updating pointcloud)\r\n this.mouse.scrolling = true;\r\n clearTimeout(this.mouse.wheelTimeout);\r\n this.mouse.wheelTimeout = setTimeout(() => {\r\n this.mouse.scrolling = false;\r\n }, this.mouse.wheelDelay);\r\n\r\n if (this.enabled === false) {\r\n return;\r\n }\r\n\r\n if (this.orbit.state) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n\r\n let delta = 0;\r\n if (event.deltaY > 0) {\r\n delta = -5;\r\n } else if (event.deltaY < 0) {\r\n delta = 5;\r\n }\r\n\r\n this.wheelDelta = delta;\r\n }\r\n\r\n onMouseDoubleClick(event) {\r\n if ((!this.enabled) || (this.measurements.enabled)) {\r\n return;\r\n }\r\n\r\n let coordinate = this.getPickerResults(event);\r\n if (coordinate === null) {\r\n return;\r\n }\r\n\r\n if (this.orbit.status && !this.orbit.flyModeEnabled) {\r\n // Move to new pointcloud location\r\n this.flyControls.start(coordinate, true);\r\n }\r\n }\r\n\r\n restrictOrbitMovement(value) {\r\n let orbit = this.orbit.controls;\r\n orbit.enableRotate = value;\r\n orbit.enablePan = value;\r\n }\r\n\r\n finishMouseUp() {\r\n let callback = () => {\r\n if (this.mouse.movement) {\r\n this.viewer.updatePickers();\r\n }\r\n\r\n this.mouse.movement = false;\r\n this.orbit.movement = false;\r\n };\r\n\r\n if (this.orbit.controls.enabled) {\r\n // Function will be called when orbit controls stop rotating/panning\r\n this.orbit.movement = true;\r\n this.orbit.callback = callback;\r\n } else {\r\n // Call our function immediately\r\n callback();\r\n }\r\n\r\n this.removeMouseUp();\r\n }\r\n\r\n getCameraDistance() {\r\n let minDistance = 1.0;\r\n let distance = minDistance;\r\n\r\n if (this.orbit.state) {\r\n let orbitObject = this.orbit.controls;\r\n let cameraPosition = orbitObject.object.position;\r\n let cameraPivot = orbitObject.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(event) {\r\n let mouseEvent = touchToMouse(this, event);\r\n if (!mouseEvent) {\r\n return;\r\n }\r\n\r\n event.preventDefault();\r\n event.changedTouches[0].target.dispatchEvent(mouseEvent);\r\n }\r\n\r\n rotateSynchronous(angle) {\r\n this.thetaDelta += angle;\r\n this.adjustLookat();\r\n }\r\n\r\n adjustLookat() {\r\n this.object.up = this.up;\r\n let phiDelta = this.phiDelta + MathUtils.degToRad(90);\r\n this.direction.x = Math.cos(this.thetaDelta) * Math.sin(phiDelta);\r\n this.direction.y = Math.sin(this.thetaDelta) * Math.sin(phiDelta);\r\n this.direction.z = -1 * Math.cos(phiDelta);\r\n this.direction.add(this.object.position);\r\n this.object.lookAt(this.direction);\r\n this.object.updateProjectionMatrix();\r\n\r\n let maxAngle = 360 * Math.PI / 180;\r\n this.thetaDelta = this.thetaDelta % maxAngle;\r\n this.phiDelta = this.phiDelta % maxAngle;\r\n }\r\n\r\n updateView() {\r\n if (this.wheelDelta !== 0) { // controls mouse wheel zoom\r\n let fov = this.object.fov - this.wheelDelta;\r\n this.fov = fov;\r\n }\r\n\r\n // Rotate our lookat vector\r\n this.adjustLookat();\r\n\r\n // Reset\r\n this.wheelDelta = 0;\r\n this.zooming = false;\r\n }\r\n\r\n update(changeDetector) {\r\n withPerformanceMeasure(\"controls.ts\", () => {\r\n this.cameraAlignerAdv.update(changeDetector);\r\n this.onMouseMove(this.moveEvent);\r\n\r\n if (this.orbit.movement) {\r\n this.orbit.checkMovement();\r\n }\r\n\r\n // Update orbit performance tick\r\n let timeEnd = performance.now();\r\n let tick = timeEnd - this.time;\r\n this.time = timeEnd;\r\n this.orbit.controls.tick = tick;\r\n\r\n if (this.flyControls.enabled) {\r\n this.flyControls.move();\r\n }\r\n\r\n if (!this.enabled) {\r\n return;\r\n }\r\n\r\n this.orbit.update();\r\n this.updateView();\r\n });\r\n }\r\n}\r\n\r\nclass MouseConfig {\r\n private down: any;\r\n private button: any;\r\n private moveTolerance: any;\r\n private wheelTimeout: any;\r\n private wheelDelay: any;\r\n private endTimeout: any;\r\n private endDelay: any;\r\n private rotating: any;\r\n private zooming: any;\r\n private scrolling: any;\r\n private moveTick: any;\r\n private moveInterval: any;\r\n private moveEvent: any;\r\n private moveEnabled: any;\r\n private moveStart: any;\r\n private moveEnd: any;\r\n private moveDelta: any;\r\n private moveDistance: any;\r\n private upEnabled: any;\r\n\r\n constructor() {\r\n this.down = false;\r\n this.button = 0;\r\n this.moveTolerance = 10;\r\n\r\n this.wheelTimeout = null;\r\n this.wheelDelay = 150;\r\n\r\n this.endTimeout = 50;\r\n this.endDelay = 500;\r\n\r\n // Detect movement\r\n this.rotating = false;\r\n this.zooming = false;\r\n this.scrolling = false;\r\n\r\n this.moveTick = 100;\r\n this.moveInterval = null;\r\n this.moveEvent = null;\r\n this.moveEnabled = false;\r\n\r\n this.moveStart = new Vector2();\r\n this.moveEnd = new Vector2();\r\n this.moveDelta = new Vector2();\r\n this.moveDistance = 0;\r\n\r\n this.upEnabled = false;\r\n }\r\n}\r\n\r\nclass FlyMoveControls {\r\n private panoControls: PanoControls;\r\n private maxSteps: any;\r\n private rotateLength: any;\r\n private heightAbove: any;\r\n private enabled: any;\r\n private step: any;\r\n private initial: SphericalPosition;\r\n private increment: SphericalPosition;\r\n private pivot: Vector3;\r\n\r\n constructor(parent) {\r\n this.panoControls = parent;\r\n\r\n this.maxSteps = 10;\r\n this.rotateLength = 2.0;\r\n this.heightAbove = 0.0;\r\n\r\n this.disable();\r\n }\r\n\r\n get viewer() {\r\n return this.panoControls.viewer;\r\n }\r\n\r\n enable(pivot, initial, increment) {\r\n this.enabled = true;\r\n this.step = 0;\r\n this.pivot = pivot;\r\n this.initial = initial;\r\n this.increment = increment;\r\n }\r\n\r\n disable() {\r\n this.enabled = false;\r\n this.step = null;\r\n this.initial = null;\r\n this.increment = null;\r\n }\r\n\r\n start(pivot, addHeight, final = null) {\r\n let orbit = this.panoControls.orbit;\r\n let current = this.viewer.camera.position;\r\n let totalIntervals = this.maxSteps;\r\n\r\n if (addHeight) {\r\n // We actually move above our clicked point, so we cant move around\r\n // easier after getting to this location;\r\n pivot.z += this.heightAbove;\r\n }\r\n\r\n if (final === null) {\r\n // Final position is our clicked values minus the rotate length\r\n let vector = new Vector3()\r\n .add(pivot)\r\n .sub(current)\r\n .setLength(this.rotateLength);\r\n\r\n // Calculate final position based on rotate length\r\n final = new Vector3().add(pivot).sub(vector);\r\n }\r\n\r\n let sphereStart = new SphericalPosition()\r\n .fromVectors(pivot, current);\r\n\r\n let sphereFinish = new SphericalPosition()\r\n .fromVectors(pivot, final);\r\n\r\n let dRadius = sphereFinish.radius - sphereStart.radius;\r\n let dPhi = sphereFinish.phi - sphereStart.phi;\r\n\r\n // Make sure the rotation stays between [-180, 180]\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 let increment = new SphericalPosition().fromValues(\r\n dRadius / totalIntervals,\r\n dTheta / totalIntervals,\r\n dPhi / totalIntervals,\r\n );\r\n\r\n // Initial starting point (current position, looking at final pivot)\r\n orbit.setPositionValues(current, pivot, true);\r\n\r\n this.enable(pivot, sphereStart, increment);\r\n }\r\n\r\n move() {\r\n let orbit = this.panoControls.orbit;\r\n let theta = this.initial.theta + this.increment.theta * this.step;\r\n let radius = this.initial.radius + this.increment.radius * this.step;\r\n let phi = this.initial.phi + this.increment.phi * this.step;\r\n\r\n let pos = new SphericalPosition()\r\n .fromValues(radius, theta, phi)\r\n .toVector3()\r\n .add(this.pivot);\r\n\r\n // Travelled our max distance\r\n if (this.step === this.maxSteps) {\r\n // Set the final position and pivot\r\n orbit.setPositionValues(pos, this.pivot, true);\r\n this.disable();\r\n return;\r\n }\r\n\r\n // Set position only. Increment step counter\r\n this.viewer.camera.position.set(pos.x, pos.y, pos.z);\r\n //this.pos.add(increment);\r\n this.step += 1;\r\n }\r\n}\r\n\r\nclass OrbitController {\r\n private panoControls: PanoControls;\r\n private up: any;\r\n private rotateLength: any;\r\n private state: any;\r\n private movement: any;\r\n private camera: any;\r\n private controls: any;\r\n private orbit: any;\r\n private mouse: any;\r\n private flyControls: any;\r\n private callback: any;\r\n\r\n constructor(panoControls, up) {\r\n this.panoControls = panoControls;\r\n this.up = up;\r\n\r\n this.rotateLength = 10.0;\r\n this.state = false;\r\n this.movement = false;\r\n\r\n this.camera = this.panoControls.object.clone();\r\n this.camera.isPerspectiveCamera = true;\r\n this.camera.up.copy(this.up);\r\n\r\n this.controls = new CustomOrbitControls(this.camera,\r\n this.panoControls.domElement);\r\n this.controls.enableDamping = true;\r\n this.controls.dampingFactor = 0.15;\r\n this.controls.rotateSpeed = 0.50;\r\n this.controls.panSpeed = 0.50;\r\n this.controls.enabled = false;\r\n }\r\n\r\n get status() {\r\n return this.state;\r\n }\r\n\r\n get flyModeEnabled() {\r\n return this.controls.flyMode;\r\n }\r\n\r\n get loadingRestricted() {\r\n let orbit = this.orbit;\r\n let orbitMovement = (orbit.movement) && (orbit.status);\r\n\r\n if (this.mouse.scrolling) {\r\n return true;\r\n } else if (this.flyControls.enabled) {\r\n return true;\r\n } else if (orbitMovement) {\r\n return true;\r\n } else if (this.mouse.down) {\r\n return true;\r\n }\r\n\r\n return false;\r\n }\r\n\r\n set flyModeSpeed(value) {\r\n this.controls.setFlySpeed(value);\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.camera.position)\r\n .toDataProjection()\r\n .toArray();\r\n\r\n pivot = new SceneCoordinate(this.controls.target)\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(pos, pivot, enabled, smooth=false) {\r\n if (smooth) {\r\n this.panoControls.flyControls.start(pivot, false, pos);\r\n } else {\r\n this.controls.position0.set(pos.x, pos.y, pos.z);\r\n this.controls.target0.set(pivot.x, pivot.y, pivot.z);\r\n this.controls.reset();\r\n }\r\n\r\n this.controls.enabled = enabled;\r\n }\r\n\r\n setUpVector(upVector) {\r\n this.up = upVector;\r\n this.camera.up.copy(this.up);\r\n }\r\n\r\n update() {\r\n if (!this.state) {\r\n return;\r\n }\r\n\r\n this.controls.update();\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.controls.enabled = value;\r\n }\r\n }\r\n\r\n // Our orbit controls keep spinning/panning for a while after you release the\r\n // mouse button, so we need to find out when they are actually done rotating\r\n checkMovement() {\r\n let camera = this.controls;\r\n if (camera.isMoving() === false) {\r\n this.callback();\r\n }\r\n }\r\n}\r\n\r\nexport class RayCaster {\r\n private debug: any;\r\n private initialized: any;\r\n private width: any;\r\n private height: any;\r\n private event: any;\r\n private camera: any;\r\n private raycaster: any;\r\n\r\n constructor(viewer: Viewer, event) {\r\n this.debug = false;\r\n this.initialized = false;\r\n this.width = viewer.width;\r\n this.height = viewer.height;\r\n this.event = event;\r\n this.camera = viewer.camera;\r\n\r\n this.init();\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 intersectObject(target) {\r\n return this.raycaster.intersectObject(target);\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 };\r\n\r\n let options = {...defaults, ...opts};\r\n\r\n let objects = this.raycaster.intersectObjects(targets);\r\n\r\n if (options.minDistance !== null) {\r\n objects = objects.filter(item => item.distance > 0.10);\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 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 raycastDirection(vec) {\r\n vec.unproject(this.camera);\r\n vec.sub(this.camera.position).normalize();\r\n return vec;\r\n }\r\n\r\n defaultRaycaster(direction) {\r\n if (!direction) {\r\n return false;\r\n }\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 return raycaster;\r\n }\r\n}\r\n","/**\r\n * Full-screen textured quad shader\r\n */\r\n\r\nvar CopyShader = {\r\n\r\n uniforms: {\r\n\r\n \"tDiffuse\": { value: null },\r\n \"opacity\": { value: 1.0 }\r\n\r\n },\r\n\r\n vertexShader: [\r\n\r\n \"varying vec2 vUv;\",\r\n\r\n \"void main() {\",\r\n\r\n \"\tvUv = uv;\",\r\n \"\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\",\r\n\r\n \"}\"\r\n\r\n ].join( \"\\n\" ),\r\n\r\n fragmentShader: [\r\n\r\n \"uniform float opacity;\",\r\n\r\n \"uniform sampler2D tDiffuse;\",\r\n\r\n \"varying vec2 vUv;\",\r\n\r\n \"void main() {\",\r\n\r\n \"\tvec4 texel = texture2D( tDiffuse, vUv );\",\r\n \"\tgl_FragColor = opacity * texel;\",\r\n\r\n \"}\"\r\n\r\n ].join( \"\\n\" )\r\n\r\n};\r\n\r\nexport { CopyShader };\r\n","import {\r\n OrthographicCamera,\r\n PlaneBufferGeometry,\r\n Mesh\r\n} from \"three\";\r\n\r\nfunction Pass() {\r\n\r\n // if set to true, the pass is processed by the composer\r\n this.enabled = true;\r\n\r\n // if set to true, the pass indicates to swap read and write buffer after rendering\r\n this.needsSwap = true;\r\n\r\n // if set to true, the pass clears its buffer before rendering\r\n this.clear = false;\r\n\r\n // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.\r\n this.renderToScreen = false;\r\n\r\n}\r\n\r\nObject.assign( Pass.prototype, {\r\n\r\n setSize: function ( /* width, height */ ) {},\r\n\r\n render: function ( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) {\r\n\r\n console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );\r\n\r\n }\r\n\r\n} );\r\n\r\n// Helper for passes that need to fill the viewport with a single quad.\r\n\r\n// Important: It's actually a hack to put FullScreenQuad into the Pass namespace. This is only\r\n// done to make examples/js code work. Normally, FullScreenQuad should be exported\r\n// from this module like Pass.\r\n\r\nPass.FullScreenQuad = ( function () {\r\n\r\n var camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\r\n var geometry = new PlaneBufferGeometry( 2, 2 );\r\n\r\n var FullScreenQuad = function ( material ) {\r\n\r\n this._mesh = new Mesh( geometry, material );\r\n\r\n };\r\n\r\n Object.defineProperty( FullScreenQuad.prototype, 'material', {\r\n\r\n get: function () {\r\n\r\n return this._mesh.material;\r\n\r\n },\r\n\r\n set: function ( value ) {\r\n\r\n this._mesh.material = value;\r\n\r\n }\r\n\r\n } );\r\n\r\n Object.assign( FullScreenQuad.prototype, {\r\n\r\n dispose: function () {\r\n\r\n this._mesh.geometry.dispose();\r\n\r\n },\r\n\r\n render: function ( renderer ) {\r\n\r\n renderer.render( this._mesh, camera );\r\n\r\n }\r\n\r\n } );\r\n\r\n return FullScreenQuad;\r\n\r\n} )();\r\n\r\nexport { Pass };\r\n","import {\r\n ShaderMaterial,\r\n UniformsUtils\r\n} from \"three\";\r\nimport { Pass } from './Pass';\r\n\r\nvar ShaderPass = function ( shader, textureID ) {\r\n\r\n Pass.call( this );\r\n\r\n this.textureID = ( textureID !== undefined ) ? textureID : \"tDiffuse\";\r\n\r\n if ( shader instanceof ShaderMaterial ) {\r\n\r\n this.uniforms = shader.uniforms;\r\n\r\n this.material = shader;\r\n\r\n } else if ( shader ) {\r\n\r\n this.uniforms = UniformsUtils.clone( shader.uniforms );\r\n\r\n this.material = new ShaderMaterial( {\r\n\r\n defines: Object.assign( {}, shader.defines ),\r\n uniforms: this.uniforms,\r\n vertexShader: shader.vertexShader,\r\n fragmentShader: shader.fragmentShader\r\n\r\n } );\r\n\r\n }\r\n\r\n this.fsQuad = new Pass.FullScreenQuad( this.material );\r\n\r\n};\r\n\r\nShaderPass.prototype = Object.assign( Object.create( Pass.prototype ), {\r\n\r\n constructor: ShaderPass,\r\n\r\n render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {\r\n\r\n if ( this.uniforms[ this.textureID ] ) {\r\n\r\n this.uniforms[ this.textureID ].value = readBuffer.texture;\r\n\r\n }\r\n\r\n this.fsQuad.material = this.material;\r\n\r\n if ( this.renderToScreen ) {\r\n\r\n renderer.setRenderTarget( null );\r\n this.fsQuad.render( renderer );\r\n\r\n } else {\r\n\r\n renderer.setRenderTarget( writeBuffer );\r\n // TODO: Avoid using autoClear properties, see https://github.com/mrdoob/three.js/pull/15571#issuecomment-465669600\r\n if ( this.clear ) renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );\r\n this.fsQuad.render( renderer );\r\n\r\n }\r\n\r\n }\r\n\r\n} );\r\n\r\nexport { ShaderPass };\r\n","import { Pass } from './Pass';\r\n\r\nvar MaskPass = function ( scene, camera ) {\r\n\r\n Pass.call( this );\r\n\r\n this.scene = scene;\r\n this.camera = camera;\r\n\r\n this.clear = true;\r\n this.needsSwap = false;\r\n\r\n this.inverse = false;\r\n\r\n};\r\n\r\nMaskPass.prototype = Object.assign( Object.create( Pass.prototype ), {\r\n\r\n constructor: MaskPass,\r\n\r\n render: function ( renderer, writeBuffer, readBuffer /*, deltaTime, maskActive */ ) {\r\n\r\n var context = renderer.getContext();\r\n var state = renderer.state;\r\n\r\n // don't update color or depth\r\n\r\n state.buffers.color.setMask( false );\r\n state.buffers.depth.setMask( false );\r\n\r\n // lock buffers\r\n\r\n state.buffers.color.setLocked( true );\r\n state.buffers.depth.setLocked( true );\r\n\r\n // set up stencil\r\n\r\n var writeValue, clearValue;\r\n\r\n if ( this.inverse ) {\r\n\r\n writeValue = 0;\r\n clearValue = 1;\r\n\r\n } else {\r\n\r\n writeValue = 1;\r\n clearValue = 0;\r\n\r\n }\r\n\r\n state.buffers.stencil.setTest( true );\r\n state.buffers.stencil.setOp( context.REPLACE, context.REPLACE, context.REPLACE );\r\n state.buffers.stencil.setFunc( context.ALWAYS, writeValue, 0xffffffff );\r\n state.buffers.stencil.setClear( clearValue );\r\n state.buffers.stencil.setLocked( true );\r\n\r\n // draw into the stencil buffer\r\n\r\n renderer.setRenderTarget( readBuffer );\r\n if ( this.clear ) renderer.clear();\r\n renderer.render( this.scene, this.camera );\r\n\r\n renderer.setRenderTarget( writeBuffer );\r\n if ( this.clear ) renderer.clear();\r\n renderer.render( this.scene, this.camera );\r\n\r\n // unlock color and depth buffer for subsequent rendering\r\n\r\n state.buffers.color.setLocked( false );\r\n state.buffers.depth.setLocked( false );\r\n\r\n // only render where stencil is set to 1\r\n\r\n state.buffers.stencil.setLocked( false );\r\n state.buffers.stencil.setFunc( context.EQUAL, 1, 0xffffffff ); // draw if == 1\r\n state.buffers.stencil.setOp( context.KEEP, context.KEEP, context.KEEP );\r\n state.buffers.stencil.setLocked( true );\r\n\r\n }\r\n\r\n} );\r\n\r\n\r\nvar ClearMaskPass = function () {\r\n\r\n Pass.call( this );\r\n\r\n this.needsSwap = false;\r\n\r\n};\r\n\r\nClearMaskPass.prototype = Object.create( Pass.prototype );\r\n\r\nObject.assign( ClearMaskPass.prototype, {\r\n\r\n render: function ( renderer /*, writeBuffer, readBuffer, deltaTime, maskActive */ ) {\r\n\r\n renderer.state.buffers.stencil.setLocked( false );\r\n renderer.state.buffers.stencil.setTest( false );\r\n\r\n }\r\n\r\n} );\r\n\r\nexport { MaskPass, ClearMaskPass };\r\n","import {\r\n Clock,\r\n LinearFilter,\r\n Mesh,\r\n OrthographicCamera,\r\n PlaneBufferGeometry,\r\n RGBAFormat,\r\n Vector2,\r\n WebGLRenderTarget\r\n} from \"three\";\r\nimport { CopyShader } from \"./shaders/CopyShader.js\";\r\nimport { ShaderPass } from \"../postprocessing/ShaderPass.js\";\r\nimport { MaskPass } from \"../postprocessing/MaskPass.js\";\r\nimport { ClearMaskPass } from \"../postprocessing/MaskPass.js\";\r\n\r\nvar EffectComposer = function ( renderer, renderTarget ) {\r\n\r\n this.renderer = renderer;\r\n\r\n if ( renderTarget === undefined ) {\r\n\r\n var parameters = {\r\n minFilter: LinearFilter,\r\n magFilter: LinearFilter,\r\n format: RGBAFormat\r\n };\r\n\r\n var size = renderer.getSize( new Vector2() );\r\n this._pixelRatio = renderer.getPixelRatio();\r\n this._width = size.width;\r\n this._height = size.height;\r\n\r\n renderTarget = new WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, parameters );\r\n renderTarget.texture.name = 'EffectComposer.rt1';\r\n\r\n } else {\r\n\r\n this._pixelRatio = 1;\r\n this._width = renderTarget.width;\r\n this._height = renderTarget.height;\r\n\r\n }\r\n\r\n this.renderTarget1 = renderTarget;\r\n this.renderTarget2 = renderTarget.clone();\r\n this.renderTarget2.texture.name = 'EffectComposer.rt2';\r\n\r\n this.writeBuffer = this.renderTarget1;\r\n this.readBuffer = this.renderTarget2;\r\n\r\n this.renderToScreen = true;\r\n\r\n this.passes = [];\r\n\r\n // dependencies\r\n\r\n if ( CopyShader === undefined ) {\r\n\r\n console.error( 'THREE.EffectComposer relies on CopyShader' );\r\n\r\n }\r\n\r\n if ( ShaderPass === undefined ) {\r\n\r\n console.error( 'THREE.EffectComposer relies on ShaderPass' );\r\n\r\n }\r\n\r\n this.copyPass = new ShaderPass( CopyShader );\r\n\r\n this.clock = new Clock();\r\n\r\n};\r\n\r\nObject.assign( EffectComposer.prototype, {\r\n\r\n swapBuffers: function () {\r\n\r\n var tmp = this.readBuffer;\r\n this.readBuffer = this.writeBuffer;\r\n this.writeBuffer = tmp;\r\n\r\n },\r\n\r\n addPass: function ( pass ) {\r\n\r\n this.passes.push( pass );\r\n pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );\r\n\r\n },\r\n\r\n insertPass: function ( pass, index ) {\r\n\r\n this.passes.splice( index, 0, pass );\r\n pass.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );\r\n\r\n },\r\n\r\n isLastEnabledPass: function ( passIndex ) {\r\n\r\n for ( var i = passIndex + 1; i < this.passes.length; i ++ ) {\r\n\r\n if ( this.passes[ i ].enabled ) {\r\n\r\n return false;\r\n\r\n }\r\n\r\n }\r\n\r\n return true;\r\n\r\n },\r\n\r\n render: function ( deltaTime ) {\r\n\r\n // deltaTime value is in seconds\r\n\r\n if ( deltaTime === undefined ) {\r\n\r\n deltaTime = this.clock.getDelta();\r\n\r\n }\r\n\r\n var currentRenderTarget = this.renderer.getRenderTarget();\r\n\r\n var maskActive = false;\r\n\r\n var pass, i, il = this.passes.length;\r\n\r\n for ( i = 0; i < il; i ++ ) {\r\n\r\n pass = this.passes[ i ];\r\n\r\n if ( pass.enabled === false ) continue;\r\n\r\n pass.renderToScreen = ( this.renderToScreen && this.isLastEnabledPass( i ) );\r\n pass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime, maskActive );\r\n\r\n if ( pass.needsSwap ) {\r\n\r\n if ( maskActive ) {\r\n\r\n var context = this.renderer.getContext();\r\n var stencil = this.renderer.state.buffers.stencil;\r\n\r\n //context.stencilFunc( context.NOTEQUAL, 1, 0xffffffff );\r\n stencil.setFunc( context.NOTEQUAL, 1, 0xffffffff );\r\n\r\n this.copyPass.render( this.renderer, this.writeBuffer, this.readBuffer, deltaTime );\r\n\r\n //context.stencilFunc( context.EQUAL, 1, 0xffffffff );\r\n stencil.setFunc( context.EQUAL, 1, 0xffffffff );\r\n\r\n }\r\n\r\n this.swapBuffers();\r\n\r\n }\r\n\r\n if ( MaskPass !== undefined ) {\r\n\r\n if ( pass instanceof MaskPass ) {\r\n\r\n maskActive = true;\r\n\r\n } else if ( pass instanceof ClearMaskPass ) {\r\n\r\n maskActive = false;\r\n\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n this.renderer.setRenderTarget( currentRenderTarget );\r\n\r\n },\r\n\r\n reset: function ( renderTarget ) {\r\n\r\n if ( renderTarget === undefined ) {\r\n\r\n var size = this.renderer.getSize( new Vector2() );\r\n this._pixelRatio = this.renderer.getPixelRatio();\r\n this._width = size.width;\r\n this._height = size.height;\r\n\r\n renderTarget = this.renderTarget1.clone();\r\n renderTarget.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );\r\n\r\n }\r\n\r\n this.renderTarget1.dispose();\r\n this.renderTarget2.dispose();\r\n this.renderTarget1 = renderTarget;\r\n this.renderTarget2 = renderTarget.clone();\r\n\r\n this.writeBuffer = this.renderTarget1;\r\n this.readBuffer = this.renderTarget2;\r\n\r\n },\r\n\r\n setSize: function ( width, height ) {\r\n\r\n this._width = width;\r\n this._height = height;\r\n\r\n var effectiveWidth = this._width * this._pixelRatio;\r\n var effectiveHeight = this._height * this._pixelRatio;\r\n\r\n this.renderTarget1.setSize( effectiveWidth, effectiveHeight );\r\n this.renderTarget2.setSize( effectiveWidth, effectiveHeight );\r\n\r\n for ( var i = 0; i < this.passes.length; i ++ ) {\r\n\r\n this.passes[ i ].setSize( effectiveWidth, effectiveHeight );\r\n\r\n }\r\n\r\n },\r\n\r\n setPixelRatio: function ( pixelRatio ) {\r\n\r\n this._pixelRatio = pixelRatio;\r\n\r\n this.setSize( this._width, this._height );\r\n\r\n }\r\n\r\n} );\r\n\r\n\r\nvar Pass = function () {\r\n\r\n // if set to true, the pass is processed by the composer\r\n this.enabled = true;\r\n\r\n // if set to true, the pass indicates to swap read and write buffer after rendering\r\n this.needsSwap = true;\r\n\r\n // if set to true, the pass clears its buffer before rendering\r\n this.clear = false;\r\n\r\n // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.\r\n this.renderToScreen = false;\r\n\r\n};\r\n\r\nObject.assign( Pass.prototype, {\r\n\r\n setSize: function ( /* width, height */ ) {},\r\n\r\n render: function ( /* renderer, writeBuffer, readBuffer, deltaTime, maskActive */ ) {\r\n\r\n console.error( 'THREE.Pass: .render() must be implemented in derived pass.' );\r\n\r\n }\r\n\r\n} );\r\n\r\n// Helper for passes that need to fill the viewport with a single quad.\r\nPass.FullScreenQuad = ( function () {\r\n\r\n var camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );\r\n var geometry = new PlaneBufferGeometry( 2, 2 );\r\n\r\n var FullScreenQuad = function ( material ) {\r\n\r\n this._mesh = new Mesh( geometry, material );\r\n\r\n };\r\n\r\n Object.defineProperty( FullScreenQuad.prototype, 'material', {\r\n\r\n get: function () {\r\n\r\n return this._mesh.material;\r\n\r\n },\r\n\r\n set: function ( value ) {\r\n\r\n this._mesh.material = value;\r\n\r\n }\r\n\r\n } );\r\n\r\n Object.assign( FullScreenQuad.prototype, {\r\n\r\n dispose: function () {\r\n\r\n this._mesh.geometry.dispose();\r\n\r\n },\r\n\r\n render: function ( renderer ) {\r\n\r\n renderer.render( this._mesh, camera );\r\n\r\n }\r\n\r\n } );\r\n\r\n return FullScreenQuad;\r\n\r\n} )();\r\n\r\nexport { EffectComposer, Pass };\r\n","import {\r\n AdditiveBlending,\r\n LinearFilter,\r\n RGBAFormat,\r\n ShaderMaterial,\r\n UniformsUtils,\r\n WebGLRenderTarget\r\n} from \"three\";\r\nimport { Pass } from \"../postprocessing/Pass.js\";\r\nimport { CopyShader } from \"./shaders/CopyShader.js\";\r\n\r\n/**\r\n*\r\n* Supersample Anti-Aliasing Render Pass\r\n*\r\n* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results.\r\n*\r\n* References: https://en.wikipedia.org/wiki/Supersampling\r\n*\r\n*/\r\n\r\nvar SSAARenderPass = function ( scene, camera, clearColor, clearAlpha ) {\r\n\r\n Pass.call( this );\r\n\r\n this.scene = scene;\r\n this.camera = camera;\r\n\r\n this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16.\r\n this.unbiased = true;\r\n\r\n // as we need to clear the buffer in this pass, clearColor must be set to something, defaults to black.\r\n this.clearColor = ( clearColor !== undefined ) ? clearColor : 0x000000;\r\n this.clearAlpha = ( clearAlpha !== undefined ) ? clearAlpha : 0;\r\n\r\n if ( CopyShader === undefined ) console.error( \"SSAARenderPass relies on CopyShader\" );\r\n\r\n var copyShader = CopyShader;\r\n this.copyUniforms = UniformsUtils.clone( copyShader.uniforms );\r\n\r\n this.copyMaterial = new ShaderMaterial(\t{\r\n uniforms: this.copyUniforms,\r\n vertexShader: copyShader.vertexShader,\r\n fragmentShader: copyShader.fragmentShader,\r\n premultipliedAlpha: true,\r\n transparent: true,\r\n blending: AdditiveBlending,\r\n depthTest: false,\r\n depthWrite: false\r\n } );\r\n\r\n this.fsQuad = new Pass.FullScreenQuad( this.copyMaterial );\r\n\r\n};\r\n\r\nSSAARenderPass.prototype = Object.assign( Object.create( Pass.prototype ), {\r\n\r\n constructor: SSAARenderPass,\r\n\r\n dispose: function () {\r\n\r\n if ( this.sampleRenderTarget ) {\r\n\r\n this.sampleRenderTarget.dispose();\r\n this.sampleRenderTarget = null;\r\n\r\n }\r\n\r\n },\r\n\r\n setSize: function ( width, height ) {\r\n\r\n if ( this.sampleRenderTarget )\tthis.sampleRenderTarget.setSize( width, height );\r\n\r\n },\r\n\r\n render: function ( renderer, writeBuffer, readBuffer ) {\r\n\r\n if ( ! this.sampleRenderTarget ) {\r\n\r\n this.sampleRenderTarget = new WebGLRenderTarget( readBuffer.width, readBuffer.height, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat } );\r\n this.sampleRenderTarget.texture.name = \"SSAARenderPass.sample\";\r\n\r\n }\r\n\r\n var jitterOffsets = SSAARenderPass.JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ];\r\n\r\n var autoClear = renderer.autoClear;\r\n renderer.autoClear = false;\r\n\r\n var oldClearColor = renderer.getClearColor().getHex();\r\n var oldClearAlpha = renderer.getClearAlpha();\r\n\r\n var baseSampleWeight = 1.0 / jitterOffsets.length;\r\n var roundingRange = 1 / 32;\r\n this.copyUniforms[ \"tDiffuse\" ].value = this.sampleRenderTarget.texture;\r\n\r\n var width = readBuffer.width, height = readBuffer.height;\r\n\r\n // render the scene multiple times, each slightly jitter offset from the last and accumulate the results.\r\n for ( var i = 0; i < jitterOffsets.length; i ++ ) {\r\n\r\n var jitterOffset = jitterOffsets[ i ];\r\n\r\n if ( this.camera.setViewOffset ) {\r\n\r\n this.camera.setViewOffset( width, height,\r\n jitterOffset[ 0 ] * 0.0625, jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16\r\n width, height );\r\n\r\n }\r\n\r\n var sampleWeight = baseSampleWeight;\r\n\r\n if ( this.unbiased ) {\r\n\r\n // the theory is that equal weights for each sample lead to an accumulation of rounding errors.\r\n // The following equation varies the sampleWeight per sample so that it is uniformly distributed\r\n // across a range of values whose rounding errors cancel each other out.\r\n\r\n var uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length );\r\n sampleWeight += roundingRange * uniformCenteredDistribution;\r\n\r\n }\r\n\r\n this.copyUniforms[ \"opacity\" ].value = sampleWeight;\r\n renderer.setClearColor( this.clearColor, this.clearAlpha );\r\n renderer.setRenderTarget( this.sampleRenderTarget );\r\n renderer.clear();\r\n renderer.render( this.scene, this.camera );\r\n\r\n renderer.setRenderTarget( this.renderToScreen ? null : writeBuffer );\r\n\r\n if ( i === 0 ) {\r\n\r\n renderer.setClearColor( 0x000000, 0.0 );\r\n renderer.clear();\r\n\r\n }\r\n\r\n this.fsQuad.render( renderer );\r\n\r\n }\r\n\r\n if ( this.camera.clearViewOffset ) this.camera.clearViewOffset();\r\n\r\n renderer.autoClear = autoClear;\r\n renderer.setClearColor( oldClearColor, oldClearAlpha );\r\n\r\n }\r\n\r\n} );\r\n\r\n\r\n// These jitter vectors are specified in integers because it is easier.\r\n// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5)\r\n// before being used, thus these integers need to be scaled by 1/16.\r\n//\r\n// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396\r\nSSAARenderPass.JitterVectors = [\r\n [\r\n [ 0, 0 ]\r\n ],\r\n [\r\n [ 4, 4 ], [ - 4, - 4 ]\r\n ],\r\n [\r\n [ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ]\r\n ],\r\n [\r\n [ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ],\r\n [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ]\r\n ],\r\n [\r\n [ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ],\r\n [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ],\r\n [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ],\r\n [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ]\r\n ],\r\n [\r\n [ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ],\r\n [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ],\r\n [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ],\r\n [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ],\r\n [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ],\r\n [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ],\r\n [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ],\r\n [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ]\r\n ]\r\n];\r\n\r\nexport { SSAARenderPass };\r\n","import { Viewer } 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 \"../../../postprocessing/EffectComposer\";\r\nimport { ShaderPass } from \"../../../postprocessing/ShaderPass\";\r\nimport { CopyShader } from \"../../../postprocessing/shaders/CopyShader\";\r\nimport { SSAARenderPass } from \"../../../postprocessing/SSAARenderPass\";\r\n\r\nclass TextMaterial extends MeshPhongMaterial {\r\n public textures;\r\n public text;\r\n\r\n constructor(opts, textures, text) {\r\n super(opts);\r\n\r\n this.textures = textures;\r\n this.text = text;\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 setViewerTooltipText;\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) {\r\n const {setViewerTooltipText} = props;\r\n\r\n this.viewer = viewer;\r\n this.setViewerTooltipText = setViewerTooltipText;\r\n\r\n this.initScene();\r\n this.initAntiAliasing();\r\n this.setCanvasStyle();\r\n this.addObjects();\r\n this.addLights();\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 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\", {rotation: 270}),\r\n this.getTextMaterial(\"LEFT\", {rotation: 90}),\r\n this.getTextMaterial(\"BACK\", {rotation: 180}),\r\n this.getTextMaterial(\"FRONT\"),\r\n this.getTextMaterial(\"TOP\"),\r\n this.getTextMaterial(\"BOTTOM\", {rotation: 180, scale: 0.85}),\r\n ];\r\n\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.east = this.getDirectionMesh(\"E\");\r\n this.pivot.add(this.east);\r\n\r\n this.west = this.getDirectionMesh(\"W\");\r\n this.pivot.add(this.west);\r\n\r\n this.north = this.getDirectionMesh(\"N\");\r\n this.pivot.add(this.north);\r\n\r\n this.south = this.getDirectionMesh(\"S\");\r\n this.pivot.add(this.south);\r\n }\r\n\r\n getTextMaterial(text, opts = {}): TextMaterial {\r\n let defaults = {\r\n rotation: 0,\r\n scale: 1.0\r\n };\r\n\r\n let options = {...defaults, ...opts};\r\n\r\n let canvasSize = 1024;\r\n let fontSize = 200;\r\n let border = 32;\r\n let outlineSize = 5;\r\n\r\n // Might require font scaling\r\n fontSize = fontSize * options.scale;\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(options.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);\r\n\r\n return material;\r\n }\r\n\r\n getLetterMaterial(letter): 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(letter, x, y);\r\n\r\n // Black outline\r\n context.lineWidth = outlineSize;\r\n context.strokeStyle = \"#000000\";\r\n context.strokeText(letter, 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(letter): 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 (letter === \"E\") {\r\n pivot.position.x = this.cubeSize;\r\n } else if (letter === \"W\") {\r\n pivot.position.x = -1 * this.cubeSize;\r\n } else if (letter === \"N\") {\r\n pivot.position.y = this.cubeSize;\r\n } else if (letter === \"S\") {\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(letter);\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(letter);\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 onMouseMove(event) {\r\n let {hovering} = this.checkMouseHover(event);\r\n\r\n return hovering;\r\n }\r\n\r\n mouseClick(event): boolean {\r\n let controls = this.viewer.controls;\r\n let {hovering, side} = this.checkMouseHover(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 checkMouseHover(event) {\r\n let side = this.getSelectedSide(event);\r\n let 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.text;\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 setCanvasStyle() {\r\n this.domElement.style[\"pointer-events\"] = \"none\";\r\n this.domElement.style.position = \"absolute\";\r\n this.domElement.style.top = \"0px\";\r\n this.domElement.style.right = \"0px\";\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 this.setViewerTooltipText(\"\");\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 {Viewer} from '../main';\r\nimport {RayCaster} from \"../controls\";\r\nimport MeasurementController from './measurement-controller';\r\nimport {\r\n BufferGeometry,\r\n LineBasicMaterial,\r\n Line,\r\n SphereGeometry,\r\n MeshBasicMaterial,\r\n Mesh,\r\n Line3,\r\n Vector3,\r\n Plane\r\n} from 'three';\r\n\r\nexport const imageOnlyDistance = 20;\r\n\r\nexport class MultipleCameraMeasurement {\r\n private viewer: Viewer;\r\n private controller: MeasurementController;\r\n private coordinates = [];\r\n private maxSeperation = 1.0;\r\n private maxDistance = 100.0;\r\n private sceneItems = [];\r\n\r\n constructor(controller, viewer) {\r\n this.viewer = viewer;\r\n this.controller = controller;\r\n }\r\n\r\n getEndpoint(origin, direction) {\r\n return direction.clone().setLength(100.0).add(origin);\r\n }\r\n\r\n drawLine(start, end, color) {\r\n let geometry = new BufferGeometry().setFromPoints([start, end]);\r\n let material = new LineBasicMaterial({color: color});\r\n let line = new Line(geometry, material);\r\n this.controller.scene.add(line);\r\n this.sceneItems.push(line);\r\n }\r\n\r\n drawSphere(position) {\r\n let geometry = new SphereGeometry( 0.05, 32, 32 );\r\n let material = new MeshBasicMaterial( {color: 0xffff00} );\r\n let sphere = new Mesh( geometry, material );\r\n sphere.position.copy(position);\r\n this.controller.scene.add(sphere);\r\n this.sceneItems.push(sphere);\r\n }\r\n\r\n mouseClick(event) {\r\n if (this.coordinates.length === 2) {\r\n this.sceneItems.forEach(item => {\r\n this.controller.scene.remove(item);\r\n });\r\n this.coordinates = [];\r\n }\r\n\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let direction = raycaster.vectorFromEvent(event);\r\n let origin = this.viewer.camera.position.clone();\r\n\r\n // Clicked line\r\n let endPoint = this.getEndpoint(origin, direction);\r\n this.drawLine(origin, endPoint, 0xffff00);\r\n\r\n this.coordinates.push({\r\n \"origin\": origin,\r\n \"direction\": direction\r\n });\r\n\r\n console.log(`Image-only measure click #${this.coordinates.length}`);\r\n\r\n if (this.coordinates.length === 2) {\r\n this.finish();\r\n }\r\n }\r\n\r\n finish() {\r\n let rayA = this.coordinates[0];\r\n let rayB = this.coordinates[1];\r\n let result = this.getIntersection(rayA, rayB);\r\n console.log(result);\r\n }\r\n\r\n /** Get closest possible midpoint for two line segments */\r\n getIntersection(rayA, rayB) {\r\n let p1 = rayA.origin;\r\n let d1 = rayA.direction;\r\n let p2 = rayB.origin;\r\n let d2 = rayB.direction;\r\n\r\n let n = d1.clone().cross(d2);\r\n let n1 = d1.clone().cross(n);\r\n let n2 = d2.clone().cross(n);\r\n\r\n let t1 = p2.clone().sub(p1).dot(n2);\r\n let b1 = d1.clone().dot(n2);\r\n let v1 = d1.clone().multiplyScalar(b1 !== 0 ? t1 / b1 : 0);\r\n let c1 = p1.clone().add(v1);\r\n\r\n let t2 = p1.clone().sub(p2).dot(n1);\r\n let b2 = d2.clone().dot(n1);\r\n let v2 = d2.clone().multiplyScalar(b2 !== 0 ? t2 / b2 : 0);\r\n let c2 = p2.clone().add(v2);\r\n\r\n // Make sure our result is in front of us\r\n let d1n = c1.clone().sub(p1).setLength(1.0);\r\n let d2n = c2.clone().sub(p2).setLength(1.0);\r\n let inFront = (d1.angleTo(d1n) === 0) && (d2.angleTo(d2n) === 0);\r\n\r\n // Make sure both lines are a valid length\r\n let distances = [c1.distanceTo(p1), c2.distanceTo(p2)];\r\n let maxDistance = Math.max(...distances);\r\n let minDistance = Math.min(...distances);\r\n let validDistance = (maxDistance < this.maxDistance)\r\n && (minDistance > 0);\r\n\r\n // Get our midpoint and segment length\r\n let lineSegment = new Line3(c1, c2);\r\n let segmentLength = lineSegment.distance();\r\n let midPoint = new Vector3();\r\n lineSegment.getCenter(midPoint);\r\n let validSeperation = segmentLength < this.maxSeperation;\r\n\r\n console.log(`Intersection in front: ${inFront}`);\r\n console.log(`Segment Distance: [${c1.distanceTo(p1)}, ${c2.distanceTo(p2)}]`);\r\n console.log(`Segment Distance Valid: ${validDistance}`);\r\n console.log(`Seperation Distance: ${segmentLength}`);\r\n console.log(`Seperation Distance Valid: ${validSeperation}`);\r\n\r\n // Midpoint sphere\r\n this.drawSphere(midPoint);\r\n\r\n // Segment line\r\n this.drawLine(c1, c2, 0xff00ff);\r\n\r\n // All conditions must be valid\r\n let valid = inFront && validDistance && validSeperation;\r\n\r\n return {\r\n \"point\": midPoint,\r\n \"valid\": valid\r\n };\r\n }\r\n}\r\n\r\nexport class GroundPlaneMeasurement {\r\n private viewer: Viewer;\r\n public maxDistance2D = imageOnlyDistance;\r\n\r\n constructor(viewer) {\r\n this.viewer = viewer;\r\n }\r\n\r\n getPosition(event) {\r\n let cameras = this.viewer.cameraList;\r\n\r\n let raycaster = new RayCaster(this.viewer, event);\r\n let direction = raycaster.vectorFromEvent(event);\r\n direction.setLength(this.maxDistance2D);\r\n\r\n let normal = new Vector3(0, 0, 1);\r\n let point = cameras.current.position.viewer;\r\n\r\n let lineStart = point.clone();\r\n let lineEnd = point.clone().add(direction);\r\n let line = new Line3(lineStart, lineEnd);\r\n\r\n point.z = point.z - cameras.current.height;\r\n let plane = new Plane().setFromNormalAndCoplanarPoint(\r\n normal, point);\r\n\r\n let intersect = new Vector3();\r\n let intersected = plane.intersectLine(line, intersect);\r\n if (!intersected) {\r\n return null;\r\n }\r\n\r\n return intersect;\r\n }\r\n}","import {\r\n Button,\r\n Card,\r\n CardContent,\r\n CardHeader,\r\n createStyles,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n FormControlLabel,\r\n IconButton,\r\n InputLabel,\r\n List,\r\n makeStyles,\r\n Menu,\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 TableRow,\r\n Theme,\r\n Typography,\r\n useTheme\r\n} from '@material-ui/core';\r\nimport clsx from 'clsx';\r\nimport React, {useEffect, useState} from 'react';\r\nimport RotateRightIcon from '@material-ui/icons/RotateRight';\r\nimport {AerialAreaMeasurement, AerialMeasurement,\r\n Measurement3D, MeasurementArea, MeasurementPoint,\r\n MeasurementVolume} from '../viewer/js/measurements/measurement';\r\nimport DeleteIcon from '@material-ui/icons/Delete';\r\nimport InfoIcon from '@material-ui/icons/Info';\r\nimport EditIcon from '@material-ui/icons/Edit';\r\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\r\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess';\r\nimport 'font-awesome/css/font-awesome.css';\r\nimport { nanoid } from '@reduxjs/toolkit';\r\nimport { AlertDialog, PromptDialog, TextDialog } from '../dialogs';\r\nimport { imageOnlyDistance } from '../viewer/js/measurements/image-only';\r\nimport unitConverter from '../viewer/js/utilities/unit-converter';\r\nimport { dialog, fs, isStaticSite } from \"../electron-modules\";\r\nimport { useSnackbar } from 'notistack';\r\nimport slash from 'slash';\r\nimport fileDialog from 'file-dialog';\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport { selectMeasureUnits, changeMeasureUnits } from '../redux/projections-slice';\r\nimport LocalScene from '../viewer/js/projections';\r\nimport { ArrowTooltip } from '../tooltips';\r\nimport { DenseDivider, IconToolBar, SlimScrollbar, ToolBarButton, ToolBarDivider } from '../toolbar';\r\nimport { Viewer } from '../viewer/js/main';\r\n\r\nconst copyTextToClipboard = require('copy-to-clipboard');\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n vertexWrapped: {\r\n float: \"right\"\r\n },\r\n textField: {\r\n marginBottom: theme.spacing(3)\r\n },\r\n userWarning: {\r\n padding: theme.spacing(2)\r\n },\r\n cardButtons: {\r\n marginTop: 0,\r\n alignSelf: \"center\"\r\n },\r\n card: {\r\n margin: theme.spacing(1.5),\r\n userSelect: \"none\"\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: \"center\"\r\n },\r\n measurementUnitsFlex: {\r\n flex: 1,\r\n justifyContent: \"center\"\r\n },\r\n measurementUnitsRadio: {\r\n paddingTop: theme.spacing(0.5),\r\n paddingBottom: theme.spacing(0.5)\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 tableContent: {\r\n backgroundColor: \"white\",\r\n padding: \"0px !important\",\r\n },\r\n cardHeader: {\r\n padding: \"10px\"\r\n },\r\n cell: {\r\n fontSize: \"0.75em\",\r\n padding: \"6px 10px\"\r\n },\r\n headerTitle: {\r\n fontWeight: \"bold\",\r\n cursor: \"pointer\"\r\n },\r\n calculateButton: {\r\n padding: \"2px 4px\",\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: \"5px !important\"\r\n },\r\n copyClipboard: {\r\n cursor: \"pointer\"\r\n },\r\n measureList: {\r\n padding: \"0px\",\r\n overflow: \"auto\",\r\n flex: 1\r\n },\r\n lastTableRow: {\r\n borderBottom: \"0px\"\r\n },\r\n })\r\n);\r\n\r\nconst ExportDialog = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {open, classes, onClose} = props;\r\n const [exportType, setExportType] = useState(\"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 Measurements Export\r\n \r\n\r\n \r\n {/* Export type */}\r\n Export Type\r\n {\r\n setExportType(event.target.value as string);\r\n }}\r\n >\r\n CSV File\r\n Measure Data\r\n \r\n\r\n {exportType === \"csv\" && (\r\n \r\n {/* Ordering */}\r\n Ordering\r\n {\r\n setOrdering(event.target.value as string);\r\n }}\r\n >\r\n Easting, Northing, Elevation\r\n Northing, Easting, Elevation\r\n \r\n \r\n )}\r\n\r\n {exportType !== \"csv\" && (\r\n The file generated using \"Measure Data\" options can be\r\n re-imported as a new measurement group in any project\r\n )}\r\n \r\n\r\n \r\n \r\n \r\n Export\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst MeasureTypeIcon = (props) => {\r\n const {type, icon, measureType, setMeasureType} = props;\r\n\r\n // Remove hyphen and capitalize each word\r\n const title = type\r\n .replace(\"-\", \" \")\r\n .replace(/(^\\w|\\s\\w)/g, m => m.toUpperCase());\r\n\r\n const onClick = () => {\r\n setMeasureType(type);\r\n };\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nconst ImportExportIcon = (props) => {\r\n const {icon, onClick} = props;\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nconst MeasurementCard = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {measurement, classes, first} = props;\r\n\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n const [expanded, setExpanded] = useState(false);\r\n const [hover, setHover] = useState(false);\r\n const [renameOpen, setRenameOpen] = useState(false);\r\n const [deleteOpen, setDeleteOpen] = useState(false);\r\n\r\n const formatter = measurement.formatter;\r\n\r\n const onMouseOver = () => {\r\n setHover(true);\r\n };\r\n\r\n const onMouseLeave = () => {\r\n setHover(false);\r\n };\r\n\r\n const generateVertexPositions = () => {\r\n let rows = [];\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 verticesReprojected.forEach((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\r\n let type = verticesReprojected.length > 1 ?\r\n `Vertex ${index + 1}` : \"Position\";\r\n\r\n rows.push({\r\n type: type,\r\n value: (\r\n {\r\n event.stopPropagation();\r\n let x = vertex.x.toFixed(precision.x);\r\n let y = vertex.y.toFixed(precision.y);\r\n let z = vertex.z.toFixed(precision.z);\r\n let text = `(${x}, ${y}, ${z})`;\r\n copyTextToClipboard(text);\r\n showMessage(\"Copied to clipboard\", {\r\n variant: \"success\"\r\n });\r\n }}\r\n >\r\n \r\n
\r\n X: {x}
\r\n Y: {y}
\r\n Z: {z}
\r\n
\r\n
\r\n \r\n )\r\n });\r\n });\r\n\r\n return rows;\r\n };\r\n\r\n const getVolumeResults = () => {\r\n let volumeValue = measurement.invalidVolumeMessage;\r\n\r\n if (measurement.valid) {\r\n if (measurement.calculating) {\r\n volumeValue = (\r\n \r\n Calculating...\r\n \r\n );\r\n } else if (measurement.calculated) {\r\n const value = formatter.formatVolume(measurement);\r\n volumeValue = (\r\n
\r\n
\r\n \r\n {\r\n event.stopPropagation();\r\n measurement.recalculate();\r\n }}\r\n >\r\n \r\n \r\n \r\n
\r\n );\r\n } else {\r\n volumeValue = (\r\n \r\n {\r\n event.stopPropagation();\r\n measurement.calculate();\r\n }}\r\n >\r\n Calculate\r\n \r\n \r\n );\r\n }\r\n }\r\n\r\n return volumeValue;\r\n };\r\n\r\n const generateMeasurementRows = () => {\r\n let rows = [];\r\n\r\n if (measurement instanceof MeasurementArea) {\r\n let areaValue = measurement.valid ?\r\n formatter.formatArea(measurement.area3D) :\r\n measurement.areaInvalidMessage;\r\n rows.push({type: \"Area\", value: areaValue});\r\n\r\n if (measurement instanceof MeasurementVolume) {\r\n let volumeValue = getVolumeResults();\r\n rows.push({type: \"Volume\", value: volumeValue});\r\n }\r\n } else if (measurement instanceof MeasurementPoint) {\r\n // Do nothing for points\r\n } else if (measurement instanceof Measurement3D) {\r\n rows.push({type: \"Distance (2D)\", value: formatter.formatLength(measurement.distance2D)});\r\n rows.push({type: \"Distance (3D)\", value: formatter.formatLength(measurement.distance3D)});\r\n rows.push({type: \"Grade\", value: formatter.formatGrade(measurement.grade)});\r\n rows.push({type: \"Angle\", value: formatter.formatAngle(measurement.angle)});\r\n } else if (measurement instanceof AerialMeasurement) {\r\n if (measurement instanceof AerialAreaMeasurement) {\r\n rows.push({\r\n type: measurement.displayType,\r\n value: formatter.formatArea(measurement.getValue())\r\n });\r\n } else {\r\n rows.push({\r\n type: measurement.displayType,\r\n value: formatter.formatLength(measurement.getValue())\r\n });\r\n }\r\n }\r\n\r\n if (measurement instanceof Measurement3D) {\r\n rows.push(...generateVertexPositions());\r\n }\r\n\r\n return rows;\r\n };\r\n\r\n const createMarkup = (content) => {\r\n if (typeof(content) === \"string\") {\r\n return content ?\r\n (
) :\r\n \"\";\r\n }\r\n\r\n return content;\r\n };\r\n\r\n const handleRenameSubmit = name => {\r\n setRenameOpen(false);\r\n viewer?.renameMeasurement(measurement, name);\r\n };\r\n\r\n const handleDeleteSubmit = () => {\r\n setDeleteOpen(false);\r\n viewer?.deleteMeasurement(measurement);\r\n };\r\n\r\n useEffect(() => {\r\n viewer?.updateMeasureHover(measurement, hover);\r\n }, [viewer, hover]);\r\n\r\n useEffect(() => {\r\n setExpanded(first);\r\n }, [first]);\r\n\r\n let rows = generateMeasurementRows();\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 setRenameOpen(true);\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 setDeleteOpen(true);\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={`Total Vertices: ${measurement.numVertices}`}\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 {/* Measurement values table */}\r\n \r\n \r\n \r\n {rows.map((row, index) => {\r\n const isLastRow = index === (rows.length - 1);\r\n\r\n return (\r\n \r\n \r\n {row.type}\r\n \r\n\r\n \r\n {createMarkup(row.value)}\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 {/* Delete Dialog */}\r\n {\r\n setDeleteOpen(false);\r\n }}\r\n title=\"Delete entry?\"\r\n prompt=\"Do you want to delete this measurement?\"\r\n button=\"Delete\"\r\n />\r\n\r\n {/* Rename Dialog */}\r\n {\r\n setRenameOpen(false);\r\n }}\r\n title=\"Rename Measurement\"\r\n prompt=\"Enter new name\"\r\n default={measurement.title}\r\n label=\"Measurement Name\"\r\n />\r\n \r\n );\r\n};\r\n\r\nexport const Measurements = (props) => {\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const dispatch = useDispatch();\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const viewer = props.viewer as Viewer;\r\n const {active, measurements} = props;\r\n\r\n const measurementUnits = useSelector(selectMeasureUnits);\r\n const [exportModalOpen, setExportModalOpen] = useState(false);\r\n const [measureType, setMeasureType] = useState(\"standard\");\r\n const [measureUnits, setMeasureUnits] = useState('m');\r\n const [contextState, setContextState] = useState({\r\n mouseX: null,\r\n mouseY: null,\r\n });\r\n\r\n const loadImportData = (text) => {\r\n let encoded = decodeURIComponent(text);\r\n let data = JSON.parse(encoded);\r\n let response = viewer.loadMeasurementData(data);\r\n\r\n if (response.success) {\r\n showMessage(response.message, {\r\n variant: \"success\"\r\n });\r\n } else {\r\n showMessage(response.message, {\r\n variant: \"error\"\r\n });\r\n }\r\n };\r\n\r\n const openImportElectron = () => {\r\n const fileFilter = viewer?.getMeasureExportType();\r\n\r\n dialog.showOpenDialog( {\r\n filters: fileFilter,\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('Error loading measurement data', 'An error occurred while loading the measurement file.');\r\n }\r\n\r\n loadImportData(text);\r\n });\r\n }\r\n }).catch(() => {\r\n dialog.showErrorBox('Error', 'An error occurred while loading the specified file.');\r\n });\r\n };\r\n\r\n const openImportBrowser = () => {\r\n const fileFilter = viewer?.getMeasureExportType();\r\n const fileType = fileFilter[0].extensions[0];\r\n\r\n fileDialog({accept: `.${fileType}`})\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 openExportMenu = (event) => {\r\n setContextState({\r\n mouseX: event.clientX - 2,\r\n mouseY: event.clientY - 4,\r\n });\r\n };\r\n\r\n const closeExportMenu = () => {\r\n setContextState({\r\n mouseX: null,\r\n mouseY: null,\r\n });\r\n };\r\n\r\n const onExport = () => {\r\n closeExportMenu();\r\n setExportModalOpen(true);\r\n };\r\n\r\n const onImport = () => {\r\n closeExportMenu();\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 useEffect(() => {\r\n viewer?.toggleMeasurements(active);\r\n viewer?.updateMeasureType(measureType);\r\n }, [viewer, active]);\r\n\r\n useEffect(() => {\r\n viewer?.updateMeasureType(measureType);\r\n }, [viewer, measureType]);\r\n\r\n useEffect(() => {\r\n setMeasureUnits(measurementUnits);\r\n viewer?.setMeasurementUnits(measurementUnits);\r\n }, [viewer, measurementUnits]);\r\n\r\n const reversed = [...measurements].reverse();\r\n const iconProps = {classes, measureType, setMeasureType};\r\n const menuOpen = contextState.mouseY !== null;\r\n const [imageOnlyWarningOpen, setImageOnlyWarningOpen] = useState(false);\r\n const anchorPosition = contextState.mouseY !== null && contextState.mouseX !== null\r\n ? { top: contextState.mouseY, left: contextState.mouseX }\r\n : undefined;\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 imageDistanceText = unitConverter.convert(imageOnlyDistance,\r\n 'm', measurementUnits).toFixed(2);\r\n\r\n return (\r\n \r\n {/* Measurement icons */}\r\n \r\n \r\n \r\n {(isImageOnly === false) && ()}\r\n {(isImageOnly === false) && ()}\r\n \r\n {(isImageOnly === false) && ()}\r\n \r\n \r\n \r\n\r\n \r\n\r\n {/* Measurement list */}\r\n \r\n \r\n {measurements.length === 0 && (\r\n No measurements have been added.\r\n )}\r\n\r\n {reversed.map((measurement, index) => {\r\n return (\r\n \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={Metric}\r\n />\r\n\r\n }\r\n label={Imperial}\r\n />\r\n \r\n
\r\n\r\n {/* Image only warning */}\r\n {isImageOnly && (
\r\n Image-only measurements enabled\r\n {\r\n setImageOnlyWarningOpen(true);\r\n }}\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 Export Measurements\r\n \r\n \r\n Import Measurements\r\n \r\n \r\n\r\n {/* Export Measurements */}\r\n {\r\n setExportModalOpen(false);\r\n }}\r\n />\r\n\r\n {/* Image only warning */}\r\n {\r\n setImageOnlyWarningOpen(false);\r\n }}\r\n >\r\n \r\n Image-only measurements are calculated by intersecting a flat plane at the approximate\r\n ground height, based on the provided \"sensor height\" project configuration value.\r\n \r\n
\r\n \r\n Due to the lowered accuracy further away from the camera position, the measurements\r\n clicks are restricted to {imageDistanceText}{measurementUnits} from the current\r\n camera position`\r\n \r\n \r\n
\r\n );\r\n};\r\n","import IconButton from \"@material-ui/core/IconButton\";\r\nimport ChevronLeftIcon from \"@material-ui/icons/ChevronLeft\";\r\nimport ChevronRightIcon from \"@material-ui/icons/ChevronRight\";\r\nimport {FolderList} from \"./folder/folder-list\";\r\nimport Drawer from \"@material-ui/core/Drawer\";\r\nimport React, { useState } from \"react\";\r\nimport {createStyles, makeStyles, Theme, useTheme} from \"@material-ui/core/styles\";\r\nimport { AppBar, Box, Tab } from \"@material-ui/core\";\r\nimport { PanelProps, TabPanel, TabProps } from \"./tabs\";\r\nimport Tabs from \"@material-ui/core/Tabs/Tabs\";\r\nimport { Measurements } from \"./measurements/measurements\";\r\nimport { PromptDialog } from \"./dialogs\";\r\nimport { Viewer } from \"./viewer/js/main\";\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 \"min-width\": \"0px !important\"\r\n },\r\n box: {\r\n padding: \"10px 0px 0px 0px !important\",\r\n height: \"calc(100% - 10px)\",\r\n overflow: \"auto\",\r\n display: \"flex\",\r\n flexDirection: \"column\"\r\n },\r\n tabGrow: {\r\n \"flex-grow\": 1\r\n },\r\n panel: {\r\n flex: 1,\r\n overflow: \"hidden\"\r\n }\r\n }),\r\n);\r\n\r\nexport const AssetDrawer = (props) => {\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n\r\n const viewer = props.viewer as Viewer;\r\n const {assetDrawerState, measurements, activeTab, setTabValue,\r\n tabsEnabled, setDefaultTab, setAssetDrawerState} = props;\r\n\r\n const [activeMeasurePrompt, setActiveMeasurePrompt] = useState(false);\r\n const [newTabValue, setNewTabValue] = useState(null);\r\n const [closeDrawer, setCloseDrawer] = useState(false);\r\n\r\n const measurementsOpen = activeTab === 1;\r\n const hasMeasurements = measurements.length > 0;\r\n\r\n const setActiveTab = (event, value) => {\r\n // Tab navigation disabled\r\n if (tabsEnabled === false) {\r\n return;\r\n }\r\n\r\n if (measurementsOpen && hasMeasurements) {\r\n setCloseDrawer(false);\r\n setNewTabValue(value);\r\n setActiveMeasurePrompt(true);\r\n return;\r\n }\r\n\r\n setTabValue(value);\r\n };\r\n\r\n const handleDrawerClose = () => {\r\n if (measurementsOpen && hasMeasurements) {\r\n setCloseDrawer(true);\r\n setNewTabValue(0);\r\n setActiveMeasurePrompt(true);\r\n return;\r\n }\r\n\r\n setDefaultTab();\r\n setAssetDrawerState(false);\r\n };\r\n\r\n const onModalClose = () => {\r\n setTabValue(newTabValue);\r\n\r\n if (closeDrawer) {\r\n setAssetDrawerState(false);\r\n }\r\n };\r\n\r\n const handleClose = () => {\r\n setActiveMeasurePrompt(false);\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 {theme.direction === 'ltr' ? : }\r\n \r\n \r\n \r\n\r\n {/* Assets */}\r\n \r\n \r\n \r\n\r\n {/* Measurements */}\r\n \r\n \r\n \r\n\r\n
\r\n \r\n\r\n {/* Discard measurements dialog */}\r\n {\r\n onModalClose();\r\n handleClose();\r\n }}\r\n title=\"Discard measurements?\"\r\n prompt=\"Active measurements found, do you want to discard measurements?\"\r\n button=\"Discard\"\r\n />\r\n\r\n
\r\n );\r\n};","import {fsPromises, isStaticSite, dialog, fs} from \"./electron-modules\";\r\nimport slash from 'slash';\r\n\r\ninterface TransformResponse {\r\n success: Boolean,\r\n content: any\r\n}\r\n\r\nexport const cameraMatrixFilter = [{name: 'Camera Correction Matrix', extensions: [\"4x4\"]}];\r\n\r\nexport const saveMatrixFile = (cameraTransformPath, showMessage) => {\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 showMessage(\"Failed to save camera correction matrix file\", {\r\n variant: \"error\"\r\n });\r\n } else {\r\n showMessage(\"Camera correction matrix file saved\", {\r\n variant: \"success\"\r\n });\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: 'Error reading camera correction .4x4 file'\r\n };\r\n\r\n if (!path) {\r\n resolve(errorResponse);\r\n return;\r\n }\r\n\r\n try {\r\n let data = isStaticSite ?\r\n await fetch(path).then(res => res.text()) :\r\n await fsPromises.readFile(path, {encoding: 'utf8'});\r\n\r\n let arr = [];\r\n let valid = true;\r\n let rows = data.split(\"\\n\");\r\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 => {\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 === false) {\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};","import React, {useEffect, useState} from 'react';\r\nimport {makeStyles, Theme, createStyles} from '@material-ui/core/styles';\r\nimport AppBar from '@material-ui/core/AppBar';\r\nimport Toolbar from '@material-ui/core/Toolbar';\r\nimport Typography from '@material-ui/core/Typography';\r\nimport IconButton from '@material-ui/core/IconButton';\r\nimport MenuIcon from '@material-ui/icons/Menu';\r\nimport SettingsIcon from '@material-ui/icons/Settings';\r\nimport EditIcon from '@material-ui/icons/Edit';\r\nimport {\r\n changeName,\r\n selectName\r\n} from \"./redux/project-slice\";\r\nimport {useSelector, useDispatch} from 'react-redux';\r\nimport {Projection, changeData, changeView, selectData} from './redux/projections-slice';\r\nimport projections, {\r\n generateID,\r\n unknownProjectionFeet,\r\n unknownProjectionMeters,\r\n unknownTextFeet,\r\n unknownTextMeters\r\n} from './projections/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 '@material-ui/core';\r\nimport {assetDrawerWidth} from './asset-drawer';\r\nimport LocalScene, { infoToMeters, projectionUnits } from './viewer/js/projections';\r\nimport {dialog, isStaticSite} from \"./electron-modules\";\r\nimport { useSnackbar } from 'notistack';\r\nimport slash from 'slash';\r\nimport {\r\n changeBasicAdjustments,\r\n changeCameraHeight,\r\n changeCameraTransform,\r\n selectBasicAdjustments,\r\n selectCameraHeight,\r\n selectCameraTransform\r\n} from './redux/camera-slice';\r\nimport { readTransformFile, cameraMatrixFilter, saveMatrixFile } from './camera-utils';\r\nimport clsx from 'clsx';\r\nimport { ArrowTooltip } from './tooltips';\r\nimport { Viewer } from './viewer/js/main';\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 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 marginTop: \"-5px\",\r\n color: \"white\"\r\n },\r\n transformMatrix: {\r\n maxWidth: \"60px\",\r\n paddingRight: \"10px\"\r\n },\r\n matrixColumn: {\r\n display: \"flex\",\r\n flexDirection: \"column\"\r\n },\r\n matrix: {\r\n display: \"flex\"\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 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 matrixAndButtons: {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\"\r\n },\r\n verticalButtons: {\r\n display: \"flex\",\r\n flexDirection: \"column\"\r\n }\r\n }),\r\n);\r\n\r\nconst openDialogMatrix = (): Promise => {\r\n return dialog.showOpenDialog( {\r\n filters: cameraMatrixFilter,\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('Error', 'An error occurred while loading the specified file.');\r\n return [];\r\n });\r\n};\r\n\r\nconst MatrixTextField = (props) => {\r\n const {value, classes} = props;\r\n\r\n /** Truncate and set fixed number of digits */\r\n const truncate = (number, digits=3) => {\r\n const multiplier = Math.pow(10, digits);\r\n return (Math.trunc(number * multiplier) / multiplier)\r\n .toFixed(digits);\r\n };\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst MatrixRepresentation = (props) => {\r\n const {classes, cameraTransform} = props;\r\n const matrix = cameraTransform.matrix;\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\n \r\n \r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nconst ProjectDetails = (props) => { const dispatch = useDispatch();\r\n const classes = useStyles();\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const viewer = props.viewer as Viewer;\r\n const {assetDrawerState} = props;\r\n\r\n const [open, setOpen] = useState(false);\r\n const [warnOpen, setWarnOpen] = useState(false);\r\n const [name, setName] = useState(\"\");\r\n const [height, setHeight] = useState(0);\r\n const [proj, setProj] = useState(\"\");\r\n const [imported, setImported] = useState(null);\r\n const [cameraTransform, setCameraTransform] = useState({\r\n matrix: null,\r\n path: null\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(selectName);\r\n const projectHeight = useSelector(selectCameraHeight);\r\n const cameraTransformPath = useSelector(selectCameraTransform);\r\n const dataProjection = useSelector(selectData);\r\n const basicAdjustments = useSelector(selectBasicAdjustments);\r\n\r\n const getNewProjection = () => {\r\n let newProjection = null;\r\n if (proj === unknownTextMeters) {\r\n newProjection = unknownProjectionMeters;\r\n } else if (proj === unknownTextFeet) {\r\n newProjection = unknownProjectionFeet;\r\n } else {\r\n const results = data.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 return newProjection;\r\n };\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n };\r\n\r\n const handleWarnClose = () => {\r\n setWarnOpen(false);\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 setErrors({...errors, projection: false});\r\n setProj(value);\r\n };\r\n\r\n const onSubmit = () => {\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 setOpen(false);\r\n showMessage(\"Project details updated\", {\r\n variant: \"success\"\r\n });\r\n\r\n setTimeout(() => {\r\n dispatch(changeName(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 projName = selectedProjection.name;\r\n const projChanged = !LocalScene.currentProjection(projName);\r\n\r\n if (projChanged) {\r\n dispatch(changeData(selectedProjection));\r\n dispatch(changeView(selectedProjection));\r\n }\r\n }, 50);\r\n };\r\n\r\n const handleCollisions = () => {\r\n const name = dataProjection.name;\r\n if ((name === unknownTextFeet) || (name === unknownTextMeters)) {\r\n return;\r\n }\r\n\r\n if (imported?.name === name) {\r\n return;\r\n }\r\n\r\n const results = projections.data.filter(x => x.name === name);\r\n\r\n if (results.length > 0) {\r\n // Compare projection with existing projections\r\n const existing = results[0];\r\n const importedProjection = JSON.stringify(dataProjection, Object.keys(dataProjection).sort());\r\n const userProjection = JSON.stringify(existing, Object.keys(existing).sort());\r\n\r\n if (importedProjection === userProjection) {\r\n // Projections are the same, do nothing\r\n return;\r\n } else {\r\n // Projections are different, so we warn the user\r\n setWarnOpen(true);\r\n }\r\n }\r\n\r\n setImported({...dataProjection, imported: true});\r\n };\r\n\r\n const onCorrectionSelect = () => {\r\n openDialogMatrix().then(filePath => {\r\n if (!filePath) {\r\n return;\r\n }\r\n\r\n readTransformFile(filePath)\r\n .then(data => {\r\n const {success, content} = data;\r\n\r\n if (success) {\r\n setCameraTransform({\r\n path: filePath,\r\n matrix: content\r\n });\r\n } else {\r\n showMessage(content, {\r\n variant: \"error\"\r\n });\r\n }\r\n });\r\n });\r\n };\r\n\r\n const onCorrectionRemove = () => {\r\n setCameraTransform({\r\n path: null,\r\n matrix: null\r\n });\r\n };\r\n\r\n const updateTitle = (title) => {\r\n document.title = \"SOLV3D engine viewer - \" + title;\r\n };\r\n\r\n const clearBasicAlignment = () => {\r\n dispatch(changeBasicAdjustments({}));\r\n viewer?.resetBasicAlignerCamera();\r\n };\r\n\r\n useEffect(() => {\r\n setProj(dataProjection.name);\r\n }, [dataProjection]);\r\n\r\n useEffect(() => {\r\n setName(projectName);\r\n updateTitle(projectName);\r\n }, [projectName]);\r\n\r\n useEffect(() => {\r\n readTransformFile(cameraTransformPath)\r\n .then(data => {\r\n const {success, content} = data;\r\n\r\n if (success) {\r\n setCameraTransform({\r\n path: cameraTransformPath,\r\n matrix: content\r\n });\r\n } else {\r\n setCameraTransform({\r\n path: null,\r\n matrix: null\r\n });\r\n }\r\n });\r\n }, [cameraTransformPath]);\r\n\r\n useEffect(() => {\r\n const height = projectHeight / toMeters;\r\n setHeight(height);\r\n }, [open]);\r\n\r\n handleCollisions();\r\n\r\n const data = projections.data;\r\n 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 const matchingProjection = projections.data?.filter(\r\n x => x.name === dataProjection.name)[0];\r\n\r\n const defaultProjection = (dataProjection.name === unknownTextMeters)\r\n || (dataProjection.name === unknownTextFeet);\r\n\r\n const selectedProjection = getNewProjection();\r\n const units = projectionUnits(selectedProjection);\r\n const toMeters = infoToMeters(selectedProjection);\r\n const hasBasicAlignment = Object.keys(basicAdjustments).length !== 0;\r\n\r\n return (\r\n
\r\n \r\n \r\n {projectName}\r\n \r\n \r\n {dataProjection.name}\r\n \r\n \r\n\r\n {(!isStaticSite) && ( {\r\n setOpen(true);\r\n }}\r\n color={\"inherit\"}\r\n >\r\n \r\n )}\r\n\r\n \r\n Project Information\r\n \r\n {/* Project display title */}\r\n Title\r\n \r\n The display name of the project that is shown when users export/share the project data.\r\n \r\n \r\n\r\n {/* Camera height */}\r\n Camera Height ({units})\r\n \r\n The height of the camera from the ground. Used when displaying markers and for image-only measurements.\r\n \r\n \r\n\r\n {/* Projection dropdown */}\r\n Data Projection\r\n \r\n The projection that describes your input data (point cloud and images). Note that\r\n changing the projection will force a reload of data, and remove all active measurements.\r\n \r\n \r\n {imported && (Imported Projections)}\r\n\r\n {imported && ({imported.name})}\r\n\r\n Generic Projections\r\n\r\n {unknownTextMeters}\r\n\r\n {unknownTextFeet}\r\n\r\n User Projections\r\n\r\n {data.map(row => {\r\n const conflict = imported ? imported.name === row.name : false;\r\n const suffix = conflict ? \"__conflict\" : \"\";\r\n return ({row.name});\r\n })}\r\n \r\n\r\n {/* Camera Correction Matrix */}\r\n
\r\n Camera Correction File (Optional)\r\n\r\n {(!hasBasicAlignment) && (\r\n An optional camera correction matrix for misaligned cameras. This is only required if\r\n post-capture data alignment was done using the Data Alignment module.\r\n )}\r\n\r\n {(hasBasicAlignment) && (
\r\n \r\n Image and Point Cloud data currently have a basic alignment applied. Current Alignment\r\n must be cleared before applying correction matrix\r\n \r\n
)}\r\n\r\n
\r\n {cameraTransform.path && ()}\r\n\r\n
\r\n {/* Save matrix file */}\r\n {(cameraTransform.path) && (saveMatrixFile(cameraTransform.path, showMessage)}\r\n className={clsx(classes.button, classes.slimButton)}\r\n color=\"primary\"\r\n >\r\n Save File\r\n )}\r\n\r\n {/* Remove matrix file */}\r\n {cameraTransform.path && (\r\n Remove File\r\n )}\r\n\r\n {/* Upload matrix file */}\r\n {(!hasBasicAlignment) && (\r\n Upload File\r\n )}\r\n\r\n {/* Cancel basic alignment */}\r\n {(hasBasicAlignment) && (\r\n Clear Alignment\r\n )}\r\n
\r\n
\r\n\r\n
\r\n\r\n
\r\n {\r\n setOpen(false);\r\n }}\r\n className={classes.button}\r\n >\r\n Cancel\r\n \r\n\r\n \r\n Update Project\r\n \r\n
\r\n
\r\n \r\n\r\n {/* Warning message for projection mismatch */}\r\n \r\n {\"Projection Mismatch\"}\r\n \r\n \r\n The projection ({dataProjection.name}) imported from the project file does not match the\r\n user projection of the same name. To ensure compatability, the user projection will be disabled\r\n in the project edit screen.\r\n \r\n\r\n \r\n Imported Projection{dataProjection.transform ? \" (+ Custom Transform)\" : \"\"}\r\n

\r\n \"{dataProjection.string}\"\r\n
\r\n\r\n \r\n Existing Projection{matchingProjection?.transform ? \" (+ Custom Transform)\" : \"\"}\r\n

\r\n \"{matchingProjection?.string}\"\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n
\r\n );\r\n};\r\n\r\nexport const MainAppBar = (props) => {\r\n const classes = useStyles();\r\n\r\n const viewer = props.viewer as Viewer;\r\n const {handleAssetDrawerOpen, handleSettingsDrawerOpen, assetDrawerState} = 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\n};","import React, {useCallback, useEffect, useState} from 'react';\r\nimport {createStyles, makeStyles, Theme, useTheme} from '@material-ui/core/styles';\r\nimport Drawer from '@material-ui/core/Drawer';\r\nimport { debounce } from 'throttle-debounce';\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} from \"@material-ui/core\";\r\nimport IconButton from \"@material-ui/core/IconButton\";\r\nimport ChevronLeftIcon from \"@material-ui/icons/ChevronLeft\";\r\nimport ChevronRightIcon from \"@material-ui/icons/ChevronRight\";\r\nimport Divider from \"@material-ui/core/Divider\";\r\nimport Typography from \"@material-ui/core/Typography\";\r\nimport Slider from \"@material-ui/core/Slider\";\r\nimport {useSelector, useDispatch} from 'react-redux';\r\nimport {\r\n ColorMapKey, ColorType,\r\n selectCloudDistance, changeCloudDistance,\r\n selectOpacity, changeOpacity,\r\n selectOrthoOpacity, changeOrthoOpacity,\r\n selectCloudSize, changeCloudSize,\r\n selectHeightClip, changeHeightClip,\r\n selectIntensityClip, changeIntensityClip,\r\n selectColorMap, changeColorMap,\r\n selectColorType, changeColorType,\r\n selectDynamicSize, changeDynamicSize,\r\n selectAvailableClassifications, changeClassificationVisibility,\r\n selectClassificationVisibilities, changeAllClassificationVisibility,\r\n changeCircularPoints, selectCircularPoints,\r\n changeArrowMarkers, selectArrowMarkers, MarkerNavType,\r\n selectCloudMaxPoints, changeCloudMaxPoints\r\n} from './redux/settings-slice';\r\nimport {colorMaps} from \"./viewer/textures/colormaps\";\r\nimport { getClassificationColors } from \"./classifications\";\r\nimport { isDevMode } from './electron-modules';\r\nimport { selectAllAssets, getOrthoAssets } from './redux/assets-slice';\r\nimport { drawerWidth } from './app';\r\nimport { ArrowTooltip } from './tooltips';\r\nimport { Viewer } from './viewer/js/main';\r\nimport { SlimScrollbar } from './toolbar';\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 },\r\n drawerPaper: {\r\n width: drawerWidth,\r\n },\r\n asterisk: {\r\n \"&:after\": {\r\n content:'\"*\"',\r\n color: \"red\"\r\n }\r\n },\r\n drawerHeader: {\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 },\r\n list: {\r\n width: '100%',\r\n maxWidth: 360,\r\n backgroundColor: theme.palette.background.paper,\r\n },\r\n listItem: {\r\n width: '100%',\r\n paddingRight: '5px',\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 switch: {\r\n marginLeft: 0\r\n },\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 img: {\r\n objectFit: 'fill',\r\n transform: 'rotate(-90deg)'\r\n },\r\n classificationPreview: {\r\n height: theme.spacing(1.25),\r\n width: theme.spacing(1.25),\r\n backgroundColor: '#bbb',\r\n borderRadius: '50%',\r\n borderColor: '#000000',\r\n borderStyle: 'solid',\r\n borderWidth: '1px',\r\n marginRight: theme.spacing(1),\r\n display: 'inline-block'\r\n },\r\n switchLabel: {\r\n display: \"inline-block\"\r\n },\r\n switchElement: {\r\n float: \"right\"\r\n },\r\n boldTypography: {\r\n fontWeight: 'bold',\r\n display: \"inline-block\",\r\n fontSize: '1em'\r\n }\r\n }),\r\n);\r\n\r\nexport const SettingsDrawer = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n\r\n const dispatch = useDispatch();\r\n const theme = useTheme();\r\n const classes = useStyles();\r\n const colorMap = useSelector(selectColorMap);\r\n const colorType = useSelector(selectColorType);\r\n const dynamicSize = useSelector(selectDynamicSize);\r\n const circularPoints = useSelector(selectCircularPoints);\r\n const arrowMarkers = useSelector(selectArrowMarkers);\r\n const availableClassifications = useSelector(selectAvailableClassifications);\r\n const classificationVisibilities = useSelector(selectClassificationVisibilities);\r\n const [classificationColors, setClassificationColors] = useState(Array(256).fill('#ffffff'));\r\n const assets = useSelector(selectAllAssets);\r\n const orthoFiles = getOrthoAssets(assets);\r\n\r\n const getClassifications = (classifications) => {\r\n if (classifications.length === 0) {\r\n return
\r\n \r\n \r\n No points loaded\r\n \r\n \r\n
;\r\n }\r\n\r\n return classifications.map(classification => (\r\n \r\n
\r\n
\r\n \r\n\r\n \r\n {`${classification.name} (${classification.id})`}\r\n \r\n\r\n {\r\n dispatch(changeClassificationVisibility(classification.id));\r\n }}\r\n />\r\n
\r\n
\r\n
\r\n ));\r\n };\r\n\r\n const dispatchInterval = 1000;\r\n\r\n /** Cloud Opacity */\r\n const opacity = useSelector(selectOpacity);\r\n const [opacitySliderValue, setOpacitySlider] = useState(0);\r\n const saveOpacity = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeOpacity(value));\r\n }), []);\r\n\r\n /** Ortho Opacity */\r\n const orthoOpacity = useSelector(selectOrthoOpacity);\r\n const [orthoOpacitySliderValue, setOrthoOpacitySlider] = useState(0);\r\n const saveOrthoOpacity = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeOrthoOpacity(value));\r\n }), []);\r\n\r\n /** Cloud Distance */\r\n const cloudDistance = useSelector(selectCloudDistance);\r\n const [distanceSliderValue, setDistanceSlider] = useState(0);\r\n const saveCloudDistance = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeCloudDistance(value));\r\n }), []);\r\n\r\n /** Cloud Max Points */\r\n const cloudMaxPoints = useSelector(selectCloudMaxPoints);\r\n const [maxPointsSlider, setMaxPointsSlider] = useState(0);\r\n const saveCloudMaxPoints = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeCloudMaxPoints(value));\r\n }), []);\r\n\r\n /** Cloud Size */\r\n const cloudSize = useSelector(selectCloudSize);\r\n const [cloudSizeSlider, setCloudSizeSlider] = useState(0);\r\n const saveCloudSize = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeCloudSize(value));\r\n }), []);\r\n\r\n /** Height Range */\r\n const heightClip = useSelector(selectHeightClip);\r\n const [heightClipSlider, setHeightClipSlider] = useState({min: 0,max: 0});\r\n const saveHeightClip = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeHeightClip(value));\r\n }), []);\r\n\r\n /** Intensity Range */\r\n const intensityClip = useSelector(selectIntensityClip);\r\n const [intensityClipSlider, setIntensityClipSlider] = useState({min: 0,max: 0});\r\n const saveIntensityClip = useCallback(\r\n debounce(dispatchInterval, (value) => {\r\n dispatch(changeIntensityClip(value));\r\n }), []);\r\n\r\n const updateOpacity = (value) => {\r\n setOpacitySlider(value);\r\n viewer?.setPointCloudOpacity(value);\r\n };\r\n\r\n const updateOrthoOpacity = (value) => {\r\n setOrthoOpacitySlider(value);\r\n viewer?.setOrthoOpacity(value);\r\n };\r\n\r\n const updateDistance = (value) => {\r\n setDistanceSlider(value);\r\n viewer?.setPointCloudDistance(value);\r\n };\r\n\r\n const updateMaxPoints = (value) => {\r\n setMaxPointsSlider(value);\r\n viewer?.setPointCloudMaxPoints(value);\r\n };\r\n\r\n const updateCloudSize = (value) => {\r\n setCloudSizeSlider(value);\r\n viewer?.setPointCloudSize(value);\r\n };\r\n\r\n const updateHeightClip = (value) => {\r\n setHeightClipSlider(value);\r\n viewer?.setPointCloudHeightClip(value);\r\n };\r\n\r\n const updateIntensityClip = (value) => {\r\n setIntensityClipSlider(value);\r\n viewer?.setPointCloudIntensityClip(value);\r\n };\r\n\r\n useEffect(() => {\r\n updateOpacity(opacity);\r\n }, [viewer, opacity]);\r\n\r\n useEffect(() => {\r\n updateOrthoOpacity(orthoOpacity);\r\n }, [viewer, orthoOpacity]);\r\n\r\n useEffect(() => {\r\n updateDistance(cloudDistance);\r\n }, [viewer, cloudDistance]);\r\n\r\n useEffect(() => {\r\n updateMaxPoints(cloudMaxPoints);\r\n }, [viewer, cloudDistance]);\r\n\r\n useEffect(() => {\r\n updateCloudSize(cloudSize);\r\n }, [viewer, cloudSize]);\r\n\r\n useEffect(() => {\r\n updateHeightClip(heightClip);\r\n }, [viewer, heightClip]);\r\n\r\n useEffect(() => {\r\n updateIntensityClip(intensityClip);\r\n }, [viewer, intensityClip]);\r\n\r\n useEffect(() => {\r\n viewer?.setVisibleClassifications(classificationVisibilities);\r\n }, [viewer, classificationVisibilities]);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudColorMap(colorMap);\r\n }, [viewer, colorMap]);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudColorType(colorType);\r\n }, [viewer, colorType]);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudDynamicSize(dynamicSize);\r\n }, [viewer, dynamicSize]);\r\n\r\n useEffect(() => {\r\n viewer?.setPointCloudCircularPoints(circularPoints);\r\n }, [viewer, circularPoints]);\r\n\r\n useEffect(() => {\r\n viewer?.setNavigationType(arrowMarkers);\r\n }, [viewer, arrowMarkers]);\r\n\r\n useEffect(() => {\r\n getClassificationColors().then(result => {\r\n setClassificationColors(result);\r\n });\r\n }, []);\r\n\r\n const isIntensity = colorType === 0;\r\n const isHeightmap = colorType === 2;\r\n const colorMapRequired = isIntensity || isHeightmap;\r\n\r\n return (\r\n \r\n
\r\n \r\n {theme.direction === \"rtl\" ? (\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 Point Cloud Controls\r\n \r\n \r\n\r\n {/* Color type */}\r\n \r\n
\r\n \r\n Color Type\r\n \r\n \r\n {\r\n const value = event.target.value as ColorType;\r\n dispatch(changeColorType(value));\r\n }}\r\n >\r\n \r\n Intensity\r\n \r\n \r\n Color\r\n \r\n \r\n Height\r\n \r\n \r\n Classification\r\n \r\n \r\n \r\n
\r\n
\r\n\r\n {/* Color maps */}\r\n {colorMapRequired && (\r\n \r\n
\r\n \r\n Color Map\r\n \r\n \r\n \r\n colorMaps.find((colorMap) => colorMap.id === value).name\r\n }\r\n onChange={(event) => {\r\n const value = event.target.value as ColorMapKey;\r\n dispatch(changeColorMap(value));\r\n }}\r\n >\r\n {colorMaps.map((colorMap) => (\r\n \r\n \r\n {colorMap.name}\r\n \r\n ))}\r\n \r\n \r\n
\r\n
\r\n )}\r\n\r\n {/* Arrow Markers */}\r\n \r\n
\r\n \r\n Navigation\r\n \r\n \r\n {\r\n let value = event.target.value as MarkerNavType;\r\n dispatch(changeArrowMarkers(value));\r\n }}\r\n >\r\n \r\n Arrows\r\n \r\n \r\n Markers\r\n \r\n \r\n None\r\n \r\n \r\n \r\n
\r\n
\r\n\r\n {/* Cloud Opacity */}\r\n \r\n
\r\n \r\n Point Visibility\r\n \r\n {\r\n updateOpacity(value);\r\n saveOpacity(value);\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Cloud Max Points */}\r\n \r\n
\r\n \r\n \r\n Max Visible Points\r\n \r\n \r\n\r\n {\r\n updateMaxPoints(value);\r\n saveCloudMaxPoints(value);\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Cloud Distance */}\r\n \r\n
\r\n \r\n Distance\r\n \r\n {\r\n updateDistance(value);\r\n saveCloudDistance(value);\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Cloud Size */}\r\n \r\n
\r\n \r\n Size\r\n \r\n {\r\n updateCloudSize(value);\r\n saveCloudSize(value);\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Height range */}\r\n {isHeightmap && (\r\n \r\n
\r\n \r\n Height Range\r\n \r\n {\r\n let height = { min: value[0], max: value[1] };\r\n updateHeightClip(height);\r\n saveHeightClip(height);\r\n }}\r\n />\r\n
\r\n
\r\n )}\r\n\r\n {/* Intensity range */}\r\n {isIntensity && (\r\n \r\n
\r\n \r\n Intensity Range\r\n \r\n {\r\n let height = { min: value[0], max: value[1] };\r\n updateIntensityClip(height);\r\n saveIntensityClip(height);\r\n }}\r\n />\r\n
\r\n
\r\n )}\r\n\r\n {/* Dynamic size */}\r\n \r\n
\r\n \r\n \r\n Dynamic Point Sizing\r\n \r\n \r\n\r\n {\r\n dispatch(changeDynamicSize(checked));\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Circular Points */}\r\n \r\n
\r\n \r\n Circular Points\r\n \r\n\r\n {\r\n dispatch(changeCircularPoints(checked));\r\n }}\r\n />\r\n
\r\n
\r\n\r\n {/* Picker Debug */}\r\n {isDevMode && (\r\n \r\n
\r\n \r\n Picker Debug\r\n \r\n\r\n {\r\n viewer?.togglePickerDebug(checked);\r\n }}\r\n />\r\n
\r\n
\r\n )}\r\n \r\n\r\n {/* Orthomosaic Settings */}\r\n {orthoFiles.length > 0 && (\r\n \r\n \r\n\r\n \r\n \r\n \r\n Orthomosaic Settings\r\n \r\n \r\n\r\n {/* Ortho opacity */}\r\n \r\n
\r\n \r\n Opacity\r\n \r\n {\r\n updateOrthoOpacity(value);\r\n saveOrthoOpacity(value);\r\n }}\r\n />\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 Classifications\r\n \r\n\r\n {availableClassifications.length > 0 && (\r\n \r\n classification.visible\r\n )}\r\n className={classes.switchElement}\r\n size=\"small\"\r\n color=\"secondary\"\r\n onChange={(_, checked) => {\r\n dispatch(changeAllClassificationVisibility(checked));\r\n }}\r\n />\r\n \r\n )}\r\n
\r\n
\r\n {getClassifications(availableClassifications)}\r\n
\r\n\r\n
\r\n \r\n );\r\n};\r\n","import React from 'react';\r\nimport {\r\n createStyles,\r\n IconButton,\r\n makeStyles,\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} from '@material-ui/core';\r\nimport DeleteForeverIcon from '@material-ui/icons/DeleteForever';\r\nimport {useState} from 'react';\r\nimport clsx from 'clsx';\r\nimport { PromptDialog } from './dialogs';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n header: {\r\n fontWeight: \"bold\"\r\n },\r\n denseCell: {\r\n padding: \"4px 12px !important\",\r\n },\r\n footerDense: {\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 color: \"lightgray\"\r\n },\r\n \"& td\": {\r\n color: \"lightgray\"\r\n }\r\n },\r\n break: {\r\n wordBreak: \"break-word\"\r\n },\r\n rowHover: {\r\n cursor: \"pointer\"\r\n }\r\n }),\r\n);\r\n\r\nconst EnhancedTableHead = (props) => {\r\n const {classes, order, orderBy, onRequestSort, columns,\r\n deletable, isDense, isSortable} = props;\r\n\r\n const createSortHandler = (property) => (event) => {\r\n onRequestSort(event, property);\r\n };\r\n\r\n const cellClassName = isDense ? classes.denseCell : \"\";\r\n\r\n return (\r\n \r\n \r\n {columns.map((column, index) => (\r\n \r\n {/* Non-sortable column header */}\r\n {(isSortable === false) && (column.label)}\r\n\r\n {/* Sortable column header */}\r\n {(isSortable === true) && (\r\n {column.label}\r\n {orderBy === column.id ? (\r\n \r\n {order === 'desc' ? 'sorted descending' : 'sorted ascending'}\r\n \r\n ) : null}\r\n )}\r\n \r\n ))}\r\n {deletable && ()}\r\n \r\n \r\n );\r\n};\r\n\r\nconst EnhancedTable = (props) => {\r\n const {columns, rows, rowType, onRowClick, deletable,\r\n onDeleteClick, dense, pageSize, defaultSort, sortable,\r\n wordBreak, ...other} = props;\r\n\r\n const classes = useStyles();\r\n\r\n const numRowsPerPage = pageSize !== undefined ? pageSize : 5;\r\n const isSortable = sortable !== undefined ? sortable : true;\r\n\r\n const [open, setOpen] = useState(false);\r\n const [order, setOrder] = useState('asc');\r\n const [orderBy, setOrderBy] = useState(defaultSort);\r\n const [selectedRow, setSelectedRow] = useState();\r\n const [page, setPage] = useState(0);\r\n const [rowsPerPage, setRowsPerPage] = useState(numRowsPerPage);\r\n\r\n const handleClose = () => {\r\n setOpen(false);\r\n setSelectedRow(null);\r\n };\r\n\r\n const handleChangePage = (event, newPage) => {\r\n setPage(newPage);\r\n };\r\n\r\n const handleChangeRowsPerPage = (event) => {\r\n setRowsPerPage(parseInt(event.target.value, 10));\r\n setPage(0);\r\n };\r\n\r\n const handleRequestSort = (event, property) => {\r\n const isAsc = orderBy === property && order === 'asc';\r\n setOrder(isAsc ? 'desc' : 'asc');\r\n setOrderBy(property);\r\n };\r\n\r\n const descendingComparator = (a, b, orderBy) => {\r\n let compA = a[orderBy];\r\n let compB = b[orderBy];\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 = (order, orderBy) => {\r\n return order === 'desc'\r\n ? (a, b) => descendingComparator(a, b, orderBy)\r\n : (a, b) => -descendingComparator(a, b, orderBy);\r\n };\r\n\r\n // Make sure our max page is valid\r\n const maxPage = Math.max(0, Math.ceil(rows.length / rowsPerPage) - 1);\r\n if (page > maxPage) {\r\n setPage(maxPage);\r\n }\r\n\r\n if (isSortable) {\r\n // Sort based on sort criteria\r\n rows.sort(getComparator(order, orderBy));\r\n }\r\n\r\n let sliced = rows.slice(\r\n page * rowsPerPage,\r\n page * rowsPerPage + rowsPerPage\r\n );\r\n\r\n const isDense = dense === true;\r\n const cellClassName = isDense ? classes.denseCell : \"\";\r\n const footerClassName = isDense ? classes.footerDense : \"\";\r\n\r\n const cellContent = (content, condition) => {\r\n if (typeof(content) === \"string\") {\r\n content = condition ? content : `${content.slice(0,100)}...`;\r\n }\r\n return content;\r\n };\r\n\r\n const cellTitle = (content) => {\r\n return (typeof(content) === \"string\") ? content : \"\";\r\n };\r\n\r\n return (\r\n
\r\n \r\n \r\n \r\n \r\n \r\n {sliced.map((row, index) => {\r\n const isItemSelected = selectedRow === row;\r\n const disabled = row.disabled === true;\r\n\r\n return (\r\n \r\n {columns.map((column, index) => {\r\n const key = `${row.id}${column.id}`;\r\n const first = index === 0;\r\n const text = row[column.id];\r\n const condition = (column.numeric || text.length <= 100);\r\n const showHover = index === 1 && text !== 'No File'; \r\n \r\n return ( {\r\n if (disabled) {\r\n return;\r\n }\r\n onRowClick(row, index);\r\n }}\r\n className={clsx(cellClassName, {\r\n [classes.break]: wordBreak, \r\n [classes.rowHover]: showHover\r\n })}\r\n title={cellTitle(showHover ? 'Jump to image' : text)}\r\n >\r\n {cellContent(text, condition)}\r\n );\r\n })}\r\n\r\n {deletable && disabled && (\r\n \r\n )}\r\n\r\n {/* Delete button */}\r\n {deletable && (disabled===false) && (\r\n \r\n {\r\n setOpen(true);\r\n setSelectedRow(row);\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 {/* Delete Dialog */}\r\n {\r\n onDeleteClick(selectedRow);\r\n handleClose();\r\n }}\r\n title=\"Delete entry?\"\r\n prompt={`Do you want to delete this ${rowType}?`}\r\n button=\"Delete\"\r\n />\r\n
\r\n );\r\n};\r\n\r\nexport default EnhancedTable;","import React, {useEffect} from 'react';\r\nimport clsx from 'clsx';\r\nimport Button from '@material-ui/core/Button';\r\nimport Dialog from '@material-ui/core/Dialog';\r\nimport MuiDialogContent from '@material-ui/core/DialogContent';\r\nimport IconButton from '@material-ui/core/IconButton';\r\nimport CloseIcon from '@material-ui/icons/Close';\r\nimport {createStyles, makeStyles, Theme} from \"@material-ui/core/styles\";\r\nimport projections, {defaultProjection, defaultTransform, generateID} from './projections';\r\nimport EnhancedTable from '../enhanced-table';\r\nimport {useState} from 'react';\r\nimport {\r\n AppBar,\r\n Checkbox,\r\n Divider,\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 '@material-ui/core';\r\nimport LocalScene, { isValidProjection } from '../viewer/js/projections';\r\nimport { PanelProps, TabPanel, TabProps } from '../tabs';\r\nimport { useSnackbar } from 'notistack';\r\nimport { ipcRenderer } from '../electron-modules';\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 position: 'absolute',\r\n right: theme.spacing(0),\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 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 panel: {\r\n background: \"rgba(200,200,200,0.1)\"\r\n }\r\n }),\r\n);\r\n\r\nconst UserProjectionPanel = (props) => {\r\n const {classes, loadProjectionToEdit, setActiveTab, showMessage} = props;\r\n\r\n // Table headers\r\n const columns = [\r\n {id: 'name', numeric: false, label: 'Projection Name'},\r\n {id: 'type', numeric: false, label: 'Type'},\r\n {id: 'custom', numeric: false, label: 'Custom'},\r\n ];\r\n\r\n // Convert projections to data row\r\n const data = projections.data;\r\n const rows = data.map(option => {\r\n return {\r\n id: generateID(option.name),\r\n name: option.name,\r\n custom: option.transform ? \"Yes\" : \"No\",\r\n type: option.type,\r\n disabled: LocalScene.currentProjection(option.name)\r\n };\r\n });\r\n\r\n const onRowClick = (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 onDeleteClick = (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 projections.delete(projection.name);\r\n showMessage(\"Projection deleted\", {\r\n variant: \"error\"\r\n });\r\n\r\n // Force projection list refresh\r\n setActiveTab(0);\r\n };\r\n\r\n return (\r\n
\r\n {rows.length === 0 && (\r\n No user projections have been added. Click on \"Add New\" to add a custom\r\n projection or \"Search Online\" to look up common results\r\n )}\r\n\r\n {rows.length > 0 && ()}\r\n
\r\n );\r\n};\r\n\r\nconst EditPanel = (props) => {\r\n const {classes, customProjection, updateEditableValues,\r\n transformCheckbox, setTransformCheckbox, clearProjectionValues,\r\n newProjection, setActiveTab, existingName, showMessage, errors,\r\n setErrors} = props;\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 setTransformCheckbox(event.target.checked);\r\n };\r\n\r\n const saveProjection = () => {\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 nameError = nameTrim === \"\";\r\n let stringError = stringTrim === \"\";\r\n setErrors({\r\n name: nameError,\r\n string: stringError\r\n });\r\n\r\n if (nameError || stringError) {\r\n return;\r\n }\r\n\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 (!transformCheckbox) {\r\n delete data.transform;\r\n }\r\n\r\n const nameChanged = data.name !== existingName;\r\n\r\n // Check for duplicates if our name has changed\r\n if (nameChanged) {\r\n if (projections.isDuplicate(data)) {\r\n setErrors({...errors, name: true});\r\n showMessage(\"Duplicate projection (name already exists)\", {\r\n variant: \"error\"\r\n });\r\n return;\r\n }\r\n }\r\n\r\n // Check for valid projection string\r\n let validProjection = isValidProjection(projString);\r\n if (!validProjection) {\r\n setErrors({...errors, string: true});\r\n showMessage(\"Invalid projection string\", {\r\n variant: \"error\"\r\n });\r\n return;\r\n }\r\n\r\n // Delete existing projection\r\n if (!newProjection) {\r\n projections.delete(existingName);\r\n }\r\n\r\n // Save new projection\r\n const success = projections.save(data);\r\n if (!success) {\r\n return;\r\n }\r\n\r\n showMessage(`Projection ${newProjection ? \"added\" : \"updated\"}`, {\r\n variant: \"success\"\r\n });\r\n\r\n if (newProjection) {\r\n clearProjectionValues();\r\n } else {\r\n setActiveTab(0);\r\n }\r\n };\r\n\r\n const updateType = (event) => {\r\n // Update projection type and clear projection string\r\n updateEditableValues({\r\n 'type': String(event.target.value),\r\n 'string': \"\"\r\n });\r\n };\r\n\r\n const updateName = (event) => {\r\n setErrors({...errors, name: false});\r\n updateEditableValues({\r\n \"name\": event.target.value\r\n });\r\n };\r\n\r\n const updateString = (event) => {\r\n let string = event.target.value;\r\n if (customProjection['type'] === \"epsg\") {\r\n string = `EPSG:${string}`;\r\n }\r\n setErrors({...errors, string: false});\r\n updateEditableValues({\r\n \"string\": string\r\n });\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] = value;\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] = value;\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n const updateScale = (event) => {\r\n let transform = customProjection.transform;\r\n transform['scale'] = parseFloat(event.target.value);\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n const updateRotation = (event) => {\r\n let transform = customProjection.transform;\r\n transform['rotation'] = parseFloat(event.target.value);\r\n updateEditableValues({\r\n \"transform\":transform\r\n });\r\n };\r\n\r\n return (\r\n
\r\n {/* Projection Name */}\r\n \r\n\r\n {/* Projection Type */}\r\n
\r\n \r\n Projection Type\r\n \r\n \r\n Projection String (Proj4)\r\n Well Known Text (WKT)\r\n {/*EPSG Code*/}\r\n \r\n
\r\n\r\n {/* Projection string (proj4) */}\r\n {type===\"proj4\" && ()}\r\n\r\n {/* Projection string (WKT) */}\r\n {type===\"wkt\" && ()}\r\n\r\n {/* EPSG Code */}\r\n {type===\"epsg\" && (EPSG:,\r\n }}\r\n className={classes.marginTop}\r\n />)}\r\n\r\n \r\n }\r\n label=\"Additional Parameters\"\r\n />\r\n\r\n {transformCheckbox && (\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 />\r\n \r\n \r\n {\r\n updateOrigin(e, 1);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\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 />\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 />\r\n \r\n \r\n {\r\n updateTranslation(e, 1);\r\n }}\r\n InputLabelProps={{\r\n shrink: true,\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 />\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 Cancel\r\n )}\r\n\r\n \r\n {newProjection ? \"Add Projection\" : \"Save Changes\"}\r\n \r\n
\r\n
\r\n );\r\n};\r\n\r\nconst SearchPanel = (props) => {\r\n const {classes, setActiveTab, loadProjectionToEdit} = props;\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\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 onRowClick = (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 // Table headers\r\n const columns = [\r\n {id: 'name', numeric: false, label: 'Name'},\r\n {id: 'epsg', numeric: true, label: 'EPSG'},\r\n {id: 'proj4', numeric: false, label: 'Proj4 String'},\r\n ];\r\n\r\n // Convert projections to data row\r\n const data = searchResults;\r\n const rows = data.map(projection => {\r\n return {\r\n id: generateID(projection.name),\r\n name: projection.name,\r\n epsg: parseInt(projection.code),\r\n proj4: projection.proj4,\r\n };\r\n });\r\n\r\n return (\r\n
\r\n {/* Search Type */}\r\n
\r\n \r\n Search Type\r\n \r\n \r\n Text\r\n UTM Zone\r\n EPSG Code\r\n \r\n
\r\n\r\n {/* UTM Zone */}\r\n {type===\"utm\" && (
\r\n UTM Zone,\r\n\r\n classes: {\r\n adornedEnd: classes.adornedEnd\r\n }\r\n }}\r\n className={classes.marginTop}\r\n />\r\n\r\n \r\n North\r\n 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 {/* Projection string (proj4) */}\r\n {type===\"text\" && ()}\r\n\r\n {/* Search button */}\r\n
\r\n \r\n {searching ? \"Searching EPSG.io...\" : \"Search Online\"}\r\n \r\n
\r\n\r\n {/* Results table */}\r\n
\r\n
\r\n );\r\n};\r\n\r\nexport const ProjectionsManager = (props) => {\r\n const {projectionsOpen, setProjectionsOpen} = props;\r\n\r\n const classes = useStyles();\r\n const showMessage = useSnackbar().enqueueSnackbar;\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 [transformCheckbox, setTransformCheckbox] = useState(false);\r\n const [errors, setErrors] = useState({});\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 clearAllErrors = () => {\r\n setErrors({\r\n name: false,\r\n string: false\r\n });\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 clearAllErrors();\r\n setTransformCheckbox(hasTransform);\r\n setCustomProjection({...dataCopy});\r\n setExistingName(dataCopy.name);\r\n setNewProjection(newProjection);\r\n };\r\n\r\n const handleOpen = () => {\r\n setProjectionsOpen(true);\r\n };\r\n\r\n const handleClose = () => {\r\n setProjectionsOpen(false);\r\n };\r\n\r\n const handleChange = (event, newactiveTab) => {\r\n setActiveTab(newactiveTab);\r\n };\r\n\r\n useEffect(() => {\r\n ipcRenderer?.on(\"open-projection-manager\", () => {\r\n handleOpen();\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n // Load default projection for debug purposes\r\n clearProjectionValues();\r\n clearAllErrors();\r\n }, []);\r\n\r\n const tabLabel = newProjection ? \"Add New\" : \"Edit Existing\";\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 {/* 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 );\r\n};\r\n","import {configureStore, combineReducers} from '@reduxjs/toolkit';\r\nimport thunk from 'redux-thunk';\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\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});\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 (loadConfig) {\r\n state = action.payload;\r\n }\r\n\r\n if (newProject) {\r\n state = undefined;\r\n }\r\n\r\n let modified = appReducer(state, action);\r\n\r\n if (configInit || newProject) {\r\n modified = appReducer(modified, {\r\n type: \"settings/applySavedDefaults\",\r\n payload: null\r\n });\r\n }\r\n\r\n if (newProject || loadConfig) {\r\n modified = appReducer(modified, {\r\n type: \"project/refreshModified\",\r\n payload: null\r\n });\r\n }\r\n\r\n if (loadConfig) {\r\n appReducer(modified, {\r\n type: \"settings/changeDefaultSettings\",\r\n payload: null\r\n });\r\n }\r\n\r\n return modified;\r\n};\r\n\r\nexport const store = configureStore({\r\n reducer: rootReducer,\r\n middleware: [thunk],\r\n});","import {store} from './redux/store';\r\nimport {defaultProjectTitle, changeName, changePath, currentConfigVersion} from './redux/project-slice';\r\nimport {dialog, fs, app, isStaticSite, ipcRenderer} from './electron-modules';\r\nimport slash from 'slash';\r\nimport path from 'path';\r\nimport {isEqual} from 'lodash';\r\n\r\nexport const projectFileType = \"json\";\r\nconst filterFilter = [{name: 'Engine Viewer Projects', extensions: [projectFileType]}];\r\n\r\nexport const saveProjectAs = () => {\r\n return dialog.showSaveDialog({\r\n title: \"Save Project\",\r\n defaultPath: `${store.getState().project.name}.json`,\r\n filters: filterFilter,\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 // update the title of the project to the filename\r\n if (store.getState().project.name === defaultProjectTitle) {\r\n // get filename from path\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(changeName(nameWithoutExt));\r\n }\r\n\r\n const state = store.getState();\r\n writeProject(state);\r\n return true;\r\n }).catch(() => {\r\n dialog.showErrorBox('Error saving project', 'An error occurred while saving the project.');\r\n return false;\r\n });\r\n};\r\n\r\nexport const saveProject = (allowSaveAs = true) => {\r\n return new Promise(resolve => {\r\n const 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(state);\r\n resolve(true);\r\n }\r\n });\r\n};\r\n\r\nexport const loadProjectJSON = (data) => {\r\n const projectJSON = JSON.parse(data);\r\n\r\n store.dispatch({\r\n type: 'LOAD',\r\n payload: projectJSON\r\n });\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 const jsonConfigVersion = projectJSON.project.configVersion;\r\n\r\n // Update the loadJSON state\r\n projectJSON.assets.forEach((asset, index) => {\r\n projectJSON.assets[index].fromJSON = true;\r\n });\r\n\r\n if (jsonConfigVersion !== currentConfigVersion) {\r\n const versionOld = (jsonConfigVersion % 1.0 === 0.0)\r\n ? jsonConfigVersion.toFixed(1)\r\n : jsonConfigVersion;\r\n\r\n const versionNew = (currentConfigVersion % 1.0 === 0.0)\r\n ? currentConfigVersion.toFixed(1)\r\n : currentConfigVersion;\r\n\r\n alert(`Invalid config version (${versionOld}). Latest version is ${versionNew}`);\r\n return false;\r\n }\r\n\r\n const projectString = JSON.stringify(projectJSON);\r\n loadProjectJSON(projectString);\r\n return true;\r\n } catch (err) {\r\n alert('Error loading project');\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: filterFilter\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 = () => {\r\n dialog.showMessageBox({\r\n type: 'question',\r\n title: 'Create new project?',\r\n message: 'Any unsaved changes to your current project will be lost.',\r\n buttons: ['Cancel', 'Create new project'],\r\n noLink: true\r\n }).then(result => {\r\n if (result.response === 0) {\r\n return;\r\n }\r\n\r\n store.dispatch({type: 'NEW'});\r\n });\r\n};\r\n\r\nconst writeProject = (state) => {\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\nif (!isStaticSite) {\r\n ipcRenderer.on(\"save-project\", () => {\r\n const state = store.getState();\r\n\r\n if (state.project.path !== \"\") {\r\n const data = fs.readFileSync(state.project.path, \"utf8\");\r\n let projectJSON = JSON.parse(data);\r\n projectJSON.project.modified = state.project.modified;\r\n }\r\n\r\n saveProject().then((saved) => {\r\n\r\n if (saved) {\r\n app.exit();\r\n }\r\n });\r\n });\r\n\r\n ipcRenderer.on(\"project-changed\", () => {\r\n const state = store.getState();\r\n let hasChanged;\r\n\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 projectJSON.project.modified = state.project.modified;\r\n hasChanged = !isEqual(state, projectJSON);\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 ipcRenderer.send('should-save', hasChanged);\r\n });\r\n}\r\n","import React, {useEffect, useState} from 'react';\r\nimport Button from '@material-ui/core/Button';\r\nimport IconButton from '@material-ui/core/IconButton';\r\nimport {createStyles, makeStyles, Theme} from \"@material-ui/core/styles\";\r\nimport {Checkbox} from \"@material-ui/core\";\r\nimport ControlPointIcon from '@material-ui/icons/ControlPoint';\r\nimport EnhancedTable from '../enhanced-table';\r\nimport DialogActions from '@material-ui/core/DialogActions';\r\nimport DialogContent from '@material-ui/core/DialogContent';\r\nimport Typography from '@material-ui/core/Typography';\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport { AlertDialog, DraggableDialog, PromptDialog } from '../dialogs';\r\nimport { PythonExecutable } from '../executable';\r\nimport { app, csv, ipcRenderer} from '../electron-modules';\r\nimport {saveMatrixFile} from '../camera-utils';\r\nimport { useSnackbar } from 'notistack';\r\nimport { Box, DialogContentText } from '@material-ui/core';\r\nimport clsx from 'clsx';\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 { saveProject } from '../project-utils';\r\nimport { selectAllAssets, getCameraFileAssets } from '../redux/assets-slice';\r\nimport { Viewer } from '../viewer/js/main';\r\nimport { pointObsColor, imageObsColor } from '../viewer/js/image-aligner/image-aligner';\r\nimport LocalScene from '../viewer/js/projections';\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 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 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 panel: {\r\n background: \"rgba(200,200,200,0.1)\"\r\n },\r\n success: {\r\n color: theme.palette.success.main\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 assetCheckbox: {\r\n position: \"relative\",\r\n transform: \"translateY(0%)\"\r\n },\r\n checkboxPadding: {\r\n padding: \"0px\"\r\n }\r\n }),\r\n);\r\n\r\nconst PointObservationIcon = (props) => {\r\n return ObservationIcon(props, 'point');\r\n};\r\n\r\nconst ImageObservationIcon = (props) => {\r\n return ObservationIcon(props, 'image');\r\n};\r\n\r\n\r\nconst ObservationIcon = (props, type) => {\r\n const {color} = props;\r\n const classes = useStyles();\r\n\r\n return (\r\n \r\n \r\n \r\n );\r\n};\r\n\r\nconst ResidualError = (props) => {\r\n const {value} = props;\r\n const classes = useStyles();\r\n return (\r\n = lowCutoff),\r\n [classes.errorHigh]: (value >= highCutoff)\r\n })}>\r\n {value}\r\n \r\n );\r\n};\r\n\r\nexport const ImageAlignerAdvanced = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {addObservations, setDefaultTab, setTabsEnabled,\r\n observationType, setObservationType, alignerAdvOpen,\r\n alignerBasicOpen, setAlignerAdvOpen} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const [rows, setRows] = useState([]);\r\n const [csvPath, setCsvPath] = useState(\"\");\r\n const [encompassCsvPath, setEncompassCsvPath] = useState(\"\");\r\n const [aligned, setAligned] = useState(false);\r\n const [alignmentConfirm, setAlignmentConfirm] = useState(false);\r\n const [alignerMatrixPath, setAlignerMatrixPath] = useState(null);\r\n const [valid, setValid] = useState(false);\r\n const [tableNonEmpty, setTableNonEmpty] = useState(false);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [isAligned, setIsAligned] = useState(false);\r\n const [alertOpen, setAlertOpen] = useState(false);\r\n const [askRemoveOpen, setAskRemoveOpen] = useState(false);\r\n const [alignPosition, setAlignPosition] = useState(true);\r\n const [alignRotation, setAlignRotation] = useState(true);\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 columns = [\r\n {id: 'obs_num', numeric: true, label: '#'},\r\n {id: 'name', numeric: false, label: 'Filename'},\r\n {id: 'img_obs', numeric: false, label: 'Image Control'},\r\n {id: 'pc_obs', numeric: false, label: 'Point Control'},\r\n {id: 'error', numeric: true, label: 'Error(\\u00B0)'},\r\n ];\r\n\r\n const handleOpen = () => {\r\n if (alignerBasicOpen) {\r\n setAlertOpen(true);\r\n return;\r\n }\r\n\r\n setAlignerAdvOpen(true);\r\n setDefaultTab();\r\n };\r\n\r\n const handleClose = () => {\r\n setAlignerAdvOpen(false);\r\n };\r\n\r\n const handleAlertClose = () => {\r\n setAlertOpen(false);\r\n };\r\n\r\n const resetRowsAndMesh = () => {\r\n setRows([]);\r\n generateRows(requiredRows);\r\n };\r\n\r\n const exportCSV = () => {\r\n let appPath = app.getPath('userData');\r\n let csvPath = appPath + '/alignTemp.csv';\r\n let csvOut = [];\r\n csvOut.push(['filename',\r\n 'x_img', 'y_img', 'z_img',\r\n 'x_ground', 'y_ground', 'z_ground']);\r\n for (let i=0; i console.error(err))\r\n .on('finish', () => console.log('Done writing.'));\r\n setCsvPath(csvPath);\r\n\r\n let csvEncompassPath = appPath + '/encompassTemp.csv';\r\n let csvEncompassOut = [];\r\n csvEncompassOut.push(['filename',\r\n 'X', 'Y', 'Z',\r\n 'Roll', 'Pitch', 'Yaw']);\r\n for (let i=0; i< viewer.getNumEntriesCameraAligner(); i++) {\r\n csvEncompassOut.push(viewer.getCamPoseCameraAligner(i));\r\n }\r\n csv.writeToPath(csvEncompassPath, csvEncompassOut)\r\n .on('error', err => console.error(err))\r\n .on('finish', () => console.log('Done writing.'));\r\n setEncompassCsvPath(csvEncompassPath);\r\n };\r\n\r\n const projectionUnits = LocalScene.dataProjectionUnits;\r\n const runAlignerPython =() => {\r\n let exe = new PythonExecutable();\r\n let commands = [\r\n \"-p\", \"camera_aligner_advanced\",\r\n \"--csv_obs\", csvPath,\r\n \"--csv_encompass\", encompassCsvPath,\r\n \"--sulphur\", \"True\",\r\n \"--align_position\", alignPosition ? \"True\" : \"False\",\r\n \"--align_rotation\", alignRotation ? \"True\" : \"False\",\r\n \"--units\", projectionUnits\r\n ];\r\n \r\n let isConverted = false;\r\n let camPoseEntry = viewer.getCamPoseCameraAligner(0);\r\n let largeResiduals = false;\r\n\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 (async () => {\r\n new PythonExecutable().run({\r\n command: ['--check-tool', 'aligner-advanced']\r\n });\r\n })();\r\n\r\n exe.run({\r\n command: commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n let residualsTemp = parseResiduals(jsonData);\r\n if (residualsTemp.length !== 0) {\r\n viewer?.setErrorsCameraAligner(residualsTemp);\r\n isConverted = true;\r\n }\r\n residualsTemp.forEach(res => {\r\n if (res >= highCutoff) {\r\n largeResiduals = true;\r\n }\r\n });\r\n },\r\n onClose: () => {\r\n try {\r\n if (isConverted) {\r\n showMessage(\"Alignment Adjustment Complete!\", {\r\n variant: \"success\"\r\n });\r\n setAlignerMatrixPath(correctionPath);\r\n setAligned(true);\r\n updateRows(resetRowIcons());\r\n if (largeResiduals) {\r\n showMessage(\"Large errors in alignment correction\", {\r\n variant: \"warning\"\r\n });\r\n }\r\n } else {\r\n showMessage(\"Alignment Correction experienced a problem and did not apply a correction\", {\r\n variant: \"error\"\r\n });\r\n }\r\n }\r\n catch (err) {\r\n showMessage(\"Alignment Correction experienced a problem and did not apply a correction\", {\r\n variant: \"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 emptyObservation = (index) => {\r\n return {\r\n id: index,\r\n obs_num: index+1,\r\n name: \"No File\",\r\n img_obs: ,\r\n pc_obs: ,\r\n error: 0\r\n };\r\n };\r\n\r\n const generateRows = (rowNum) => {\r\n viewer?.resetCameraAligner();\r\n\r\n let rowsTemp = [];\r\n for (let i=0; i {\r\n let tempRows = [...rows];\r\n\r\n for (let i=0; i {\r\n if (tempRows.length === 0) {\r\n return;\r\n }\r\n\r\n for (let i=0; i;\r\n }\r\n\r\n setRows(tempRows);\r\n };\r\n\r\n const onDeleteClick = (row) => {\r\n if (rows.length === 1) {\r\n resetRowsAndMesh();\r\n return;\r\n }\r\n let tempRows = resetRowIcons();\r\n viewer.deleteRowCameraAligner(row.id);\r\n tempRows.splice(row.id, 1);\r\n updateRows(tempRows);\r\n setObservationType(\"none\");\r\n showMessage(\"Aligner Entry Deleted\", {\r\n variant: \"error\"\r\n });\r\n setAlignmentConfirm(false);\r\n if (aligned) {\r\n cancelCurrentAlignment();\r\n setValid(false);\r\n }\r\n };\r\n\r\n const resetRowIcons = () => {\r\n let tempRows = [...rows];\r\n\r\n for (let i=0; i;\r\n\r\n const hasPointObs = viewer.getPointObsCameraAligner(i) != null;\r\n tempRows[i].pc_obs = ;\r\n }\r\n\r\n return tempRows;\r\n };\r\n\r\n const onRowClick = (row, index) => {\r\n if (index > 3 || index < 2){\r\n setObservationType(\"none\");\r\n viewer.setCurrentRowCameraAligner(-1);\r\n let camID = viewer.getCamIdFromAligner(row.id);\r\n const position = viewer.getObservationPosition(row.id);\r\n viewer.setCameraVisible(camID, {position});\r\n viewer.flashObservations(row.id);\r\n } else if (index === 2){\r\n if (aligned || viewer?.checkIfAligned()) {\r\n cancelCurrentAlignment();\r\n setValid(false);\r\n }\r\n\r\n let tempRows = resetRowIcons();\r\n tempRows[row.id].img_obs = ;\r\n\r\n updateRows(tempRows);\r\n\r\n setObservationType(\"image\");\r\n viewer.setCurrentRowCameraAligner(row.id);\r\n viewer.hideCurrentObservation('image', row.id);\r\n setAlignmentConfirm(false);\r\n } else if (index === 3) {\r\n if (aligned || viewer?.checkIfAligned()) {\r\n cancelCurrentAlignment();\r\n setValid(false);\r\n }\r\n\r\n let tempRows = resetRowIcons();\r\n\r\n tempRows[row.id].pc_obs = ;\r\n updateRows(tempRows);\r\n\r\n setObservationType(\"point\");\r\n viewer.setCurrentRowCameraAligner(row.id);\r\n viewer.hideCurrentObservation('point', row.id);\r\n setAlignmentConfirm(false);\r\n }\r\n };\r\n\r\n const cancelCurrentAlignment = () => {\r\n setAligned(false);\r\n setIsAligned(false);\r\n setAlignmentConfirm(false);\r\n setAlignerMatrixPath(null);\r\n dispatch(changeCameraTransform(null));\r\n showMessage(`Alignment Cleared`, {\r\n variant: \"success\"\r\n });\r\n };\r\n\r\n const onClearAlignments = () => {\r\n dispatch(changeBasicAdjustments({}));\r\n viewer?.resetBasicAlignerCamera();\r\n saveProject(false);\r\n cancelCurrentAlignment();\r\n };\r\n\r\n const confirmAlignment = () => {\r\n dispatch(changeCameraTransform(alignerMatrixPath));\r\n setAlignmentConfirm(true);\r\n };\r\n\r\n const handleAlignPositionCheck = () => {\r\n setAlignPosition(!alignPosition);\r\n };\r\n\r\n const handleAlignRotationCheck = () => {\r\n setAlignRotation(!alignRotation);\r\n };\r\n\r\n const checkRowsValid = () => {\r\n if (rows.length < requiredRows) {\r\n setValid(false);\r\n setTableNonEmpty(false);\r\n return false;\r\n }\r\n\r\n if (!viewer.getNumEntriesCameraAligner()){\r\n setValid(false);\r\n return false;\r\n }\r\n\r\n if (viewer === null) {\r\n setValid(false);\r\n setTableNonEmpty(false);\r\n return false;\r\n }\r\n\r\n let validCheck = true;\r\n let nonEmpty = false;\r\n for (let i=0; i < rows.length; i++) {\r\n let imgCheck = (viewer?.getImageObsCameraAligner(i) != null);\r\n let pointCheck = (viewer?.getPointObsCameraAligner(i) != null);\r\n let validTemp = (imgCheck && pointCheck);\r\n validCheck = (validCheck && validTemp);\r\n nonEmpty = (imgCheck || pointCheck || nonEmpty);\r\n }\r\n setValid(validCheck);\r\n setTableNonEmpty(nonEmpty);\r\n return validCheck;\r\n };\r\n\r\n const checkClose = () => {\r\n if (tableNonEmpty) {\r\n setClosePrompt(true);\r\n } else {\r\n handleClose();\r\n }\r\n };\r\n\r\n useEffect(() => {\r\n ipcRenderer?.removeAllListeners(\"open-image-aligner-adv\");\r\n ipcRenderer?.on(\"open-image-aligner-adv\", handleOpen);\r\n }, [alignerBasicOpen]);\r\n\r\n useEffect(() => {\r\n if (viewer) {\r\n generateRows(requiredRows);\r\n }\r\n }, [viewer]);\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 setAskRemoveOpen(true);\r\n }\r\n }, [currentCamera]);\r\n\r\n useEffect(() => {\r\n if (addObservations) {\r\n showMessage(`New ${observationType} observation added`, {\r\n variant: \"success\"\r\n });\r\n updateRows(resetRowIcons());\r\n setObservationType(\"none\");\r\n checkRowsValid();\r\n }\r\n }, [addObservations]);\r\n\r\n useEffect(() => {\r\n if (!viewer) {\r\n return;\r\n }\r\n\r\n viewer?.setObservationTypeCameraAligner(observationType);\r\n if (observationType===\"none\") {\r\n updateRows(resetRowIcons());\r\n }\r\n }, [viewer, observationType]);\r\n\r\n useEffect(() => {\r\n if (!alignerAdvOpen) {\r\n resetRowsAndMesh();\r\n }\r\n\r\n setTabsEnabled(!alignerAdvOpen);\r\n viewer?.toggleCameraAligner(alignerAdvOpen);\r\n }, [viewer, alignerAdvOpen]);\r\n\r\n useEffect(() => {\r\n let validCheck = checkRowsValid();\r\n if (validCheck) {\r\n exportCSV();\r\n }\r\n }, [rows]);\r\n\r\n useEffect(() => {\r\n setIsAligned(viewer?.checkIfAligned() || hasBasicAlignment);\r\n }, [viewer, alignerAdvOpen, aligned, isAligned]);\r\n\r\n useEffect(() => {\r\n if (alignerAdvOpen && !alignRotation && !alignPosition) {\r\n showMessage(\"At least one of Align Position and Align Rotation must be enabled\", {\r\n variant: \"warning\"\r\n });\r\n setAlignPosition(true);\r\n setAlignRotation(true);\r\n }\r\n\r\n }, [alignPosition, alignRotation]);\r\n\r\n const hasBasicAlignment = Object.keys(basicAdjustments).length !== 0;\r\n\r\n return (\r\n \r\n\r\n \r\n \r\n\r\n {(!isAligned) && (\r\n Select at least ({requiredRows}) corresponding points in both image and point cloud to align data.\r\n More observations may help give a better final result.\r\n )}\r\n\r\n {(isAligned) && (\r\n Image and Point Cloud data currently have a set alignment. Current Alignment must be cleared\r\n before adding observations.\r\n )}\r\n\r\n {(!isAligned) && }\r\n \r\n\r\n \r\n {rows.length === 0 && (\r\n \r\n )}\r\n\r\n {(!isAligned) && (rows.length >= 1) &&\r\n ((alignmentConfirm === false)) && (\r\n \r\n )}\r\n\r\n {(valid === true) && (aligned === false) && (\r\n \r\n )}\r\n\r\n {(aligned === true) && (alignmentConfirm === true) && (\r\n \r\n )}\r\n\r\n {(aligned === true) && (\r\n \r\n )}\r\n\r\n {(aligned === false) && (isAligned === true) && (\r\n \r\n )}\r\n\r\n {(aligned === true) && (alignmentConfirm === false) && (\r\n \r\n )}\r\n\r\n \r\n\r\n {!isAligned && (\r\n\r\n {/* Calculate lever arm */}\r\n
\r\n \r\n Align Position\r\n \r\n \r\n
\r\n\r\n {/* Calculate rotation */}\r\n
\r\n \r\n Align Rotation\r\n \r\n \r\n
\r\n\r\n
)}\r\n \r\n\r\n setClosePrompt(false)}\r\n onSubmit={() => {\r\n handleClose();\r\n setClosePrompt(false);\r\n }}\r\n title=\"Close Aligner?\"\r\n prompt={`Do you want to close the Data Aligner? All observations will be lost.`}\r\n button=\"Close\"\r\n />\r\n\r\n setAskRemoveOpen(false)}\r\n onSubmit={() => {\r\n dispatch(changeCameraTransform(null));\r\n setAskRemoveOpen(false);\r\n }}\r\n title=\"Remove Alignment Matrix?\"\r\n prompt={`All cameras have been removed. Do you want to remove the current camera\r\n correction matrix? If the existing matrix is not removed it will automatically\r\n be applied to all new CSVs.`}\r\n button=\"Remove Matrix\"\r\n />\r\n\r\n \r\n \r\n Unable to open advanced data aligner if basic mode is open\r\n \r\n \r\n
\r\n );\r\n};\r\n","import React, {useEffect, useState} from 'react';\r\nimport { createStyles, makeStyles, Theme } from \"@material-ui/core/styles\";\r\nimport { useSnackbar } from 'notistack';\r\nimport {\r\n Box,\r\n Button,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n Grid,\r\n Typography\r\n} from '@material-ui/core';\r\nimport { AlertDialog, DraggableDialog, PromptDialog } from '../dialogs';\r\nimport { ipcRenderer } from '../electron-modules';\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 '../project-utils';\r\nimport { PythonExecutable } from \"../executable\";\r\nimport { Viewer } from '../viewer/js/main';\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 return (\r\n \r\n \r\n \r\n \r\n Adjust Roll (-): Keypad 7\r\n \r\n \r\n\r\n \r\n \r\n Adjust Roll (+): Keypad 9\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n Adjust Pitch (-): Keypad 4\r\n \r\n \r\n\r\n \r\n \r\n Adjust Pitch (+): Keypad 6\r\n \r\n \r\n \r\n\r\n \r\n \r\n \r\n Adjust Yaw (-): Keypad 1\r\n \r\n \r\n\r\n \r\n \r\n Adjust Yaw (+): Keypad 3\r\n \r\n \r\n \r\n \r\n );\r\n};\r\n\r\nexport const ImageAlignerBasic = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {setDefaultTab, setTabsEnabled, singleAlignment,\r\n alignerBasicOpen, alignerAdvOpen, setAlignerBasicOpen} = props;\r\n\r\n const classes = useStyles();\r\n const dispatch = useDispatch();\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const [alertOpen, setAlertOpen] = useState(false);\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 handleOpen = () => {\r\n if (alignerAdvOpen) {\r\n setAlertOpen(true);\r\n return;\r\n }\r\n\r\n setAlignerBasicOpen(true);\r\n setDefaultTab();\r\n };\r\n\r\n const handleClose = () => {\r\n setAlignerBasicOpen(false);\r\n setClosePrompt(false);\r\n };\r\n\r\n const handleAlertClose = () => {\r\n setAlertOpen(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\r\n showMessage(`Alignment Reset`, {\r\n variant: \"success\"\r\n });\r\n };\r\n\r\n const saveAdjustment = () => {\r\n const updated = {...basicAdjustments};\r\n updated[currentCamera] = alignment;\r\n dispatch(changeBasicAdjustments(updated));\r\n viewer?.resetBasicAlignerCamera(alignment);\r\n saveProject(false);\r\n\r\n (async () => {\r\n new PythonExecutable().run({\r\n command: ['--check-tool', 'aligner-basic']\r\n });\r\n })();\r\n\r\n showMessage(`Alignment Saved`, {\r\n variant: \"success\"\r\n });\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) {\r\n return false;\r\n }\r\n\r\n const epsilon = 1e-10;\r\n const dx = (savedAngle[0] - singleAlignment[0]) < epsilon;\r\n const dy = (savedAngle[1] - singleAlignment[1]) < epsilon;\r\n const dz = (savedAngle[2] - singleAlignment[2]) < epsilon;\r\n\r\n return !(dx && dy && dz);\r\n };\r\n\r\n useEffect(() => {\r\n ipcRenderer?.removeAllListeners(\"open-image-aligner-basic\");\r\n ipcRenderer?.on(\"open-image-aligner-basic\", handleOpen);\r\n }, [alignerAdvOpen]);\r\n\r\n useEffect(() => {\r\n setHasTransform(cameraTransformPath !== null);\r\n }, [viewer, cameraTransformPath]);\r\n\r\n useEffect(() => {\r\n setTabsEnabled(!alignerBasicOpen);\r\n const enabled = hasActiveCamera && alignerBasicOpen;\r\n viewer?.setBasicAlignerState(enabled);\r\n }, [viewer, alignerBasicOpen, currentCamera]);\r\n\r\n useEffect(() => {\r\n // Not applicable if transform matrix is applied\r\n if (hasTransform) {\r\n return;\r\n }\r\n\r\n viewer?.resetBasicAlignerCamera(savedAngle);\r\n }, [viewer, currentCamera]);\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 A global transformation is currently applied. Current alignment must be cleared\r\n before adding per-camera corrections\r\n )}\r\n\r\n {(hasTransform === false) && (\r\n {/* Current camera section */}\r\n \r\n \r\n Current Camera:\r\n \r\n\r\n \r\n {hasActiveCamera ? activeCameraName : \"No Camera Selected\"}\r\n \r\n \r\n\r\n {/* Current adjustment section */}\r\n \r\n \r\n Current Adjustment:\r\n \r\n\r\n \r\n {hasActiveCamera ? `[${alignment[0]}, ${alignment[1]}, ${alignment[2]}]` : \"N/A\"}\r\n \r\n \r\n\r\n {/* Current adjustment section */}\r\n \r\n \r\n Alignment Status:\r\n \r\n\r\n \r\n {isModified ? \"Modified\" : \"Saved\"}\r\n \r\n \r\n\r\n {/* Alignment shortcut keys */}\r\n \r\n \r\n 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 Reset Values\r\n \r\n\r\n \r\n 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=\"Close Aligner?\"\r\n prompt={`Do you want to close the data aligner? Current modifications will not be saved.`}\r\n button=\"Close\"\r\n />\r\n\r\n \r\n \r\n Unable to open basic data aligner if advanced mode is open\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 '@material-ui/core';\r\nimport { roundDigit } from './viewer/js/misc';\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 {\r\n createStyles,\r\n IconButton,\r\n makeStyles,\r\n Theme\r\n} from \"@material-ui/core\";\r\nimport clsx from 'clsx';\r\nimport React from \"react\";\r\nimport { ArrowTooltip } from \"./tooltips\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n disabled: {\r\n opacity: 0.3\r\n }\r\n })\r\n);\r\n\r\nexport const EnhancedIconButton = (props) => {\r\n const classes = useStyles();\r\n const {title, visible, onClick, disabled, children} = props;\r\n\r\n const isVisible = visible !== undefined ? visible : true;\r\n const tooltipText = disabled ? `${title} (Disabled)` : title;\r\n\r\n const createMarkup = () => {\r\n return tooltipText ?\r\n (
) :\r\n \"\";\r\n };\r\n\r\n return (\r\n \r\n {isVisible && (\r\n \r\n {children}\r\n \r\n )}\r\n \r\n );\r\n};\r\n","import React, {useEffect, useState} from 'react';\r\nimport { useSelector, useDispatch } from 'react-redux';\r\nimport {ProgressDialog, TextDialog} from \"../dialogs\";\r\nimport CloseIcon from '@material-ui/icons/Close';\r\nimport CheckIcon from '@material-ui/icons/Check';\r\nimport EditIcon from '@material-ui/icons/Edit';\r\nimport WarningIcon from '@material-ui/icons/Warning';\r\nimport PriorityHighIcon from '@material-ui/icons/PriorityHigh';\r\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\r\nimport ExpandLessIcon from '@material-ui/icons/ExpandLess';\r\nimport AddToPhotosIcon from '@material-ui/icons/AddToPhotos';\r\nimport DeleteIcon from '@material-ui/icons/Delete';\r\nimport ZoomInIcon from '@material-ui/icons/ZoomIn';\r\nimport {\r\n Box,\r\n Card,\r\n CardHeader,\r\n CircularProgress,\r\n Dialog,\r\n DialogContent,\r\n List,\r\n ListItem,\r\n Typography\r\n} from '@material-ui/core';\r\nimport { DraggableDialog, PromptDialog } from '../dialogs';\r\nimport { createStyles, makeStyles, Theme } from \"@material-ui/core/styles\";\r\nimport { app, dialog, ipcRenderer, fs } from '../electron-modules';\r\nimport { useSnackbar } from 'notistack';\r\nimport { changeSwitched } from \"../redux/settings-slice\";\r\nimport { textToColor } from '../viewer/js/labelling/categories';\r\nimport { ArrowTooltip } from '../tooltips';\r\nimport { DenseDivider, IconToolBar, SlimScrollbar, ToolBarButton } from '../toolbar';\r\nimport slash from 'slash';\r\nimport { PythonExecutable } from '../executable';\r\nimport { Viewer } from '../viewer/js/main';\r\nimport LocalScene from '../viewer/js/projections';\r\nimport { FixedSizeList } from \"react-window\";\r\nimport { LinearProgressWithLabel } from '../progress';\r\nimport path from 'path';\r\nimport { EnhancedIconButton } from '../buttons';\r\nimport { AssetType, getCameraFileAssets, selectAllAssets } from '../redux/assets-slice';\r\n\r\nconst labelExtension = \"3dl\";\r\nconst modelExtension = \"pth\";\r\nconst dxfExtension = \"dxf\";\r\nconst labelFilter = [{name: 'Engine Label File', extensions: [labelExtension]}];\r\nconst modelFilter = [{name: 'Engine Trained Model File', extensions: [modelExtension]}];\r\nconst dxfFilter = [{name: 'DXF File', extensions: [dxfExtension]}];\r\nconst labelHeight = 46;\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 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 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: \"10px\"\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 labelTitle: {\r\n flex: 1,\r\n userSelect: \"none\"\r\n },\r\n labelTitleWarning: {\r\n flex: 1,\r\n userSelect: \"none\",\r\n color: theme.palette.warning.main\r\n },\r\n labelTitleError: {\r\n flex: 1,\r\n userSelect: \"none\",\r\n color: theme.palette.error.main\r\n },\r\n card: {\r\n marginTop: theme.spacing(1),\r\n marginBottom: theme.spacing(2),\r\n marginLeft: theme.spacing(4),\r\n marginRight: theme.spacing(4),\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(4.0),\r\n color: theme.palette.warning.main\r\n }\r\n }),\r\n);\r\n\r\nconst Label = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {label, index, isScrolling, style, labelName} = props;\r\n\r\n const classes = useStyles();\r\n const selected = label.selected;\r\n const completed = label.completed;\r\n const hasEnoughPoints = label.hasEnoughPoints;\r\n\r\n let labelTitle = label.highlighted\r\n ? classes.labelTitleWarning\r\n : classes.labelTitle;\r\n\r\n const selectLabel = (id) => {\r\n viewer?.selectLabel(id);\r\n };\r\n\r\n const completeLabel = (id) => {\r\n viewer?.completeLabel(id);\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 {`${labelName} #${index + 1} (${label.numPoints})`}\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 {/* Complete Label */}\r\n {\r\n completeLabel(label.id);\r\n }}\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 {/* Edit Label */}\r\n {\r\n selectLabel(label.id);\r\n }}\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 {/* Delete Label */}\r\n {\r\n deleteLabel(label.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n )}\r\n\r\n \r\n );\r\n};\r\n\r\nconst TrainingArea = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {trainingArea} = props;\r\n\r\n const color = textToColor(trainingArea.name);\r\n const scrollingDivLength = trainingArea.labels.length;\r\n const useScrollingDiv = scrollingDivLength > 100;\r\n const scrollingDivHeight = Math.min(scrollingDivLength*labelHeight, 250);\r\n\r\n const classes = useStyles();\r\n const [expanded, setExpanded] = useState(false);\r\n const [deletePrompt, setDeletePrompt] = useState(false);\r\n\r\n const deleteTrainingArea = () => {\r\n viewer?.deleteTrainingAreas();\r\n setDeletePrompt(false);\r\n };\r\n\r\n const addThenExpand = (trainingAreaID) => {\r\n addLabel(trainingAreaID);\r\n setExpanded(true);\r\n };\r\n\r\n const addLabel = (id) => {\r\n viewer?.addTrainingAreaLabel();\r\n };\r\n\r\n const addNewlabelTooltip = `\r\n Add new training area\r\n
Press space to add new\r\n
area to Training Areas\r\n `;\r\n\r\n return (\r\n \r\n \r\n {/* Header */}\r\n \r\n {/* Expand/collapse measurement */}\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 {/* Add new area label */}\r\n {\r\n addThenExpand(trainingArea.id);\r\n }}\r\n >\r\n \r\n \r\n\r\n {/* Delete TrainingArea */}\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 Training Areas\r\n \r\n }\r\n subheader={\r\n \r\n {`Total Areas: ${trainingArea.labels.length}`}\r\n \r\n }\r\n />\r\n\r\n {/* Expandable content */}\r\n {expanded && (\r\n {/* Use normal list for small labels list */}\r\n {!useScrollingDiv && (\r\n \r\n {trainingArea.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 {expanded && useScrollingDiv && (\r\n \r\n {({index, isScrolling, style}) => (\r\n \r\n )}\r\n \r\n )}\r\n )}\r\n \r\n\r\n setDeletePrompt(false)}\r\n onSubmit={deleteTrainingArea}\r\n title=\"Delete Training Areas?\"\r\n prompt={`Do you want to delete all Training Areas?`}\r\n button=\"Delete\"\r\n />\r\n\r\n \r\n );\r\n};\r\n\r\nconst Category = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {category, isValidCategory} = props;\r\n\r\n const classes = useStyles();\r\n const [expanded, setExpanded] = useState(false);\r\n const [editPrompt, setEditPrompt] = useState(false);\r\n const [deletePrompt, setDeletePrompt] = useState(false);\r\n\r\n const formatName = (name) => {\r\n return (name.length > 12) ? name.substr(0,11) + \"...\" : 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 activeLabel = () => {\r\n return viewer?.checkIfSelected();\r\n };\r\n\r\n const addNewLabelDisabled = activeLabel();\r\n const addNewlabelTooltip = `\r\n Add new label\r\n
Press space to add new\r\n
label to ${viewer.currentCategory()} category\r\n `;\r\n\r\n const color = textToColor(category.name);\r\n const scrollingDivLength = category.labels.length;\r\n const useScrollingDiv = scrollingDivLength >= 25;\r\n const scrollingDivHeight = Math.min(scrollingDivLength*labelHeight, 250);\r\n\r\n return (\r\n \r\n \r\n {/* Header */}\r\n \r\n {/* Expand/collapse measurement */}\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 {/* 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 {`Total Labels: ${category.labels.length}`}\r\n \r\n }\r\n />\r\n\r\n {/* Expandable content */}\r\n {expanded && (\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 {expanded && useScrollingDiv && (\r\n \r\n {({index, isScrolling, style}) => (\r\n \r\n )}\r\n \r\n )}\r\n )}\r\n\r\n \r\n\r\n setEditPrompt(false)}\r\n onSubmit={handleEditCategory}\r\n title=\"Edit Class\"\r\n prompt=\"Enter new class name\"\r\n default={category.name}\r\n label=\"Class Name\"\r\n clear={true}\r\n />\r\n\r\n setDeletePrompt(false)}\r\n onSubmit={handleDeleteCategory}\r\n title=\"Delete Class?\"\r\n prompt={`Do you want to delete this class (${category.name})? All labels will be removed`}\r\n button=\"Delete\"\r\n />\r\n \r\n );\r\n};\r\n\r\nexport const ImageLabelling = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {setDefaultTab, setTabsEnabled, categoryList, trainingArea,\r\n imageLabelOpen, setImageLabelOpen} = props;\r\n\r\n\r\n const classes = useStyles();\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n const dispatch = useDispatch();\r\n\r\n const [labelType, setLabelType] = useState(null);\r\n const [minimized, setMinimized] = useState(null);\r\n const [addCategory, setAddCategory] = useState(false);\r\n const [closePrompt, setClosePrompt] = useState(false);\r\n const [importData, setImportData] = useState(null);\r\n const [modalName, setModalName] = useState(\"\");\r\n const [labelLoadProgress, setLabelLoadProgress] = useState(0);\r\n const [trainClassifyProgress, setTrainClassifyProgress] = useState(0);\r\n const [trainClassifyExe, setTrainClassifyExe] = useState(null);\r\n const [predOrTrain, setPredOrTrain] = useState(\"\");\r\n const [classification, setClassification] = 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 assets = useSelector(selectAllAssets);\r\n const cameraFiles = getCameraFileAssets(assets);\r\n\r\n const isOrthoLabel = labelType === \"ortho\";\r\n const isSceneLabel = labelType === \"scene\";\r\n const importPrompt = importData !== null;\r\n const importCategories = importData?.categories.map(x => x.name);\r\n const numPanoramics = cameraFiles.filter(x => x.type === AssetType.Panoramic).length;\r\n const numPlanars = cameraFiles.filter(x => x.type === AssetType.Planar).length;\r\n\r\n let numImportLabels = 0;\r\n importData?.annotations.forEach(label => {\r\n numImportLabels += label.segmentation.length;\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 setClassification(false);\r\n };\r\n\r\n const handleOpen = (type) => {\r\n setImageLabelOpen(true);\r\n setLabelType(type);\r\n };\r\n\r\n const handleClose = () => {\r\n setImageLabelOpen(false);\r\n handleCancelProgress();\r\n };\r\n\r\n const handleImport = async () => {\r\n await viewer.loadImageLabelData(importData, setLabelLoadProgress);\r\n showMessage(`Labels Loaded Successfully...`, {\r\n variant: \"success\"\r\n });\r\n\r\n setImportData(null);\r\n };\r\n\r\n const handleMinimize = () => {\r\n setMinimized(true);\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 showMessage(`Class already exists`, {\r\n variant: \"error\"\r\n });\r\n return false;\r\n }\r\n\r\n // Alphanumeric, dash and underscore\r\n const alphanumeric = /^[a-zA-Z0-9-_]+$/;\r\n if (!alphanumeric.test(name)) {\r\n showMessage(`Invalid class name. Allowed characters are: [a-z, 0-9, _, -]`, {\r\n variant: \"error\"\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const validIterations = (iterations) => {\r\n const numeric = /^[0-9]+$/;\r\n let validChar = numeric.test(iterations);\r\n let iterNumber = parseInt(iterations);\r\n\r\n let minIterations = 10;\r\n let maxIterations = 8192;\r\n let validNumber = (iterNumber >= minIterations)\r\n && (iterNumber <= maxIterations);\r\n\r\n if (!validChar || ! validNumber) {\r\n showMessage(`Invalid iterations. Allowed characters are: [0-9], must be between ${minIterations}-${maxIterations}`, {\r\n variant: \"error\"\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const validScore = (score) => {\r\n const numeric = /^[0-9-.]+$/;\r\n let validChar = numeric.test(score);\r\n let scoreNumber = parseFloat(score);\r\n let validNumber = (scoreNumber >= 0.0 && scoreNumber <= 1.0);\r\n\r\n if (!validChar || ! validNumber) {\r\n showMessage(`Invalid score. Must be between 0.0-1.0`, {\r\n variant: \"error\"\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const addTrainingArea = () => {\r\n viewer?.addTrainingArea();\r\n }\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 handleTrainingPrompt = (iterations) => {\r\n let iterValid = validIterations(iterations);\r\n if (!iterValid){\r\n return;\r\n }\r\n\r\n runTraining(parseInt(iterations));\r\n setTrainingPrompt(false);\r\n };\r\n\r\n const handleClassificationPrompt = (score) => {\r\n let scoreValid = validScore(score);\r\n if (!scoreValid){\r\n return;\r\n }\r\n\r\n runClassification(parseFloat(score));\r\n setClassificationPrompt(false);\r\n };\r\n\r\n const handleCancelProgress = () => {\r\n trainClassifyExe?.destroy();\r\n resetExecutableValues();\r\n };\r\n\r\n const handleViewTraining = (url) => {\r\n ipcRenderer?.send(\"show-training-window\", url);\r\n };\r\n\r\n const exportJSON = (categoryList) => {\r\n // No labels\r\n if (categoryList.length === 0) {\r\n showMessage(`No labels created to export`, {\r\n variant: \"warning\"\r\n });\r\n return;\r\n }\r\n\r\n const name = `${viewer.projectName}.${labelExtension}`;\r\n\r\n dialog.showSaveDialog({\r\n defaultPath: name,\r\n filters: labelFilter,\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n if (result.filePath) {\r\n let savePath = slash(result.filePath);\r\n let json = viewer?.labelObject();\r\n let text = JSON.stringify(json, null, 2);\r\n fs.writeFile(savePath, text, 'utf8', (err) => {\r\n if (err) {\r\n console.log(err);\r\n showMessage(`Failed to export labels`, {\r\n variant: \"error\"\r\n });\r\n }\r\n else {\r\n showMessage(`Image labels saved to ${path.basename(savePath)}`, {\r\n variant: \"success\"\r\n });\r\n console.log(`File written successfully to ${savePath}`);\r\n }\r\n });\r\n }\r\n });\r\n };\r\n\r\n const importImageLabels = () => {\r\n dialog.showOpenDialog({\r\n properties: ['openFile'],\r\n filters: [...labelFilter, ...modelFilter]\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 }).catch(error => {\r\n console.log(error);\r\n });\r\n };\r\n\r\n /** @private */\r\n const importLabelsPTH = (filePath) => {\r\n let exe = new PythonExecutable();\r\n let pythonName = \"extract_coco_from_model\";\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--model_path\", filePath,\r\n ];\r\n\r\n let data;\r\n\r\n exe.run({\r\n command: 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 data = jsonData.coco_data;\r\n }\r\n },\r\n onClose: () => {\r\n setDownloadResourcesDialog(\"\");\r\n\r\n if (data) {\r\n importLabelData(data);\r\n } else {\r\n showMessage(`Error reading image labels file`, {\r\n variant: \"error\"\r\n });\r\n }\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 showMessage(`Error reading image labels file`, {\r\n variant: \"error\"\r\n });\r\n }\r\n };\r\n\r\n /** @private */\r\n const importLabelData = (data) => {\r\n if (data.type !== labelType) {\r\n showMessage(`Label type mismatch: \"${data.type}\"`, {\r\n variant: \"error\"\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 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 canExportDXF = () => {\r\n let jsonData = viewer?.labelObject();\r\n\r\n const noAnnotations = jsonData.annotations.length === 0;\r\n const noImages = jsonData.images.length === 0;\r\n if (noAnnotations || noImages) {\r\n showMessage(`No exportable labels found. Active images are required`, {\r\n variant: \"warning\"\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const runExportDXF = () => {\r\n // No labels\r\n if (categoryList.length === 0) {\r\n showMessage(`No labels created to export`, {\r\n variant: \"warning\"\r\n });\r\n return;\r\n }\r\n\r\n const name = `${viewer.projectName}.${dxfExtension}`;\r\n\r\n dialog.showSaveDialog({\r\n defaultPath: name,\r\n filters: dxfFilter,\r\n }).then(result => {\r\n if (result.canceled) {\r\n return;\r\n }\r\n if (result.filePath) {\r\n let savePath = slash(result.filePath);\r\n let jsonData = viewer?.labelObject();\r\n let text = JSON.stringify(jsonData, null, 2);\r\n let tempCocoPath = path.join(app.getPath('userData'), \"tempLabels.3dl\");\r\n\r\n fs.writeFile(tempCocoPath, text, 'utf8', (err) => {\r\n if (err) {\r\n console.log(err);\r\n showMessage(`Failed to export labels to DXF file`, {\r\n variant: \"error\"\r\n });\r\n }\r\n });\r\n\r\n let exe = new PythonExecutable();\r\n let pythonName = \"coco_to_dxf\";\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--coco_path\", tempCocoPath,\r\n \"--dxf_path\", savePath\r\n ];\r\n\r\n exe.run({\r\n command: commands,\r\n saveLogs: true,\r\n onClose: () => {\r\n try {\r\n showMessage(`DXF file saved to ${savePath}`, {\r\n variant: \"success\"\r\n });\r\n }\r\n catch (err) {\r\n console.log(err);\r\n showMessage(\"DXF file failed to save\", {\r\n variant: \"error\"\r\n });\r\n }\r\n }\r\n });\r\n }\r\n }).catch(error => {\r\n console.log(error);\r\n });\r\n };\r\n\r\n const canRunClassification = () => {\r\n const imagePaths = viewer.loadedImageLabelPaths();\r\n if (imagePaths.length === 0) {\r\n showMessage(`No images found for classification`, {\r\n variant: \"warning\"\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const runClassification = (score) => {\r\n if (training) {\r\n showMessage(`Cannot run Classification until training is complete`, {\r\n variant: \"warning\"\r\n });\r\n return;\r\n }\r\n\r\n resetExecutableValues();\r\n setClassification(true);\r\n\r\n dialog.showOpenDialog({\r\n properties: ['openFile'],\r\n filters: modelFilter\r\n }).then(result => {\r\n if (result.canceled) {\r\n setClassification(false);\r\n return;\r\n }\r\n\r\n try {\r\n let modelPath = slash(result.filePaths[0]);\r\n\r\n if (result.canceled) {\r\n setClassification(false);\r\n return;\r\n }\r\n\r\n try {\r\n let pythonName = \"aerial_image_classification\";\r\n let appPath = app.getPath('userData');\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--image_paths\", viewer.loadedImageLabelPaths(),\r\n \"--output_folder\", appPath,\r\n \"--prediction_model\", modelPath,\r\n \"--proj_string\", LocalScene.dataProjection,\r\n \"--prediction_score_threshold\", score,\r\n ];\r\n\r\n forceInitialProgress();\r\n\r\n let importData;\r\n\r\n let exe = new PythonExecutable();\r\n setTrainClassifyExe(exe);\r\n\r\n exe.run({\r\n command: commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n updateDownloadingResources(jsonData);\r\n\r\n if (jsonData.progress) {\r\n setTrainClassifyProgress(jsonData.progress);\r\n } else {\r\n importData = jsonData;\r\n showMessage(`Classification complete, loading detected labels...`, {\r\n variant: \"success\"\r\n });\r\n }\r\n },\r\n onClose: async () => {\r\n try {\r\n await viewer.loadImageLabelData(importData, setLabelLoadProgress);\r\n showMessage(`Labels Loaded Successfully...`, {\r\n variant: \"success\"\r\n });\r\n }\r\n catch (err) {\r\n showMessage(\"Classification Process not completed\", {\r\n variant: \"warning\"\r\n });\r\n }\r\n finally {\r\n resetExecutableValues();\r\n }\r\n }\r\n });\r\n } catch {\r\n setClassification(false);\r\n showMessage(`Error running Classification_model`, {\r\n variant: \"error\"\r\n });\r\n }\r\n } catch {\r\n setClassification(false);\r\n showMessage(`Error finding trained model file`, {\r\n variant: \"error\"\r\n });\r\n }\r\n }).catch(error => {\r\n console.log(error);\r\n setClassification(false);\r\n });\r\n };\r\n\r\n const canRunTraining = () => {\r\n let jsonData = viewer?.labelObject();\r\n const noAnnotations = jsonData.annotations.length === 0;\r\n const noImages = jsonData.images.length === 0;\r\n if (noAnnotations || noImages) {\r\n showMessage(`No training labels found. Active images are required`, {\r\n variant: \"warning\"\r\n });\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n const runTraining = (numIterations) => {\r\n if (training) {\r\n showMessage(`Cannot run training last process complete is complete`, {\r\n variant: \"warning\"\r\n });\r\n return;\r\n }\r\n\r\n resetExecutableValues();\r\n setTraining(true);\r\n\r\n let modelPath;\r\n let cocoPath;\r\n let outputPath;\r\n\r\n dialog.showOpenDialog({\r\n properties: ['openDirectory']\r\n }).then(result => {\r\n if (result.canceled) {\r\n setTraining(false);\r\n return;\r\n }\r\n\r\n try {\r\n outputPath = slash(result.filePaths[0]);\r\n cocoPath = path.join(outputPath, \"labels_for_training.3dl\");\r\n let jsonData = viewer?.labelObject();\r\n let text = JSON.stringify(jsonData, null, 4);\r\n\r\n fs.writeFile(cocoPath, text, 'utf8', (err) => {\r\n if (err) {\r\n console.log(err);\r\n showMessage(`Failed to export labels for training`, {\r\n variant: \"error\"\r\n });\r\n }\r\n });\r\n\r\n forceInitialProgress();\r\n\r\n let exe = new PythonExecutable();\r\n setTrainClassifyExe(exe);\r\n\r\n let pythonName = \"aerial_image_training\";\r\n let modelName = path.basename(outputPath);\r\n let commands = [\r\n \"-p\", pythonName,\r\n \"--image_paths\", viewer.activeImageLabelPaths(),\r\n \"--output_folder\", outputPath,\r\n \"--coco_data_file\", cocoPath,\r\n \"--solver_max_iterations\", numIterations,\r\n '--model_title', modelName,\r\n '--batch_size_per_image', 256,\r\n \"--tiled_image_mode\", isOrthoLabel\r\n ];\r\n\r\n exe.run({\r\n command: commands,\r\n saveLogs: true,\r\n onLine: jsonData => {\r\n updateDownloadingResources(jsonData);\r\n\r\n if (jsonData.gpu_memory_error) {\r\n showMessage(`GPU has insufficient memory. Switching to CPU based training`, {\r\n variant: \"warning\"\r\n });\r\n } else if (jsonData.model_diverge_error){\r\n showMessage(`Training model has diverged, training data may be insufficient or inaccurate`, {\r\n variant: \"error\"\r\n });\r\n } else if (jsonData.label_bounds_error){\r\n showMessage(\"Unable to find any labels inside the defined image bounds\", {\r\n variant: \"error\"\r\n });\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 handleViewTraining(jsonData.url);\r\n }\r\n },\r\n onClose: () => {\r\n try {\r\n if (modelPath) {\r\n showMessage(`Training complete, model saved to ${modelPath}`, {\r\n variant: \"success\"\r\n });\r\n } else {\r\n showMessage(`Training incomplete, model may not have saved correctly.`, {\r\n variant: \"warning\"\r\n });\r\n }\r\n }\r\n catch (err) {\r\n console.log(err);\r\n showMessage(\"Training process not completed\", {\r\n variant: \"warning\"\r\n });\r\n }\r\n finally {\r\n resetExecutableValues();\r\n }\r\n }\r\n });\r\n }\r\n catch (err ){\r\n console.log(err);\r\n setTraining(false);\r\n showMessage(\"Error in training\", {\r\n variant: \"error\"\r\n });\r\n }\r\n }).catch(error => {\r\n console.log(error);\r\n setTraining(false);\r\n });\r\n };\r\n\r\n useEffect(() => {\r\n if (!imageLabelOpen) {\r\n return;\r\n }\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 }, [imageLabelOpen]);\r\n\r\n useEffect(() => {\r\n ipcRenderer?.removeAllListeners(\"open-label-ortho\");\r\n ipcRenderer?.on(\"open-label-ortho\", () => {\r\n handleOpen(\"ortho\");\r\n });\r\n\r\n ipcRenderer?.removeAllListeners(\"open-label-scene\");\r\n ipcRenderer?.on(\"open-label-scene\", () => {\r\n handleOpen(\"scene\");\r\n });\r\n }, [viewer, imageLabelOpen, labelType]);\r\n\r\n useEffect(() => {\r\n viewer?.setActiveLabelType(labelType);\r\n\r\n if (isOrthoLabel) {\r\n dispatch(changeSwitched(true));\r\n setModalName(\"Aerial Classification\");\r\n } else if (isSceneLabel) {\r\n dispatch(changeSwitched(false));\r\n setModalName(\"Scene View Classification\");\r\n }\r\n }, [labelType]);\r\n\r\n useEffect(() => {\r\n if (imageLabelOpen) {\r\n setDefaultTab();\r\n } else {\r\n if (!minimized) {\r\n setLabelType(null);\r\n }\r\n setMinimized(false);\r\n }\r\n\r\n setTabsEnabled(!imageLabelOpen);\r\n }, [viewer, imageLabelOpen]);\r\n\r\n useEffect(() => {\r\n if (minimized) {\r\n setImageLabelOpen(false);\r\n }\r\n }, [minimized]);\r\n\r\n useEffect(() => {\r\n if (classification) {\r\n setPredOrTrain(\"Classification\");\r\n } else if (training) {\r\n setPredOrTrain(\"Training\");\r\n }\r\n\r\n if (trainClassifyProgress === 100) {\r\n setTrainClassifyProgress(0);\r\n }\r\n }, [trainClassifyProgress, classification, training]);\r\n\r\n const isTraining = predOrTrain === \"Training\";\r\n const isModified = categoryList.length !== 0;\r\n const exportDisabled = viewer?.anyLabelSelected();\r\n const labelDisabled = classification || training || (labelLoadProgress > 0);\r\n const trainingLinkDisabled = trainingURL === null;\r\n const sceneTrainingDisabled = isSceneLabel && (numPanoramics > 0) && (numPlanars > 0);\r\n const categoryListDisabled = sceneTrainingDisabled;\r\n\r\n return (\r\n \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 disabled={categoryListDisabled}\r\n />\r\n\r\n {/* Enable training areas */}\r\n addTrainingArea()}\r\n success\r\n />\r\n\r\n {/* Run Training */}\r\n {\r\n if (!canRunTraining()) {\r\n return;\r\n }\r\n\r\n setTrainingPrompt(true);\r\n }}\r\n disabled={categoryListDisabled || labelDisabled}\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={categoryListDisabled || labelDisabled}\r\n />\r\n\r\n {/* Import label file */}\r\n \r\n\r\n {/* Export Label file */}\r\n exportJSON(categoryList)}\r\n disabled={categoryListDisabled || exportDisabled}\r\n />\r\n\r\n {/* Export to DXF */}\r\n {\r\n if (!canExportDXF()) {\r\n return;\r\n }\r\n\r\n runExportDXF();\r\n }}\r\n disabled={categoryListDisabled}\r\n />\r\n\r\n \r\n\r\n \r\n\r\n {(trainClassifyProgress > 0) && (\r\n\r\n
\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 {/** Training/Classification cancel button */}\r\n {isTraining && (\r\n {\r\n handleViewTraining(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 Downloading Resources... \r\n \r\n )}\r\n\r\n {/** Extracting resources */}\r\n {(downloadingResources === \"extract\") && (\r\n \r\n Extracting Resources... \r\n \r\n )}\r\n\r\n {sceneTrainingDisabled && (\r\n \r\n Image classification is not supported for mixed camera type\r\n datasets (planar + panoramic). Removing conflicting camera\r\n files will restore all labelling functionality.\r\n \r\n )}\r\n\r\n\r\n {!categoryListDisabled && (\r\n \r\n \r\n {trainingArea.map(areas =>\r\n )}\r\n \r\n\r\n {(trainingArea.length > 0) && }\r\n\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=\"Close Classification Window?\"\r\n prompt={`Do you want to close the ${modalName} window? All created labels will be lost.`}\r\n button=\"Close\"\r\n />\r\n\r\n setImportData(null)}\r\n onSubmit={() => handleImport()}\r\n title=\"Import Image Labels\"\r\n prompt={`Do you want to import ${importCategories?.length} ${labelType} classes\r\n (${importCategories?.join(\", \")}) and ${numImportLabels} labels?. Connected labels\r\n will be merged together`}\r\n button=\"Import Labels\"\r\n />\r\n\r\n {/* Set training parameters */}\r\n setTrainingPrompt(false)}\r\n onSubmit={handleTrainingPrompt}\r\n title=\"Select training model parameters\"\r\n prompt=\"Select the number of iterations for training your model file.\"\r\n default='250'\r\n label=\"Training Iterations\"\r\n />\r\n\r\n {/* Set classification parameters */}\r\n setClassificationPrompt(false)}\r\n onSubmit={handleClassificationPrompt}\r\n title=\"Select classification parameters\"\r\n prompt=\"Select the classification score, as a decimal between 0 - 1.\"\r\n default='0.5'\r\n label=\"Classification Score\"\r\n />\r\n\r\n {/* Image label import percent dialog */}\r\n 0}\r\n text={\"Importing Image Labels...\"}\r\n percent={labelLoadProgress}\r\n noTransition\r\n />\r\n\r\n \r\n \r\n\r\n {/** Downloading resources (modal) */}\r\n {(downloadResourcesDialog === \"download\") && (\r\n \r\n Downloading Resources... \r\n \r\n )}\r\n\r\n {/** Extracting resources (modal) */}\r\n {(downloadResourcesDialog === \"extract\") && (\r\n \r\n Extracting Resources... \r\n \r\n )}\r\n\r\n \r\n \r\n\r\n
\r\n );\r\n};","import * as React from \"react\";\r\nimport Menu from '@material-ui/core/Menu';\r\nimport MenuItem from '@material-ui/core/MenuItem';\r\nimport {createStyles, makeStyles, Theme} from \"@material-ui/core\";\r\nimport { Viewer } from \"./js/main\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n menuItem: {\r\n fontSize: \"0.875em\",\r\n }\r\n }),\r\n);\r\n\r\nexport const ContextMenu = (props) => {\r\n const classes = useStyles();\r\n const viewer = props.viewer as Viewer;\r\n const {state, setContextState, setViewerTooltipText} = props;\r\n\r\n const onClose = () => {\r\n setContextState({\r\n mouseX: null,\r\n mouseY: null,\r\n id: null,\r\n isPoint: null\r\n });\r\n };\r\n\r\n const onEnter = () => {\r\n setViewerTooltipText(\"\");\r\n };\r\n\r\n const getMenuItems = () => {\r\n let numHighlighted = viewer.numHighlighted();\r\n let labelActive = viewer.checkIfActive();\r\n // No labelling\r\n if (numHighlighted === 0 || !labelActive) {\r\n return [\r\n {\r\n text: `${viewer.orbitState ? \"Disable\" : \"Enable\"} 3D Mode`,\r\n disabled: !(viewer.hasPoints && viewer.cameraSelected),\r\n callback: () => {\r\n viewer.controls.toggleCamera();\r\n }\r\n },\r\n {\r\n text: \"Reset 3D Mode\",\r\n disabled: !viewer.orbitState,\r\n callback: () => {\r\n viewer.controls.resetCamera();\r\n }\r\n }\r\n ];\r\n }\r\n // With Labelling\r\n else if (numHighlighted > 0) {\r\n return [\r\n {\r\n text: `Delete Selected Labels (${numHighlighted})`,\r\n disabled: (viewer.anyLabelSelected()),\r\n callback: () => {\r\n viewer.deleteHighlighted();\r\n }\r\n },\r\n {\r\n text: `Delete Selected Point`,\r\n disabled: (viewer.anyLabelSelected() || !state.isPoint),\r\n callback: () => {\r\n viewer.imageLabels.deletePoint(state.isPoint);\r\n }\r\n },\r\n {\r\n text: `Unselect All Labels`,\r\n disabled: viewer.anyLabelSelected(),\r\n callback: () => {\r\n viewer.unHighlightAll();\r\n }\r\n },\r\n {\r\n text: \"Edit Label\",\r\n disabled: (viewer.anyLabelSelected() || numHighlighted > 1),\r\n callback: () => {\r\n viewer.selectLabel(state.id);\r\n }\r\n }\r\n ];\r\n }\r\n\r\n return [];\r\n };\r\n\r\n const options = viewer ? getMenuItems() : [];\r\n const anchorPosition = state.mouseY !== null && state.mouseX !== null\r\n ? { top: state.mouseY, left: state.mouseX }\r\n : undefined;\r\n\r\n const open = state.mouseY !== null;\r\n\r\n return (\r\n \r\n {options.map(option => {\r\n return (\r\n {\r\n onClose();\r\n option.callback();\r\n }}\r\n >\r\n {option.text}\r\n \r\n );\r\n })}\r\n \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\n\r\nconst textures = {\r\n 'open-street-maps': openStreetMaps,\r\n 'arcgis-world': arcgisWorld,\r\n 'arcgis-street': arcgisStreet,\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\";","import * as React from \"react\";\r\nimport {createStyles, makeStyles, useTheme, Theme} from \"@material-ui/core/styles\";\r\nimport Popover from '@material-ui/core/Popover';\r\nimport Button from '@material-ui/core/Button';\r\nimport MenuItem from '@material-ui/core/MenuItem';\r\nimport FormatListBulletedIcon from '@material-ui/icons/FormatListBulleted';\r\nimport {Avatar} from \"@material-ui/core\";\r\nimport previews from './textures/map-preview';\r\nimport {useState} from \"react\";\r\nimport { Viewer } from \"./js/main\";\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n buttonParent: {\r\n padding: \"3px\",\r\n background: \"rgba(255,255,255,0.4)\",\r\n position: 'absolute',\r\n bottom: \"0.5em\",\r\n left: \"0.5em\",\r\n zIndex: 10,\r\n borderRadius: \"5px\"\r\n },\r\n button: {\r\n padding: \"0px\",\r\n background: \"rgba(0,60,136,0.5)\",\r\n color: \"white\",\r\n minWidth: theme.spacing(3),\r\n \"&:hover\": {\r\n background: \"rgba(0,60,136,0.7)\"\r\n }\r\n },\r\n heading: {\r\n padding: theme.spacing(2),\r\n },\r\n icon: {\r\n width: \"22px\",\r\n height: \"22px\"\r\n },\r\n menuItem: {\r\n fontSize: \"0.9em\",\r\n },\r\n preview: {\r\n width: theme.spacing(4),\r\n height: theme.spacing(4),\r\n marginRight: theme.spacing(2),\r\n borderRadius: theme.spacing(1)\r\n }\r\n }),\r\n);\r\n\r\nexport const LayerSwitcher = (props) => {\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const [anchorEl, setAnchorEl] = useState(null);\r\n\r\n const viewer = props.viewer as Viewer;\r\n const {clearTooltipText} = props;\r\n\r\n const handleClick = (event: React.MouseEvent) => {\r\n setAnchorEl(event.currentTarget);\r\n clearTooltipText();\r\n };\r\n\r\n const handleClose = () => {\r\n setAnchorEl(null);\r\n };\r\n\r\n const handleSelect = (layerID) => {\r\n const minimap = viewer.minimap;\r\n minimap.setVisibleBasemap(layerID);\r\n };\r\n\r\n const getMenuItems = () => {\r\n const minimap = viewer.minimap;\r\n const layers = minimap.basemapIds;\r\n const selected = minimap.activeBasemap;\r\n\r\n return layers.map(layer => {\r\n return {\r\n id: layer.id,\r\n text: layer.text,\r\n icon: previews[layer.id],\r\n selected: layer.id === selected\r\n };\r\n });\r\n };\r\n\r\n const open = Boolean(anchorEl);\r\n const id = open ? 'simple-popover' : undefined;\r\n const options = viewer ? getMenuItems() : [];\r\n\r\n return (\r\n
\r\n \r\n \r\n \r\n \r\n {options.map(option => {\r\n return (\r\n {\r\n handleSelect(option.id);\r\n handleClose();\r\n }}\r\n >\r\n \r\n {option.text}\r\n \r\n );\r\n })}\r\n \r\n
\r\n );\r\n};","import * as React from \"react\";\r\nimport * as THREE from \"three\";\r\nimport {Viewer} from './js/main';\r\nimport {ContextMenu} from \"./context-menu\";\r\nimport {LayerSwitcher} from \"./layer-switcher\";\r\nimport {useCallback, useEffect, useRef, useState} from \"react\";\r\nimport {createStyles, makeStyles, Theme, useTheme} from \"@material-ui/core/styles\";\r\nimport {changeMeasureUnits, selectData, selectView} from '../redux/projections-slice';\r\nimport {useSelector, useDispatch} from 'react-redux';\r\nimport {\r\n getCameraFileAssets,\r\n getPointCloudAssets,\r\n getOrthoAssets,\r\n selectAllAssets\r\n} from \"../redux/assets-slice\";\r\nimport {headerHeight} from \"../app\";\r\nimport LocalScene from \"./js/projections\";\r\nimport {\r\n selectName,\r\n selectProjectModified\r\n} from \"../redux/project-slice\";\r\nimport {assetDrawerWidth, assetDrawerHeight} from \"../asset-drawer\";\r\nimport {Button} from \"@material-ui/core\";\r\nimport RotateLeftIcon from '@material-ui/icons/RotateLeft';\r\nimport {changeAvailableClassifications, changeSwitched,\r\n selectViewerSwitched} from \"../redux/settings-slice\";\r\nimport { CursorTooltip } from \"../tooltips\";\r\nimport { AlertDialog } from \"../dialogs\";\r\nimport {isDevMode} from '../electron-modules';\r\nimport { useSnackbar } from 'notistack';\r\nimport {\r\n changeCameraState,\r\n changeSavedAerialState,\r\n initialAerialState,\r\n initialSceneState,\r\n isValidAerialState,\r\n isValidCameraState,\r\n selectBasicAdjustments,\r\n selectCameraHeight,\r\n selectCameraState,\r\n selectCameraTransform,\r\n selectSavedAerialState\r\n} from \"../redux/camera-slice\";\r\nimport { readTransformFile } from \"../camera-utils\";\r\nimport proj4 from 'proj4';\r\nimport {register} from 'ol/proj/proj4';\r\nimport { throttle } from 'throttle-debounce';\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n parent: {\r\n flex: 1\r\n },\r\n large: {\r\n width: '100%',\r\n height: `calc(100% - ${headerHeight}px)`,\r\n position: 'fixed'\r\n },\r\n small: {\r\n width: `${assetDrawerWidth}px`,\r\n height: `${100-assetDrawerHeight}%`,\r\n position: 'absolute',\r\n background: 'white',\r\n margin: '0.5em',\r\n border: '1px solid',\r\n zIndex: 1\r\n },\r\n offsetSmall: {\r\n bottom: theme.spacing(0),\r\n margin: theme.spacing(0),\r\n borderTop: \"1px solid black\",\r\n zIndex: theme.zIndex.modal,\r\n border: \"none\"\r\n },\r\n offsetLarge: {\r\n marginLeft: assetDrawerWidth,\r\n width: `calc(100% - ${assetDrawerWidth}px)`,\r\n },\r\n gradient: {\r\n 'background-image': 'linear-gradient(45deg, #fdfcfb 0%, #e2d1c3 100%);'\r\n },\r\n buttonParent: {\r\n padding: \"3px\",\r\n background: \"rgba(255,255,255,0.4)\",\r\n position: 'absolute',\r\n top: \"0.5em\",\r\n left: \"0.5em\",\r\n \"z-index\": \"10\",\r\n \"border-radius\": \"5px\",\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 button: {\r\n padding: \"0px\",\r\n background: \"rgba(0,60,136,0.5)\",\r\n color: \"white\",\r\n \"min-width\": \"24px\",\r\n \"&:hover\": {\r\n background: \"rgba(0,60,136,0.7)\",\r\n }\r\n }\r\n }),\r\n);\r\n\r\nconst ViewSwitcher = props => {\r\n const {classes, visible, handleSwitched} = props;\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\nexport const SceneViewer = (props) => {\r\n const viewer = props.viewer as Viewer;\r\n const {setViewer, assetDrawerState, setAddObservations,\r\n setMeasurements, resetObservationType, setSingleAlignment,\r\n orthoLabelOpen, setOrthoLabelOpen, setCategoryList, setTrainingArea,\r\n closeAllTools} = props;\r\n\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const dispatch = useDispatch();\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const assets = useSelector(selectAllAssets);\r\n\r\n const dataProjection = useSelector(selectData);\r\n const viewProjection = useSelector(selectView);\r\n const cameraTransformPath = useSelector(selectCameraTransform);\r\n const projectModifiedDate = useSelector(selectProjectModified);\r\n const projectName = useSelector(selectName);\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 divRef = useRef(null);\r\n const mapRef = useRef(null);\r\n\r\n const [viewerTooltipText, updateViewerTooltipText] = useState(\"\");\r\n const [aerialTooltipText, updateAerialTooltipText] = useState(\"\");\r\n const [customAlertHTML, setCustomAlertHTML] = useState(null);\r\n const [aerialState, setAerialState] = useState({\r\n ...initialAerialState\r\n });\r\n const [cameraState, setCameraState] = useState({\r\n ...initialSceneState\r\n });\r\n const [contextState, setContextState] = useState({\r\n mouseX: null,\r\n mouseY: null,\r\n isPoint: null,\r\n id: null\r\n });\r\n\r\n const tooltipThrottleMilliseconds = 10;\r\n\r\n const setViewerTooltipText = useCallback(throttle(\r\n tooltipThrottleMilliseconds, (value) => {\r\n updateViewerTooltipText(value);\r\n }), []);\r\n\r\n const setAerialTooltipText = useCallback(throttle(\r\n tooltipThrottleMilliseconds, (value) => {\r\n updateAerialTooltipText(value);\r\n }), []);\r\n\r\n const clearTooltipText = () => {\r\n setViewerTooltipText(\"\");\r\n setAerialTooltipText(\"\");\r\n };\r\n\r\n const contextMenuClick = (event, isPoint=null, id=null) => {\r\n event.preventDefault();\r\n setContextState({\r\n mouseX: event.clientX - 2,\r\n mouseY: event.clientY - 4,\r\n isPoint: isPoint,\r\n id: id\r\n });\r\n };\r\n\r\n const getClasses = (switched) => {\r\n let mapClasses = [];\r\n let viewerClasses = [classes.gradient];\r\n\r\n const classLarge = [\r\n classes.large,\r\n assetDrawerState ? classes.offsetLarge : \"\"\r\n ];\r\n const classSmall = [\r\n classes.small,\r\n assetDrawerState ? classes.offsetSmall : \"\"\r\n ];\r\n\r\n if (switched) {\r\n mapClasses = [...mapClasses, ...classLarge];\r\n viewerClasses = [...viewerClasses, ...classSmall];\r\n } else {\r\n mapClasses = [...mapClasses, ...classSmall];\r\n viewerClasses = [...viewerClasses, ...classLarge];\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 = () => {\r\n dispatch(changeSwitched(!viewerSwitched));\r\n };\r\n\r\n const triggerWindowResize = () => {\r\n window.dispatchEvent(new Event('resize'));\r\n };\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 viewer?.checkShiftReset();\r\n\r\n // Add/remove images\r\n const camerasFiles = getCameraFileAssets(assetList);\r\n viewer?.reconcileCameras(camerasFiles, cameraHeight,\r\n basicAdjustments, savedCameraState);\r\n\r\n // Add/remove pointclouds\r\n const pointClouds = getPointCloudAssets(assetList);\r\n viewer?.reconcilePointClouds(pointClouds, savedCameraState);\r\n\r\n // Add/remove orthomosiacs\r\n const orthoFiles = getOrthoAssets(assetList);\r\n viewer?.reconcileOrthos(orthoFiles);\r\n };\r\n\r\n useEffect(() => {\r\n /** Ran after new project is created or project is loaded */\r\n closeAllTools();\r\n viewer?.resetDefaultAerialState(savedAerialState);\r\n viewer?.resetDefaultOrbitState();\r\n }, [projectModifiedDate]);\r\n\r\n useEffect(() => {\r\n let validState = isValidCameraState(cameraState);\r\n if (!validState) {\r\n return;\r\n }\r\n\r\n dispatch(changeCameraState(cameraState));\r\n }, [cameraState]);\r\n\r\n useEffect(() => {\r\n let validState = isValidAerialState(aerialState);\r\n if (!validState) {\r\n return;\r\n }\r\n\r\n dispatch(changeSavedAerialState(aerialState));\r\n }, [aerialState]);\r\n\r\n useEffect(() => {\r\n viewer?.setProjectName(projectName);\r\n }, [viewer, projectName]);\r\n\r\n useEffect(() => {\r\n clearTooltipText();\r\n triggerWindowResize();\r\n if (viewerSwitched) {\r\n viewer?.removeInteractions();\r\n }\r\n }, [viewerSwitched]);\r\n\r\n useEffect(() => {\r\n triggerWindowResize();\r\n }, [assetDrawerState]);\r\n\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n if (viewer) {\r\n const classifications = viewer.getAvailableClassifications();\r\n dispatch(changeAvailableClassifications(classifications));\r\n }\r\n }, 1000);\r\n\r\n return () => {\r\n clearInterval(interval);\r\n };\r\n }, [viewer, dispatch]);\r\n\r\n useEffect(() => {\r\n const viewerProps = {\r\n contextMenuClick,\r\n setMeasurements,\r\n setAerialState,\r\n setSingleAlignment,\r\n setViewerTooltipText,\r\n setAerialTooltipText,\r\n setAddObservations,\r\n resetObservationType,\r\n showMessage,\r\n setCameraState,\r\n orthoLabelOpen,\r\n setOrthoLabelOpen,\r\n setCategoryList,\r\n setTrainingArea\r\n };\r\n\r\n let viewerRef = new Viewer(divRef.current, mapRef.current, viewerProps);\r\n setViewer(viewerRef);\r\n\r\n if (isDevMode) {\r\n // Temporary global for easy access\r\n window['viewer'] = viewerRef;\r\n window['local'] = LocalScene;\r\n window['THREE'] = THREE;\r\n }\r\n\r\n return () => {\r\n console.log(\"Destroy viewer\");\r\n viewerRef.destroy();\r\n };\r\n }, []);\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 viewer?.resetLoadedOnce();\r\n\r\n // Update projection\r\n viewer?.setDataProjection(dataProjection);\r\n\r\n // Force assets to reload\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 === null) {\r\n viewer?.resetCameraMatrix();\r\n return;\r\n }\r\n\r\n readTransformFile(cameraTransformPath)\r\n .then(data => {\r\n const {success, content} = data;\r\n\r\n if (success) {\r\n viewer?.setCameraMatrix(content);\r\n } else {\r\n showMessage(content, {\r\n variant: \"error\"\r\n });\r\n }\r\n });\r\n }, [viewer, cameraTransformPath]);\r\n\r\n useEffect(() => {\r\n viewer?.setCameraHeights(cameraHeight);\r\n }, [viewer, cameraHeight]);\r\n\r\n useEffect(() => {\r\n viewer?.setCameraAdjustments(basicAdjustments);\r\n }, [viewer, basicAdjustments]);\r\n\r\n useEffect(() => {\r\n addAllAssets(assets);\r\n }, [viewer, assets]);\r\n\r\n let {viewerClasses, mapClasses} = getClasses(viewerSwitched);\r\n\r\n return (\r\n \r\n
\r\n {/* Viewer div */}\r\n \r\n {\r\n setViewerTooltipText(\"\");\r\n }}\r\n >\r\n \r\n \r\n
\r\n \r\n\r\n {/* Map div */}\r\n \r\n {\r\n setAerialTooltipText(\"\");\r\n }}\r\n >\r\n \r\n \r\n
\r\n \r\n
\r\n\r\n {/* Viewer alert dialog */}\r\n {\r\n setCustomAlertHTML(null);\r\n }}\r\n >\r\n
\r\n \r\n \r\n );\r\n};","import React, {useEffect, useState} from 'react';\r\nimport {app, dialog, copydir, fs, fsPromises, ipcRenderer, isDevMode} from './electron-modules';\r\nimport {store} from './redux/store';\r\nimport slash from 'slash';\r\nimport path from 'path';\r\nimport { AssetType, selectAllAssets, getCameraFileAssets, getOrthoAssets, getPointCloudAssets } from './redux/assets-slice';\r\nimport LocalScene from './viewer/js/projections';\r\nimport {PythonExecutable} from './executable';\r\nimport {useSelector} from 'react-redux';\r\nimport {\r\n Box,\r\n Button,\r\n CircularProgress,\r\n createStyles,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogContentText,\r\n DialogTitle,\r\n LinearProgress,\r\n LinearProgressProps,\r\n makeStyles,\r\n Theme,\r\n Typography,\r\n useTheme\r\n} from '@material-ui/core';\r\nimport { AlertDialog } from './dialogs';\r\nimport { openDirectory } from './asset-utils';\r\nimport {Asset} from './redux/assets-slice';\r\nimport sanitize from \"sanitize-filename\";\r\nimport { selectName } from './redux/project-slice';\r\nimport { useSnackbar } from 'notistack';\r\n\r\nconst processTimeout = 1000;\r\nconst dataPathName = \"asset-data\";\r\nconst pointsFolder = \"points\";\r\nconst imagesFolder = \"images\";\r\nconst dialogTitle = \"Data Export\";\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 }),\r\n);\r\n\r\nconst LinearProgressWithLabel = (props: LinearProgressProps & { value: number }) => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n {`${Math.round(\r\n props.value,\r\n )}%`}\r\n \r\n \r\n );\r\n};\r\n\r\nconst initialState = {\r\n rootOutputPath: null,\r\n webOutputPath: null,\r\n assets: [] as Asset[],\r\n numAssets: 0,\r\n currentIndex: 0\r\n};\r\n\r\nexport const StaticExporter = (props) => {\r\n const {exportModalOpen, setExportModalOpen} = props;\r\n\r\n const theme = useTheme();\r\n const classes = useStyles(theme);\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const assets = useSelector(selectAllAssets);\r\n const orthoFiles = getOrthoAssets(assets);\r\n const pointClouds = getPointCloudAssets(assets);\r\n const camerasFiles = getCameraFileAssets(assets);\r\n\r\n const projectName = useSelector(selectName);\r\n\r\n const [exportName, setExportName] = useState(\"\");\r\n const [dataExportOpen, setDataExportOpen] = useState(false);\r\n const [runnable, setRunnable] = useState(false);\r\n const [successOpen, setSuccessOpen] = useState(false);\r\n const [cancelOpen, setCancelOpen] = useState(false);\r\n const [cancelling, setCancelling] = useState(false);\r\n const [finishing, setFinishing] = useState(false);\r\n const [runningExe, setRunningExe] = useState(null);\r\n const [exportTopMessage, setExportTopMessage] = useState(\"\");\r\n const [exportBottomMessage, setExportBottomMessage] = useState(\"\");\r\n const [exportPercent, setExportPercent] = useState(0);\r\n const [exportAssets, setExportAssets] = useState<{\r\n rootOutputPath: string | null,\r\n webOutputPath: string | null\r\n assets: Asset[]\r\n numAssets: number\r\n currentIndex: number\r\n }>(initialState);\r\n\r\n const numClouds = pointClouds.length;\r\n const numCameras = camerasFiles.length;\r\n const numOrthos = orthoFiles.length;\r\n const canExport = (numClouds > 0) || (numCameras > 0) || (numOrthos > 0);\r\n const numRawPointcloud = pointClouds.filter(x => x.type === AssetType.LAS).length;\r\n\r\n const handleOpen = () => {\r\n setExportModalOpen(true);\r\n };\r\n\r\n const handleClose = () => {\r\n setExportModalOpen(false);\r\n };\r\n\r\n const onExportFinished = () => {\r\n setRunnable(false);\r\n setDataExportOpen(false);\r\n };\r\n\r\n const handleExportCancel = () => {\r\n onExportFinished();\r\n setCancelling(true);\r\n setNewRunningExe(null);\r\n };\r\n\r\n const setNewRunningExe = (exe) => {\r\n runningExe?.destroy();\r\n setRunningExe(exe);\r\n };\r\n\r\n const handleExport = () => {\r\n handleClose();\r\n exportToHtml(pointClouds, camerasFiles);\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 getAssetIndex = (state, asset) => {\r\n const assetIds = state.assets.map(x => x.id);\r\n const index = assetIds.indexOf(asset.id);\r\n return index;\r\n };\r\n\r\n const createNewFolder = async (folderPath) => {\r\n await deleteFolder(folderPath);\r\n await fsPromises.mkdir(folderPath);\r\n };\r\n\r\n const deleteFolder = async (folderPath) => {\r\n const folderExists = fs.existsSync(folderPath);\r\n if (folderExists) {\r\n await fsPromises.rmdir(folderPath, {recursive: true});\r\n }\r\n };\r\n\r\n const moveCameraData = async (asset, dataPath) => {\r\n const output = `${imagesFolder}-${asset.id}`;\r\n const imagesPath = path.join(dataPath, output);\r\n\r\n await createNewFolder(imagesPath);\r\n\r\n return new Promise(async (resolve) => {\r\n const imagesData = asset.data;\r\n for (let i=0;i {\r\n resolve(true);\r\n }, processTimeout);\r\n });\r\n };\r\n\r\n const moveEncompassData = async (asset, dataPath) => {\r\n const inputPath = asset.data.path;\r\n const output = `${pointsFolder}-${asset.id}`;\r\n const pointPath = path.join(dataPath, output);\r\n\r\n return new Promise((resolve) => {\r\n copydir(inputPath, pointPath, {}, err => {\r\n if (err) {\r\n dialog.showErrorBox('Error', `An error occurred while exporting ${asset.name}`);\r\n return;\r\n }\r\n\r\n setTimeout(() => {\r\n resolve(true);\r\n }, processTimeout);\r\n });\r\n });\r\n };\r\n\r\n const moveRawPointcloud = async (asset, dataPath) => {\r\n const units = LocalScene.dataProjectionUnits;\r\n const inputPath = asset.data.path;\r\n const output = `${pointsFolder}-${asset.id}`;\r\n const pointPath = path.join(dataPath, output);\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 \"--units\", units\r\n ];\r\n\r\n const exe = new PythonExecutable();\r\n setNewRunningExe(exe);\r\n\r\n exe.run({\r\n command: commands,\r\n parseLineData: false,\r\n onLine: text => {\r\n setExportBottomMessage(text);\r\n },\r\n onClose: () => {\r\n setTimeout(() => {\r\n resolve(true);\r\n }, processTimeout);\r\n }\r\n });\r\n });\r\n };\r\n\r\n const updateCameraDataState = (asset, state) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n const output = `${imagesFolder}-${asset.id}`;\r\n\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(dataPathName, output, imageName);\r\n state.assets[assetIndex].data[imageIndex].path = `./${finalPath}`;\r\n });\r\n };\r\n\r\n const updateEncompassDataState = (asset, state) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n const output = `${pointsFolder}-${asset.id}`;\r\n const finalPath = path.join(dataPathName, output);\r\n state.assets[assetIndex].data.path = `./${finalPath}`;\r\n };\r\n\r\n const updateRawPointcloudDataState = (asset, state) => {\r\n const assetIndex = getAssetIndex(state, asset);\r\n const output = `${pointsFolder}-${asset.id}`;\r\n const finalPath = path.join(dataPathName, output, \"points\");\r\n state.assets[assetIndex].data.path = `./${finalPath}`;\r\n state.assets[assetIndex].type = AssetType.Encompass;\r\n };\r\n\r\n const updateCameraTransformPath = (state, outputPath) => {\r\n const dataPath = path.join(outputPath, dataPathName);\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 fsPromises.copyFile(matrixPath, newImagePath);\r\n const finalPath = path.join(dataPathName, outputName);\r\n state.camera.transform = `./${finalPath}`;\r\n }\r\n };\r\n\r\n const moveAssetData = async (asset, outputPath) => {\r\n const dataPath = path.join(outputPath, dataPathName);\r\n\r\n if (asset.type === AssetType.Encompass) {\r\n await moveEncompassData(asset, dataPath);\r\n } else if (asset.type === AssetType.LAS) {\r\n await moveRawPointcloud(asset, dataPath);\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 }\r\n };\r\n\r\n const finishExport = (webOutputPath, rootOutputPath) => {\r\n setExportMessage(\"Export project state\");\r\n\r\n const state = JSON.parse(JSON.stringify(store.getState()));\r\n const assets = exportAssets.assets;\r\n\r\n assets.forEach(asset => {\r\n if (asset.type === AssetType.Encompass) {\r\n updateEncompassDataState(asset, state);\r\n } else if (asset.type === AssetType.LAS) {\r\n updateRawPointcloudDataState(asset, state);\r\n } else if (asset.type === AssetType.Panoramic) {\r\n updateCameraDataState(asset, state);\r\n } else if (asset.type === AssetType.Planar) {\r\n updateCameraDataState(asset, state);\r\n }\r\n });\r\n\r\n // Update camera transform path\r\n updateCameraTransformPath(state, webOutputPath);\r\n\r\n setExportPercent(100);\r\n\r\n const projectJson = JSON.stringify(state, null, 2);\r\n const projectPath = path.join(webOutputPath, \"static.json\");\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 fs.writeFile(projectPath, projectJson, (err) => {\r\n if (err) {\r\n dialog.showErrorBox('Error', 'An error occurred while exporting static html');\r\n }\r\n\r\n setTimeout(() => {\r\n setDataExportOpen(false);\r\n setNewRunningExe(null);\r\n setSuccessOpen(true);\r\n }, processTimeout);\r\n });\r\n };\r\n\r\n const exportToHtml = (pointClouds, cameras) => {\r\n const buildPath = getBuildPath();\r\n\r\n (async () => {\r\n new PythonExecutable().run({\r\n command: ['--check-tool', 'exporter']\r\n });\r\n })();\r\n\r\n openDirectory().then(async outputFolder => {\r\n if (!outputFolder) {\r\n return;\r\n }\r\n\r\n setExportPercent(0);\r\n setDataExportOpen(true);\r\n setExportMessage(\"Creating output folder\");\r\n\r\n // Create final output folder\r\n const rootOutputPath = path.join(outputFolder, exportName);\r\n await createNewFolder(rootOutputPath);\r\n\r\n // Create final output folder\r\n const webOutputPath = path.join(rootOutputPath, \"web\");\r\n await createNewFolder(webOutputPath);\r\n\r\n setExportMessage(\"Copy html files output folder\");\r\n\r\n copydir(buildPath, webOutputPath, {}, err => {\r\n if (err) {\r\n dialog.showErrorBox('Error', 'An error occurred while exporting static html');\r\n return;\r\n }\r\n\r\n setExportMessage(\"Preparing data to export\");\r\n\r\n setTimeout(async () => {\r\n const dataPath = path.join(webOutputPath, dataPathName);\r\n await createNewFolder(dataPath);\r\n\r\n const assets = [...cameras, ...pointClouds];\r\n\r\n if (assets.length === 0) {\r\n // Skip directly to final step\r\n finishExport(webOutputPath, rootOutputPath);\r\n return;\r\n }\r\n\r\n setExportAssets({\r\n webOutputPath: webOutputPath,\r\n rootOutputPath: rootOutputPath,\r\n assets: assets,\r\n numAssets: assets.length,\r\n currentIndex: 0\r\n });\r\n setRunnable(true);\r\n }, processTimeout);\r\n });\r\n });\r\n };\r\n\r\n const getBuildPath= () => {\r\n const appPath = slash(app.getAppPath());\r\n const buildPath = isDevMode\r\n ? path.join(appPath, \"build\")\r\n : path.join(path.dirname(appPath), \"app.asar.unpacked\", \"build\");\r\n\r\n return buildPath;\r\n };\r\n\r\n const getMiniViewerPath= () => {\r\n const appPath = slash(app.getAppPath());\r\n const buildPath = isDevMode\r\n ? path.join(appPath, \"miniviewer.exe\")\r\n : path.join(path.dirname(appPath), \"app.asar.unpacked\", \"miniviewer.exe\");\r\n\r\n return buildPath;\r\n };\r\n\r\n useEffect(() => {\r\n ipcRenderer?.removeAllListeners(\"open-static-export\");\r\n ipcRenderer?.on(\"open-static-export\", () => {\r\n if (canExport) {\r\n handleOpen();\r\n return;\r\n }\r\n\r\n showMessage(\"No data loaded\", {\r\n variant: \"error\"\r\n });\r\n });\r\n }, [ipcRenderer, canExport]);\r\n\r\n useEffect(() => {\r\n setExportName(`export [${sanitize(projectName)}]`);\r\n }, [projectName]);\r\n\r\n useEffect(() => {\r\n const currentIndex = exportAssets.currentIndex;\r\n const numAssets = exportAssets.numAssets;\r\n const webOutputPath = exportAssets.webOutputPath;\r\n const assets = exportAssets.assets;\r\n const toProcess = assets[currentIndex];\r\n\r\n if (!toProcess) {\r\n return;\r\n }\r\n\r\n if (!runnable) {\r\n return;\r\n }\r\n\r\n // Process one asset from the list\r\n const processNextAsset = async () => {\r\n setExportTopMessage(`Processing data: ${toProcess.name}`);\r\n await moveAssetData(toProcess, webOutputPath);\r\n\r\n const nextIndex = currentIndex + 1;\r\n const percent = 100.0 * nextIndex / numAssets;\r\n setExportPercent(percent);\r\n setExportAssets({\r\n ...exportAssets,\r\n currentIndex: nextIndex\r\n });\r\n\r\n if (nextIndex === numAssets) {\r\n setFinishing(true);\r\n } else {\r\n setCancelling(false);\r\n }\r\n };\r\n processNextAsset();\r\n }, [exportAssets, runnable]);\r\n\r\n useEffect(() => {\r\n if (cancelling) {\r\n setCancelOpen(true);\r\n } else {\r\n setTimeout(async () => {\r\n // Delete output folder and close modal\r\n const webOutputPath = exportAssets.webOutputPath;\r\n await deleteFolder(webOutputPath);\r\n setCancelOpen(false);\r\n }, processTimeout);\r\n }\r\n }, [cancelling]);\r\n\r\n useEffect(() => {\r\n if (!finishing) {\r\n return;\r\n }\r\n\r\n if (!cancelling) {\r\n // Reached the end and not cancelling export\r\n const webOutputPath = exportAssets.webOutputPath;\r\n const rootOutputPath = exportAssets.rootOutputPath;\r\n finishExport(webOutputPath, rootOutputPath);\r\n }\r\n\r\n setCancelling(false);\r\n setFinishing(false);\r\n }, [finishing]);\r\n\r\n const pointListItem = numClouds > 0 ?\r\n `
  • Point Cloud${numClouds !== 1 ? \"s\" : \"\"} (${numClouds})
  • `\r\n : \"\";\r\n\r\n const cameraListItem = numCameras > 0\r\n ? `
  • Camera File${numCameras !== 1 ? \"s\" : \"\"} (${numCameras})
  • `\r\n : \"\";\r\n\r\n const orthoListItem = numOrthos > 0\r\n ? `
  • Orthomosaic${numOrthos !== 1 ? \"s\" : \"\"} (${numOrthos})
  • `\r\n : \"\";\r\n\r\n return (\r\n \r\n {/* Exporting dialog */}\r\n \r\n {\"Exporting HTML\"}\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 Cancel Export\r\n \r\n \r\n \r\n\r\n {/* Main dialog */}\r\n \r\n {dialogTitle}\r\n\r\n \r\n ${exportName} will be created.\r\n

    \r\n Export data includes:\r\n
      \r\n ${pointListItem}\r\n ${cameraListItem}\r\n ${orthoListItem}\r\n
    \r\n `\r\n }}/>\r\n\r\n {(numRawPointcloud > 0) && (\r\n This process may take some time due to the conversion process.\r\n )}\r\n
    \r\n\r\n \r\n \r\n\r\n \r\n Export\r\n \r\n \r\n \r\n\r\n {/* Cancelling dialog */}\r\n \r\n {dialogTitle}\r\n \r\n \r\n \r\n Cancelling export\r\n \r\n \r\n \r\n\r\n {/* Success dialog */}\r\n {\r\n setSuccessOpen(false);\r\n }}\r\n >\r\n \r\n Successfully exported data to static HTML\r\n \r\n \r\n
    \r\n );\r\n};\r\n","import {MainAppBar} from \"./app-bar\";\r\nimport React, {useEffect, useState} from \"react\";\r\nimport {createMuiTheme} from \"@material-ui/core/styles\";\r\nimport {ThemeProvider} from '@material-ui/styles';\r\nimport {SettingsDrawer} from \"./settings-drawer\";\r\nimport {AssetDrawer} from \"./asset-drawer\";\r\nimport {ProjectionsManager} from \"./projections/manager\";\r\nimport {ImageAlignerAdvanced, ImageAlignerBasic} from \"./alignment\";\r\nimport {ImageLabelling} from \"./labelling/image-labelling\";\r\nimport {SceneViewer} from \"./viewer/viewer\";\r\nimport {Backdrop, Box, CircularProgress, createStyles, makeStyles, Theme} from \"@material-ui/core\";\r\nimport {useDispatch, useSelector} from 'react-redux';\r\nimport {addAssetFolder, isAssetFile} from './asset-utils';\r\nimport {changeDrawerOpen, changeSelectedTab, selectDrawerOpen, selectSelectedTab} from \"./redux/settings-slice\";\r\nimport {useSnackbar} from 'notistack';\r\nimport {app, dialog, isDevMode, isStaticSite, remote} from \"./electron-modules\";\r\nimport path from 'path';\r\nimport slash from \"slash\";\r\nimport {loadProjectFile, loadProjectJSON, projectFileType} from \"./project-utils\";\r\nimport {StaticExporter} from \"./static-export\";\r\nimport {PythonExecutable, WorkflowExecutable} from \"./executable\";\r\n\r\nexport const headerHeight = 48;\r\nexport const drawerWidth = 280;\r\n\r\n// NOTE: Custom theme colors work but need to be manually added\r\ndeclare module \"@material-ui/core/styles/createPalette\" {\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n interface Palette {\r\n custom: Palette['primary'];\r\n }\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n interface PaletteOptions {\r\n custom: PaletteOptions['primary'];\r\n }\r\n}\r\n\r\nconst theme = createMuiTheme({\r\n zIndex: {\r\n appBar: 1100,\r\n modal: 1250,\r\n drawer: 1200,\r\n snackbar: 1400,\r\n tooltip: 1500\r\n },\r\n overrides: {\r\n MuiPopover: {\r\n root: {\r\n \"z-index\": \"1300 !important\"\r\n }\r\n },\r\n MuiTooltip: {\r\n tooltip: {\r\n backgroundColor: \"rgba(0, 0, 0, 0.5)\",\r\n },\r\n arrow: {\r\n \"&::before\": {\r\n backgroundColor: \"rgba(0, 0, 0, 0.5)\",\r\n border: \"0px\"\r\n }\r\n },\r\n }\r\n },\r\n palette: {\r\n primary: {\r\n main: '#162031'\r\n },\r\n secondary: {\r\n main: '#dd0c29'\r\n },\r\n custom: {\r\n main: '#5c6ac4',\r\n },\r\n },\r\n mixins: {\r\n toolbar: {\r\n // override default\r\n }\r\n }\r\n});\r\n\r\nconst useStyles = makeStyles((theme: Theme) =>\r\n createStyles({\r\n backdrop: {\r\n color: '#fff',\r\n zIndex: theme.zIndex.snackbar + 1,\r\n flexDirection: \"column\",\r\n },\r\n backdropText: {\r\n padding: theme.spacing(1)\r\n }\r\n }),\r\n);\r\n\r\nconst DragDropLoader = (props) => {\r\n const {setAssetDrawerState, assetDrawerState, addFilePathsFunc} = props;\r\n\r\n const handleDrop = async event => {\r\n if (isStaticSite) {\r\n return;\r\n }\r\n\r\n const files = [...event.dataTransfer.files]\r\n .map(file => slash(file.path));\r\n\r\n addFilePathsFunc(files);\r\n };\r\n\r\n const handleDragOver = event => {\r\n if (isStaticSite) {\r\n return;\r\n }\r\n\r\n event.stopPropagation();\r\n event.preventDefault();\r\n\r\n if (!assetDrawerState) {\r\n // Only trigger change if the draw was closed. This will avoid\r\n // performance issues due to calling the dispatch function too often\r\n setAssetDrawerState(true);\r\n }\r\n };\r\n\r\n return (\r\n \r\n {props.children}\r\n
    \r\n );\r\n};\r\n\r\nconst BackdropToggle = () => {\r\n const classes = useStyles(theme);\r\n const [backdropOpen, setBackdropOpen] = useState(false);\r\n\r\n const handleClose = () => {\r\n setBackdropOpen(false);\r\n };\r\n\r\n const handleOpen = () => {\r\n setBackdropOpen(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 );\r\n};\r\n\r\nexport const App = () => {\r\n const dispatch = useDispatch();\r\n\r\n const projectDrawerState = useSelector(selectDrawerOpen);\r\n const projectActiveTab = useSelector(selectSelectedTab);\r\n const showMessage = useSnackbar().enqueueSnackbar;\r\n\r\n const [viewer, setViewer] = useState(null);\r\n const [assetDrawerState, setDrawerState] = useState(false);\r\n const [settingsDrawerState, setSettingsDrawerState] = useState(false);\r\n const [measurements, setMeasurements] = useState([]);\r\n const [singleAlignment, setSingleAlignment] = useState([0, 0, 0]);\r\n const [activeTab, setSelectedTab] = useState(0);\r\n const [tabsEnabled, setTabsEnabled] = useState(true);\r\n const [addObservations, setAddObservations] = useState(false);\r\n const [observationType, setObservationType] = useState(\"none\");\r\n const [categoryList, setCategoryList] = useState([]);\r\n const [trainingArea, setTrainingArea] = useState([]);\r\n const [alignerAdvOpen, setAlignerAdvOpen] = useState(false);\r\n const [alignerBasicOpen, setAlignerBasicOpen] = useState(false);\r\n const [imageLabelOpen, setImageLabelOpen] = useState(false);\r\n const [projectionsOpen, setProjectionsOpen] = useState(false);\r\n const [exportModalOpen, setExportModalOpen] = useState(false);\r\n\r\n const setDefaultTab = () => {\r\n setTabValue(0);\r\n };\r\n\r\n const setTabValue = (value) => {\r\n dispatch(changeSelectedTab(value));\r\n };\r\n\r\n const setAssetDrawerState = (state) => {\r\n dispatch(changeDrawerOpen(state));\r\n };\r\n\r\n const resetObservationType = () => {\r\n setObservationType(\"none\");\r\n };\r\n\r\n\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 let args = fileArgs.map((arg) => slash(arg.toString()));\r\n return args;\r\n } catch {\r\n return null;\r\n }\r\n };\r\n\r\n const addFilePaths = files => {\r\n if (!files || files.length === 0) {\r\n return;\r\n }\r\n\r\n const configs = files.filter(x => {\r\n return path.extname(x) === `.${projectFileType}`;\r\n });\r\n\r\n const assets = files.filter(x => isAssetFile(x));\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 showMessage(\"Load project config file\", {\r\n variant: \"success\"\r\n });\r\n }\r\n return;\r\n }\r\n\r\n if (assets.length > 0) {\r\n // Add new assets\r\n addAssetFolder(showMessage, dispatch, assets);\r\n }\r\n };\r\n\r\n /** Load geospatial file from launch arguments */\r\n const loadFromCompiledExe = () => {\r\n let paths = getAllFileArgs();\r\n\r\n // Load files from command line. addFilePaths\r\n // makes sure that invalid files will be ignored\r\n addFilePaths(paths);\r\n };\r\n\r\n /** Load project json from relative location */\r\n const loadFromStaticSite = () => {\r\n console.log(\"Load static site project config file\");\r\n\r\n const cache = Date.now();\r\n fetch(`./static.json?cache=${cache}`)\r\n .then(res => res.text())\r\n .then(response => {\r\n loadProjectJSON(response);\r\n })\r\n .catch(() => {\r\n console.error(\"Error reading static website config\");\r\n });\r\n };\r\n\r\n /** Close all active tool modals */\r\n const closeAllTools = () => {\r\n setAlignerAdvOpen(false);\r\n setAlignerBasicOpen(false);\r\n setImageLabelOpen(false);\r\n setProjectionsOpen(false);\r\n setExportModalOpen(false);\r\n };\r\n\r\n useEffect(() => {\r\n if (isDevMode || isStaticSite) {\r\n return;\r\n }\r\n\r\n new PythonExecutable().run({\r\n command: ['--check-tool', 'viewer'],\r\n onLine: jsonData => {\r\n if (!jsonData.available) {\r\n dialog.showMessageBox({\r\n title: 'Invalid License',\r\n message: 'This product is not licensed. If you have a valid license key, please open SOLV3D Engine and activate your license using the License Manager.',\r\n buttons: ['Exit', 'Open Engine'],\r\n type: 'error',\r\n noLink: true\r\n }).then(selection => {\r\n if (selection.response === 1) {\r\n new WorkflowExecutable().run({command: []});\r\n }\r\n\r\n app.quit();\r\n });\r\n }\r\n },\r\n });\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (isStaticSite) {\r\n // Block browser context menu\r\n window.oncontextmenu = event => {\r\n event.preventDefault();\r\n };\r\n\r\n loadFromStaticSite();\r\n } else {\r\n loadFromCompiledExe();\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n setDrawerState(projectDrawerState);\r\n }, [projectDrawerState]);\r\n\r\n useEffect(() => {\r\n setSelectedTab(projectActiveTab);\r\n }, [projectActiveTab]);\r\n\r\n useEffect(() => {\r\n let width = settingsDrawerState ? drawerWidth : 0;\r\n viewer?.updateCompassOffset(width);\r\n }, [viewer, settingsDrawerState]);\r\n\r\n return (\r\n \r\n \r\n {(!isStaticSite) && ()}\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 setAssetDrawerState(true);\r\n }}\r\n handleSettingsDrawerOpen={() => {\r\n setSettingsDrawerState(true);\r\n }}\r\n assetDrawerState={assetDrawerState}\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\nexport const showBackdrop = () => {\r\n const button = document.getElementById(\"backdrop-show\");\r\n button.click();\r\n};\r\n\r\nexport const hideBackdrop = () => {\r\n const button = document.getElementById(\"backdrop-hide\");\r\n button.click();\r\n};","import React, { useRef } from 'react';\r\nimport ReactDOM from 'react-dom';\r\nimport {App} from \"./app\";\r\nimport {\r\n saveProjectAs,\r\n loadProject,\r\n saveProject,\r\n newProject\r\n} from \"./project-utils\";\r\nimport {Provider} from 'react-redux';\r\nimport {store} from './redux/store';\r\nimport {\r\n getCurrentWindow,\r\n Menu,\r\n isDevMode,\r\n remote,\r\n fs,\r\n shell,\r\n logDirectoryPath\r\n} from './electron-modules';\r\nimport {\r\n WorkflowExecutable,\r\n PythonExecutable\r\n} from \"./executable\";\r\nimport { SnackbarProvider } from 'notistack';\r\nimport { Button } from '@material-ui/core';\r\nimport Zoom from '@material-ui/core/Zoom';\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 loadLogDirectory = () => {\r\n fs.promises.mkdir(logDirectoryPath).catch(() => {});\r\n shell.openPath(logDirectoryPath);\r\n};\r\n\r\nconst generateTemplateList = () => {\r\n // Generate menu from templates\r\n let template = [fileMenu, toolsMenu, helpMenu] as any[];\r\n\r\n if (isDevMode) {\r\n template.push(debugMenu);\r\n }\r\n\r\n return template;\r\n};\r\n\r\nconst fileMenu = {\r\n label: 'File',\r\n submenu: [\r\n {\r\n label: 'Open Engine Workflow',\r\n click: async () => {\r\n new WorkflowExecutable().run({command: []});\r\n }\r\n },\r\n {type: 'separator'},\r\n {\r\n label: 'New Project',\r\n click: async () => {\r\n newProject();\r\n }\r\n },\r\n {\r\n label: 'Open Project',\r\n click: async () => {\r\n loadProject();\r\n }\r\n },\r\n {\r\n label: 'Save Project',\r\n click: async () => {\r\n saveProject();\r\n }\r\n },\r\n {\r\n label: 'Save Project as...',\r\n click: async () => {\r\n saveProjectAs();\r\n }\r\n },\r\n {type: 'separator'},\r\n {role: 'quit'}\r\n ]\r\n};\r\n\r\nconst helpMenu = {\r\n label: 'Help',\r\n submenu: [\r\n {\r\n label: 'Open Log Directory',\r\n click: loadLogDirectory\r\n }\r\n ]\r\n};\r\n\r\nconst toolsMenu = {\r\n label: 'Tools',\r\n id: 'tools',\r\n submenu: [\r\n {\r\n id: 'projections',\r\n label: 'Projection Manager',\r\n click: async () => {\r\n sendToMainWindow(\"open-projection-manager\");\r\n }\r\n },\r\n {\r\n id: 'aligner-advanced-menu',\r\n label: 'Data Aligner (Advanced)',\r\n enabled: false,\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 label: 'Data Aligner (Basic)',\r\n enabled: false,\r\n click: async () => {\r\n sendToMainWindow(\"open-image-aligner-basic\");\r\n }\r\n },\r\n {\r\n id: 'label-ortho-menu',\r\n label: 'Aerial Classification',\r\n enabled: false,\r\n click: async () => {\r\n sendToMainWindow(\"open-label-ortho\");\r\n }\r\n },\r\n {\r\n id: 'label-scene-menu',\r\n label: 'Scene View Classification',\r\n enabled: false,\r\n visible: false, // Disabled until we make more progress on the export side\r\n click: async () => {\r\n sendToMainWindow(\"open-label-scene\");\r\n }\r\n },\r\n {\r\n id: 'exporter-menu',\r\n label: 'Export',\r\n enabled: false,\r\n click: async () => {\r\n sendToMainWindow(\"open-static-export\");\r\n }\r\n }\r\n ]\r\n};\r\n\r\nconst debugMenu = {\r\n label: 'Refresh',\r\n click: () => {\r\n getCurrentWindow().reload();\r\n }\r\n};\r\n\r\nconst setToolAvailability = async toolName => {\r\n const exe = new PythonExecutable();\r\n exe.run({\r\n command: ['--check-tool', toolName],\r\n showStatus: false,\r\n onLine: jsonData => {\r\n Menu.getApplicationMenu().items\r\n .find(item => item.id === 'tools').submenu.items\r\n .find(item => item.id === toolName).enabled = jsonData.available;\r\n }\r\n });\r\n};\r\n\r\nconst checkAllowedMenuItems = async () => {\r\n // TODO: check all tools at once\r\n setToolAvailability('aligner-advanced-menu');\r\n setToolAvailability('aligner-basic-menu');\r\n setToolAvailability('exporter-menu');\r\n setToolAvailability('label-ortho-menu');\r\n setToolAvailability('label-scene-menu');\r\n};\r\n\r\nif (Menu) {\r\n const template = generateTemplateList();\r\n const menu = Menu.buildFromTemplate(template);\r\n Menu.setApplicationMenu(menu);\r\n checkAllowedMenuItems();\r\n}\r\n\r\nconst MessageProvider = (props) => {\r\n const messageRef = useRef(null);\r\n\r\n const onMessageClose = key => () => {\r\n messageRef.current.closeSnackbar(key);\r\n };\r\n\r\n return (\r\n (\r\n \r\n )}\r\n >\r\n {props.children}\r\n \r\n );\r\n};\r\n\r\nReactDOM.render(\r\n \r\n \r\n \r\n \r\n ,\r\n document.getElementById('root')\r\n);","import path from \"path\";\r\n\r\n/** Electron specific modules that will fail for static html site */\r\n\r\nexport const electron = window.require ? window.require(\"electron\") : null;\r\n\r\nexport const remote = electron ? electron.remote : null;\r\n\r\nexport const shell = electron ? electron.shell : null;\r\n\r\nexport const ipcRenderer = electron ? electron.ipcRenderer : null;\r\n\r\nexport const child = electron ? window.require(\"child_process\") : null;\r\n\r\nexport const process = electron ? window.require(\"process\") : null;\r\n\r\nexport const dialog = remote ? remote.dialog : null;\r\n\r\nexport const app = remote ? remote.app : null;\r\n\r\nexport const getCurrentWindow = electron ? electron.remote.getCurrentWindow : null;\r\n\r\nexport const Menu = remote ? remote.Menu : null;\r\n\r\nexport const fs = remote ? remote.require('fs') : null;\r\n\r\nexport const fsPromises = fs ? fs.promises : null;\r\n\r\nexport const csv = remote ? remote.require('fast-csv') : null;\r\n\r\nexport const copydir = remote ? remote.require('copy-dir') : null;\r\n\r\nexport const glob = remote ? remote.require('glob') : null;\r\n\r\nexport const isDevMode = remote ? (app.isPackaged === false) : false;\r\n\r\nexport const isStaticSite = electron ? false : true;\r\n\r\nexport const logDirectoryPath = app\r\n ? path.join(app.getPath('userData'), \"logs\")\r\n : null;\r\n\r\nexport const storage = remote ? remote.require('electron-json-storage-sync') : {\r\n get: () => {\r\n return {status: false};\r\n },\r\n set: () => {}\r\n};\r\n"],"sourceRoot":""}