123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 |
- import * as THREE from "../../../libs/three.js/build/three.module.js";
- import {LineDraw, MeshDraw} from "../../utils/DrawUtil.js";
- import math from "../../utils/math.js";
- const verticalLine = new THREE.Line3()
- //控制点和边的合集。具有可以拖拽修改的功能,拖拽时能防止线相交。
- export class ctrlPolygon extends THREE.Object3D {
- constructor (type, prop) {
- super()
- this.type = type
-
- this.maxMarkers = Number.MAX_SAFE_INTEGER;
-
-
- this.transformData(prop);
- for(let i in prop){
- this[i] = prop[i]
- }
-
- if(this.closed && this.dimension == '2d'){
- this.areaPlane = this.createAreaPlane();
- this.add(this.areaPlane)
- }
-
- //数据--刚开始一定是空的
- this.points = [];
- //mesh 不一定有
- this.markers = [];
- this.edges = [];
-
- this.center
-
-
-
-
- }
-
- initData(prop){
- //开始加数据
- if(Potree.settings.editType == 'merge'){ //融合页面没有地图,measure的不需要指定datasetId,每个点都有各自的datasetId,跟着各自的模型走
- if(this.dataset_points){
- this.dataset_points = this.dataset_points.map(e=>{
- return e && new THREE.Vector3().copy(e)
- })
- prop.points = this.dataset_points.map((p,i)=>{
- return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.points_datasets[i], position: p})
- })
- if(prop.points.some(e=>e == void 0)){
- return false
- }
- }else{
- this.dataset_points = []
- }
- }
-
-
-
- if(prop.points){
-
- for(const p of prop.points){
- const pos = new THREE.Vector3().copy(p)
- this.addMarker({point:pos});
- }
-
-
- if(Potree.settings.editType != 'merge'){
- if(this.datasetId != void 0){//初始化位置
- if(this.dataset_points){
- this.dataset_points = this.dataset_points.map(e=>{
- return e && new THREE.Vector3().copy(e)
- })
- this.transformByPointcloud() //根据dataset_points生成points
- }
- }else{
- if(prop.dataset_points && prop.dataset_points.some(e=>e != void 0)){
- console.error('存在测量线的datasetId为空而dataset_points有值,请检查并删除:'+this.sid)//存在过的bug,原因未知,可能是后台处理dataset时替换的错误:http://192.168.0.21/index.php?m=bug&f=view&bugID=23601
- console.log(this)
- }
- }
- }
-
- this.getFacePlane()
- this.getPoint2dInfo(this.points)
-
- this.update({ifUpdateMarkers:true})
- //this.dragChange(new THREE.Vector3().copy(prop.points[prop.points.length-1]), prop.points.length-1);
- this.setSelected(false )
- this.markers.forEach(marker=>{marker.dispatchEvent('addHoverEvent') })
- return true
- }
- }
-
-
-
-
-
- addMarker(o={}){
- var index = o.index == void 0 ? this.points.length : o.index //要当第几个
-
- this.points = [...this.points.slice(0,index), o.point, ...this.points.slice(index,this.points.length)]
- //this.points.push(o.point);
-
- if(o.marker){
- this.add(o.marker)
- this.markers = [...this.markers.slice(0,index), o.marker, ...this.markers.slice(index,this.markers.length)]
- this.updateMarker(o.marker, o.point)
- o.marker.addEventListener('drag', this.dragMarker.bind(this));
- o.marker.addEventListener('drop', this.dropMarker.bind(this));
-
-
- let addHoverEvent = (e)=>{
- let mouseover = (e) => {
- this.setMarkerSelected(e.object, 'hover', 'single');
- viewer.dispatchEvent({
- type : "CursorChange", action : "add", name:"markerMove"
- })
- };
- let mouseleave = (e) => {
- this.setMarkerSelected(e.object, 'unhover', 'single');
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"markerMove"
- })
- }
- o.marker.addEventListener('mouseover', mouseover);
- o.marker.addEventListener('mouseleave', mouseleave);
- o.marker.removeEventListener('addHoverEvent',addHoverEvent)
- }
- o.marker.addEventListener('addHoverEvent',addHoverEvent)//当非isNew时才添加事件
- if(!this.isNew){
- o.marker.dispatchEvent('addHoverEvent')
- }
-
- }
-
- if(o.edge){
- this.add(o.edge)
- this.edges = [...this.edges.slice(0,index), o.edge, ...this.edges.slice(index,this.edges.length)]
- }
-
-
- }
-
-
-
-
- dragMarker(e){
-
- var I, atMap
-
- if(e.hoverViewport != e.drag.dragViewport){//不能使用e.dragViewport,要使用drag中的,因为drag中存储的要一直继承下来,不因mouseup了而改变。
- viewer.dispatchEvent({
- type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
- })
- return
- }
-
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
- })
-
- atMap = e.drag.dragViewport.name == 'mapViewport'
-
- if(atMap && this.unableDragAtMap){
- e.drag.object = null //取消拖拽
- return
- }
- e.drag.object.isDragging = true
-
-
- I = e.intersect && (e.intersect.orthoIntersect || e.intersect.location)
-
- //记录数据集
-
- //在三维中脱离点云(在map中拉到周围都没有点云的地方)的顶点,无法拖拽怎么办
-
- if (I) {
- let i = this.markers.indexOf(e.drag.object);
- if (i !== -1) {
- this.dragChange(I.clone(), i, atMap)
-
- /* if(this.points_datasets){
- if(e.intersect.pointcloud) this.points_datasets[i] = e.intersect.pointcloud.dataset_id
- else this.points_datasets[i] = null
- } */
- if(this.points_datasets){
- if(e.intersect.pointcloud) this.points_datasets[i] = e.intersect.pointcloud.dataset_id
- else if(e.intersect.object) this.points_datasets[i] = e.intersect.object.dataset_id
- else this.points_datasets[i] = null
- }
- }
- this.editStateChange(true)
- return true
- }
-
-
-
-
- };
-
-
-
-
-
-
- dragChange(intersectPos, i, atMap){
- let len = this.markers.length
- let oldPoint = this.points[i];
- if(atMap){
- intersectPos.setZ(oldPoint.z) //在地图上拖拽,不改变其高度。
- }
- let location = intersectPos.clone()
-
-
-
- if(this.faceDirection && this.maxMarkers == 2 && len == 2){//add 固定方向的点不直接拖拽
- var p1 = this.markers[0].position
- if(this.faceDirection == 'horizontal'){
- var projectPos = location.clone().setZ(p1.z)
- }else{
- var projectPos = p1.clone().setZ(location.z)
- }
- //var p2 = p1.clone().add(this.direction)
- //var projectPos = math.getFootPoint(location, p1, p2)
-
-
- LineDraw.updateLine(this.guideLine, [location, projectPos])
- location = projectPos
- this.guideLine.visible = true
- }else if( len > 1){
-
- var points = this.points.map(e=>e.clone())
- points[i].copy(location) //算normal需要提前确认point
-
- //若为定义了面朝向的矩形
- if(this.faceDirection == 'horizontal'){
- if(len == 2){
- location.setZ(points[0].z)
- }
- if(!this.facePlane){//一个点就能确定面
- this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3(0,0,1), this.points[0] )
- }
- }else if(this.faceDirection == 'vertical'){//当有两个点时, 有两个方向的可能
- if(len == 2){
- if(this.isRect){
- let vec = points[0].clone().sub(location)
- if(Math.sqrt(vec.x*vec.x+vec.y*vec.y) > Math.abs(vec.z) ){//水平(高度差小于水平距离时)
- location.setZ(points[0].z)
- //this.cannotConfirmNormal = false;//能确定面为水平方向
- }else{//垂直 (当两点一样时也属于这种)
- location.setX(points[0].x);
- location.setY(points[0].y);
- //this.cannotConfirmNormal = true; //不能确定面,因第三点可绕着纵轴线自由移动
- }
- }
- }else{
- {//判断cannotConfirmNormal. 如果前几段都在竖直线上,就不能固定出面方向。
- this.cannotConfirmNormal = true
- let max = this.isRect ? 1 : len-2
- for(let i=0;i<max;i++){
- let p1 = points[i].clone()
- let p2 = points[i+1].clone()
- let vec = p1.sub(p2);
- if(vec.x != 0 || vec.y != 0){
- this.cannotConfirmNormal = false
- break;
- }
- }
- }
-
- if(!this.facePlane || this.cannotConfirmNormal){//三个点且为水平方向时,计算面
-
- var points_ = points.map(e=>new THREE.Vector2(e.x,e.y))
- var points2 = getDifferentPoint(points_, 2);
- if(points2){
- let normal = math.getNormal2d({p1:points2[0], p2:points2[1]})
- normal = new THREE.Vector3(normal.x, normal.y, 0)
- this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( normal, this.points[0] )
- }
- }
- }
- }
- if(len > 2){//area
-
- if(!this.faceDirection){
- if(len == 3 || this.isRect) this.cannotConfirmNormal = true //当第三个点固定后(有四个点时)才能固定面
- if(!this.facePlane || this.cannotConfirmNormal){
- var points3 = getDifferentPoint(points, 3);//只有找到三个不同的点算拥有面和area
- if(points3){
- this.facePlane = new THREE.Plane().setFromCoplanarPoints(...points3 )
- }
- }
- }
-
- if( this.facePlane && !this.cannotConfirmNormal ){//之后加的点一定要在面上
- if(atMap){
- //地图上用垂直线,得到和面的交点。
- verticalLine.set(location.clone().setZ(100000), location.clone().setZ(-100000))//确保长度范围覆盖所有测量面
- location = this.facePlane.intersectLine(verticalLine, new THREE.Vector3() )
- if(!location) return;
- }else{
- location = this.facePlane.projectPoint(intersectPos, new THREE.Vector3() )
- }
- }
-
-
- points[i].copy(location)//再copy确认一次
-
- if(this.isRect){ //是矩形 (即使没有faceDirection也能执行)
- //根据前两个点计算当前和下一个点
- var p1 = points[(i-2+len)%len]
- var p2 = points[(i-1+len)%len]
- if(p1.equals(p2)){//意外情况:重复点两次 ( bug点,改了好多遍)
- if(this.faceDirection == 'vertical'){
- p2.add(new THREE.Vector3(0,0,0.0001))
- }else{
- p2.add(new THREE.Vector3(0,0.0001,0))
- }
- }
- //p3 : location
- var foot = math.getFootPoint(location, p1, p2)//p2 修改p2到垂足的位置
- var vec = foot.clone().sub(location)
- var p4 = p1.clone().sub(vec)
-
-
- points[(i-1+len)%len].copy(foot)
- points[(i+1)%len].copy(p4)
- this.setPosition((i-1+len)%len, foot);//p2
- this.setPosition((i+1)%len, p4);
-
- }
-
- /* let points2d;
- if(this.facePlane){
- var originPoint0 = points[0].clone()
- var qua = math.getQuaBetween2Vector(this.facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
- points2d = points.map(e=>e.clone().applyQuaternion(qua))
- } */
- this.getPoint2dInfo(points)
-
- var isIntersectSelf = !this.isRect && len > 3 && this.intersectSelf(this.point2dInfo.points2d)//检测相交
- if(isIntersectSelf){
- //not-allowed
- viewer.dispatchEvent({
- type : "CursorChange", action : "add", name:"polygon_isIntersectSelf"
- })
- this.isIntersectSelf = true
- return
- }else{
- this.isIntersectSelf = false
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_isIntersectSelf"
- })
- /* this.facePlane && (this.point2dInfo = {
- originPoint0 ,
- points2d,
- quaInverse : qua.clone().invert()
- }) */
- }
-
-
-
- }
-
- var showGuideLine = len>1 && (this.faceDirection || len > 3)
- if(showGuideLine && this.guideLine){
- LineDraw.updateLine(this.guideLine, [intersectPos, location])
- this.guideLine.visible = true
- }
-
- //console.log(this.points.map(e=>e.toArray()))
- }
-
-
- if(this.restrictArea){
- let holes = this.restrictArea.holes.concat(this.restrictArea.parentHoles)
- let holesPoints = holes.filter(e=>e!=this && e.points.length>2).map(e=>e.points)
- if(!math.isPointInArea(this.restrictArea.points, holesPoints, location)){
- viewer.dispatchEvent({
- type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
- })
- this.isAtWrongPlace = true
- return
- }
- //就不处理相交线了。 有个缺点:floor上的hole可以限制room,但hole不受room限制,会导致room的marker被框在hole里而动不了。只能去调整hole了
- }
-
-
-
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
- })
- this.isAtWrongPlace = false
- this.setPosition(i, location);
- this.update()
-
- this.dispatchEvent({type:'dragChange', index:i})
-
-
-
- }
-
- dropMarker(e){
- //console.log('dropMarker')
- if (this.isNew && e.pressDistance>Potree.config.clickMaxDragDis){//拖拽的话返回
- return this.continueDrag(null,e)
- }
-
- if(e.isTouch){
- if(e.hoverViewport != viewer.mainViewport && this.unableDragAtMap){
- viewer.dispatchEvent({type:'reticule_forbit', v:true})
- //console.log('reticule_forbit',true)
- return this.continueDrag(null,e)
- }else{
- viewer.dispatchEvent({type:'reticule_forbit', v:false})
- //console.log('reticule_forbit',false)
- }
- this.dragMarker(e) //触屏时必须先更新下点
-
- }
-
-
- if (e.button != THREE.MOUSE.RIGHT && (//右键click的话继续执行,因为会停止
- this.isIntersectSelf && this.isNew //有线相交了
- || this.isAtWrongPlace && this.isNew
- || !e.isAtDomElement && this.isNew//如果是刚添加时在其他dom点击, 不要响应
- || e.hoverViewport != viewer.mainViewport && this.unableDragAtMap //垂直的测量线不允许在地图上放点
- || this.isNew && !getDifferentPoint(this.points, this.points.length ) //不允许和之前的点相同, 但这句在点云稀疏时会导致难结束
- )
- ){
- return this.continueDrag(null,e)
- }
-
- //console.log('drop marker' )
-
- let i = this.markers.indexOf(e.drag.object);
- if (i !== -1) {
- this.dispatchEvent({
- 'type': 'marker_dropped',
- 'index': i
- });
- if(this.markers.length>2 && this.facePlane)this.cannotConfirmNormal = false
- this.guideLine &&(this.guideLine.visible = false)
- }
-
-
-
- this.setMarkerSelected(e.drag.object, 'unhover', 'single')
-
- this.editStateChange(false)
-
-
-
-
- e.drag.endDragFun && e.drag.endDragFun(e)// addmarker
-
- //if(this.changeCallBack)this.changeCallBack()
-
- return true
- };
-
- getFacePlane(){//最普通一种get方法,根据顶点。且假设所有点已经共面,且不重合
- if(this.points.length<3) return
- this.facePlane = new THREE.Plane().setFromCoplanarPoints(...this.points.slice(0,3) )
-
- }
-
- getPoint2dInfo(points){ //在更新areaplane之前必须更新过point2dInfo
- if(this.facePlane){
- var originPoint0 = points[0].clone()
- var qua = math.getQuaBetween2Vector(this.facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
- let points2d = points.map(e=>e.clone().applyQuaternion(qua))
-
- this.point2dInfo = {
- originPoint0 ,
- points2d,
- quaInverse : qua.clone().invert()
- }
- }
- }
-
-
-
-
- setPosition (index, position) {//拖拽后设置位置
- let point = this.points[index];
- point.copy(position);
- /* if(this.datasetId){
- this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.datasetId, position:point.clone()})
- } */
-
- /* if(Potree.settings.editType == 'merge'){
- this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true,this.points_datasets[i], position:point.clone()})
- } */
-
- let marker = this.markers[index];
- this.updateMarker(marker, point)
-
-
- }
-
- updateMarker(marker, pos){
- marker.position.copy(pos);
- marker.update();
- }
-
-
- intersectSelf(points2d){//add
- var len = points2d.length
- for(var i=0;i<len;i++){
- for(var j=i+2;j<len;j++){
- if(Math.abs(j-len-i)<2)continue;//不和邻边比
-
- var p1 = points2d[i]
- var p2 = points2d[i+1]
- var p3 = points2d[j]
- var p4 = points2d[(j+1)%len]
- if(p1.equals(p2) || p3.equals(p4) || p1.equals(p3) || p2.equals(p3) || p1.equals(p4) || p2.equals(p4))continue
-
-
- var line1 = [p1,p2]
- var line2 = [p3,p4]
- var intersect = math.isLineIntersect(line1, line2, false, 0.001)
- if(intersect){
- return true
- break
- }
- }
- }
-
- }
-
- removeMarker (index) {
-
- this.points.splice(index, 1);
-
- const marker = this.markers[index]
- //this.remove(marker);
- this.markers.splice(index, 1);
- marker.dispatchEvent({type:'dispose'})
-
-
- let edgeIndex = index //(index === 0) ? 0 : (index - 1);
- const edge = this.edges[edgeIndex]
- if(edge){
- this.remove(edge);
- this.edges.splice(edgeIndex, 1);
- edge.dispatchEvent({type:'dispose'})
- }
- this.point2dInfo && this.point2dInfo.points2d.splice(index, 1); //add
- this.dispatchEvent({type:'removeMarker',index,marker})
-
-
- }
-
- createAreaPlane(mat){
- var geometry = new THREE.Geometry();
- var mesh = new THREE.Mesh(geometry, mat)
-
- return mesh
- }
-
- updateAreaPlane(){
- if(!this.point2dInfo)return
- this.areaPlane.geometry.dispose()
- if(this.points.length>2){
- this.areaPlane.geometry = MeshDraw.getShapeGeo(this.point2dInfo.points2d)
- var center = math.getCenterOfGravityPoint(this.point2dInfo.points2d) //重心
-
- var firstPos = this.point2dInfo.points2d[0].clone()
- firstPos.z = 0 //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
- firstPos.applyQuaternion(this.point2dInfo.quaInverse)
- var vec = this.point2dInfo.originPoint0.clone().sub(firstPos)
- center = new THREE.Vector3(center.x, center.y, 0)
- center.applyQuaternion(this.point2dInfo.quaInverse)
- this.areaPlane.quaternion.copy(this.point2dInfo.quaInverse)
- this.areaPlane.position.copy(vec)
- center.add(vec)
- this.center = center
- }else{
- this.areaPlane.geometry = new THREE.Geometry()
-
- }
-
-
- }
-
-
-
-
- update(options={}){
- if(this.points.length === 0){
- return;
- }
-
-
-
-
-
- let lastIndex = this.points.length - 1;
-
-
- for (let index = 0; index <= lastIndex; index++) {
-
- let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
- let previousIndex = (index === 0) ? lastIndex : index - 1;
- let point = this.points[index];
- let nextPoint = this.points[nextIndex];
- let previousPoint = this.points[previousIndex];
- if(options.ifUpdateMarkers){
- this.updateMarker(this.markers[index], point)
- }
- { // edges
- let edge = this.edges[index];
- if(edge){
- LineDraw.updateLine(edge, [point, nextPoint])
- //edge.visible = index < lastIndex || this.isRect || (this.closed && !this.isNew);
- }
-
-
- }
-
-
- }
-
- if(this.areaPlane){
- this.updateAreaPlane()
- }
-
- //this.dispatchEvent({type:'update'})
- viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed') //暂时先这么都通知
-
- }
-
- dispose(){//add
- this.parent.remove(this)
- this.markers.concat(this.edges).forEach(e=>e.dispatchEvent({type:'dispose'}))
- }
-
-
- reDraw(restMarkerCount=0){//重新开始画
- let pointCount = this.points.length - restMarkerCount // restMarkerCount为需要留下的marker数量
- while(pointCount > 0){
- this.removeMarker(--pointCount)
- }
- this.point2dInfo = null
- this.facePlane = null
-
-
-
- }
-
-
- setMarkerSelected(){}
- editStateChange(state){
- if(!state){
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_isIntersectSelf"
- })
- viewer.dispatchEvent({
- type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
- })
- viewer.dispatchEvent({type:'reticule_forbit', v:false})
-
- this.markers.forEach(e=>e.isDragging = false )
- }
- }
-
- transformData(){}
- setSelected(){}
-
-
-
- continueDrag(marker, e){
- let object = marker || e.drag.object
- object.isDragging = true
- var timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
- if(this.parent && object.isDragging){
- //console.log('continueDrag')
- viewer.inputHandler.startDragging( object ,
- {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport}
- )
- }
- },1)
- return timer
- }
-
-
- }
- function getDifferentPoint(points, count){//for facePlane
- var result = [];
- for(let i=0;i<points.length;i++){
- var p = points[i];
- if(result.find(e=>e.equals(p)))continue;
- else result.push(p)
- if(result.length == count)break
- }
- if(result.length == count)return result
- }
-
-
|