MoveRoad.js 34 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. import { roadService } from "../Service/RoadService";
  2. import { dataService } from "../Service/DataService";
  3. import Constant from "../Constant";
  4. import { mathUtil } from "../Util/MathUtil";
  5. import { elementService } from "../Service/ElementService";
  6. import { coordinate } from "../Coordinate";
  7. export default class MoveRoad {
  8. constructor() {
  9. this.startMoving = false;
  10. this.moveFlag = false;
  11. //拖拽墙角的时候,墙角的父亲与其他墙角相交
  12. this.adsorbPointRoads = {};
  13. //拖拽墙角的时候,该墙角与其他墙面相交
  14. this.splitRoadId = null;
  15. }
  16. setStartMoving(value) {
  17. this.startMoving = value;
  18. }
  19. // 测试要考虑pointId拖拽到包含他的所有墙的另一头
  20. // 这个函数不会删除/拆分/合并墙或者点
  21. movePoint(pointId, position, modifyPoint) {
  22. let point = dataService.getPoint(pointId);
  23. let linkedPointId = null;
  24. let linkedRoadId = null;
  25. if (modifyPoint != null) {
  26. position = {
  27. x: modifyPoint.x,
  28. y: modifyPoint.y,
  29. };
  30. linkedPointId = modifyPoint.linkedPointId;
  31. linkedRoadId = modifyPoint.linkedRoadId;
  32. }
  33. this.adsorbPointRoads = {};
  34. this.splitRoadId = null;
  35. let flag = this.canMoveForPoint(
  36. pointId,
  37. position,
  38. linkedPointId,
  39. linkedRoadId
  40. );
  41. if (!flag) {
  42. if (
  43. this.splitRoadId == null &&
  44. Object.keys(this.adsorbPointRoads).length > 0
  45. ) {
  46. //要吸附一下
  47. const adsorbPointId = Object.keys(this.adsorbPointRoads)[0];
  48. const road = dataService.getRoad(this.adsorbPointRoads[adsorbPointId]);
  49. const otherPointId = road.getOtherPointId(pointId);
  50. let otherPoint = dataService.getPoint(otherPointId);
  51. let modifyPoint = dataService.getPoint(adsorbPointId);
  52. let line = mathUtil.createLine1(otherPoint, modifyPoint);
  53. position = mathUtil.getJoinLinePoint(position, line);
  54. point.setPosition(position);
  55. }
  56. return false;
  57. }
  58. let newPosition = null;
  59. if (modifyPoint == null) {
  60. //90°或者180°纠正
  61. //不考虑当前角度
  62. //当前点的parent只有一个,考虑邻居点
  63. let neighPoints = roadService.getNeighPoints(pointId);
  64. if (neighPoints.length == 1) {
  65. newPosition = elementService.checkAngle(
  66. position,
  67. neighPoints[0].vectorId,
  68. pointId
  69. );
  70. }
  71. //当前点的parent有两个
  72. else if (neighPoints.length == 2) {
  73. newPosition = elementService.checkAngle(
  74. position,
  75. neighPoints[0].vectorId,
  76. pointId
  77. );
  78. if (!newPosition) {
  79. newPosition = elementService.checkAngle(
  80. position,
  81. neighPoints[1].vectorId,
  82. pointId
  83. );
  84. }
  85. }
  86. if (newPosition) {
  87. flag = this.canMoveForPoint(
  88. pointId,
  89. newPosition,
  90. linkedPointId,
  91. linkedRoadId
  92. );
  93. if (!flag) {
  94. return false;
  95. }
  96. mathUtil.clonePoint(position, newPosition);
  97. }
  98. point.setPosition(position);
  99. }
  100. // 与别的墙角重合
  101. else if (
  102. modifyPoint.hasOwnProperty("linkedPointId") &&
  103. modifyPoint.linkedPointId != null
  104. ) {
  105. const roadId = roadService.getRoadId(pointId, modifyPoint.linkedPointId);
  106. // pointId与linkedPointId属于同一堵墙,不允许,所以不移动
  107. if (roadId != null) {
  108. return false;
  109. } else {
  110. point.setPosition(modifyPoint);
  111. }
  112. }
  113. // 与别的墙面重合
  114. // 如果墙面的交点与其余墙角的距离过短,那也不允许拖动
  115. else if (modifyPoint.hasOwnProperty("linkedRoadId")) {
  116. const road = dataService.getRoad(modifyPoint.linkedRoadId);
  117. const startPoint = dataService.getPoint(road.startId);
  118. const endPoint = dataService.getPoint(road.endId);
  119. // 与其余墙角的距离过短,不允许拖动
  120. if (
  121. mathUtil.getDistance(startPoint, position) < Constant.minRealDis ||
  122. mathUtil.getDistance(endPoint, position) < Constant.minRealDis
  123. ) {
  124. return false;
  125. }
  126. point.setPosition(modifyPoint);
  127. } else {
  128. if (
  129. modifyPoint.hasOwnProperty("linkedPointIdX") &&
  130. modifyPoint.linkedPointIdX
  131. ) {
  132. point.setPosition(position);
  133. }
  134. if (
  135. modifyPoint.hasOwnProperty("linkedPointIdY") &&
  136. modifyPoint.linkedPointIdY
  137. ) {
  138. point.setPosition(position);
  139. }
  140. }
  141. return true;
  142. }
  143. //拖拽墙角/墙面,被其他墙角吸附
  144. updateForAbsorbRoadPoints() {
  145. if (Object.keys(this.adsorbPointRoads).length == 0) {
  146. return;
  147. } else if (Object.keys(this.adsorbPointRoads).length == 2) {
  148. debugger;
  149. }
  150. let joins = [];
  151. let roadId = null;
  152. for (let key in this.adsorbPointRoads) {
  153. let point = dataService.getPoint(key);
  154. joins.push({
  155. join: point,
  156. pointId: key,
  157. });
  158. roadId = this.adsorbPointRoads[key];
  159. }
  160. const road = dataService.getRoad(roadId);
  161. const startPoint = dataService.getPoint(road.startId);
  162. function sortNumber(a, b) {
  163. return (
  164. mathUtil.getDistance(startPoint, a.join) -
  165. mathUtil.getDistance(startPoint, b.join)
  166. );
  167. }
  168. joins = joins.sort(sortNumber.bind(this));
  169. for (let i = 0; i < joins.length; ++i) {
  170. const info = joins[i];
  171. const join = info.join;
  172. const pointId = info.pointId;
  173. roadService.splitRoad(roadId, pointId, "end");
  174. }
  175. }
  176. getNewPointsForMoveRoad(roadId, dx, dy) {
  177. dx = dx / coordinate.res;
  178. dy = -dy / coordinate.res;
  179. const road = dataService.getRoad(roadId);
  180. const startPoint = dataService.getPoint(road.startId);
  181. const endPoint = dataService.getPoint(road.endId);
  182. const p1 = { x: startPoint.x + dx, y: startPoint.y + dy };
  183. const p2 = { x: endPoint.x + dx, y: endPoint.y + dy };
  184. return {
  185. point1: p1,
  186. point2: p2,
  187. };
  188. }
  189. getTwoLimitInfos(roadId, newLine) {
  190. const road = dataService.getRoad(roadId);
  191. const startPoint = dataService.getPoint(road.startId);
  192. const endPoint = dataService.getPoint(road.endId);
  193. let startLimitLine, endLimitLine, info;
  194. const roadLine = roadService.getMidLine(road);
  195. const limitInfos = {};
  196. limitInfos.newStartRoadId = false; // 不需要新建墙
  197. limitInfos.newEndRoadId = false; // 不需要新建墙
  198. // 先处理start
  199. if (Object.keys(startPoint.parent).length == 1) {
  200. startLimitLine = mathUtil.getVerticalLine(roadLine, startPoint);
  201. limitInfos.startRoadId = null;
  202. } else if (Object.keys(startPoint.parent).length == 2) {
  203. let tempRoad;
  204. if (Object.keys(startPoint.parent)[0] == roadId) {
  205. tempRoad = dataService.getRoad(Object.keys(startPoint.parent)[1]);
  206. } else if (Object.keys(startPoint.parent)[1] == roadId) {
  207. tempRoad = dataService.getRoad(Object.keys(startPoint.parent)[0]);
  208. }
  209. if (!tempRoad) {
  210. console.error(352);
  211. }
  212. const angle = roadService.AngleForRoad(tempRoad.vectorId, roadId);
  213. startLimitLine = roadService.getMidLine(tempRoad);
  214. limitInfos.startRoadId = tempRoad.vectorId;
  215. if (angle > (Constant.maxAngle / 180) * Math.PI) {
  216. startLimitLine = mathUtil.getVerticalLine(roadLine, startPoint);
  217. limitInfos.startRoadId = null;
  218. limitInfos.newStartRoadId = true;
  219. }
  220. } else {
  221. let tempRoad, tempRoadId;
  222. info = roadService.roadIdForMinAngle(road.startId, roadId);
  223. const road1 = dataService.getRoad(info.min0.roadId);
  224. const startPoint1 = dataService.getPoint(road1.startId);
  225. const endPoint1 = dataService.getPoint(road1.endId);
  226. const road2 = dataService.getRoad(info.min1.roadId);
  227. const startPoint2 = dataService.getPoint(road2.startId);
  228. const endPoint2 = dataService.getPoint(road2.endId);
  229. const join1 = mathUtil.getIntersectionPoint4(
  230. startPoint1,
  231. endPoint1,
  232. newLine
  233. );
  234. const join2 = mathUtil.getIntersectionPoint4(
  235. startPoint2,
  236. endPoint2,
  237. newLine
  238. );
  239. // 取角度大的
  240. if (join1 == null && join2 == null) {
  241. let angle0 = roadService.AngleForRoad(roadId, info.min0.roadId);
  242. let angle1 = roadService.AngleForRoad(roadId, info.min1.roadId);
  243. if (angle0 > Math.PI) {
  244. angle0 = Math.PI - angle0;
  245. }
  246. if (angle1 > Math.PI) {
  247. angle1 = Math.PI - angle1;
  248. }
  249. if (angle0 < angle1) {
  250. tempRoadId = info.min0.roadId;
  251. } else {
  252. tempRoadId = info.min1.roadId;
  253. }
  254. limitInfos.newStartRoadId = true;
  255. }
  256. // 取角度小的
  257. else if (join1 != null && join2 != null) {
  258. if (info.min0.angle < info.min1.angle) {
  259. tempRoadId = info.min0.roadId;
  260. } else {
  261. tempRoadId = info.min1.roadId;
  262. }
  263. } else if (join1 == null && join2 != null) {
  264. tempRoadId = info.min1.roadId;
  265. } else if (join1 != null && join2 == null) {
  266. tempRoadId = info.min0.roadId;
  267. }
  268. limitInfos.startRoadId = tempRoadId;
  269. tempRoad = dataService.getRoad(tempRoadId);
  270. const angle = roadService.AngleForRoad(tempRoadId, roadId);
  271. startLimitLine = roadService.getMidLine(tempRoad);
  272. let join = mathUtil.getIntersectionPoint(startLimitLine, newLine);
  273. const tempStartPoint = dataService.getPoint(tempRoad.startId);
  274. const tempEndPoint = dataService.getPoint(tempRoad.endId);
  275. if (
  276. angle > (Constant.maxAngle / 180) * Math.PI ||
  277. !mathUtil.isPointOnSegment(join, tempStartPoint, tempEndPoint)
  278. ) {
  279. startLimitLine = mathUtil.getVerticalLine(roadLine, startPoint);
  280. limitInfos.startRoadId = null;
  281. limitInfos.newStartRoadId = true;
  282. }
  283. }
  284. // 再处理end
  285. if (Object.keys(endPoint.parent).length == 1) {
  286. endLimitLine = mathUtil.getVerticalLine(roadLine, endPoint);
  287. limitInfos.endRoadId = null;
  288. } else if (Object.keys(endPoint.parent).length == 2) {
  289. let tempRoad;
  290. if (Object.keys(endPoint.parent)[0] == roadId) {
  291. tempRoad = dataService.getRoad(Object.keys(endPoint.parent)[1]);
  292. } else if (Object.keys(endPoint.parent)[1] == roadId) {
  293. tempRoad = dataService.getRoad(Object.keys(endPoint.parent)[0]);
  294. }
  295. const angle = roadService.AngleForRoad(tempRoad.vectorId, roadId);
  296. endLimitLine = roadService.getMidLine(tempRoad);
  297. limitInfos.endRoadId = tempRoad.vectorId;
  298. if (angle > (Constant.maxAngle / 180) * Math.PI) {
  299. endLimitLine = mathUtil.getVerticalLine(roadLine, endPoint);
  300. limitInfos.endRoadId = null;
  301. limitInfos.newEndRoadId = true;
  302. }
  303. } else {
  304. let tempRoad, tempRoadId;
  305. info = dataService.roadIdForMinAngle(road.endId, roadId);
  306. const road1 = dataService.getRoad(info.min0.roadId);
  307. const startPoint1 = dataService.getPoint(road1.startId);
  308. const endPoint1 = dataService.getPoint(road1.endId);
  309. const road2 = dataService.getRoad(info.min1.roadId);
  310. const startPoint2 = dataService.getPoint(road2.startId);
  311. const endPoint2 = dataService.getPoint(road2.endId);
  312. const join1 = mathUtil.getIntersectionPoint4(
  313. startPoint1,
  314. endPoint1,
  315. newLine
  316. );
  317. const join2 = mathUtil.getIntersectionPoint4(
  318. startPoint2,
  319. endPoint2,
  320. newLine
  321. );
  322. // 取角度大的
  323. if (join1 == null && join2 == null) {
  324. let angle0 = roadService.AngleForRoad(roadId, info.min0.roadId);
  325. let angle1 = roadService.AngleForRoad(roadId, info.min1.roadId);
  326. if (angle0 > Math.PI) {
  327. angle0 = Math.PI - angle0;
  328. }
  329. if (angle1 > Math.PI) {
  330. angle1 = Math.PI - angle1;
  331. }
  332. if (angle0 < angle1) {
  333. tempRoadId = info.min0.roadId;
  334. } else {
  335. tempRoadId = info.min1.roadId;
  336. }
  337. limitInfos.newEndRoadId = true;
  338. }
  339. // 取角度小的
  340. else if (join1 != null && join2 != null) {
  341. if (info.min0.angle < info.min1.angle) {
  342. tempRoadId = info.min0.roadId;
  343. } else {
  344. tempRoadId = info.min1.roadId;
  345. }
  346. } else if (join1 == null && join2 != null) {
  347. tempRoadId = info.min1.roadId;
  348. } else if (join1 != null && join2 == null) {
  349. tempRoadId = info.min0.roadId;
  350. }
  351. limitInfos.endRoadId = tempRoadId;
  352. tempRoad = dataService.getRoad(tempRoadId);
  353. const angle = roadService.AngleForRoad(tempRoadId, roadId);
  354. endLimitLine = roadService.getMidLine(tempRoad);
  355. let join = mathUtil.getIntersectionPoint(endLimitLine, newLine);
  356. const tempStartPoint = dataService.getPoint(tempRoad.start);
  357. const tempEndPoint = dataService.getPoint(tempRoad.end);
  358. if (
  359. angle > (Constant.maxAngle / 180) * Math.PI ||
  360. !mathUtil.isPointOnSegment(join, tempStartPoint, tempEndPoint)
  361. ) {
  362. endLimitLine = mathUtil.getVerticalLine(roadLine, endPoint);
  363. limitInfos.endRoadId = null;
  364. limitInfos.newEndRoadId = true;
  365. }
  366. }
  367. limitInfos.startLimitLine = startLimitLine;
  368. limitInfos.endLimitLine = endLimitLine;
  369. return limitInfos;
  370. }
  371. // 是否可以移动point
  372. // 两个判断:拖拽的墙(可能是多个),一方面不能与其他墙相交,另一方面这些墙之间或者与别的墙之间的角度必须大于Constant.minAngle
  373. canMoveForPoint(pointId, position, linkedPointId, linkedRoadId) {
  374. const point = dataService.getPoint(pointId);
  375. // 先判断第二点(这些墙之间或者与别的墙之间的角度必须大于MinAngle)
  376. let flag = this.isOKForMinAngleRoad(pointId, position);
  377. // 开始考虑第一点
  378. if (flag) {
  379. // 不仅仅角度,还有相交
  380. flag = this.isOKForCross(
  381. pointId,
  382. position,
  383. point.parent,
  384. linkedPointId,
  385. linkedRoadId
  386. );
  387. }
  388. return flag;
  389. }
  390. isOKForMinAngleRoad(pointId, position) {
  391. const point = dataService.getPoint(pointId);
  392. const parent = point.parent;
  393. const angle = this.getMinAngle(pointId, position);
  394. if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
  395. return false;
  396. }
  397. // 判断邻居点
  398. for (const key in parent) {
  399. const road = dataService.getRoad(key);
  400. const otherPointId = road.getOtherPointId(pointId);
  401. const info = this.getNeighMinAngle(otherPointId, key, position);
  402. if (info && Math.abs(info.angle) < (Constant.minAngle / 180) * Math.PI) {
  403. return false;
  404. } else {
  405. const otherPoint = dataService.getPoint(otherPointId);
  406. if (mathUtil.getDistance(position, otherPoint) < Constant.minRealDis) {
  407. return false;
  408. }
  409. }
  410. }
  411. return true;
  412. }
  413. //点pointId移动到position后,求出最小角度
  414. getMinAngle(pointId, position) {
  415. const point = dataService.getPoint(pointId);
  416. const parent = point.parent;
  417. let angle = null;
  418. if (Object.keys(parent).length == 1) {
  419. return 2 * Math.PI;
  420. } else if (Object.keys(parent).length == 2) {
  421. const road1 = dataService.getRoad(Object.keys(parent)[0]);
  422. const road2 = dataService.getRoad(Object.keys(parent)[1]);
  423. const otherPointId1 = road1.getOtherPointId(pointId);
  424. const otherPoint1 = dataService.getPoint(otherPointId1);
  425. const otherPointId2 = road2.getOtherPointId(pointId);
  426. const otherPoint2 = dataService.getPoint(otherPointId2);
  427. angle = mathUtil.Angle(position, otherPoint1, otherPoint2);
  428. return angle;
  429. } else {
  430. const _position = {
  431. x: position.x + 1,
  432. y: position.y,
  433. };
  434. let angles = [];
  435. for (const key in parent) {
  436. const road = dataService.getRoad(key);
  437. const otherPointId = road.getOtherPointId(pointId);
  438. const otherPoint = dataService.getPoint(otherPointId);
  439. if (mathUtil.equalPoint(_position, otherPoint)) {
  440. angles.push(0);
  441. continue;
  442. } else {
  443. let angle = mathUtil.Angle(position, _position, otherPoint);
  444. // 统一按照逆时针顺序
  445. if (otherPoint.y < position.y) {
  446. angle = 2 * Math.PI - angle;
  447. }
  448. angles.push(angle);
  449. }
  450. }
  451. angles = angles.sort(sortNumber);
  452. let minAngle = 2 * Math.PI;
  453. for (let i = 0; i < angles.length - 1; ++i) {
  454. for (let j = i + 1; j < angles.length; ++j) {
  455. const _angle = angles[j] - angles[i];
  456. if (_angle < minAngle) {
  457. minAngle = _angle;
  458. }
  459. }
  460. }
  461. const angle1 = angles[0];
  462. const angle2 = angles[angles.length - 1];
  463. if (angle1 < Math.PI && angle2 > Math.PI) {
  464. const dAngle = 2 * Math.PI + angle1 - angle2;
  465. if (dAngle < minAngle) {
  466. minAngle = dAngle;
  467. }
  468. }
  469. return minAngle;
  470. }
  471. function sortNumber(a, b) {
  472. return a - b;
  473. }
  474. }
  475. // 用于邻居点
  476. // pointId是顶点
  477. // position是roadId相对于pointId另一头的点的坐标,一般发生改变的时候使用这个函数
  478. getNeighMinAngle(otherPointId, roadId, position) {
  479. const point1 = dataService.getPoint(otherPointId);
  480. const point2 = {
  481. x: position.x,
  482. y: position.y,
  483. };
  484. let pointId3 = null;
  485. let point3 = null;
  486. let minAngle = null;
  487. let result = null;
  488. for (const key in point1.parent) {
  489. if (key == roadId) {
  490. continue;
  491. }
  492. const road = dataService.getRoad(key);
  493. pointId3 = road.getOtherPointId(otherPointId);
  494. point3 = dataService.getPoint(pointId3);
  495. const angle = mathUtil.Angle(point1, point2, point3);
  496. if (minAngle == null || minAngle > angle) {
  497. minAngle = angle;
  498. result = {
  499. angle: minAngle,
  500. pointId: pointId3,
  501. };
  502. }
  503. }
  504. return result;
  505. }
  506. // linkedPointId,linkedRoadId表示吸附
  507. // roadIds是pointId的parent
  508. isOKForCross(pointId, position, roadIds, linkedPointId, linkedRoadId) {
  509. const roads = dataService.getRoads();
  510. for (const key in roads) {
  511. if (roadIds.hasOwnProperty(key)) {
  512. continue;
  513. } else if (linkedRoadId == key) {
  514. continue;
  515. }
  516. for (const _key in roadIds) {
  517. //相连就不用考虑了
  518. if (roadService.isRoadLink(key, _key)) {
  519. continue;
  520. }
  521. const _road = dataService.getRoad(_key);
  522. const otherPointId = _road.getOtherPointId(pointId);
  523. const otherPoint = dataService.getPoint(otherPointId);
  524. const flag = this.isOKForCrossTwoRoad(
  525. position,
  526. otherPoint,
  527. key,
  528. linkedPointId,
  529. linkedRoadId,
  530. _road.vectorId
  531. );
  532. // 交叉
  533. if (!flag) {
  534. this.adsorbPointRoads = {};
  535. return false;
  536. }
  537. }
  538. }
  539. //需要吸附了。
  540. if (Object.keys(this.adsorbPointRoads).length > 0) {
  541. return false;
  542. } else if (this.splitRoadId != null) {
  543. return false;
  544. }
  545. // 不交叉
  546. return true;
  547. }
  548. // position1表示拖拽的点的坐标(修复过了的)
  549. // position2对应墙的另一头坐标
  550. // roadId表示其余的墙(与position1无关的墙)
  551. isOKForCrossTwoRoad(
  552. position1,
  553. position2,
  554. roadId,
  555. linkedPointId,
  556. linkedRoadId,
  557. dragRoadId
  558. ) {
  559. const road = dataService.getRoad(roadId);
  560. const startPoint = dataService.getPoint(road.startId);
  561. const endPoint = dataService.getPoint(road.endId);
  562. const join = mathUtil.getIntersectionPoint3(
  563. position1,
  564. position2,
  565. startPoint,
  566. endPoint
  567. );
  568. if (join && road.startId != linkedPointId && road.endId != linkedPointId) {
  569. // 交叉了
  570. this.splitRoadId = roadId;
  571. return true;
  572. } else {
  573. if (mathUtil.equalPoint(position1, position2)) {
  574. return true;
  575. }
  576. let line = mathUtil.createLine1(position1, position2);
  577. let join1 = mathUtil.getJoinLinePoint(startPoint, line);
  578. let join2 = mathUtil.getJoinLinePoint(endPoint, line);
  579. if (
  580. mathUtil.getDistance(join1, startPoint) < Constant.minRealDis &&
  581. mathUtil.PointInSegment(join1, position1, position2)
  582. ) {
  583. if (road.startId != linkedPointId) {
  584. // 交叉了
  585. this.adsorbPointRoads[startPoint.vectorId] = dragRoadId;
  586. //为了找到全部的吸附点,暂时返回true,在外面一层再做判断
  587. return true;
  588. }
  589. } else if (
  590. mathUtil.getDistance(join2, endPoint) < Constant.minRealDis &&
  591. mathUtil.PointInSegment(join2, position1, position2)
  592. ) {
  593. if (road.endId != linkedPointId) {
  594. // 交叉了
  595. this.adsorbPointRoads[endPoint.vectorId] = dragRoadId;
  596. //为了找到全部的吸附点,暂时返回true,在外面一层再做判断
  597. return true;
  598. }
  599. }
  600. line = mathUtil.createLine1(startPoint, endPoint);
  601. join1 = mathUtil.getJoinLinePoint(position1, line);
  602. join2 = mathUtil.getJoinLinePoint(position2, line);
  603. if (
  604. mathUtil.getDistance(join1, position1) < Constant.minRealDis &&
  605. mathUtil.PointInSegment(join1, startPoint, endPoint)
  606. ) {
  607. if (
  608. road.startId != linkedPointId &&
  609. road.endId != linkedPointId &&
  610. roadId != linkedRoadId
  611. ) {
  612. // 交叉了
  613. //return false
  614. return true;
  615. }
  616. } else if (
  617. mathUtil.getDistance(join2, position2) < Constant.minRealDis &&
  618. mathUtil.PointInSegment(join2, startPoint, endPoint)
  619. ) {
  620. if (
  621. road.startId != linkedPointId &&
  622. road.endId != linkedPointId &&
  623. roadId != linkedRoadId
  624. ) {
  625. // 交叉了
  626. //return false
  627. return true;
  628. }
  629. }
  630. }
  631. return true;
  632. }
  633. isOKForCrossTwoRoad2(position1, position2, roadId) {
  634. const road = dataService.getRoad(roadId);
  635. const startPoint = dataService.getPoint(road.startId);
  636. const endPoint = dataService.getPoint(road.endId);
  637. let flag = mathUtil.crossTwoLines(
  638. position1,
  639. position2,
  640. startPoint,
  641. endPoint,
  642. 0.01
  643. );
  644. if (flag) {
  645. // 交叉了
  646. return false;
  647. } else {
  648. if (mathUtil.equalPoint(position1, position2)) {
  649. return true;
  650. }
  651. flag = this.isCoincide(position1, position2, roadId);
  652. if (!flag) {
  653. return false;
  654. }
  655. }
  656. return true;
  657. }
  658. isOKForCrossTwoRoad3(position1, position2, roadId) {
  659. const road = dataService.getRoad(roadId);
  660. const startPoint = dataService.getPoint(road.startId);
  661. const endPoint = dataService.getPoint(road.endId);
  662. const flag = mathUtil.crossTwoLines(
  663. position1,
  664. position2,
  665. startPoint,
  666. endPoint,
  667. 0.01
  668. );
  669. if (flag) {
  670. // 交叉了
  671. return false;
  672. } else {
  673. if (mathUtil.equalPoint(position1, position2)) {
  674. return true;
  675. }
  676. let line = mathUtil.createLine1(position1, position2);
  677. let join1 = mathUtil.getJoinLinePoint(startPoint, line);
  678. const join2 = mathUtil.getJoinLinePoint(endPoint, line);
  679. if (
  680. mathUtil.getDistance(join1, startPoint) < Constant.minRealDis &&
  681. mathUtil.isPointOnSegment(join1, position1, position2)
  682. ) {
  683. // 交叉了
  684. return false;
  685. } else if (
  686. mathUtil.getDistance(join2, endPoint) < Constant.minRealDis &&
  687. mathUtil.isPointOnSegment(join2, position1, position2)
  688. ) {
  689. // 交叉了
  690. return false;
  691. }
  692. line = mathUtil.createLine1(startPoint, endPoint);
  693. join1 = mathUtil.getJoinLinePoint(position1, line);
  694. if (
  695. mathUtil.getDistance(join1, position1) < Constant.minRealDis &&
  696. roadService.isContain(road, join1)
  697. ) {
  698. // 交叉了
  699. return false;
  700. }
  701. }
  702. return true;
  703. }
  704. isCoincide(position1, position2, roadId) {
  705. const road = dataService.getRoad(roadId);
  706. const startPoint = dataService.getPoint(road.startId);
  707. const endPoint = dataService.getPoint(road.endId);
  708. let line = mathUtil.createLine1(position1, position2);
  709. let join1 = mathUtil.getJoinLinePoint(startPoint, line);
  710. let join2 = mathUtil.getJoinLinePoint(endPoint, line);
  711. if (
  712. mathUtil.getDistance(join1, startPoint) < Constant.minRealDis &&
  713. mathUtil.PointInSegment(join1, position1, position2)
  714. ) {
  715. // 交叉了
  716. return false;
  717. } else if (
  718. mathUtil.getDistance(join2, endPoint) < Constant.minRealDis &&
  719. mathUtil.PointInSegment(join2, position1, position2)
  720. ) {
  721. // 交叉了
  722. return false;
  723. }
  724. line = mathUtil.createLine1(startPoint, endPoint);
  725. join1 = mathUtil.getJoinLinePoint(position1, line);
  726. join2 = mathUtil.getJoinLinePoint(position2, line);
  727. if (
  728. mathUtil.getDistance(join1, position1) < Constant.minRealDis &&
  729. roadService.isContain(road, join1)
  730. ) {
  731. // 交叉了
  732. return false;
  733. } else if (
  734. mathUtil.getDistance(join2, position2) < Constant.minRealDis &&
  735. roadService.isContain(road, join2)
  736. ) {
  737. // 交叉了
  738. return false;
  739. }
  740. return true;
  741. }
  742. // 更新virtualPosition(一般是吸附)
  743. updateVirtualPosition(pointId, virtualPosition, limitRoadId, needNew) {
  744. const limitRoad = dataService.getRoad(limitRoadId);
  745. const point = dataService.getPoint(pointId);
  746. let otherPointId, otherPoint;
  747. let adsorb = false;
  748. // 不需要新建墙
  749. if (!needNew) {
  750. if (limitRoad != null) {
  751. otherPointId = limitRoad.getOtherPointId(pointId);
  752. otherPoint = dataService.getPoint(otherPointId);
  753. // 会吸附另一头
  754. if (
  755. mathUtil.getDistance(virtualPosition, otherPoint) <
  756. Constant.minRealDis ||
  757. (!roadService.isContain(limitRoad, virtualPosition) &&
  758. mathUtil.getDistance(virtualPosition, otherPoint) <
  759. mathUtil.getDistance(virtualPosition, point))
  760. ) {
  761. mathUtil.clonePoint(virtualPosition, otherPoint);
  762. adsorb = true;
  763. }
  764. }
  765. }
  766. // 需要新建墙
  767. else {
  768. // 新建的墙太短,不允许
  769. if (mathUtil.getDistance(point, virtualPosition) < Constant.minRealDis) {
  770. return null;
  771. }
  772. }
  773. return {
  774. adsorb: adsorb,
  775. adsorbPointId: adsorb ? otherPointId : null,
  776. virtualPosition: virtualPosition,
  777. };
  778. }
  779. // 两条线段的夹角,这两条线段分别有一个端点挨的很近
  780. isOKForTwoSegmentsAngle(pointId, pointId1, pointId2) {
  781. const point = dataService.getPoint(pointId);
  782. const point1 = dataService.getPoint(pointId1);
  783. const point2 = dataService.getPoint(pointId2);
  784. const dx = point.x - point1.x;
  785. const dy = point.y - point1.y;
  786. const newPoint2 = {
  787. x: dx + point2.x,
  788. y: dy + point2.y,
  789. };
  790. for (const key in point.parent) {
  791. const road = dataService.getRoad(key);
  792. const otherPointId = road.getOtherPointId(pointId);
  793. const otherPoint = dataService.getPoint(otherPointId);
  794. const angle = mathUtil.Angle(point, otherPoint, newPoint2);
  795. if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
  796. return false;
  797. }
  798. }
  799. return true;
  800. }
  801. // 一头吸附后,是否会重合
  802. // pointId属于roadId,当pointId吸附到adsorbPointId时
  803. isCoincideForAdsorbOne(pointId, adsorbPointId, roadId) {
  804. if (pointId && adsorbPointId) {
  805. const road = dataService.getRoad(roadId);
  806. const otherPointId = road.getOtherPointId(pointId);
  807. const _roadId = roadService.getRoadId(otherPointId, adsorbPointId);
  808. if (_roadId != null) {
  809. return true;
  810. }
  811. }
  812. return false;
  813. }
  814. isCoincideForAdsorbOne2(roadId, adsorbPointId1, adsorbPointId2) {
  815. if (adsorbPointId1 && adsorbPointId2) {
  816. const _roadId = roadService.getRoadId(adsorbPointId1, adsorbPointId2);
  817. if (_roadId != null) {
  818. return true;
  819. }
  820. // 可能吸附的是两堵墙,但是这两堵墙呈180°
  821. else {
  822. let adsorbPoint = dataService.getPoint(adsorbPointId1);
  823. let parent = adsorbPoint.parent;
  824. for (const key in parent) {
  825. const angle = roadService.AngleForRoad3(roadId, key);
  826. if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
  827. return true;
  828. }
  829. }
  830. adsorbPoint = dataService.getPoint(adsorbPointId2);
  831. parent = adsorbPoint.parent;
  832. for (const key in parent) {
  833. const angle = roadService.AngleForRoad3(roadId, key);
  834. if (Math.abs(angle) < (Constant.minAngle / 180) * Math.PI) {
  835. return true;
  836. }
  837. }
  838. }
  839. }
  840. return false;
  841. }
  842. // position1和position2表示road的两个端点坐标(下一步的)
  843. // position3和position4表示road的start一边的线段(startPoint——virtualStartPoint)
  844. // position5和position6表示road的end一边的线段(endPoint——virtualEndPoint)
  845. // adsorbPointId1对应start那一头的吸附点
  846. // adsorbPointId2对应end那一头的吸附点
  847. isOKForCrossForMoveRoad(
  848. position1,
  849. position2,
  850. roadId,
  851. startPointId,
  852. endPointId,
  853. adsorbPointId1,
  854. adsorbPointId2
  855. ) {
  856. const startPoint = dataService.getPoint(startPointId);
  857. const endPoint = dataService.getPoint(endPointId);
  858. let flag = true;
  859. const roads = dataService.getRoads();
  860. for (const key in roads) {
  861. if (key == roadId) {
  862. continue;
  863. }
  864. let flag1 = true;
  865. let flag2 = true;
  866. const _road = dataService.getRoad(key);
  867. if (
  868. adsorbPointId1 &&
  869. (adsorbPointId1 == _road.startId || adsorbPointId1 == _road.endId)
  870. ) {
  871. flag1 = false;
  872. }
  873. if (
  874. adsorbPointId2 &&
  875. (adsorbPointId2 == _road.startId || adsorbPointId2 == _road.endId)
  876. ) {
  877. flag2 = false;
  878. }
  879. if (_road.startId == startPointId || _road.endId == startPointId) {
  880. flag1 = false;
  881. }
  882. if (_road.startId == endPointId || _road.endId == endPointId) {
  883. flag2 = false;
  884. }
  885. // 两头不连
  886. if (flag1 && flag2) {
  887. flag = this.isOKForCrossTwoRoad2(position1, position2, key);
  888. }
  889. if (!flag) {
  890. return false;
  891. }
  892. if (
  893. flag1 &&
  894. _road.startId != startPointId &&
  895. _road.endId != startPointId
  896. ) {
  897. flag = this.isOKForCrossTwoRoad3(position1, startPoint, key);
  898. }
  899. if (!flag) {
  900. return false;
  901. }
  902. if (flag2 && _road.startId != endPointId && _road.endId != endPointId) {
  903. flag = this.isOKForCrossTwoRoad3(position2, endPoint, key);
  904. }
  905. if (!flag) {
  906. return false;
  907. }
  908. }
  909. return flag;
  910. }
  911. // 更新pointId的坐标
  912. updatePointForMoveRoad(roadId, pointId, virtualInfo, limitRoadId, needNew) {
  913. const point = dataService.getPoint(pointId);
  914. const road = dataService.getRoad(roadId);
  915. // 如果没有约束墙,只有两种情况:一种是不新建墙,另一种是需要新建墙
  916. if (limitRoadId == null) {
  917. // 不需要新建墙,这种情况一般是pointId的parent只有一个
  918. if (!needNew) {
  919. point.setPosition(virtualInfo.virtualPosition);
  920. }
  921. // 新建墙
  922. else {
  923. this.createRoadForMoveRoad(
  924. pointId,
  925. roadId,
  926. virtualInfo.virtualPosition
  927. );
  928. }
  929. } else {
  930. /*
  931. 不新建墙:
  932. 1. 更新坐标(一种是当pointId的parent是2个,另一种是三个,但是roadId对应的两堵墙接近180°)
  933. 2. 拆分墙
  934. 3. 吸附邻居墙的另一个端点
  935. 新建墙:
  936. */
  937. // 不新建墙
  938. if (!needNew) {
  939. if (!virtualInfo.adsorb) {
  940. // 只更新坐标
  941. if (Object.keys(point.parent).length == 2) {
  942. point.setPosition(virtualInfo.virtualPosition);
  943. } else {
  944. const info = roadService.roadIdForMinAngle(pointId, roadId);
  945. const angle = roadService.AngleForRoad(
  946. info.min0.roadId,
  947. info.min1.roadId
  948. );
  949. // 只更新坐标
  950. if (
  951. Object.keys(point.parent).length == 3 &&
  952. angle > (Constant.maxAngle / 180) * Math.PI
  953. ) {
  954. point.setPosition(virtualInfo.virtualPosition);
  955. }
  956. // 拆分墙
  957. else {
  958. const dir = roadService.getDirction(pointId, roadId);
  959. // 先断开链接
  960. roadService.subtraRoadFromIntersect(pointId, roadId);
  961. const newPointId = road.getPointId(dir);
  962. const newPoint = dataService.getPoint(newPointId);
  963. // 更新新坐标
  964. newPoint.setPosition(virtualInfo.virtualPosition);
  965. // 拆分
  966. roadService.splitRoad(limitRoadId, newPointId, dir);
  967. }
  968. }
  969. }
  970. // 吸附邻居墙的另一个端点。
  971. else {
  972. roadService.moveTo(pointId, virtualInfo.adsorbPointId);
  973. }
  974. }
  975. // 新建墙
  976. else {
  977. this.createRoadForMoveRoad(
  978. pointId,
  979. roadId,
  980. virtualInfo.virtualPosition
  981. );
  982. }
  983. }
  984. }
  985. //
  986. createRoadForMoveRoad(pointId, roadId, newPosition) {
  987. const road = dataService.getRoad(roadId);
  988. const dir = roadService.getDirction(pointId, roadId);
  989. // 第一步是断开连接
  990. roadService.subtraRoadFromIntersect(pointId, roadId);
  991. // 第二步更新端点坐标
  992. const newPointId = road.getPointId(dir);
  993. const newPoint = dataService.getPoint(newPointId);
  994. newPoint.setPosition(newPosition);
  995. // 第三步先新建墙
  996. roadService.create(pointId, newPointId);
  997. // 还缺少road和newRoad相交,这需要等另一头的point完成后最后处理
  998. }
  999. deleteRoadForLinked(roadId) {
  1000. const road = dataService.getRoad(roadId);
  1001. roadService.subtraRoadFromIntersect(road.startId, roadId);
  1002. roadService.subtraRoadFromIntersect(road.endId, roadId);
  1003. dataService.deleteRoad(roadId);
  1004. }
  1005. }
  1006. const moveRoad = new MoveRoad();
  1007. export { moveRoad };