Measure.js 44 KB

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