123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- import * as THREE from "../../libs/three.js/build/three.module.js";
- import {Measure} from "./Measure.js";
- import {Utils} from "../utils.js";
- import math from "./math.js";
- import {CameraMode,MOUSE} from "../defines.js";
- import { EventDispatcher } from "../EventDispatcher.js";
-
- function updateAzimuth(viewer, measure){
- if(!measure.showAzimuth)return
- const azimuth = measure.azimuth;
- const isOkay = measure.points.length === 2;
- azimuth.node.visible = isOkay
- if(!azimuth.node.visible){
- return;
- }
- const camera = viewer.scene.getActiveCamera();
- const renderAreaSize = viewer.renderer.getSize(new THREE.Vector2());
- const width = renderAreaSize.width;
- const height = renderAreaSize.height;
-
- const [p0, p1] = measure.points;
- const r = p0.position.distanceTo(p1.position);
- const northVec = Utils.getNorthVec(p0.position, r, viewer.getProjection());
- const northPos = p0.position.clone().add(northVec);
- azimuth.center.position.copy(p0.position);
- azimuth.center.scale.set(2, 2, 2);
-
- azimuth.center.visible = false;
- // azimuth.target.visible = false;
- { // north
- azimuth.north.position.copy(northPos);
- azimuth.north.scale.set(2, 2, 2);
- let distance = azimuth.north.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, width, height);
- let scale = (5 / pr);
- azimuth.north.scale.set(scale, scale, scale);
- }
- { // target
- azimuth.target.position.copy(p1.position);
- azimuth.target.position.z = azimuth.north.position.z;
- let distance = azimuth.target.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, width, height);
- let scale = (5 / pr);
- azimuth.target.scale.set(scale, scale, scale);
- }
-
- azimuth.circle.position.copy(p0.position);
- azimuth.circle.scale.set(r, r, r);
- azimuth.circle.material.resolution.set(width, height);
- // to target
- azimuth.centerToTarget.geometry.setPositions([
- 0, 0, 0,
- ...p1.position.clone().sub(p0.position).toArray(),
- ]);
- azimuth.centerToTarget.position.copy(p0.position);
- azimuth.centerToTarget.geometry.verticesNeedUpdate = true;
- azimuth.centerToTarget.geometry.computeBoundingSphere();
- azimuth.centerToTarget.computeLineDistances();
- azimuth.centerToTarget.material.resolution.set(width, height);
- // to target ground
- azimuth.centerToTargetground.geometry.setPositions([
- 0, 0, 0,
- p1.position.x - p0.position.x,
- p1.position.y - p0.position.y,
- 0,
- ]);
- azimuth.centerToTargetground.position.copy(p0.position);
- azimuth.centerToTargetground.geometry.verticesNeedUpdate = true;
- azimuth.centerToTargetground.geometry.computeBoundingSphere();
- azimuth.centerToTargetground.computeLineDistances();
- azimuth.centerToTargetground.material.resolution.set(width, height);
- // to north
- azimuth.centerToNorth.geometry.setPositions([
- 0, 0, 0,
- northPos.x - p0.position.x,
- northPos.y - p0.position.y,
- 0,
- ]);
- azimuth.centerToNorth.position.copy(p0.position);
- azimuth.centerToNorth.geometry.verticesNeedUpdate = true;
- azimuth.centerToNorth.geometry.computeBoundingSphere();
- azimuth.centerToNorth.computeLineDistances();
- azimuth.centerToNorth.material.resolution.set(width, height);
- // label
- const radians = Utils.computeAzimuth(p0.position, p1.position, viewer.getProjection());
- let degrees = THREE.Math.radToDeg(radians);
- if(degrees < 0){
- degrees = 360 + degrees;
- }
- const txtDegrees = `${degrees.toFixed(2)}°`;
- const labelDir = northPos.clone().add(p1.position).multiplyScalar(0.5).sub(p0.position);
- if(labelDir.length() > 0){
- labelDir.z = 0;
- labelDir.normalize();
- const labelVec = labelDir.clone().multiplyScalar(r);
- const labelPos = p0.position.clone().add(labelVec);
- azimuth.label.position.copy(labelPos);
- }
- azimuth.label.setText(txtDegrees);
- let distance = azimuth.label.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, width, height);
- let scale = (70 / pr);
- azimuth.label.scale.set(scale, scale, scale);
- }
- export class MeasuringTool extends EventDispatcher{
- constructor (viewer) {
- super();
- this.viewer = viewer;
- this.renderer = viewer.renderer;
- this.viewer.addEventListener('start_inserting_measurement', e => {
- this.viewer.dispatchEvent({
- type: 'cancel_insertions'
- });
- });
- this.showLabels = true;
- this.scene = new THREE.Scene();
- this.scene.name = 'scene_measurement';
- //this.light = new THREE.PointLight(0xffffff, 1.0);
- //this.scene.add(this.light);
- this.viewer.inputHandler.registerInteractiveScene(this.scene);
-
-
- //this.scene = viewer.overlay//
-
-
- this.onRemove = (e) => { e.measurement.dispose()/* this.scene.remove(e.measurement); */};
- this.onAdd = e => {this.scene.add(e.measurement);};
- for(let measurement of viewer.scene.measurements){
- this.onAdd({measurement: measurement});
- }
-
- viewer.addEventListener('camera_changed',(e)=>{
- if(e.viewport == viewer.mainViewport ) this.update()
- })
-
-
- //viewer.addEventListener("update", this.update.bind(this));
- viewer.addEventListener("render.pass.perspective_overlay", this.render.bind(this));
- viewer.addEventListener("scene_changed", this.onSceneChange.bind(this));
- viewer.scene.addEventListener('measurement_added', this.onAdd);
- viewer.scene.addEventListener('measurement_removed', this.onRemove);
-
- viewer.addEventListener('resize',this.setSize.bind(this))
-
- }
- onSceneChange(e){
- if(e.oldScene){
- e.oldScene.removeEventListener('measurement_added', this.onAdd);
- e.oldScene.removeEventListener('measurement_removed', this.onRemove);
- }
- e.scene.addEventListener('measurement_added', this.onAdd);
- e.scene.addEventListener('measurement_removed', this.onRemove);
- }
-
-
- createMeasureFromData(data){//add
- const measure = new Measure(data);
-
- viewer.scene.addMeasurement(measure);
-
- if(measure.guideLine)measure.guideLine.visible = false
- return measure
- }
-
-
- update(){
- return;
-
-
-
-
- let camera = this.viewer.scene.getActiveCamera();
- let domElement = this.renderer.domElement;
- let measurements = this.viewer.scene.measurements;
-
- // make size independant of distance
- let mainLabels = [], subLabels = [];
-
-
-
- for (let measure of measurements) {
- measure.lengthUnit = this.viewer.lengthUnit;
- measure.lengthUnitDisplay = this.viewer.lengthUnitDisplay;
- //measure.update();
- updateAzimuth(this.viewer, measure);
-
- /* [...measure.markers, ...measure.edgeLabels, measure.areaLabel].forEach(e=>{
- e && e.update()
- }); */
-
- // labels
- /* let labels = measure.edgeLabels.concat(measure.angleLabels);
- for(let label of labels){
- label.update()
- if(label.elem.hasClass('sub')){
- subLabels.push(label)
- }else{
- mainLabels.push(label)
- }
- }
- // coordinate labels
- for (let j = 0; j < measure.coordinateLabels.length; j++) {
- let label = measure.coordinateLabels[j];
- label.update()
- mainLabels.push(label)
- }
-
- if(measure.showArea){ // area label
- let label = measure.areaLabel;
- label.update()
- mainLabels.push(label)
- } */
-
-
- /* if(measure.showCircle){ // radius label
- let label = measure.circleRadiusLabel;
- let distance = label.position.distanceTo(camera.position);
- let pr = Utils.projectedRadius(1, camera, distance, clientWidth, clientHeight);
- let scale = (70 / pr);
- label.scale.set(scale, scale, scale);
- } */
- if(!this.showLabels){
- const labels = [
- ...measure.sphereLabels,
- ...measure.angleLabels,
- measure.circleRadiusLabel,
- ];
- for(const label of labels){
- label.visible = false;
- }
- }
- }
- //this.updateLabelZIndex([{labels:subLabels},{labels:mainLabels}])
-
- }
- setSize(e){ //e.resolution
- /* if(Measure.lineMats){
- for(var m in Measure.lineMats){
- Measure.lineMats[m].resolution.set(e.canvasWidth, e.canvasHeight);
- }
- }
- if(Measure.sphereMats){
- for(var s in Measure.sphereMats){
- Measure.sphereMats[s].uniforms.resolution.value.set(e.canvasWidth, e.canvasHeight);
- }
- }
- for (let measure of this.viewer.scene.measurements) {
- measure.edgeLabels.concat(measure.areaLabel).forEach(label=>{
- label.sprite.material.uniforms.resolution.value.set(e.canvasWidth, e.canvasHeight);
- })
- } */
- }
-
- updateLabelZIndex(group){//[{labels:[]},{}] 顺序按照z-index低到高
-
- group.forEach((e,i)=>{
- e.base = group[i-1] ? group[i-1].base + group[i-1].labels.length : 0
-
- var labels = e.labels.sort((a,b)=>{
- return b.pos2d.z - a.pos2d.z
- })
- labels.forEach((label,index)=>{
- $(label.elem).css('z-index', e.base+index)
- })
- })
-
- }
-
-
-
-
- editStateChange(e){
- //console.log("editStateChange" , e.state)
- let state = e.state
- if(!state){
- state = viewer.scene.measurements.some(e=>e.isEditing)
- }
-
- if(state){
- viewer.dispatchEvent({type:"measureMovePoint"})
- }else{
- viewer.dispatchEvent({type:"endMeasureMove"})
- }
-
-
- //this.editing =
- }
-
-
-
- startInsertion (args = {}, callback, cancelFun) {
-
-
- let domElement = this.viewer.renderer.domElement;
-
- const pick = (defaul, alternative) => {
- if(defaul != null){
- return defaul;
- }else{
- return alternative;
- }
- };
- args.showDistances = (args.showDistances === null) ? true : args.showDistances;
- args.showArea = pick(args.showArea, false);
- args.showAngles = pick(args.showAngles, false);
- args.showCoordinates = pick(args.showCoordinates, false);
- args.showHeight = pick(args.showHeight, false);
- args.showCircle = pick(args.showCircle, false);
- args.showAzimuth = pick(args.showAzimuth, false);
- args.showEdges = pick(args.showEdges, true);
- args.closed = pick(args.closed, false);
- args.maxMarkers = pick(args.maxMarkers, Infinity);
- args.direction = args.direction//add
- args.type = args.type /* || 'Measurement'; */
- args.showGuideLine = pick(args.showGuideLine, false);
- args.isRect = pick(args.isRect, false);
-
-
- let measure = new Measure(args);
- this.scene.add(measure);
- measure.isNew = true
-
-
- this.viewer.dispatchEvent({
- type: 'start_inserting_measurement',
- measure: measure
- });
-
- measure.addEventListener('editStateChange', this.editStateChange.bind(this))
- measure.editStateChange(true)
-
- let timer;
- let continueDrag = (marker)=>{
- timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
- this.viewer.inputHandler.startDragging(marker,
- {endDragFun, notPressMouse:true}
- );
- },1)
- }
- let endDragFun = (e) => {
- if (e.button == THREE.MOUSE.LEFT /* e.drag.mouse == MOUSE.LEFT */) {
- if (measure.points.length >= measure.maxMarkers) {
- end({finish:true});
- }else{
- if(measure.points.length == 1){//点击第一下,恢复可见
- measure.markers[0].visible = true;
- }
-
- var marker = measure.addMarker({point:measure.points[measure.points.length - 1].clone()})
-
- if(args.isRect && measure.markers.length == 3){
- measure.addMarker({point:measure.points[0].clone()})
- }
- measure.editStateChange(true) //重新激活reticule状态
- continueDrag(marker)
- }
-
- } else if (e.button === THREE.MOUSE.RIGHT /* e.drag.mouse === MOUSE.RIGHT */) {
- if(e.pressDistance < Potree.config.clickMaxDragDis )end(e);//非拖拽的话
- else continueDrag(e.drag.object)
-
- }
- };
- let end = (e={}) => {//确定、结束
- if(!measure.isNew)return
- if(args.minMarkers != void 0){
- if(!e.finish && measure.markers.length<=args.minMarkers){//右键 当个数不够时取消
- //this.viewer.scene.removeMeasurement(measure)
- //cancelFun && cancelFun()
- //重新开始画
- measure.reDraw()
-
-
- this.viewer.addEventListener('global_click', click, 10)
-
- measure.editStateChange(true)
- return
-
- /* if(!Potree.settings.isOfficial) this.viewer.scene.removeMeasurement(measure)
- else if(e.drag){ //正式版本不允许右键退出, 继续
- continueDrag(e.drag.object)
- measure.editStateChange(true)
- return
- } */
- }
- }
- if (!e.finish && measure.markers.length > 3) {
- measure.removeMarker(measure.points.length - 1);
- }
- measure.isNew = false
- clearTimeout(timer)
- this.viewer.removeEventListener('cancel_insertions', Exit);
- //pressExit && this.viewer.inputHandler.removeEventListener('keydown', pressExit);
- this.viewer.removeEventListener('global_click', click)
- this.viewer.removeEventListener('global_mousemove', ifAtWrongPlace)
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
- });
- e.remove || callback && callback()
- /* this.viewer.dispatchEvent({
- type: 'finish_inserting_measurement',
- measure: measure
- }); */
- };
-
- let Exit = (e)=>{//强制退出
-
- if(e.measure && e.measure != measure){
- return;//若指定了退出的measure但和该measure不一致,就返回
- }
- console.log('Exit: ' + measure.id)
- if(e.remove){
- viewer.scene.removeMeasurement(measure)
- }
- if(this.viewer.inputHandler.drag && !e.remove){//还未触发drop的话
- this.viewer.inputHandler.drag.object.dispatchEvent({
- type: 'drop',
- drag: this.viewer.inputHandler.drag,
- viewer: this.viewer,
- pressDistance:0,
- button : THREE.MOUSE.RIGHT
- });
-
- }else{
- end({finish:true, remove:e.remove}) //未结束时添加新的measure时会触发
- }
- this.viewer.inputHandler.drag = null
- measure.editStateChange(false)
- }
- this.viewer.addEventListener('cancel_insertions', Exit);
-
-
- /*let pressExit
- if(!Potree.settings.isOfficial){
- pressExit = (e)=>{
- if(e.keyCode == 27){//Esc
- //Exit()
- //怎么模拟右键???//现由前端发出
- }
- }
- this.viewer.inputHandler.addEventListener('keydown', pressExit)
- } */
-
-
-
- let click = (e)=>{//一旦点击就立刻增加两marker
- if(measure.unableDragAtMap && e.viewport.name == 'mapViewport' )return
- var marker = measure.addMarker({point:new THREE.Vector3(0, 0, 0)})
- this.viewer.inputHandler.startDragging(marker , {endDragFun, notPressMouse:true} ); //notPressMouse代表不是通过按下鼠标来拖拽
- e.drag = this.viewer.inputHandler.drag
- e.drag.endDragFun = endDragFun
- e.drag.notPressMouse = true
- e.intersectPoint = this.viewer.inputHandler.intersectPoint
- measure.dragMarker(e)
- measure.dropMarker(e)
-
- this.viewer.removeEventListener('global_click', click)///* global_drop */
-
- return {stopContinue:true}//防止继续执行别的侦听,如flytopano
- }
- this.viewer.addEventListener('global_click', click, 10)//add importance:10
-
- let ifAtWrongPlace = (e)=>{
- if(measure.unableDragAtMap && e.hoverViewport.name == 'mapViewport' ){
- viewer.dispatchEvent({
- type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
- });
- }else{
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
- });
- }
- }
- if(measure.unableDragAtMap){
- this.viewer.addEventListener('global_mousemove', ifAtWrongPlace)
- }
-
-
- this.viewer.scene.addMeasurement(measure);
-
- return measure;
- }
-
-
- render(o={}){
- viewer.setCameraLayers(o.camera, ['measure'])
- this.viewer.renderer.render(this.scene, o.camera/* this.viewer.scene.getActiveCamera() */);
- }
- };
|