SymbolService.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149
  1. // import { mathUtil } from "../Util/MathUtil.js/index.js";
  2. // import SingleDoor from "../Geometry/SingleDoor.js";
  3. // import DoubleDoor from "../Geometry/DoubleDoor.js";
  4. // import SlideDoor from "../Geometry/SlideDoor.js";
  5. // import SingleWindow from "../Geometry/SingleWindow.js";
  6. // import FrenchWindow from "../Geometry/FrenchWindow.js";
  7. // import BayWindow from "../Geometry/BayWindow.js";
  8. // import Pass from "../Geometry/Pass.js";
  9. import { coordinate } from "../Coordinate";
  10. import { dataService } from "./DataService.js";
  11. // import { wallService } from "./WallService.js";
  12. import VectorType from "../enum/VectorType.js";
  13. import Constant from "../Constant";
  14. // import { moveSymbol } from "../Controls/MoveSymbol.js";
  15. import { stateService } from "./StateService.js";
  16. export class SymbolService {
  17. constructor() {
  18. this.enterImg = null;
  19. }
  20. // 新建symbol
  21. createSymbol(start, end, geoType, parent, symbolId) {
  22. let symbol = null;
  23. switch (geoType) {
  24. case VectorType.BayWindow:
  25. symbol = new BayWindow(start, end, symbolId);
  26. break;
  27. case VectorType.FrenchWindow:
  28. symbol = new FrenchWindow(start, end, symbolId);
  29. break;
  30. case VectorType.SingleDoor:
  31. symbol = new SingleDoor(start, end, symbolId);
  32. break;
  33. case VectorType.DoubleDoor:
  34. symbol = new DoubleDoor(start, end, symbolId);
  35. break;
  36. case VectorType.SlideDoor:
  37. symbol = new SlideDoor(start, end, symbolId);
  38. break;
  39. case VectorType.SingleWindow:
  40. symbol = new SingleWindow(start, end, symbolId);
  41. break;
  42. case VectorType.Pass:
  43. symbol = new Pass(start, end, symbolId);
  44. break;
  45. }
  46. if (symbol != null) {
  47. symbol.setSymbolParent(parent);
  48. symbol.setPoints2d();
  49. this.setPosition3d(symbol);
  50. dataService.addSymbol(symbol);
  51. }
  52. if (parent) {
  53. const wall = dataService.getWall(parent);
  54. wallService.addChildren(wall, symbol.vectorId);
  55. }
  56. symbol.len = mathUtil.getDistance(start, end);
  57. return symbol;
  58. }
  59. addSymbol(position, symbolType, wallId) {
  60. const symbolLen = this.getDefaultSymbolLen(symbolType);
  61. const wall = dataService.getWall(wallId);
  62. const wallLine = wallService.getLine(wall);
  63. position = mathUtil.getJoinLinePoint(position, wallLine);
  64. // const twoParallels = mathUtil.getParallelLineForDistance(vSymbolLine, symbolLen / 2)
  65. // const point1 = mathUtil.getIntersectionPoint(twoParallels.line1, wallLine)
  66. // const point2 = mathUtil.getIntersectionPoint(twoParallels.line2, wallLine)
  67. // 不能超出墙的范围
  68. // const newPositions = this.getNewForContainSymbols(point1, point2, wallId)
  69. // if (wallService.isContain(wall, point1) && wallService.isContain(wall, point2) && newPositions != null && !newPositions.collision) {
  70. // const symbol = this.createSymbol(point1, point2, symbolType, wallId)
  71. // return symbol.vectorId
  72. // }
  73. const newPositions = this.getNewPosForSymbol(
  74. position,
  75. wallId,
  76. null,
  77. symbolLen
  78. );
  79. if (newPositions.state) {
  80. const symbol = this.createSymbol(
  81. newPositions.position1,
  82. newPositions.position2,
  83. symbolType,
  84. wallId
  85. );
  86. return symbol.vectorId;
  87. }
  88. return null;
  89. }
  90. setPosition3d(symbol) {
  91. const mid = {
  92. x: (symbol.startPoint.x + symbol.endPoint.x) / 2,
  93. y: (symbol.startPoint.y + symbol.endPoint.y) / 2,
  94. };
  95. const height = dataService.getFloorHeight();
  96. symbol.position3d = {
  97. x: mid.x,
  98. y: height,
  99. z: -1 * mid.y,
  100. };
  101. }
  102. isSymbol(geoType) {
  103. switch (geoType) {
  104. case "BayWindow":
  105. return true;
  106. case "FrenchWindow":
  107. return true;
  108. case "SingleDoor":
  109. return true;
  110. case "DoubleDoor":
  111. return true;
  112. case "SlideDoor":
  113. return true;
  114. case "SingleWindow":
  115. return true;
  116. case "Pass":
  117. return true;
  118. }
  119. return false;
  120. }
  121. getDefaultSymbolLen(geoType) {
  122. let len = 0;
  123. switch (geoType) {
  124. case "BayWindow":
  125. len = 1.5;
  126. break;
  127. case "FrenchWindow":
  128. len = 1.5;
  129. break;
  130. case "SingleDoor":
  131. len = 0.8;
  132. break;
  133. case "DoubleDoor":
  134. len = 1.5;
  135. break;
  136. case "SlideDoor":
  137. len = 1.5;
  138. break;
  139. case "SingleWindow":
  140. len = 0.8;
  141. break;
  142. case "Pass":
  143. len = 0.8;
  144. break;
  145. }
  146. return len;
  147. }
  148. //从墙上去掉symbol的所属
  149. deleteSymbolForWall(wall, symbolId) {
  150. if (wall) {
  151. let index = wall.children.indexOf(symbolId);
  152. if (index > -1) {
  153. wall.children.splice(index, 1);
  154. }
  155. let symbol = dataService.getSymbol(symbolId);
  156. symbol.parent = null;
  157. }
  158. }
  159. deleteSymbol(symbolId) {
  160. const symbol = dataService.getSymbol(symbolId);
  161. if (symbol.parent) {
  162. let wall = dataService.getWall(symbol.parent);
  163. this.deleteSymbolForWall(wall, symbolId);
  164. }
  165. dataService.deleteSymbol(symbolId);
  166. }
  167. // 更新symbol的归属
  168. changeSymbolForBelong(symbolId, wallId) {
  169. const symbol = dataService.getSymbol(symbolId);
  170. const parentId = symbol.parent;
  171. const parent = dataService.getWall(parentId);
  172. this.deleteSymbolForWall(parent, symbolId);
  173. symbol.setSymbolParent(wallId);
  174. let wall = dataService.getWall(wallId);
  175. wallService.addChildren(wall, symbolId);
  176. }
  177. // 拆分墙的时候,symbol也要相应的改变
  178. // wall拆分成wallId1和wallId2,一般情况wallId和wallId1是相同的
  179. reBelongForSplitWall(wallId, wallId1, wallId2) {
  180. const wall = dataService.getWall(wallId);
  181. for (let i = 0; i < wall.children.length; ++i) {
  182. const symbolId = wall.children[i];
  183. if (wallId != wallId1 && this.isContainSymbolForWall(symbolId, wallId1)) {
  184. this.changeSymbolForBelong(symbolId, wallId1);
  185. } else if (
  186. wallId != wallId2 &&
  187. this.isContainSymbolForWall(symbolId, wallId2)
  188. ) {
  189. this.changeSymbolForBelong(symbolId, wallId2);
  190. }
  191. }
  192. }
  193. // wallId对应的墙是否包含symbol
  194. isContainSymbolForWall(symbolId, wallId) {
  195. const wall = dataService.getWall(wallId);
  196. const symbol = dataService.getSymbol(symbolId);
  197. const point = {
  198. x: (symbol.startPoint.x + symbol.endPoint.x) / 2,
  199. y: (symbol.startPoint.y + symbol.endPoint.y) / 2,
  200. };
  201. if (wallService.isContain(wall, point)) {
  202. return true;
  203. }
  204. }
  205. // 更新symbol的归属
  206. // 墙可能删除了,也可能合并了等等
  207. changeSymbolForBelong(symbolId, wallId) {
  208. const symbol = dataService.getSymbol(symbolId);
  209. const parentId = symbol.parent;
  210. let parent = dataService.getWall(parentId);
  211. this.deleteSymbolForWall(parent, symbolId);
  212. symbol.setSymbolParent(wallId);
  213. let wall = dataService.getWall(wallId);
  214. wallService.addChildren(wall, symbolId);
  215. }
  216. // 墙角pointId移动的时候,周围的symbol都跟着变化
  217. updateSymbolsPositionsForWallCorner(pointId) {
  218. const point = dataService.getPoint(pointId);
  219. const parent = point.parent;
  220. for (const key in parent) {
  221. this.updateSymbolsPositionsForWall(key);
  222. }
  223. }
  224. // wallId对应的wall改变的时候,上面的symbol也跟着改变
  225. updateSymbolsPositionsForWall(wallId) {
  226. const wall = dataService.getWall(wallId);
  227. const symbolIds = wall.children;
  228. for (let i = 0; i < symbolIds.length; ++i) {
  229. const symbol = dataService.getSymbol(symbolIds[i]);
  230. this.updateSEForChangeWall(symbol);
  231. }
  232. }
  233. // 更新Symbold的startPoint,endPoint和points2d,随着wall来
  234. updateSEForChangeWall(symbol) {
  235. const symbolId = symbol.vectorId;
  236. //const symbol = dataService.getSymbol(symbolId);
  237. const wall = dataService.getWall(symbol.parent);
  238. const startPoint = dataService.getPoint(wall.start);
  239. const endPoint = dataService.getPoint(wall.end);
  240. const line = mathUtil.createLine1(startPoint, endPoint);
  241. const newStart = mathUtil.getJoinLinePoint(symbol.startPoint, line);
  242. const newEnd = mathUtil.getJoinLinePoint(symbol.endPoint, line);
  243. const dif = { x: 0, y: 0 };
  244. const min = 0.001; //不要超出一点
  245. let containFlag = true;
  246. if (!wallService.isContain(wall, newStart)) {
  247. // symbol的start与wall的start挨的近
  248. if (
  249. mathUtil.getDistance(newStart, startPoint) <
  250. mathUtil.getDistance(newStart, endPoint)
  251. ) {
  252. dif.x = startPoint.x - newStart.x;
  253. dif.y = startPoint.y - newStart.y;
  254. } else {
  255. dif.x = endPoint.x - newStart.x;
  256. dif.y = endPoint.y - newStart.y;
  257. }
  258. newStart.x += dif.x;
  259. newStart.y += dif.y;
  260. if (
  261. wallService.isContain(wall, {
  262. x: newEnd.x + dif.x,
  263. y: newEnd.y + dif.y,
  264. })
  265. ) {
  266. newEnd.x += dif.x;
  267. newEnd.y += dif.y;
  268. }
  269. containFlag = false;
  270. } else if (!wallService.isContain(wall, newEnd)) {
  271. if (
  272. mathUtil.getDistance(newEnd, startPoint) <
  273. mathUtil.getDistance(newEnd, endPoint)
  274. ) {
  275. dif.x = startPoint.x - newEnd.x;
  276. dif.y = startPoint.y - newEnd.y;
  277. } else {
  278. dif.x = endPoint.x - newEnd.x;
  279. dif.y = endPoint.y - newEnd.y;
  280. }
  281. newEnd.x += dif.x;
  282. newEnd.y += dif.y;
  283. if (
  284. wallService.isContain(wall, {
  285. x: newStart.x + dif.x,
  286. y: newStart.y + dif.y,
  287. })
  288. ) {
  289. newStart.x += dif.x;
  290. newStart.y += dif.y;
  291. }
  292. containFlag = false;
  293. }
  294. // 是否与wall上别的symbol部分重合
  295. if (!containFlag) {
  296. this.updateSEForCollideSymbols(symbolId, newStart, newEnd);
  297. } else {
  298. this.setPosition(symbol, newStart, "start");
  299. this.setPosition(symbol, newEnd, "end");
  300. symbol.setPoints2d();
  301. }
  302. }
  303. //需要考虑碰撞
  304. updateSEForCollideSymbols(symbolId, newStart, newEnd) {
  305. const symbol = dataService.getSymbol(symbolId);
  306. // 是否与wall上别的symbol部分重合
  307. const newPositions = this.getNewForContainSymbols(
  308. newStart,
  309. newEnd,
  310. symbol.parent,
  311. symbolId
  312. );
  313. // if (newPositions != null) {
  314. // this.setPosition(symbol, newPositions.position1, 'start')
  315. // this.setPosition(symbol, newPositions.position2, 'end')
  316. // symbol.setPoints2d()
  317. // }
  318. // if (mathUtil.getDistance(symbol.startPoint, symbol.endPoint) < Constant.minSymbolLen) {
  319. // this.deleteSymbol(symbolId)
  320. // }
  321. if (newPositions != null) {
  322. if (
  323. mathUtil.getDistance(newPositions.position1, newPositions.position2) <
  324. Constant.minSymbolLen
  325. ) {
  326. this.deleteSymbol(symbolId);
  327. } else {
  328. this.setPosition(symbol, newPositions.position1, "start");
  329. this.setPosition(symbol, newPositions.position2, "end");
  330. symbol.setPoints2d();
  331. }
  332. }
  333. }
  334. //position1, position2表示exceptSymbolId新的坐标
  335. getNewForContainSymbols(position1, position2, wallId, exceptSymbolId) {
  336. const min = 0.01;
  337. const wall = dataService.getWall(wallId);
  338. let points = [];
  339. for (let i = 0; i < wall.children.length; ++i) {
  340. const symbolId = wall.children[i];
  341. if (symbolId == exceptSymbolId) {
  342. continue;
  343. }
  344. const symbol = dataService.getSymbol(symbolId);
  345. points.push({
  346. x: symbol.startPoint.x,
  347. y: symbol.startPoint.y,
  348. index: 1,
  349. vectorId: symbolId,
  350. });
  351. points.push({
  352. x: symbol.endPoint.x,
  353. y: symbol.endPoint.y,
  354. index: 2,
  355. vectorId: symbolId,
  356. });
  357. }
  358. points.push({
  359. x: position1.x,
  360. y: position1.y,
  361. index: 1,
  362. vectorId: exceptSymbolId,
  363. });
  364. points.push({
  365. x: position2.x,
  366. y: position2.y,
  367. index: 2,
  368. vectorId: exceptSymbolId,
  369. });
  370. const startPoint = dataService.getPoint(wall.start);
  371. points = points.sort(sortNumber.bind(this));
  372. function sortNumber(a, b) {
  373. return (
  374. mathUtil.getDistance(startPoint, a) -
  375. mathUtil.getDistance(startPoint, b)
  376. );
  377. }
  378. for (let i = 0; i < points.length - 1; ++i) {
  379. if (points[i].vectorId == exceptSymbolId) {
  380. if (i == 0 || i == points.length - 2) {
  381. if (
  382. mathUtil.getDistance(points[i], points[i + 1]) <
  383. Constant.minSymbolLen
  384. ) {
  385. return null;
  386. } else if (points[i + 1].vectorId == exceptSymbolId) {
  387. return {
  388. position1: position1,
  389. position2: { x: points[i + 1].x, y: points[i + 1].y },
  390. };
  391. } else if (points[i + 1].vectorId != exceptSymbolId) {
  392. return {
  393. position1: position1,
  394. position2: { x: points[i + 1].x, y: points[i + 1].y },
  395. collision: true,
  396. };
  397. }
  398. }
  399. //不在其他symbol内部
  400. else if (
  401. points[i + 1].vectorId == exceptSymbolId &&
  402. points[i - 1].vectorId != points[i + 2].vectorId
  403. ) {
  404. if (
  405. mathUtil.getDistance(
  406. { x: points[i - 1].x, y: points[i - 1].y },
  407. { x: points[i + 2].x, y: points[i + 2].y }
  408. ) < Constant.minSymbolLen
  409. ) {
  410. return null;
  411. } else {
  412. return {
  413. position1: { x: points[i - 1].x, y: points[i - 1].y },
  414. position2: { x: points[i + 2].x, y: points[i + 2].y },
  415. //collision: true,
  416. };
  417. }
  418. }
  419. }
  420. }
  421. return null;
  422. }
  423. getNewPosForSymbol(point, wallId, exceptSymbolId, currentSymbolLen) {
  424. const wall = dataService.getWall(wallId);
  425. const startPoint = dataService.getPoint(wall.start);
  426. const endPoint = dataService.getPoint(wall.end);
  427. const wallLine = wallService.getLine(wall);
  428. const vSymbolLine = mathUtil.getVerticalLine(wallLine, point);
  429. let symbolLen = currentSymbolLen;
  430. if (exceptSymbolId) {
  431. const currentSymbol = dataService.getSymbol(exceptSymbolId);
  432. symbolLen = currentSymbol.len;
  433. }
  434. const twoParallels = mathUtil.getParallelLineForDistance(
  435. vSymbolLine,
  436. symbolLen / 2
  437. );
  438. let point1 = mathUtil.getIntersectionPoint(twoParallels.line1, wallLine);
  439. let point2 = mathUtil.getIntersectionPoint(twoParallels.line2, wallLine);
  440. //如果在墙外部,就平移到墙内部
  441. if (mathUtil.getDistance(startPoint, endPoint) < symbolLen) {
  442. mathUtil.clonePoint(point1, startPoint);
  443. mathUtil.clonePoint(point2, endPoint);
  444. } else {
  445. let dx, dy;
  446. let _point1 = {};
  447. let _point2 = {};
  448. if (!wallService.isContain(wall, point1)) {
  449. dx = startPoint.x - point1.x;
  450. dy = startPoint.y - point1.y;
  451. _point2.x = point2.x + dx;
  452. _point2.y = point2.y + dy;
  453. if (!wallService.isContain(wall, _point2)) {
  454. dx = endPoint.x - point1.x;
  455. dy = endPoint.y - point1.y;
  456. point2.x += dx;
  457. point2.y += dy;
  458. mathUtil.clonePoint(point1, endPoint);
  459. } else {
  460. point2.x += dx;
  461. point2.y += dy;
  462. mathUtil.clonePoint(point1, startPoint);
  463. }
  464. } else if (!wallService.isContain(wall, point2)) {
  465. dx = startPoint.x - point2.x;
  466. dy = startPoint.y - point2.y;
  467. _point1.x = point1.x + dx;
  468. _point1.y = point1.y + dy;
  469. if (!wallService.isContain(wall, _point1)) {
  470. dx = endPoint.x - point2.x;
  471. dy = endPoint.y - point2.y;
  472. point1.x += dx;
  473. point1.y += dy;
  474. mathUtil.clonePoint(point2, endPoint);
  475. } else {
  476. point1.x += dx;
  477. point1.y += dy;
  478. mathUtil.clonePoint(point2, startPoint);
  479. }
  480. }
  481. }
  482. let points = [];
  483. for (let i = 0; i < wall.children.length; ++i) {
  484. const symbolId = wall.children[i];
  485. if (symbolId == exceptSymbolId) {
  486. continue;
  487. }
  488. const symbol = dataService.getSymbol(symbolId);
  489. points.push({
  490. x: symbol.startPoint.x,
  491. y: symbol.startPoint.y,
  492. index: 1, //表示start
  493. vectorId: symbolId,
  494. });
  495. points.push({
  496. x: symbol.endPoint.x,
  497. y: symbol.endPoint.y,
  498. index: 2, //表示end
  499. vectorId: symbolId,
  500. });
  501. }
  502. points.push({
  503. x: startPoint.x,
  504. y: startPoint.y,
  505. index: 1,
  506. vectorId: wallId,
  507. type: VectorType.Wall,
  508. });
  509. points.push({
  510. x: endPoint.x,
  511. y: endPoint.y,
  512. index: 2,
  513. vectorId: wallId,
  514. type: VectorType.Wall,
  515. });
  516. points = points.sort(sortNumber.bind(this));
  517. function sortNumber(a, b) {
  518. return (
  519. mathUtil.getDistance(startPoint, a) -
  520. mathUtil.getDistance(startPoint, b)
  521. );
  522. }
  523. let flag = true;
  524. for (let i = 0; i < points.length - 1; ++i) {
  525. if (mathUtil.isContainForSegment(point, points[i], points[i + 1])) {
  526. if (mathUtil.getDistance(points[i], points[i + 1]) > symbolLen) {
  527. //完全在一个symbol内部或者symbol内有其他的symbol
  528. if (
  529. points[i].vectorId == points[i + 1].vectorId &&
  530. points[i].type != VectorType.Wall
  531. ) {
  532. return {
  533. position1: point1,
  534. position2: point2,
  535. collision: true,
  536. state: false,
  537. };
  538. }
  539. //完全在wall内部
  540. else if (
  541. points[i].vectorId == points[i + 1].vectorId &&
  542. points[i].type == VectorType.Wall
  543. ) {
  544. return {
  545. position1: point1,
  546. position2: point2,
  547. collision: true,
  548. state: true,
  549. };
  550. }
  551. //一端在墙/门/窗外部
  552. else if (
  553. !mathUtil.isContainForSegment(point1, points[i], points[i + 1]) ||
  554. !mathUtil.isContainForSegment(point2, points[i], points[i + 1])
  555. ) {
  556. return {
  557. position1: point1,
  558. position2: point2,
  559. collision: true,
  560. state: false,
  561. };
  562. }
  563. } else if (
  564. mathUtil.getDistance(points[i], points[i + 1]) < Constant.minSymbolLen
  565. ) {
  566. return {
  567. position1: point1,
  568. position2: point2,
  569. collision: true,
  570. state: false,
  571. };
  572. }
  573. //大于最小距离,小于本来的长度。
  574. else if (points[i].vectorId != points[i + 1].vectorId) {
  575. return {
  576. position1: { x: points[i].x, y: points[i].y },
  577. position2: { x: points[i + 1].x, y: points[i + 1].y },
  578. collision: true,
  579. state: true,
  580. };
  581. }
  582. //完全在一个symbol内部
  583. else if (
  584. points[i].vectorId == points[i + 1].vectorId &&
  585. points[i].type != VectorType.Wall
  586. ) {
  587. return {
  588. position1: point1,
  589. position2: point2,
  590. collision: true,
  591. state: false,
  592. };
  593. } else if (
  594. points[i].vectorId == points[i + 1].vectorId &&
  595. points[i].type == VectorType.Wall
  596. ) {
  597. return {
  598. position1: { x: points[i].x, y: points[i].y },
  599. position2: { x: points[i + 1].x, y: points[i + 1].y },
  600. collision: true,
  601. state: true,
  602. };
  603. }
  604. flag = false;
  605. } else if (mathUtil.getDistance(point, points[i]) < Constant.minAdsorb) {
  606. return {
  607. position1: point1,
  608. position2: point2,
  609. collision: true,
  610. state: false,
  611. };
  612. }
  613. }
  614. if (flag) {
  615. return {
  616. position1: point1,
  617. position2: point2,
  618. collision: false,
  619. state: true,
  620. };
  621. } else {
  622. //console.error(566)
  623. return {
  624. position1: point1,
  625. position2: point2,
  626. collision: false,
  627. state: true,
  628. };
  629. }
  630. // return {
  631. // position1: point1,
  632. // position2: point2,
  633. // collision: false,
  634. // state: true,
  635. // }
  636. }
  637. setPosition(symbol, position, dir) {
  638. if (dir == "start") {
  639. mathUtil.clonePoint(symbol.startPoint, position);
  640. } else if (dir == "end") {
  641. mathUtil.clonePoint(symbol.endPoint, position);
  642. }
  643. }
  644. // 只考虑symbol的端点可能不在墙面上了,这时候要更新
  645. // 用在移动墙面的时候,邻居墙的symbols可能要变
  646. updateSymbolsPositionsForNeighWall(wallId) {
  647. const wall = dataService.getWall(wallId);
  648. const symbolIds = wall.children;
  649. for (let i = 0; i < symbolIds.length; ++i) {
  650. this.updateSEForWallSize(symbolIds[i]);
  651. }
  652. }
  653. // 更新symbol的start或者end,一般是symbol的端点在墙外了
  654. updateSEForWallSize(symbolId) {
  655. const symbol = dataService.getSymbol(symbolId);
  656. const wall = dataService.getWall(symbol.parent);
  657. const startPoint = dataService.getPoint(wall.start);
  658. const endPoint = dataService.getPoint(wall.end);
  659. const newStart = {
  660. x: symbol.startPoint.x,
  661. y: symbol.startPoint.y,
  662. };
  663. const newEnd = {
  664. x: symbol.endPoint.x,
  665. y: symbol.endPoint.y,
  666. };
  667. const dif = { x: 0, y: 0 };
  668. if (!wallService.isContain(wall, newStart)) {
  669. // symbol的start与wall的start挨的近
  670. if (
  671. mathUtil.getDistance(newStart, startPoint) <
  672. mathUtil.getDistance(newStart, endPoint)
  673. ) {
  674. dif.x = startPoint.x - newStart.x;
  675. dif.y = startPoint.y - newStart.y;
  676. } else {
  677. dif.x = endPoint.x - newStart.x;
  678. dif.y = endPoint.y - newStart.y;
  679. }
  680. newStart.x += dif.x;
  681. newStart.y += dif.y;
  682. } else if (!wallService.isContain(wall, newEnd)) {
  683. if (
  684. mathUtil.getDistance(newEnd, startPoint) <
  685. mathUtil.getDistance(newEnd, endPoint)
  686. ) {
  687. dif.x = startPoint.x - newEnd.x;
  688. dif.y = startPoint.y - newEnd.y;
  689. } else {
  690. dif.x = endPoint.x - newEnd.x;
  691. dif.y = endPoint.y - newEnd.y;
  692. }
  693. newEnd.x += dif.x;
  694. newEnd.y += dif.y;
  695. } else {
  696. return null;
  697. }
  698. this.updateSEForCollideSymbols(symbolId, newStart, newEnd);
  699. }
  700. updateSymbolForLen(symbolId, len) {
  701. const symbol = dataService.getSymbol(symbolId);
  702. const start = symbol.startPoint;
  703. const end = symbol.endPoint;
  704. const line = mathUtil.createLine1(start, end);
  705. const midPoint = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 };
  706. const vertLine = mathUtil.getVerticalLine(line, midPoint);
  707. const wall = dataService.getWall(symbol.parent);
  708. const startPoint = dataService.getPoint(wall.start);
  709. const endPoint = dataService.getPoint(wall.end);
  710. if (len == null || typeof len === "undefined") {
  711. len = mathUtil.getDistance(start, end);
  712. const distance = mathUtil.getDistance(startPoint, endPoint);
  713. if (len > distance) {
  714. len = distance;
  715. }
  716. }
  717. const lines = mathUtil.getParallelLineForDistance(vertLine, len / 2);
  718. const join1 = mathUtil.getIntersectionPoint(lines.line1, line);
  719. const join2 = mathUtil.getIntersectionPoint(lines.line2, line);
  720. const symbolInfo = {};
  721. if (
  722. mathUtil.getDistance(start, join1) < mathUtil.getDistance(start, join2)
  723. ) {
  724. symbolInfo.start = join1;
  725. symbolInfo.end = join2;
  726. } else {
  727. symbolInfo.start = join2;
  728. symbolInfo.end = join1;
  729. }
  730. let startFlag = false;
  731. let endFlag = false;
  732. let dx, dy;
  733. const nearestPosition = this.getNearestPosition(
  734. symbol.parent,
  735. symbolId,
  736. true
  737. );
  738. if (
  739. nearestPosition.startPosition != null &&
  740. mathUtil.PointInSegment(
  741. nearestPosition.startPosition,
  742. symbolInfo.start,
  743. symbolInfo.end
  744. )
  745. ) {
  746. // start堵住了,end需要增加
  747. //dx = symbolInfo.end.x - symbol.endPoint.x
  748. //dy = symbolInfo.end.y - symbol.endPoint.y
  749. dx = symbolInfo.start.x - nearestPosition.startPosition.x;
  750. dy = symbolInfo.start.y - nearestPosition.startPosition.y;
  751. mathUtil.clonePoint(symbolInfo.start, nearestPosition.startPosition);
  752. symbolInfo.end.x -= dx;
  753. symbolInfo.end.y -= dy;
  754. startFlag = true;
  755. }
  756. if (
  757. nearestPosition.endPosition != null &&
  758. mathUtil.PointInSegment(
  759. nearestPosition.endPosition,
  760. symbolInfo.start,
  761. symbolInfo.end
  762. )
  763. ) {
  764. // end堵住了,start需要增加
  765. dx = symbolInfo.end.x - nearestPosition.endPosition.x;
  766. dy = symbolInfo.end.y - nearestPosition.endPosition.y;
  767. mathUtil.clonePoint(symbolInfo.end, nearestPosition.endPosition);
  768. if (!startFlag) {
  769. symbolInfo.start.x -= dx;
  770. symbolInfo.start.y -= dy;
  771. //这时候可能start又超出范围了
  772. if (
  773. mathUtil.PointInSegment(
  774. nearestPosition.startPosition,
  775. symbolInfo.start,
  776. symbolInfo.end
  777. )
  778. ) {
  779. mathUtil.clonePoint(symbolInfo.start, nearestPosition.startPosition);
  780. startFlag = true;
  781. }
  782. }
  783. endFlag = true;
  784. }
  785. symbolInfo.vectorId = symbolId;
  786. mathUtil.clonePoint(symbol.startPoint, symbolInfo.start);
  787. mathUtil.clonePoint(symbol.endPoint, symbolInfo.end);
  788. symbol.setPoints2d();
  789. return {
  790. block: startFlag & endFlag,
  791. start: symbolInfo.start,
  792. end: symbolInfo.end,
  793. };
  794. }
  795. getNearestPosition(wallId, symbolId, isExceedWall, position1, position2) {
  796. const wall = dataService.getWall(wallId);
  797. const startPoint = dataService.getPoint(wall.start);
  798. const endPoint = dataService.getPoint(wall.end);
  799. const symbolIds = wall.children;
  800. let symbol = dataService.getSymbol(symbolId);
  801. if (!symbol && !symbolId) {
  802. symbol = {};
  803. symbol = {
  804. struct: {},
  805. };
  806. symbol.startPoint = position1;
  807. symbol.endPoint = position2;
  808. }
  809. let minSdis = 10000;
  810. let minEdis = 10000;
  811. let startPosition = null;
  812. let endPosition = null;
  813. // 与startPosition同属symbol端点(另一头)
  814. let startPosition2 = null;
  815. // 与endPosition同属symbol端点(另一头)
  816. let endPosition2 = null;
  817. for (let i = 0; i < symbolIds.length; ++i) {
  818. if (symbolIds[i] == symbolId) {
  819. continue;
  820. }
  821. const otherSymbol = dataService.getSymbol(symbolIds[i]);
  822. const dis1 = mathUtil.getDistance(
  823. symbol.startPoint,
  824. otherSymbol.startPoint
  825. );
  826. const dis2 = mathUtil.getDistance(
  827. symbol.startPoint,
  828. otherSymbol.endPoint
  829. );
  830. if (minSdis > Math.min(dis1, dis2)) {
  831. if (dis1 < dis2) {
  832. startPosition = otherSymbol.startPoint;
  833. startPosition2 = otherSymbol.endPoint;
  834. } else {
  835. startPosition = otherSymbol.endPoint;
  836. startPosition2 = otherSymbol.startPoint;
  837. }
  838. if (
  839. mathUtil.getDistance(symbol.startPoint, startPosition) >
  840. mathUtil.getDistance(symbol.endPoint, startPosition)
  841. ) {
  842. startPosition = null;
  843. startPosition2 = null;
  844. } else {
  845. minSdis = Math.min(dis1, dis2);
  846. }
  847. }
  848. const dis3 = mathUtil.getDistance(
  849. symbol.endPoint,
  850. otherSymbol.startPoint
  851. );
  852. const dis4 = mathUtil.getDistance(symbol.endPoint, otherSymbol.endPoint);
  853. if (minEdis > Math.min(dis3, dis4)) {
  854. if (dis3 < dis4) {
  855. endPosition = otherSymbol.startPoint;
  856. endPosition2 = otherSymbol.endPoint;
  857. } else {
  858. endPosition = otherSymbol.endPoint;
  859. endPosition2 = otherSymbol.startPoint;
  860. }
  861. if (
  862. mathUtil.getDistance(symbol.endPoint, endPosition) >
  863. mathUtil.getDistance(symbol.startPoint, endPosition)
  864. ) {
  865. endPosition = null;
  866. endPosition2 = null;
  867. } else {
  868. minEdis = Math.min(dis3, dis4);
  869. }
  870. }
  871. }
  872. if (isExceedWall) {
  873. if (startPosition == null) {
  874. if (
  875. mathUtil.getDistance(startPoint, symbol.startPoint) >
  876. mathUtil.getDistance(startPoint, symbol.endPoint)
  877. ) {
  878. startPosition = endPoint;
  879. startPosition2 = endPoint;
  880. } else {
  881. startPosition = startPoint;
  882. startPosition2 = startPoint;
  883. }
  884. }
  885. if (endPosition == null) {
  886. if (
  887. mathUtil.getDistance(startPoint, symbol.startPoint) >
  888. mathUtil.getDistance(startPoint, symbol.endPoint)
  889. ) {
  890. endPosition = startPoint;
  891. endPosition2 = startPoint;
  892. } else {
  893. endPosition = endPoint;
  894. endPosition2 = endPoint;
  895. }
  896. }
  897. }
  898. return {
  899. startPosition: startPosition,
  900. startPosition2: startPosition2,
  901. endPosition: endPosition,
  902. endPosition2: endPosition2,
  903. };
  904. }
  905. // point是目标点,selectState表示start还是end
  906. // 只是不允许start和end互换位置
  907. moveSymbolSinglePoint(targetPosition, symbolId, selectState) {
  908. const symbol = dataService.getSymbol(symbolId);
  909. const symbolLine = mathUtil.createLine1(symbol.startPoint, symbol.endPoint);
  910. const vSymbolLine = mathUtil.getVerticalLine(symbolLine, targetPosition);
  911. targetPosition = mathUtil.getIntersectionPoint(vSymbolLine, symbolLine);
  912. const midPoint = {
  913. x: (symbol.startPoint.x + symbol.endPoint.x) / 2,
  914. y: (symbol.startPoint.y + symbol.endPoint.y) / 2,
  915. };
  916. // 是否超过了wall外
  917. const wall = dataService.getWall(symbol.parent);
  918. const startPoint = dataService.getPoint(wall.start);
  919. const endPoint = dataService.getPoint(wall.end);
  920. if (selectState == "start") {
  921. // symbol的start和end位置交换了
  922. if (!mathUtil.PointInSegment(midPoint, targetPosition, symbol.endPoint)) {
  923. return null;
  924. } else {
  925. // start-start
  926. if (
  927. mathUtil.getDistance(symbol.startPoint, startPoint) <
  928. mathUtil.getDistance(symbol.endPoint, startPoint)
  929. ) {
  930. // 超出了
  931. if (
  932. mathUtil.getDistance(targetPosition, midPoint) >
  933. mathUtil.getDistance(startPoint, midPoint)
  934. ) {
  935. mathUtil.clonePoint(targetPosition, startPoint);
  936. }
  937. }
  938. // start-end
  939. else {
  940. // 超出了
  941. if (
  942. mathUtil.getDistance(targetPosition, midPoint) >
  943. mathUtil.getDistance(endPoint, midPoint)
  944. ) {
  945. mathUtil.clonePoint(targetPosition, endPoint);
  946. }
  947. }
  948. }
  949. } else if (selectState == "end") {
  950. // symbol的start和end位置交换了
  951. if (
  952. !mathUtil.PointInSegment(midPoint, targetPosition, symbol.startPoint)
  953. ) {
  954. return null;
  955. } else {
  956. // start-start
  957. if (
  958. mathUtil.getDistance(symbol.endPoint, endPoint) <
  959. mathUtil.getDistance(symbol.startPoint, endPoint)
  960. ) {
  961. // 超出了
  962. if (
  963. mathUtil.getDistance(targetPosition, midPoint) >
  964. mathUtil.getDistance(endPoint, midPoint)
  965. ) {
  966. mathUtil.clonePoint(targetPosition, endPoint);
  967. }
  968. }
  969. // start-end
  970. else {
  971. // 超出了
  972. if (
  973. mathUtil.getDistance(targetPosition, midPoint) >
  974. mathUtil.getDistance(startPoint, midPoint)
  975. ) {
  976. mathUtil.clonePoint(targetPosition, startPoint);
  977. }
  978. }
  979. }
  980. }
  981. return {
  982. dir: selectState,
  983. position: targetPosition,
  984. };
  985. }
  986. setSymbolInfo(symbolInfo) {
  987. let symbol = dataService.getSymbol(symbolInfo.vectorId);
  988. symbol.openSide = symbolInfo.openSide;
  989. symbol.startPoint = symbolInfo.start;
  990. symbol.endPoint = symbolInfo.end;
  991. symbol.points2d = JSON.parse(JSON.stringify(symbolInfo.points2d));
  992. symbol.enter = symbolInfo.enter;
  993. symbol.parent = symbolInfo.parent;
  994. return symbol;
  995. }
  996. setEnterImg(img) {
  997. this.enterImg = img;
  998. }
  999. getEnterImg() {
  1000. return this.enterImg;
  1001. }
  1002. createSymbolFromPanorama(raycaster, geoType, panoId) {
  1003. //console.log(raycaster, geoType)
  1004. let joinsInfo = [];
  1005. const start = {
  1006. x: raycaster.ray.origin.x,
  1007. y: -1 * raycaster.ray.origin.z,
  1008. };
  1009. // const end = {
  1010. // x: raycaster.ray.origin.x + raycaster.ray.direction.x,
  1011. // y: -1 * (raycaster.ray.origin.z + raycaster.ray.direction.z),
  1012. // }
  1013. const walls = dataService.getWalls();
  1014. for (const wallId in walls) {
  1015. const wall = dataService.getWall(wallId);
  1016. const startPoint = dataService.getPoint(wall.start);
  1017. const endPoint = dataService.getPoint(wall.end);
  1018. const join = mathUtil.raySegmentIntersection(
  1019. start,
  1020. raycaster.ray.direction,
  1021. startPoint,
  1022. endPoint
  1023. );
  1024. if (join != null) {
  1025. joinsInfo.push({
  1026. wallId: wallId,
  1027. join: join,
  1028. });
  1029. }
  1030. }
  1031. if (joinsInfo.length > 0) {
  1032. joinsInfo = joinsInfo.sort(sortNumber.bind(this));
  1033. function sortNumber(a, b) {
  1034. return (
  1035. mathUtil.getDistance(start, a.join) -
  1036. mathUtil.getDistance(start, b.join)
  1037. );
  1038. }
  1039. const symbolId = this.addSymbol(
  1040. joinsInfo[0].join,
  1041. geoType,
  1042. joinsInfo[0].wallId
  1043. );
  1044. if (symbolId != null) {
  1045. moveSymbol.moveFullSymbol(
  1046. joinsInfo[0].join,
  1047. symbolId,
  1048. joinsInfo[0].wallId
  1049. );
  1050. const symbol = dataService.getSymbol(symbolId);
  1051. return symbolId;
  1052. } else {
  1053. console.error("漫游模式下添加门/窗:门/窗区域太小,加不上");
  1054. return null;
  1055. }
  1056. } else {
  1057. console.error("漫游模式下添加门/窗:没有与任何墙相交");
  1058. return null;
  1059. }
  1060. }
  1061. }
  1062. const symbolService = new SymbolService();
  1063. export { symbolService };