MoveRoad.js 37 KB

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