function createPointcloudData(pointcloud) { let material = pointcloud.material; let ranges = []; for(let [name, value] of material.ranges){ ranges.push({ name: name, value: value, }); } if(typeof material.elevationRange[0] === "number"){ ranges.push({ name: "elevationRange", value: material.elevationRange, }); } if(typeof material.intensityRange[0] === "number"){ ranges.push({ name: "intensityRange", value: material.intensityRange, }); } let pointSizeTypeName = Object.entries(Potree.PointSizeType).find(e => e[1] === material.pointSizeType)[0]; let jsonMaterial = { activeAttributeName: material.activeAttributeName, ranges: ranges, size: material.size, minSize: material.minSize, pointSizeType: pointSizeTypeName, matcap: material.matcap, }; const pcdata = { name: pointcloud.name, url: pointcloud.pcoGeometry.url, position: pointcloud.position.toArray(), rotation: pointcloud.rotation.toArray(), scale: pointcloud.scale.toArray(), material: jsonMaterial, }; return pcdata; } function createProfileData(profile){ const data = { uuid: profile.uuid, name: profile.name, points: profile.points.map(p => p.toArray()), height: profile.height, width: profile.width, }; return data; } function createVolumeData(volume){ const data = { uuid: volume.uuid, type: volume.constructor.name, name: volume.name, position: volume.position.toArray(), rotation: volume.rotation.toArray(), scale: volume.scale.toArray(), visible: volume.visible, clip: volume.clip, }; return data; } function createCameraAnimationData(animation){ const controlPoints = animation.controlPoints.map( cp => { const cpdata = { position: cp.position.toArray(), target: cp.target.toArray(), }; return cpdata; }); const data = { uuid: animation.uuid, name: animation.name, duration: animation.duration, t: animation.t, curveType: animation.curveType, visible: animation.visible, controlPoints: controlPoints, }; return data; } function createMeasurementData(measurement){ const data = { uuid: measurement.uuid, name: measurement.name, points: measurement.points.map(p => p.position.toArray()), showDistances: measurement.showDistances, showCoordinates: measurement.showCoordinates, showArea: measurement.showArea, closed: measurement.closed, showAngles: measurement.showAngles, showHeight: measurement.showHeight, showCircle: measurement.showCircle, showAzimuth: measurement.showAzimuth, showEdges: measurement.showEdges, color: measurement.color.toArray(), }; return data; } function createOrientedImagesData(images){ const data = { cameraParamsPath: images.cameraParamsPath, imageParamsPath: images.imageParamsPath, }; return data; } function createGeopackageData(geopackage){ const data = { path: geopackage.path, }; return data; } function createAnnotationData(annotation){ const data = { uuid: annotation.uuid, title: annotation.title.toString(), description: annotation.description, position: annotation.position.toArray(), offset: annotation.offset.toArray(), children: [], }; if(annotation.cameraPosition){ data.cameraPosition = annotation.cameraPosition.toArray(); } if(annotation.cameraTarget){ data.cameraTarget = annotation.cameraTarget.toArray(); } if(typeof annotation.radius !== "undefined"){ data.radius = annotation.radius; } return data; } function createAnnotationsData(viewer){ const map = new Map(); viewer.scene.annotations.traverseDescendants(a => { const aData = createAnnotationData(a); map.set(a, aData); }); for(const [annotation, data] of map){ for(const child of annotation.children){ const childData = map.get(child); data.children.push(childData); } } const annotations = viewer.scene.annotations.children.map(a => map.get(a)); return annotations; } function createSettingsData(viewer){ return { pointBudget: viewer.getPointBudget(), fov: viewer.getFOV(), edlEnabled: viewer.getEDLEnabled(), edlRadius: viewer.getEDLRadius(), edlStrength: viewer.getEDLStrength(), background: viewer.getBackground(), minNodeSize: viewer.getMinNodeSize(), showBoundingBoxes: viewer.getShowBoundingBox(), }; } function createSceneContentData(viewer){ const data = []; const potreeObjects = []; viewer.scene.scene.traverse(node => { if(node.potree){ potreeObjects.push(node); } }); for(const object of potreeObjects){ if(object.potree.file){ const saveObject = { file: object.potree.file, }; data.push(saveObject); } } return data; } function createViewData(viewer){ const view = viewer.scene.view; const data = { position: view.position.toArray(), target: view.getPivot().toArray(), }; return data; } function createClassificationData(viewer){ const classifications = viewer.classifications; const data = classifications; return data; } export function saveProject(viewer) { const scene = viewer.scene; const data = { type: "Potree", version: 1.7, settings: createSettingsData(viewer), view: createViewData(viewer), classification: createClassificationData(viewer), pointclouds: scene.pointclouds.map(createPointcloudData), measurements: scene.measurements.map(createMeasurementData), volumes: scene.volumes.map(createVolumeData), cameraAnimations: scene.cameraAnimations.map(createCameraAnimationData), profiles: scene.profiles.map(createProfileData), annotations: createAnnotationsData(viewer), orientedImages: scene.orientedImages.map(createOrientedImagesData), geopackages: scene.geopackages.map(createGeopackageData), // objects: createSceneContentData(viewer), }; return data; }