| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744 |
- import * as THREE from "../../../../libs/three.js/build/three.module.js";
- import {TextSprite} from "../TextSprite.js";
- import {Utils} from "../../../utils.js";
- import Label from "../Label.js";
- import {LineDraw} from "../../utils/DrawUtil.js";
- import math from "../../utils/math.js";
- import DepthBasicMaterial from "../../materials/DepthBasicMaterial.js";
- import BasicMaterial from '../../materials/BasicMaterial.js'
- import Sprite from '../Sprite.js'
- import {config} from '../../settings.js'
- import browser from "../../utils/browser.js";
- import {ctrlPolygon} from './ctrlPolygon.js'
-
-
- let texLoader = new THREE.TextureLoader()
- let defaultColor = new THREE.Color(config.measure.default.color);
- let highlightColor = new THREE.Color(config.measure.highlight.color);
- let color = new THREE.Color(config.measure.color)
- let textColor = new THREE.Color(config.measure.textColor)
- let markerMaps
-
- const textSizeRatio = math.linearClamp(window.outerWidth * window.outerHeight , [360*720, 1920*1080], [0.7, 1]) //pc字显示大一些 用
-
- const lineDepthInfo = {
- clipDistance : 15,//4,//消失距离
- occlusionDistance: 3,//1,//变为backColor距离
- }
-
- const markerMapShrink = browser.isMobile() ? 0.4 : 0.8 //触屏需要更大的热区
- const markerSizeInfo = {
- width2d : 18 / markerMapShrink , // nearBound : 1.5, farBound : 15,
- }
- /* const markerSizeInfo = {
- minSize : 10 , maxSize : 15 , nearBound : 1.5, farBound : 15,
- } */
- const labelSizeInfo = {width2d:200}
-
- const mainLabelProp = {
- //backgroundColor: {r: defaultColor.r*255, g: defaultColor.g*255, b: defaultColor.b*255, a:config.measure.default.opacity},
- backgroundColor: {r: 0, g: 0, b: 0, a:0},
- textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
- textBorderColor: {r:255, g: 255, b:255, a: 1.0},
- textBorderThick:3 ,
- fontsize: 14 * textSizeRatio,
- borderRadius : 12, margin:{x:20,y:4},
- renderOrder : Potree.config.renderOrders.measureLabel,
- pickOrder: Potree.config.renderOrders.measureLabel,
- transform2D: {x:0, y:-0.15},
-
- useDepth : true ,
- // 2023.10 尽量不让数字被挡住
- clipDistance : 10,//消失距离
- occlusionDistance: 10,//变为backColor距离
- maxOcclusionFactor:0.3,
- maxClipFactor:0.8,
- maxLineWidth: 300,
- lineSpace:6
-
- }
- const subLabelProp = {
- backgroundColor: {r: 255, g: 255, b: 255, a:0},
- textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
- textBorderColor: {r:255, g: 255, b:255, a: 1.0},
- textBorderThick:3 ,
- fontsize: 13 * textSizeRatio,
- renderOrder : Potree.config.renderOrders.measureLabelSub,
- pickOrder: Potree.config.renderOrders.measureLabelSub,
- transform2D: {x:0, y:-0.13},
- }
-
- const angle = THREE.Math.degToRad(config.measure.guideLineMinAngle || 5); //显示水平垂直辅助线的最小角度
- const guideShowMinAngle = {min: angle, max: Math.PI/2 - angle}
-
-
- export class Measure extends ctrlPolygon{
- constructor (prop) {
- prop.dimension = '2d'
- super('measure',prop);
- this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
-
-
- this.name = this.name || this.measureType + this.constructor.counter
- this.selectStates = {}
-
- this.edgeLabels = [];
- this.coordinateLabels = [];
- this.area = {value:0,string:''}
- this.expands = []
-
- if( this.showArea ){
- this.areaLabel = this.createAreaLabel();
- this.add(this.areaLabel)
- }
-
-
-
- //add:
- if(this.atPlane || this.faceDirection){ //是一个平面上的话
- this.createGuideLine();
- }
- if(this.measureType == 'Distance' /* || this.measureType.includes('MulDistance') */){
- this.createHorVerGuideLine()
- }
-
-
-
-
- this.setUnitSystem(prop.unit || viewer.unitConvert.UnitService.defaultSystem)
- //Potree.Utils.setObjectLayers(this, 'measure' ) //取消:scene单独渲染应该不需要设置layer
-
-
- if(this.measureType == 'MulDistance' || this.measureType == 'Hor MulDistance' || this.measureType == 'Ver MulDistance'){
- //this.showTotalDis = true
- this.totalDisLabel = this.createTotalDisLabel()
- this.add(this.totalDisLabel)
- }
-
-
- //addMarkers:
-
- this.initData(prop)
- this.pointsPos2d = new Map //屏幕上的二维坐标
-
- this.points_datasets || (this.points_datasets = []) //存每个点是哪个数据集
-
-
-
- this.addEventListener('marker_dropped',(e)=>{
- this.updateDatasetBelong(e.index)
- })
-
- this.addEventListener('isVisible', ()=>{
- viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'})
- })
-
- this.lastDropTime = 0
- }
-
-
-
- initData(prop){
- let makeIt = super.initData(prop)
- if(makeIt){
- this.edges.forEach(edge=>{edge.dispatchEvent('addHoverEvent') })
- }else{
- this.failBuilded = true
- }
- if(prop.expands){ //基本不会从这加
- for(let data of prop.expands){
- this.addExpand(data)
- }
- }
- }
-
-
- updateDatasetBelong(changeIndex){//更新所属数据集
-
- if(Potree.settings.editType == "merge" || this.measureType == 'MulDistance Ring'){//点直接跟着数据集走,不用找整体的datasetId
-
- this.dataset_points[changeIndex] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.points_datasets[changeIndex], position:this.points[changeIndex].clone()})
-
- return
- }
-
-
-
-
- let old = this.datasetId
-
- let maxCount = {id:null,count:0}
- let datasets = {}
-
- this.points_datasets.forEach(e=>{
- if(e == void 0)return
- if(datasets[e]){
- datasets[e] ++
- }else{
- datasets[e] = 1
- }
- })
- for(let i in datasets) {
- if(datasets[i]>maxCount.count){
- maxCount = {id:i, count:datasets[i]}
- }
- }
- this.datasetId = maxCount.count > 0 ? maxCount.id : null
-
- //if(this.datasetId != old){
- //this.dispatchEvent({type:'changeDatasetId'})
- if(this.datasetId == void 0){
- this.dataset_points = null //可能为空或[null,null...]
- }else{
-
- this.dataset_points = this.points.map(e=>{
- return Potree.Utils.datasetPosTransform({toDataset:true,datasetId:this.datasetId, position:e.clone()})
- })
- }
- //}
- }
-
-
-
-
- transformByPointcloud(){//每次移动点云 or 加载测量线时要获取一下当前position //有地图时
- if(this.datasetId == void 0)return
- this.points = this.dataset_points.map(e=>{
- return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.datasetId, position:e.clone()})
- })
-
- this.getPoint2dInfo(this.points)
- this.update({ifUpdateMarkers:true})
- this.setSelected(false)//隐藏edgelabel
-
- }
-
-
- changeColor(color){
- this.color = color //'#ffffff'
- this.edges.forEach(e=>e.material = this.getMat('edgeDefault')) //update
- this.markers.forEach(e=>e.material = this.getMat('markerDefault'))
- this.areaPlane && (this.areaPlane.material = this.getMat('planeDefault') )
- this.expands.forEach(e=>e.edges.forEach(a=>a.material = this.getMat('edgeExpand')))
- viewer.dispatchEvent('content_changed')
- }
-
-
-
- update(options={}) {
- if(options.index == -1)return
-
- super.update(options)
-
- if(this.showCoordinates && this.points.length>0){
- let position = this.points[0];
-
- this.markers[0].position.copy(position);
- { // coordinate labels
- let coordinateLabel = this.coordinateLabels[0];
-
- let pos = [
- position.toArray()
- ]
- if(viewer.transform){
- let lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray())
- let EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat)
- pos.push(lonlat,EPSG4550)
- }
-
- //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
- let msg = pos.map(a=>
- a.map(p => Utils.addCommas(p.toFixed(10))).join(", ")
- ).join("<br>")
- coordinateLabel.setText(msg);
- coordinateLabel.setPos(position)
- coordinateLabel.setVisible(true)//this.showCoordinates;
- }
- return
- }
-
-
-
- let setEdgeLabel = (label,p1,p2,distance,type)=>{//设置label位置和字
- this.setEdgeLabelPos(label,p1,p2)
- distance = distance == void 0 ? p1.distanceTo(p2) : distance;
- //var text = viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision, this.unitSystem, 1 , true)//distance要传0.1 这个factor
- var text = this.getConvertString(distance, 'distance')
- this.showArea || type == 'addTitle' && (text = this.labelAddName(text))
- label.setText(text)
- return distance
- }
-
-
-
- let lastIndex = this.points.length - 1
-
-
- let setLabel = (index)=>{
- if(index == null)return
- let previousIndex = this.getIndex(index, -1)
- let nextIndex = this.getIndex(index, +1)
- let previousPoint = this.points[previousIndex];
- let point = this.points[index];
- let nextPoint = this.points[nextIndex];
-
- if(this.showDistances ){ // edge labels
- let edgeLabel = this.edgeLabels[index];
- let distance = nextPoint && point.distanceTo(nextPoint)
- this.edges[index].distance_ = distance
- edgeLabel.shouldVisi = nextPoint && (index < lastIndex || this.isRect || this.closed && !this.isNew ) && distance>0
- //this.closed || edgeLabel.setVisible(edgeLabel.shouldVisi) //closed的在setEdgesDisplay中设置
- Utils.updateVisible(edgeLabel, 'shouldVisi', edgeLabel.shouldVisi, 2)
- if(edgeLabel.shouldVisi){
- edgeLabel.lineDir = new THREE.Vector3().subVectors(point,nextPoint).normalize() //[point,nextPoint]
- setEdgeLabel(edgeLabel,point,nextPoint,distance, this.measureType != 'MulDistance' && 'addTitle')
- }
- }
- }
-
-
- if(options.index != void 0){//更新第几个点
-
- setLabel(options.index)
- let previousIndex = this.getIndex(options.index, -1)
- setLabel(previousIndex)
- }else{
- for (let index = 0; index <= lastIndex; index++) {
- setLabel(index)
- }
- }
-
- if(Potree.config.measure.mulLabelHideFaraway ){
- this.measureType == 'MulDistance' && this.clearEdgeLabelVisi()
- }
-
-
- if(this.measureType == 'Distance' && this.points.length>1){//设置水平垂直辅助线
- var pTop, pBtm
- if(this.points[0].z > this.points[1].z ){
- pTop = this.points[0];
- pBtm = this.points[1];
- }else{
- pTop = this.points[1];
- pBtm = this.points[0];
- }
- let projectPos = new THREE.Vector3(pTop.x, pTop.y, pBtm.z);//两条guideline的交点
-
- {//倾斜角度太小的时候不显示
- let tan = pTop.distanceTo(projectPos) / pBtm.distanceTo(projectPos)
- let angle = Math.atan(tan);
-
- this.shouldShowHorVerGuide = angle > guideShowMinAngle.min && angle < guideShowMinAngle.max
-
- if(this.showAngleToGround){
- let deg = math.toPrecision(THREE.Math.radToDeg(angle), 2) + '°'
- this.angleToGroundLabel.setText(deg)
- let vec1 = new THREE.Vector3().subVectors(pTop,pBtm).normalize()
- let vec2 = new THREE.Vector3().subVectors(projectPos,pBtm).normalize()
- let midVec = new THREE.Vector3().addVectors(vec1,vec2).normalize()
- //this.angleToGroundLabel.lineDir = midVec
- this.angleToGroundLabel.setPos(new THREE.Vector3().addVectors(pBtm, midVec.clone().multiplyScalar(0.15) ))
- // 最好是让label垂直于midVec然后transform2Dpercent向上,这样无论向左看向右看都可以,但字斜着不直观
-
-
- //绘制夹角弧线(省略成直线)
- let midDis = 0.1
- let sideLen = midDis * Math.cos(angle / 2)
- let p1 = new THREE.Vector3().addVectors(pBtm, vec1.multiplyScalar(sideLen))
- let p2 = new THREE.Vector3().addVectors(pBtm, vec2.multiplyScalar(sideLen))
- LineDraw.updateLine(this.angleLine, [p1, p2])
- this.angleLine.visible = this.angleToGroundLabel.visible = this.shouldShowHorVerGuide
- }
- }
-
-
- LineDraw.updateLine(this.verGuideEdge, [pTop, projectPos])
- LineDraw.updateLine(this.horGuideEdge, [pBtm, projectPos])
- setEdgeLabel(this.verEdgeLabel,pTop,projectPos)
- setEdgeLabel(this.horEdgeLabel,pBtm,projectPos)
-
- this.verGuideEdge.visible = this.horGuideEdge.visible = this.shouldShowHorVerGuide
- this.verEdgeLabel.visible = this.horEdgeLabel.visible = this.shouldShowHorVerGuide
-
- }
-
-
- if(this.showArea && this.points.length > 2){ // update area
-
- let msg = this.getArea().string
- msg = this.labelAddName(msg)
- this.areaLabel.setPos(this.getCenter('areaPlaneCenter'))
- this.areaLabel.setText(msg);
- Utils.updateVisible(this.areaLabel, 'setVisible', true) //this.areaLabel.setVisible(true)
-
- }
-
- if(this.totalDisLabel){
- this.ifShowTotalDis()
-
- Utils.updateVisible(this.totalDisLabel,'setVisible', this.showTotalDis)
- this.edgeLabels.forEach(e=> Utils.updateVisible(e, 'showTotalDis', !this.showTotalDis))
-
- if(this.showTotalDis){
- let dis = this.getTotalDistance()
- let msg = this.getConvertString(dis, 'distance')
- msg = this.labelAddName(msg)
- this.center = null
- this.center = this.getCenter()
- this.totalDisLabel.setPos(this.center);
- this.totalDisLabel.setText(msg);
- }
- }
-
- this.expands.forEach(e=>e.update(options))
- };
-
- labelAddName(msg){
- if(Potree.config.measure.showName && this.title?.trim()){
- msg = [this.title,msg]
- }
- return msg
- }
-
- getArea(){
- let area
- if(this._area != void 0){
- area = this._area
- }else if(this.point2dInfo){
- area = Math.abs(math.getArea(this.point2dInfo.points2d))//this.getArea();
- }else{//mulDistance Ring 2d面
- area = Math.abs(math.getArea(this.points))
- }
- let msg = this.getConvertString(area, 'area')
- //let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ )
- this.area = {value:area, string:msg}
- return this.area
- }
-
- getConvertString(num, type){
- return viewer.unitConvert.convert(num, type, Potree.settings.precision, this.unitSystem, true ,
- {
- 'imperial': {minFactor: 0.01 },
- 'metric': {minFactor: 0.01}
- }
- )
- }
-
-
- ifShowTotalDis(){
-
- let show = this.points.length > 2
-
- if(show){
- let maxDis = 0.15
- let lastIndex = this.points.length - 1;
- for(let i=0;i<lastIndex;i++){
- let len = this.edges[i].distance_
-
- if(len > maxDis){
- show = false; break;
- }
- }
- }
-
-
- this.showTotalDis = show
-
- /* 连续测量:
- 1. ≥2次测量,单个距离<15cm时,居中显示总长, hover、选中时显示每段长度
- 2. 若连续测量的线段中,大于等于1段超出15cm,所有线段均显示长度
- -------------------
- */
- }
- clearEdgeLabelVisi(){//修改点位置后清空,下次render时会自动getEdgeLabelVisi
- let lastIndex = this.points.length - 1;
- for (let index = 0; index <= lastIndex; index++) {
- if(!this.closed && index == lastIndex)continue
- let edgeLabel = this.edgeLabels[index];
- edgeLabel.visiMap.clear()
- }
- }
-
- getEdgeLabelVisi(viewport){//获取多折线的edgelabel在不同视图里的可见性。要保证任何时候label能出现的线最小二维长度一致
- let camera = viewport.camera
- let lastIndex = this.points.length - 1;
- /* let pos2ds = this.points.map(point=> point.clone().project(camera) ) //即使只是旋转也会变动,尤其是转到屏幕外后变为显示。所以不用这种
- let minDis = 0.01; */
- let minDis = 0.02 , minAngleRatio = 0.07, minAngle
- let vecs
- let forceShow
- if(camera.type == 'OrthographicCamera'){
- minDis *= Math.pow(camera.top / camera.zoom, 2);
- //console.log(minDis)
- }else{
- if(Potree.settings.displayMode == 'showPanos' && viewer.images360.zoomLevel == Potree.settings.zoom.max){
- forceShow = true //当zoom到最大时强制显示,避免有的线太短永远显示不出长度
- }else{
- vecs = this.points.map(point=> new THREE.Vector3().subVectors(point, camera.position).normalize())
- minAngleRatio /= viewport.resolution.y / 1000 / textSizeRatio //角度占fov最小比率
- minAngle = minAngleRatio * THREE.Math.degToRad(camera.fov)
- }
- }
-
-
- for (let index = 0; index <= lastIndex; index++) {
- if(!this.closed && index == lastIndex)continue
- let edgeLabel = this.edgeLabels[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 point2d = pos2ds[index];
- let nextPoint2d = pos2ds[nextIndex];
- let dis2d = point2d.distanceToSquared(nextPoint2d)
- let v = dis2d > minDis //可见长度太小,为避免拥挤,不显示
- edgeLabel.visiMap.set(camera, v) */
- let v
-
- if(forceShow){
- v = true
-
- }else if(camera.type == 'OrthographicCamera'){
- let vec = new THREE.Vector3().subVectors(point,nextPoint)
- let projVec = vec.projectOnPlane(viewport.view.direction)
- v = projVec.lengthSq() > minDis
- }else{
- let vec0 = vecs[index];
- let vec1 = vecs[nextIndex];
- v = Math.acos(vec0.dot(vec1)) > minAngle //角度过小代表可见长度太小,为避免拥挤,不显示
-
- }
- edgeLabel.visiMap.set(camera, v)
-
- }
- }
- setEdgeLabelPos(label,p1,p2){ //调整label的位置,使倾斜后看起来在线的中心,而不要挡住端点
- let center = new THREE.Vector3().addVectors(p1,p2).multiplyScalar(0.5);
- return label.setPos(center)
-
-
-
- if(label.lineDir && label.lineDir.length() > 0){
- if(viewer.mainViewport.camera.type == 'OrthographicCamera'){
- label.setPos(center)
- }else{
- //根据视线和线的夹角(后又加入相机和两个端点距离差)来决定标签偏移位置。+
- let eyePos = viewer.mainViewport.camera.position;
- let dir = viewer.mainViewport.view.direction //new THREE.Vector3().subVectors(center,eyePos).normalize()
-
- /*let centerDir = new THREE.Vector3().subVectors(center,eyePos).normalize()
- if(centerDir.dot(dir)<0){//中点在相机后方,就不设置
- label.setPos(center)
- return
- } */
- let cos = dir.dot(label.lineDir)
- let nearPoint = cos > 0 ? p2 : p1 //近端点。
- let far = cos > 0 ? p1 : p2 //远端点。
- let nearPointDir = new THREE.Vector3().subVectors(nearPoint,eyePos)//.normalize()
- //使label在中点和近端点中变化, 近端点可能到了相机后方,需要投影到相机所在平面上
- if(nearPointDir.dot(dir)<0){//近端点到了相机后方,前移。
- //let hfov = cameraLight.getHFOVForCamera(viewer.mainViewport.camera , true ); //暂且只看水平fov
- //if(nearPointDir.dot(dir)<Math.cos(hfov/2)){//近端点在镜头外,前移。 --但是这个就得把点转化成在镜头边缘而非左右两边(camDirPlane上)
- let ray = new THREE.Raycaster()
- ray.set(nearPoint, cos>0?label.lineDir:label.lineDir.clone().negate())
- let camDirPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(dir, eyePos)
- nearPoint = ray.ray.intersectPlane(camDirPlane, new THREE.Vector3())
- if(!nearPoint){//线是垂直的,视线是水平的时候
- return label.setPos(center)
- }
- }
-
-
- //防止离远了之后也偏移很多,但远了之后相机到端点vec和到中点的vec的夹角接近,不需要怎么偏移的。
- let dis1 = nearPoint.distanceToSquared(eyePos)
- let dis2 = far.distanceToSquared(eyePos)
- let diff = Math.abs(dis1/dis2)
- diff<1 && (diff = 1/diff)
- diff = math.linearClamp(diff,[0, 30], [ 0,1 ])
-
-
-
- let efficiency = 0.7; // 0-1 数值越高,r越容易接近1或-1,label越容易在倾斜后靠近近端点。
- //let r = 0.5*efficiency*cos + 0.5
- let r = 0.5*efficiency*diff*cos + 0.5
- r = THREE.Math.clamp(r,0.1,0.9)
-
- //视线越接近线的方向,标签应该越往近端点偏移,防止看起来几乎在远端。
- if(cos > 0){
- center = p1.clone().multiplyScalar(1-r).add(nearPoint.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
- }else{
- center = nearPoint.clone().multiplyScalar(1-r).add(p2.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
- }
-
- label.setPos(center)
- }
-
-
- //归零
- //this.orient2dInfo = null
- //this.markers.forEach(e=>e.needsUpdate=true)
- }else{
-
- label.setPos(center)
- }
-
-
- }
- cloneMarker(cloneIndex, index){
- return this.addMarker({
- index,
- point: this.points[cloneIndex],
- dataset_point:this.dataset_points && this.dataset_points[cloneIndex],
- points_dataset:this.points_datasets[cloneIndex]
- })
- }
-
-
- addMarker (o={}) {
- var index = o.index == void 0 ? this.points.length : o.index //要当第几个
-
- let marker = o.marker || new Sprite({mat:this.getMat('markerDefault'), sizeInfo: markerSizeInfo, name:"measure_point"} )
- //Potree.Utils.setObjectLayers(marker, 'measure' )
- marker.pickOrder = marker.renderOrder = Potree.config.renderOrders.measureMarker
- marker.markerSelectStates = {}
- marker.addEventListener('startDragging',(e)=>{
- /* if(e.drag.dragViewport.name == 'MainView') */viewer.inputHandler.dispatchEvent( {type: 'measuring',v:true, cause:'startDragging', situation:'dragging', object:this})
-
-
- //add for 调试,方便后期增加点
- if(!this.isNew && viewer.inputHandler.pressedKeys['M'.charCodeAt(0)] && this.points.length<this.maxMarkers){
- viewer.measuringTool.history.beforeChange(this)
- let curIndex = this.markers.indexOf(marker)
- this.cloneMarker(curIndex, curIndex+1)
- }
- this.isNew || viewer.measuringTool.history.beforeChange(this)
-
- })
-
-
- marker.addEventListener('drop',(e)=>{
- if( e.button != THREE.MOUSE.LEFT )return
-
- viewer.inputHandler.dispatchEvent({type: 'measuring', v:false, cause:'stopDragging', situation:'dragging', object:this} )
-
- this.lastDropTime = Date.now()
-
- if(Potree.settings.adsorption){
- this.isNew || viewer.viewports.forEach((viewport)=>{
- this.getPointsPos2d(viewport, true )//forceUpdate
- })
- }
-
- this.isNew || viewer.measuringTool.history.afterChange(this)
-
- })
-
- marker.addEventListener('click',()=>{
-
- if(viewer.measuringTool.editMode == 'delPoint' ){
- /* if(this.points.length == this.minMarkers){//--前端去重绘
- viewer.scene.removeMeasurement(this)
- }else{ */
- viewer.measuringTool.history.beforeChange(this)
- let index = this.markers.indexOf(marker)
- this.removeMarker(index)
- viewer.measuringTool.history.afterChange(this)
- this.dispatchEvent('changed')
- //}
-
- }
- })
-
- //marker.measure = this
- let edge
- { // edges
- edge = o.edge || LineDraw.createFatLine( [ ],{mat:this.getMat('edgeDefault')} )
- edge.pickOrder = 0
- //Potree.Utils.setObjectLayers(edge, 'measure' )
-
- let addHoverEvent = ()=>{ //当非isNew时才添加事件
-
- let mouseover = (e) => {
- /* if(this.measureType == 'MulDistance'){
- } */
- this.setSelected(true, 'edge')
- };
- let mouseleave = (e) => {
- this.setSelected(false, 'edge')
- };
-
- edge.addEventListener('mouseover', mouseover);
- edge.addEventListener('mouseleave', mouseleave);
- edge.removeEventListener('addHoverEvent', addHoverEvent);
-
- edge.addEventListener('click',(e)=>{
- let now = Date.now()
- if(now - this.lastDropTime<100)return ;//防止拖拽marker时误触导致focus, 以及点到marker不focus
-
-
- if(viewer.measuringTool.editMode == 'addPoint' && this.points.length < this.maxMarkers){
- viewer.measuringTool.history.beforeChange(this)
- let index = this.edges.indexOf(edge) + 1
- let nextIndex = index % this.edges.length
- let point = math.getFootPoint(e.hoveredElement.point, this.points[index-1], this.points[nextIndex] );
-
- this.addMarker({
- index,
- point,
- dataset_point: this.dataset_points && new THREE.Vector3 , //初始化
- points_dataset : this.points_datasets[index-1] //使用前一个的
- })
- this.updateDatasetBelong(index) //获取dataset_point
- viewer.measuringTool.history.afterChange(this)
- this.dispatchEvent('changed')
- //this.update({})
- }else{
- this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure') //正在添加测量线时不要focus其他线(容易误触)
- }
- })
-
- }
- edge.addEventListener('addHoverEvent', addHoverEvent);
- if(!this.isNew){
- edge.dispatchEvent('addHoverEvent')
- }
- }
-
- super.addMarker(Object.assign(o, {index, marker, edge}))
-
-
- if(this.showEdges){ // edge labels
- const edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed)
- this.edgeLabels = [...this.edgeLabels.slice(0,index), edgeLabel, ...this.edgeLabels.slice(index,this.edgeLabels.length)]
-
- }
-
- if(this.showCoordinates){ // coordinate labels
- let coordinateLabel = new Label({
- className:'measure_pointPos',
- camera: viewer.scene.getActiveCamera()
- })
- coordinateLabel.setVisible(false)
- this.coordinateLabels.push(coordinateLabel);
-
- }
-
-
-
-
-
- let event = {
- type: 'marker_added',
- measurement: this,
- marker: marker
- };
- this.dispatchEvent(event);
-
- this.expands.forEach(e=>e.addMarker(o))
- //this.setMarker(this.points.length - 1, point);
- this.update({index})//更新一下倒数第二条线
- return marker;//add
- };
-
-
- editStateChange(state){ //主要针对edgeLabels显示切换,编辑时显示
- super.editStateChange(state)
- if(!state){
- this.editStateTimer = setTimeout(()=>{
- if(!this.isEditing){
- this.dispatchEvent({type:'editStateChange',state:false})
- this.setEdgesDisplay(false)
- this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true)
- this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true)
- }
- },100)
- }else{
- if(!this.isEditing){
- this.dispatchEvent({type:'editStateChange',state:true})
- this.setEdgesDisplay(true)
- clearTimeout(this.editStateTimer)
- }
- }
- this.isEditing = state
- }
-
-
- setMarkerSelected(marker, state, hoverObject){
-
- //console.warn(marker.id , state, hoverObject)
-
- marker.markerSelectStates[hoverObject] = state
- let absoluteState = false
- for(var i in marker.markerSelectStates){
- if(marker.markerSelectStates[i] == 'hover'){
- absoluteState = true; break;
- }
- }
- if(absoluteState){
- marker.material = this.getMat('markerSelect')
- marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker+1
- }else{
- marker.material = this.getMat('markerDefault')
- marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker
- }
-
- marker.selected = absoluteState
-
- viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed')
- viewer.dispatchEvent('content_changed')
- }
-
-
-
- setEdgesDisplay(state, ignoreGuideLine){
- this.closed && this.edgeLabels.forEach(e=>Utils.updateVisible(e,'hover',state))
-
-
- if(this.totalDisLabel && !viewer.screenshoting){
- this.edgeLabels.forEach(e=> Utils.updateVisible(e, 'hover', state, 1, state ? 'add' : 'cancel'))
- Utils.updateVisible(this.totalDisLabel,'hover', !state )
- }
-
-
- if(!this.horVerShowAlways && !ignoreGuideLine && this.measureType == 'Distance'){
- this.horEdgeLabel.visible = this.verEdgeLabel.visible = this.horGuideEdge.visible = this.verGuideEdge.visible = !!(state && this.shouldShowHorVerGuide)
-
- if(this.showAngleToGround){
- this.angleToGroundLabel.visible = this.angleLine.visible = !!(state && this.shouldShowHorVerGuide)
- }
- }
- }
-
-
- setSelected(state, hoverObject){//add
- //console.log('setSelected',state, hoverObject)
-
- let absoluteState = !!state
-
- if(hoverObject){//如果没有hoverObject且state为false 就强制取消选中态
- this.selectStates[hoverObject] = state
- for(var i in this.selectStates){
- if(this.selectStates[i]){
- absoluteState = true; break;
- }
- }
- }
-
-
- if(absoluteState){
- this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) )
-
- this.edges.forEach(e=>{
- e.renderOrder = Potree.config.renderOrders.line + 1
- e.material = this.getMat('edgeSelect')
- })
-
- this.areaPlane && (this.areaPlane.material = this.getMat('planeSelected'))
-
-
- //this.areaLabel && this.areaLabel.elem.addClass('highLight')
- //this.closed || this.edgeLabels.forEach(e=>e.elem.addClass('highLight') )
- this.setEdgesDisplay(true, hoverObject=="screenshot")
-
- this.areaLabel && setLabelHightState(this.areaLabel, true)
- this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, true) )
-
- }else{
- this.markers.forEach(e=>this.setMarkerSelected(e, 'unhover', 'selectAll' ))
- this.edges.forEach(e=>e.material = this.getMat('edgeDefault') )
- this.areaPlane && (this.areaPlane.material = this.getMat('planeDefault'))
- this.setEdgesDisplay(false, hoverObject=="screenshot")
- //this.areaLabel && this.areaLabel.elem.removeClass('highLight')
- //this.closed || this.edgeLabels.forEach(e=>e.elem.removeClass('highLight') )
- this.areaLabel && setLabelHightState(this.areaLabel, false)
- this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, false) )
-
- }
-
- this.selected = absoluteState
-
- if(hoverObject != 'byList'){
- //this.bus && this.bus.emit('highlight', this.selected)
- this.dispatchEvent({type:'highlight',state:this.selected})//列表高亮
- }
-
- viewer.dispatchEvent('content_changed')
- viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed')
- }
-
- removeMarker(index ){
- super.removeMarker(index)
-
- this.points_datasets.splice(index, 1);
- this.dataset_points && this.dataset_points.splice(index, 1)
- this.coordinateLabels.splice(index, 1);
-
- let edgeIndex = index//(index === 0) ? 0 : (index - 1);
- if(this.edgeLabels[edgeIndex]){
- this.edgeLabels[edgeIndex].dispose()
- this.edgeLabels.splice(edgeIndex, 1);
- }
- this.expands.forEach(e=>e.removeMarker(index))
- this.closed || this.points.length && (this.edges[this.points.length-1].visible = false)
- this.update({index: this.getIndex(index, -1)});
- this.dispatchEvent({type: 'marker_removed', measurement: this});
- }
-
- setPosition(index, position) {
- super.setPosition(index, position)
- let event = {
- type: 'marker_moved',
- measure: this,
- index: index,
- position: position.clone()
- };
- this.dispatchEvent(event);
- }
-
- dispose(){//add
- var labels = this.edgeLabels.concat(this.coordinateLabels)
- this.areaLabel && labels.push(this.areaLabel)
- labels.forEach(e=>e.dispose())
- this.expands.forEach(e=>e.dispose())
- this.expands.length = 0
- super.dispose()
- this.dispatchEvent('disposed')
- }
-
-
- getAngleBetweenLines (cornerPoint, point1, point2) {
- let v1 = new THREE.Vector3().subVectors(point1, cornerPoint);
- let v2 = new THREE.Vector3().subVectors(point2, cornerPoint);
- // avoid the error printed by threejs if denominator is 0
- const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
- if(denominator === 0){
- return 0;
- }else{
- return v1.angleTo(v2);
- }
- };
- getAngle (index) {
- if (this.points.length < 3 || index >= this.points.length) {
- return 0;
- }
- let previous = (index === 0) ? this.points[this.points.length - 1] : this.points[index - 1];
- let point = this.points[index];
- let next = this.points[(index + 1) % (this.points.length)];
- return this.getAngleBetweenLines(point, previous, next);
- }
-
-
-
- // updateAzimuth(){
- // // if(this.points.length !== 2){
- // // return;
- // // }
- // // const azimuth = this.azimuth;
- // // const [p0, p1] = this.points;
- // // const r = p0.distanceTo(p1);
-
- // }
-
-
-
-
- createGuideLine(){//add 辅助线
- var guideLine = LineDraw.createFatLine([ ],{mat:this.getMat('edgeGuide')} )
- guideLine.visible = false
- this.guideLine = guideLine
- this.add(guideLine);
- }
- createHorVerGuideLine(){//创建水平与垂直辅助线,仅距离测量有。
- var verGuideEdge = LineDraw.createFatLine([ ],{mat:this.getMat('edgeGuide')} )
- verGuideEdge.visible = false
- this.verGuideEdge = verGuideEdge
- verGuideEdge.name = 'verGuideEdge'
-
- var horGuideEdge = LineDraw.createFatLine([ ],{mat:this.getMat('edgeGuide')} )
- horGuideEdge.visible = false
- horGuideEdge.name = 'horGuideEdge'
- this.horGuideEdge = horGuideEdge
-
- this.add(this.verGuideEdge);
- this.add(this.horGuideEdge);
-
-
- //label:
- this.verEdgeLabel = this.createEdgeLabel('verGuideEdge')
- this.horEdgeLabel = this.createEdgeLabel('horGuideEdge')
- if(this.showAngleToGround){
- this.angleToGroundLabel = new TextSprite(
- $.extend({}, subLabelProp, {
- sizeInfo: labelSizeInfo, name:'angleToGroundLabel', transform2D:null
- })
- )
- this.angleLine = LineDraw.createFatLine([ ],{mat:this.getMat('angle')} )
- this.add(this.angleToGroundLabel)
- this.add(this.angleLine)
- }
- }
-
- createEdgeLabel(name, hasHoverEvent){
-
- let inf = {
- sizeInfo: labelSizeInfo, name:name||'edgeLabel',
- }
- if(name && name.includes('Guide')){
- inf.fontsize = 12
- }
- const edgeLabel = new TextSprite(
- $.extend({}, hasHoverEvent ? mainLabelProp : subLabelProp, inf)
- )
- if(hasHoverEvent){
- edgeLabel.addEventListener('mouseover',()=>{
- this.setSelected(true, 'edgeLabel')
- })
- edgeLabel.addEventListener('mouseleave',()=>{
- this.setSelected(false, 'edgeLabel')
- })
- edgeLabel.addEventListener('click',(e)=>{
- this.isNew || viewer.measuringTool.isAdding || e.button == THREE.MOUSE.LEFT && viewer.focusOnObject(this, 'measure')
- })
- }
- edgeLabel.visible = false
- edgeLabel.measure = this
- edgeLabel.sprite.material.depthTestWhenPick = true
- //Potree.Utils.setObjectLayers(edgeLabel, 'measure' )
- this.add(edgeLabel)
-
- if(this.measureType == 'MulDistance'){
- edgeLabel.visiMap = new Map()
- }
-
-
-
- return edgeLabel
- }
-
- createAreaLabel(){
- const areaLabel = this.createCenterLabel('areaLabel')
-
- return areaLabel;
- }
-
- createTotalDisLabel(){
- const totalDisLabel = this.createCenterLabel('totalDisLabel')
-
- return totalDisLabel;
- }
-
- createCenterLabel(name){
- const centerLabel = new TextSprite(
- $.extend({},mainLabelProp,{sizeInfo: labelSizeInfo, name, transform2D:null, fontsize:16*textSizeRatio} )
- )
-
- centerLabel.addEventListener('mouseover',()=>{
- this.isNew || this.setSelected(true, 'centerLabel')
- })
- centerLabel.addEventListener('mouseleave',()=>{
- this.isNew || this.setSelected(false, 'centerLabel')
- })
- centerLabel.addEventListener('click',()=>{
- this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure')
- })
- //Potree.Utils.setObjectLayers(centerLabel, 'measure' )
-
- Utils.updateVisible(centerLabel, 'setVisible', false)
- return centerLabel;
- }
-
-
-
-
-
-
-
-
-
-
- getMat(type) {
- if(!Measure.Mats){ //不变色的部分
- Measure.Mats = {
- edgeGuide: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
- color:config.measure.guide.color,
- dashSize: 0.1,
- gapSize: 0.02,
- dashed: true,
- lineWidth: config.measure.lineWidth/2
- })),
- angle: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
- color:config.measure.guide.color,
- lineWidth: config.measure.lineWidth/2
- })),
- multiColors:{}
- }
- {
- markerMaps = [texLoader.load(Potree.resourcePath+'/textures/whiteCircle.png' ), //pic_point_s32
- texLoader.load(Potree.resourcePath+'/textures/pic_point32.png' )]
- markerMaps.forEach(map=>{
- map.repeat.set(1/markerMapShrink,1/markerMapShrink)
- map.offset.set((markerMapShrink-1)/2/markerMapShrink, (markerMapShrink-1)/2/markerMapShrink)
- })
- markerMaps[0].minFilter = 1006 //禁黑边
- }
-
-
- }
-
-
- let mat = Measure.Mats[type]
- let multiColors = Measure.Mats.multiColors
- //console.log('getMat', this.name, this.color, type)
- if(!mat){
-
- let colorObject = multiColors[this.color]
- if(!colorObject){
-
-
- let c = new THREE.Color().set(this.color).getHSL({ h: 0, s: 0, l: 0 })
- let expandColor = new THREE.Color().setHSL(c.h, c.s, c.l >= 0.4 ? c.l - 0.3: c.l + 0.3)
- let expandSelectedColor = new THREE.Color().setHSL(c.h, c.s > 0.5 ? c.s - 0.2 : c.s + 0.2, c.l >= 0.6 ? c.l - 0.1 : c.l + 0.1 )
-
- colorObject = {
- edgeDefault: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
- color: this.color || config.measure.default.color,
- lineWidth: config.measure.lineWidth,
- useDepth :true,
- dashWithDepth :true, // 只在被遮住的部分显示虚线,因为实线容易挡住label
- dashed :true,
- dashSize : 0.04,
- gapSize: 0.04,
- transparent: true,
- opacity: config.measure.default.opacity,
- depthTestWhenPick:true,
- })),
- edgeSelect: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
- color: this.color || config.measure.highlight.color,//'#f0ff00',
- dashSize: 0.5,
- gapSize: 0.2,
- lineWidth: config.measure.lineWidth ,
- transparent: true,
- opacity: config.measure.highlight.opacity
- })),
-
- edgeExpand : LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
- color: expandColor,
- useDepth :true,
- lineWidth: 2 ,
- transparent: true,
- opacity: config.measure.default.opacity,
- })),
-
- 'edgeExpand-selected': LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
- color: expandSelectedColor,
- useDepth :true,
- lineWidth: 2 ,
- transparent: true,
- opacity: config.measure.highlight.opacity,
- })),
-
-
- markerDefault: new DepthBasicMaterial($.extend({},lineDepthInfo,{
- transparent: !0,
- opacity: 1,
- map: markerMaps[0] ,
- useDepth:true ,
- color: this.color,
- //mapScale: markerMapShrink
- })),
- markerSelect: new BasicMaterial({
- transparent: !0,
- opacity: 1,
- depthTest:false,
- map: markerMaps[1],
- }),
- planeDefault : new DepthBasicMaterial( $.extend({},lineDepthInfo,{
- color : this.color || color,
- side:THREE.DoubleSide,
- opacity:0.2,
- transparent:true,
- useDepth:true,
- })),
- planeSelected: new THREE.MeshBasicMaterial({
- color: this.color || color,
- side:THREE.DoubleSide,
- opacity:0.3,
- transparent:true,
- //wireframe:true
- })
- }
- colorObject.markerSelect.defines.replaceColor = '' //将绿色部分替换成color
- colorObject.markerSelect.uniforms.newMapColor = {type:'v3', value: new THREE.Color(this.color)}
- colorObject.markerSelect.onBeforeCompile = function ( shader ) {
- shader.fragmentShader = shader.fragmentShader
- .replace( 'uniform sampler2D map;', `uniform sampler2D map; uniform vec3 newMapColor;` )//将图中绿色#00C8AF换成指定色
- .replace( 'gl_FragColor = texColor * color_;', `
- vec3 texWhite = vec3(1.0,1.0,1.0); //中心部分白色不变,外围原本绿色的r刚好为0,所以r值越高越往白色过渡
- texColor.rgb = mix(newMapColor, texWhite, texColor.r);
- gl_FragColor = texColor * color_;` )
- }
- multiColors[this.color] = colorObject
-
- {//清理不用的colorObject
- let measures = viewer.scene.measurements.slice()
- measures.includes(this) || measures.push(this)
- for(let co in multiColors){
- multiColors[co].useCount = 0
- }
- measures.forEach(e=>{
- multiColors[e.color].useCount ++
- })
- let deletes = []
- for(let co in multiColors){
- if(multiColors[co].useCount == 0){
- deletes.push(co)
- delete multiColors[co].useCount
- for(let i in multiColors[co]){
- multiColors[co][i].dispose()
- }
- }
- }
- deletes.forEach(co=>delete multiColors[co])
- }
- }
-
-
- mat = colorObject[type]
-
-
-
- }
-
- return mat
- }
-
-
-
-
-
- createAreaPlane(){
- return super.createAreaPlane(this.getMat('planeDefault'))
- }
-
-
- raycast (raycaster, intersects) {
- for (let i = 0; i < this.points.length; i++) {
- let marker = this.markers[i];
- marker.raycast(raycaster, intersects);
- }
- // recalculate distances because they are not necessarely correct
- // for scaled objects.
- // see https://github.com/mrdoob/three.js/issues/5827
- // TODO: remove this once the bug has been fixed
- for (let i = 0; i < intersects.length; i++) {
- let I = intersects[i];
- I.distance = raycaster.ray.origin.distanceTo(I.point);
- }
- intersects.sort(function (a, b) { return a.distance - b.distance; });
- };
-
- getPointsPos2d(viewport, update){//获取屏幕上的二维坐标
- let ps = this.pointsPos2d.get(viewport)
- if(update || !ps){
- let points = this.points.map(e=>{
- let p = Potree.Utils.getPos2d(e, viewport, viewer.renderArea )
- p.pos3d = e.clone(), p.object = this
- return p
- });
-
- this.pointsPos2d.set(viewport, points)
- console.log('updatePointsPos2d',this.uuid,viewport.name)
- }
-
- return this.pointsPos2d.get(viewport)
- }
-
- transformData(prop){
- if(prop.measureType == 'Point'){
- prop.showCoordinates = true,
- prop.closed = true,
- prop.maxMarkers = 1,
- prop.minMarkers = 1
- }else if(prop.measureType == 'Distance'){
- prop.showDistances = true,
- prop.showEdges = true,
- prop.maxMarkers = 2,
- prop.minMarkers = 2
- }else if(prop.measureType == 'MulDistance'){
- prop.showDistances = true,
- prop.showEdges = true,
- prop.minMarkers = 2
- }else if(prop.measureType == 'MulDistance Ring'){
- prop.showDistances = true,
- prop.showEdges = true,
- prop.showArea = true,
- prop.closed = true,
- prop.minMarkers = 3
- }else if(prop.measureType == 'Ver MulDistance'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.minMarkers = 2
- prop.faceDirection = "vertical"
- prop.unableDragAtMap = true
- }else if(prop.measureType == 'Hor MulDistance'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.minMarkers = 2
- prop.faceDirection = "horizontal"
- }else if(prop.measureType == 'Ver Distance'){
- prop.showDistances = true,
- prop.showEdges = true,
- prop.maxMarkers = 2,
- prop.minMarkers = 2,
- prop.faceDirection = "vertical"
- prop.unableDragAtMap = true
- }else if(prop.measureType == 'Hor Distance'){
- prop.showDistances = true,
- prop.showEdges = true,
- prop.maxMarkers = 2,
- prop.minMarkers = 2,
- prop.faceDirection = "horizontal"
-
- }else if(prop.measureType == 'Area'){
- prop.showDistances = true,
- Potree.settings.areaAtNotPlane || (prop.atPlane = true)
- prop.showEdges = true,
- prop.closed = true,
- prop.minMarkers = 3
- }else if(prop.measureType == 'Hor Area'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.closed = true,
- prop.minMarkers = 3
- prop.faceDirection = "horizontal"
-
- }else if(prop.measureType == 'Ver Area'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.closed = true,
- prop.minMarkers = 3
- prop.faceDirection = "vertical"
- prop.unableDragAtMap = true
- }else if(prop.measureType == 'Rect Area'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.closed = true,
- prop.minMarkers = 4
- prop.maxMarkers = 4
- }else if(prop.measureType == 'Hor Rect Area'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.closed = true,
- prop.minMarkers = 4
- prop.maxMarkers = 4
- prop.isRect = true
- prop.faceDirection = "horizontal"
- }else if(prop.measureType == 'Ver Rect Area'){
- prop.showDistances = true,
- prop.atPlane = true,
- prop.showEdges = true,
- prop.closed = true,
- prop.minMarkers = 4
- prop.maxMarkers = 4
- prop.isRect = true
- prop.faceDirection = "vertical"
- prop.unableDragAtMap = true
- }
- if(prop.atPlane && prop.closed){ //atPlane在同一平面上
- prop.showArea = true
- }
-
-
- super.transformData(prop)
-
-
-
- }
- setUnitSystem(unitSystem){
- //console.log(this.name +':' +this.unitSystem)
- if(unitSystem != this.unitSystem){
- if(unitSystem == "metric"){
-
- }else if(unitSystem == 'imperial'){
-
- }
- this.unitSystem = unitSystem
- this.expands.forEach(e=>e.unitSystem = unitSystem)
- this.update()
- }
- }
- reDraw(restMarkerCount=0){//重新开始画
- super.reDraw(restMarkerCount)
- if(this.measureType == 'Distance'){
- this.shouldShowHorVerGuide = false
- this.setEdgesDisplay(false)
- }
- if(this.showArea){
- this.area = {value:0};
- this.areaLabel && Utils.updateVisible(this.areaLabel, 'setVisible', false )
- }
- if(this.totalDisLabel && this.showTotalDis){
- Utils.updateVisible(this.totalDisLabel, 'setVisible', false )
- }
- viewer.inputHandler.dispatchEvent( {type:'measuring', v:true, cause:'reDraw',object:this, situation:'dragging'} )
-
- }
-
-
- addExpand(data){//{offset,color}
- data.measure = this
- let expand = new ExpandLine(data)
- this.expands.push(expand)
- viewer.scene.overlayScene.add(expand) //this.add(expand) //因为其可见性不随父结点所以分开
- }
-
- removeExpand(expand){
- let index = this.expands.indexOf(expand)
- if(index > -1){
- expand.dispose()
- this.expands.splice(index,1)
- //this.remove(expand)
- }
- }
- }
- function setLabelHightState(label, state){
- if(state){
- let color = new THREE.Color(Potree.config.measure.highlight.color)
- //label.sprite.material.opacity = config.measure.highlight.opacity
-
- //label.setBackgroundColor({r:255*color.r, g:255*color.g, b:255*color.b, a:config.measure.highlight.opacity})
-
- label.sprite.material.useDepth = false;
- //label.textColor = {r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a: 1}
- }else{
- //label.setBackgroundColor({r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a:config.measure.default.opacity})
-
- label.sprite.material.useDepth = true
- //label.sprite.material.opacity = 0.98
- //label.textColor = {r: 255, g: 255, b: 255, a: 1}
-
- }
- label.updateTexture()
- }
-
- function createCircleRadiusLabel(){
- const circleRadiusLabel = new TextSprite("");
- circleRadiusLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
- circleRadiusLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
- circleRadiusLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
- circleRadiusLabel.fontsize = 16;
- circleRadiusLabel.material.depthTest = false;
- circleRadiusLabel.material.opacity = 1;
- circleRadiusLabel.visible = false;
-
- return circleRadiusLabel;
- }
- function createCircleRadiusLine(){
-
-
- var circleRadiusLine = LineDraw.createFatLine([ ],{
- color:0xff0000,
- dashSize: 0.5,
- gapSize: 0.2,
- lineWidth: config.measure.lineWidth
- })
- circleRadiusLine.visible = false;
- return circleRadiusLine;
- }
- function createCircleLine(){
- const coordinates = [];
- let n = 128;
- for(let i = 0; i <= n; i++){
- let u0 = 2 * Math.PI * (i / n);
- let u1 = 2 * Math.PI * (i + 1) / n;
- let p0 = new THREE.Vector3(
- Math.cos(u0),
- Math.sin(u0),
- 0
- );
- let p1 = new THREE.Vector3(
- Math.cos(u1),
- Math.sin(u1),
- 0
- );
- coordinates.push(
- p0,
- p1
- );
- }
-
- var circleLine = LineDraw.createFatLine(coordinates,{
- color: 0xff0000,
- dashSize: 0.5,
- gapSize: 0.2,
- lineWidth: config.measure.lineWidth
- })
- return circleLine;
- }
-
- function createLine(){
-
- const line = LineDraw.createFatLine([ ],{
- color: 0xff0000,
- dashSize: 0.5,
- gapSize: 0.2,
- lineWidth: config.measure.lineWidth
- })
-
-
-
- return line;
- }
- function createCircle(){
- const coordinates = [];
- let n = 128;
- for(let i = 0; i <= n; i++){
- let u0 = 2 * Math.PI * (i / n);
- let u1 = 2 * Math.PI * (i + 1) / n;
- let p0 = new THREE.Vector3(
- Math.cos(u0),
- Math.sin(u0),
- 0
- );
- let p1 = new THREE.Vector3(
- Math.cos(u1),
- Math.sin(u1),
- 0
- );
- coordinates.push(
- p0,
- p1
- );
- }
-
- var line = LineDraw.createFatLine(coordinates,{
- color: 0xff0000,
- dashSize: 0.5,
- gapSize: 0.2,
- lineWidth: config.measure.lineWidth
- })
- return line;
- }
- //缓冲区扩展,随measure改变,不可拖拽
- class ExpandLine extends ctrlPolygon{
-
- constructor (prop) {
- prop.points = prop.measure.points.map(e=>e.clone()) //先复制 用来加marker
- prop.unitSystem = prop.measure.unitSystem
- prop.atPlane = prop.measure.atPlane
- prop.closed = prop.measure.closed
- super('expandLine',prop);
-
- this.name = 'measureExpand_'+prop.measure.name
-
-
- this.initData(prop)
-
- //offset 正数为朝外
- }
-
- update(options={}){//暂时每次都全部更新,以后再改
-
- let points = this.measure.points
- let count = this.measure.points.length
- let newPoints = []
- let facePlane = this.getFacePlane(true) //更新normal. 不用measure的是因为measure没更新normal
- let normal = facePlane?.normal //this.measure.facePlane.normal
- if(!normal)return //暂时不知道怎么写
- let offset = this.offset //Potree.math.getArea(this.measure.point2dInfo.points2d) > 0 ? -this.offset : this.offset // 时针受normal影响
- //console.log('offset',offset, 'normal', normal.toArray(), 'clockwise', Potree.math.getArea(this.measure.point2dInfo.points2d) > 0)
-
- for(let i=0; i<count; i++){
-
- let O = points[i] //该点
- let A = this.measure.getPoint(i,-1)//points[i-1] //上一个点
- let B = this.measure.getPoint(i,1)//points[i+1] //下一个点
-
-
- let p1, p2 //该点两边的折点
- let sideVec //该点两边对应的向量
- //如果是线段的话,
-
- if(!A || !B){ //端点
- let vec = new THREE.Vector3().subVectors(i==0 ? B : O, i==0 ? O : A)
- sideVec = new THREE.Vector3().crossVectors(normal, vec).normalize().multiplyScalar(offset)
- //sideVec = new THREE.Vector3().copy(math.getNormal2d({p1: i==0 ? B : O, p2: i==0 ? O : A})).setZ(0).multiplyScalar(this.halfPathWidth) //垂线
-
- }else{
- let OA = new THREE.Vector3().subVectors(A,O).normalize() //只保证俯视角度正确。(如果两点有高度差,该段四个点不会在同一平面,看起来有扭转,有的地方会肥大,但从俯视角度看是正确的。)
- let OB = new THREE.Vector3().subVectors(B,O).normalize()
- let angle = math.getAngle(OA, OB, normal)
-
- if(math.closeTo(angle,0,1e-4) || math.closeTo(angle,Math.PI,1e-4) || math.closeTo(angle, -Math.PI,1e-4)){ //这时候直接加两个向量算出的平分线不准,故直接找垂线
-
- let vec = new THREE.Vector3().subVectors(O, A)
- sideVec = new THREE.Vector3().crossVectors(normal, vec).normalize().multiplyScalar(offset)
-
- //sideVec = new THREE.Vector3().copy(math.getNormal2d({p1: O, p2: A})) //垂线
- //console.log('接近0或180',angle, sideVec)
- }else{
- let midVecLength = offset / Math.sin(angle/2)
- sideVec = new THREE.Vector3().addVectors(OA,OB).normalize().multiplyScalar(midVecLength) //角平分线 ( 和上一个方向保持在同一侧,故而顺时针和逆时针方向不同 )
- }
-
- }
-
- let p = new THREE.Vector3().addVectors(O, sideVec)
- newPoints.push(p)
- }
- this.points = newPoints
- super.update()
- }
-
- changeOffset(offset){
- this.offset = offset
- this.update()
- }
-
-
-
- addMarker({point,index }={}){
- super.addMarker({index, point, edge: LineDraw.createFatLine( [ ],{ mat: this.measure.getMat('edgeExpand') })})
- }
-
- getArea(){
-
- if(!this.closed)return
- this.getPoint2dInfo(this.points)
- this.measure.getArea.call(this)
- this.measure.getArea()
-
- let area = Math.abs(this.measure.area.value - this.area.value)
- this.area = {value:area, string: this.getConvertString(area, 'area') }
- return this.area
- }
-
- setSelected(state){
- this.edges.forEach(e=>{
- e.material = this.measure.getMat(state ? 'edgeExpand-selected' : 'edgeExpand')
- })
- viewer.dispatchEvent('content_changed')
- }
- }
- ExpandLine.prototype.getPoint2dInfo = Measure.prototype.getPoint2dInfo
- ExpandLine.prototype.getConvertString = Measure.prototype.getConvertString
-
-
- /*
- 按alt鼠标滚轮或WS键放慢。
- 按Alt键可以平行屏幕拖拽点。&dragPolyBeyondPoint 后缀在拖拽到无点云区域也是此效果。
- 按M键拖拽点可以复制出当前点
-
- */
|