Measure.js 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307
  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 {ctrlPolygon} from './ctrlPolygon.js'
  11. let texLoader = new THREE.TextureLoader()
  12. let defaultColor = new THREE.Color(config.measure.default.color);
  13. let highlightColor = new THREE.Color(config.measure.highlight.color);
  14. let color = new THREE.Color(config.measure.color)
  15. let textColor = new THREE.Color(config.measure.textColor)
  16. var markerMats;
  17. var lineMats;
  18. var planeMats
  19. const lineDepthInfo = {
  20. clipDistance : 4,//消失距离
  21. occlusionDistance: 1,//变为backColor距离
  22. }
  23. const LabelDepthInfo = {
  24. clipDistance : 6,//消失距离
  25. occlusionDistance: 2,//变为backColor距离
  26. }
  27. /* const LabelDepthInfo = {
  28. clipDistance : 0.1,//消失距离
  29. occlusionDistance: 0.1,//变为backColor距离
  30. } */
  31. const markerSizeInfo = {
  32. minSize : 25 , maxSize : 65, nearBound : 0.2, farBound : 4,
  33. }
  34. const labelSizeInfo = {width2d:200}
  35. const mainLabelProp = {
  36. backgroundColor: {r: defaultColor.r*255, g: defaultColor.g*255, b: defaultColor.b*255, a:config.measure.default.opacity},
  37. textColor: {r: textColor.r*255, g: textColor.g*255, b: textColor.b*255, a: 1.0},
  38. fontsize:16,
  39. useDepth : true ,
  40. renderOrder : 5, pickOrder:5,
  41. }
  42. const subLabelProp = {
  43. backgroundColor: {r: 255, g: 255, b: 255, a:1},
  44. textColor: {r: 0, g: 0, b:0, a: 1.0},
  45. fontsize:14,
  46. renderOrder : 4, pickOrder:4,
  47. }
  48. const angle = THREE.Math.degToRad(5);//显示水平垂直辅助线的最小角度
  49. const guideShowMinAngle = {min: angle, max: Math.PI/2 - angle}
  50. export class Measure extends ctrlPolygon{
  51. constructor (prop) {
  52. prop.dimension = '2d'
  53. super('measure',prop);
  54. this.constructor.counter = (this.constructor.counter === undefined) ? 0 : this.constructor.counter + 1;
  55. this.name = this.measureType + this.constructor.counter //'Measure_' + this.constructor.counter;
  56. this.markerLabels = [];
  57. this.edgeLabels = [];
  58. this.angleLabels = [];
  59. this.coordinateLabels = [];
  60. this.area = {value:0,string:''}
  61. if( this.showArea ){
  62. this.areaLabel = this.createAreaLabel();
  63. this.add(this.areaLabel)
  64. }
  65. //add:
  66. if(this.atPlane || this.faceDirection){ //是一个平面上的话
  67. this.createGuideLine();
  68. }
  69. if(this.measureType == 'Distance' /* || this.measureType.includes('MulDistance') */){
  70. this.createHorVerGuideLine()
  71. }
  72. this.selectStates = {}
  73. this.setUnitSystem(prop.unit || viewer.unitConvert.UnitService.defaultSystem)
  74. Potree.Utils.setObjectLayers(this, 'measure' )
  75. //addMarkers:
  76. this.initData(prop)
  77. this.points_datasets || (this.points_datasets = []) //存每个点是哪个数据集
  78. this.addEventListener('marker_dropped',(e)=>{
  79. this.updateDatasetBelong(e.index)
  80. })
  81. this.addEventListener('isVisible', ()=>{
  82. viewer.mapViewer && viewer.mapViewer.dispatchEvent({type:'content_changed'})
  83. })
  84. }
  85. initData(prop){
  86. let makeIt = super.initData(prop)
  87. if(makeIt){
  88. this.edges.forEach(edge=>{edge.dispatchEvent('addHoverEvent') })
  89. }else{
  90. this.failBuilded = true
  91. }
  92. }
  93. updateDatasetBelong(changeIndex){//更新所属数据集
  94. if(Potree.settings.editType == "merge"){//无地图
  95. /* this.dataset_points = this.points.map((e,i)=>{
  96. return Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.points_datasets[i], position:e.clone()})
  97. }) */
  98. this.dataset_points[changeIndex] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.points_datasets[changeIndex], position:this.points[changeIndex].clone()})
  99. return
  100. }
  101. let old = this.datasetId
  102. let maxCount = {id:null,count:0}
  103. let datasets = {}
  104. this.points_datasets.forEach(e=>{
  105. if(e == void 0)return
  106. if(datasets[e]){
  107. datasets[e] ++
  108. }else{
  109. datasets[e] = 1
  110. }
  111. })
  112. for(let i in datasets) {
  113. if(datasets[i]>maxCount.count){
  114. maxCount = {id:i, count:datasets[i]}
  115. }
  116. }
  117. this.datasetId = maxCount.count > 0 ? maxCount.id : null
  118. //if(this.datasetId != old){
  119. //this.dispatchEvent({type:'changeDatasetId'})
  120. if(this.datasetId == void 0){
  121. this.dataset_points = null //可能为空或[null,null...]
  122. }else{
  123. this.dataset_points = this.points.map(e=>{
  124. return Potree.Utils.datasetPosTransform({toDataset:true,datasetId:this.datasetId, position:e.clone()})
  125. })
  126. }
  127. //}
  128. }
  129. transformByPointcloud(){//每次移动点云 or 加载测量线时要获取一下当前position //有地图时
  130. if(this.datasetId == void 0)return
  131. this.points = this.dataset_points.map(e=>{
  132. return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.datasetId, position:e.clone()})
  133. })
  134. this.getPoint2dInfo(this.points)
  135. this.update({ifUpdateMarkers:true})
  136. this.setSelected(false)//隐藏edgelabel
  137. }
  138. update(options={}) {
  139. super.update(options)
  140. if(this.showCoordinates && this.points.length>0){
  141. let position = this.points[0];
  142. this.markers[0].position.copy(position);
  143. { // coordinate labels
  144. let coordinateLabel = this.coordinateLabels[0];
  145. let lonlat = viewer.transform.lonlatToLocal.inverse(position.toArray())
  146. let EPSG4550 = viewer.transform.lonlatTo4550.forward(lonlat)
  147. let pos = [
  148. position.toArray(),
  149. lonlat,
  150. EPSG4550
  151. ]
  152. //let msg = position.toArray().map(p => Utils.addCommas(p.toFixed(2))).join(" / ");
  153. let msg = pos.map(a=>
  154. a.map(p => Utils.addCommas(p.toFixed(10))).join(", ")
  155. ).join("<br>")
  156. coordinateLabel.setText(msg);
  157. coordinateLabel.setPos(position)
  158. coordinateLabel.setVisible(true)//this.showCoordinates;
  159. }
  160. return
  161. }
  162. let setEdgeLabel = (label,p1,p2,distance)=>{//设置label位置和字
  163. let center = new THREE.Vector3().addVectors(p1,p2).multiplyScalar(0.5);
  164. label.setPos(center)
  165. distance = distance == void 0 ? p1.distanceTo(p2) : distance;
  166. var text = viewer.unitConvert.convert(distance, 'distance', Potree.settings.precision, this.unitSystem, 0.1 , true)//distance要传0.1 这个factor
  167. label.setText(text)
  168. return distance
  169. }
  170. let lastIndex = this.points.length - 1;
  171. for (let index = 0; index <= lastIndex; index++) {
  172. let nextIndex = (index + 1 > lastIndex) ? 0 : index + 1;
  173. let previousIndex = (index === 0) ? lastIndex : index - 1;
  174. //if(!this.closed && nextIndex == 0 )break; //add
  175. let point = this.points[index];
  176. let nextPoint = this.points[nextIndex];
  177. let previousPoint = this.points[previousIndex];
  178. if(this.showDistances){ // edge labels
  179. let edgeLabel = this.edgeLabels[index];
  180. let distance = point.distanceTo(nextPoint)
  181. edgeLabel.shouldVisi = (index < lastIndex || this.isRect || this.closed && !this.isNew ) && distance>0
  182. /* this.closed || */edgeLabel.setVisible(edgeLabel.shouldVisi)
  183. if(edgeLabel.visible){
  184. setEdgeLabel(edgeLabel,point,nextPoint,distance)
  185. }
  186. edgeLabel.sprite.lineDir = new THREE.Vector3().subVectors(point,nextPoint).normalize() //[point,nextPoint]
  187. }
  188. }
  189. if(this.measureType == 'Distance' && this.points.length>1){//设置水平垂直辅助线
  190. var pTop, pBtm
  191. if(this.points[0].z > this.points[1].z ){
  192. pTop = this.points[0];
  193. pBtm = this.points[1];
  194. }else{
  195. pTop = this.points[1];
  196. pBtm = this.points[0];
  197. }
  198. let projectPos = new THREE.Vector3(pTop.x, pTop.y, pBtm.z);//两条guideline的交点
  199. {//倾斜角度太小的时候不显示
  200. let tan = pTop.distanceTo(projectPos) / pBtm.distanceTo(projectPos)
  201. let angle = Math.atan(tan);
  202. this.shouldShowHorVerGuide = angle > guideShowMinAngle.min && angle < guideShowMinAngle.max
  203. }
  204. LineDraw.updateLine(this.verGuideEdge, [pTop, projectPos])
  205. LineDraw.updateLine(this.horGuideEdge, [pBtm, projectPos])
  206. setEdgeLabel(this.verEdgeLabel,pTop,projectPos)
  207. setEdgeLabel(this.horEdgeLabel,pBtm,projectPos)
  208. this.verGuideEdge.visible = this.horGuideEdge.visible = this.shouldShowHorVerGuide
  209. this.verEdgeLabel.visible = this.horEdgeLabel.visible = this.shouldShowHorVerGuide
  210. }
  211. if(this.showArea && this.point2dInfo){ // update area
  212. /* if(this.points.length>2){
  213. this.area = {value:0};
  214. this.areaLabel.setVisible(false)
  215. }else{ */
  216. let area = Math.abs(math.getArea(this.point2dInfo.points2d))//this.getArea();
  217. let msg = viewer.unitConvert.convert(area, 'area', Potree.settings.precision, this.unitSystem/* , 0.1 */ )
  218. this.area = {value:area, string:msg}
  219. this.areaLabel.setPos(this.center);
  220. this.areaLabel.setText(msg);
  221. this.areaLabel.setVisible(true)
  222. //}
  223. }
  224. };
  225. addMarker (o={}) {
  226. let marker = new Sprite({mat:this.getMarkerMaterial('default'), sizeInfo: markerSizeInfo, name:"measure_point"} )
  227. Potree.Utils.setObjectLayers(marker, 'measure' )
  228. marker.pickOrder = marker.renderOrder = 3
  229. marker.markerSelectStates = {}
  230. marker.addEventListener('startDragging',(e)=>{
  231. if(e.drag.dragViewport.name == 'MainView')viewer.inputHandler.dispatchEvent( {type: 'isMeasuring',v:true, cause:'startDragging'})
  232. })
  233. marker.addEventListener('drop',(e)=>{
  234. viewer.inputHandler.dispatchEvent({type: 'isMeasuring', v:false, cause:'stopDragging'} )
  235. })
  236. let edge
  237. { // edges
  238. edge = LineDraw.createFatLine( [ ],{material:this.getLineMat('edgeDefault')} )
  239. edge.pickOrder = 0
  240. Potree.Utils.setObjectLayers(edge, 'measure' )
  241. let addHoverEvent = ()=>{ //当非isNew时才添加事件
  242. let mouseover = (e) => {this.setSelected(true, 'edge')};
  243. let mouseleave = (e) => {this.setSelected(false, 'edge')};
  244. edge.addEventListener('mouseover', mouseover);
  245. edge.addEventListener('mouseleave', mouseleave);
  246. edge.removeEventListener('addHoverEvent', addHoverEvent);
  247. }
  248. edge.addEventListener('addHoverEvent', addHoverEvent);
  249. }
  250. super.addMarker({point:o.point, marker:marker, edge})
  251. if(this.showEdges){ // edge labels
  252. const edgeLabel = this.createEdgeLabel('edgeLabel', !this.closed)
  253. this.edgeLabels.push(edgeLabel);
  254. }
  255. if(this.showCoordinates){ // coordinate labels
  256. let coordinateLabel = new Label({
  257. className:'measure_pointPos',
  258. camera: viewer.scene.getActiveCamera()
  259. })
  260. coordinateLabel.setVisible(false)
  261. this.coordinateLabels.push(coordinateLabel);
  262. }
  263. let event = {
  264. type: 'marker_added',
  265. measurement: this,
  266. marker: marker
  267. };
  268. this.dispatchEvent(event);
  269. //this.setMarker(this.points.length - 1, point);
  270. this.update()//更新一下倒数第二条线
  271. return marker;//add
  272. };
  273. editStateChange(state){ //主要针对edgeLabels显示切换,编辑时显示
  274. super.editStateChange(state)
  275. if(!state){
  276. this.editStateTimer = setTimeout(()=>{
  277. if(!this.isEditing){
  278. this.dispatchEvent({type:'editStateChange',state:false})
  279. this.setEdgesDisplay(false)
  280. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true)
  281. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true)
  282. }
  283. },100)
  284. }else{
  285. if(!this.isEditing){
  286. this.dispatchEvent({type:'editStateChange',state:true})
  287. this.setEdgesDisplay(true)
  288. clearTimeout(this.editStateTimer)
  289. }
  290. }
  291. this.isEditing = state
  292. }
  293. setMarkerSelected(marker, state, hoverObject){
  294. //console.warn(marker.id , state, hoverObject)
  295. marker.markerSelectStates[hoverObject] = state
  296. let absoluteState = false
  297. for(var i in marker.markerSelectStates){
  298. if(marker.markerSelectStates[i] == 'hover'){
  299. absoluteState = true; break;
  300. }
  301. }
  302. if(absoluteState){
  303. marker.material = this.getMarkerMaterial('select')
  304. }else{
  305. marker.material = this.getMarkerMaterial('default')
  306. }
  307. marker.selected = absoluteState
  308. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed')
  309. viewer.dispatchEvent('content_changed')
  310. }
  311. setEdgesDisplay(state, ignoreGuideLine){
  312. this.closed && this.edgeLabels.forEach(e=>e.setVisible(!!(state && e.shouldVisi)) )
  313. if(!ignoreGuideLine && this.measureType == 'Distance'){
  314. this.horEdgeLabel.visible = this.verEdgeLabel.visible = this.horGuideEdge.visible = this.verGuideEdge.visible = !!(state && this.shouldShowHorVerGuide)
  315. }
  316. }
  317. setSelected(state, hoverObject){//add
  318. //console.log('setSelected', state, hoverObject)
  319. hoverObject && (this.selectStates[hoverObject] = state)
  320. let absoluteState = false
  321. for(var i in this.selectStates){
  322. if(this.selectStates[i]){
  323. absoluteState = true; break;
  324. }
  325. }
  326. if(absoluteState){
  327. this.markers.forEach(e=>this.setMarkerSelected(e, 'hover', 'selectAll' ) )
  328. this.edges.forEach(e=>e.material = this.getLineMat('edgeSelect') )
  329. this.areaPlane && (this.areaPlane.material = planeMats.selected)
  330. //this.areaLabel && this.areaLabel.elem.addClass('highLight')
  331. //this.closed || this.edgeLabels.forEach(e=>e.elem.addClass('highLight') )
  332. this.setEdgesDisplay(true, hoverObject=="screenshot")
  333. this.areaLabel && setLabelHightState(this.areaLabel, true)
  334. this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, true) )
  335. }else{
  336. this.markers.forEach(e=>this.setMarkerSelected(e, 'unhover', 'selectAll' ))
  337. this.edges.forEach(e=>e.material = this.getLineMat('edgeDefault') )
  338. this.areaPlane && (this.areaPlane.material = planeMats.default)
  339. this.setEdgesDisplay(false, hoverObject=="screenshot")
  340. //this.areaLabel && this.areaLabel.elem.removeClass('highLight')
  341. //this.closed || this.edgeLabels.forEach(e=>e.elem.removeClass('highLight') )
  342. this.areaLabel && setLabelHightState(this.areaLabel, false)
  343. this.closed || this.edgeLabels.forEach(e=>setLabelHightState(e, false) )
  344. }
  345. this.selected = absoluteState
  346. if(hoverObject != 'byList'){
  347. //this.bus && this.bus.emit('highlight', this.selected)
  348. this.dispatchEvent({type:'highlight',state:this.selected})//列表高亮
  349. }
  350. viewer.dispatchEvent('content_changed')
  351. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed')
  352. }
  353. removeMarker(index ){
  354. super.removeMarker(index)
  355. this.points_datasets.splice(index, 1);
  356. this.dataset_points && this.dataset_points.splice(index, 1)
  357. this.coordinateLabels.splice(index, 1);
  358. let edgeIndex = index//(index === 0) ? 0 : (index - 1);
  359. if(this.edgeLabels[edgeIndex]){
  360. this.edgeLabels[edgeIndex].dispose()
  361. this.edgeLabels.splice(edgeIndex, 1);
  362. }
  363. this.update();
  364. this.dispatchEvent({type: 'marker_removed', measurement: this});
  365. }
  366. setPosition(index, position) {
  367. super.setPosition(index, position)
  368. let event = {
  369. type: 'marker_moved',
  370. measure: this,
  371. index: index,
  372. position: position.clone()
  373. };
  374. this.dispatchEvent(event);
  375. }
  376. dispose(){//add
  377. var labels = this.edgeLabels.concat(this.coordinateLabels)
  378. this.areaLabel && labels.push(this.areaLabel)
  379. labels.forEach(e=>e.dispatchEvent({type:'dispose'}))
  380. super.dispose()
  381. }
  382. getTotalDistance () {
  383. if (this.points.length === 0) {
  384. return 0;
  385. }
  386. let distance = 0;
  387. for (let i = 1; i < this.points.length; i++) {
  388. let prev = this.points[i - 1];
  389. let curr = this.points[i];
  390. let d = prev.distanceTo(curr);
  391. distance += d;
  392. }
  393. if (this.closed && this.points.length > 1) {
  394. let first = this.points[0];
  395. let last = this.points[this.points.length - 1];
  396. let d = last.distanceTo(first);
  397. distance += d;
  398. }
  399. return distance;
  400. }
  401. getAngleBetweenLines (cornerPoint, point1, point2) {
  402. let v1 = new THREE.Vector3().subVectors(point1, cornerPoint);
  403. let v2 = new THREE.Vector3().subVectors(point2, cornerPoint);
  404. // avoid the error printed by threejs if denominator is 0
  405. const denominator = Math.sqrt( v1.lengthSq() * v2.lengthSq() );
  406. if(denominator === 0){
  407. return 0;
  408. }else{
  409. return v1.angleTo(v2);
  410. }
  411. };
  412. getAngle (index) {
  413. if (this.points.length < 3 || index >= this.points.length) {
  414. return 0;
  415. }
  416. let previous = (index === 0) ? this.points[this.points.length - 1] : this.points[index - 1];
  417. let point = this.points[index];
  418. let next = this.points[(index + 1) % (this.points.length)];
  419. return this.getAngleBetweenLines(point, previous, next);
  420. }
  421. getCenter(/* update */){
  422. if(this.closed){
  423. return this.center.clone()
  424. }else{
  425. let center = this.points.reduce(function(total, currentValue ){
  426. return total.add(currentValue)
  427. }, new THREE.Vector3 )
  428. center.multiplyScalar(1/this.points.length)
  429. return center //求不出重心呜呜
  430. }
  431. }
  432. // updateAzimuth(){
  433. // // if(this.points.length !== 2){
  434. // // return;
  435. // // }
  436. // // const azimuth = this.azimuth;
  437. // // const [p0, p1] = this.points;
  438. // // const r = p0.distanceTo(p1);
  439. // }
  440. createGuideLine(){//add 辅助线
  441. var guideLine = LineDraw.createFatLine([ ],{material:this.getLineMat('guide')} )
  442. guideLine.visible = false
  443. this.guideLine = guideLine
  444. this.add(guideLine);
  445. }
  446. createHorVerGuideLine(){//创建水平与垂直辅助线,仅距离测量有。
  447. var verGuideEdge = LineDraw.createFatLine([ ],{material:this.getLineMat('guide')} )
  448. verGuideEdge.visible = false
  449. this.verGuideEdge = verGuideEdge
  450. verGuideEdge.name = 'verGuideEdge'
  451. var horGuideEdge = LineDraw.createFatLine([ ],{material:this.getLineMat('guide')} )
  452. horGuideEdge.visible = false
  453. horGuideEdge.name = 'horGuideEdge'
  454. this.horGuideEdge = horGuideEdge
  455. this.add(this.verGuideEdge);
  456. this.add(this.horGuideEdge);
  457. //label:
  458. this.verEdgeLabel = this.createEdgeLabel('verGuideEdge')
  459. this.horEdgeLabel = this.createEdgeLabel('horGuideEdge')
  460. }
  461. focus(){
  462. viewer.focusOnObject(this, 'measure')
  463. if(this.clickSelected)return
  464. this.setSelected(true, 'focus')
  465. this.dispatchEvent({type:'selected', state:true})
  466. this.clickSelected = true
  467. //viewer.dispatchEvent({type:'selectMeasure', measure:this})
  468. let cancelSelect = ()=>{
  469. this.clickSelected = false
  470. this.removeEventListener('cancelSelect', cancelSelect)
  471. viewer.removeEventListener('global_click', cancelSelect)
  472. this.setSelected(false, 'focus')
  473. this.dispatchEvent({type:'selected', state:false})
  474. }
  475. setTimeout(()=>{
  476. this.addEventListener('cancelSelect', cancelSelect)
  477. viewer.addEventListener('global_click', cancelSelect)
  478. },10)
  479. }
  480. createEdgeLabel(name, hasHoverEvent){
  481. const edgeLabel = new TextSprite(
  482. $.extend(hasHoverEvent ? mainLabelProp : subLabelProp,{sizeInfo: labelSizeInfo, name:name||'edgeLabel'})
  483. )
  484. if(hasHoverEvent){
  485. edgeLabel.addEventListener('mouseover',()=>{
  486. this.setSelected(true, 'edgeLabel')
  487. })
  488. edgeLabel.addEventListener('mouseleave',()=>{
  489. this.setSelected(false, 'edgeLabel')
  490. })
  491. edgeLabel.addEventListener('click',()=>{
  492. if(!this.isNew) this.focus()
  493. })
  494. }
  495. edgeLabel.visible = false
  496. edgeLabel.sprite.material.depthTestWhenPick = true
  497. Potree.Utils.setObjectLayers(edgeLabel, 'measure' )
  498. this.add(edgeLabel)
  499. return edgeLabel
  500. }
  501. createAreaLabel(){
  502. /* const areaLabel = new Label({
  503. className:'measure_area',
  504. })
  505. areaLabel.elem.on('mouseover',()=>{
  506. this.setSelected(true, 'areaLabel')
  507. })
  508. areaLabel.elem.on('mouseout',()=>{
  509. this.setSelected(false, 'areaLabel')
  510. }) */
  511. const areaLabel = new TextSprite(
  512. $.extend(mainLabelProp,{sizeInfo: labelSizeInfo, name:'areaLabel_'} )
  513. )
  514. areaLabel.addEventListener('mouseover',()=>{
  515. this.setSelected(true, 'areaLabel')
  516. })
  517. areaLabel.addEventListener('mouseleave',()=>{
  518. this.setSelected(false, 'areaLabel')
  519. })
  520. areaLabel.addEventListener('click',()=>{
  521. if(!this.isNew) this.focus()
  522. })
  523. Potree.Utils.setObjectLayers(areaLabel, 'measure' )
  524. areaLabel.setVisible(false)
  525. return areaLabel;
  526. }
  527. getMarkerMaterial(type) {
  528. if(!markerMats){
  529. markerMats = {
  530. default: new DepthBasicMaterial($.extend({},lineDepthInfo,{
  531. transparent: !0,
  532. opacity: 1,
  533. map: texLoader.load(Potree.resourcePath+'/textures/pic_point_s32.png' ),
  534. useDepth:true
  535. })),
  536. select: new THREE.MeshBasicMaterial({
  537. transparent: !0,
  538. opacity: 1,
  539. depthTest:false,
  540. map: texLoader.load(Potree.resourcePath+'/textures/pic_point32.png'/* , null, null, { antialias: false } */),
  541. }),
  542. }
  543. Measure.markerMats = markerMats
  544. }
  545. return markerMats[type]
  546. }
  547. getLineMat(type) {
  548. if(!Measure.lineMats){
  549. Measure.lineMats = {
  550. edgeDefault: LineDraw.createFatLineMat({
  551. color: config.measure.default.color,
  552. lineWidth: config.measure.lineWidth,
  553. useDepth :true,
  554. dashWithDepth :true, // 只在被遮住的部分显示虚线,因为实线容易挡住label
  555. dashed :true,
  556. dashSize : 0.04,
  557. gapSize: 0.04,
  558. transparent: true,
  559. opacity: config.measure.default.opacity,
  560. depthTestWhenPick:true,
  561. }),
  562. edgeSelect: LineDraw.createFatLineMat({
  563. color: config.measure.highlight.color,//'#f0ff00',
  564. dashSize: 0.5,
  565. gapSize: 0.2,
  566. lineWidth: config.measure.lineWidth ,
  567. transparent: true,
  568. opacity: config.measure.highlight.opacity
  569. }),
  570. guide: LineDraw.createFatLineMat({
  571. color:config.measure.guide.color,
  572. dashSize: 0.1,
  573. gapSize: 0.02,
  574. dashed: true,
  575. lineWidth: config.measure.lineWidth
  576. })
  577. }
  578. }
  579. return Measure.lineMats[type]
  580. }
  581. createAreaPlane(){
  582. planeMats || (planeMats = {
  583. default: new DepthBasicMaterial( $.extend({},LabelDepthInfo,{
  584. color:color,
  585. side:THREE.DoubleSide,
  586. opacity:0.2,
  587. transparent:true,
  588. useDepth:true
  589. })),
  590. selected: new THREE.MeshBasicMaterial({
  591. color: color ,
  592. side:THREE.DoubleSide,
  593. opacity:0.3,
  594. transparent:true,
  595. })
  596. },Measure.planeMats = planeMats)
  597. return super.createAreaPlane(planeMats.default)
  598. }
  599. raycast (raycaster, intersects) {
  600. for (let i = 0; i < this.points.length; i++) {
  601. let marker = this.markers[i];
  602. marker.raycast(raycaster, intersects);
  603. }
  604. // recalculate distances because they are not necessarely correct
  605. // for scaled objects.
  606. // see https://github.com/mrdoob/three.js/issues/5827
  607. // TODO: remove this once the bug has been fixed
  608. for (let i = 0; i < intersects.length; i++) {
  609. let I = intersects[i];
  610. I.distance = raycaster.ray.origin.distanceTo(I.point);
  611. }
  612. intersects.sort(function (a, b) { return a.distance - b.distance; });
  613. };
  614. transformData(prop){
  615. if(prop.measureType == 'Point'){
  616. prop.showCoordinates = true,
  617. prop.closed = true,
  618. prop.maxMarkers = 1,
  619. prop.minMarkers = 1
  620. }else if(prop.measureType == 'Distance'){
  621. prop.showDistances = true,
  622. prop.showEdges = true,
  623. prop.maxMarkers = 2,
  624. prop.minMarkers = 2
  625. }else if(prop.measureType == 'MulDistance'){//new
  626. prop.showDistances = true,
  627. prop.showEdges = true,
  628. prop.minMarkers = 2
  629. }else if(prop.measureType == 'Ver MulDistance'){
  630. prop.showDistances = true,
  631. prop.atPlane = true,
  632. prop.showEdges = true,
  633. prop.minMarkers = 2
  634. prop.faceDirection = "vertical"
  635. prop.unableDragAtMap = true
  636. }else if(prop.measureType == 'Hor MulDistance'){
  637. prop.showDistances = true,
  638. prop.atPlane = true,
  639. prop.showEdges = true,
  640. prop.minMarkers = 2
  641. prop.faceDirection = "horizontal"
  642. }else if(prop.measureType == 'Ver Distance'){
  643. prop.showDistances = true,
  644. prop.showEdges = true,
  645. prop.maxMarkers = 2,
  646. prop.minMarkers = 2,
  647. prop.faceDirection = "vertical"
  648. prop.unableDragAtMap = true
  649. }else if(prop.measureType == 'Hor Distance'){
  650. prop.showDistances = true,
  651. prop.showEdges = true,
  652. prop.maxMarkers = 2,
  653. prop.minMarkers = 2,
  654. prop.faceDirection = "horizontal"
  655. }else if(prop.measureType == 'Area'){
  656. prop.showDistances = true,
  657. prop.atPlane = true,
  658. prop.showEdges = true,
  659. prop.closed = true,
  660. prop.minMarkers = 3
  661. }else if(prop.measureType == 'Hor Area'){
  662. prop.showDistances = true,
  663. prop.atPlane = true,
  664. prop.showEdges = true,
  665. prop.closed = true,
  666. prop.minMarkers = 3
  667. prop.faceDirection = "horizontal"
  668. }else if(prop.measureType == 'Ver Area'){
  669. prop.showDistances = true,
  670. prop.atPlane = true,
  671. prop.showEdges = true,
  672. prop.closed = true,
  673. prop.minMarkers = 3
  674. prop.faceDirection = "vertical"
  675. prop.unableDragAtMap = true
  676. }else if(prop.measureType == 'Rect Area'){
  677. prop.showDistances = true,
  678. prop.atPlane = true,
  679. prop.showEdges = true,
  680. prop.closed = true,
  681. prop.minMarkers = 4
  682. prop.maxMarkers = 4
  683. }else if(prop.measureType == 'Hor Rect Area'){
  684. prop.showDistances = true,
  685. prop.atPlane = true,
  686. prop.showEdges = true,
  687. prop.closed = true,
  688. prop.minMarkers = 4
  689. prop.maxMarkers = 4
  690. prop.isRect = true
  691. prop.faceDirection = "horizontal"
  692. }else if(prop.measureType == 'Ver Rect Area'){
  693. prop.showDistances = true,
  694. prop.atPlane = true,
  695. prop.showEdges = true,
  696. prop.closed = true,
  697. prop.minMarkers = 4
  698. prop.maxMarkers = 4
  699. prop.isRect = true
  700. prop.faceDirection = "vertical"
  701. prop.unableDragAtMap = true
  702. }
  703. if(prop.atPlane && prop.closed){ //atPlane在同一平面上
  704. prop.showArea = true
  705. }
  706. super.transformData(prop)
  707. }
  708. setUnitSystem(unitSystem){
  709. //console.log(this.name +':' +this.unitSystem)
  710. if(unitSystem != this.unitSystem){
  711. if(unitSystem == "metric"){
  712. }else if(unitSystem == 'imperial'){
  713. }
  714. this.unitSystem = unitSystem
  715. this.update()
  716. }
  717. }
  718. reDraw(restMarkerCount=0){//重新开始画
  719. super.reDraw(restMarkerCount)
  720. if(this.measureType == 'Distance'){
  721. this.shouldShowHorVerGuide = false
  722. this.setEdgesDisplay(false)
  723. }
  724. if(this.showArea){
  725. this.area = {value:0};
  726. this.areaLabel && this.areaLabel.setVisible(false)
  727. }
  728. viewer.inputHandler.dispatchEvent( {type:'isMeasuring', v:true, cause:'reDraw'} )
  729. }
  730. /* get showCoordinates () {
  731. return this._showCoordinates;
  732. }
  733. set showCoordinates (value) {
  734. this._showCoordinates = value;
  735. this.update();
  736. }
  737. get showAngles () {
  738. return this._showAngles;
  739. }
  740. set showAngles (value) {
  741. this._showAngles = value;
  742. this.update();
  743. }
  744. get showCircle () {
  745. return this._showCircle;
  746. }
  747. set showCircle (value) {
  748. this._showCircle = value;
  749. this.update();
  750. }
  751. get showAzimuth(){
  752. return this._showAzimuth;
  753. }
  754. set showAzimuth(value){
  755. this._showAzimuth = value;
  756. this.update();
  757. }
  758. get showEdges () {
  759. return this._showEdges;
  760. }
  761. set showEdges (value) {
  762. this._showEdges = value;
  763. this.update();
  764. }
  765. get showHeight () {
  766. return this._showHeight;
  767. }
  768. set showHeight (value) {
  769. this._showHeight = value;
  770. this.update();
  771. }
  772. get showArea () {
  773. return this._showArea;
  774. }
  775. set showArea (value) {
  776. this._showArea = value;
  777. this.update();
  778. }
  779. get closed () {
  780. return this._closed;
  781. }
  782. set closed (value) {
  783. this._closed = value;
  784. this.update();
  785. }
  786. get showDistances () {
  787. return this._showDistances;
  788. }
  789. set showDistances (value) {
  790. this._showDistances = value;
  791. this.update();
  792. } */
  793. }
  794. function setLabelHightState(label, state){
  795. if(state){
  796. label.backgroundColor = {r: highlightColor.r*255, g: highlightColor.g*255, b: highlightColor.b*255, a:config.measure.highlight.opacity},
  797. label.backgroundColor.a = config.measure.highlight.opacity
  798. label.sprite.material.useDepth = false;
  799. }else{
  800. label.backgroundColor = mainLabelProp.backgroundColor
  801. label.backgroundColor.a = config.measure.default.opacity
  802. label.sprite.material.useDepth = true
  803. }
  804. label.updateTexture()
  805. //label.sprite.material.needsUpdate = true
  806. }
  807. function createCircleRadiusLabel(){
  808. const circleRadiusLabel = new TextSprite("");
  809. circleRadiusLabel.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  810. circleRadiusLabel.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  811. circleRadiusLabel.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  812. circleRadiusLabel.fontsize = 16;
  813. circleRadiusLabel.material.depthTest = false;
  814. circleRadiusLabel.material.opacity = 1;
  815. circleRadiusLabel.visible = false;
  816. return circleRadiusLabel;
  817. }
  818. function createCircleRadiusLine(){
  819. /* const lineGeometry = new LineGeometry();
  820. lineGeometry.setPositions([
  821. 0, 0, 0,
  822. 0, 0, 0,
  823. ]);
  824. const lineMaterial = new LineMaterial({
  825. color: 0xff0000,
  826. lineWidth: 2,
  827. resolution: new THREE.Vector2(1000, 1000),
  828. gapSize: 1,
  829. dashed: true,
  830. });
  831. lineMaterial.depthTest = false;
  832. const circleRadiusLine = new Line2(lineGeometry, lineMaterial);*/
  833. var circleRadiusLine = LineDraw.createFatLine([ ],{
  834. color:0xff0000,
  835. dashSize: 0.5,
  836. gapSize: 0.2,
  837. lineWidth: config.measure.lineWidth
  838. })
  839. circleRadiusLine.visible = false;
  840. return circleRadiusLine;
  841. }
  842. function createCircleLine(){
  843. const coordinates = [];
  844. let n = 128;
  845. for(let i = 0; i <= n; i++){
  846. let u0 = 2 * Math.PI * (i / n);
  847. let u1 = 2 * Math.PI * (i + 1) / n;
  848. let p0 = new THREE.Vector3(
  849. Math.cos(u0),
  850. Math.sin(u0),
  851. 0
  852. );
  853. let p1 = new THREE.Vector3(
  854. Math.cos(u1),
  855. Math.sin(u1),
  856. 0
  857. );
  858. coordinates.push(
  859. p0,
  860. p1
  861. );
  862. }
  863. /* const geometry = new LineGeometry();
  864. geometry.setPositions(coordinates);
  865. const material = new LineMaterial({
  866. color: 0xff0000,
  867. dashSize: 5,
  868. gapSize: 2,
  869. lineWidth: 2,
  870. resolution: new THREE.Vector2(1000, 1000),
  871. });
  872. material.depthTest = false;
  873. const circleLine = new Line2(geometry, material);
  874. circleLine.visible = false;
  875. circleLine.computeLineDistances();*/
  876. var circleLine = LineDraw.createFatLine(coordinates,{
  877. color: 0xff0000,
  878. dashSize: 0.5,
  879. gapSize: 0.2,
  880. lineWidth: config.measure.lineWidth
  881. })
  882. return circleLine;
  883. }
  884. /* function createCircleCenter(){
  885. const sg = new THREE.markerGeometry(1, 32, 32);
  886. const sm = new THREE.MeshNormalMaterial();
  887. const circleCenter = new THREE.Mesh(sg, sm);
  888. circleCenter.visible = false;
  889. return circleCenter;
  890. } */
  891. function createLine(){
  892. const line = LineDraw.createFatLine([ ],{
  893. color: 0xff0000,
  894. dashSize: 0.5,
  895. gapSize: 0.2,
  896. lineWidth: config.measure.lineWidth
  897. })
  898. return line;
  899. }
  900. function createCircle(){
  901. const coordinates = [];
  902. let n = 128;
  903. for(let i = 0; i <= n; i++){
  904. let u0 = 2 * Math.PI * (i / n);
  905. let u1 = 2 * Math.PI * (i + 1) / n;
  906. let p0 = new THREE.Vector3(
  907. Math.cos(u0),
  908. Math.sin(u0),
  909. 0
  910. );
  911. let p1 = new THREE.Vector3(
  912. Math.cos(u1),
  913. Math.sin(u1),
  914. 0
  915. );
  916. coordinates.push(
  917. p0,
  918. p1
  919. );
  920. }
  921. var line = LineDraw.createFatLine(coordinates,{
  922. color: 0xff0000,
  923. dashSize: 0.5,
  924. gapSize: 0.2,
  925. lineWidth: config.measure.lineWidth
  926. })
  927. return line;
  928. }
  929. /* function createAzimuth(){
  930. const azimuth = {
  931. label: null,
  932. center: null,
  933. target: null,
  934. north: null,
  935. centerToNorth: null,
  936. centerToTarget: null,
  937. centerToTargetground: null,
  938. targetgroundToTarget: null,
  939. circle: null,
  940. node: null,
  941. };
  942. const sg = new THREE.markerGeometry(1, 32, 32);
  943. const sm = new THREE.MeshNormalMaterial();
  944. {
  945. const label = new TextSprite("");
  946. label.setTextColor({r: 140, g: 250, b: 140, a: 1.0});
  947. label.setBorderColor({r: 0, g: 0, b: 0, a: 1.0});
  948. label.setBackgroundColor({r: 0, g: 0, b: 0, a: 1.0});
  949. label.fontsize = 16;
  950. label.material.depthTest = false;
  951. label.material.opacity = 1;
  952. azimuth.label = label;
  953. }
  954. azimuth.center = new THREE.Mesh(sg, sm);
  955. azimuth.target = new THREE.Mesh(sg, sm);
  956. azimuth.north = new THREE.Mesh(sg, sm);
  957. azimuth.centerToNorth = createLine();
  958. azimuth.centerToTarget = createLine();
  959. azimuth.centerToTargetground = createLine();
  960. azimuth.targetgroundToTarget = createLine();
  961. azimuth.circle = createCircle();
  962. azimuth.node = new THREE.Object3D();
  963. azimuth.node.add(
  964. azimuth.centerToNorth,
  965. azimuth.centerToTarget,
  966. azimuth.centerToTargetground,
  967. azimuth.targetgroundToTarget,
  968. azimuth.circle,
  969. azimuth.label,
  970. azimuth.center,
  971. azimuth.target,
  972. azimuth.north,
  973. );
  974. return azimuth;
  975. } */
  976. /*
  977. */