ctrlPolygon.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894
  1. import * as THREE from "../../../../libs/three.js/build/three.module.js";
  2. import {LineDraw, MeshDraw} from "../../utils/DrawUtil.js";
  3. import math from "../../utils/math.js";
  4. //THREE.Vector2.name1 = 'ctrlPolygon'
  5. const verticalLine = new THREE.Line3()
  6. //控制点和边的合集。具有可以拖拽修改的功能,拖拽时能防止线相交。
  7. export class ctrlPolygon extends THREE.Object3D {
  8. constructor (type, prop) {
  9. super()
  10. this.type = type
  11. this.maxMarkers = Number.MAX_SAFE_INTEGER;
  12. this.transformData(prop);
  13. for(let i in prop){
  14. this[i] = prop[i]
  15. }
  16. if((this.atPlane || this.showArea ) && this.closed && this.dimension == '2d'){
  17. this.areaPlane = this.createAreaPlane();
  18. this.add(this.areaPlane)
  19. }
  20. //数据--刚开始一定是空的
  21. this.points = [];
  22. //mesh 不一定有
  23. this.markers = [];
  24. this.edges = [];
  25. this.center
  26. }
  27. initData(prop){
  28. //开始加数据
  29. prop.dataset_points && (this.dataset_points = prop.dataset_points)
  30. prop.datasetId && (this.datasetId = prop.datasetId)
  31. prop.points_datasets && (this.points_datasets = prop.points_datasets)
  32. if(Potree.settings.editType == 'merge' || this.measureType == 'MulDistance Ring'){ //融合页面没有地图,measure的不需要指定datasetId,每个点都有各自的datasetId,跟着各自的模型走
  33. if(this.dataset_points){
  34. this.dataset_points = this.dataset_points.map(e=>{
  35. return e && new THREE.Vector3().copy(e)
  36. })
  37. prop.points = this.dataset_points.map((p,i)=>{
  38. return Potree.Utils.datasetPosTransform({fromDataset:true, datasetId:this.points_datasets[i], position: p})
  39. })
  40. if(prop.points.some(e=>e == void 0)){
  41. return false
  42. }
  43. }else{
  44. this.dataset_points = []
  45. }
  46. }
  47. if(prop.points){
  48. for(const p of prop.points){
  49. const pos = new THREE.Vector3().copy(p)
  50. this.addMarker({point:pos});
  51. }
  52. if(Potree.settings.editType != 'merge' && this.measureType != 'MulDistance Ring'){
  53. if(this.datasetId != void 0){//初始化位置
  54. if(this.dataset_points){
  55. this.dataset_points = this.dataset_points.map(e=>{
  56. return e && new THREE.Vector3().copy(e)
  57. })
  58. this.transformByPointcloud() //根据dataset_points和this.datasetId生成points
  59. }
  60. }else{
  61. if(prop.dataset_points && prop.dataset_points.some(e=>e != void 0)){
  62. console.error('存在测量线的datasetId为空而dataset_points有值,请检查并删除:'+this.sid)//存在过的bug,原因未知,可能是后台处理dataset时替换的错误:http://192.168.0.21/index.php?m=bug&f=view&bugID=23601
  63. console.log(this)
  64. }
  65. }
  66. }
  67. this.facePlane = this.getFacePlane()
  68. this.getPoint2dInfo(this.points)
  69. this.update({ifUpdateMarkers:true})
  70. //this.dragChange(new THREE.Vector3().copy(prop.points[prop.points.length-1]), prop.points.length-1);
  71. this.setSelected(false )
  72. this.markers.forEach(marker=>{marker.dispatchEvent('addHoverEvent') })
  73. return true
  74. }
  75. }
  76. addMarker(o={}){
  77. var index = o.index == void 0 ? this.points.length : o.index //要当第几个
  78. this.points = [...this.points.slice(0,index), o.point.clone(), ...this.points.slice(index,this.points.length)]
  79. //this.points.push(o.point);
  80. if('dataset_point' in o){//需要增加,可能是null
  81. this.dataset_points = this.dataset_points ? [...this.dataset_points.slice(0,index), o.dataset_point && o.dataset_point.clone(), ...this.dataset_points.slice(index,this.dataset_points.length)] : null //如果原本是null,新加的应该也是
  82. }
  83. if('points_dataset' in o){
  84. this.points_datasets = [...this.points_datasets.slice(0,index), o.points_dataset, ...this.points_datasets.slice(index,this.points_datasets.length)]
  85. }
  86. if(o.marker){
  87. this.add(o.marker)
  88. this.markers = [...this.markers.slice(0,index), o.marker, ...this.markers.slice(index,this.markers.length)]
  89. this.updateMarker(o.marker, o.point)
  90. o.marker.addEventListener('drag', this.dragMarker.bind(this),{importance:2});
  91. o.marker.addEventListener('drop', this.dropMarker.bind(this),{importance:2});
  92. o.marker.createTime = Date.now()
  93. let addHoverEvent = (e)=>{
  94. let mouseover = (e) => {
  95. this.setMarkerSelected(e.object, 'hover', 'single');
  96. viewer.dispatchEvent({
  97. type : "CursorChange", action : "add", name:"markerMove"
  98. })
  99. };
  100. let mouseleave = (e) => {
  101. this.setMarkerSelected(e.object, 'unhover', 'single');
  102. viewer.dispatchEvent({
  103. type : "CursorChange", action : "remove", name:"markerMove"
  104. })
  105. }
  106. o.marker.addEventListener('mouseover', mouseover);
  107. o.marker.addEventListener('mouseleave', mouseleave);
  108. o.marker.addEventListener('startDragging', (e)=>{//for mobile
  109. this.setMarkerSelected(o.marker, 'hover', 'single');
  110. this.dispatchEvent('startDragging')
  111. });
  112. o.marker.addEventListener('drop', (e)=>{//for mobile
  113. this.setMarkerSelected(o.marker, 'unhover', 'single');
  114. });
  115. o.marker.removeEventListener('addHoverEvent',addHoverEvent)
  116. }
  117. o.marker.addEventListener('addHoverEvent',addHoverEvent)//当非isNew时才添加事件
  118. if(!this.isNew){
  119. o.marker.dispatchEvent('addHoverEvent')
  120. }
  121. }
  122. if(o.edge){
  123. this.add(o.edge)
  124. this.edges = [...this.edges.slice(0,index), o.edge, ...this.edges.slice(index,this.edges.length)]
  125. }
  126. }
  127. dragMarker(e){
  128. var I, atMap
  129. if(e.hoverViewport != e.drag.dragViewport){//不能使用e.dragViewport,要使用drag中的,因为drag中存储的要一直继承下来,不因mouseup了而改变。
  130. viewer.dispatchEvent({
  131. type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
  132. })
  133. return
  134. }
  135. if(e.drag.pointerDelta.length() == 0 && !this.isNew){ //部分设备(华为matePad11)在touchstart后立即执行了touchmove,导致marker立即移动,需要屏蔽..(刚创建时也会是0)
  136. return
  137. }
  138. viewer.dispatchEvent({
  139. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  140. })
  141. atMap = e.drag.dragViewport.name == 'mapViewport'
  142. if(atMap && this.unableDragAtMap){
  143. e.drag.object = null //取消拖拽
  144. return
  145. }
  146. e.drag.object.isDragging = true
  147. I = e.intersect && (e.intersect.adsorption ? e.intersect.location : (e.intersect.orthoIntersect || e.intersect.location))
  148. if(viewer.inputHandler.pressedKeys[18] || Potree.settings.dragPolyBeyondPoint&&!I ){//alt dragPolyBeyondPoint可以平移拖拽到无点的地方---测试用
  149. let i = this.markers.indexOf(e.drag.object);
  150. I = this.points[i].clone()
  151. const projected = I.clone().project(e.drag.dragViewport.camera);
  152. projected.x = e.pointer.x
  153. projected.y = e.pointer.y
  154. const unprojected = projected.clone().unproject(e.drag.dragViewport.camera);
  155. I.copy(unprojected);
  156. }
  157. if (I) {
  158. let i = this.markers.indexOf(e.drag.object);
  159. if (i !== -1) {
  160. this.dragChange(I.clone(), i, atMap)
  161. if(this.points_datasets){
  162. if(e.intersect.pointcloud) this.points_datasets[i] = e.intersect.pointcloud.dataset_id
  163. else if(e.intersect.object) this.points_datasets[i] = e.intersect.object.dataset_id
  164. else{
  165. if(this.measureType == 'MulDistance Ring'){//因为它的每个point跟着各自的dataset走,而不是整体的dataset
  166. let pointcloud = viewer.findClosestDatasetOnMap(I) || viewer.scene.pointclouds[0]
  167. this.points_datasets[i] = pointcloud.dataset_id
  168. }else this.points_datasets[i] = null
  169. }
  170. }
  171. }
  172. this.editStateChange(true)
  173. return true
  174. }
  175. };
  176. dragChange(intersectPos, i, atMap){
  177. let len = this.markers.length
  178. let oldPoint = this.points[i];
  179. if(atMap){
  180. intersectPos.setZ(oldPoint.z) //在地图上拖拽,不改变其高度。
  181. }
  182. let location = intersectPos.clone()
  183. if(this.faceDirection && this.maxMarkers == 2 && len == 2){//add 固定方向的点不直接拖拽
  184. var p1 = this.markers[0].position
  185. if(this.faceDirection == 'horizontal'){
  186. var projectPos = location.clone().setZ(p1.z)
  187. }else{
  188. var projectPos = p1.clone().setZ(location.z)
  189. }
  190. //var p2 = p1.clone().add(this.direction)
  191. //var projectPos = math.getFootPoint(location, p1, p2)
  192. LineDraw.updateLine(this.guideLine, [location, projectPos])
  193. location = projectPos
  194. this.guideLine.visible = true
  195. }else if( len > 1 ){
  196. var points = this.points.map(e=>e.clone())
  197. points[i].copy(location) //算normal需要提前确认point
  198. //若为定义了面朝向的矩形
  199. if(this.faceDirection == 'horizontal'){
  200. if(len == 2){
  201. location.setZ(points[0].z)
  202. }
  203. if(!this.facePlane){//一个点就能确定面
  204. this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( new THREE.Vector3(0,0,1), this.points[0] )
  205. }
  206. }else if(this.faceDirection == 'vertical'){//当有两个点时, 有两个方向的可能
  207. if(len == 2){
  208. if(this.isRect){
  209. let vec = points[0].clone().sub(location)
  210. if(Math.sqrt(vec.x*vec.x+vec.y*vec.y) > Math.abs(vec.z) ){//水平(高度差小于水平距离时)
  211. location.setZ(points[0].z)
  212. //this.cannotConfirmNormal = false;//能确定面为水平方向
  213. }else{//垂直 (当两点一样时也属于这种)
  214. location.setX(points[0].x);
  215. location.setY(points[0].y);
  216. //this.cannotConfirmNormal = true; //不能确定面,因第三点可绕着纵轴线自由移动
  217. }
  218. }
  219. }else{
  220. {//判断cannotConfirmNormal. 如果前几段都在竖直线上,就不能固定出面方向。
  221. this.cannotConfirmNormal = true
  222. let max = this.isRect ? 1 : len-2
  223. for(let i=0;i<max;i++){
  224. let p1 = points[i].clone()
  225. let p2 = points[i+1].clone()
  226. let vec = p1.sub(p2);
  227. if(vec.x != 0 || vec.y != 0){
  228. this.cannotConfirmNormal = false
  229. break;
  230. }
  231. }
  232. }
  233. if(!this.facePlane || this.cannotConfirmNormal){//三个点且为水平方向时,计算面
  234. var points_ = points.map(e=>new THREE.Vector2(e.x,e.y))
  235. var points2 = getDifferentPoint(points_, 2);
  236. if(points2){
  237. let normal = math.getNormal2d({p1:points2[0], p2:points2[1]})
  238. normal = new THREE.Vector3(normal.x, normal.y, 0)
  239. this.facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint( normal, this.points[0] )
  240. }
  241. }
  242. }
  243. }
  244. if(len > 2){
  245. if(!this.faceDirection && this.showArea){
  246. if(len == 3 || this.isRect) this.cannotConfirmNormal = true //当第三个点固定后(有四个点时)才能固定面
  247. if(!this.facePlane || this.cannotConfirmNormal){
  248. var points3 = getDifferentPoint(points, 3);//只有找到三个不同的点算拥有面和area
  249. if(points3){
  250. this.facePlane = new THREE.Plane().setFromCoplanarPoints(...points3 )
  251. }
  252. }
  253. }
  254. if(this.atPlane && this.facePlane && !this.cannotConfirmNormal ){//之后加的点一定要在面上
  255. if(atMap){
  256. //地图上用垂直线,得到和面的交点。
  257. verticalLine.set(location.clone().setZ(100000), location.clone().setZ(-100000))//确保长度范围覆盖所有测量面
  258. location = this.facePlane.intersectLine(verticalLine, new THREE.Vector3() )
  259. if(!location) return;
  260. }else{
  261. location = this.facePlane.projectPoint(intersectPos, new THREE.Vector3() )
  262. }
  263. }
  264. points[i].copy(location)//再copy确认一次
  265. if(len == 3 && this.faceDirection == 'horizontal' && this.closed){ //normal方向还不确定 会影响label在里侧还是外侧
  266. let facePlane = new THREE.Plane().setFromCoplanarPoints(...points)
  267. if(facePlane.normal.z && facePlane.normal.z * this.facePlane.normal.z < 0){
  268. this.facePlane.normal.z *= -1, this.facePlane.constant *= -1
  269. //console.log(this.facePlane.normal, this.facePlane.constant)
  270. }
  271. }
  272. if(this.isRect){ //是矩形 (即使没有faceDirection也能执行)
  273. //根据前两个点计算当前和下一个点
  274. var p1 = points[(i-2+len)%len]
  275. var p2 = points[(i-1+len)%len]
  276. if(p1.equals(p2)){//意外情况:重复点两次 ( bug点,改了好多遍)
  277. if(this.faceDirection == 'vertical'){
  278. p2.add(new THREE.Vector3(0,0,0.0001))
  279. }else{
  280. p2.add(new THREE.Vector3(0,0.0001,0))
  281. }
  282. }
  283. //p3 : location
  284. var foot = math.getFootPoint(location, p1, p2)//p2 修改p2到垂足的位置
  285. var vec = foot.clone().sub(location)
  286. var p4 = p1.clone().sub(vec)
  287. points[(i-1+len)%len].copy(foot)
  288. points[(i+1)%len].copy(p4)
  289. this.setPosition((i-1+len)%len, foot);//p2
  290. this.setPosition((i+1)%len, p4);
  291. }
  292. this.getPoint2dInfo(points)
  293. var isIntersectSelf = this.atPlane && this.closed && !this.isRect && this.point2dInfo && this.intersectSelf(this.point2dInfo.points2d)//检测相交
  294. this.isIntersectSelf = isIntersectSelf
  295. if(isIntersectSelf){//not-allowed
  296. if(!this.isNew && isIntersectSelf == 'lastLine') this.isIntersectSelf = 'all' //已经画好了就不用特别对待最后一条线
  297. if(this.isIntersectSelf == 'lastLine'){
  298. Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', false)
  299. Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', false)
  300. }else{
  301. viewer.dispatchEvent({
  302. type : "CursorChange", action : "add", name:"polygon_isIntersectSelf"
  303. })
  304. return
  305. }
  306. }
  307. if(!this.isIntersectSelf){
  308. this.areaPlane && Potree.Utils.updateVisible(this.areaPlane, 'intersectLastLine', true)
  309. this.areaLabel && Potree.Utils.updateVisible(this.areaLabel, 'intersectLastLine', true)
  310. }
  311. if(!this.isIntersectSelf || this.isIntersectSelf == 'lastLine' ){
  312. viewer.dispatchEvent({
  313. type : "CursorChange", action : "remove", name:"polygon_isIntersectSelf"
  314. })
  315. }
  316. }
  317. var showGuideLine = len>1 && (this.faceDirection || len > 3)
  318. if(showGuideLine && this.guideLine){
  319. LineDraw.updateLine(this.guideLine, [intersectPos, location])
  320. this.guideLine.visible = true
  321. }
  322. //console.log(this.points.map(e=>e.toArray()))
  323. }
  324. if(this.restrictArea){
  325. let holes = this.restrictArea.holes.concat(this.restrictArea.parentHoles)
  326. let holesPoints = holes.filter(e=>e!=this && e.points.length>2).map(e=>e.points)
  327. if(!math.isPointInArea(this.restrictArea.points, holesPoints, location)){
  328. viewer.dispatchEvent({
  329. type : "CursorChange", action : "add", name:"polygon_AtWrongPlace"
  330. })
  331. this.isAtWrongPlace = true
  332. return
  333. }
  334. //就不处理相交线了。 有个缺点:floor上的hole可以限制room,但hole不受room限制,会导致room的marker被框在hole里而动不了。只能去调整hole了
  335. }
  336. viewer.dispatchEvent({
  337. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  338. })
  339. this.isAtWrongPlace = false
  340. this.setPosition(i, location);
  341. this.update({index: this.isRect ? null : i})
  342. this.dispatchEvent({type:'dragChange', index:i})
  343. }
  344. dropMarker(e){
  345. //console.log('dropMarker')
  346. if (this.isNew && e.pressDistance>Potree.config.clickMaxDragDis){//拖拽的话返回
  347. return this.continueDrag(null,e)
  348. }
  349. if(e.hoverViewport != e.drag.dragViewport){//copy from dragMarker, for sitemodel, only mapViewport can be dropped
  350. return this.continueDrag(null,e)
  351. }
  352. if(e.isTouch){
  353. if(e.hoverViewport != viewer.mainViewport && this.unableDragAtMap){
  354. viewer.dispatchEvent({type:'reticule_forbit', v:true})
  355. //console.log('reticule_forbit',true)
  356. return this.continueDrag(null,e)
  357. }else{
  358. viewer.dispatchEvent({type:'reticule_forbit', v:false})
  359. //console.log('reticule_forbit',false)
  360. }
  361. this.isNew && this.dragMarker(e) //isNew触屏点击时必须先更新下点,因为指尖不在屏幕上时没更新。但对已经创建的marker点击时不应该更新
  362. }
  363. if (e.button != THREE.MOUSE.RIGHT && (//右键click的话继续执行,因为会停止
  364. this.isIntersectSelf == 'all' && this.isNew //有线相交了
  365. || this.isAtWrongPlace && this.isNew
  366. || !e.isAtDomElement && this.isNew//如果是刚添加时在其他dom点击, 不要响应
  367. || e.hoverViewport != viewer.mainViewport && this.unableDragAtMap //垂直的测量线不允许在地图上放点
  368. || this.isNew && !getDifferentPoint(this.points, this.points.length ) //不允许和之前的点相同, 但这句在点云稀疏时会导致难结束
  369. )
  370. ){
  371. return this.continueDrag(null,e)
  372. }
  373. //console.log('drop marker' )
  374. let i = this.markers.indexOf(e.drag.object);
  375. if (i !== -1) {
  376. this.dispatchEvent({
  377. 'type': 'marker_dropped',
  378. 'index': i
  379. });
  380. if(this.markers.length>2 && this.facePlane)this.cannotConfirmNormal = false
  381. this.guideLine &&(this.guideLine.visible = false)
  382. }
  383. this.setMarkerSelected(e.drag.object, 'unhover', 'single')
  384. this.editStateChange(false)
  385. e.drag.endDragFun && e.drag.endDragFun(e)// addmarker
  386. //if(this.changeCallBack)this.changeCallBack()
  387. return true
  388. };
  389. getFacePlane(){//最普通一种get方法,根据顶点。且假设所有点已经共面,且不重合
  390. if(/* !this.atPlane || */this.points.length<3) return
  391. /* this.facePlane = new THREE.Plane().setFromCoplanarPoints(...this.points.slice(0,3) ) */
  392. let facePlane = this.facePlane
  393. if(!this.atPlane || !facePlane){//多折线 没有实时更新facePlane所以重新算
  394. let normal = new THREE.Vector3, len = this.points.length - 2
  395. for(let i=0;i<len;i++){ //获取normal的顺序方法必须和setFromCoplanarPoints一致
  396. let vec0 = new THREE.Vector3().subVectors(this.points[i+2], this.points[i+1], )
  397. let vec1 = new THREE.Vector3().subVectors(this.points[i], this.points[i+1])
  398. let nor = vec0.cross(vec1).normalize();
  399. normal.add(nor)
  400. }
  401. normal.normalize();
  402. facePlane = new THREE.Plane().setFromNormalAndCoplanarPoint(normal, this.points[0])
  403. }
  404. return facePlane
  405. }
  406. getPoint2dInfo(points){ //在更新areaplane之前必须更新过point2dInfo
  407. if(this.facePlane && this.atPlane){
  408. var originPoint0 = points[0].clone()
  409. var qua = math.getQuaBetween2Vector(this.facePlane.normal, new THREE.Vector3(0,0,1), new THREE.Vector3(0,0,1));
  410. let points2d = points.map(e=>e.clone().applyQuaternion(qua))
  411. this.point2dInfo = {
  412. originPoint0 ,
  413. points2d,
  414. quaInverse : qua.clone().invert()
  415. }
  416. }
  417. }
  418. setPosition (index, position) {//拖拽后设置位置
  419. let point = this.points[index];
  420. point.copy(position);
  421. /* if(this.datasetId){
  422. this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true, datasetId:this.datasetId, position:point.clone()})
  423. } */
  424. /* if(Potree.settings.editType == 'merge'){
  425. this.dataset_points[index] = Potree.Utils.datasetPosTransform({toDataset:true,this.points_datasets[i], position:point.clone()})
  426. } */
  427. let marker = this.markers[index];
  428. this.updateMarker(marker, point)
  429. }
  430. updateMarker(marker, pos){
  431. marker.position.copy(pos);
  432. marker.waitUpdate();
  433. }
  434. intersectSelf(points2d){//add
  435. var len = points2d.length
  436. for(var i=0;i<len;i++){
  437. for(var j=i+2;j<len;j++){
  438. if(Math.abs(j-len-i)<2)continue;//不和邻边比
  439. var p1 = points2d[i]
  440. var p2 = points2d[i+1]
  441. var p3 = points2d[j]
  442. var p4 = points2d[(j+1)%len]
  443. if(p1.equals(p2) || p3.equals(p4) || p1.equals(p3) || p2.equals(p3) || p1.equals(p4) || p2.equals(p4))continue
  444. var line1 = [p1,p2]
  445. var line2 = [p3,p4]
  446. var intersect = math.isLineIntersect(line1, line2, false, 0.001)
  447. if(intersect){
  448. if(i==len-1 || j==len-1){//最后一条线。如果还没绘制完,最后的线还没定下,可被允许继续绘制,但无法显示面积。
  449. return 'lastLine'
  450. }else{
  451. return 'all'
  452. }
  453. break
  454. }
  455. }
  456. }
  457. }
  458. removeMarker (index) {
  459. this.points.splice(index, 1);
  460. const marker = this.markers[index]
  461. //this.remove(marker);
  462. this.markers.splice(index, 1);
  463. marker.dispose()
  464. let edgeIndex = index //(index === 0) ? 0 : (index - 1);
  465. const edge = this.edges[edgeIndex]
  466. if(edge){
  467. this.remove(edge);
  468. this.edges.splice(edgeIndex, 1);
  469. edge.geometry.dispose()
  470. }
  471. this.point2dInfo && this.point2dInfo.points2d.splice(index, 1); //add
  472. this.dispatchEvent({type:'removeMarker',index,marker})
  473. }
  474. createAreaPlane(mat){
  475. var geometry = new THREE.Geometry();
  476. var mesh = new THREE.Mesh(geometry, mat)
  477. return mesh
  478. }
  479. updateAreaPlane(){
  480. this.areaPlane.geometry.dispose()
  481. if(this.points.length>2){
  482. if(this.point2dInfo){
  483. this.areaPlane.geometry = MeshDraw.getShapeGeo(this.point2dInfo.points2d)
  484. let center = math.getCenterOfGravityPoint(this.point2dInfo.points2d) //重心
  485. let firstPos = this.point2dInfo.points2d[0].clone()
  486. firstPos.z = 0 //因为shape只读取了xy,所以位移下, 再算出最终位置,得到差距
  487. firstPos.applyQuaternion(this.point2dInfo.quaInverse)
  488. let vec = this.point2dInfo.originPoint0.clone().sub(firstPos)
  489. center = new THREE.Vector3(center.x, center.y, 0)
  490. center.applyQuaternion(this.point2dInfo.quaInverse)
  491. this.areaPlane.quaternion.copy(this.point2dInfo.quaInverse)
  492. this.areaPlane.position.copy(vec)
  493. center.add(vec)
  494. this.center = center
  495. }else{//prism
  496. let z = this.horizonZ || 0
  497. let points2d = this.points.map(e=>e.clone().setZ(z))
  498. this.areaPlane.geometry = MeshDraw.getShapeGeo(points2d) //z=0
  499. let center = math.getCenterOfGravityPoint(points2d) //重心
  500. this.areaPlaneCenter = new THREE.Vector3(center.x, center.y, z)
  501. this.areaPlane.position.z = z
  502. }
  503. }else{
  504. this.areaPlane.geometry = new THREE.Geometry()
  505. }
  506. }
  507. getIndex(index, add){
  508. let lastIndex = this.points.length - 1
  509. if(add == -1) return (index === 0) ? lastIndex : index - 1;
  510. else if(add == 1) return (index + 1 > lastIndex) ? 0 : index + 1;
  511. }
  512. update(options={}){
  513. if(this.points.length === 0){
  514. return;
  515. }
  516. //performance.mark('measureUpdate-start')
  517. let lastIndex = this.points.length - 1
  518. if(options.index != void 0){//更新第几个点
  519. this.updateMarker(this.markers[options.index], this.points[options.index])
  520. let previousIndex = this.getIndex(options.index, -1)
  521. let nextIndex = this.getIndex(options.index, +1)
  522. if( this.closed || nextIndex != 0 ) LineDraw.updateLine( this.edges[options.index], [this.points[options.index], this.points[nextIndex]])
  523. if( this.closed || previousIndex != lastIndex ) LineDraw.updateLine( this.edges[previousIndex], [this.points[options.index], this.points[previousIndex]])
  524. }else{
  525. for (let index = 0; index <= lastIndex; index++) {
  526. let nextIndex = this.getIndex(index, +1)
  527. let previousIndex = this.getIndex(index, -1)
  528. let point = this.points[index];
  529. let nextPoint = this.points[nextIndex];
  530. let previousPoint = this.points[previousIndex];
  531. if(options.ifUpdateMarkers){
  532. this.updateMarker(this.markers[index], point)
  533. }
  534. if(!this.closed && nextIndex == 0 )break; //add
  535. {
  536. let edge = this.edges[index];
  537. if(edge){
  538. LineDraw.updateLine(edge, [point, nextPoint])
  539. }
  540. }
  541. }
  542. }
  543. if(this.areaPlane){
  544. this.updateAreaPlane()
  545. }
  546. //this.dispatchEvent({type:'update'})
  547. viewer.dispatchEvent('content_changed')
  548. viewer.mapViewer && viewer.mapViewer.dispatchEvent('content_changed') //暂时先这么都通知
  549. //performance.mark('measureUpdate-end')
  550. //let measure = performance.measure('measure-','measureUpdate-start', 'measureUpdate-end' );
  551. //console.log('update-time', measure.duration)
  552. }
  553. createPrismLines(color){
  554. this.lineMesh = LineDraw.createLine([],{color})
  555. this.lineMesh.name = 'PrismLines'
  556. this.add(this.lineMesh)
  557. }
  558. updatePrismLines(){
  559. if(!this.lineMesh)return
  560. let positions = [];
  561. let length = this.points.length
  562. this.points.forEach((point, index)=>{
  563. //竖线:
  564. positions.push(point.clone().setZ(this.zMin), point.clone().setZ(this.zMax))
  565. //横线
  566. let nextPoint = this.points[(index+1)%length];
  567. if(!nextPoint)return;//when length==1
  568. positions.push(point.clone().setZ(this.zMax), nextPoint.clone().setZ(this.zMax))//上横线
  569. positions.push(point.clone().setZ(this.zMin), nextPoint.clone().setZ(this.zMin))//下横线
  570. })
  571. LineDraw.moveLine(this.lineMesh,positions)
  572. viewer.dispatchEvent('content_changed')
  573. }
  574. dispose(){//add
  575. this.parent.remove(this)
  576. this.markers.forEach(e=>e.dispose())
  577. this.edges.forEach(e=>e.geometry.dispose())
  578. }
  579. reDraw(restMarkerCount=0){//重新开始画
  580. let pointCount = this.points.length - restMarkerCount // restMarkerCount为需要留下的marker数量
  581. while(pointCount > 0){
  582. this.removeMarker(--pointCount)
  583. }
  584. this.point2dInfo = null
  585. this.facePlane = null
  586. }
  587. setMarkerSelected(){}
  588. editStateChange(state){
  589. if(!state){
  590. viewer.dispatchEvent({
  591. type : "CursorChange", action : "remove", name:"polygon_isIntersectSelf"
  592. })
  593. viewer.dispatchEvent({
  594. type : "CursorChange", action : "remove", name:"polygon_AtWrongPlace"
  595. })
  596. viewer.dispatchEvent({type:'reticule_forbit', v:false})
  597. this.markers.forEach(e=>e.isDragging = false )
  598. }
  599. }
  600. transformData(prop){
  601. const pick = (defaul, alternative) => {
  602. if(defaul != null){
  603. return defaul;
  604. }else{
  605. return alternative;
  606. }
  607. };
  608. prop.showDistances = (prop.showDistances === null) ? true : prop.showDistances;
  609. prop.showArea = pick(prop.showArea, false);
  610. prop.showAngles = pick(prop.showAngles, false);
  611. prop.showCoordinates = pick(prop.showCoordinates, false);
  612. prop.showHeight = pick(prop.showHeight, false);
  613. prop.showCircle = pick(prop.showCircle, false);
  614. prop.showAzimuth = pick(prop.showAzimuth, false);
  615. prop.showEdges = pick(prop.showEdges, true);
  616. prop.closed = pick(prop.closed, false);
  617. prop.maxMarkers = pick(prop.maxMarkers, Infinity);
  618. prop.direction = prop.direction//add
  619. prop.type = prop.type
  620. prop.showGuideLine = pick(prop.showGuideLine, false);
  621. prop.isRect = pick(prop.isRect, false);
  622. }
  623. setSelected(){}
  624. continueDrag(marker, e){
  625. let object = marker || e.drag.object
  626. object.isDragging = true
  627. this.editStateChange(true)
  628. var timer = setTimeout(()=>{//等 drag=null之后 //右键拖拽结束后需要重新得到drag
  629. if(this.parent && object.parent && object.isDragging){
  630. //console.log('continueDrag')
  631. viewer.inputHandler.startDragging( object ,
  632. {endDragFun: e.drag.endDragFun, notPressMouse:e.drag.notPressMouse, dragViewport:e.drag.dragViewport}
  633. )
  634. }
  635. },1)
  636. return timer
  637. }
  638. }
  639. function getDifferentPoint(points, count){//for facePlane
  640. var result = [];
  641. for(let i=0;i<points.length;i++){
  642. var p = points[i];
  643. if(result.find(e=>e.equals(p)))continue;
  644. else result.push(p)
  645. if(result.length == count)break
  646. }
  647. if(result.length == count)return result
  648. }