MoveRoad.js 38 KB

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