import * as THREE from "../../libs/three.js/build/three.module.js"; import {GeoJSONExporter} from "../exporter/GeoJSONExporter.js" import {DXFExporter} from "../exporter/DXFExporter.js" import {Volume, SphereVolume} from "../utils/VolumeNew.js" import {PolygonClipVolume} from "../utils/PolygonClipVolume.js" import {PropertiesPanel} from "./PropertyPanels/PropertiesPanel.js" import {PointCloudTree} from "../PointCloudTree.js" import {Profile} from "../utils/Profile.js" import {Measure} from "../custom/objects/tool/Measure.js" import {Annotation} from "../Annotation.js" import {CameraMode, ClipTask, ClipMethod} from "../defines.js" import {ScreenBoxSelectTool} from "../utils/ScreenBoxSelectTool.js" import {Utils} from "../utils.js" import {CameraAnimation} from "../custom/modules/CameraAnimation/CameraAnimation.js" import {HierarchicalSlider} from "./HierarchicalSlider.js" import {OrientedImage} from "../modules/OrientedImages/OrientedImages.js"; import {Images360} from "../custom/modules/panos/Images360.js"; import JSON5 from "../../libs/json5-2.1.3/json5.mjs"; export class Sidebar{ constructor(viewer){ this.viewer = viewer; this.measuringTool = viewer.measuringTool; this.profileTool = viewer.profileTool; this.volumeTool = viewer.volumeTool; this.dom = $("#sidebar_root"); } createToolIcon(icon, title, callback){ let element = $(` `); element.click(callback); return element; } init(){ if(Potree.settings.editType == 'merge'){ this.initMergeBar() this.initToolbar(); this.initScene(); this.initNavigation(); }else{ this.initAccordion(); this.initAppearance(); this.initToolbar(); this.initScene(); this.initNavigation(); this.initFilters(); //this.initClippingTool(); //因为修改了clipping,所以这项有bug不能使用 this.initSettings(); if(Potree.settings.editType != 'pano'){ this.initAlignment(); this.initClipModel(); this.initSiteModel() this.initParitcle() this.initClippingModel() }else{ this.initPanosEdit() } } $('#potree_version_number').html(Potree.version.major + "." + Potree.version.minor + Potree.version.suffix); } initAlignment(){ let Alignment = viewer.modules.Alignment var pannel = $('#alignment'); var buttons = pannel.find('[name="transform"] button') var applyToPointcloud = (fun, value)=>{ return function(){ var selected = $('#alignment li[name="selectPointCloud"] input:checked' ) Array.from(selected).forEach(e=>{ var pointcloud = viewer.scene.pointclouds.find(p=>p.name == e.name) fun(pointcloud, value) }) } } //逆时针是正数 buttons.eq(0).on('click', applyToPointcloud(Alignment.rotate, 10)) //viewer.scene.pointclouds[0].rotation.z += THREE.Math.degToRad(10) buttons.eq(1).on('click' ,applyToPointcloud(Alignment.rotate, 1)) buttons.eq(2).on('click', applyToPointcloud(Alignment.rotate, 0.1)) buttons.eq(3).on('click', applyToPointcloud(Alignment.rotate, -10)) buttons.eq(4).on('click',applyToPointcloud(Alignment.rotate, -1)) buttons.eq(5).on('click',applyToPointcloud(Alignment.rotate, -0.1)) buttons.eq(6).on('click', applyToPointcloud(Alignment.translate, new THREE.Vector3(-1,0,0))) buttons.eq(7).on('click', applyToPointcloud(Alignment.translate, new THREE.Vector3(1,0,0))) buttons.eq(8).on('click', applyToPointcloud(Alignment.translate, new THREE.Vector3(0,-1,0))) buttons.eq(9).on('click', applyToPointcloud(Alignment.translate, new THREE.Vector3(0,1,0))) buttons.eq(10).on('click', applyToPointcloud(Alignment.translate, new THREE.Vector3(0,0,-1))) buttons.eq(11).on('click', applyToPointcloud(Alignment.translate, new THREE.Vector3(0,0,1))) pannel.find('#startAlignment').on('click', ()=>{ Alignment.enter() }) pannel.find('#exitAlignment').on('click', ()=>{ Alignment.save() Alignment.leave() }) pannel.find('#rotTool').on('click', ()=>{ Alignment.switchHandle('rotate') }) pannel.find('#moveTool').on('click', ()=>{ Alignment.switchHandle('translate') }) } initMergeBar(){//多元融合模块 var pannel = $('#mergeModel'); var buttons = pannel.find('button') let MergeEditor = viewer.modules.MergeEditor let loading = false; pannel.find('ul[name="model"] li button').on('click',(e)=>{ if(loading)return console.log('还在加载', loading) let $elem = $(e.target) let parent = $elem.parent() let name = parent.attr('name') if($elem.attr('name') == 'select'){ return Potree.selectModel(name) } if($elem.text() == '添加'){ let startTime = Date.now() Potree.addModel(name,()=>{ loading = false //$elem.text('删除') let now = Date.now() console.log('加载完毕', name, '用时', (now-startTime)/1000, 's') }) loading = name }else{ Potree.removeModel(name) $elem.text('添加') } }) pannel.find('li button[name="splitScreen"]').on('click',(e)=>{ let $elem = $(e.target) if($elem.text() == '分屏'){ $elem.text('恢复') MergeEditor.enterSplit() }else{ $elem.text('分屏') MergeEditor.leaveSplit() } }) let addingTag = false pannel.find('li button[name="tag"]').on('click',(e)=>{ let $elem = $(e.target) viewer.tagTool.startInsertion() }) } initClippingModel(){//实时裁剪 /* 总共两种box : 可见和不可见(都是并集) 当有可见box时,需要在任一可见box内才可见 当有不可见box时,不在所有不可见box内才可见 */ var clipping = viewer.modules.clipping var pannel = $('#clipping'); var addBtn = pannel.find('[name="operation"] button[name="add"] ') var switchBtn = pannel.find('[name="operation"] button[name="switchView"] ') var enterBtn = pannel.find(' button[name="enter"] ') var exitBtn = pannel.find(' button[name="exit"] ') let list = pannel.find('[name="list"] ul ') enterBtn.on('click',()=>{ clipping.enter() pannel.find('li[name=operation]').css('display','block') pannel.find('li[name=list]').css('display','block') }) exitBtn.on('click',()=>{ clipping.leave() pannel.find('li[name=operation]').css('display','none') pannel.find('li[name=list]').css('display','none') }) switchBtn.on('click',()=>{ clipping.switchView(clipping.activeViewName == 'top' ? 'mainView' : 'top') }) pannel.find('[name="operation"] button[name="translation"] ').on('click',()=>{ clipping.setTranMode('translation') }) pannel.find('[name="operation"] button[name="rotation"] ').on('click',()=>{ clipping.setTranMode('rotation') }) pannel.find('[name="operation"] button[name="scale"] ').on('click',()=>{ clipping.setTranMode('scale') }) addBtn.on('click',()=>{ let volumeBox = this.volumeTool.startInsertion({clip: true, clipTask:Potree.ClipTask.SHOW_OUTSIDE}); let li = $("
  • ") list.append(li); li.find('button[name=changeTask]').on('click',(e)=>{ if(e.target.innerText == '不可见'){ volumeBox.clipTask = Potree.ClipTask.SHOW_INSIDE e.target.innerText = '可见' }else{ volumeBox.clipTask = Potree.ClipTask.SHOW_OUTSIDE e.target.innerText = '不可见' } volumeBox.update() }) li.find('button[name=chose]').on('click',(e)=>{ viewer.transformObject(volumeBox)//viewer.inputHandler.toggleSelection(volumeBox) }) li.find('button[name=delete]').on('click',(e)=>{ li.remove() viewer.scene.removeVolume(volumeBox); }) }) pannel.find('button[name=save]').on('click',(e)=>{ let data = clipping.saveClipData(); }) } addAlignmentButton(pointcloud){ var pannel = $('#alignment li[name="selectPointCloud"]>div'); var option = $(` `) pannel.append(option) /* option.find("input").on('change',function(){ }) */ } initClipModel(){ let Clip = viewer.modules.Clip var pannel = $('#clipModel'); var buttons = pannel.find('button') buttons.eq(0).on('click', Clip.enter.bind(Clip)) buttons.eq(1).on('click', Clip.download.bind(Clip)) buttons.eq(2).on('click', Clip.leave.bind(Clip)) } initSiteModel(){ let SiteModel = viewer.modules.SiteModel var pannel = $('#siteModel'); pannel.find('button[name="start"] ').on('click', SiteModel.enter.bind(SiteModel)) pannel.find('button[name="exit"] ').on('click', SiteModel.leave.bind(SiteModel)) pannel.find('button[name="building"] ').on('click', SiteModel.startInsertion.bind(SiteModel,'building')) pannel.find('button[name="floor"] ').on('click', ()=>{ SiteModel.addFloor(SiteModel.buildings[0], 'top') } ) pannel.find('button[name="room"] ').on('click', ()=>{ SiteModel.startInsertion('room', SiteModel.buildings[0].buildChildren[0]) }) pannel.find('button[name="digHole"] ').on('click', ()=>{ SiteModel.selected && SiteModel.startInsertion('hole', SiteModel.selected) }) pannel.find('button[name="selectBuilding"] ').on('click', ()=>{ SiteModel.selectEntity(SiteModel.buildings[0] ) } ) pannel.find('button[name="selectFloor"] ').on('click', ()=>{ SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0]) } ) pannel.find('button[name="selectRoom"] ').on('click', ()=>{ SiteModel.selectEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0]) }) pannel.find('button[name="removeFirstBuilding"] ').on('click', ()=>{ SiteModel.removeEntity(SiteModel.buildings[0]) }) pannel.find('button[name="removeFirstFloor"] ').on('click', ()=>{ SiteModel.removeEntity(SiteModel.buildings[0].buildChildren[0]) }) pannel.find('button[name="removeFirstRoom"] ').on('click', ()=>{ SiteModel.removeEntity(SiteModel.buildings[0].buildChildren[0].buildChildren[0]) }) pannel.find('button[name="removeFirstHole"] ').on('click', ()=>{ SiteModel.selected.removeHole(SiteModel.selected.holes[0]) }) pannel.find('button[name="removeFirstMarker"] ').on('click', ()=>{ //SiteModel.removeMarker(SiteModel.selected.markers[0]) SiteModel.selected.removeMarker(0) }) } initParitcle(){ let ParticleEditor = viewer.modules.ParticleEditor var pannel = $('#particle'); pannel.find('button[name="addFire"] ').on('click', ()=>{ ParticleEditor.startInsertion('fire+smoke') }) pannel.find('button[name="addExplode"] ').on('click', ()=>{ ParticleEditor.startInsertion('explode') }) } initPanosEdit(){ let PanoEditor = viewer.modules.PanoEditor let Alignment = viewer.modules.Alignment var pannel = $('#panos'); pannel.find('button[name="save"] ').on('click', ()=>{ console.log('saveData',PanoEditor.exportSavingData()) }) pannel.find('button[name="translate"] ').on('click', ()=>{ Alignment.switchHandle('translate') }) pannel.find('button[name="rotate"] ').on('click', ()=>{ Alignment.switchHandle('rotate') }) pannel.find('button[name="topView"] ').on('click', ()=>{ PanoEditor.switchView('top') }) pannel.find('button[name="sideView"] ').on('click', ()=>{ PanoEditor.switchView('right') }) pannel.find('button[name="3DView"] ').on('click', ()=>{ PanoEditor.switchView('mainView') }) pannel.find('button[name="addLink"] ').on('click', ()=>{ PanoEditor.setLinkOperateState('addLink', true) }) pannel.find('button[name="removeLink"] ').on('click', ()=>{ PanoEditor.setLinkOperateState('removeLink', true) }) pannel.find('button[name="getCloser"] ').on('click', ()=>{ PanoEditor.setZoomInState(true) }) } initToolbar(){ // ANGLE let elToolbar = $('#tools'); elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/angle.png', '[title]tt.angle_measurement', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: false, showAngles: true, showArea: false, closed: true, maxMarkers: 3, minMarkers:3, measureType: 'Angle'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // POINT elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/point.svg', '[title]tt.point_measurement', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: false, showAngles: false, showCoordinates: true, showEdges:false, showArea: false, closed: true, maxMarkers: 1, minMarkers:1, measureType: 'Point'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // DISTANCE elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/distance.svg', '[title]tt.distance_measurement', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: false, closed: false, minMarkers:2, maxMarkers: 2, measureType: 'Distance' }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // DISTANCE2 elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/distance.svg', '[title]MulDistance', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: false, closed: false, minMarkers:2, measureType: 'MulDistance' }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // DISTANCE2 elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/distance.svg', '[title]MulDistance Ring', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ //showArea: false, closed: true, minMarkers:3, measureType: 'MulDistance Ring' }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/distance.svg', '[title]Ver MulDistance', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ measureType: 'Ver MulDistance' }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/distance.svg', '[title]Hor MulDistance', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ measureType: 'Hor MulDistance' }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // HEIGHT elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/height.svg', '[title]tt.height_measurement', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true,//false, showHeight: true, showArea: false, closed: false, maxMarkers: 2, minMarkers:2, //showGuideLine: true: true measureType: 'Ver Distance', }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // CIRCLE elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/circle.svg', '[title]tt.circle_measurement', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: false, showHeight: false, showArea: false, showCircle: true, showEdges: false, closed: false, maxMarkers: 3, minMarkers:3, measureType: 'Circle' }); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // AZIMUTH elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/azimuth.svg', 'Azimuth', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: false, showHeight: false, showArea: false, showCircle: false, showEdges: false, showAzimuth: true, closed: false, maxMarkers: 2, minMarkers:2, measureType: 'Azimuth'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // AREA elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/area.svg', '[title]tt.area_measurement', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: true, closed: true, minMarkers:3, //showGuideLine: true: true, measureType: 'Area'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); //Hor AREA elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/area.svg', '[title]Hor Area', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: true, closed: true, minMarkers:3, measureType: 'Hor Area'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // Ver Area elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/area.svg', '[title]Ver Area', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: true, closed: true, minMarkers:3, measureType: 'Ver Area'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // rect area freedom direction elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/area.svg', '[title]area_freedom_rect', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: true, closed: true, minMarkers:4, maxMarkers:4, //showGuideLine: true: true, isRect:true, measureType: 'Rect Area'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // rect area horizontal elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/area.svg', '[title]area_horizontal_rect', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: true, closed: true, minMarkers:4, maxMarkers:4, //showGuideLine: true: true, isRect:true, faceDirection:"horizontal", measureType: 'Hor Rect Area'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // rect area vertical elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/area.svg', '[title]area_vertical_rect', () => { $('#menu_measurements').next().slideDown(); let measurement = this.measuringTool.startInsertion({ showDistances: true, showArea: true, closed: true, minMarkers:4, maxMarkers:4, //showGuideLine: true: true, isRect:true, faceDirection:"vertical", measureType: 'Ver Rect Area'}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === measurement.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // VOLUME elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/volume.svg', '[title]tt.volume_measurement', () => { let volume = this.volumeTool.startInsertion(); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === volume.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // SPHERE VOLUME elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/sphere_distances.svg', '[title]tt.volume_measurement', () => { let volume = this.volumeTool.startInsertion({type: SphereVolume}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === volume.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // PROFILE elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/profile.svg', '[title]tt.height_profile', () => { $('#menu_measurements').next().slideDown(); ; let profile = this.profileTool.startInsertion(); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === profile.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // ANNOTATION elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/annotation.svg', '[title]tt.annotation', () => { $('#menu_measurements').next().slideDown(); ; let annotation = this.viewer.annotationTool.startInsertion(); let annotationsRoot = $("#jstree_scene").jstree().get_json("annotations"); let jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // REMOVE ALL elToolbar.append(this.createToolIcon( Potree.resourcePath + '/icons/reset_tools.svg', '[title]tt.remove_all_measurement', () => { this.viewer.scene.removeAllMeasurements(); } )); { // SHOW / HIDE Measurements let elShow = $("#measurement_options_show"); elShow.selectgroup({title: "Show/Hide labels"}); elShow.find("input").click( (e) => { const show = e.target.value === "SHOW"; this.measuringTool.showLabels = show; }); let currentShow = this.measuringTool.showLabels ? "SHOW" : "HIDE"; elShow.find(`input[value=${currentShow}]`).trigger("click"); } } initScene(){ let elScene = $("#menu_scene"); let elObjects = elScene.next().find("#scene_objects"); let elProperties = elScene.next().find("#scene_object_properties"); { let elExport = elScene.next().find("#scene_export"); let geoJSONIcon = `${Potree.resourcePath}/icons/file_geojson.svg`; let dxfIcon = `${Potree.resourcePath}/icons/file_dxf.svg`; let potreeIcon = `${Potree.resourcePath}/icons/file_potree.svg`; elExport.append(` Export:
    `); let elDownloadJSON = elExport.find("img[name=geojson_export_button]").parent(); elDownloadJSON.click( (event) => { let scene = this.viewer.scene; let measurements = [...scene.measurements, ...scene.profiles, ...scene.volumes]; if(measurements.length > 0){ let geoJson = GeoJSONExporter.toString(measurements); let url = window.URL.createObjectURL(new Blob([geoJson], {type: 'data:application/octet-stream'})); elDownloadJSON.attr('href', url); }else{ this.viewer.postError("nothing to export"); event.preventDefault(); } }); let elDownloadDXF = elExport.find("img[name=dxf_export_button]").parent(); elDownloadDXF.click( (event) => { let scene = this.viewer.scene; let measurements = [...scene.measurements, ...scene.profiles, ...scene.volumes]; if(measurements.length > 0){ let dxf = DXFExporter.toString(measurements); let url = window.URL.createObjectURL(new Blob([dxf], {type: 'data:application/octet-stream'})); elDownloadDXF.attr('href', url); }else{ this.viewer.postError("no measurements to export"); event.preventDefault(); } }); let elDownloadPotree = elExport.find("img[name=potree_export_button]").parent(); elDownloadPotree.click( (event) => { let data = Potree.saveProject(this.viewer); let dataString = JSON5.stringify(data, null, "\t") let url = window.URL.createObjectURL(new Blob([dataString], {type: 'data:application/octet-stream'})); elDownloadPotree.attr('href', url); }); } let propertiesPanel = new PropertiesPanel(elProperties, this.viewer); propertiesPanel.setScene(this.viewer.scene); localStorage.removeItem('jstree'); let tree = $(`
    `); elObjects.append(tree); tree.jstree({ 'plugins': ["checkbox", "state"], 'core': { "dblclick_toggle": false, "state": { "checked" : true }, 'check_callback': true, "expand_selected_onload": true }, "checkbox" : { "keep_selected_style": true, "three_state": false, "whole_node": false, "tie_selection": false, }, }); let createNode = (parent, text, icon, object) => { let nodeID = tree.jstree('create_node', parent, { "text": text, "icon": icon, "data": object }, "last", false, false); if(object.visible){ tree.jstree('check_node', nodeID); }else{ tree.jstree('uncheck_node', nodeID); } return nodeID; } let pcID = tree.jstree('create_node', "#", { "text": "Point Clouds", "id": "pointclouds"}, "last", false, false); let measurementID = tree.jstree('create_node', "#", { "text": "Measurements", "id": "measurements" }, "last", false, false); let annotationsID = tree.jstree('create_node', "#", { "text": "Annotations", "id": "annotations" }, "last", false, false); let otherID = tree.jstree('create_node', "#", { "text": "Other", "id": "other" }, "last", false, false); let vectorsID = tree.jstree('create_node', "#", { "text": "Vectors", "id": "vectors" }, "last", false, false); let imagesID = tree.jstree('create_node', "#", { "text": " Images", "id": "images" }, "last", false, false); tree.jstree("check_node", pcID); tree.jstree("check_node", measurementID); tree.jstree("check_node", annotationsID); tree.jstree("check_node", otherID); tree.jstree("check_node", vectorsID); tree.jstree("check_node", imagesID); tree.on('create_node.jstree', (e, data) => { tree.jstree("open_all"); }); tree.on("select_node.jstree", (e, data) => { let object = data.node.data; propertiesPanel.set(object); this.viewer.inputHandler.deselectAll(); if(object instanceof Volume){ this.viewer.inputHandler.toggleSelection(object); } $(this.viewer.renderer.domElement).focus(); }); tree.on("deselect_node.jstree", (e, data) => { propertiesPanel.set(null); }); tree.on("delete_node.jstree", (e, data) => { propertiesPanel.set(null); }); tree.on('dblclick','.jstree-anchor', (e) => { let instance = $.jstree.reference(e.target); let node = instance.get_node(e.target); let object = node.data; // ignore double click on checkbox if(e.target.classList.contains("jstree-checkbox")){ return; } if(object instanceof PointCloudTree){ let box = this.viewer.getBoundingBox([object]); let node = new THREE.Object3D(); node.boundingBox = box; this.viewer.zoomTo(node, 1, 500); }else if(object instanceof Measure){ let points = object.points.map(p => p.position); let box = new THREE.Box3().setFromPoints(points); if(box.getSize(new THREE.Vector3()).length() == 0){ box.min = box.max.clone();//禁止相同 box.expandByVector(new THREE.Vector3(1,1,1)); } let node = new THREE.Object3D(); node.boundingBox = box; this.viewer.zoomTo(node, 2, 500); }else if(object instanceof Profile){ let points = object.points; let box = new THREE.Box3().setFromPoints(points); if(box.getSize(new THREE.Vector3()).length() > 0){ let node = new THREE.Object3D(); node.boundingBox = box; this.viewer.zoomTo(node, 1, 500); } }else if(object instanceof Volume){ let box = object.boundingBox.clone().applyMatrix4(object.matrixWorld); if(box.getSize(new THREE.Vector3()).length() > 0){ let node = new THREE.Object3D(); node.boundingBox = box; this.viewer.zoomTo(node, 1, 500); } }else if(object instanceof Annotation){ object.moveHere(this.viewer.scene.getActiveCamera()); }else if(object instanceof PolygonClipVolume){ let dir = object.camera.getWorldDirection(new THREE.Vector3()); let target; if(object.camera instanceof THREE.OrthographicCamera){ dir.multiplyScalar(object.camera.right) target = new THREE.Vector3().addVectors(object.camera.position, dir); this.viewer.setCameraMode(CameraMode.ORTHOGRAPHIC); }else if(object.camera instanceof THREE.PerspectiveCamera){ dir.multiplyScalar(this.viewer.scene.view.radius); target = new THREE.Vector3().addVectors(object.camera.position, dir); this.viewer.setCameraMode(CameraMode.PERSPECTIVE); } this.viewer.scene.view.position.copy(object.camera.position); this.viewer.scene.view.lookAt(target); }else if(object.type === "SpotLight"){ let distance = (object.distance > 0) ? object.distance / 4 : 5 * 1000; let position = object.position; let target = new THREE.Vector3().addVectors( position, object.getWorldDirection(new THREE.Vector3()).multiplyScalar(distance)); this.viewer.scene.view.position.copy(object.position); this.viewer.scene.view.lookAt(target); }else if(object instanceof THREE.Object3D){ let box = new THREE.Box3().setFromObject(object); if(box.getSize(new THREE.Vector3()).length() > 0){ let node = new THREE.Object3D(); node.boundingBox = box; this.viewer.zoomTo(node, 1, 500); } }else if(object instanceof OrientedImage){ // TODO zoom to images // let box = new THREE.Box3().setFromObject(object); // if(box.getSize(new THREE.Vector3()).length() > 0){ // let node = new THREE.Object3D(); // node.boundingBox = box; // this.viewer.zoomTo(node, 1, 500); // } }else if(object instanceof Images360){ // TODO }else if(object instanceof Geopackage){ // TODO } }); tree.on("uncheck_node.jstree", (e, data) => { let object = data.node.data; if(object){ object.visible = false; } }); tree.on("check_node.jstree", (e, data) => { let object = data.node.data; if(object){ object.visible = true; } }); let onPointCloudAdded = (e) => { let pointcloud = e.pointcloud; let cloudIcon = `${Potree.resourcePath}/icons/cloud.svg`; let node = createNode(pcID, pointcloud.name, cloudIcon, pointcloud); pointcloud.addEventListener("visibility_changed", () => { if(pointcloud.visible){ tree.jstree('check_node', node); }else{ tree.jstree('uncheck_node', node); } }); }; let onMeasurementAdded = (e) => { let measurement = e.measurement; let icon = Utils.getMeasurementIcon(measurement); createNode(measurementID, measurement.name, icon, measurement); }; let onVolumeAdded = (e) => { let volume = e.volume; let icon = Utils.getMeasurementIcon(volume); let node = createNode(measurementID, volume.name, icon, volume); volume.addEventListener("visibility_changed", () => { if(volume.visible){ tree.jstree('check_node', node); }else{ tree.jstree('uncheck_node', node); } }); }; let onProfileAdded = (e) => { let profile = e.profile; let icon = Utils.getMeasurementIcon(profile); createNode(measurementID, profile.name, icon, profile); }; let onAnnotationAdded = (e) => { let annotation = e.annotation; let annotationIcon = `${Potree.resourcePath}/icons/annotation.svg`; let parentID = this.annotationMapping.get(annotation.parent); let annotationID = createNode(parentID, annotation.title, annotationIcon, annotation); this.annotationMapping.set(annotation, annotationID); annotation.addEventListener("annotation_changed", (e) => { let annotationsRoot = $("#jstree_scene").jstree().get_json("annotations"); let jsonNode = annotationsRoot.children.find(child => child.data.uuid === annotation.uuid); $.jstree.reference(jsonNode.id).rename_node(jsonNode.id, annotation.title); }); }; let onCameraAnimationAdded = (e) => { const animation = e.animation; const animationIcon = `${Potree.resourcePath}/icons/camera_animation.svg`; createNode(otherID, "animation", animationIcon, animation); }; let onOrientedImagesAdded = (e) => { const images = e.images; const imagesIcon = `${Potree.resourcePath}/icons/picture.svg`; const node = createNode(imagesID, "images", imagesIcon, images); images.addEventListener("visibility_changed", () => { if(images.visible){ tree.jstree('check_node', node); }else{ tree.jstree('uncheck_node', node); } }); }; let onImages360Added = (e) => { const images = e.images; const imagesIcon = `${Potree.resourcePath}/icons/picture.svg`; const node = createNode(imagesID, "360° images", imagesIcon, images); images.addEventListener("visibility_changed", () => { if(images.visible){ tree.jstree('check_node', node); }else{ tree.jstree('uncheck_node', node); } }); }; const onGeopackageAdded = (e) => { const geopackage = e.geopackage; const geopackageIcon = `${Potree.resourcePath}/icons/triangle.svg`; const tree = $(`#jstree_scene`); const parentNode = "vectors"; for(const layer of geopackage.node.children){ const name = layer.name; let shpPointsID = tree.jstree('create_node', parentNode, { "text": name, "icon": geopackageIcon, "object": layer, "data": layer, }, "last", false, false); tree.jstree(layer.visible ? "check_node" : "uncheck_node", shpPointsID); } }; this.viewer.scene.addEventListener("pointcloud_added", onPointCloudAdded); this.viewer.scene.addEventListener("measurement_added", onMeasurementAdded); this.viewer.scene.addEventListener("profile_added", onProfileAdded); this.viewer.scene.addEventListener("volume_added", onVolumeAdded); this.viewer.scene.addEventListener("camera_animation_added", onCameraAnimationAdded); this.viewer.scene.addEventListener("oriented_images_added", onOrientedImagesAdded); this.viewer.scene.addEventListener("360_images_added", onImages360Added); this.viewer.scene.addEventListener("geopackage_added", onGeopackageAdded); this.viewer.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded); this.viewer.scene.annotations.addEventListener("annotation_added", onAnnotationAdded); let onMeasurementRemoved = (e) => { let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.measurement.uuid); tree.jstree("delete_node", jsonNode.id); }; let onVolumeRemoved = (e) => { let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid); tree.jstree("delete_node", jsonNode.id); }; let onPolygonClipVolumeRemoved = (e) => { let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.volume.uuid); tree.jstree("delete_node", jsonNode.id); }; let onProfileRemoved = (e) => { let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === e.profile.uuid); tree.jstree("delete_node", jsonNode.id); }; this.viewer.scene.addEventListener("measurement_removed", onMeasurementRemoved); this.viewer.scene.addEventListener("volume_removed", onVolumeRemoved); this.viewer.scene.addEventListener("polygon_clip_volume_removed", onPolygonClipVolumeRemoved); this.viewer.scene.addEventListener("profile_removed", onProfileRemoved); { let annotationIcon = `${Potree.resourcePath}/icons/annotation.svg`; this.annotationMapping = new Map(); this.annotationMapping.set(this.viewer.scene.annotations, annotationsID); this.viewer.scene.annotations.traverseDescendants(annotation => { let parentID = this.annotationMapping.get(annotation.parent); let annotationID = createNode(parentID, annotation.title, annotationIcon, annotation); this.annotationMapping.set(annotation, annotationID); }); } const scene = this.viewer.scene; for(let pointcloud of scene.pointclouds){ onPointCloudAdded({pointcloud: pointcloud}); } for(let measurement of scene.measurements){ onMeasurementAdded({measurement: measurement}); } for(let volume of [...scene.volumes, ...scene.polygonClipVolumes]){ onVolumeAdded({volume: volume}); } for(let animation of scene.cameraAnimations){ onCameraAnimationAdded({animation: animation}); } for(let images of scene.orientedImages){ onOrientedImagesAdded({images: images}); } for(let images of scene.images360){ onImages360Added({images: images}); } for(const geopackage of scene.geopackages){ onGeopackageAdded({geopackage: geopackage}); } for(let profile of scene.profiles){ onProfileAdded({profile: profile}); } { createNode(otherID, "Camera", null, new THREE.Camera()); } this.viewer.addEventListener("scene_changed", (e) => { propertiesPanel.setScene(e.scene); e.oldScene.removeEventListener("pointcloud_added", onPointCloudAdded); e.oldScene.removeEventListener("measurement_added", onMeasurementAdded); e.oldScene.removeEventListener("profile_added", onProfileAdded); e.oldScene.removeEventListener("volume_added", onVolumeAdded); e.oldScene.removeEventListener("polygon_clip_volume_added", onVolumeAdded); e.oldScene.removeEventListener("measurement_removed", onMeasurementRemoved); e.scene.addEventListener("pointcloud_added", onPointCloudAdded); e.scene.addEventListener("measurement_added", onMeasurementAdded); e.scene.addEventListener("profile_added", onProfileAdded); e.scene.addEventListener("volume_added", onVolumeAdded); e.scene.addEventListener("polygon_clip_volume_added", onVolumeAdded); e.scene.addEventListener("measurement_removed", onMeasurementRemoved); }); } initClippingTool(){ this.viewer.addEventListener("cliptask_changed", (event) => { console.log("TODO"); }); this.viewer.addEventListener("clipmethod_changed", (event) => { console.log("TODO"); }); { let elClipTask = $("#cliptask_options"); elClipTask.selectgroup({title: "Clip Task"}); elClipTask.find("input").click( (e) => { this.viewer.setClipTask(ClipTask[e.target.value]); }); let currentClipTask = Object.keys(ClipTask) .filter(key => ClipTask[key] === this.viewer.clipTask); elClipTask.find(`input[value=${currentClipTask}]`).trigger("click"); } { let elClipMethod = $("#clipmethod_options"); elClipMethod.selectgroup({title: "Clip Method"}); elClipMethod.find("input").click( (e) => { this.viewer.setClipMethod(ClipMethod[e.target.value]); }); let currentClipMethod = Object.keys(ClipMethod) .filter(key => ClipMethod[key] === this.viewer.clipMethod); elClipMethod.find(`input[value=${currentClipMethod}]`).trigger("click"); } let clippingToolBar = $("#clipping_tools"); // CLIP VOLUME clippingToolBar.append(this.createToolIcon( Potree.resourcePath + '/icons/clip_volume.svg', '[title]tt.clip_volume', () => { let item = this.volumeTool.startInsertion({clip: true}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); // CLIP POLYGON clippingToolBar.append(this.createToolIcon( Potree.resourcePath + "/icons/clip-polygon.svg", "[title]tt.clip_polygon", () => { let item = this.viewer.clippingTool.startInsertion({type: "polygon"}); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); {// SCREEN BOX SELECT let boxSelectTool = new ScreenBoxSelectTool(this.viewer); clippingToolBar.append(this.createToolIcon( Potree.resourcePath + "/icons/clip-screen.svg", "[title]tt.screen_clip_box", () => { if(!(this.viewer.scene.getActiveCamera() instanceof THREE.OrthographicCamera)){ this.viewer.postMessage(`Switch to Orthographic Camera Mode before using the Screen-Box-Select tool.`, {duration: 2000}); return; } let item = boxSelectTool.startInsertion(); let measurementsRoot = $("#jstree_scene").jstree().get_json("measurements"); let jsonNode = measurementsRoot.children.find(child => child.data.uuid === item.uuid); $.jstree.reference(jsonNode.id).deselect_all(); $.jstree.reference(jsonNode.id).select_node(jsonNode.id); } )); } { // REMOVE CLIPPING TOOLS clippingToolBar.append(this.createToolIcon( Potree.resourcePath + "/icons/remove.svg", "[title]tt.remove_all_clipping_volumes", () => { this.viewer.scene.removeAllClipVolumes(); } )); } } initFilters(){ this.initClassificationList(); this.initReturnFilters(); this.initGPSTimeFilters(); this.initPointSourceIDFilters(); } initReturnFilters(){ let elReturnFilterPanel = $('#return_filter_panel'); { // RETURN NUMBER let sldReturnNumber = elReturnFilterPanel.find('#sldReturnNumber'); let lblReturnNumber = elReturnFilterPanel.find('#lblReturnNumber'); sldReturnNumber.slider({ range: true, min: 0, max: 7, step: 1, values: [0, 7], slide: (event, ui) => { this.viewer.setFilterReturnNumberRange(ui.values[0], ui.values[1]) } }); let onReturnNumberChanged = (event) => { let [from, to] = this.viewer.filterReturnNumberRange; lblReturnNumber[0].innerHTML = `${from} to ${to}`; sldReturnNumber.slider({values: [from, to]}); }; this.viewer.addEventListener('filter_return_number_range_changed', onReturnNumberChanged); onReturnNumberChanged(); } { // NUMBER OF RETURNS let sldNumberOfReturns = elReturnFilterPanel.find('#sldNumberOfReturns'); let lblNumberOfReturns = elReturnFilterPanel.find('#lblNumberOfReturns'); sldNumberOfReturns.slider({ range: true, min: 0, max: 7, step: 1, values: [0, 7], slide: (event, ui) => { this.viewer.setFilterNumberOfReturnsRange(ui.values[0], ui.values[1]) } }); let onNumberOfReturnsChanged = (event) => { let [from, to] = this.viewer.filterNumberOfReturnsRange; lblNumberOfReturns[0].innerHTML = `${from} to ${to}`; sldNumberOfReturns.slider({values: [from, to]}); }; this.viewer.addEventListener('filter_number_of_returns_range_changed', onNumberOfReturnsChanged); onNumberOfReturnsChanged(); } } initGPSTimeFilters(){ let elGPSTimeFilterPanel = $('#gpstime_filter_panel'); { let slider = new HierarchicalSlider({ levels: 4, slide: (event) => { this.viewer.setFilterGPSTimeRange(...event.values); }, }); let initialized = false; let initialize = () => { let elRangeContainer = $("#gpstime_multilevel_range_container"); elRangeContainer[0].prepend(slider.element); let extent = this.viewer.getGpsTimeExtent(); slider.setRange(extent); slider.setValues(extent); initialized = true; }; this.viewer.addEventListener("update", (e) => { let extent = this.viewer.getGpsTimeExtent(); let gpsTimeAvailable = extent[0] !== Infinity; if(!initialized && gpsTimeAvailable){ initialize(); } slider.setRange(extent); //高耗cpu }); } { const txtGpsTime = elGPSTimeFilterPanel.find("#txtGpsTime"); const btnFindGpsTime = elGPSTimeFilterPanel.find("#btnFindGpsTime"); let targetTime = null; txtGpsTime.on("input", (e) => { const str = txtGpsTime.val(); if(!isNaN(str)){ const value = parseFloat(str); targetTime = value; txtGpsTime.css("background-color", "") }else{ targetTime = null; txtGpsTime.css("background-color", "#ff9999") } }); btnFindGpsTime.click( () => { if(targetTime !== null){ viewer.moveToGpsTimeVicinity(targetTime); } }); } } initPointSourceIDFilters() { let elPointSourceIDFilterPanel = $('#pointsourceid_filter_panel'); { let slider = new HierarchicalSlider({ levels: 4, range: [0, 65535], precision: 1, slide: (event) => { let values = event.values; this.viewer.setFilterPointSourceIDRange(values[0], values[1]); } }); let initialized = false; let initialize = () => { elPointSourceIDFilterPanel[0].prepend(slider.element); initialized = true; }; this.viewer.addEventListener("update", (e) => { let extent = this.viewer.filterPointSourceIDRange; if(!initialized){ initialize(); slider.setValues(extent); } }); } // let lblPointSourceID = elPointSourceIDFilterPanel.find("#lblPointSourceID"); // let elPointSourceID = elPointSourceIDFilterPanel.find("#spnPointSourceID"); // let slider = new ZoomableSlider(); // elPointSourceID[0].appendChild(slider.element); // slider.update(); // slider.change( () => { // let range = slider.chosenRange; // this.viewer.setFilterPointSourceIDRange(range[0], range[1]); // }); // let onPointSourceIDExtentChanged = (event) => { // let range = this.viewer.filterPointSourceIDExtent; // slider.setVisibleRange(range); // }; // let onPointSourceIDChanged = (event) => { // let range = this.viewer.filterPointSourceIDRange; // let precision = 1; // let from = `${Utils.addCommas(range[0].toFixed(precision))}`; // let to = `${Utils.addCommas(range[1].toFixed(precision))}`; // lblPointSourceID[0].innerHTML = `${from} to ${to}`; // slider.setRange(range); // }; // this.viewer.addEventListener('filter_point_source_id_range_changed', onPointSourceIDChanged); // this.viewer.addEventListener('filter_point_source_id_extent_changed', onPointSourceIDExtentChanged); } initClassificationList(){ let elClassificationList = $('#classificationList'); let addClassificationItem = (code, name) => { const classification = this.viewer.classifications[code]; const inputID = 'chkClassification_' + code; const colorPickerID = 'colorPickerClassification_' + code; const checked = classification.visible ? "checked" : ""; let element = $(`
  • `); const elInput = element.find('input'); const elColorPicker = element.find(`#${colorPickerID}`); elInput.click(event => { this.viewer.setClassificationVisibility(code, event.target.checked); }); let defaultColor = classification.color.map(c => c * 255).join(", "); defaultColor = `rgb(${defaultColor})`; elColorPicker.spectrum({ // flat: true, color: defaultColor, showInput: true, preferredFormat: 'rgb', cancelText: '', chooseText: 'Apply', move: color => { let rgb = color.toRgb(); const c = [rgb.r / 255, rgb.g / 255, rgb.b / 255, 1]; classification.color = c; }, change: color => { let rgb = color.toRgb(); const c = [rgb.r / 255, rgb.g / 255, rgb.b / 255, 1]; classification.color = c; } }); elClassificationList.append(element); }; const addToggleAllButton = () => { // toggle all button const element = $(`
  • `); let elInput = element.find('input'); elInput.click(event => { this.viewer.toggleAllClassificationsVisibility(); }); elClassificationList.append(element); } const addInvertButton = () => { const element = $(`
  • `); let elInput = element.find('input'); elInput.click( () => { const classifications = this.viewer.classifications; for(let key of Object.keys(classifications)){ let value = classifications[key]; this.viewer.setClassificationVisibility(key, !value.visible); } }); elClassificationList.append(element); }; const populate = () => { addToggleAllButton(); for (let classID in this.viewer.classifications) { addClassificationItem(classID, this.viewer.classifications[classID].name); } addInvertButton(); }; populate(); this.viewer.addEventListener("classifications_changed", () => { elClassificationList.empty(); populate(); }); this.viewer.addEventListener("classification_visibility_changed", () => { { // set checked state of classification buttons for(const classID of Object.keys(this.viewer.classifications)){ const classValue = this.viewer.classifications[classID]; let elItem = elClassificationList.find(`#chkClassification_${classID}`); elItem.prop("checked", classValue.visible); } } { // set checked state of toggle button based on state of all other buttons let numVisible = 0; let numItems = 0; for(const key of Object.keys(this.viewer.classifications)){ if(this.viewer.classifications[key].visible){ numVisible++; } numItems++; } const allVisible = numVisible === numItems; let elToggle = elClassificationList.find("#toggleClassificationFilters"); elToggle.prop("checked", allVisible); } }); } initAccordion(){ $('.accordion > h3').each(function(){ let header = $(this); let content = $(this).next(); //header.addClass('accordion-header ui-widget'); //content.addClass('accordion-content ui-widget'); content.hide(); header.click(() => { content.slideToggle(); }); }); let languages = [ ["EN", "en"], ["FR", "fr"], ["DE", "de"], ["JP", "jp"], ["ES", "es"], ["SE", "se"], ["ZH", "zh"] ]; let elLanguages = $('#potree_languages'); for(let i = 0; i < languages.length; i++){ let [key, value] = languages[i]; let element = $(`${key}`); element.click(() => this.viewer.setLanguage(value)); if(i === 0){ element.css("margin-left", "30px"); } elLanguages.append(element); if(i < languages.length - 1){ elLanguages.append($(document.createTextNode(' - '))); } } // to close all, call // $(".accordion > div").hide() // to open the, for example, tool menu, call: // $("#menu_tools").next().show() } initAppearance(){ const sldPointBudget = this.dom.find('#sldPointBudget'); sldPointBudget.slider({ value: this.viewer.getPointBudget(), min: 100 * 1000, max: 10 * 1000 * 1000, step: 1000, slide: (event, ui) => { this.viewer.setPointBudget(ui.value); } }); this.dom.find('#sldFOV').slider({ value: this.viewer.getFOV(), min: 20, max: 100, step: 1, slide: (event, ui) => { this.viewer.setFOV(ui.value); } }); $('#sldEDLRadius').slider({ value: this.viewer.getEDLRadius(), min: 1, max: 4, step: 0.01, slide: (event, ui) => { this.viewer.setEDLRadius(ui.value); } }); $('#sldEDLStrength').slider({ value: this.viewer.getEDLStrength(), min: 0, max: 5, step: 0.01, slide: (event, ui) => { this.viewer.setEDLStrength(ui.value); } }); $('#sldEDLOpacity').slider({ value: this.viewer.getEDLOpacity(), min: 0, max: 1, step: 0.01, slide: (event, ui) => { this.viewer.setEDLOpacity(ui.value); } }); this.viewer.addEventListener('point_budget_changed', (event) => { $('#lblPointBudget')[0].innerHTML = Utils.addCommas(this.viewer.getPointBudget()); sldPointBudget.slider({value: this.viewer.getPointBudget()}); }); this.viewer.addEventListener('fov_changed', (event) => { $('#lblFOV')[0].innerHTML = parseInt(this.viewer.getFOV()); $('#sldFOV').slider({value: this.viewer.getFOV()}); }); this.viewer.addEventListener('use_edl_changed', (event) => { $('#chkEDLEnabled')[0].checked = this.viewer.getEDLEnabled(); }); this.viewer.addEventListener('edl_radius_changed', (event) => { $('#lblEDLRadius')[0].innerHTML = this.viewer.getEDLRadius().toFixed(1); $('#sldEDLRadius').slider({value: this.viewer.getEDLRadius()}); }); this.viewer.addEventListener('edl_strength_changed', (event) => { $('#lblEDLStrength')[0].innerHTML = this.viewer.getEDLStrength().toFixed(1); $('#sldEDLStrength').slider({value: this.viewer.getEDLStrength()}); }); this.viewer.addEventListener('background_changed', (event) => { $("input[name=background][value='" + this.viewer.getBackground() + "']").prop('checked', true); }); $('#lblPointBudget')[0].innerHTML = Utils.addCommas(this.viewer.getPointBudget()); $('#lblFOV')[0].innerHTML = parseInt(this.viewer.getFOV()); $('#lblEDLRadius')[0].innerHTML = this.viewer.getEDLRadius().toFixed(1); $('#lblEDLStrength')[0].innerHTML = this.viewer.getEDLStrength().toFixed(1); $('#chkEDLEnabled')[0].checked = this.viewer.getEDLEnabled(); { let elBackground = $(`#background_options`); elBackground.selectgroup(); elBackground.find("input").click( (e) => { this.viewer.setBackground(e.target.value); }); let currentBackground = this.viewer.getBackground(); try{ $(`input[name=background_options][value=${currentBackground}]`).trigger("click"); }catch(e){} } $('#chkEDLEnabled').click( () => { this.viewer.setEDLEnabled($('#chkEDLEnabled').prop("checked")); }); } initNavigation(){ let elNavigation = $('#navigation'); let sldMoveSpeed = $('#sldMoveSpeed'); let lblMoveSpeed = $('#lblMoveSpeed'); elNavigation.append(this.createToolIcon( Potree.resourcePath + '/icons/earth_controls_1.png', '[title]tt.earth_control', () => { this.viewer.setControls(this.viewer.earthControls); } )); elNavigation.append(this.createToolIcon( Potree.resourcePath + '/icons/fps_controls.svg', '[title]tt.flight_control', () => { this.viewer.setControls(this.viewer.fpControls); this.viewer.fpControls.lockElevation = false; } )); elNavigation.append(this.createToolIcon( Potree.resourcePath + '/icons/helicopter_controls.svg', '[title]tt.heli_control', () => { this.viewer.setControls(this.viewer.fpControls); this.viewer.fpControls.lockElevation = true; } )); elNavigation.append(this.createToolIcon( Potree.resourcePath + '/icons/orbit_controls.svg', '[title]tt.orbit_control', () => { this.viewer.setControls(this.viewer.orbitControls); } )); elNavigation.append(this.createToolIcon( Potree.resourcePath + '/icons/focus.svg', '[title]tt.focus_control', () => { this.viewer.fitToScreen(); } )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/navigation_cube.svg", "[title]tt.navigation_cube_control", () => {this.viewer.toggleNavigationCube()} )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/images/compas.svg", "[title]tt.compass", () => { const visible = !this.viewer.compass.isVisible(); this.viewer.compass.setVisible(visible); } )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/camera_animation.svg", "[title]tt.camera_animation", () => { const animation = CameraAnimation.defaultFromView(this.viewer); viewer.scene.addCameraAnimation(animation); } )); elNavigation.append("
    "); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/left.svg", "[title]tt.left_view_control", () => {this.viewer.setLeftView()} )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/right.svg", "[title]tt.right_view_control", () => {this.viewer.setRightView()} )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/front.svg", "[title]tt.front_view_control", () => {this.viewer.setFrontView()} )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/back.svg", "[title]tt.back_view_control", () => {this.viewer.setBackView()} )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/top.svg", "[title]tt.top_view_control", () => {this.viewer.setTopView()} )); elNavigation.append(this.createToolIcon( Potree.resourcePath + "/icons/bottom.svg", "[title]tt.bottom_view_control", () => {this.viewer.setBottomView()} )); let elCameraProjection = $(` `); elNavigation.append(elCameraProjection); elCameraProjection.selectgroup({title: "Camera Projection"}); elCameraProjection.find("input").click( (e) => { this.viewer.setCameraMode(CameraMode[e.target.value]); }); let cameraMode = Object.keys(CameraMode) .filter(key => CameraMode[key] === this.viewer.scene.cameraMode); elCameraProjection.find(`input[value=${cameraMode}]`).trigger("click"); let speedRange = new THREE.Vector2(1, 10 * 1000); let toLinearSpeed = (value) => { return Math.pow(value, 4) * speedRange.y + speedRange.x; }; let toExpSpeed = (value) => { return Math.pow((value - speedRange.x) / speedRange.y, 1 / 4); }; sldMoveSpeed.slider({ value: toExpSpeed(this.viewer.getMoveSpeed()), min: 0, max: 1, step: 0.01, slide: (event, ui) => { this.viewer.setMoveSpeed(toLinearSpeed(ui.value)); } }); this.viewer.addEventListener('move_speed_changed', (event) => { lblMoveSpeed.html(this.viewer.getMoveSpeed().toFixed(1)); sldMoveSpeed.slider({value: toExpSpeed(this.viewer.getMoveSpeed())}); }); lblMoveSpeed.html(this.viewer.getMoveSpeed().toFixed(1)); } initSettings(){ { $('#sldMinNodeSize').slider({ value: this.viewer.getMinNodeSize(), min: 0, max: 1000, step: 0.01, slide: (event, ui) => { this.viewer.setMinNodeSize(ui.value); } }); this.viewer.addEventListener('minnodesize_changed', (event) => { $('#lblMinNodeSize').html(parseInt(this.viewer.getMinNodeSize())); $('#sldMinNodeSize').slider({value: this.viewer.getMinNodeSize()}); }); $('#lblMinNodeSize').html(parseInt(this.viewer.getMinNodeSize())); } { let elSplatQuality = $("#splat_quality_options"); elSplatQuality.selectgroup({title: "Splat Quality"}); elSplatQuality.find("input").click( (e) => { if(e.target.value === "standard"){ this.viewer.useHQ = false; }else if(e.target.value === "hq"){ this.viewer.useHQ = true; } }); let currentQuality = this.viewer.useHQ ? "hq" : "standard"; elSplatQuality.find(`input[value=${currentQuality}]`).trigger("click"); } $('#show_bounding_box').click(() => { this.viewer.setShowBoundingBox($('#show_bounding_box').prop("checked")); }); $('#set_freeze').click(() => { this.viewer.setFreeze($('#set_freeze').prop("checked")); }); } }