Measure.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632
  1. import * as THREE from "../../../../libs/three.js/build/three.module.js";
  2. import {TextSprite} from "../TextSprite.js";
  3. import {Utils} from "../../../utils.js";
  4. import Label from "../Label.js";
  5. import {LineDraw} from "../../utils/DrawUtil.js";
  6. import math from "../../utils/math.js";
  7. import DepthBasicMaterial from "../../materials/DepthBasicMaterial.js";
  8. import Sprite from '../Sprite.js'
  9. import {config} from '../../settings.js'
  10. import browser from "../../utils/browser.js";
  11. import {ctrlPolygon} from './ctrlPolygon.js'
  12. let texLoader = new THREE.TextureLoader()
  13. let defaultColor = new THREE.Color(config.measure.default.color);
  14. let highlightColor = new THREE.Color(config.measure.highlight.color);
  15. let color = new THREE.Color(config.measure.color)
  16. let textColor = new THREE.Color(config.measure.textColor)
  17. var markerMats;
  18. var lineMats;
  19. var planeMats
  20. const textSizeRatio = math.linearClamp(window.outerWidth * window.outerHeight , [360*720, 1920*1080], [0.7, 1]) //pc字显示大一些 用
  21. const lineDepthInfo = {
  22. clipDistance : 15,//4,//消失距离
  23. occlusionDistance: 3,//1,//变为backColor距离
  24. }
  25. const markerMapShrink = browser.isMobile() ? 0.4 : 0.8 //触屏需要更大的热区
  26. const markerSizeInfo = {
  27. width2d : 18 / markerMapShrink , // nearBound : 1.5, farBound : 15,
  28. }
  29. /* const markerSizeInfo = {
  30. minSize : 10 , maxSize : 15 , nearBound : 1.5, farBound : 15,
  31. } */
  32. const labelSizeInfo = {width2d:200}
  33. const mainLabelProp = {
  34. //backgroundColor: {r: defaultColor.r*255, g: defaultColor.g*255, b: defaultColor.b*255, a:config.measure.default.opacity},
  35. backgroundColor: {r: 0, g: 0, b: 0, a:0},
  36. textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
  37. textBorderColor: {r:255, g: 255, b:255, a: 1.0},
  38. textBorderThick:3 ,
  39. fontsize: 15 * textSizeRatio,
  40. borderRadius : 12, margin:{x:20,y:4},
  41. renderOrder : Potree.config.renderOrders.measureLabel,
  42. pickOrder: Potree.config.renderOrders.measureLabel,
  43. disToLine:-0.15,
  44. useDepth : true ,
  45. // 2023.10 尽量不让数字被挡住
  46. clipDistance : 10,//消失距离
  47. occlusionDistance: 10,//变为backColor距离
  48. maxOcclusionFactor:0.3,
  49. maxClipFactor:0.8
  50. }
  51. const subLabelProp = {
  52. backgroundColor: {r: 255, g: 255, b: 255, a:0},
  53. textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
  54. textBorderColor: {r:255, g: 255, b:255, a: 1.0},
  55. textBorderThick:3 ,
  56. fontsize: 14 * textSizeRatio,
  57. renderOrder : Potree.config.renderOrders.measureLabelSub,
  58. pickOrder: Potree.config.renderOrders.measureLabelSub,
  59. disToLine:-0.13,
  60. }
  61. const angle = THREE.Math.degToRad(5);//显示水平垂直辅助线的最小角度
  62. const guideShowMinAngle = {min: angle, max: Math.PI/2 - angle}
  63. export class Measure extends ctrlPolygon{
  64. constructor (prop) {
  65. prop.dimension = '2d'
  66. super('measure',prop);
  67. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  68. this.name = this.measureType + this.constructor.counter //'Measure_' + this.constructor.counter;
  69. this.markerLabels = [];
  70. this.edgeLabels = [];
  71. this.angleLabels = [];
  72. this.coordinateLabels = [];
  73. this.area = {value:0,string:''}
  74. if( this.showArea ){
  75. this.areaLabel = this.createAreaLabel();
  76. this.add(this.areaLabel)
  77. }
  78. //add:
  79. if(this.atPlane || this.faceDirection){ //是一个平面上的话
  80. this.createGuideLine();
  81. }
  82. if(this.measureType == 'Distance' /* || this.measureType.includes('MulDistance') */){
  83. this.createHorVerGuideLine()
  84. }
  85. this.selectStates = {}
  86. this.setUnitSystem(prop.unit || viewer.unitConvert.UnitService.defaultSystem)
  87. Potree.Utils.setObjectLayers(this, 'measure' )
  88. if(this.measureType == 'MulDistance' || this.measureType == 'Hor MulDistance' || this.measureType == 'Ver MulDistance'){
  89. //this.showTotalDis = true
  90. this.totalDisLabel = this.createTotalDisLabel()
  91. this.add(this.totalDisLabel)
  92. }
  93. //addMarkers:
  94. this.initData(prop)
  95. this.pointsPos2d = new Map //屏幕上的二维坐标
  96. this.points_datasets || (this.points_datasets = []) //存每个点是哪个数据集
  97. this.addEventListener('marker_dropped',(e)=>{
  98. this.updateDatasetBelong(e.index)
  99. })
  100. this.addEventListener('isVisible', ()=>{
  101. viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'})
  102. })
  103. this.lastDropTime = 0
  104. }
  105. initData(prop){
  106. let makeIt = super.initData(prop)
  107. if(makeIt){
  108. this.edges.forEach(edge=>{edge.dispatchEvent('addHoverEvent') })
  109. }else{
  110. this.failBuilded = true
  111. }
  112. }
  113. updateDatasetBelong(changeIndex){//更新所属数据集
  114. if(Potree.settings.editType == "merge" || this.measureType == 'MulDistance Ring'){//点直接跟着数据集走,不用找整体的datasetId
  115. this.dataset_points[changeIndex] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.points_datasets[changeIndex], position:this.points[changeIndex].clone()})
  116. return
  117. }
  118. let old = this.datasetId
  119. let maxCount = {id:null,count:0}
  120. let datasets = {}
  121. this.points_datasets.forEach(e=>{
  122. if(e == void 0)return
  123. if(datasets[e]){
  124. datasets[e] ++
  125. }else{
  126. datasets[e] = 1
  127. }
  128. })
  129. for(let i in datasets) {
  130. if(datasets[i]>maxCount.count){
  131. maxCount = {id:i, count:datasets[i]}
  132. }
  133. }
  134. this.datasetId = maxCount.count > 0 ? maxCount.id : null
  135. //if(this.datasetId != old){
  136. //this.dispatchEvent({type:'changeDatasetId'})
  137. if(this.datasetId == void 0){
  138. this.dataset_points = null //可能为空或[null,null...]
  139. }else{
  140. this.dataset_points = this.points.map(e=>{
  141. return Potree.Utils.datasetPosTransform({toDataset:true,datasetId:this.datasetId, position:e.clone()})
  142. })
  143. }
  144. //}
  145. }
  146. transformByPointcloud(){//每次移动点云 or 加载测量线时要获取一下当前position //有地图时
  147. if(this.datasetId == void 0)return
  148. this.points = this.dataset_points.map(e=>{
  149. return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.datasetId, position:e.clone()})
  150. })
  151. this.getPoint2dInfo(this.points)
  152. this.update({ifUpdateMarkers:true})
  153. this.setSelected(false)//隐藏edgelabel
  154. }
  155. update(options={}) {
  156. if(options.index == -1)return
  157. super.update(options)
  158. if(this.showCoordinates && this.points.length>0){
  159. let position = this.points[0];
  160. this.markers[0].position.copy(position);
  161. { // coordinate labels
  162. let coordinateLabel = this.coordinateLabels[0];
  163. let pos = [
  164. position.toArray()
  165. ]
  166. if(viewer.transform){
  167. let lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray())
  168. let EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat)
  169. pos.push(lonlat,EPSG4550)
  170. }
  171. //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
  172. let msg = pos.map(a=>
  173. a.map(p => Utils.addCommas(p.toFixed(10))).join(", ")
  174. ).join("<br>")
  175. coordinateLabel.setText(msg);
  176. coordinateLabel.setPos(position)
  177. coordinateLabel.setVisible(true)//this.showCoordinates;
  178. }
  179. return
  180. }
  181. let setEdgeLabel = (label,p1,p2,distance)=>{//设置label位置和字
  182. this.setEdgeLabelPos(label,p1,p2)
  183. distance = distance == void 0 ? p1.distanceTo(p2) : distance;
  184. //var text = viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision, this.unitSystem, 1 , true)//distance要传0.1 这个factor
  185. var text = this.getConvertString(distance, 'distance')
  186. label.setText(text)
  187. return distance
  188. }
  189. /* let setEdgeLabel = (label,p1,p2,distance)=>{//设置label位置和字
  190. this.setEdgeLabelPos(label,p1,p2)
  191. distance = distance == void 0 ? p1.distanceTo(p2) : distance;
  192. var text = this.labelText || viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision , this.unitSystem, 0.001 , true, true)//distance要传0.1 这个factor
  193. label.setText(text)
  194. } */
  195. let lastIndex = this.points.length - 1
  196. let setLabel = (index)=>{
  197. let previousIndex = this.getIndex(index, -1)
  198. let nextIndex = this.getIndex(index, +1)
  199. let previousPoint = this.points[previousIndex];
  200. let point = this.points[index];
  201. let nextPoint = this.points[nextIndex];
  202. if(this.showDistances){ // edge labels
  203. let edgeLabel = this.edgeLabels[index];
  204. let distance = point.distanceTo(nextPoint)
  205. this.edges[index].distance_ = distance
  206. edgeLabel.shouldVisi = (index < lastIndex || this.isRect || this.closed && !this.isNew ) && distance>0
  207. //this.closed || edgeLabel.setVisible(edgeLabel.shouldVisi) //closed的在setEdgesDisplay中设置
  208. Utils.updateVisible(edgeLabel, 'shouldVisi', edgeLabel.shouldVisi, 2)
  209. if(edgeLabel.shouldVisi){
  210. edgeLabel.lineDir = new THREE.Vector3().subVectors(point,nextPoint).normalize() //[point,nextPoint]
  211. setEdgeLabel(edgeLabel,point,nextPoint,distance)
  212. }
  213. }
  214. }
  215. if(options.index != void 0){//更新第几个点
  216. setLabel(options.index)
  217. let previousIndex = this.getIndex(options.index, -1)
  218. setLabel(previousIndex)
  219. }else{
  220. for (let index = 0; index <= lastIndex; index++) {
  221. setLabel(index)
  222. }
  223. }
  224. if(Potree.config.measure.mulLabelHideFaraway ){
  225. this.measureType == 'MulDistance' && this.clearEdgeLabelVisi()
  226. }
  227. if(this.measureType == 'Distance' && this.points.length>1){//设置水平垂直辅助线
  228. var pTop, pBtm
  229. if(this.points[0].z > this.points[1].z ){
  230. pTop = this.points[0];
  231. pBtm = this.points[1];
  232. }else{
  233. pTop = this.points[1];
  234. pBtm = this.points[0];
  235. }
  236. let projectPos = new THREE.Vector3(pTop.x, pTop.y, pBtm.z);//两条guideline的交点
  237. {//倾斜角度太小的时候不显示
  238. let tan = pTop.distanceTo(projectPos) / pBtm.distanceTo(projectPos)
  239. let angle = Math.atan(tan);
  240. this.shouldShowHorVerGuide = angle > guideShowMinAngle.min && angle < guideShowMinAngle.max
  241. }
  242. LineDraw.updateLine(this.verGuideEdge, [pTop, projectPos])
  243. LineDraw.updateLine(this.horGuideEdge, [pBtm, projectPos])
  244. setEdgeLabel(this.verEdgeLabel,pTop,projectPos)
  245. setEdgeLabel(this.horEdgeLabel,pBtm,projectPos)
  246. this.verGuideEdge.visible = this.horGuideEdge.visible = this.shouldShowHorVerGuide
  247. this.verEdgeLabel.visible = this.horEdgeLabel.visible = this.shouldShowHorVerGuide
  248. }
  249. if(this.showArea && this.points.length > 2){ // update area
  250. let msg = this.getArea().string
  251. this.areaLabel.setPos(this.getCenter('areaPlaneCenter'))
  252. this.areaLabel.setText(msg);
  253. Utils.updateVisible(this.areaLabel, 'setVisible', true) //this.areaLabel.setVisible(true)
  254. }
  255. if(this.totalDisLabel){
  256. this.ifShowTotalDis()
  257. Utils.updateVisible(this.totalDisLabel,'setVisible', this.showTotalDis)
  258. this.edgeLabels.forEach(e=> Utils.updateVisible(e, 'showTotalDis', !this.showTotalDis))
  259. if(this.showTotalDis){
  260. let dis = this.getTotalDistance()
  261. let msg = this.getConvertString(dis, 'distance')
  262. this.center = null
  263. this.center = this.getCenter()
  264. this.totalDisLabel.setPos(this.center);
  265. this.totalDisLabel.setText(msg);
  266. }
  267. }
  268. };
  269. getArea(){
  270. let area
  271. if(this._area != void 0){
  272. area = this._area
  273. }else if(this.point2dInfo){
  274. area = Math.abs(math.getArea(this.point2dInfo.points2d))//this.getArea();
  275. }else{//mulDistance Ring 2d面
  276. area = Math.abs(math.getArea(this.points))
  277. }
  278. let msg = this.getConvertString(area, 'area')
  279. //let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ )
  280. this.area = {value:area, string:msg}
  281. return this.area
  282. }
  283. getConvertString(num, type){
  284. return viewer.unitConvert.convert(num, type, Potree.settings.precision, this.unitSystem, true ,
  285. {
  286. 'imperial': {minFactor: 0.01 },
  287. 'metric': {minFactor: 0.01}
  288. }
  289. )
  290. }
  291. ifShowTotalDis(){
  292. let show = this.points.length > 2
  293. if(show){
  294. let maxDis = 0.15
  295. let lastIndex = this.points.length - 1;
  296. for(let i=0;i<lastIndex;i++){
  297. let len = this.edges[i].distance_
  298. if(len > maxDis){
  299. show = false; break;
  300. }
  301. }
  302. }
  303. this.showTotalDis = show
  304. /* 连续测量:
  305. 1. ≥2次测量,单个距离<15cm时,居中显示总长, hover、选中时显示每段长度
  306. 2. 若连续测量的线段中,大于等于1段超出15cm,所有线段均显示长度
  307. -------------------
  308. */
  309. }
  310. clearEdgeLabelVisi(){//修改点位置后清空,下次render时会自动getEdgeLabelVisi
  311. let lastIndex = this.points.length - 1;
  312. for (let index = 0; index <= lastIndex; index++) {
  313. if(!this.closed && index == lastIndex)continue
  314. let edgeLabel = this.edgeLabels[index];
  315. edgeLabel.visiMap.clear()
  316. }
  317. }
  318. getEdgeLabelVisi(viewport){//获取多折线的edgelabel在不同视图里的可见性。要保证任何时候label能出现的线最小二维长度一致
  319. let camera = viewport.camera
  320. let lastIndex = this.points.length - 1;
  321. /* let pos2ds = this.points.map(point=> point.clone().project(camera) ) //即使只是旋转也会变动,尤其是转到屏幕外后变为显示。所以不用这种
  322. let minDis = 0.01; */
  323. let minDis = 0.02 , minAngleRatio = 0.07, minAngle
  324. let vecs
  325. let forceShow
  326. if(camera.type == 'OrthographicCamera'){
  327. minDis *= Math.pow(camera.top / camera.zoom, 2);
  328. //console.log(minDis)
  329. }else{
  330. if(Potree.settings.displayMode == 'showPanos' && viewer.images360.zoomLevel == Potree.settings.zoom.max){
  331. forceShow = true //当zoom到最大时强制显示,避免有的线太短永远显示不出长度
  332. }else{
  333. vecs = this.points.map(point=> new THREE.Vector3().subVectors(point, camera.position).normalize())
  334. minAngleRatio /= viewport.resolution.y / 1000 / textSizeRatio //角度占fov最小比率
  335. minAngle = minAngleRatio * THREE.Math.degToRad(camera.fov)
  336. }
  337. }
  338. for (let index = 0; index <= lastIndex; index++) {
  339. if(!this.closed && index == lastIndex)continue
  340. let edgeLabel = this.edgeLabels[index];
  341. let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
  342. let previousIndex = (index === 0) ? lastIndex : index - 1;
  343. let point = this.points[index];
  344. let nextPoint = this.points[nextIndex];
  345. /* let point2d = pos2ds[index];
  346. let nextPoint2d = pos2ds[nextIndex];
  347. let dis2d = point2d.distanceToSquared(nextPoint2d)
  348. let v = dis2d > minDis //可见长度太小,为避免拥挤,不显示
  349. edgeLabel.visiMap.set(camera, v) */
  350. let v
  351. if(forceShow){
  352. v = true
  353. }else if(camera.type == 'OrthographicCamera'){
  354. let vec = new THREE.Vector3().subVectors(point,nextPoint)
  355. let projVec = vec.projectOnPlane(viewport.view.direction)
  356. v = projVec.lengthSq() > minDis
  357. }else{
  358. let vec0 = vecs[index];
  359. let vec1 = vecs[nextIndex];
  360. v = Math.acos(vec0.dot(vec1)) > minAngle //角度过小代表可见长度太小,为避免拥挤,不显示
  361. }
  362. edgeLabel.visiMap.set(camera, v)
  363. }
  364. }
  365. setEdgeLabelPos(label,p1,p2){ //调整label的位置,使倾斜后看起来在线的中心,而不要挡住端点
  366. let center = new THREE.Vector3().addVectors(p1,p2).multiplyScalar(0.5);
  367. return label.setPos(center)
  368. if(label.lineDir && label.lineDir.length() > 0){
  369. if(viewer.mainViewport.camera.type == 'OrthographicCamera'){
  370. label.setPos(center)
  371. }else{
  372. //根据视线和线的夹角(后又加入相机和两个端点距离差)来决定标签偏移位置。+
  373. let eyePos = viewer.mainViewport.camera.position;
  374. let dir = viewer.mainViewport.view.direction //new THREE.Vector3().subVectors(center,eyePos).normalize()
  375. /*let centerDir = new THREE.Vector3().subVectors(center,eyePos).normalize()
  376. if(centerDir.dot(dir)<0){//中点在相机后方,就不设置
  377. label.setPos(center)
  378. return
  379. } */
  380. let cos = dir.dot(label.lineDir)
  381. let nearPoint = cos > 0 ? p2 : p1 //近端点。
  382. let far = cos > 0 ? p1 : p2 //远端点。
  383. let nearPointDir = new THREE.Vector3().subVectors(nearPoint,eyePos)//.normalize()
  384. //使label在中点和近端点中变化, 近端点可能到了相机后方,需要投影到相机所在平面上
  385. if(nearPointDir.dot(dir)<0){//近端点到了相机后方,前移。
  386. //let hfov = cameraLight.getHFOVForCamera(viewer.mainViewport.camera , true ); //暂且只看水平fov
  387. //if(nearPointDir.dot(dir)<Math.cos(hfov/2)){//近端点在镜头外,前移。 --但是这个就得把点转化成在镜头边缘而非左右两边(camDirPlane上)
  388. let ray = new THREE.Raycaster()
  389. ray.set(nearPoint, cos>0?label.lineDir:label.lineDir.clone().negate())
  390. let camDirPlane = new THREE.Plane().setFromNormalAndCoplanarPoint(dir, eyePos)
  391. nearPoint = ray.ray.intersectPlane(camDirPlane, new THREE.Vector3())
  392. if(!nearPoint){//线是垂直的,视线是水平的时候
  393. return label.setPos(center)
  394. }
  395. }
  396. //防止离远了之后也偏移很多,但远了之后相机到端点vec和到中点的vec的夹角接近,不需要怎么偏移的。
  397. let dis1 = nearPoint.distanceToSquared(eyePos)
  398. let dis2 = far.distanceToSquared(eyePos)
  399. let diff = Math.abs(dis1/dis2)
  400. diff<1 && (diff = 1/diff)
  401. diff = math.linearClamp(diff,[0, 30], [ 0,1 ])
  402. let efficiency = 0.7; // 0-1 数值越高,r越容易接近1或-1,label越容易在倾斜后靠近近端点。
  403. //let r = 0.5*efficiency*cos + 0.5
  404. let r = 0.5*efficiency*diff*cos + 0.5
  405. r = THREE.Math.clamp(r,0.1,0.9)
  406. //视线越接近线的方向,标签应该越往近端点偏移,防止看起来几乎在远端。
  407. if(cos > 0){
  408. center = p1.clone().multiplyScalar(1-r).add(nearPoint.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
  409. }else{
  410. center = nearPoint.clone().multiplyScalar(1-r).add(p2.clone().multiplyScalar(r)); //label在线上滑动,使尽量保持在视觉中心
  411. }
  412. label.setPos(center)
  413. }
  414. //归零
  415. //this.orient2dInfo = null
  416. //this.markers.forEach(e=>e.needsUpdate=true)
  417. }else{
  418. label.setPos(center)
  419. }
  420. }
  421. cloneMarker(cloneIndex, index){
  422. return this.addMarker({
  423. index,
  424. point: this.points[cloneIndex],
  425. dataset_point:this.dataset_points && this.dataset_points[cloneIndex],
  426. points_dataset:this.points_datasets[cloneIndex]
  427. })
  428. }
  429. addMarker (o={}) {
  430. var index = o.index == void 0 ? this.points.length : o.index //要当第几个
  431. let marker = new Sprite({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, name:"measure_point"} )
  432. Potree.Utils.setObjectLayers(marker, 'measure' )
  433. marker.pickOrder = marker.renderOrder = Potree.config.renderOrders.measureMarker
  434. marker.markerSelectStates = {}
  435. marker.addEventListener('startDragging',(e)=>{
  436. /* if(e.drag.dragViewport.name == 'MainView') */viewer.inputHandler.dispatchEvent( {type: 'measuring',v:true, cause:'startDragging', situation:'dragging', object:this})
  437. //add for 调试,方便后期增加点
  438. if(!this.isNew && viewer.inputHandler.pressedKeys['M'.charCodeAt(0)] && this.points.length<this.maxMarkers){
  439. viewer.measuringTool.history.beforeChange(this)
  440. let curIndex = this.markers.indexOf(marker)
  441. this.cloneMarker(curIndex, curIndex+1)
  442. }
  443. this.isNew || viewer.measuringTool.history.beforeChange(this)
  444. })
  445. marker.addEventListener('drop',(e)=>{
  446. if( e.button != THREE.MOUSE.LEFT )return
  447. viewer.inputHandler.dispatchEvent({type: 'measuring', v:false, cause:'stopDragging', situation:'dragging', object:this} )
  448. this.lastDropTime = Date.now()
  449. if(Potree.settings.adsorption){
  450. this.isNew || viewer.viewports.forEach((viewport)=>{
  451. this.getPointsPos2d(viewport, true )//forceUpdate
  452. })
  453. }
  454. this.isNew || viewer.measuringTool.history.afterChange(this)
  455. })
  456. marker.addEventListener('click',()=>{
  457. if(viewer.measuringTool.editMode == 'delPoint' ){
  458. /* if(this.points.length == this.minMarkers){//--前端去重绘
  459. viewer.scene.removeMeasurement(this)
  460. }else{ */
  461. viewer.measuringTool.history.beforeChange(this)
  462. let index = this.markers.indexOf(marker)
  463. this.removeMarker(index)
  464. viewer.measuringTool.history.afterChange(this)
  465. this.dispatchEvent('changed')
  466. //}
  467. }
  468. })
  469. //marker.measure = this
  470. let edge
  471. { // edges
  472. edge = LineDraw.createFatLine( [ ],{mat:this.getLineMat('edgeDefault')} )
  473. edge.pickOrder = 0
  474. Potree.Utils.setObjectLayers(edge, 'measure' )
  475. let addHoverEvent = ()=>{ //当非isNew时才添加事件
  476. let mouseover = (e) => {
  477. /* if(this.measureType == 'MulDistance'){
  478. } */
  479. this.setSelected(true, 'edge')
  480. };
  481. let mouseleave = (e) => {
  482. this.setSelected(false, 'edge')
  483. };
  484. edge.addEventListener('mouseover', mouseover);
  485. edge.addEventListener('mouseleave', mouseleave);
  486. edge.removeEventListener('addHoverEvent', addHoverEvent);
  487. edge.addEventListener('click',(e)=>{
  488. let now = Date.now()
  489. if(now - this.lastDropTime<100)return ;//防止拖拽marker时误触导致focus, 以及点到marker不focus
  490. if(viewer.measuringTool.editMode == 'addPoint' && this.points.length < this.maxMarkers){
  491. viewer.measuringTool.history.beforeChange(this)
  492. let index = this.edges.indexOf(edge) + 1
  493. let nextIndex = index % this.edges.length
  494. let point = math.getFootPoint(e.hoveredElement.point, this.points[index-1], this.points[nextIndex] );
  495. this.addMarker({
  496. index,
  497. point,
  498. dataset_point: this.dataset_points && new THREE.Vector3 , //初始化
  499. points_dataset : this.points_datasets[index-1] //使用前一个的
  500. })
  501. this.updateDatasetBelong(index) //获取dataset_point
  502. viewer.measuringTool.history.afterChange(this)
  503. this.dispatchEvent('changed')
  504. //this.update({})
  505. }else{
  506. this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure') //正在添加测量线时不要focus其他线(容易误触)
  507. }
  508. })
  509. }
  510. edge.addEventListener('addHoverEvent', addHoverEvent);
  511. if(!this.isNew){
  512. edge.dispatchEvent('addHoverEvent')
  513. }
  514. }
  515. super.addMarker(Object.assign(o, {index, marker, edge}))
  516. if(this.showEdges){ // edge labels
  517. const edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed)
  518. this.edgeLabels = [...this.edgeLabels.slice(0,index), edgeLabel, ...this.edgeLabels.slice(index,this.edgeLabels.length)]
  519. }
  520. if(this.showCoordinates){ // coordinate labels
  521. let coordinateLabel = new Label({
  522. className:'measure_pointPos',
  523. camera: viewer.scene.getActiveCamera()
  524. })
  525. coordinateLabel.setVisible(false)
  526. this.coordinateLabels.push(coordinateLabel);
  527. }
  528. let event = {
  529. type: 'marker_added',
  530. measurement: this,
  531. marker: marker
  532. };
  533. this.dispatchEvent(event);
  534. //this.setMarker(this.points.length - 1, point);
  535. this.update({index})//更新一下倒数第二条线
  536. return marker;//add
  537. };
  538. editStateChange(state){ //主要针对edgeLabels显示切换,编辑时显示
  539. super.editStateChange(state)
  540. if(!state){
  541. this.editStateTimer = setTimeout(()=>{
  542. if(!this.isEditing){
  543. this.dispatchEvent({type:'editStateChange',state:false})
  544. this.setEdgesDisplay(false)
  545. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true)
  546. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true)
  547. }
  548. },100)
  549. }else{
  550. if(!this.isEditing){
  551. this.dispatchEvent({type:'editStateChange',state:true})
  552. this.setEdgesDisplay(true)
  553. clearTimeout(this.editStateTimer)
  554. }
  555. }
  556. this.isEditing = state
  557. }
  558. setMarkerSelected(marker, state, hoverObject){
  559. //console.warn(marker.id , state, hoverObject)
  560. marker.markerSelectStates[hoverObject] = state
  561. let absoluteState = false
  562. for(var i in marker.markerSelectStates){
  563. if(marker.markerSelectStates[i] == 'hover'){
  564. absoluteState = true; break;
  565. }
  566. }
  567. if(absoluteState){
  568. marker.material = this.getMarkerMaterial('select')
  569. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker+1
  570. }else{
  571. marker.material = this.getMarkerMaterial('default')
  572. marker.renderOrder = marker.pickOrder = Potree.config.renderOrders.measureMarker
  573. }
  574. marker.selected = absoluteState
  575. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed')
  576. viewer.dispatchEvent('content_changed')
  577. }
  578. setEdgesDisplay(state, ignoreGuideLine){
  579. this.closed && this.edgeLabels.forEach(e=>Utils.updateVisible(e,'hover',state))
  580. if(this.totalDisLabel && !viewer.screenshoting){
  581. this.edgeLabels.forEach(e=> Utils.updateVisible(e, 'hover', state, 1, state ? 'add' : 'cancel'))
  582. Utils.updateVisible(this.totalDisLabel,'hover', !state )
  583. }
  584. if(!ignoreGuideLine && this.measureType == 'Distance'){
  585. this.horEdgeLabel.visible = this.verEdgeLabel.visible = this.horGuideEdge.visible = this.verGuideEdge.visible = !!(state && this.shouldShowHorVerGuide)
  586. }
  587. }
  588. setSelected(state, hoverObject){//add
  589. //console.log('setSelected',state, hoverObject)
  590. let absoluteState = !!state
  591. if(hoverObject){//如果没有hoverObject且state为false 就强制取消选中态
  592. this.selectStates[hoverObject] = state
  593. for(var i in this.selectStates){
  594. if(this.selectStates[i]){
  595. absoluteState = true; break;
  596. }
  597. }
  598. }
  599. if(absoluteState){
  600. this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) )
  601. this.edges.forEach(e=>{
  602. e.renderOrder = Potree.config.renderOrders.lines + 1
  603. e.material = this.getLineMat('edgeSelect')
  604. })
  605. this.areaPlane && (this.areaPlane.material = planeMats.selected)
  606. //this.areaLabel && this.areaLabel.elem.addClass('highLight')
  607. //this.closed || this.edgeLabels.forEach(e=>e.elem.addClass('highLight') )
  608. this.setEdgesDisplay(true, hoverObject=="screenshot")
  609. this.areaLabel && setLabelHightState(this.areaLabel, true)
  610. this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, true) )
  611. }else{
  612. this.markers.forEach(e=>this.setMarkerSelected(e, 'unhover', 'selectAll' ))
  613. this.edges.forEach(e=>e.material = this.getLineMat('edgeDefault') )
  614. this.areaPlane && (this.areaPlane.material = planeMats.default)
  615. this.setEdgesDisplay(false, hoverObject=="screenshot")
  616. //this.areaLabel && this.areaLabel.elem.removeClass('highLight')
  617. //this.closed || this.edgeLabels.forEach(e=>e.elem.removeClass('highLight') )
  618. this.areaLabel && setLabelHightState(this.areaLabel, false)
  619. this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, false) )
  620. }
  621. this.selected = absoluteState
  622. if(hoverObject != 'byList'){
  623. //this.bus && this.bus.emit('highlight', this.selected)
  624. this.dispatchEvent({type:'highlight',state:this.selected})//列表高亮
  625. }
  626. viewer.dispatchEvent('content_changed')
  627. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed')
  628. }
  629. removeMarker(index ){
  630. super.removeMarker(index)
  631. this.points_datasets.splice(index, 1);
  632. this.dataset_points && this.dataset_points.splice(index, 1)
  633. this.coordinateLabels.splice(index, 1);
  634. let edgeIndex = index//(index === 0) ? 0 : (index - 1);
  635. if(this.edgeLabels[edgeIndex]){
  636. this.edgeLabels[edgeIndex].dispose()
  637. this.edgeLabels.splice(edgeIndex, 1);
  638. }
  639. this.update({index: this.getIndex(index, -1)});
  640. this.dispatchEvent({type: 'marker_removed', measurement: this});
  641. }
  642. setPosition(index, position) {
  643. super.setPosition(index, position)
  644. let event = {
  645. type: 'marker_moved',
  646. measure: this,
  647. index: index,
  648. position: position.clone()
  649. };
  650. this.dispatchEvent(event);
  651. }
  652. dispose(){//add
  653. var labels = this.edgeLabels.concat(this.coordinateLabels)
  654. this.areaLabel && labels.push(this.areaLabel)
  655. labels.forEach(e=>e.dispose())
  656. super.dispose()
  657. this.dispatchEvent('disposed')
  658. }
  659. getTotalDistance () {
  660. if (this.points.length === 0) {
  661. return 0;
  662. }
  663. let distance = 0;
  664. for (let i = 1; i < this.points.length; i++) {
  665. let prev = this.points[i - 1];
  666. let curr = this.points[i];
  667. let d = prev.distanceTo(curr);
  668. distance += d;
  669. }
  670. if (this.closed && this.points.length > 1) {
  671. let first = this.points[0];
  672. let last = this.points[this.points.length - 1];
  673. let d = last.distanceTo(first);
  674. distance += d;
  675. }
  676. return distance;
  677. }
  678. getAngleBetweenLines (cornerPoint, point1, point2) {
  679. let v1 = new THREE.Vector3().subVectors(point1, cornerPoint);
  680. let v2 = new THREE.Vector3().subVectors(point2, cornerPoint);
  681. // avoid the error printed by threejs if denominator is 0
  682. const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
  683. if(denominator === 0){
  684. return 0;
  685. }else{
  686. return v1.angleTo(v2);
  687. }
  688. };
  689. getAngle (index) {
  690. if (this.points.length < 3 || index >= this.points.length) {
  691. return 0;
  692. }
  693. let previous = (index === 0) ? this.points[this.points.length - 1] : this.points[index - 1];
  694. let point = this.points[index];
  695. let next = this.points[(index + 1) % (this.points.length)];
  696. return this.getAngleBetweenLines(point, previous, next);
  697. }
  698. getCenter(type){
  699. if(this.center){
  700. return this.center.clone()
  701. }else{
  702. let center = this.points.reduce(function(total, currentValue ){
  703. return total.add(currentValue)
  704. }, new THREE.Vector3 )
  705. this.points.length && center.multiplyScalar(1/this.points.length)
  706. return center //求不出重心呜呜
  707. }
  708. }
  709. // updateAzimuth(){
  710. // // if(this.points.length !== 2){
  711. // // return;
  712. // // }
  713. // // const azimuth = this.azimuth;
  714. // // const [p0, p1] = this.points;
  715. // // const r = p0.distanceTo(p1);
  716. // }
  717. createGuideLine(){//add 辅助线
  718. var guideLine = LineDraw.createFatLine([ ],{mat:this.getLineMat('guide')} )
  719. guideLine.visible = false
  720. this.guideLine = guideLine
  721. this.add(guideLine);
  722. }
  723. createHorVerGuideLine(){//创建水平与垂直辅助线,仅距离测量有。
  724. var verGuideEdge = LineDraw.createFatLine([ ],{mat:this.getLineMat('guide')} )
  725. verGuideEdge.visible = false
  726. this.verGuideEdge = verGuideEdge
  727. verGuideEdge.name = 'verGuideEdge'
  728. var horGuideEdge = LineDraw.createFatLine([ ],{mat:this.getLineMat('guide')} )
  729. horGuideEdge.visible = false
  730. horGuideEdge.name = 'horGuideEdge'
  731. this.horGuideEdge = horGuideEdge
  732. this.add(this.verGuideEdge);
  733. this.add(this.horGuideEdge);
  734. //label:
  735. this.verEdgeLabel = this.createEdgeLabel('verGuideEdge')
  736. this.horEdgeLabel = this.createEdgeLabel('horGuideEdge')
  737. }
  738. createEdgeLabel(name, hasHoverEvent){
  739. let inf = {
  740. sizeInfo: labelSizeInfo, name:name||'edgeLabel',
  741. }
  742. if(name && name.includes('Guide')){
  743. inf.fontsize = 12
  744. }
  745. const edgeLabel = new TextSprite(
  746. $.extend({}, hasHoverEvent ? mainLabelProp : subLabelProp, inf)
  747. )
  748. if(hasHoverEvent){
  749. edgeLabel.addEventListener('mouseover',()=>{
  750. this.setSelected(true, 'edgeLabel')
  751. })
  752. edgeLabel.addEventListener('mouseleave',()=>{
  753. this.setSelected(false, 'edgeLabel')
  754. })
  755. edgeLabel.addEventListener('click',()=>{
  756. this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure')
  757. })
  758. }
  759. edgeLabel.visible = false
  760. edgeLabel.measure = this
  761. edgeLabel.sprite.material.depthTestWhenPick = true
  762. Potree.Utils.setObjectLayers(edgeLabel, 'measure' )
  763. this.add(edgeLabel)
  764. if(this.measureType == 'MulDistance'){
  765. edgeLabel.visiMap = new Map()
  766. }
  767. return edgeLabel
  768. }
  769. createAreaLabel(){
  770. const areaLabel = this.createCenterLabel('areaLabel')
  771. return areaLabel;
  772. }
  773. createTotalDisLabel(){
  774. const totalDisLabel = this.createCenterLabel('totalDisLabel')
  775. return totalDisLabel;
  776. }
  777. createCenterLabel(name){
  778. const centerLabel = new TextSprite(
  779. $.extend({},mainLabelProp,{sizeInfo: labelSizeInfo, name, disToLine:0, fontsize:16*textSizeRatio} )
  780. )
  781. centerLabel.addEventListener('mouseover',()=>{
  782. this.isNew || this.setSelected(true, 'centerLabel')
  783. })
  784. centerLabel.addEventListener('mouseleave',()=>{
  785. this.isNew || this.setSelected(false, 'centerLabel')
  786. })
  787. centerLabel.addEventListener('click',()=>{
  788. this.isNew || viewer.measuringTool.isAdding || viewer.focusOnObject(this, 'measure')
  789. })
  790. Potree.Utils.setObjectLayers(centerLabel, 'measure' )
  791. Utils.updateVisible(centerLabel, 'setVisible', false)
  792. return centerLabel;
  793. }
  794. getMarkerMaterial(type) {
  795. if(!markerMats){
  796. markerMats = {
  797. default: new DepthBasicMaterial($.extend({},lineDepthInfo,{
  798. transparent: !0,
  799. opacity: 1,
  800. map: texLoader.load(Potree.resourcePath+'/textures/pic_point_s32.png' ),
  801. useDepth:true ,
  802. mapScale: markerMapShrink
  803. })),
  804. select: new THREE.MeshBasicMaterial({
  805. transparent: !0,
  806. opacity: 1,
  807. depthTest:false,
  808. map: texLoader.load(Potree.resourcePath+'/textures/pic_point32.png'/* , null, null, { antialias: false } */),
  809. }),
  810. }
  811. Measure.markerMats = markerMats
  812. markerMats.select.map.repeat.set(1/markerMapShrink,1/markerMapShrink)
  813. markerMats.select.map.offset.set((markerMapShrink-1)/2/markerMapShrink, (markerMapShrink-1)/2/markerMapShrink)
  814. //markerMats.select.map.offset.set( -1.1 , -1.1 )
  815. }
  816. return markerMats[type]
  817. }
  818. getLineMat(type) {
  819. if(!Measure.lineMats){
  820. Measure.lineMats = {
  821. edgeDefault: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
  822. color: config.measure.default.color,
  823. lineWidth: config.measure.lineWidth,
  824. useDepth :true,
  825. dashWithDepth :true, // 只在被遮住的部分显示虚线,因为实线容易挡住label
  826. dashed :true,
  827. dashSize : 0.04,
  828. gapSize: 0.04,
  829. transparent: true,
  830. opacity: config.measure.default.opacity,
  831. depthTestWhenPick:true,
  832. })),
  833. edgeSelect: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
  834. color: config.measure.highlight.color,//'#f0ff00',
  835. dashSize: 0.5,
  836. gapSize: 0.2,
  837. lineWidth: config.measure.lineWidth ,
  838. transparent: true,
  839. opacity: config.measure.highlight.opacity
  840. })),
  841. guide: LineDraw.createFatLineMat($.extend({},lineDepthInfo,{
  842. color:config.measure.guide.color,
  843. dashSize: 0.1,
  844. gapSize: 0.02,
  845. dashed: true,
  846. lineWidth: config.measure.lineWidth/2
  847. })),
  848. }
  849. }
  850. return Measure.lineMats[type]
  851. }
  852. createAreaPlane(){
  853. planeMats || (planeMats = {
  854. default: new DepthBasicMaterial( $.extend({},lineDepthInfo,{
  855. color:color,
  856. side:THREE.DoubleSide,
  857. opacity:0.2,
  858. transparent:true,
  859. useDepth:true,
  860. })),
  861. selected: new THREE.MeshBasicMaterial({
  862. color: color ,
  863. side:THREE.DoubleSide,
  864. opacity:0.3,
  865. transparent:true,
  866. //wireframe:true
  867. })
  868. },Measure.planeMats = planeMats)
  869. return super.createAreaPlane(planeMats.default)
  870. }
  871. raycast (raycaster, intersects) {
  872. for (let i = 0; i < this.points.length; i++) {
  873. let marker = this.markers[i];
  874. marker.raycast(raycaster, intersects);
  875. }
  876. // recalculate distances because they are not necessarely correct
  877. // for scaled objects.
  878. // see https://github.com/mrdoob/three.js/issues/5827
  879. // TODO: remove this once the bug has been fixed
  880. for (let i = 0; i < intersects.length; i++) {
  881. let I = intersects[i];
  882. I.distance = raycaster.ray.origin.distanceTo(I.point);
  883. }
  884. intersects.sort(function (a, b) { return a.distance - b.distance; });
  885. };
  886. getPointsPos2d(viewport, update){//获取屏幕上的二维坐标
  887. let ps = this.pointsPos2d.get(viewport)
  888. if(update || !ps){
  889. let points = this.points.map(e=>{
  890. let p = Potree.Utils.getPos2d(e, viewport, viewer.renderArea )
  891. p.pos3d = e.clone(), p.object = this
  892. return p
  893. });
  894. this.pointsPos2d.set(viewport, points)
  895. console.log('updatePointsPos2d',this.uuid,viewport.name)
  896. }
  897. return this.pointsPos2d.get(viewport)
  898. }
  899. transformData(prop){
  900. if(prop.measureType == 'Point'){
  901. prop.showCoordinates = true,
  902. prop.closed = true,
  903. prop.maxMarkers = 1,
  904. prop.minMarkers = 1
  905. }else if(prop.measureType == 'Distance'){
  906. prop.showDistances = true,
  907. prop.showEdges = true,
  908. prop.maxMarkers = 2,
  909. prop.minMarkers = 2
  910. }else if(prop.measureType == 'MulDistance'){
  911. prop.showDistances = true,
  912. prop.showEdges = true,
  913. prop.minMarkers = 2
  914. }else if(prop.measureType == 'MulDistance Ring'){
  915. prop.showDistances = true,
  916. prop.showEdges = true,
  917. prop.showArea = true,
  918. prop.closed = true,
  919. prop.minMarkers = 3
  920. }else if(prop.measureType == 'Ver MulDistance'){
  921. prop.showDistances = true,
  922. prop.atPlane = true,
  923. prop.showEdges = true,
  924. prop.minMarkers = 2
  925. prop.faceDirection = "vertical"
  926. prop.unableDragAtMap = true
  927. }else if(prop.measureType == 'Hor MulDistance'){
  928. prop.showDistances = true,
  929. prop.atPlane = true,
  930. prop.showEdges = true,
  931. prop.minMarkers = 2
  932. prop.faceDirection = "horizontal"
  933. }else if(prop.measureType == 'Ver Distance'){
  934. prop.showDistances = true,
  935. prop.showEdges = true,
  936. prop.maxMarkers = 2,
  937. prop.minMarkers = 2,
  938. prop.faceDirection = "vertical"
  939. prop.unableDragAtMap = true
  940. }else if(prop.measureType == 'Hor Distance'){
  941. prop.showDistances = true,
  942. prop.showEdges = true,
  943. prop.maxMarkers = 2,
  944. prop.minMarkers = 2,
  945. prop.faceDirection = "horizontal"
  946. }else if(prop.measureType == 'Area'){
  947. prop.showDistances = true,
  948. Potree.settings.areaAtNotPlane || (prop.atPlane = true)
  949. prop.showEdges = true,
  950. prop.closed = true,
  951. prop.minMarkers = 3
  952. }else if(prop.measureType == 'Hor Area'){
  953. prop.showDistances = true,
  954. prop.atPlane = true,
  955. prop.showEdges = true,
  956. prop.closed = true,
  957. prop.minMarkers = 3
  958. prop.faceDirection = "horizontal"
  959. }else if(prop.measureType == 'Ver Area'){
  960. prop.showDistances = true,
  961. prop.atPlane = true,
  962. prop.showEdges = true,
  963. prop.closed = true,
  964. prop.minMarkers = 3
  965. prop.faceDirection = "vertical"
  966. prop.unableDragAtMap = true
  967. }else if(prop.measureType == 'Rect Area'){
  968. prop.showDistances = true,
  969. prop.atPlane = true,
  970. prop.showEdges = true,
  971. prop.closed = true,
  972. prop.minMarkers = 4
  973. prop.maxMarkers = 4
  974. }else if(prop.measureType == 'Hor Rect Area'){
  975. prop.showDistances = true,
  976. prop.atPlane = true,
  977. prop.showEdges = true,
  978. prop.closed = true,
  979. prop.minMarkers = 4
  980. prop.maxMarkers = 4
  981. prop.isRect = true
  982. prop.faceDirection = "horizontal"
  983. }else if(prop.measureType == 'Ver Rect Area'){
  984. prop.showDistances = true,
  985. prop.atPlane = true,
  986. prop.showEdges = true,
  987. prop.closed = true,
  988. prop.minMarkers = 4
  989. prop.maxMarkers = 4
  990. prop.isRect = true
  991. prop.faceDirection = "vertical"
  992. prop.unableDragAtMap = true
  993. }
  994. if(prop.atPlane && prop.closed){ //atPlane在同一平面上
  995. prop.showArea = true
  996. }
  997. super.transformData(prop)
  998. }
  999. setUnitSystem(unitSystem){
  1000. //console.log(this.name +':' +this.unitSystem)
  1001. if(unitSystem != this.unitSystem){
  1002. if(unitSystem == "metric"){
  1003. }else if(unitSystem == 'imperial'){
  1004. }
  1005. this.unitSystem = unitSystem
  1006. this.update()
  1007. }
  1008. }
  1009. reDraw(restMarkerCount=0){//重新开始画
  1010. super.reDraw(restMarkerCount)
  1011. if(this.measureType == 'Distance'){
  1012. this.shouldShowHorVerGuide = false
  1013. this.setEdgesDisplay(false)
  1014. }
  1015. if(this.showArea){
  1016. this.area = {value:0};
  1017. this.areaLabel && Utils.updateVisible(this.areaLabel, 'setVisible', false )
  1018. }
  1019. if(this.totalDisLabel && this.showTotalDis){
  1020. Utils.updateVisible(this.totalDisLabel, 'setVisible', false )
  1021. }
  1022. viewer.inputHandler.dispatchEvent( {type:'measuring', v:true, cause:'reDraw',object:this, situation:'dragging'} )
  1023. }
  1024. }
  1025. function setLabelHightState(label, state){
  1026. if(state){
  1027. let color = new THREE.Color(Potree.config.measure.highlight.color)
  1028. //label.sprite.material.opacity = config.measure.highlight.opacity
  1029. //label.setBackgroundColor({r:255*color.r, g:255*color.g, b:255*color.b, a:config.measure.highlight.opacity})
  1030. label.sprite.material.useDepth = false;
  1031. //label.textColor = {r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a: 1}
  1032. }else{
  1033. //label.setBackgroundColor({r: this.color.r*255, g: this.color.g*255, b: this.color.b*255, a:config.measure.default.opacity})
  1034. label.sprite.material.useDepth = true
  1035. //label.sprite.material.opacity = 0.98
  1036. //label.textColor = {r: 255, g: 255, b: 255, a: 1}
  1037. }
  1038. label.updateTexture()
  1039. }
  1040. /* function setLabelHightState(label, state){
  1041. if(state){
  1042. label.setBackgroundColor({r: highlightColor.r*255, g: highlightColor.g*255, b: highlightColor.b*255, a:config.measure.highlight.labelOpacity})
  1043. label.sprite.material.useDepth = false;
  1044. }else{
  1045. label.setBackgroundColor(mainLabelProp.backgroundColor)
  1046. label.sprite.material.useDepth = true
  1047. }
  1048. label.updateTexture()
  1049. //label.sprite.material.needsUpdate = true
  1050. }
  1051. */
  1052. function createCircleRadiusLabel(){
  1053. const circleRadiusLabel = new TextSprite("");
  1054. circleRadiusLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  1055. circleRadiusLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  1056. circleRadiusLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  1057. circleRadiusLabel.fontsize = 16;
  1058. circleRadiusLabel.material.depthTest = false;
  1059. circleRadiusLabel.material.opacity = 1;
  1060. circleRadiusLabel.visible = false;
  1061. return circleRadiusLabel;
  1062. }
  1063. function createCircleRadiusLine(){
  1064. /* const lineGeometry = new LineGeometry();
  1065. lineGeometry.setPositions([
  1066. 0, 0, 0,
  1067. 0, 0, 0,
  1068. ]);
  1069. const lineMaterial = new LineMaterial({
  1070. color: 0xff0000,
  1071. lineWidth: 2,
  1072. resolution: new THREE.Vector2(1000, 1000),
  1073. gapSize: 1,
  1074. dashed: true,
  1075. });
  1076. lineMaterial.depthTest = false;
  1077. const circleRadiusLine = new Line2(lineGeometry, lineMaterial);*/
  1078. var circleRadiusLine = LineDraw.createFatLine([ ],{
  1079. color:0xff0000,
  1080. dashSize: 0.5,
  1081. gapSize: 0.2,
  1082. lineWidth: config.measure.lineWidth
  1083. })
  1084. circleRadiusLine.visible = false;
  1085. return circleRadiusLine;
  1086. }
  1087. function createCircleLine(){
  1088. const coordinates = [];
  1089. let n = 128;
  1090. for(let i = 0; i <= n; i++){
  1091. let u0 = 2 * Math.PI * (i / n);
  1092. let u1 = 2 * Math.PI * (i + 1) / n;
  1093. let p0 = new THREE.Vector3(
  1094. Math.cos(u0),
  1095. Math.sin(u0),
  1096. 0
  1097. );
  1098. let p1 = new THREE.Vector3(
  1099. Math.cos(u1),
  1100. Math.sin(u1),
  1101. 0
  1102. );
  1103. coordinates.push(
  1104. p0,
  1105. p1
  1106. );
  1107. }
  1108. /* const geometry = new LineGeometry();
  1109. geometry.setPositions(coordinates);
  1110. const material = new LineMaterial({
  1111. color: 0xff0000,
  1112. dashSize: 5,
  1113. gapSize: 2,
  1114. lineWidth: 2,
  1115. resolution: new THREE.Vector2(1000, 1000),
  1116. });
  1117. material.depthTest = false;
  1118. const circleLine = new Line2(geometry, material);
  1119. circleLine.visible = false;
  1120. circleLine.computeLineDistances();*/
  1121. var circleLine = LineDraw.createFatLine(coordinates,{
  1122. color: 0xff0000,
  1123. dashSize: 0.5,
  1124. gapSize: 0.2,
  1125. lineWidth: config.measure.lineWidth
  1126. })
  1127. return circleLine;
  1128. }
  1129. /* function createCircleCenter(){
  1130. const sg = new THREE.markerGeometry(1, 32, 32);
  1131. const sm = new THREE.MeshNormalMaterial();
  1132. const circleCenter = new THREE.Mesh(sg, sm);
  1133. circleCenter.visible = false;
  1134. return circleCenter;
  1135. } */
  1136. function createLine(){
  1137. const line = LineDraw.createFatLine([ ],{
  1138. color: 0xff0000,
  1139. dashSize: 0.5,
  1140. gapSize: 0.2,
  1141. lineWidth: config.measure.lineWidth
  1142. })
  1143. return line;
  1144. }
  1145. function createCircle(){
  1146. const coordinates = [];
  1147. let n = 128;
  1148. for(let i = 0; i <= n; i++){
  1149. let u0 = 2 * Math.PI * (i / n);
  1150. let u1 = 2 * Math.PI * (i + 1) / n;
  1151. let p0 = new THREE.Vector3(
  1152. Math.cos(u0),
  1153. Math.sin(u0),
  1154. 0
  1155. );
  1156. let p1 = new THREE.Vector3(
  1157. Math.cos(u1),
  1158. Math.sin(u1),
  1159. 0
  1160. );
  1161. coordinates.push(
  1162. p0,
  1163. p1
  1164. );
  1165. }
  1166. var line = LineDraw.createFatLine(coordinates,{
  1167. color: 0xff0000,
  1168. dashSize: 0.5,
  1169. gapSize: 0.2,
  1170. lineWidth: config.measure.lineWidth
  1171. })
  1172. return line;
  1173. }
  1174. /* function createAzimuth(){
  1175. const azimuth = {
  1176. label: null,
  1177. center: null,
  1178. target: null,
  1179. north: null,
  1180. centerToNorth: null,
  1181. centerToTarget: null,
  1182. centerToTargetground: null,
  1183. targetgroundToTarget: null,
  1184. circle: null,
  1185. node: null,
  1186. };
  1187. const sg = new THREE.markerGeometry(1, 32, 32);
  1188. const sm = new THREE.MeshNormalMaterial();
  1189. {
  1190. const label = new TextSprite("");
  1191. label.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  1192. label.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  1193. label.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  1194. label.fontsize = 16;
  1195. label.material.depthTest = false;
  1196. label.material.opacity = 1;
  1197. azimuth.label = label;
  1198. }
  1199. azimuth.center = new THREE.Mesh(sg, sm);
  1200. azimuth.target = new THREE.Mesh(sg, sm);
  1201. azimuth.north = new THREE.Mesh(sg, sm);
  1202. azimuth.centerToNorth = createLine();
  1203. azimuth.centerToTarget = createLine();
  1204. azimuth.centerToTargetground = createLine();
  1205. azimuth.targetgroundToTarget = createLine();
  1206. azimuth.circle = createCircle();
  1207. azimuth.node = new THREE.Object3D();
  1208. azimuth.node.add(
  1209. azimuth.centerToNorth,
  1210. azimuth.centerToTarget,
  1211. azimuth.centerToTargetground,
  1212. azimuth.targetgroundToTarget,
  1213. azimuth.circle,
  1214. azimuth.label,
  1215. azimuth.center,
  1216. azimuth.target,
  1217. azimuth.north,
  1218. );
  1219. return azimuth;
  1220. } */
  1221. /*
  1222. 按alt鼠标滚轮或WS键放慢。
  1223. 按Alt键可以平行屏幕拖拽点。&dragPolyBeyondPoint 后缀在拖拽到无点云区域也是此效果。
  1224. 按M键拖拽点可以复制出当前点
  1225. */