build-dxf 0.0.22 → 0.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/build.js CHANGED
@@ -1,17 +1,17 @@
1
- import * as M from "three";
2
- import { EventDispatcher as tt } from "three";
3
- import F from "clipper-lib";
4
- import R from "dxf-writer";
5
- import { OBJExporter as et } from "three/examples/jsm/exporters/OBJExporter.js";
6
- import { GLTFExporter as nt } from "three/examples/jsm/exporters/GLTFExporter.js";
7
- function N() {
8
- return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(g) {
9
- var t = Math.random() * 16 | 0, e = g == "x" ? t : t & 3 | 8;
1
+ import * as q from "three";
2
+ import { EventDispatcher as ot } from "three";
3
+ import Z from "clipper-lib";
4
+ import W from "dxf-writer";
5
+ import { OBJExporter as rt } from "three/examples/jsm/exporters/OBJExporter.js";
6
+ import { GLTFExporter as at } from "three/examples/jsm/exporters/GLTFExporter.js";
7
+ function k() {
8
+ return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(M) {
9
+ var t = Math.random() * 16 | 0, e = M == "x" ? t : t & 3 | 8;
10
10
  return e.toString(16);
11
11
  });
12
12
  }
13
- class $ extends tt {
14
- uuid = N();
13
+ class tt extends ot {
14
+ uuid = k();
15
15
  addEventListener(t, e, n) {
16
16
  const { once: i = !1 } = n ?? {}, s = (r) => {
17
17
  e(r), i && o();
@@ -31,7 +31,7 @@ class $ extends tt {
31
31
  e && (e.forEach((n) => n()), this.eventRecordStack.delete(t));
32
32
  }
33
33
  }
34
- class q extends $ {
34
+ class V extends tt {
35
35
  parent;
36
36
  destroyed = !1;
37
37
  constructor(...t) {
@@ -49,7 +49,7 @@ class q extends $ {
49
49
  this.destroyed = !0;
50
50
  }
51
51
  }
52
- class it extends $ {
52
+ class ct extends tt {
53
53
  static EventType = {
54
54
  ADD_COMPONENT: "addComponent"
55
55
  };
@@ -72,7 +72,7 @@ class it extends $ {
72
72
  * @param component
73
73
  */
74
74
  removeComponent(t) {
75
- if (t instanceof q) {
75
+ if (t instanceof V) {
76
76
  const e = this.components.indexOf(t);
77
77
  e > -1 && (this.components.splice(e, 1), this.dispatchEvent({
78
78
  type: "removeComponent",
@@ -117,7 +117,7 @@ class it extends $ {
117
117
  return e || null;
118
118
  }
119
119
  }
120
- class p {
120
+ class g {
121
121
  x;
122
122
  y;
123
123
  get X() {
@@ -150,7 +150,7 @@ class p {
150
150
  * @returns
151
151
  */
152
152
  equal(t) {
153
- return t.x === this.x && t.y === this.y;
153
+ return Math.abs(t.x - this.x) < 1e-9 && Math.abs(t.y - this.y) < 1e-9;
154
154
  }
155
155
  /**
156
156
  *
@@ -207,8 +207,8 @@ class p {
207
207
  * @param angle 旋转角度,单位为弧度
208
208
  */
209
209
  rotate(t, e) {
210
- const n = this.x - t.x, i = this.y - t.y, s = Math.cos(e), o = Math.sin(e), r = n * s - i * o, a = n * o + i * s;
211
- return this.x = r + t.x, this.y = a + t.y, this;
210
+ const n = this.x - t.x, i = this.y - t.y, s = Math.cos(e), o = Math.sin(e), r = n * s - i * o, l = n * o + i * s;
211
+ return this.x = r + t.x, this.y = l + t.y, this;
212
212
  }
213
213
  /**
214
214
  * 保留小数位数
@@ -234,7 +234,7 @@ class p {
234
234
  */
235
235
  normal(t) {
236
236
  const e = this.x - t.x, n = this.y - t.y, i = Math.sqrt(e * e + n * n), s = -n / i, o = e / i;
237
- return new p(s, o);
237
+ return new g(s, o);
238
238
  }
239
239
  /**
240
240
  * 获取由传入的点到该点的单位方向向量
@@ -244,7 +244,7 @@ class p {
244
244
  */
245
245
  direction(t) {
246
246
  const e = this.x - t.x, n = this.y - t.y, i = Math.sqrt(e * e + n * n);
247
- return i === 0 ? new p(0, 0) : new p(e / i, n / i);
247
+ return i === 0 ? new g(0, 0) : new g(e / i, n / i);
248
248
  }
249
249
  /**
250
250
  * 计算模长
@@ -279,8 +279,8 @@ class p {
279
279
  angleBetween(t, e = "radian", n = "180") {
280
280
  const i = this.dot(t), s = this.magnitude(), o = t.magnitude();
281
281
  if (s === 0 || o === 0) return 0;
282
- const r = i / (s * o), a = Math.max(-1, Math.min(1, r));
283
- return e === "radian" ? Math.acos(a) : e === "cos" ? a : n === "180" || this.cross(t) < 0 ? Math.acos(a) / (Math.PI / 180) : 360 - Math.acos(a) / (Math.PI / 180);
282
+ const r = i / (s * o), l = Math.max(-1, Math.min(1, r));
283
+ return e === "radian" ? Math.acos(l) : e === "cos" ? l : n === "180" || this.cross(t) < 0 ? Math.acos(l) / (Math.PI / 180) : 360 - Math.acos(l) / (Math.PI / 180);
284
284
  }
285
285
  /** 获取向量长度
286
286
  */
@@ -302,7 +302,7 @@ class p {
302
302
  * @returns
303
303
  */
304
304
  clone() {
305
- return new p(this.x, this.y);
305
+ return new g(this.x, this.y);
306
306
  }
307
307
  /**
308
308
  * 克隆
@@ -319,23 +319,23 @@ class p {
319
319
  };
320
320
  }
321
321
  static from(t) {
322
- return Array.isArray(t) ? new p(t[0], t[1]) : "x" in t && "y" in t ? new p(t.x, t.y) : "X" in t && "Y" in t ? new p(t.X, t.Y) : this.zero();
322
+ return Array.isArray(t) ? new g(t[0], t[1]) : "x" in t && "y" in t ? new g(t.x, t.y) : "X" in t && "Y" in t ? new g(t.X, t.Y) : this.zero();
323
323
  }
324
324
  static zero() {
325
- return new p(0, 0);
325
+ return new g(0, 0);
326
326
  }
327
327
  }
328
- class v {
328
+ class C {
329
329
  minX = 0;
330
330
  maxX = 0;
331
331
  minY = 0;
332
332
  maxY = 0;
333
333
  get points() {
334
334
  return [
335
- new p(this.minX, this.minY),
336
- new p(this.maxX, this.minY),
337
- new p(this.maxX, this.maxY),
338
- new p(this.minX, this.maxY)
335
+ new g(this.minX, this.minY),
336
+ new g(this.maxX, this.minY),
337
+ new g(this.maxX, this.maxY),
338
+ new g(this.minX, this.maxY)
339
339
  ];
340
340
  }
341
341
  get width() {
@@ -345,7 +345,7 @@ class v {
345
345
  return this.maxY - this.minY;
346
346
  }
347
347
  get center() {
348
- return new p(
348
+ return new g(
349
349
  this.minX + (this.maxX - this.minX) * 0.5,
350
350
  this.minY + (this.maxY - this.minY) * 0.5
351
351
  );
@@ -376,13 +376,13 @@ class v {
376
376
  return this.minX <= e.x && e.x <= this.maxX && this.minY <= e.y && e.y <= this.maxY;
377
377
  let o = Number.NEGATIVE_INFINITY, r = Number.POSITIVE_INFINITY;
378
378
  if (i !== 0) {
379
- const a = (this.minX - e.x) / i, c = (this.maxX - e.x) / i;
380
- o = Math.max(o, Math.min(a, c)), r = Math.min(r, Math.max(a, c));
379
+ const l = (this.minX - e.x) / i, c = (this.maxX - e.x) / i;
380
+ o = Math.max(o, Math.min(l, c)), r = Math.min(r, Math.max(l, c));
381
381
  } else if (e.x < this.minX || e.x > this.maxX)
382
382
  return !1;
383
383
  if (s !== 0) {
384
- const a = (this.minY - e.y) / s, c = (this.maxY - e.y) / s;
385
- o = Math.max(o, Math.min(a, c)), r = Math.min(r, Math.max(a, c));
384
+ const l = (this.minY - e.y) / s, c = (this.maxY - e.y) / s;
385
+ o = Math.max(o, Math.min(l, c)), r = Math.min(r, Math.max(l, c));
386
386
  } else if (e.y < this.minY || e.y > this.maxY)
387
387
  return !1;
388
388
  return o <= r && o <= 1 && r >= 0;
@@ -400,37 +400,45 @@ class v {
400
400
  * @param rectangle
401
401
  */
402
402
  intersectRectangle(t) {
403
- const e = (o) => this.minX <= o.x && o.x <= this.maxX && this.minY <= o.y && o.y <= this.maxY, n = (o) => {
404
- let r = 0;
405
- for (let a = 0; a < 4; a++) {
406
- const c = t.points[a], h = t.points[(a + 1) % 4], l = { x: h.x - c.x, y: h.y - c.y }, d = { x: o.x - c.x, y: o.y - c.y }, f = l.x * d.y - l.y * d.x;
403
+ const e = t.points;
404
+ let n = e[0].x, i = e[0].y, s = e[0].x, o = e[0].y;
405
+ for (let c = 1; c < 4; c++) {
406
+ const a = e[c];
407
+ a.x < n && (n = a.x), a.y < i && (i = a.y), a.x > s && (s = a.x), a.y > o && (o = a.y);
408
+ }
409
+ if (this.maxX < n || this.minX > s || this.maxY < i || this.minY > o)
410
+ return !1;
411
+ const r = this.points;
412
+ for (let c = 0; c < 4; c++) {
413
+ const a = r[c], h = r[(c + 1) % 4];
414
+ for (let d = 0; d < 4; d++) {
415
+ const u = e[d], f = e[(d + 1) % 4], y = (h.x - a.x) * (u.y - a.y) - (h.y - a.y) * (u.x - a.x), p = (h.x - a.x) * (f.y - a.y) - (h.y - a.y) * (f.x - a.x), x = (f.x - u.x) * (a.y - u.y) - (f.y - u.y) * (a.x - u.x), D = (f.x - u.x) * (h.y - u.y) - (f.y - u.y) * (h.x - u.x);
416
+ if (y * p < 0 && x * D < 0 || y === 0 && Math.min(a.x, h.x) <= u.x && u.x <= Math.max(a.x, h.x) && Math.min(a.y, h.y) <= u.y && u.y <= Math.max(a.y, h.y) || p === 0 && Math.min(a.x, h.x) <= f.x && f.x <= Math.max(a.x, h.x) && Math.min(a.y, h.y) <= f.y && f.y <= Math.max(a.y, h.y) || x === 0 && Math.min(u.x, f.x) <= a.x && a.x <= Math.max(u.x, f.x) && Math.min(u.y, f.y) <= a.y && a.y <= Math.max(u.y, f.y) || D === 0 && Math.min(u.x, f.x) <= h.x && h.x <= Math.max(u.x, f.x) && Math.min(u.y, f.y) <= h.y && h.y <= Math.max(u.y, f.y))
417
+ return !0;
418
+ }
419
+ }
420
+ for (let c = 0; c < 4; c++) {
421
+ const a = e[c];
422
+ if (a.x >= this.minX && a.x <= this.maxX && a.y >= this.minY && a.y <= this.maxY)
423
+ return !0;
424
+ }
425
+ const l = (c) => {
426
+ let a = 0;
427
+ for (let h = 0; h < 4; h++) {
428
+ const d = e[h], u = e[(h + 1) % 4], f = (u.x - d.x) * (c.y - d.y) - (u.y - d.y) * (c.x - d.x);
407
429
  if (f === 0) {
408
- const m = l.x !== 0 ? (o.x - c.x) / l.x : (o.y - c.y) / l.y;
409
- if (m >= 0 && m <= 1) return !0;
430
+ const y = Math.abs(u.x - d.x) > 1e-10 ? u.x - d.x : u.y - d.y, p = y ? (c.x - d.x) / y : 0;
431
+ if (p >= 0 && p <= 1) return !0;
410
432
  } else {
411
- const m = f > 0 ? 1 : -1;
412
- if (r === 0 && (r = m), r !== m) return !1;
433
+ const y = f > 0 ? 1 : -1;
434
+ if (a === 0) a = y;
435
+ else if (a !== y) return !1;
413
436
  }
414
437
  }
415
438
  return !0;
416
- }, i = (o, r, a, c) => {
417
- const h = (u, x, w) => {
418
- const S = (x.y - u.y) * (w.x - x.x) - (x.x - u.x) * (w.y - x.y);
419
- return S === 0 ? 0 : S > 0 ? 1 : 2;
420
- }, l = (u, x, w) => Math.min(u.x, w.x) <= x.x && x.x <= Math.max(u.x, w.x) && Math.min(u.y, w.y) <= x.y && x.y <= Math.max(u.y, w.y), d = h(o, r, a), f = h(o, r, c), m = h(a, c, o), y = h(a, c, r);
421
- return !!(d !== f && m !== y || d === 0 && l(o, a, r) || f === 0 && l(o, c, r) || m === 0 && l(a, o, c) || y === 0 && l(a, r, c));
422
- }, s = this.points;
423
- for (let o = 0; o < 4; o++) {
424
- const r = s[o], a = s[(o + 1) % 4];
425
- for (let c = 0; c < 4; c++) {
426
- const h = t.points[c], l = t.points[(c + 1) % 4];
427
- if (i(r, a, h, l)) return !0;
428
- }
429
- }
430
- for (let o of t.points)
431
- if (e(o)) return !0;
432
- for (let o of s)
433
- if (n(o)) return !0;
439
+ };
440
+ for (let c = 0; c < 4; c++)
441
+ if (l(r[c])) return !0;
434
442
  return !1;
435
443
  }
436
444
  /**
@@ -500,7 +508,7 @@ class v {
500
508
  * @returns
501
509
  */
502
510
  clone() {
503
- return new v(this.minX, this.maxX, this.minY, this.maxY);
511
+ return new C(this.minX, this.maxX, this.minY, this.maxY);
504
512
  }
505
513
  /**
506
514
  *
@@ -511,7 +519,25 @@ class v {
511
519
  const e = [], n = [];
512
520
  return t.forEach((i) => {
513
521
  e.push(i.x), n.push(i.y);
514
- }), new v(
522
+ }), new C(
523
+ Math.min(...e),
524
+ Math.max(...e),
525
+ Math.min(...n),
526
+ Math.max(...n)
527
+ );
528
+ }
529
+ /**
530
+ *
531
+ * @param points
532
+ * @returns
533
+ */
534
+ static fromByLineSegment(...t) {
535
+ const e = [], n = [];
536
+ return t.forEach((i) => {
537
+ i?.points?.forEach((s) => {
538
+ e.push(s.x), n.push(s.y);
539
+ });
540
+ }), new C(
515
541
  Math.min(...e),
516
542
  Math.max(...e),
517
543
  Math.min(...n),
@@ -519,7 +545,128 @@ class v {
519
545
  );
520
546
  }
521
547
  }
522
- class O {
548
+ class U {
549
+ map = /* @__PURE__ */ new Map();
550
+ gridSize;
551
+ constructor(t = 2) {
552
+ this.gridSize = t;
553
+ }
554
+ /**
555
+ * 插入
556
+ * @param point
557
+ * @param userData
558
+ */
559
+ insert(t, e) {
560
+ if (!t || isNaN(t.x) || isNaN(t.y))
561
+ throw new Error("无效的点坐标");
562
+ const n = this.getGridId(t);
563
+ this.map.has(n) || this.map.set(n, /* @__PURE__ */ new Set());
564
+ const i = this.map.get(n), s = { point: t, userData: e };
565
+ i.add(s), t.userData.pointVirtualGrid = { set: i, target: s };
566
+ }
567
+ /**
568
+ * 批量加入
569
+ * @param points
570
+ */
571
+ insertBatch(t) {
572
+ for (const { point: e, userData: n } of t)
573
+ this.insert(e, n);
574
+ }
575
+ /** 移除点
576
+ * @param point
577
+ */
578
+ remove(t) {
579
+ const { set: e, target: n } = t?.userData?.pointVirtualGrid ?? {};
580
+ e && (e.delete(n), delete t?.userData?.pointVirtualGridMap);
581
+ }
582
+ /**
583
+ * 获取通过坐标,获取唯一网格索引
584
+ * @param point
585
+ * @returns
586
+ */
587
+ getGridId(t) {
588
+ const e = Math.ceil(t.x / this.gridSize), n = Math.ceil(t.y / this.gridSize);
589
+ return `${e}.${n}`;
590
+ }
591
+ /**
592
+ *
593
+ * @param gridId
594
+ * @returns
595
+ */
596
+ decodeGridId(t) {
597
+ const [e, n] = t.split(".").map(Number);
598
+ return new g(e, n);
599
+ }
600
+ /**
601
+ * 查询与矩形相交的点
602
+ * @param rectangle 矩形
603
+ * @returns 相交的节点数组
604
+ */
605
+ queryRect(t) {
606
+ const e = t.toBox(), n = Math.ceil(e.minX / this.gridSize), i = Math.ceil(e.maxX / this.gridSize), s = Math.ceil(e.minY / this.gridSize), o = Math.ceil(e.maxY / this.gridSize);
607
+ for (let r = n; r <= i; r++)
608
+ for (let l = s; l <= o; l++) {
609
+ const c = `${r}.${l}`;
610
+ if (!this.map.has(c)) continue;
611
+ this.map.get(c)?.forEach((h) => {
612
+ t.containsPoint(h.point);
613
+ });
614
+ }
615
+ }
616
+ /**
617
+ * 查询与圆形区域相交的点
618
+ * @param pos 圆心
619
+ * @param radius 半径
620
+ * @returns 相交的节点数组
621
+ */
622
+ queryCircle(t, e) {
623
+ const n = new C(t.x - e, t.x + e, t.y - e, t.y + e), i = Math.ceil(n.minX / this.gridSize), s = Math.ceil(n.maxX / this.gridSize), o = Math.ceil(n.minY / this.gridSize), r = Math.ceil(n.maxY / this.gridSize), l = [];
624
+ for (let c = i; c <= s; c++)
625
+ for (let a = o; a <= r; a++) {
626
+ const h = `${c}.${a}`;
627
+ if (!this.map.has(h)) continue;
628
+ this.map.get(h)?.forEach((u) => {
629
+ t.distance(u.point) <= e && l.push(u);
630
+ });
631
+ }
632
+ return l;
633
+ }
634
+ /**
635
+ * 查询与包围盒相交的点
636
+ * @param box2 包围盒
637
+ * @returns 相交的节点数组
638
+ */
639
+ queryBox(t) {
640
+ const e = Math.ceil(t.minX / this.gridSize), n = Math.ceil(t.maxX / this.gridSize), i = Math.ceil(t.minY / this.gridSize), s = Math.ceil(t.maxY / this.gridSize), o = [];
641
+ for (let r = e; r <= n; r++)
642
+ for (let l = i; l <= s; l++) {
643
+ const c = `${r}.${l}`;
644
+ if (!this.map.has(c)) continue;
645
+ this.map.get(c)?.forEach((h) => {
646
+ t.containsPoint(h.point) && o.push(h);
647
+ });
648
+ }
649
+ return o;
650
+ }
651
+ /**
652
+ * 查找相同点
653
+ * @param point
654
+ */
655
+ queryPoint(t) {
656
+ const e = this.getGridId(t), n = [];
657
+ return this.map.has(e) && this.map.get(e)?.forEach((s) => {
658
+ t.equal(s.point) && n.push(s);
659
+ }), n;
660
+ }
661
+ /**
662
+ * 查找点自己
663
+ * @param point
664
+ */
665
+ queryPointSelf(t) {
666
+ return t.userData.pointVirtualGrid && t.userData.pointVirtualGrid.target ? t.userData.pointVirtualGrid.target : null;
667
+ }
668
+ }
669
+ class J {
523
670
  points;
524
671
  get p0() {
525
672
  return this.points[0];
@@ -542,7 +689,7 @@ class O {
542
689
  path2D(t) {
543
690
  return this.points.flatMap((e, n) => {
544
691
  const i = this.points[(n + 1) % this.points.length];
545
- return t && t(new p(e.x, e.y), new p(i.x, i.y)), [e.x, e.y, i.x, i.y];
692
+ return t && t(new g(e.x, e.y), new g(i.x, i.y)), [e.x, e.y, i.x, i.y];
546
693
  });
547
694
  }
548
695
  createGeometry() {
@@ -568,17 +715,19 @@ class O {
568
715
  intersectLineSegment(t) {
569
716
  if (t.points.length !== 2)
570
717
  throw new Error("LineSegment must have exactly 2 points");
571
- const [e, n] = t.points, i = (s, o, r, a) => {
572
- const c = (y, u, x) => {
573
- const w = (u.y - y.y) * (x.x - u.x) - (u.x - y.x) * (x.y - u.y);
574
- return w === 0 ? 0 : w > 0 ? 1 : 2;
575
- }, h = (y, u, x) => Math.min(y.x, x.x) <= u.x && u.x <= Math.max(y.x, x.x) && Math.min(y.y, x.y) <= u.y && u.y <= Math.max(y.y, x.y), l = c(s, o, r), d = c(s, o, a), f = c(r, a, s), m = c(r, a, o);
576
- return !!(l !== d && f !== m || l === 0 && h(s, r, o) || d === 0 && h(s, a, o) || f === 0 && h(r, s, a) || m === 0 && h(r, o, a));
577
- };
578
- for (let s = 0; s < 4; s++) {
579
- const o = this.points[s], r = this.points[(s + 1) % 4];
580
- if (i(e, n, o, r))
581
- return !0;
718
+ const [e, n] = t.points, i = n.x - e.x, s = n.y - e.y;
719
+ for (let o = 0; o < 4; o++) {
720
+ const r = this.points[o], l = this.points[(o + 1) % 4], c = l.x - r.x, a = l.y - r.y, h = i * a - s * c;
721
+ if (h === 0) {
722
+ if ((e.x - r.x) * a - (e.y - r.y) * c !== 0) continue;
723
+ const u = c * c + a * a, f = ((e.x - r.x) * c + (e.y - r.y) * a) / u, y = ((n.x - r.x) * c + (n.y - r.y) * a) / u;
724
+ if (Math.max(f, y) >= 0 && Math.min(f, y) <= 1)
725
+ return !0;
726
+ } else {
727
+ const d = ((r.x - e.x) * a - (r.y - e.y) * c) / h, u = ((r.x - e.x) * s - (r.y - e.y) * i) / h;
728
+ if (d >= 0 && d <= 1 && u >= 0 && u <= 1)
729
+ return !0;
730
+ }
582
731
  }
583
732
  return !!this.containsLineSegment(t);
584
733
  }
@@ -593,13 +742,13 @@ class O {
593
742
  const e = (n) => {
594
743
  let i = 0;
595
744
  for (let s = 0; s < 4; s++) {
596
- const o = this.points[s], r = this.points[(s + 1) % 4], a = { x: r.x - o.x, y: r.y - o.y }, c = { x: n.x - o.x, y: n.y - o.y }, h = a.x * c.y - a.y * c.x;
597
- if (h === 0) {
598
- const l = a.x !== 0 ? (n.x - o.x) / a.x : (n.y - o.y) / a.y;
599
- if (l >= 0 && l <= 1) return !0;
745
+ const o = this.points[s], r = this.points[(s + 1) % 4], l = { x: r.x - o.x, y: r.y - o.y }, c = { x: n.x - o.x, y: n.y - o.y }, a = l.x * c.y - l.y * c.x;
746
+ if (a === 0) {
747
+ const h = l.x !== 0 ? (n.x - o.x) / l.x : (n.y - o.y) / l.y;
748
+ if (h >= 0 && h <= 1) return !0;
600
749
  } else {
601
- const l = h > 0 ? 1 : -1;
602
- if (i === 0 && (i = l), i !== l) return !1;
750
+ const h = a > 0 ? 1 : -1;
751
+ if (i === 0 && (i = h), i !== h) return !1;
603
752
  }
604
753
  }
605
754
  return !0;
@@ -623,7 +772,7 @@ class O {
623
772
  e.push(o.normal(r));
624
773
  }
625
774
  function n(s, o) {
626
- const r = s.points.map((a) => a.dot(o));
775
+ const r = s.points.map((l) => l.dot(o));
627
776
  return [Math.min(...r), Math.max(...r)];
628
777
  }
629
778
  function i(s, o) {
@@ -658,7 +807,7 @@ class O {
658
807
  let t = 1 / 0, e = -1 / 0, n = 1 / 0, i = -1 / 0;
659
808
  return this.points.forEach((s) => {
660
809
  e = Math.max(s.x, e), t = Math.min(s.x, t), i = Math.max(s.x, i), n = Math.min(s.x, n);
661
- }), new v(t, e, n, i);
810
+ }), new C(t, e, n, i);
662
811
  }
663
812
  /**
664
813
  *
@@ -667,67 +816,243 @@ class O {
667
816
  * @returns
668
817
  */
669
818
  static fromByLineSegment(t, e = 0.1, n = !1, i = 0.5) {
670
- const s = t.points[0], o = t.points[1], r = o.normal(s), a = n ? o.direction(s).mutiplyScalar(e * i) : p.zero(), c = n ? s.direction(o).mutiplyScalar(e * i) : p.zero(), h = r.x * e * 0.5, l = r.y * e * 0.5;
671
- return new O([
672
- new p(s.x + h, s.y + l).add(c),
673
- new p(o.x + h, o.y + l).add(a),
674
- new p(o.x - h, o.y - l).add(a),
675
- new p(s.x - h, s.y - l).add(c)
819
+ const s = t.points[0], o = t.points[1], r = o.normal(s), l = n ? o.direction(s).mutiplyScalar(e * i) : g.zero(), c = n ? s.direction(o).mutiplyScalar(e * i) : g.zero(), a = r.x * e * 0.5, h = r.y * e * 0.5;
820
+ return new J([
821
+ new g(s.x + a, s.y + h).add(c),
822
+ new g(o.x + a, o.y + h).add(l),
823
+ new g(o.x - a, o.y - h).add(l),
824
+ new g(s.x - a, s.y - h).add(c)
676
825
  ]);
677
826
  }
678
827
  }
679
- class L {
680
- points = [new p(), new p()];
681
- userData = {};
682
- // line: any
683
- get center() {
684
- return new p(
685
- this.points[0].x + (this.points[1].x - this.points[0].x) * 0.5,
686
- this.points[0].y + (this.points[1].y - this.points[0].y) * 0.5
687
- );
688
- }
689
- get start() {
690
- return this.points[0];
691
- }
692
- get end() {
693
- return this.points[1];
828
+ class T {
829
+ bounds;
830
+ // 包围盒
831
+ capacity;
832
+ // 节点容量
833
+ maxDepth;
834
+ // 最大深度
835
+ depth;
836
+ // 当前深度
837
+ isLeaf = !0;
838
+ // 是否为叶子节点
839
+ children = null;
840
+ // 子节点数组
841
+ nodes = [];
842
+ // 存储的节点
843
+ color = [Math.random(), Math.random(), Math.random()];
844
+ // 颜色
845
+ constructor(t, e = 8, n = 10, i = 1) {
846
+ this.bounds = t, this.capacity = e, this.depth = i, this.maxDepth = n;
694
847
  }
695
- constructor(t = new p(), e = new p()) {
696
- this.points = [t, e];
848
+ /**
849
+ * 插入线段节点
850
+ * @param node 线段节点
851
+ */
852
+ insert(t) {
853
+ if (!this.isLeaf) {
854
+ const e = this.getQuadrant(t.line);
855
+ if (e !== -1) {
856
+ this.children[e].insert(t);
857
+ return;
858
+ }
859
+ }
860
+ if (this.nodes.push(t), t.parent = this, this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
861
+ this.subdivide();
862
+ const e = this.nodes;
863
+ this.nodes = [];
864
+ for (const n of e) {
865
+ const i = this.getQuadrant(n.line);
866
+ i !== -1 ? this.children[i].insert(n) : (n.parent = this, this.nodes.push(n));
867
+ }
868
+ }
697
869
  }
698
- set(t, e) {
699
- return this.start.copy(t), this.end.copy(e), this;
870
+ /** 移除
871
+ * @param node
872
+ */
873
+ remove(t) {
874
+ const e = t.parent?.nodes.indexOf(t);
875
+ e > -1 && t.parent?.nodes.splice(e, 1);
700
876
  }
701
877
  /**
702
- * 是否有相同端点
703
- * @param line
704
- * @returns
878
+ * 获取线段所属的象限
879
+ * @param line 线段
880
+ * @returns 象限索引(0:西北,1:东北,2:西南,3:东南)或-1(跨多个象限)
705
881
  */
706
- sameEndpoint(t) {
707
- return this.start.equal(t.start) || this.start.equal(t.end) || this.end.equal(t.start) || this.end.equal(t.end);
882
+ getQuadrant(t) {
883
+ const e = this.children[0].bounds.intersectLineSegment(t), n = this.children[1].bounds.intersectLineSegment(t), i = this.children[2].bounds.intersectLineSegment(t), s = this.children[3].bounds.intersectLineSegment(t);
884
+ let o = 0, r = -1;
885
+ return e && (o++, r = 0), n && (o++, r = 1), i && (o++, r = 2), s && (o++, r = 3), o === 1 ? r : -1;
708
886
  }
709
887
  /**
710
- * 相同端点是否为开始
711
- * @param line
712
- * @returns
888
+ * 细分当前节点为四个子节点
713
889
  */
714
- sameEndpointAsStart(t) {
715
- return this.start.equal(t.start) || this.start.equal(t.end);
890
+ subdivide() {
891
+ if (!this.isLeaf) return;
892
+ this.isLeaf = !1, this.children = [];
893
+ const t = (this.bounds.minX + this.bounds.maxX) / 2, e = (this.bounds.minY + this.bounds.maxY) / 2;
894
+ this.children[0] = new T(
895
+ new C(this.bounds.minX, t, this.bounds.minY, e),
896
+ this.capacity,
897
+ this.maxDepth,
898
+ this.depth + 1
899
+ ), this.children[1] = new T(
900
+ new C(t, this.bounds.maxX, this.bounds.minY, e),
901
+ this.capacity,
902
+ this.maxDepth,
903
+ this.depth + 1
904
+ ), this.children[2] = new T(
905
+ new C(this.bounds.minX, t, e, this.bounds.maxY),
906
+ this.capacity,
907
+ this.maxDepth,
908
+ this.depth + 1
909
+ ), this.children[3] = new T(
910
+ new C(t, this.bounds.maxX, e, this.bounds.maxY),
911
+ this.capacity,
912
+ this.maxDepth,
913
+ this.depth + 1
914
+ );
716
915
  }
717
916
  /**
718
- * 获取共线点
719
- * @param line
720
- * @returns
917
+ * 查询与包围盒相交的线段节点
918
+ * @param box2 包围盒
919
+ * @returns 相交的节点数组
721
920
  */
722
- getSameEndpoint(t) {
723
- return this.start.equal(t.start) ? [this.start, t.start] : this.start.equal(t.end) ? [this.start, t.end] : this.end.equal(t.start) ? [this.end, t.start] : this.end.equal(t.end) ? [this.end, t.end] : null;
921
+ queryBox(t) {
922
+ const e = [];
923
+ if (!this.bounds.intersectBox(t))
924
+ return e;
925
+ for (const n of this.nodes)
926
+ t.intersectLineSegment(n.line) && e.push(n);
927
+ if (!this.isLeaf)
928
+ for (const n of this.children)
929
+ e.push(...n.queryBox(t));
930
+ return e;
724
931
  }
725
932
  /**
726
- * 相同端点是否为结束
727
- * @param line
728
- * @returns
933
+ * 查询与圆形区域相交的线段节点
934
+ * @param pos 圆心
935
+ * @param radius 半径
936
+ * @returns 相交的节点数组
729
937
  */
730
- sameEndpointAsEnd(t) {
938
+ queryCircle(t, e) {
939
+ const n = [], i = new C(
940
+ t.x - e,
941
+ t.x + e,
942
+ t.y - e,
943
+ t.y + e
944
+ );
945
+ if (!this.bounds.intersectBox(i))
946
+ return n;
947
+ for (const s of this.nodes) {
948
+ const [o, r] = s.line.points, l = r.x - o.x, c = r.y - o.y, a = l * l + c * c;
949
+ let h = ((t.x - o.x) * l + (t.y - o.y) * c) / a;
950
+ h = Math.max(0, Math.min(1, h));
951
+ const d = o.x + h * l, u = o.y + h * c;
952
+ t.distance(new g(d, u)) <= e && n.push(s);
953
+ }
954
+ if (!this.isLeaf)
955
+ for (const s of this.children)
956
+ n.push(...s.queryCircle(t, e));
957
+ return n.sort((s) => s.line.length()), n;
958
+ }
959
+ /**
960
+ * 查询与矩形相交的线段节点
961
+ * @param rectangle 矩形
962
+ * @returns 相交的节点数组
963
+ */
964
+ queryRect(t) {
965
+ const e = [];
966
+ if (!this.bounds.intersectRectangle(t))
967
+ return e;
968
+ for (const n of this.nodes)
969
+ t.intersectLineSegment(n.line) && e.push(n);
970
+ if (!this.isLeaf)
971
+ for (const n of this.children)
972
+ e.push(...n.queryRect(t));
973
+ return e;
974
+ }
975
+ /**
976
+ * 查询与线段相交的线段节点
977
+ * @param lineSegment 线段
978
+ * @returns 相交的节点数组
979
+ */
980
+ queryLineSegment(t, e = !0) {
981
+ const n = [];
982
+ if (!this.bounds.intersectLineSegment(t))
983
+ return n;
984
+ for (const i of this.nodes)
985
+ t.intersectLineSegment(i.line, e) && n.push(i);
986
+ if (!this.isLeaf)
987
+ for (const i of this.children)
988
+ n.push(...i.queryLineSegment(t));
989
+ return n;
990
+ }
991
+ /**
992
+ * 包围盒转换为数组
993
+ * @param array
994
+ * @param colors
995
+ * @returns
996
+ */
997
+ boundsToArray(t = [], e, n = !0) {
998
+ return !this.isLeaf && n && this.children?.forEach((i) => i.boundsToArray(t, e)), t.push(...this.bounds.points.flatMap((i, s, o) => {
999
+ const r = o[(s + 1) % o.length];
1000
+ return e?.push(...this.color), e?.push(...this.color), [i.x, i.y, 0, r.x, r.y, 0];
1001
+ })), t;
1002
+ }
1003
+ }
1004
+ class I {
1005
+ points = [new g(), new g()];
1006
+ userData = {};
1007
+ // line: any
1008
+ get center() {
1009
+ return new g(
1010
+ this.points[0].x + (this.points[1].x - this.points[0].x) * 0.5,
1011
+ this.points[0].y + (this.points[1].y - this.points[0].y) * 0.5
1012
+ );
1013
+ }
1014
+ get start() {
1015
+ return this.points[0];
1016
+ }
1017
+ get end() {
1018
+ return this.points[1];
1019
+ }
1020
+ constructor(t = new g(), e = new g()) {
1021
+ this.points = [t, e];
1022
+ }
1023
+ set(t, e) {
1024
+ return this.start.copy(t), this.end.copy(e), this;
1025
+ }
1026
+ /**
1027
+ * 是否有相同端点
1028
+ * @param line
1029
+ * @returns
1030
+ */
1031
+ sameEndpoint(t) {
1032
+ return this.start.equal(t.start) || this.start.equal(t.end) || this.end.equal(t.start) || this.end.equal(t.end);
1033
+ }
1034
+ /**
1035
+ * 相同端点是否为开始
1036
+ * @param line
1037
+ * @returns
1038
+ */
1039
+ sameEndpointAsStart(t) {
1040
+ return this.start.equal(t.start) || this.start.equal(t.end);
1041
+ }
1042
+ /**
1043
+ * 获取共线点
1044
+ * @param line
1045
+ * @returns
1046
+ */
1047
+ getSameEndpoint(t) {
1048
+ return this.start.equal(t.start) ? [this.start, t.start] : this.start.equal(t.end) ? [this.start, t.end] : this.end.equal(t.start) ? [this.end, t.start] : this.end.equal(t.end) ? [this.end, t.end] : null;
1049
+ }
1050
+ /**
1051
+ * 相同端点是否为结束
1052
+ * @param line
1053
+ * @returns
1054
+ */
1055
+ sameEndpointAsEnd(t) {
731
1056
  return this.end.equal(t.start) || this.end.equal(t.end);
732
1057
  }
733
1058
  /** 膨胀
@@ -769,15 +1094,15 @@ class L {
769
1094
  * @returns {Rectangle}
770
1095
  */
771
1096
  expandToRectangle(t = 0.1, e = "all") {
772
- const n = this.start, i = this.end, s = i.normal(n), o = e === "bothSides" ? p.zero() : i.direction(n).mutiplyScalar(t * 0.5), r = e === "bothSides" ? p.zero() : n.direction(i).mutiplyScalar(t * 0.5), a = s.x * t * 0.5, c = s.y * t * 0.5, h = [
1097
+ const n = this.start, i = this.end, s = i.normal(n), o = e === "bothSides" ? g.zero() : i.direction(n).mutiplyScalar(t * 0.5), r = e === "bothSides" ? g.zero() : n.direction(i).mutiplyScalar(t * 0.5), l = s.x * t * 0.5, c = s.y * t * 0.5, a = [
773
1098
  // 第一条线
774
- new p(n.x + a, n.y + c).add(r),
775
- new p(i.x + a, i.y + c).add(o),
1099
+ new g(n.x + l, n.y + c).add(r),
1100
+ new g(i.x + l, i.y + c).add(o),
776
1101
  // 第二条线
777
- new p(n.x - a, n.y - c).add(r),
778
- new p(i.x - a, i.y - c).add(o)
1102
+ new g(n.x - l, n.y - c).add(r),
1103
+ new g(i.x - l, i.y - c).add(o)
779
1104
  ];
780
- return new O([0, 1, 3, 2].map((l) => h[l]));
1105
+ return new J([0, 1, 3, 2].map((h) => a[h]));
781
1106
  }
782
1107
  /**
783
1108
  * 计算线段的长度
@@ -814,24 +1139,24 @@ class L {
814
1139
  projectLineSegment(t) {
815
1140
  if (t.points.length !== 2 || this.points.length !== 2)
816
1141
  throw new Error("每条线段必须由两个点定义");
817
- const [e, n] = t.points, [i, s] = this.points, o = new p(s.x - i.x, s.y - i.y);
1142
+ const [e, n] = t.points, [i, s] = this.points, o = new g(s.x - i.x, s.y - i.y);
818
1143
  if (o.x === 0 && o.y === 0)
819
1144
  throw new Error("投影目标线段的两个点不能重合");
820
- const r = (m) => {
821
- const y = new p(m.x - i.x, m.y - i.y), u = o.x * o.x + o.y * o.y, w = (y.x * o.x + y.y * o.y) / u, S = i.x + w * o.x, b = i.y + w * o.y;
822
- return new p(S, b);
1145
+ const r = (f) => {
1146
+ const y = new g(f.x - i.x, f.y - i.y), p = o.x * o.x + o.y * o.y, D = (y.x * o.x + y.y * o.y) / p, w = i.x + D * o.x, b = i.y + D * o.y;
1147
+ return new g(w, b);
823
1148
  };
824
- let a = r(e), c = r(n);
825
- const h = (m) => {
826
- const y = new p(m.x - i.x, m.y - i.y), u = o.x * o.x + o.y * o.y;
827
- return (y.x * o.x + y.y * o.y) / u;
1149
+ let l = r(e), c = r(n);
1150
+ const a = (f) => {
1151
+ const y = new g(f.x - i.x, f.y - i.y), p = o.x * o.x + o.y * o.y;
1152
+ return (y.x * o.x + y.y * o.y) / p;
828
1153
  };
829
- let l = h(a), d = h(c);
830
- const f = (m) => {
831
- const y = Math.max(0, Math.min(1, m)), u = i.x + y * o.x, x = i.y + y * o.y;
832
- return new p(u, x);
1154
+ let h = a(l), d = a(c);
1155
+ const u = (f) => {
1156
+ const y = Math.max(0, Math.min(1, f)), p = i.x + y * o.x, x = i.y + y * o.y;
1157
+ return new g(p, x);
833
1158
  };
834
- return (l < 0 || l > 1) && (a = f(l)), (d < 0 || d > 1) && (c = f(d)), a.x === c.x && a.y === c.y ? new L(a, a) : new L(a, c);
1159
+ return (h < 0 || h > 1) && (l = u(h)), (d < 0 || d > 1) && (c = u(d)), l.x === c.x && l.y === c.y ? new I(l, l) : new I(l, c);
835
1160
  }
836
1161
  /**
837
1162
  * 计算一条线段在另一条直线上的投影
@@ -840,17 +1165,17 @@ class L {
840
1165
  * @returns 投影并裁剪后的线段
841
1166
  */
842
1167
  projectPoint(t, e = !0) {
843
- const [n, i] = this.points, s = new p(i.x - n.x, i.y - n.y);
1168
+ const [n, i] = this.points, s = new g(i.x - n.x, i.y - n.y);
844
1169
  if (s.x === 0 && s.y === 0)
845
1170
  throw new Error("投影目标线段的两个点不能重合");
846
- let r = ((h) => {
847
- const l = new p(h.x - n.x, h.y - n.y), d = s.x * s.x + s.y * s.y, m = (l.x * s.x + l.y * s.y) / d, y = n.x + m * s.x, u = n.y + m * s.y;
848
- return new p(y, u);
1171
+ let r = ((a) => {
1172
+ const h = new g(a.x - n.x, a.y - n.y), d = s.x * s.x + s.y * s.y, f = (h.x * s.x + h.y * s.y) / d, y = n.x + f * s.x, p = n.y + f * s.y;
1173
+ return new g(y, p);
849
1174
  })(t);
850
1175
  if (!e) return r;
851
- let c = ((h) => {
852
- const l = new p(h.x - n.x, h.y - n.y), d = s.x * s.x + s.y * s.y;
853
- return (l.x * s.x + l.y * s.y) / d;
1176
+ let c = ((a) => {
1177
+ const h = new g(a.x - n.x, a.y - n.y), d = s.x * s.x + s.y * s.y;
1178
+ return (h.x * s.x + h.y * s.y) / d;
854
1179
  })(r);
855
1180
  return c < 0 || c > 1 ? null : r;
856
1181
  }
@@ -862,14 +1187,14 @@ class L {
862
1187
  */
863
1188
  intersectLineSegment(t, e = !0) {
864
1189
  const n = this.start, i = this.end, s = t.start, o = t.end;
865
- function r(f, m, y) {
866
- return (m.x - f.x) * (y.y - f.y) - (m.y - f.y) * (y.x - f.x);
1190
+ function r(u, f, y) {
1191
+ return (f.x - u.x) * (y.y - u.y) - (f.y - u.y) * (y.x - u.x);
867
1192
  }
868
- function a(f, m, y) {
869
- return Math.min(m.x, y.x) - 1e-10 <= f.x && f.x <= Math.max(m.x, y.x) + 1e-10 && Math.min(m.y, y.y) - 1e-10 <= f.y && f.y <= Math.max(m.y, y.y) + 1e-10;
1193
+ function l(u, f, y) {
1194
+ return Math.min(f.x, y.x) - 1e-10 <= u.x && u.x <= Math.max(f.x, y.x) + 1e-10 && Math.min(f.y, y.y) - 1e-10 <= u.y && u.y <= Math.max(f.y, y.y) + 1e-10;
870
1195
  }
871
- const c = r(n, i, s), h = r(n, i, o), l = r(s, o, n), d = r(s, o, i);
872
- return !!(c * h < 0 && l * d < 0 || e && (Math.abs(c) < 1e-10 && a(s, n, i) || Math.abs(h) < 1e-10 && a(o, n, i) || Math.abs(l) < 1e-10 && a(n, s, o) || Math.abs(d) < 1e-10 && a(i, s, o)));
1196
+ const c = r(n, i, s), a = r(n, i, o), h = r(s, o, n), d = r(s, o, i);
1197
+ return !!(c * a < 0 && h * d < 0 || e && (Math.abs(c) < 1e-10 && l(s, n, i) || Math.abs(a) < 1e-10 && l(o, n, i) || Math.abs(h) < 1e-10 && l(n, s, o) || Math.abs(d) < 1e-10 && l(i, s, o)));
873
1198
  }
874
1199
  /**
875
1200
  * 判断一个点是否在线段上(含端点)
@@ -889,8 +1214,8 @@ class L {
889
1214
  const e = this.start, n = this.end, i = t.start, s = t.end, o = (e.x - n.x) * (i.y - s.y) - (e.y - n.y) * (i.x - s.x);
890
1215
  if (Math.abs(o) < 1e-10)
891
1216
  return null;
892
- const r = ((e.x - i.x) * (i.y - s.y) - (e.y - i.y) * (i.x - s.x)) / o, a = e.x + r * (n.x - e.x), c = e.y + r * (n.y - e.y);
893
- return new p(a, c);
1217
+ const r = ((e.x - i.x) * (i.y - s.y) - (e.y - i.y) * (i.x - s.x)) / o, l = e.x + r * (n.x - e.x), c = e.y + r * (n.y - e.y);
1218
+ return new g(l, c);
894
1219
  }
895
1220
  /**
896
1221
  * 获取两条线段夹角
@@ -907,6 +1232,14 @@ class L {
907
1232
  directionEqual(t, e = 0.1) {
908
1233
  return this.includedAngle(t) < e;
909
1234
  }
1235
+ /**
1236
+ * 两条线段是否平行
1237
+ * @param line
1238
+ */
1239
+ parallel(t, e = 1) {
1240
+ const n = this.includedAngle(t);
1241
+ return n < e || n > 180 - e;
1242
+ }
910
1243
  /**
911
1244
  * 两条线段方向相反否一致
912
1245
  * @param line
@@ -928,29 +1261,214 @@ class L {
928
1261
  * @returns
929
1262
  */
930
1263
  areLinesCoincident(t) {
931
- const e = this.start, n = this.end, i = t.start, s = t.end, o = (n.y - e.y) / (n.x - e.x), r = e.y - o * e.x, a = (s.y - i.y) / (s.x - i.x), c = i.y - a * i.x;
932
- return !isFinite(o) && !isFinite(a) ? e.x === i.x && n.x === i.x : Math.abs(o - a) < 1e-3 && Math.abs(r - c) < 1e-3;
1264
+ const e = this.start, n = this.end, i = t.start, s = t.end, o = (n.y - e.y) / (n.x - e.x), r = e.y - o * e.x, l = (s.y - i.y) / (s.x - i.x), c = i.y - l * i.x;
1265
+ return !isFinite(o) && !isFinite(l) ? e.x === i.x && n.x === i.x : Math.abs(o - l) < 1e-3 && Math.abs(r - c) < 1e-3;
933
1266
  }
934
1267
  clone() {
935
- const t = new L(
1268
+ const t = new I(
936
1269
  this.points[0].clone(),
937
1270
  this.points[1].clone()
938
1271
  );
939
1272
  return t.userData = { ...this.userData }, t;
940
1273
  }
1274
+ /**
1275
+ * 轴对齐垂直修正
1276
+ * @param lines 待调整线段组
1277
+ * @param targettLine 轴线段
1278
+ * @returns
1279
+ */
1280
+ static axisAlignmentCorrection(t, e) {
1281
+ function n(x) {
1282
+ const D = new U();
1283
+ x.forEach((b) => b.points.forEach((P) => D.insert(P, b)));
1284
+ const w = [];
1285
+ for (let b = 0; b < x.length; b++) {
1286
+ const P = x[b], S = /* @__PURE__ */ new Map();
1287
+ P.points.forEach((m) => {
1288
+ if (D.queryPoint(m).length > 1) return;
1289
+ const A = D.queryCircle(m, 0.4).filter((E) => {
1290
+ const L = m.distance(E.point);
1291
+ return S.set(E.point, L), E.userData !== P || L > 1e-3;
1292
+ }).sort((E, L) => {
1293
+ const v = S.get(E.point), B = S.get(L.point);
1294
+ return v - B;
1295
+ });
1296
+ A.length !== 0 && w.push(new I(m.clone(), A[0].point.clone()));
1297
+ });
1298
+ }
1299
+ return [...x, ...w];
1300
+ }
1301
+ function i(x, D) {
1302
+ const w = [x], b = [], P = [];
1303
+ for (let S = 0; S < D.length; S++) {
1304
+ const m = D[S];
1305
+ if (x !== m) {
1306
+ if (m.userData.isDoor) {
1307
+ P.push(m);
1308
+ continue;
1309
+ }
1310
+ if (m.parallel(x, 45)) {
1311
+ const A = Math.atan2(m.end.y - m.start.y, m.end.x - m.start.x);
1312
+ let L = Math.atan2(x.end.y - x.start.y, x.end.x - x.start.x) - A;
1313
+ for (; L > Math.PI; ) L -= 2 * Math.PI;
1314
+ for (; L < -Math.PI; ) L += 2 * Math.PI;
1315
+ const v = m.center;
1316
+ m.start.rotate(v, L), m.end.rotate(v, L), w.push(m);
1317
+ } else {
1318
+ const A = Math.atan2(m.end.y - m.start.y, m.end.x - m.start.x), E = Math.atan2(x.end.y - x.start.y, x.end.x - x.start.x);
1319
+ let L = E + Math.PI / 2 - A, v = E - Math.PI / 2 - A;
1320
+ for (; L > Math.PI; ) L -= 2 * Math.PI;
1321
+ for (; L < -Math.PI; ) L += 2 * Math.PI;
1322
+ for (; v > Math.PI; ) v -= 2 * Math.PI;
1323
+ for (; v < -Math.PI; ) v += 2 * Math.PI;
1324
+ const B = Math.abs(L) < Math.abs(v) ? L : v, X = m.center;
1325
+ m.start.rotate(X, B), m.end.rotate(X, B), b.push(m);
1326
+ }
1327
+ }
1328
+ }
1329
+ return { parallelLines: w, verticalLines: b, doorLines: P };
1330
+ }
1331
+ function s(x, D, w, b = 0.3, P = 0.06) {
1332
+ const S = [];
1333
+ x.forEach((E) => {
1334
+ const L = w.projectPoint(E.start, !1);
1335
+ L && (L.userData = E, S.push(L));
1336
+ }), S.sort((E, L) => L.distance(w.start) - E.distance(w.start));
1337
+ const m = [], A = [];
1338
+ for (let E = 0; E < S.length; E++) {
1339
+ const L = S[E];
1340
+ if (E === 0) {
1341
+ A.push(L);
1342
+ continue;
1343
+ }
1344
+ S[E - 1].distance(L) < P || (m.push([...A]), A.length = 0), A.push(L), E === S.length - 1 && m.push(A);
1345
+ }
1346
+ return m.flatMap((E) => {
1347
+ const L = E.flatMap((j) => {
1348
+ const G = j.userData;
1349
+ return G.points.map((R) => {
1350
+ const Y = D.projectPoint(R, !1);
1351
+ return Y.userData = G, Y;
1352
+ });
1353
+ });
1354
+ L.sort((j, G) => j.distance(D.start) - G.distance(D.start));
1355
+ const v = /* @__PURE__ */ new Map(), B = [], X = [];
1356
+ return L.forEach((j, G) => {
1357
+ v.size === 0 && G > 0 && L[G - 1].distance(j) > b && (B.push([...X]), X.length = 0), v.set(j.userData, (v.get(j.userData) ?? 0) + 1);
1358
+ for (const R of v.values()) if (R !== 2) return;
1359
+ X.push(...v.keys()), v.clear();
1360
+ }), B.push([...X]), B;
1361
+ });
1362
+ }
1363
+ function o(x, D = 0.1) {
1364
+ return x.map((w) => {
1365
+ if (w.length === 0) return;
1366
+ if (w.length === 1) return w[0];
1367
+ const b = [];
1368
+ w.forEach((Y) => {
1369
+ b.push(Y.start.clone(), Y.end.clone());
1370
+ });
1371
+ const P = w[0].direction().normalize();
1372
+ let S = 1 / 0, m = -1 / 0, A = 0, E = 0;
1373
+ b.forEach((Y) => {
1374
+ const F = Y.x * P.x + Y.y * P.y;
1375
+ S = Math.min(S, F), m = Math.max(m, F), A += Y.x, E += Y.y;
1376
+ });
1377
+ const L = new g(A / b.length, E / b.length), v = L.x * P.x + L.y * P.y, B = new g(L.x + (S - v) * P.x, L.y + (S - v) * P.y), X = new g(L.x + (m - v) * P.x, L.y + (m - v) * P.y), j = new I(B, X), G = w[0].normal().normalize();
1378
+ S = 1 / 0, m = -1 / 0, b.forEach((Y) => {
1379
+ const F = Y.x * G.x + Y.y * G.y;
1380
+ S = Math.min(S, F), m = Math.max(m, F);
1381
+ });
1382
+ const R = m - S;
1383
+ return R >= D && (j.userData.wallWidth = R), j;
1384
+ }).filter((w) => !!w);
1385
+ }
1386
+ function r(x, D = 0.2) {
1387
+ const w = new T(C.fromByLineSegment(...x)), b = /* @__PURE__ */ new Map();
1388
+ x.forEach((S) => {
1389
+ b.set(S, { line: S, userData: void 0 }), w.insert(b.get(S));
1390
+ });
1391
+ const P = new I();
1392
+ for (let S = 0; S < x.length; S++) {
1393
+ const m = x[S];
1394
+ if (m.userData.isAdsorbed) continue;
1395
+ const A = m.direction().multiplyScalar(D), [E, L] = m.points.map((v) => {
1396
+ P.set(v, v), P.start.add(A), P.end.add(A.multiplyScalar(-1));
1397
+ const B = /* @__PURE__ */ new Map(), X = w.queryRect(P.expandToRectangle(0.1, "bothSides")).filter((j) => j.line !== m).map((j) => {
1398
+ const G = j.line.getIntersection(P);
1399
+ return B.set(j.line, G), j.line;
1400
+ }).sort((j, G) => {
1401
+ const R = B.get(j), Y = B.get(G);
1402
+ return R && Y ? R.distance(v) - Y.distance(v) : 0;
1403
+ });
1404
+ return X.length ? B.get(X[0]) : void 0;
1405
+ });
1406
+ if (E && L) {
1407
+ if (E.equal(L)) {
1408
+ const v = m.start.distance(E), B = m.end.distance(L);
1409
+ v < B ? m.directionMove(m.start.direction(m.end), v) : m.directionMove(m.end.direction(m.start), B);
1410
+ } else
1411
+ m.start.copy(E), m.end.copy(L);
1412
+ m.userData.isAdsorbed = !0;
1413
+ } else E ? m.start.copy(E) : L && m.end.copy(L);
1414
+ w.remove(b.get(m)), w.insert(b.get(m));
1415
+ }
1416
+ return x.filter((S) => S.length() > 1e-3);
1417
+ }
1418
+ function l(x) {
1419
+ const D = new T(C.fromByLineSegment(...x));
1420
+ return x.forEach((w) => D.insert({ line: w, userData: void 0 })), x.flatMap((w) => {
1421
+ const b = D.queryLineSegment(w, !0).map((P) => {
1422
+ if (P.line === w) return;
1423
+ const S = P.line.getIntersection(w);
1424
+ if (!(!S || w.start.equal(S) || w.end.equal(S)))
1425
+ return S;
1426
+ }).filter((P) => !!P);
1427
+ return b.length ? (w = w.clone(), b.sort((S, m) => w.start.distance(S) - w.start.distance(m)), [...b.map((S) => {
1428
+ const m = w.clone();
1429
+ return m.set(w.start.clone(), S), w.start.copy(S), m;
1430
+ }), w]) : w;
1431
+ }).filter((w) => w.length() > 0.1);
1432
+ }
1433
+ t = n(t);
1434
+ const { parallelLines: c, verticalLines: a } = i(e, t.map((x) => x.clone())), h = e.normal(), d = e.center, u = e.direction(), f = new I(
1435
+ d.clone().add(h.clone().multiplyScalar(-1e3)),
1436
+ d.clone().add(h.clone().multiplyScalar(1e3))
1437
+ ), y = new I(
1438
+ d.clone().add(u.clone().multiplyScalar(-1e3)),
1439
+ d.clone().add(u.clone().multiplyScalar(1e3))
1440
+ );
1441
+ let p = o([
1442
+ ...s.call(this, c, y, f),
1443
+ ...s.call(this, a, f, y)
1444
+ ]);
1445
+ return p = r.call(this, p), p = r.call(this, p), p = l.call(this, p), p;
1446
+ }
1447
+ /**
1448
+ * 获取最长线段
1449
+ * @param lines
1450
+ */
1451
+ static maxLengthLineIndex(t) {
1452
+ let e = 0, n = -1;
1453
+ for (let i = 0; i < t.length; i++) {
1454
+ const s = t[i].length();
1455
+ s > e && (e = s, n = i);
1456
+ }
1457
+ return n;
1458
+ }
941
1459
  }
942
- async function G(g, t = !0) {
1460
+ async function O(M, t = !0) {
943
1461
  if (typeof global < "u" && typeof require < "u")
944
- return require(g);
1462
+ return require(M);
945
1463
  {
946
1464
  let e = await import(
947
1465
  /* @vite-ignore */
948
- g
1466
+ M
949
1467
  );
950
1468
  return t && (e = e.default), e;
951
1469
  }
952
1470
  }
953
- const st = {
1471
+ const lt = {
954
1472
  Unitless: 1,
955
1473
  // 无单位,1米 = 1(无单位)
956
1474
  Inches: 39.37007874015748,
@@ -994,27 +1512,27 @@ const st = {
994
1512
  Parsecs: 3240779289666404e-32
995
1513
  // 秒差距,1米 ≈ 0.00000000000000003240779289666404秒差距
996
1514
  };
997
- function k(g) {
1515
+ function _(M) {
998
1516
  const t = [];
999
- for (let e = 0; e < g.length; e++)
1000
- t.push(new L(
1001
- g[e].clone(),
1002
- g[(e + 1) % g.length].clone()
1517
+ for (let e = 0; e < M.length; e++)
1518
+ t.push(new I(
1519
+ M[e].clone(),
1520
+ M[(e + 1) % M.length].clone()
1003
1521
  ));
1004
1522
  return t;
1005
1523
  }
1006
- function J(g) {
1007
- return g.flatMap((t, e) => (e === g.length - 1 && [...t.points, g[0].points[0]], [t.points[0]]));
1524
+ function K(M) {
1525
+ return M.flatMap((t, e) => (e === M.length - 1 && [...t.points, M[0].points[0]], [t.points[0]]));
1008
1526
  }
1009
- class X extends q {
1527
+ class z extends V {
1010
1528
  static name = "Dxf";
1011
1529
  shortLine = 0.04;
1012
1530
  width = 0.04;
1013
1531
  scale = 1;
1014
1532
  originalData = [];
1015
1533
  data = [];
1016
- originalBox = new v(0, 0, 0, 0);
1017
- box = new v(0, 0, 0, 0);
1534
+ originalBox = new C(0, 0, 0, 0);
1535
+ box = new C(0, 0, 0, 0);
1018
1536
  pointsGroups = [];
1019
1537
  wallsGroup = [];
1020
1538
  doors = [];
@@ -1046,38 +1564,64 @@ class X extends q {
1046
1564
  constructor(t = 0.04, e = 1) {
1047
1565
  super(), this.width = t, this.scale = e, this.shortLine = t * 0.4;
1048
1566
  }
1567
+ /**
1568
+ * 预处理数据
1569
+ * @param data
1570
+ */
1571
+ preprocessing(t, e = !1) {
1572
+ const n = [];
1573
+ let i = -1;
1574
+ t.forEach(({ start: o, end: r, ...l }, c) => {
1575
+ const a = new I(
1576
+ g.from(o),
1577
+ g.from(r)
1578
+ );
1579
+ a.userData = l, n.push(a), l.isVerticalReferenceLine && (i = c);
1580
+ }), i === -1 && (i = I.maxLengthLineIndex(n));
1581
+ const s = n[i];
1582
+ if (s.userData.isVerticalReferenceLine = !0, t[i].isVerticalReferenceLine = !0, e) {
1583
+ const o = I.axisAlignmentCorrection(n, s);
1584
+ return i = I.maxLengthLineIndex(o), o[i].userData.isVerticalReferenceLine = !0, {
1585
+ lineSegments: o,
1586
+ data: this.lineDataToOriginalData(o)
1587
+ };
1588
+ }
1589
+ return {
1590
+ lineSegments: n,
1591
+ data: t
1592
+ };
1593
+ }
1049
1594
  /**
1050
1595
  * 设置
1051
1596
  * @param data
1052
1597
  * @param width
1053
1598
  * @param scale
1054
1599
  */
1055
- async set(t, e = this.width, n = this.scale) {
1600
+ async set(t, e = this.width, n = this.scale, i = !1) {
1056
1601
  if (typeof t == "string")
1057
1602
  if (typeof global < "u") {
1058
- const { default: o } = await import(
1603
+ const { default: l } = await import(
1059
1604
  /* @vite-ignore */
1060
1605
  "fs"
1061
- ), r = o.readFileSync(t), a = JSON.parse(r.toString("utf-8"));
1606
+ ), c = l.readFileSync(t), a = JSON.parse(c.toString("utf-8"));
1062
1607
  return this.set(a, e, n);
1063
1608
  } else
1064
1609
  throw new Error("非node环境不允许使用路径");
1065
1610
  this.scale = n, this.width = e, this.originalData = t, this.lineSegments.length = 0;
1066
- const i = [];
1067
- this.data = t.map(({ start: s, end: o, insetionArr: r, isDoor: a = !1, ...c }, h) => {
1068
- i.push(s.z ?? 0, o.z ?? 0);
1069
- const l = new L(
1070
- p.from(s).mutiplyScalar(n),
1071
- p.from(o).mutiplyScalar(n)
1072
- );
1073
- return l.userData = { isDoor: a, ...c }, this.lineSegments.push(l), [
1074
- l.points[0],
1075
- l.points[1],
1076
- (r ?? []).map((d) => d.index),
1611
+ const s = this.preprocessing(t, i);
1612
+ t = s.data, this.lineSegments = s.lineSegments;
1613
+ const o = [];
1614
+ this.data = t.map(({ start: r, end: l, insetionArr: c, isDoor: a = !1 }, h) => {
1615
+ o.push(r.z ?? 0, l.z ?? 0);
1616
+ const d = this.lineSegments[h];
1617
+ return [
1618
+ d.points[0],
1619
+ d.points[1],
1620
+ (c ?? []).map((u) => u.index),
1077
1621
  a,
1078
1622
  h
1079
1623
  ];
1080
- }), this.originalZAverage = i.reduce((s, o) => s + o, 0) / i.length, this.computedOriginalSize(t, this.originalBox), this.dispatchEvent({
1624
+ }), this.originalZAverage = o.reduce((r, l) => r + l, 0) / o.length, this.computedOriginalSize(t, this.originalBox), this.dispatchEvent({
1081
1625
  type: "setDta",
1082
1626
  originalData: this.originalData,
1083
1627
  data: this.data
@@ -1091,18 +1635,18 @@ class X extends q {
1091
1635
  * @returns
1092
1636
  */
1093
1637
  createGroups() {
1094
- const t = [], e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map(), s = (o, r, a = -1) => {
1095
- const [c, h, l, d] = this.data[o];
1638
+ const t = [], e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map(), s = (o, r, l = -1) => {
1639
+ const [c, a, h, d] = this.data[o];
1096
1640
  if (e.add(o), d)
1097
- return i.has(o) || i.set(o, []), i.get(o)?.push(a), n.add(this.data[o]);
1098
- r.push([c, h]), l.forEach((f) => {
1099
- e.has(f) || s(f, r, o);
1641
+ return i.has(o) || i.set(o, []), i.get(o)?.push(l), n.add(this.data[o]);
1642
+ r.push([c, a]), h.forEach((u) => {
1643
+ e.has(u) || s(u, r, o);
1100
1644
  });
1101
1645
  };
1102
1646
  return this.data.forEach((o, r) => {
1103
1647
  if (!e.has(r)) {
1104
- const a = [];
1105
- s(r, a), t.push(a);
1648
+ const l = [];
1649
+ s(r, l), t.push(l);
1106
1650
  }
1107
1651
  }), this.doors = [...n], this.pointsGroups = t, t;
1108
1652
  }
@@ -1112,7 +1656,7 @@ class X extends q {
1112
1656
  * @returns
1113
1657
  */
1114
1658
  computedSize() {
1115
- const t = this.pointsGroups.flatMap((r) => r.flatMap((a) => [a[0].x, a[1].x])), e = this.pointsGroups.flatMap((r) => r.flatMap((a) => [a[0].y, a[1].y])), n = Math.min(...t), i = Math.min(...e), s = Math.max(...t), o = Math.max(...e);
1659
+ const t = this.pointsGroups.flatMap((r) => r.flatMap((l) => [l[0].x, l[1].x])), e = this.pointsGroups.flatMap((r) => r.flatMap((l) => [l[0].y, l[1].y])), n = Math.min(...t), i = Math.min(...e), s = Math.max(...t), o = Math.max(...e);
1116
1660
  return this.box.set(n, i, s, o), this.box;
1117
1661
  }
1118
1662
  /** 线路拓扑
@@ -1122,11 +1666,11 @@ class X extends q {
1122
1666
  lineTopology(t) {
1123
1667
  const e = [];
1124
1668
  function n(s, o) {
1125
- const [r, a] = t[s];
1126
- e[s] = !0, o.push(a);
1669
+ const [r, l] = t[s];
1670
+ e[s] = !0, o.push(l);
1127
1671
  for (let c = 0; c < t.length; c++) {
1128
- const [h, l] = t[c];
1129
- if (!e[c] && Math.abs(a.x - h.x) < 1e-6 && Math.abs(a.y - h.y) < 1e-6)
1672
+ const [a, h] = t[c];
1673
+ if (!e[c] && Math.abs(l.x - a.x) < 1e-6 && Math.abs(l.y - a.y) < 1e-6)
1130
1674
  return n(c, o);
1131
1675
  }
1132
1676
  }
@@ -1164,9 +1708,9 @@ class X extends q {
1164
1708
  const i = t[n - 1], s = t[n];
1165
1709
  if (i.distance(s) < this.width * 0.5) {
1166
1710
  let r = 0;
1167
- for (let a = n + 1; a < t.length; a++) {
1168
- const c = t[a - 1], h = t[a];
1169
- if (c.distance(h) < this.width * 0.8) r++;
1711
+ for (let l = n + 1; l < t.length; l++) {
1712
+ const c = t[l - 1], a = t[l];
1713
+ if (c.distance(a) < this.width * 0.8) r++;
1170
1714
  else break;
1171
1715
  }
1172
1716
  r === 0 && n + r === t.length - 1 || n == 1 && r === 1 || (r === 3 ? (e.push(t[n + 1]), n += r) : r === 5 ? (e.push(t[n + 2]), n += r) : e.push(s));
@@ -1188,7 +1732,7 @@ class X extends q {
1188
1732
  break;
1189
1733
  }
1190
1734
  }
1191
- const e = this.mergeSameDirectionLine(k(t)), n = [e[0]];
1735
+ const e = this.mergeSameDirectionLine(_(t)), n = [e[0]];
1192
1736
  for (let i = 1; i < e.length; i++) {
1193
1737
  const s = e[i], o = e[(e.length + i - 1) % e.length];
1194
1738
  if (s.length() > this.width * 0.9) {
@@ -1200,10 +1744,10 @@ class X extends q {
1200
1744
  n.push(s), n.push(r), i = i + 1;
1201
1745
  continue;
1202
1746
  }
1203
- const a = e[i + 2];
1204
- a && o.includedAngle(a) < 2 ? (i = i + 2, n.push(a)) : n.push(s);
1747
+ const l = e[i + 2];
1748
+ l && o.includedAngle(l) < 2 ? (i = i + 2, n.push(l)) : n.push(s);
1205
1749
  }
1206
- return n.length > 3 ? J(this.mergeSameDirectionLine(n)) : [];
1750
+ return n.length > 3 ? K(this.mergeSameDirectionLine(n)) : [];
1207
1751
  }
1208
1752
  /**
1209
1753
  * 移除短线段
@@ -1211,48 +1755,48 @@ class X extends q {
1211
1755
  * @param path
1212
1756
  */
1213
1757
  removeShortLine(t, e = this.shortLine) {
1214
- const n = k(t), i = [], s = Math.PI / 180;
1758
+ const n = _(t), i = [], s = Math.PI / 180;
1215
1759
  for (let o = 0; o < n.length; o++) {
1216
- const r = n[o], a = r.length(), c = o;
1217
- if (a > e || i.length === 0) {
1760
+ const r = n[o], l = r.length(), c = o;
1761
+ if (l > e || i.length === 0) {
1218
1762
  i.push(r);
1219
1763
  continue;
1220
1764
  }
1221
- let h = n[++o];
1222
- const l = i[i.length - 1], d = l.direction();
1765
+ let a = n[++o];
1766
+ const h = i[i.length - 1], d = h.direction();
1223
1767
  for (; o < n.length; ) {
1224
- const m = d.angleBetween(h.direction()) / s;
1225
- if (h.length() <= e || m < 4 || m > 176)
1226
- h = n[++o];
1768
+ const f = d.angleBetween(a.direction()) / s;
1769
+ if (a.length() <= e || f < 4 || f > 176)
1770
+ a = n[++o];
1227
1771
  else break;
1228
1772
  }
1229
- if (!h) continue;
1230
- const f = n[o - 1];
1231
- if (l.length() > f.length()) {
1232
- const m = l.getIntersection(h);
1233
- if (m) {
1234
- const y = l.points[1].clone(), u = h.points[0].clone();
1235
- l.points[1].copy(m), h.points[0].copy(m), l.length() < this.width ? (l.points[1].copy(y), h.points[0].copy(y)) : h.length() < this.width && (l.points[1].copy(u), h.points[0].copy(u));
1773
+ if (!a) continue;
1774
+ const u = n[o - 1];
1775
+ if (h.length() > u.length()) {
1776
+ const f = h.getIntersection(a);
1777
+ if (f) {
1778
+ const y = h.points[1].clone(), p = a.points[0].clone();
1779
+ h.points[1].copy(f), a.points[0].copy(f), h.length() < this.width ? (h.points[1].copy(y), a.points[0].copy(y)) : a.length() < this.width && (h.points[1].copy(p), a.points[0].copy(p));
1236
1780
  } else
1237
- l.points[1].copy(h.points[0]);
1238
- i.push(h);
1781
+ h.points[1].copy(a.points[0]);
1782
+ i.push(a);
1239
1783
  } else
1240
1784
  o = c;
1241
1785
  }
1242
- return i.length > 3 ? J(i) : [];
1786
+ return i.length > 3 ? K(i) : [];
1243
1787
  }
1244
1788
  /** 线偏移
1245
1789
  * @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
1246
1790
  */
1247
- lineOffset(t = X.EndType.etOpenSquare, e = X.JoinType.jtMiter, n = 1e4) {
1248
- let i = new F.Paths();
1249
- const s = new F.ClipperOffset(20, 0.25);
1791
+ lineOffset(t = z.EndType.etOpenSquare, e = z.JoinType.jtMiter, n = 1e4) {
1792
+ let i = new Z.Paths();
1793
+ const s = new Z.ClipperOffset(20, 0.25);
1250
1794
  return this.pointsGroups.forEach((o) => {
1251
- const r = this.lineTopology(o).map((a) => a.map((c) => c.clone().mutiplyScalar(n)));
1795
+ const r = this.lineTopology(o).map((l) => l.map((c) => c.clone().mutiplyScalar(n)));
1252
1796
  s.AddPaths(r, e, t);
1253
1797
  }), s.Execute(i, this.width / 2 * n), this.wallsGroup = i.map((o) => {
1254
- let r = o.map((a) => p.from(a).divisionScalar(n));
1255
- return r = this.lineSegmentStraightening(r), t == X.EndType.etOpenSquare && (r = this.squareRemoveBurr(r)), r;
1798
+ let r = o.map((l) => g.from(l).divisionScalar(n));
1799
+ return r = this.lineSegmentStraightening(r), t == z.EndType.etOpenSquare && (r = this.squareRemoveBurr(r)), r;
1256
1800
  }), this.dispatchEvent({
1257
1801
  type: "lineOffset",
1258
1802
  wallsGroup: this.wallsGroup
@@ -1265,8 +1809,8 @@ class X extends q {
1265
1809
  const n = [];
1266
1810
  return this.wallsGroup.forEach((i) => {
1267
1811
  for (let s = 0; s < i.length; s++) {
1268
- const o = i[s], r = s === i.length - 1 ? 0 : s + 1, a = i[r];
1269
- n.push(o.X * t, o.Y * t, e, a.X * t, a.Y * t, e);
1812
+ const o = i[s], r = s === i.length - 1 ? 0 : s + 1, l = i[r];
1813
+ n.push(o.X * t, o.Y * t, e, l.X * t, l.Y * t, e);
1270
1814
  }
1271
1815
  }), new Float32Array(n);
1272
1816
  }
@@ -1278,16 +1822,42 @@ class X extends q {
1278
1822
  */
1279
1823
  getArcAngleRange(t, e, n) {
1280
1824
  const i = e.x - t.x, s = e.y - t.y, o = n.x - t.x, r = n.y - t.y;
1281
- let a = Math.atan2(s, i), c = Math.atan2(r, o);
1282
- a = a < 0 ? a + 2 * Math.PI : a, c = c < 0 ? c + 2 * Math.PI : c;
1283
- let h, l;
1284
- return Math.abs(c - a) <= Math.PI ? (h = Math.min(a, c), l = Math.max(a, c)) : (h = Math.max(a, c), l = Math.min(a, c) + 2 * Math.PI), [h / (Math.PI / 180), l / (Math.PI / 180)];
1825
+ let l = Math.atan2(s, i), c = Math.atan2(r, o);
1826
+ l = l < 0 ? l + 2 * Math.PI : l, c = c < 0 ? c + 2 * Math.PI : c;
1827
+ let a, h;
1828
+ return Math.abs(c - l) <= Math.PI ? (a = Math.min(l, c), h = Math.max(l, c)) : (a = Math.max(l, c), h = Math.min(l, c) + 2 * Math.PI), [a / (Math.PI / 180), h / (Math.PI / 180)];
1829
+ }
1830
+ /**
1831
+ * 线段数据转为原始json数据
1832
+ */
1833
+ lineDataToOriginalData(t, e) {
1834
+ return t.map((n) => {
1835
+ const i = n.userData, s = i.drawWindow;
1836
+ e = e ?? new T(C.fromByLineSegment(...t));
1837
+ const o = e.queryLineSegment(n).filter((r) => r.line !== n && !r.userData?.isDoor).map((r) => ({ index: this.lines.indexOf(r.line) }));
1838
+ return {
1839
+ start: n.start.toJson(this.originalZAverage),
1840
+ end: n.end.toJson(this.originalZAverage),
1841
+ insetionArr: o,
1842
+ isDoor: i.isDoor,
1843
+ doorDirectConnection: i.isDoor,
1844
+ length: n.length(),
1845
+ isWindow: i.isWindow,
1846
+ isVerticalReferenceLine: i.isVerticalReferenceLine,
1847
+ wallWidth: n.userData.wallWidth,
1848
+ drawWindow: s && s.map((r) => ({
1849
+ p: { x: r.p.x, y: r.p.y, z: r.p.z },
1850
+ width: r.width,
1851
+ full: r.full
1852
+ }))
1853
+ };
1854
+ });
1285
1855
  }
1286
1856
  /**
1287
1857
  * 转为绘制数据
1288
1858
  */
1289
1859
  toDrawDataJson(t = "Millimeters") {
1290
- const e = st[t], n = {
1860
+ const e = lt[t], n = {
1291
1861
  unit: t,
1292
1862
  line: [],
1293
1863
  arc: [],
@@ -1298,584 +1868,272 @@ class X extends q {
1298
1868
  scale: e
1299
1869
  };
1300
1870
  let i = "white";
1301
- function s(c, h) {
1302
- n.line.push([c.X * e, c.Y * e, h.X * e, h.Y * e, i]);
1871
+ function s(c, a) {
1872
+ n.line.push([c.X * e, c.Y * e, a.X * e, a.Y * e, i]);
1303
1873
  }
1304
- function o(c, h, l, d) {
1874
+ function o(c, a, h, d) {
1305
1875
  n.arc.push([
1306
1876
  c.x * e,
1307
1877
  c.y * e,
1308
- h * e,
1309
- l,
1878
+ a * e,
1879
+ h,
1310
1880
  d,
1311
1881
  i
1312
1882
  ]);
1313
1883
  }
1314
1884
  for (let c = 0; c < this.originalData.length; c++) {
1315
- const h = this.originalData[c];
1316
- if (h.isVerticalReferenceLine) {
1317
- n.dimensionLine.push([h.start.x * e, h.start.y * e, h.end.x * e, h.end.y * e]);
1885
+ const a = this.originalData[c];
1886
+ if (a.isVerticalReferenceLine) {
1887
+ n.dimensionLine.push([a.start.x * e, a.start.y * e, a.end.x * e, a.end.y * e]);
1318
1888
  break;
1319
1889
  }
1320
1890
  }
1321
1891
  this.wallsGroup.forEach((c) => {
1322
- for (let h = 0; h < c.length; h++) {
1323
- const l = c[h], d = h === c.length - 1 ? 0 : h + 1, f = c[d];
1324
- s(l, f);
1892
+ for (let a = 0; a < c.length; a++) {
1893
+ const h = c[a], d = a === c.length - 1 ? 0 : a + 1, u = c[d];
1894
+ s(h, u);
1325
1895
  }
1326
1896
  });
1327
- const r = this.width * 0.2, a = [];
1897
+ const r = this.width * 0.2, l = [];
1328
1898
  return this.doorLineSegment.forEach((c) => {
1329
1899
  if (c.length() < 0.4) return;
1330
- const h = c.clone().expansion(-this.width * 0.5);
1331
- if (i = "cyan", h.length() < 1.2) {
1332
- h.expansion(-r * 0.5);
1333
- const l = c.normal();
1334
- let d = new L(
1335
- h.start.clone(),
1336
- h.start.clone().add(l.clone().multiplyScalar(h.length()))
1900
+ const a = c.clone().expansion(-this.width * 0.5);
1901
+ if (i = "cyan", a.length() < 1.2) {
1902
+ a.expansion(-r * 0.5);
1903
+ const h = c.normal();
1904
+ let d = new I(
1905
+ a.start.clone(),
1906
+ a.start.clone().add(h.clone().multiplyScalar(a.length()))
1337
1907
  );
1338
- const f = d.clone().directionMove(d.normal(), h.length() * -0.5).expandToRectangle(h.length(), "bothSides");
1339
- for (let b = 0; b < a.length; b++)
1340
- if (a[b].intersectRectangle(f)) {
1341
- d = new L(
1342
- h.start.clone(),
1343
- h.start.clone().add(l.clone().multiplyScalar(-h.length()))
1908
+ const u = d.clone().directionMove(d.normal(), a.length() * -0.5).expandToRectangle(a.length(), "bothSides");
1909
+ for (let b = 0; b < l.length; b++)
1910
+ if (l[b].intersectRectangle(u)) {
1911
+ d = new I(
1912
+ a.start.clone(),
1913
+ a.start.clone().add(h.clone().multiplyScalar(-a.length()))
1344
1914
  );
1345
1915
  break;
1346
1916
  }
1347
1917
  d.expansion(-r * 0.5).expandToRectangle(this.width * 0.2, "bothSides").path2D((b, P) => s(b, P));
1348
- const m = h.length(), y = d.length(), u = (m ** 2 + y ** 2) / (2 * y), x = d.end.clone().add(d.direction().multiplyScalar(-u)), [w, S] = this.getArcAngleRange(x, h.end, d.end);
1349
- o(x, u, Math.min(w, S), Math.max(w, S)), a.push(f);
1350
- } else
1351
- h.clone().expansion(-this.width * 0.5).expandToRectangle(this.width).path2D((l, d) => s(l, d)), h.clone().directionMove(h.normal(), r * 0.5).directionMove(h.direction(), r * 0.5).expansion(-h.length() * 0.45, "end").forward(r * 0.5).expandToRectangle(r).path2D((l, d) => s(l, d)), h.clone().directionMove(h.normal(), -r * 0.5).directionMove(h.direction(), -r * 0.5).expansion(-h.length() * 0.45, "start").forward(-r * 0.5).expandToRectangle(r).path2D((l, d) => s(l, d));
1352
- }), i = "yellow", this.lineSegments.forEach((c) => {
1353
- if (!c.userData.isWindow) return !1;
1354
- Array.isArray(c.userData.drawWindow) && c.userData.drawWindow.forEach((h) => {
1355
- const { p: l, width: d } = h, f = p.from(l), m = f.clone().add(c.direction().multiplyScalar(d * 0.5)), y = f.clone().add(c.direction().multiplyScalar(-d * 0.5)), u = new L(m, y);
1356
- s(u.start, u.end), u.expandToRectangle(this.width, "bothSides").path2D((x, w) => s(x, w));
1357
- });
1358
- }), n;
1359
- }
1360
- /**
1361
- *
1362
- * @param type
1363
- */
1364
- async toDxfImageBlob(t = "Centimeters", e = "image/jpeg", n = "#000") {
1365
- const i = this.toDrawDataJson(t);
1366
- let s;
1367
- if (typeof window < "u")
1368
- s = document.createElement("canvas");
1369
- else if (typeof global < "u") {
1370
- const { createCanvas: c } = await G("canvas");
1371
- s = c();
1372
- } else
1373
- throw new Error("创建画布失败");
1374
- const o = 2 * i.scale, r = {
1375
- cyan: "cyan",
1376
- yellow: "yellow",
1377
- white: "white"
1378
- };
1379
- s.width = i.width + o * 2, s.height = i.height + o * 2;
1380
- const a = s.getContext("2d");
1381
- return n && (a.fillStyle = n, a.fillRect(0, 0, s.width, s.height)), a.translate(i.width * 0.5 + o, i.height * 0.5 + o), i.line.forEach(([c, h, l, d, f]) => {
1382
- a.strokeStyle = r[f], a.beginPath(), a.moveTo(c, h), a.lineTo(l, d), a.closePath(), a.stroke();
1383
- }), i.arc.forEach(([c, h, l, d, f, m]) => {
1384
- a.strokeStyle = r[m], a.beginPath(), a.arc(c, h, l, d * (Math.PI / 180), f * (Math.PI / 180)), a.stroke();
1385
- }), a.beginPath(), i.dimensionLine.forEach((c) => {
1386
- let [h, l, d, f] = c;
1387
- const m = Math.min(l, f), y = Math.max(l, f), u = (s.width * 0.5 - 0.4 * i.scale) * (h < 0 ? -1 : 1), x = (y - m) * 0.45;
1388
- a.fillStyle = "#fff", a.font = `${0.15 * i.scale}px Arial`, a.textAlign = "center", a.textBaseline = "middle", a.fillText((y - m).toFixed(2) + "cm", u, m + (y - m) * 0.5), a.moveTo(u - 0.1 * i.scale, m), a.lineTo(u + 0.1 * i.scale, m), a.moveTo(u, m), a.lineTo(u, x + m), a.moveTo(u, y), a.lineTo(u, y - x), a.moveTo(u - 0.1 * i.scale, y), a.lineTo(u + 0.1 * i.scale, y);
1389
- }), a.closePath(), a.strokeStyle = "#fff", a.stroke(), "toBlob" in s ? new Promise((c) => {
1390
- s.toBlob((h) => {
1391
- c(h);
1392
- }, e, 1);
1393
- }) : s.toBuffer(e, { quality: 1 });
1394
- }
1395
- /**
1396
- * 将点json结构转换为Dxf string
1397
- */
1398
- toDxfString(t = "Millimeters") {
1399
- const e = new R();
1400
- e.setUnits(t), e.addLayer("cyan", R.ACI.CYAN, "DOTTED"), e.addLayer("yellow", R.ACI.YELLOW, "DOTTED"), e.addLayer("white", R.ACI.WHITE, "DOTTED");
1401
- const n = this.toDrawDataJson();
1402
- return n.line.forEach((i) => {
1403
- let [s, o, r, a, c] = i;
1404
- e.setActiveLayer(c), e.drawLine(s, o, r, a);
1405
- }), n.arc.forEach((i) => {
1406
- const [s, o, r, a, c, h] = i;
1407
- e.setActiveLayer(h), e.drawArc(s, o, r, a, c);
1408
- }), e.toDxfString();
1409
- }
1410
- /**
1411
- * 将点云结构转换为DXF格式
1412
- * @returns
1413
- */
1414
- toDxfBlob(t = "Millimeters") {
1415
- return new Blob([this.toDxfString(t)]);
1416
- }
1417
- /**
1418
- * 下载
1419
- * @param filename
1420
- */
1421
- async download(t, e = "Millimeters") {
1422
- if (typeof window < "u") {
1423
- const n = this.toDxfBlob(e), i = document.createElement("a");
1424
- i.href = URL.createObjectURL(n), i.download = t + ".dxf", i.click();
1425
- } else typeof global < "u" && (await G("fs", !1)).writeFileSync(t, this.toDxfString(e));
1426
- }
1427
- /**
1428
- * 下载
1429
- * @param filename
1430
- */
1431
- async downloadImage(t, e = "Centimeters", n = "image/jpeg") {
1432
- const i = await this.toDxfImageBlob(e, n);
1433
- if (!i) return !1;
1434
- if (typeof window < "u") {
1435
- const s = document.createElement("a");
1436
- s.href = URL.createObjectURL(i), s.download = t, s.click();
1437
- } else typeof global < "u" ? (await G("fs", !1)).writeFileSync(t, i) : console.error("图片下载失败");
1438
- return !0;
1439
- }
1440
- /**
1441
- * 计算原始数据的边界框
1442
- * @description 计算所有线段的起点和终点的最小最大值,形成一个边界框
1443
- * @returns
1444
- */
1445
- computedOriginalSize(t, e = new v(0, 0, 0, 0)) {
1446
- const n = t.flatMap((c) => [c.start.x, c.end.x]), i = t.flatMap((c) => [c.start.y, c.end.y]), s = Math.min(...n), o = Math.min(...i), r = Math.max(...n), a = Math.max(...i);
1447
- return e.set(s, o, r, a), e;
1448
- }
1449
- /**
1450
- * 创建数据
1451
- * @param pointsGroups
1452
- * @returns
1453
- */
1454
- static createData(t, e = !0) {
1455
- let n = 0;
1456
- return t.flatMap((s) => {
1457
- const o = s.map((r, a) => {
1458
- const c = a === s.length - 1 ? 0 : a + 1, h = s[c];
1459
- return {
1460
- start: { x: r.x, y: r.y },
1461
- end: { x: h.x, y: h.y },
1462
- insetionArr: [
1463
- {
1464
- index: c + n
1465
- }
1466
- ]
1467
- };
1468
- });
1469
- return n += s.length, e || (o.pop(), o[o.length - 1].insetionArr.length = 0, n--), o;
1470
- });
1471
- }
1472
- }
1473
- function V(g) {
1474
- if (g === null || typeof g != "object") return g;
1475
- if (g instanceof Date) return new Date(g.getTime());
1476
- if (Array.isArray(g)) return g.map(V);
1477
- const t = {};
1478
- for (const e in g)
1479
- Object.prototype.hasOwnProperty.call(g, e) && (t[e] = V(g[e]));
1480
- return t;
1481
- }
1482
- const I = new L();
1483
- class ot extends X {
1484
- static name = "AngleCorrectionDxf";
1485
- angle = 0;
1486
- onAddFromParent(t) {
1487
- t.findComponentByName("LineAnalysis").addEventListener("analysisCompleted", async () => this.update());
1488
- }
1489
- async update() {
1490
- const t = this.parent, e = t.findComponentByName("Dxf"), n = t.findComponentByName("LineAnalysis");
1491
- let i = 0, s = null;
1492
- for (let c = 0; c < e.originalData.length; c++) {
1493
- const h = e.originalData[c];
1494
- if (I.start.copy(h.start), I.end.copy(h.end), h.isVerticalReferenceLine) {
1495
- const [l, d] = h.start.y < h.end.y ? [I.start, I.end] : [I.end, I.start];
1496
- i = -new L(l, d).direction().angleBetween(new p(0, 1), "angle", "360"), s = null;
1497
- break;
1498
- }
1499
- (!s || I.length() > s.length()) && (s = I.clone(), s.userData.index = c);
1500
- }
1501
- if (s) {
1502
- e.originalData[s.userData.index].isVerticalReferenceLine = !0;
1503
- const [c, h] = s.start.y < s.end.y ? [s.start, s.end] : [s.end, s.start];
1504
- i = -new L(c, h).direction().angleBetween(new p(0, 1), "angle", "360");
1505
- }
1506
- const o = e.originalBox.center, r = p.zero(), a = e.originalData.map((c) => {
1507
- const h = r.copy(c.start).division(o).rotate(p.zero(), i * (Math.PI / 180)).toJson(c.start.z), l = r.copy(c.end).division(o).rotate(p.zero(), i * (Math.PI / 180)).toJson(c.end.z), d = Object.assign(V(c), { start: h, end: l });
1508
- return d.drawWindow && d.drawWindow.forEach((f) => {
1509
- f.p = r.copy(f.p).division(o).rotate(p.zero(), i * (Math.PI / 180)).toJson(f.p.z), f.p.y = -f.p.y;
1510
- }), d;
1511
- });
1512
- n.appendLineSegmentList.forEach((c) => {
1513
- const h = c.clone();
1514
- h.start.division(o).rotate(p.zero(), i * (Math.PI / 180)), h.end.division(o).rotate(p.zero(), i * (Math.PI / 180)), a.push({
1515
- start: h.start.toJson(e.originalZAverage),
1516
- end: h.end.toJson(e.originalZAverage),
1517
- insetionArr: [],
1518
- length: h.length()
1519
- });
1520
- }), a.forEach((c) => {
1521
- c.start.y = -c.start.y, c.end.y = -c.end.y;
1522
- }), await this.set(a, e.width, e.scale), this.lineOffset(), this.doorLineSegment = e.doorLineSegment.map((c) => {
1523
- const h = c.clone();
1524
- return h.start.division(o).rotate(p.zero(), i * (Math.PI / 180)), h.end.division(o).rotate(p.zero(), i * (Math.PI / 180)), h.start.y = -h.start.y, h.end.y = -h.end.y, h;
1525
- }), this.angle = i, this.dispatchEvent({
1526
- type: "updateData"
1527
- });
1528
- }
1529
- // async set(data: OriginalDataItem[], width?: number, scale?: number): Promise<any> {
1530
- // await super.set(data, width, scale)
1531
- // const quadtree = new Quadtree(this.box)
1532
- // this.lineSegments.forEach(line => {
1533
- // if(line.userData.isDoor) return
1534
- // quadtree.insert({
1535
- // line,
1536
- // userData: undefined
1537
- // })
1538
- // })
1539
- // this.lineSegments.forEach(line => {
1540
- // if(line.userData.isDoor) return
1541
- // const lines = quadtree.queryLineSegment(line)
1542
- // .filter(l => l.line !== line)
1543
- // .map(l => l.line)
1544
- // const offset = new ClipperLib.ClipperOffset(20, 0.25)
1545
- // offset.AddPaths(lines.map( line => line.points.map(p => p.clone().multiplyScalar(1000)) ), ClipperLib.JoinType.jtMiter, ClipperLib.EndType.etOpenSquare)
1546
- // const result = new ClipperLib.Paths()
1547
- // offset.Execute(result, this.width / 2 * 1000)
1548
- // console.log( result )
1549
- // // const cpr = new ClipperLib.Clipper()
1550
- // // offset.AddPath(linePaths, joinType, endType)
1551
- // })
1552
- // }
1553
- }
1554
- class _ extends q {
1555
- static name = "Variable";
1556
- originalLineVisible = !0;
1557
- dxfVisible = !0;
1558
- whiteModelVisible = !0;
1559
- isLook = !1;
1560
- currentWheel = 0;
1561
- pointerMove = { x: 0, y: 0 };
1562
- currentKeyUp = "";
1563
- currentKeyDown = "";
1564
- currentMouseUp = "";
1565
- currentMouseDown = "";
1566
- focus = !1;
1567
- set(t, e) {
1568
- if (t in this) {
1569
- const n = this[t];
1570
- this[t] = e, this.dispatchEvent({
1571
- type: t,
1572
- value: e,
1573
- oldValue: n
1574
- });
1575
- }
1576
- }
1577
- get(t) {
1578
- if (t in this) return this[t];
1579
- }
1580
- }
1581
- class j {
1582
- bounds;
1583
- // 包围盒
1584
- capacity;
1585
- // 节点容量
1586
- maxDepth;
1587
- // 最大深度
1588
- depth;
1589
- // 当前深度
1590
- isLeaf = !0;
1591
- // 是否为叶子节点
1592
- children = null;
1593
- // 子节点数组
1594
- nodes = [];
1595
- // 存储的节点
1596
- color = [Math.random(), Math.random(), Math.random()];
1597
- // 颜色
1598
- constructor(t, e = 8, n = 10, i = 1) {
1599
- this.bounds = t, this.capacity = e, this.depth = i, this.maxDepth = n;
1600
- }
1601
- /**
1602
- * 插入线段节点
1603
- * @param node 线段节点
1604
- */
1605
- insert(t) {
1606
- if (!this.isLeaf) {
1607
- const e = this.getQuadrant(t.line);
1608
- if (e !== -1) {
1609
- this.children[e].insert(t);
1610
- return;
1611
- }
1612
- }
1613
- if (this.nodes.push(t), t.parent = this, this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
1614
- this.subdivide();
1615
- const e = this.nodes;
1616
- this.nodes = [];
1617
- for (const n of e) {
1618
- const i = this.getQuadrant(n.line);
1619
- i !== -1 ? this.children[i].insert(n) : (n.parent = this, this.nodes.push(n));
1620
- }
1621
- }
1622
- }
1623
- /** 移除
1624
- * @param node
1625
- */
1626
- remove(t) {
1627
- const e = t.parent?.nodes.indexOf(t);
1628
- e > -1 && t.parent?.nodes.splice(e, 1);
1629
- }
1630
- /**
1631
- * 获取线段所属的象限
1632
- * @param line 线段
1633
- * @returns 象限索引(0:西北,1:东北,2:西南,3:东南)或-1(跨多个象限)
1634
- */
1635
- getQuadrant(t) {
1636
- const e = this.children[0].bounds.intersectLineSegment(t), n = this.children[1].bounds.intersectLineSegment(t), i = this.children[2].bounds.intersectLineSegment(t), s = this.children[3].bounds.intersectLineSegment(t);
1637
- let o = 0, r = -1;
1638
- return e && (o++, r = 0), n && (o++, r = 1), i && (o++, r = 2), s && (o++, r = 3), o === 1 ? r : -1;
1639
- }
1640
- /**
1641
- * 细分当前节点为四个子节点
1642
- */
1643
- subdivide() {
1644
- if (!this.isLeaf) return;
1645
- this.isLeaf = !1, this.children = [];
1646
- const t = (this.bounds.minX + this.bounds.maxX) / 2, e = (this.bounds.minY + this.bounds.maxY) / 2;
1647
- this.children[0] = new j(
1648
- new v(this.bounds.minX, t, this.bounds.minY, e),
1649
- this.capacity,
1650
- this.maxDepth,
1651
- this.depth + 1
1652
- ), this.children[1] = new j(
1653
- new v(t, this.bounds.maxX, this.bounds.minY, e),
1654
- this.capacity,
1655
- this.maxDepth,
1656
- this.depth + 1
1657
- ), this.children[2] = new j(
1658
- new v(this.bounds.minX, t, e, this.bounds.maxY),
1659
- this.capacity,
1660
- this.maxDepth,
1661
- this.depth + 1
1662
- ), this.children[3] = new j(
1663
- new v(t, this.bounds.maxX, e, this.bounds.maxY),
1664
- this.capacity,
1665
- this.maxDepth,
1666
- this.depth + 1
1667
- );
1668
- }
1669
- /**
1670
- * 查询与包围盒相交的线段节点
1671
- * @param box2 包围盒
1672
- * @returns 相交的节点数组
1673
- */
1674
- queryBox(t) {
1675
- const e = [];
1676
- if (!this.bounds.intersectBox(t))
1677
- return e;
1678
- for (const n of this.nodes)
1679
- t.intersectLineSegment(n.line) && e.push(n);
1680
- if (!this.isLeaf)
1681
- for (const n of this.children)
1682
- e.push(...n.queryBox(t));
1683
- return e;
1684
- }
1685
- /**
1686
- * 查询与圆形区域相交的线段节点
1687
- * @param pos 圆心
1688
- * @param radius 半径
1689
- * @returns 相交的节点数组
1690
- */
1691
- queryCircle(t, e) {
1692
- const n = [], i = new v(
1693
- t.x - e,
1694
- t.x + e,
1695
- t.y - e,
1696
- t.y + e
1697
- );
1698
- if (!this.bounds.intersectBox(i))
1699
- return n;
1700
- for (const s of this.nodes) {
1701
- const [o, r] = s.line.points, a = r.x - o.x, c = r.y - o.y, h = a * a + c * c;
1702
- let l = ((t.x - o.x) * a + (t.y - o.y) * c) / h;
1703
- l = Math.max(0, Math.min(1, l));
1704
- const d = o.x + l * a, f = o.y + l * c;
1705
- t.distance(new p(d, f)) <= e && n.push(s);
1706
- }
1707
- if (!this.isLeaf)
1708
- for (const s of this.children)
1709
- n.push(...s.queryCircle(t, e));
1710
- return n.sort((s) => s.line.length()), n;
1711
- }
1712
- /**
1713
- * 查询与矩形相交的线段节点
1714
- * @param rectangle 矩形
1715
- * @returns 相交的节点数组
1716
- */
1717
- queryRect(t) {
1718
- const e = [];
1719
- if (!this.bounds.intersectRectangle(t))
1720
- return e;
1721
- for (const n of this.nodes)
1722
- t.intersectLineSegment(n.line) && e.push(n);
1723
- if (!this.isLeaf)
1724
- for (const n of this.children)
1725
- e.push(...n.queryRect(t));
1726
- return e;
1918
+ const f = a.length(), y = d.length(), p = (f ** 2 + y ** 2) / (2 * y), x = d.end.clone().add(d.direction().multiplyScalar(-p)), [D, w] = this.getArcAngleRange(x, a.end, d.end);
1919
+ o(x, p, Math.min(D, w), Math.max(D, w)), l.push(u);
1920
+ } else
1921
+ a.clone().expansion(-this.width * 0.5).expandToRectangle(this.width).path2D((h, d) => s(h, d)), a.clone().directionMove(a.normal(), r * 0.5).directionMove(a.direction(), r * 0.5).expansion(-a.length() * 0.45, "end").forward(r * 0.5).expandToRectangle(r).path2D((h, d) => s(h, d)), a.clone().directionMove(a.normal(), -r * 0.5).directionMove(a.direction(), -r * 0.5).expansion(-a.length() * 0.45, "start").forward(-r * 0.5).expandToRectangle(r).path2D((h, d) => s(h, d));
1922
+ }), i = "yellow", this.lineSegments.forEach((c) => {
1923
+ if (!c.userData.isWindow) return !1;
1924
+ Array.isArray(c.userData.drawWindow) && c.userData.drawWindow.forEach((a) => {
1925
+ const { p: h, width: d } = a, u = g.from(h), f = u.clone().add(c.direction().multiplyScalar(d * 0.5)), y = u.clone().add(c.direction().multiplyScalar(-d * 0.5)), p = new I(f, y);
1926
+ s(p.start, p.end), p.expandToRectangle(this.width, "bothSides").path2D((x, D) => s(x, D));
1927
+ });
1928
+ }), n;
1727
1929
  }
1728
1930
  /**
1729
- * 查询与线段相交的线段节点
1730
- * @param lineSegment 线段
1731
- * @returns 相交的节点数组
1931
+ *
1932
+ * @param type
1732
1933
  */
1733
- queryLineSegment(t, e = !0) {
1734
- const n = [];
1735
- if (!this.bounds.intersectLineSegment(t))
1736
- return n;
1737
- for (const i of this.nodes)
1738
- t.intersectLineSegment(i.line, e) && n.push(i);
1739
- if (!this.isLeaf)
1740
- for (const i of this.children)
1741
- n.push(...i.queryLineSegment(t));
1742
- return n;
1934
+ async toDxfImageBlob(t = "Centimeters", e = "image/jpeg", n = "#000") {
1935
+ const i = this.toDrawDataJson(t);
1936
+ let s;
1937
+ if (typeof window < "u")
1938
+ s = document.createElement("canvas");
1939
+ else if (typeof global < "u") {
1940
+ const { createCanvas: c } = await O("canvas");
1941
+ s = c();
1942
+ } else
1943
+ throw new Error("创建画布失败");
1944
+ const o = 2 * i.scale, r = {
1945
+ cyan: "cyan",
1946
+ yellow: "yellow",
1947
+ white: "white"
1948
+ };
1949
+ s.width = i.width + o * 2, s.height = i.height + o * 2;
1950
+ const l = s.getContext("2d");
1951
+ return n && (l.fillStyle = n, l.fillRect(0, 0, s.width, s.height)), l.translate(i.width * 0.5 + o, i.height * 0.5 + o), i.line.forEach(([c, a, h, d, u]) => {
1952
+ l.strokeStyle = r[u], l.beginPath(), l.moveTo(c, a), l.lineTo(h, d), l.closePath(), l.stroke();
1953
+ }), i.arc.forEach(([c, a, h, d, u, f]) => {
1954
+ l.strokeStyle = r[f], l.beginPath(), l.arc(c, a, h, d * (Math.PI / 180), u * (Math.PI / 180)), l.stroke();
1955
+ }), l.beginPath(), i.dimensionLine.forEach((c) => {
1956
+ let [a, h, d, u] = c;
1957
+ const f = Math.min(h, u), y = Math.max(h, u), p = (s.width * 0.5 - 0.4 * i.scale) * (a < 0 ? -1 : 1), x = (y - f) * 0.45;
1958
+ l.fillStyle = "#fff", l.font = `${0.15 * i.scale}px Arial`, l.textAlign = "center", l.textBaseline = "middle", l.fillText((y - f).toFixed(2) + "cm", p, f + (y - f) * 0.5), l.moveTo(p - 0.1 * i.scale, f), l.lineTo(p + 0.1 * i.scale, f), l.moveTo(p, f), l.lineTo(p, x + f), l.moveTo(p, y), l.lineTo(p, y - x), l.moveTo(p - 0.1 * i.scale, y), l.lineTo(p + 0.1 * i.scale, y);
1959
+ }), l.closePath(), l.strokeStyle = "#fff", l.stroke(), "toBlob" in s ? new Promise((c) => {
1960
+ s.toBlob((a) => {
1961
+ c(a);
1962
+ }, e, 1);
1963
+ }) : s.toBuffer(e, { quality: 1 });
1743
1964
  }
1744
1965
  /**
1745
- * 包围盒转换为数组
1746
- * @param array
1747
- * @param colors
1748
- * @returns
1966
+ * 将点json结构转换为Dxf string
1749
1967
  */
1750
- boundsToArray(t = [], e, n = !0) {
1751
- return !this.isLeaf && n && this.children?.forEach((i) => i.boundsToArray(t, e)), t.push(...this.bounds.points.flatMap((i, s, o) => {
1752
- const r = o[(s + 1) % o.length];
1753
- return e?.push(...this.color), e?.push(...this.color), [i.x, i.y, 0, r.x, r.y, 0];
1754
- })), t;
1755
- }
1756
- }
1757
- class U {
1758
- map = /* @__PURE__ */ new Map();
1759
- gridSize;
1760
- constructor(t = 2) {
1761
- this.gridSize = t;
1968
+ toDxfString(t = "Millimeters") {
1969
+ const e = new W();
1970
+ e.setUnits(t), e.addLayer("cyan", W.ACI.CYAN, "DOTTED"), e.addLayer("yellow", W.ACI.YELLOW, "DOTTED"), e.addLayer("white", W.ACI.WHITE, "DOTTED");
1971
+ const n = this.toDrawDataJson();
1972
+ return n.line.forEach((i) => {
1973
+ let [s, o, r, l, c] = i;
1974
+ e.setActiveLayer(c), e.drawLine(s, o, r, l);
1975
+ }), n.arc.forEach((i) => {
1976
+ const [s, o, r, l, c, a] = i;
1977
+ e.setActiveLayer(a), e.drawArc(s, o, r, l, c);
1978
+ }), e.toDxfString();
1762
1979
  }
1763
1980
  /**
1764
- * 插入
1765
- * @param point
1766
- * @param userData
1981
+ * 将点云结构转换为DXF格式
1982
+ * @returns
1767
1983
  */
1768
- insert(t, e) {
1769
- if (!t || isNaN(t.x) || isNaN(t.y))
1770
- throw new Error("无效的点坐标");
1771
- const n = this.getGridId(t);
1772
- this.map.has(n) || this.map.set(n, /* @__PURE__ */ new Set());
1773
- const i = this.map.get(n), s = { point: t, userData: e };
1774
- i.add(s), t.userData.pointVirtualGrid = { set: i, target: s };
1984
+ toDxfBlob(t = "Millimeters") {
1985
+ return new Blob([this.toDxfString(t)]);
1775
1986
  }
1776
1987
  /**
1777
- * 批量加入
1778
- * @param points
1779
- */
1780
- insertBatch(t) {
1781
- for (const { point: e, userData: n } of t)
1782
- this.insert(e, n);
1988
+ * 下载原始json
1989
+ * @param filename
1990
+ */
1991
+ async downloadOriginalData(t) {
1992
+ const e = JSON.stringify(this.originalData, null, 2);
1993
+ if (typeof window < "u") {
1994
+ const n = new Blob([e], { type: "application/json" }), i = document.createElement("a");
1995
+ i.href = URL.createObjectURL(n), i.download = t, i.click();
1996
+ } else typeof global < "u" && (await O("fs", !1)).writeFileSync(t, e);
1783
1997
  }
1784
- /** 移除点
1785
- * @param point
1998
+ /**
1999
+ * 下载
2000
+ * @param filename
1786
2001
  */
1787
- remove(t) {
1788
- const { set: e, target: n } = t?.userData?.pointVirtualGrid;
1789
- e && (e.delete(n), delete t?.userData?.pointVirtualGridMap);
2002
+ async download(t, e = "Millimeters") {
2003
+ if (typeof window < "u") {
2004
+ const n = this.toDxfBlob(e), i = document.createElement("a");
2005
+ i.href = URL.createObjectURL(n), i.download = t + ".dxf", i.click();
2006
+ } else typeof global < "u" && (await O("fs", !1)).writeFileSync(t, this.toDxfString(e));
1790
2007
  }
1791
2008
  /**
1792
- * 获取通过坐标,获取唯一网格索引
1793
- * @param point
1794
- * @returns
2009
+ * 下载
2010
+ * @param filename
1795
2011
  */
1796
- getGridId(t) {
1797
- const e = Math.ceil(t.x / this.gridSize), n = Math.ceil(t.y / this.gridSize);
1798
- return `${e}.${n}`;
2012
+ async downloadImage(t, e = "Centimeters", n = "image/jpeg") {
2013
+ const i = await this.toDxfImageBlob(e, n);
2014
+ if (!i) return !1;
2015
+ if (typeof window < "u") {
2016
+ const s = document.createElement("a");
2017
+ s.href = URL.createObjectURL(i), s.download = t, s.click();
2018
+ } else typeof global < "u" ? (await O("fs", !1)).writeFileSync(t, i) : console.error("图片下载失败");
2019
+ return !0;
1799
2020
  }
1800
2021
  /**
1801
- *
1802
- * @param gridId
2022
+ * 计算原始数据的边界框
2023
+ * @description 计算所有线段的起点和终点的最小最大值,形成一个边界框
1803
2024
  * @returns
1804
2025
  */
1805
- decodeGridId(t) {
1806
- const [e, n] = t.split(".").map(Number);
1807
- return new p(e, n);
2026
+ computedOriginalSize(t, e = new C(0, 0, 0, 0)) {
2027
+ const n = t.flatMap((c) => [c.start.x, c.end.x]), i = t.flatMap((c) => [c.start.y, c.end.y]), s = Math.min(...n), o = Math.min(...i), r = Math.max(...n), l = Math.max(...i);
2028
+ return e.set(s, o, r, l), e;
1808
2029
  }
1809
2030
  /**
1810
- * 查询与矩形相交的点
1811
- * @param rectangle 矩形
1812
- * @returns 相交的节点数组
2031
+ * 创建数据
2032
+ * @param pointsGroups
2033
+ * @returns
1813
2034
  */
1814
- queryRect(t) {
1815
- const e = t.toBox(), n = Math.ceil(e.minX / this.gridSize), i = Math.ceil(e.maxX / this.gridSize), s = Math.ceil(e.minY / this.gridSize), o = Math.ceil(e.maxY / this.gridSize);
1816
- for (let r = n; r <= i; r++)
1817
- for (let a = s; a <= o; a++) {
1818
- const c = `${r}.${a}`;
1819
- if (!this.map.has(c)) continue;
1820
- this.map.get(c)?.forEach((l) => {
1821
- t.containsPoint(l.point);
1822
- });
1823
- }
2035
+ static createData(t, e = !0) {
2036
+ let n = 0;
2037
+ return t.flatMap((s) => {
2038
+ const o = s.map((r, l) => {
2039
+ const c = l === s.length - 1 ? 0 : l + 1, a = s[c];
2040
+ return {
2041
+ start: { x: r.x, y: r.y },
2042
+ end: { x: a.x, y: a.y },
2043
+ insetionArr: [
2044
+ {
2045
+ index: c + n
2046
+ }
2047
+ ]
2048
+ };
2049
+ });
2050
+ return n += s.length, e || (o.pop(), o[o.length - 1].insetionArr.length = 0, n--), o;
2051
+ });
1824
2052
  }
1825
- /**
1826
- * 查询与圆形区域相交的点
1827
- * @param pos 圆心
1828
- * @param radius 半径
1829
- * @returns 相交的节点数组
1830
- */
1831
- queryCircle(t, e) {
1832
- const n = new v(t.x - e, t.x + e, t.y - e, t.y + e), i = Math.ceil(n.minX / this.gridSize), s = Math.ceil(n.maxX / this.gridSize), o = Math.ceil(n.minY / this.gridSize), r = Math.ceil(n.maxY / this.gridSize), a = [];
1833
- for (let c = i; c <= s; c++)
1834
- for (let h = o; h <= r; h++) {
1835
- const l = `${c}.${h}`;
1836
- if (!this.map.has(l)) continue;
1837
- this.map.get(l)?.forEach((f) => {
1838
- t.distance(f.point) <= e && a.push(f);
1839
- });
1840
- }
1841
- return a;
2053
+ }
2054
+ function $(M) {
2055
+ if (M === null || typeof M != "object") return M;
2056
+ if (M instanceof Date) return new Date(M.getTime());
2057
+ if (Array.isArray(M)) return M.map($);
2058
+ const t = {};
2059
+ for (const e in M)
2060
+ Object.prototype.hasOwnProperty.call(M, e) && (t[e] = $(M[e]));
2061
+ return t;
2062
+ }
2063
+ const N = new I();
2064
+ class ht extends z {
2065
+ static name = "AngleCorrectionDxf";
2066
+ angle = 0;
2067
+ onAddFromParent(t) {
2068
+ t.findComponentByName("LineAnalysis").addEventListener("analysisCompleted", async () => this.update());
1842
2069
  }
1843
- /**
1844
- * 查询与包围盒相交的点
1845
- * @param box2 包围盒
1846
- * @returns 相交的节点数组
1847
- */
1848
- queryBox(t) {
1849
- const e = Math.ceil(t.minX / this.gridSize), n = Math.ceil(t.maxX / this.gridSize), i = Math.ceil(t.minY / this.gridSize), s = Math.ceil(t.maxY / this.gridSize), o = [];
1850
- for (let r = e; r <= n; r++)
1851
- for (let a = i; a <= s; a++) {
1852
- const c = `${r}.${a}`;
1853
- if (!this.map.has(c)) continue;
1854
- this.map.get(c)?.forEach((l) => {
1855
- t.containsPoint(l.point) && o.push(l);
1856
- });
2070
+ async update() {
2071
+ const t = this.parent, e = t.findComponentByName("Dxf"), n = t.findComponentByName("LineAnalysis");
2072
+ let i = 0, s = null;
2073
+ for (let c = 0; c < e.originalData.length; c++) {
2074
+ const a = e.originalData[c];
2075
+ if (N.start.copy(a.start), N.end.copy(a.end), a.isVerticalReferenceLine) {
2076
+ const [h, d] = a.start.y < a.end.y ? [N.start, N.end] : [N.end, N.start];
2077
+ i = -new I(h, d).direction().angleBetween(new g(0, 1), "angle", "360"), s = null;
2078
+ break;
1857
2079
  }
1858
- return o;
2080
+ (!s || N.length() > s.length()) && (s = N.clone(), s.userData.index = c);
2081
+ }
2082
+ if (s) {
2083
+ e.originalData[s.userData.index].isVerticalReferenceLine = !0;
2084
+ const [c, a] = s.start.y < s.end.y ? [s.start, s.end] : [s.end, s.start];
2085
+ i = -new I(c, a).direction().angleBetween(new g(0, 1), "angle", "360");
2086
+ }
2087
+ const o = e.originalBox.center, r = g.zero(), l = e.originalData.map((c) => {
2088
+ const a = r.copy(c.start).division(o).rotate(g.zero(), i * (Math.PI / 180)).toJson(c.start.z), h = r.copy(c.end).division(o).rotate(g.zero(), i * (Math.PI / 180)).toJson(c.end.z), d = Object.assign($(c), { start: a, end: h });
2089
+ return d.drawWindow && d.drawWindow.forEach((u) => {
2090
+ u.p = r.copy(u.p).division(o).rotate(g.zero(), i * (Math.PI / 180)).toJson(u.p.z);
2091
+ }), d;
2092
+ });
2093
+ n.appendLineSegmentList.forEach((c) => {
2094
+ const a = c.clone();
2095
+ a.start.division(o).rotate(g.zero(), i * (Math.PI / 180)), a.end.division(o).rotate(g.zero(), i * (Math.PI / 180)), l.push({
2096
+ start: a.start.toJson(e.originalZAverage),
2097
+ end: a.end.toJson(e.originalZAverage),
2098
+ insetionArr: [],
2099
+ length: a.length()
2100
+ });
2101
+ }), await this.set(l, e.width, e.scale), this.lineOffset(), this.doorLineSegment = e.doorLineSegment.map((c) => {
2102
+ const a = c.clone();
2103
+ return a.start.division(o).rotate(g.zero(), i * (Math.PI / 180)), a.end.division(o).rotate(g.zero(), i * (Math.PI / 180)), a;
2104
+ }), this.angle = i, this.dispatchEvent({
2105
+ type: "updateData"
2106
+ });
1859
2107
  }
1860
- /**
1861
- * 查找相同点
1862
- * @param point
1863
- */
1864
- queryPoint(t) {
1865
- const e = this.getGridId(t), n = [];
1866
- return this.map.has(e) && this.map.get(e)?.forEach((s) => {
1867
- t.equal(s.point) && n.push(s);
1868
- }), n;
2108
+ }
2109
+ class et extends V {
2110
+ static name = "Variable";
2111
+ originalLineVisible = !0;
2112
+ dxfVisible = !0;
2113
+ whiteModelVisible = !0;
2114
+ isLook = !1;
2115
+ currentWheel = 0;
2116
+ pointerMove = { x: 0, y: 0 };
2117
+ currentKeyUp = "";
2118
+ currentKeyDown = "";
2119
+ currentMouseUp = "";
2120
+ currentMouseDown = "";
2121
+ focus = !1;
2122
+ set(t, e) {
2123
+ if (t in this) {
2124
+ const n = this[t];
2125
+ this[t] = e, this.dispatchEvent({
2126
+ type: t,
2127
+ value: e,
2128
+ oldValue: n
2129
+ });
2130
+ }
1869
2131
  }
1870
- /**
1871
- * 查找点自己
1872
- * @param point
1873
- */
1874
- queryPointSelf(t) {
1875
- return t.userData.pointVirtualGrid && t.userData.pointVirtualGrid.target ? t.userData.pointVirtualGrid.target : null;
2132
+ get(t) {
2133
+ if (t in this) return this[t];
1876
2134
  }
1877
2135
  }
1878
- class rt {
2136
+ class dt {
1879
2137
  // 所有可查找的点位
1880
2138
  possibleDoorPoints = [];
1881
2139
  doorPoint = [];
@@ -1910,32 +2168,32 @@ class rt {
1910
2168
  const o = this.dxf, r = this.searchNearby(t, e, i, s);
1911
2169
  r.push(
1912
2170
  ...t.map((c) => {
1913
- const h = this.searchAlongDirection(c, i);
1914
- if (h) return {
2171
+ const a = this.searchAlongDirection(c, i);
2172
+ if (a) return {
1915
2173
  start: c.point,
1916
- end: h.point
2174
+ end: a.point
1917
2175
  };
1918
- const l = this.searchAlongNormalDirection(c, i);
1919
- if (l) return {
2176
+ const h = this.searchAlongNormalDirection(c, i);
2177
+ if (h) return {
1920
2178
  start: c.point,
1921
- end: l.point
2179
+ end: h.point
1922
2180
  };
1923
2181
  }).filter((c) => !!c && c.start.distance(c.end) < i)
1924
2182
  );
1925
- const a = [];
2183
+ const l = [];
1926
2184
  return r.forEach((c) => {
1927
- const h = new L(c?.start, c?.end), l = h.length();
1928
- if (l < n) return;
1929
- const d = h.normal(), f = h.direction(), m = (l - o.width * 2) / 2;
2185
+ const a = new I(c?.start, c?.end), h = a.length();
2186
+ if (h < n) return;
2187
+ const d = a.normal(), u = a.direction(), f = (h - o.width * 2) / 2;
1930
2188
  for (let y = 0; y < 3; y++) {
1931
- const u = h.start.clone().add(f.clone().multiplyScalar(o.width + m * y)), x = new L(
1932
- u,
1933
- u.clone().add(d.clone().multiplyScalar(1))
2189
+ const p = a.start.clone().add(u.clone().multiplyScalar(o.width + f * y)), x = new I(
2190
+ p,
2191
+ p.clone().add(d.clone().multiplyScalar(1))
1934
2192
  );
1935
2193
  if (x.directionMove(d, -0.5), this.quadtree.queryLineSegment(x).length) return;
1936
2194
  }
1937
- a.push(h);
1938
- }), a;
2195
+ l.push(a);
2196
+ }), l;
1939
2197
  }
1940
2198
  /** 添加可查找点的过滤规则
1941
2199
  * @param rule
@@ -1952,7 +2210,7 @@ class rt {
1952
2210
  return this.lineSegments.forEach((e) => {
1953
2211
  e.points.forEach((n, i) => {
1954
2212
  for (let o = 0; o < this._pointsExcludeRule.length; o++) if (this._pointsExcludeRule[o](e, n, i)) return;
1955
- this.pointVirtualGrid.queryPoint(n).filter((o) => o.userData !== e).length === 0 && t.push({ line: e, point: n, uuid: N() });
2213
+ this.pointVirtualGrid.queryPoint(n).filter((o) => o.userData !== e).length === 0 && t.push({ line: e, point: n, uuid: k() });
1956
2214
  });
1957
2215
  }), t;
1958
2216
  }
@@ -1964,21 +2222,21 @@ class rt {
1964
2222
  return e.doors.forEach((i) => {
1965
2223
  const s = e.lineSegments[i[4]], o = e.originalData[i[4]];
1966
2224
  if (o.drawDoorData) {
1967
- const r = p.from(o.drawDoorData.start), a = p.from(o.drawDoorData.n), c = n.queryPoint(r).filter((h) => {
1968
- if (h.userData === s) return !1;
1969
- const l = h.userData, d = l.direction();
1970
- l.start.equal(r) && d.multiplyScalar(-1);
1971
- const f = a.angleBetween(d, "angle");
1972
- return f > 80 || f < 10;
2225
+ const r = g.from(o.drawDoorData.start), l = g.from(o.drawDoorData.n), c = n.queryPoint(r).filter((a) => {
2226
+ if (a.userData === s) return !1;
2227
+ const h = a.userData, d = h.direction();
2228
+ h.start.equal(r) && d.multiplyScalar(-1);
2229
+ const u = l.angleBetween(d, "angle");
2230
+ return u > 80 || u < 10;
1973
2231
  });
1974
2232
  c.length && t.push({
1975
2233
  line: c[0].userData,
1976
2234
  point: r,
1977
- uuid: N()
2235
+ uuid: k()
1978
2236
  });
1979
2237
  } else if (o.doorDirectConnection) {
1980
2238
  this.continueFind = !1;
1981
- const r = new L(p.from(o.start), p.from(o.end));
2239
+ const r = new I(g.from(o.start), g.from(o.end));
1982
2240
  r.userData = {
1983
2241
  doorDirectConnection: !0,
1984
2242
  isDoor: !0
@@ -1994,8 +2252,8 @@ class rt {
1994
2252
  searchDoubleLinePoint() {
1995
2253
  const t = /* @__PURE__ */ new Map();
1996
2254
  return this.resultList.flatMap((e) => {
1997
- const n = this.lineSegments[e.sourceIndex], i = this.lineSegments[e.targetIndex], s = i.projectPoint(n.start), o = i.projectPoint(n.end), r = n.projectPoint(i.start), a = n.projectPoint(i.end), c = s && o ? -1 : s ? 0 : o ? 1 : -1, h = r && a ? -1 : r ? 0 : a ? 1 : -1;
1998
- t.has(e.sourceIndex) ? t.get(e.sourceIndex) != c && t.set(e.sourceIndex, -1) : t.set(e.sourceIndex, c), t.has(e.targetIndex) ? t.get(e.targetIndex) != h && t.set(e.targetIndex, -1) : t.set(e.targetIndex, h);
2255
+ const n = this.lineSegments[e.sourceIndex], i = this.lineSegments[e.targetIndex], s = i.projectPoint(n.start), o = i.projectPoint(n.end), r = n.projectPoint(i.start), l = n.projectPoint(i.end), c = s && o ? -1 : s ? 0 : o ? 1 : -1, a = r && l ? -1 : r ? 0 : l ? 1 : -1;
2256
+ t.has(e.sourceIndex) ? t.get(e.sourceIndex) != c && t.set(e.sourceIndex, -1) : t.set(e.sourceIndex, c), t.has(e.targetIndex) ? t.get(e.targetIndex) != a && t.set(e.targetIndex, -1) : t.set(e.targetIndex, a);
1999
2257
  }), t;
2000
2258
  }
2001
2259
  /** 查找方案一:最近点查找
@@ -2008,93 +2266,93 @@ class rt {
2008
2266
  */
2009
2267
  searchNearby(t, e = [], n = this.doorSearchDistance, i = this.doorSearchNearAngle) {
2010
2268
  const s = this.findPointVirtualGrid, o = this.quadtree;
2011
- function r({ point: u, line: x }, w, S) {
2269
+ function r({ point: p, line: x }, D, w) {
2012
2270
  const b = x.direction();
2013
- x.start === u && b.multiplyScalar(-1);
2014
- const P = s.queryCircle(u, n).filter((D) => D.userData !== x).sort((D, E) => D.point.distance(u) - E.point.distance(u)), A = [];
2015
- for (let D = 0; D < P.length; D++) {
2016
- const E = e.findIndex((T) => T.point === P[D].point), B = t[w].uuid, Y = e[E].uuid;
2017
- if (S.has(`${B}.${Y}`)) continue;
2018
- S.add(`${B}.${Y}`), S.add(`${Y}.${B}`);
2019
- const Q = P[D].point, C = new L(u.clone(), Q.clone());
2020
- if (C.direction().angleBetween(b, "angle") < i) {
2021
- const T = t[E].line.direction();
2022
- P[D].userData.start.equal(P[D].point) && T.multiplyScalar(-1), C.direction().multiplyScalar(-1).angleBetween(T, "angle") < i && (o.queryLineSegment(C).length || A.push({
2023
- findData: P[D],
2024
- findUuid: Y,
2025
- doorLine: C,
2026
- doorUuid: B
2271
+ x.start === p && b.multiplyScalar(-1);
2272
+ const P = s.queryCircle(p, n).filter((m) => m.userData !== x).sort((m, A) => m.point.distance(p) - A.point.distance(p)), S = [];
2273
+ for (let m = 0; m < P.length; m++) {
2274
+ const A = e.findIndex((j) => j.point === P[m].point), E = t[D].uuid, L = e[A].uuid;
2275
+ if (w.has(`${E}.${L}`)) continue;
2276
+ w.add(`${E}.${L}`), w.add(`${L}.${E}`);
2277
+ const v = P[m].point, B = new I(p.clone(), v.clone());
2278
+ if (B.direction().angleBetween(b, "angle") < i) {
2279
+ const j = t[A].line.direction();
2280
+ P[m].userData.start.equal(P[m].point) && j.multiplyScalar(-1), B.direction().multiplyScalar(-1).angleBetween(j, "angle") < i && (o.queryLineSegment(B).length || S.push({
2281
+ findData: P[m],
2282
+ findUuid: L,
2283
+ doorLine: B,
2284
+ doorUuid: E
2027
2285
  }));
2028
2286
  }
2029
2287
  }
2030
- return A;
2288
+ return S;
2031
2289
  }
2032
- function a(u, x, w, S, b) {
2033
- S.add(u);
2290
+ function l(p, x, D, w, b) {
2291
+ w.add(p);
2034
2292
  const P = [];
2035
2293
  b && P.push(b);
2036
- for (let A = 0; A < w.length; A++) {
2037
- const D = w[A];
2038
- if (x.has(D.findUuid)) {
2039
- const E = x.get(D.findUuid);
2040
- a(D.findUuid, x, E, S, D) && P.push(D);
2041
- } else P.push(D);
2294
+ for (let S = 0; S < D.length; S++) {
2295
+ const m = D[S];
2296
+ if (x.has(m.findUuid)) {
2297
+ const A = x.get(m.findUuid);
2298
+ l(m.findUuid, x, A, w, m) && P.push(m);
2299
+ } else P.push(m);
2042
2300
  }
2043
- return P.sort((A, D) => A.doorLine.length() - D.doorLine.length()), b && P[0] === b ? (w.splice(0), !0) : (w.splice(1), !1);
2301
+ return P.sort((S, m) => S.doorLine.length() - m.doorLine.length()), b && P[0] === b ? (D.splice(0), !0) : (D.splice(1), !1);
2044
2302
  }
2045
- const c = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Map();
2046
- t.map((u, x) => {
2047
- const w = r(u, x, c);
2048
- w.length && h.set(u.uuid, w);
2303
+ const c = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Map();
2304
+ t.map((p, x) => {
2305
+ const D = r(p, x, c);
2306
+ D.length && a.set(p.uuid, D);
2049
2307
  }), c.clear();
2050
- const l = /* @__PURE__ */ new Map();
2051
- h.forEach((u, x) => {
2052
- if (!c.has(x) && u.length && a(x, h, u, c), u.length) {
2053
- const w = u[0];
2054
- l.has(w.doorUuid) || l.set(w.doorUuid, []), l.get(w.doorUuid)?.push(w), l.has(w.findUuid) || l.set(w.findUuid, []), l.get(w.findUuid)?.push(w);
2308
+ const h = /* @__PURE__ */ new Map();
2309
+ a.forEach((p, x) => {
2310
+ if (!c.has(x) && p.length && l(x, a, p, c), p.length) {
2311
+ const D = p[0];
2312
+ h.has(D.doorUuid) || h.set(D.doorUuid, []), h.get(D.doorUuid)?.push(D), h.has(D.findUuid) || h.set(D.findUuid, []), h.get(D.findUuid)?.push(D);
2055
2313
  }
2056
2314
  });
2057
2315
  const d = /* @__PURE__ */ new Set();
2058
- l.forEach((u) => {
2059
- if (u.length > 1) {
2060
- u.sort((x, w) => x.doorLine.length() - w.doorLine.length());
2061
- for (let x = 1; x < u.length; x++) d.add(u[x]);
2316
+ h.forEach((p) => {
2317
+ if (p.length > 1) {
2318
+ p.sort((x, D) => x.doorLine.length() - D.doorLine.length());
2319
+ for (let x = 1; x < p.length; x++) d.add(p[x]);
2062
2320
  }
2063
2321
  });
2064
- const f = [], m = [];
2065
- h.forEach((u) => {
2066
- if (u.length) {
2067
- const x = u[0];
2068
- d.has(x) || (f.push(x), m.push(x.doorUuid, x.findUuid));
2322
+ const u = [], f = [];
2323
+ a.forEach((p) => {
2324
+ if (p.length) {
2325
+ const x = p[0];
2326
+ d.has(x) || (u.push(x), f.push(x.doorUuid, x.findUuid));
2069
2327
  }
2070
2328
  });
2071
2329
  const y = [];
2072
- return f.forEach((u) => {
2073
- const x = t.findIndex((E) => E.uuid === u.doorUuid), w = e.findIndex((E) => E.uuid === u.findUuid), S = t[x].point.clone(), b = e[w].point.clone(), P = this.findLongLineSegment(t[x].line), A = this.findLongLineSegment(e[w].line), D = P.projectPoint(b);
2074
- if (D) {
2075
- S.copy(D);
2076
- const E = new L(S, b), B = A.includedAngle(E);
2077
- (B < 10 || B > 170 || Math.abs(90 - B) < 10) && y.push({
2078
- start: S,
2330
+ return u.forEach((p) => {
2331
+ const x = t.findIndex((A) => A.uuid === p.doorUuid), D = e.findIndex((A) => A.uuid === p.findUuid), w = t[x].point.clone(), b = e[D].point.clone(), P = this.findLongLineSegment(t[x].line), S = this.findLongLineSegment(e[D].line), m = P.projectPoint(b);
2332
+ if (m) {
2333
+ w.copy(m);
2334
+ const A = new I(w, b), E = S.includedAngle(A);
2335
+ (E < 10 || E > 170 || Math.abs(90 - E) < 10) && y.push({
2336
+ start: w,
2079
2337
  end: b
2080
2338
  });
2081
2339
  } else {
2082
- const E = A.projectPoint(S);
2083
- E && b.copy(E);
2084
- const B = new L(S, b), Y = P.includedAngle(B);
2085
- (Y < 10 || Y > 170 || Math.abs(90 - Y) < 10) && y.push({
2086
- start: S,
2340
+ const A = S.projectPoint(w);
2341
+ A && b.copy(A);
2342
+ const E = new I(w, b), L = P.includedAngle(E);
2343
+ (L < 10 || L > 170 || Math.abs(90 - L) < 10) && y.push({
2344
+ start: w,
2087
2345
  end: b
2088
2346
  });
2089
2347
  }
2090
2348
  }), e.splice(
2091
2349
  0,
2092
2350
  e.length,
2093
- ...e.filter((u) => m.indexOf(u.uuid) === -1)
2351
+ ...e.filter((p) => f.indexOf(p.uuid) === -1)
2094
2352
  ), t.splice(
2095
2353
  0,
2096
2354
  t.length,
2097
- ...t.filter((u) => m.indexOf(u.uuid) === -1)
2355
+ ...t.filter((p) => f.indexOf(p.uuid) === -1)
2098
2356
  ), y;
2099
2357
  }
2100
2358
  /** 方案二: 沿方向查找
@@ -2105,12 +2363,12 @@ class rt {
2105
2363
  searchAlongDirection({ point: t, line: e }, n = this.doorSearchDistance) {
2106
2364
  const i = this.quadtree, s = e.direction();
2107
2365
  e.start === t && s.multiplyScalar(-1);
2108
- const o = t.clone().add(s.clone().multiplyScalar(n)), r = new L(t.clone(), o), a = i.queryLineSegment(r).map((c) => ({
2366
+ const o = t.clone().add(s.clone().multiplyScalar(n)), r = new I(t.clone(), o), l = i.queryLineSegment(r).map((c) => ({
2109
2367
  point: c.line.getIntersection(r),
2110
2368
  line: c.line
2111
- })).filter((c) => c.point).sort((c, h) => t.distance(c.point) - t.distance(h.point));
2112
- if (a.length) {
2113
- const c = a[0];
2369
+ })).filter((c) => c.point).sort((c, a) => t.distance(c.point) - t.distance(a.point));
2370
+ if (l.length) {
2371
+ const c = l[0];
2114
2372
  if (Math.abs(90 - c.line.direction().angleBetween(s, "angle")) < 5)
2115
2373
  return c;
2116
2374
  }
@@ -2122,22 +2380,22 @@ class rt {
2122
2380
  * @returns
2123
2381
  */
2124
2382
  searchAlongNormalDirection({ point: t, line: e }, n = this.doorSearchDistance) {
2125
- const i = this.pointVirtualGrid, s = this.quadtree, o = e.direction(), r = e.start.normal(e.end), a = e.start.clone();
2126
- e.start === t && o.multiplyScalar(-1), e.start === t && a.copy(e.end);
2127
- const c = i.queryPoint(a).filter((d) => d.userData !== e);
2383
+ const i = this.pointVirtualGrid, s = this.quadtree, o = e.direction(), r = e.start.normal(e.end), l = e.start.clone();
2384
+ e.start === t && o.multiplyScalar(-1), e.start === t && l.copy(e.end);
2385
+ const c = i.queryPoint(l).filter((d) => d.userData !== e);
2128
2386
  for (let d = 0; d < c.length; d++) {
2129
- const f = c[d], m = f.userData, y = m.direction();
2130
- if (m.start === f.point && o.multiplyScalar(-1), y.angleBetween(r) / (Math.PI / 180) > 90) {
2387
+ const u = c[d], f = u.userData, y = f.direction();
2388
+ if (f.start === u.point && o.multiplyScalar(-1), y.angleBetween(r) / (Math.PI / 180) > 90) {
2131
2389
  r.multiplyScalar(-1);
2132
2390
  break;
2133
2391
  }
2134
2392
  }
2135
- const h = new L(t.clone(), t.clone().add(r.multiplyScalar(n))), l = s.queryLineSegment(h).map((d) => ({
2136
- point: d.line.getIntersection(h),
2393
+ const a = new I(t.clone(), t.clone().add(r.multiplyScalar(n))), h = s.queryLineSegment(a).map((d) => ({
2394
+ point: d.line.getIntersection(a),
2137
2395
  line: d.line
2138
- })).filter((d) => d.point).sort((d, f) => t.distance(d.point) - t.distance(f.point));
2139
- if (l.length) {
2140
- const d = l[0];
2396
+ })).filter((d) => d.point).sort((d, u) => t.distance(d.point) - t.distance(u.point));
2397
+ if (h.length) {
2398
+ const d = h[0];
2141
2399
  if (Math.abs(90 - d.line.direction().angleBetween(r, "angle")) < 5)
2142
2400
  return d;
2143
2401
  }
@@ -2166,12 +2424,12 @@ class rt {
2166
2424
  return e;
2167
2425
  }
2168
2426
  }
2169
- class at extends q {
2427
+ class ut extends V {
2170
2428
  static name = "LineAnalysis";
2171
2429
  Dxf = null;
2172
2430
  Variable = null;
2173
2431
  lineSegmentList = [];
2174
- container = new M.Group();
2432
+ container = new q.Group();
2175
2433
  // 误差角度
2176
2434
  errorAngle = 4;
2177
2435
  width = 0.4;
@@ -2180,7 +2438,7 @@ class at extends q {
2180
2438
  * @param parent
2181
2439
  */
2182
2440
  onAddFromParent(t) {
2183
- this.Dxf = t.findComponentByType(X), this.Variable = this.parent?.findComponentByType(_), this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this)), this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
2441
+ this.Dxf = t.findComponentByType(z), this.Variable = this.parent?.findComponentByType(et), this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this)), this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
2184
2442
  }
2185
2443
  /**
2186
2444
  *
@@ -2190,15 +2448,15 @@ class at extends q {
2190
2448
  * @returns
2191
2449
  */
2192
2450
  expandLineSegment(t, e, n = 0.1) {
2193
- const i = e.normal(t), s = e.direction(t).mutiplyScalar(n * 0.5), o = t.direction(e).mutiplyScalar(n * 0.5), r = i.x * n * 0.5, a = i.y * n * 0.5;
2451
+ const i = e.normal(t), s = e.direction(t).mutiplyScalar(n * 0.5), o = t.direction(e).mutiplyScalar(n * 0.5), r = i.x * n * 0.5, l = i.y * n * 0.5;
2194
2452
  return {
2195
2453
  points: [
2196
2454
  // 第一条线
2197
- new p(t.x + r, t.y + a).add(o),
2198
- new p(e.x + r, e.y + a).add(s),
2455
+ new g(t.x + r, t.y + l).add(o),
2456
+ new g(e.x + r, e.y + l).add(s),
2199
2457
  // 第二条线
2200
- new p(t.x - r, t.y - a).add(o),
2201
- new p(e.x - r, e.y - a).add(s)
2458
+ new g(t.x - r, t.y - l).add(o),
2459
+ new g(e.x - r, e.y - l).add(s)
2202
2460
  ],
2203
2461
  indices: [0, 1, 1, 3, 3, 2, 2, 0],
2204
2462
  rectIndices: [0, 1, 3, 2, 0]
@@ -2212,7 +2470,7 @@ class at extends q {
2212
2470
  */
2213
2471
  addData(t, e) {
2214
2472
  const n = this.Dxf;
2215
- n.data.push([t.clone(), e.clone(), [], !1, n.data.length]), this.appendLineSegmentList.push(new L(t.clone(), e.clone()));
2473
+ n.data.push([t.clone(), e.clone(), [], !1, n.data.length]), this.appendLineSegmentList.push(new I(t.clone(), e.clone()));
2216
2474
  }
2217
2475
  /** 结果分析创建矩形
2218
2476
  * @param result
@@ -2220,14 +2478,14 @@ class at extends q {
2220
2478
  createRectangle(t) {
2221
2479
  const e = this.Dxf, n = t.project, i = t.project2;
2222
2480
  n.includedAngle(i) > 135 && (i.points = [i.points[1], i.points[0]]), this.addData(n.points[0], i.points[0]), this.addData(n.points[1], i.points[1]);
2223
- const s = n.points[0].distance(i.points[0]), o = n.points[1].distance(i.points[1]), r = Math.ceil(Math.max(s, o) / e.width), a = s / r, c = o / r, h = i.points[0].direction(n.points[0]), l = i.points[1].direction(n.points[1]), d = n.points[0].clone(), f = n.points[1].clone(), m = f.direction(d);
2224
- m.multiplyScalar(e.width * 0.5);
2225
- const y = d.clone().add(m), u = f.clone().add(m.multiplyScalar(-1)), x = d.direction(f), w = y.direction(u);
2226
- if (!(x.x > 0 && w.x < 0 || x.x < 0 && w.x > 0 || x.y > 0 && w.y < 0 || x.y < 0 && w.y > 0)) {
2227
- d.set(y.x, y.y), f.set(u.x, u.y);
2228
- for (let S = 1; S < r; S++) {
2229
- const b = h.clone().multiplyScalar(a * S), P = l.clone().multiplyScalar(c * S), A = d.clone().add(b), D = f.clone().add(P);
2230
- this.addData(A, D);
2481
+ const s = n.points[0].distance(i.points[0]), o = n.points[1].distance(i.points[1]), r = Math.ceil(Math.max(s, o) / e.width), l = s / r, c = o / r, a = i.points[0].direction(n.points[0]), h = i.points[1].direction(n.points[1]), d = n.points[0].clone(), u = n.points[1].clone(), f = u.direction(d);
2482
+ f.multiplyScalar(e.width * 0.5);
2483
+ const y = d.clone().add(f), p = u.clone().add(f.multiplyScalar(-1)), x = d.direction(u), D = y.direction(p);
2484
+ if (!(x.x > 0 && D.x < 0 || x.x < 0 && D.x > 0 || x.y > 0 && D.y < 0 || x.y < 0 && D.y > 0)) {
2485
+ d.set(y.x, y.y), u.set(p.x, p.y);
2486
+ for (let w = 1; w < r; w++) {
2487
+ const b = a.clone().multiplyScalar(l * w), P = h.clone().multiplyScalar(c * w), S = d.clone().add(b), m = u.clone().add(P);
2488
+ this.addData(S, m);
2231
2489
  }
2232
2490
  }
2233
2491
  }
@@ -2237,7 +2495,7 @@ class at extends q {
2237
2495
  */
2238
2496
  buildQuadtree() {
2239
2497
  const t = this.Dxf, e = [];
2240
- this.quadtree = new j(t.originalBox, 2), t.lineSegments.forEach((n) => {
2498
+ this.quadtree = new T(t.originalBox, 2), t.lineSegments.forEach((n) => {
2241
2499
  n.userData?.isDoor || (this.quadtree?.insert({
2242
2500
  line: n,
2243
2501
  userData: e.length
@@ -2254,12 +2512,12 @@ class at extends q {
2254
2512
  this.buildQuadtree();
2255
2513
  const t = this.quadtree, e = this.lineSegmentList, n = /* @__PURE__ */ new Set(), i = [];
2256
2514
  e.forEach((s, o) => {
2257
- const r = e[o], a = O.fromByLineSegment(r, this.width * 2, !1, -0.01);
2258
- t.queryRect(a).map((h) => h.userData).filter((h) => h !== o).forEach((h) => {
2515
+ const r = e[o], l = J.fromByLineSegment(r, this.width * 2, !1, -0.01);
2516
+ t.queryRect(l).map((a) => a.userData).filter((a) => a !== o).forEach((a) => {
2259
2517
  try {
2260
- if (n.has(`${o}-${h}`) || n.has(`${h}-${o}`)) return;
2261
- const l = this.projectionAnalysis(h, o, r, e);
2262
- l && i.push(l), n.add(`${o}-${h}`);
2518
+ if (n.has(`${o}-${a}`) || n.has(`${a}-${o}`)) return;
2519
+ const h = this.projectionAnalysis(a, o, r, e);
2520
+ h && i.push(h), n.add(`${o}-${a}`);
2263
2521
  } catch {
2264
2522
  }
2265
2523
  });
@@ -2272,37 +2530,163 @@ class at extends q {
2272
2530
  * @returns
2273
2531
  */
2274
2532
  projectionAnalysis(t, e, n, i) {
2275
- const s = i[t], o = n.direction(), r = s.direction(), a = o.angleBetween(r) / (Math.PI / 180);
2276
- if (a < this.errorAngle || a > 180 - this.errorAngle) {
2533
+ const s = i[t], o = n.direction(), r = s.direction(), l = o.angleBetween(r) / (Math.PI / 180);
2534
+ if (l < this.errorAngle || l > 180 - this.errorAngle) {
2277
2535
  let c;
2278
- const h = s.projectLineSegment(n), l = n.projectLineSegment(s);
2279
- return h.getLength() > l.getLength() ? c = {
2536
+ const a = s.projectLineSegment(n), h = n.projectLineSegment(s);
2537
+ return a.getLength() > h.getLength() ? c = {
2280
2538
  target: s,
2281
2539
  targetIndex: t,
2282
2540
  source: n,
2283
2541
  sourceIndex: e,
2284
- project: h,
2285
- project2: l
2542
+ project: a,
2543
+ project2: h
2286
2544
  } : c = {
2287
2545
  target: n,
2288
2546
  targetIndex: e,
2289
2547
  source: s,
2290
2548
  sourceIndex: t,
2291
- project: l,
2292
- project2: h
2549
+ project: h,
2550
+ project2: a
2293
2551
  }, !c || c.project.getLength() < 0.2 || c.project2.getLength() < 0.2 ? void 0 : c;
2294
2552
  }
2295
2553
  }
2296
2554
  doorSearchNearAngle = 110;
2297
2555
  doorSearchDistance = 2;
2298
2556
  doors = [];
2557
+ DoorsAnalysis;
2299
2558
  doorsAnalysis() {
2300
- new rt(this), this.dispatchEvent({
2559
+ this.DoorsAnalysis = new dt(this), this.dispatchEvent({
2301
2560
  type: "analysisCompleted"
2302
2561
  });
2303
2562
  }
2304
2563
  }
2305
- class ct extends it {
2564
+ class ft extends V {
2565
+ static name = "ThreeVJia";
2566
+ lineSegments = [];
2567
+ onAddFromParent() {
2568
+ (this.parent?.findComponentByName("AngleCorrectionDxf")).addEventListener("updateData", async () => this.updateData());
2569
+ }
2570
+ updateData() {
2571
+ const t = this.parent?.findComponentByName("LineAnalysis"), e = this.parent?.findComponentByName("Dxf");
2572
+ this.parent?.findComponentByName("Renderer");
2573
+ const n = this.parent?.findComponentByName("AngleCorrectionDxf"), i = /* @__PURE__ */ new Map();
2574
+ let s = [...e.lineSegments], o = [], r = [];
2575
+ t.resultList.forEach((a) => {
2576
+ const h = i.get(a.target) ?? [], d = i.get(a.source) ?? [], u = a.project.clone(), f = a.project2.clone();
2577
+ u.includedAngle(f) > 135 && (f.points = [f.points[1], f.points[0]]), h.push(...u.points), d.push(...f.points), i.set(a.target, h), i.set(a.source, d);
2578
+ const y = new I(u.start, f.start), p = new I(u.end, f.end), x = new I(y.center, p.center);
2579
+ x.userData.wallWidth = Math.max(y.length(), p.length()), o.push(x);
2580
+ });
2581
+ const l = [];
2582
+ s = s.filter((a) => {
2583
+ if (r.indexOf(a) > -1) return !1;
2584
+ if (i.has(a)) {
2585
+ const h = i.get(a), d = a.clone();
2586
+ if (h) {
2587
+ for (let f = 0; f < h.length; f += 2) {
2588
+ const y = h[f], p = h[f + 1];
2589
+ y.userData.length = y.distance(d.start), p.userData.length = p.distance(d.start), y.userData.type = "start", p.userData.type = "end", d.start.distance(y) > d.start.distance(p) && (h[f] = p, h[f + 1] = y, y.userData.type = "end", p.userData.type = "start");
2590
+ }
2591
+ h.sort((f, y) => f.userData.length - y.userData.length);
2592
+ const u = [];
2593
+ for (let f = 0; f < h.length; f++) {
2594
+ const y = h[f];
2595
+ y.userData.type === "start" ? (u.length === 0 && (l.push(new I(d.start.clone(), y.clone())), d.start.copy(y)), u.push("start")) : (u.pop(), u.length === 0 && d.start.copy(y));
2596
+ }
2597
+ l.push(d);
2598
+ }
2599
+ return !1;
2600
+ }
2601
+ return !0;
2602
+ }), s.push(...o), s.push(...l.filter((a) => a.length() > 0.05));
2603
+ const c = e.box.center;
2604
+ s = s.map((a) => {
2605
+ const h = a.clone();
2606
+ return h.start.rotate(c, n.angle * (Math.PI / 180)), h.end.rotate(c, n.angle * (Math.PI / 180)), h;
2607
+ }), this.lineSegments = s;
2608
+ }
2609
+ toJson() {
2610
+ const e = /* @__PURE__ */ new Map();
2611
+ let n = 0;
2612
+ return {
2613
+ version: "2",
2614
+ name: "测试",
2615
+ communityName: "测试",
2616
+ city: "",
2617
+ province: "",
2618
+ height: 2.8,
2619
+ walls: this.lineSegments.map((i) => {
2620
+ if (!(i.userData.isDoor && !i.userData.doorDirectConnection))
2621
+ return e.set(i, n), {
2622
+ ID: n++,
2623
+ start: { x: i.start.x * 1, y: i.start.y * 1 },
2624
+ end: { x: i.end.x * 1, y: i.end.y * 1 },
2625
+ thickness: (i.userData.wallWidth ? i.userData.wallWidth : 0.12) * 1,
2626
+ type: "LINE",
2627
+ loadBearingWall: !1,
2628
+ height: 2.8 * 1
2629
+ };
2630
+ }).filter((i) => !!i),
2631
+ pillars: [],
2632
+ beams: [],
2633
+ holes: this.lineSegments.flatMap((i) => {
2634
+ if (i.userData.isDoor && i.userData.doorDirectConnection)
2635
+ return {
2636
+ id: n++,
2637
+ type: "DOOR",
2638
+ openSide: "RIGHT",
2639
+ start: {
2640
+ x: i.start.x * 1,
2641
+ y: i.start.y * 1
2642
+ },
2643
+ end: {
2644
+ x: i.end.x * 1,
2645
+ y: i.end.y * 1
2646
+ },
2647
+ height: 2.1 * 1,
2648
+ qroundClearance: 0,
2649
+ sillHeight: 0
2650
+ };
2651
+ if (i.userData.isWindow)
2652
+ return i.userData.drawWindow.map((s) => {
2653
+ const o = g.from(s.p), r = o.clone().add(
2654
+ i.direction().multiplyScalar(s.width * 0.5)
2655
+ ), l = o.clone().add(
2656
+ i.direction().multiplyScalar(-s.width * 0.5)
2657
+ );
2658
+ return {
2659
+ id: n++,
2660
+ type: "WINDOW",
2661
+ start: {
2662
+ x: r.x * 1,
2663
+ y: r.y * 1
2664
+ },
2665
+ end: {
2666
+ x: l.x * 1,
2667
+ y: l.y * 1
2668
+ },
2669
+ height: 1.6 * 1,
2670
+ groundClearance: 0.9 * 1,
2671
+ sillHeiqht: 0.9 * 1
2672
+ };
2673
+ });
2674
+ }).filter((i) => !!i),
2675
+ rooms: []
2676
+ };
2677
+ }
2678
+ /**
2679
+ * 下载
2680
+ * @param filename
2681
+ */
2682
+ async download(t = "download.json") {
2683
+ if (typeof window < "u") {
2684
+ const e = new Blob([JSON.stringify(this.toJson())]), n = document.createElement("a");
2685
+ n.href = URL.createObjectURL(e), n.download = t, n.click();
2686
+ } else typeof global < "u" && (await O("fs", !1)).writeFileSync(t, JSON.stringify(this.toJson()));
2687
+ }
2688
+ }
2689
+ class pt extends ct {
2306
2690
  Dxf;
2307
2691
  AngleCorrectionDxf;
2308
2692
  Variable;
@@ -2313,7 +2697,7 @@ class ct extends it {
2313
2697
  * @param scale 原始数据缩放比例
2314
2698
  */
2315
2699
  constructor(t = 0.1, e = 1) {
2316
- super(), this.environment = typeof window < "u" ? "browser" : typeof global < "u" ? "node" : "unknown", this.wallWidth = t, this.Dxf = new X(this.wallWidth, e), this.AngleCorrectionDxf = new ot(), this.Variable = new _(), this.addComponent(this.Variable), this.addComponent(this.Dxf), this.addComponent(new at()), this.addComponent(this.AngleCorrectionDxf);
2700
+ super(), this.environment = typeof window < "u" ? "browser" : typeof global < "u" ? "node" : "unknown", this.wallWidth = t, this.Dxf = new z(this.wallWidth, e), this.AngleCorrectionDxf = new ht(), this.Variable = new et(), this.addComponent(this.Variable), this.addComponent(this.Dxf), this.addComponent(new ut()), this.addComponent(this.AngleCorrectionDxf), this.addComponent(new ft());
2317
2701
  }
2318
2702
  usePlugin(t) {
2319
2703
  return typeof t == "function" && t.call(this, this), this;
@@ -2326,33 +2710,33 @@ class ct extends it {
2326
2710
  });
2327
2711
  }
2328
2712
  }
2329
- const ht = new et(), lt = new nt();
2330
- function dt(g, t, e = 0.1) {
2331
- const n = t.normal(g), i = t.direction(g).mutiplyScalar(e * 0.5), s = g.direction(t).mutiplyScalar(e * 0.5), o = n.x * e * 0.5, r = n.y * e * 0.5;
2713
+ const mt = new rt(), xt = new at();
2714
+ function yt(M, t, e = 0.1) {
2715
+ const n = t.normal(M), i = t.direction(M).mutiplyScalar(e * 0.5), s = M.direction(t).mutiplyScalar(e * 0.5), o = n.x * e * 0.5, r = n.y * e * 0.5;
2332
2716
  return {
2333
2717
  points: [
2334
2718
  // 第一条线
2335
- new p(g.x + o, g.y + r).add(s),
2336
- new p(t.x + o, t.y + r).add(i),
2719
+ new g(M.x + o, M.y + r).add(s),
2720
+ new g(t.x + o, t.y + r).add(i),
2337
2721
  // 第二条线
2338
- new p(g.x - o, g.y - r).add(s),
2339
- new p(t.x - o, t.y - r).add(i)
2722
+ new g(M.x - o, M.y - r).add(s),
2723
+ new g(t.x - o, t.y - r).add(i)
2340
2724
  ],
2341
2725
  indices: [0, 1, 1, 3, 3, 2, 2, 0],
2342
2726
  rectIndices: [0, 1, 3, 2, 0]
2343
2727
  };
2344
2728
  }
2345
- class H extends q {
2729
+ class nt extends V {
2346
2730
  static name = "WhiteModel";
2347
2731
  Dxf = null;
2348
2732
  Variable = null;
2349
2733
  // dxf数据白模
2350
- whiteModelGroup = new M.Group();
2734
+ whiteModelGroup = new q.Group();
2351
2735
  // dxf数据白模边缘线
2352
- whiteModelLineGroup = new M.Group();
2736
+ whiteModelLineGroup = new q.Group();
2353
2737
  // 原始数据白模
2354
- originalWhiteMode = new M.Group();
2355
- material = new M.MeshBasicMaterial({ color: 16777215, transparent: !0, opacity: 0.8, side: M.DoubleSide });
2738
+ originalWhiteMode = new q.Group();
2739
+ material = new q.MeshBasicMaterial({ color: 16777215, transparent: !0, opacity: 0.8, side: q.DoubleSide });
2356
2740
  onAddFromParent(t) {
2357
2741
  this.Dxf = t.findComponentByName("Dxf"), this.Variable = t.findComponentByName("Variable"), this.originalWhiteMode.visible = !1, this.Dxf?.addEventListener("lineOffset", () => {
2358
2742
  this.updateModel();
@@ -2362,35 +2746,35 @@ class H extends q {
2362
2746
  this.Variable?.set("whiteModelVisible", !1);
2363
2747
  const t = this.Dxf;
2364
2748
  this.originalWhiteMode.clear(), this.whiteModelGroup.clear(), this.whiteModelLineGroup.clear(), this.whiteModelGroup.add(this.whiteModelLineGroup), this.whiteModelGroup.position.z = t.originalZAverage, this.originalWhiteMode.position.z = t.originalZAverage, t.wallsGroup.forEach((n) => {
2365
- const i = new M.Shape();
2366
- n.forEach((r, a) => a === 0 ? i.moveTo(r.x / t.scale, r.y / t.scale) : i.lineTo(r.x / t.scale, r.y / t.scale));
2367
- const s = new M.ExtrudeGeometry(i, {
2749
+ const i = new q.Shape();
2750
+ n.forEach((r, l) => l === 0 ? i.moveTo(r.x / t.scale, r.y / t.scale) : i.lineTo(r.x / t.scale, r.y / t.scale));
2751
+ const s = new q.ExtrudeGeometry(i, {
2368
2752
  depth: 2.8,
2369
2753
  bevelSize: 0
2370
- }), o = new M.Mesh(s, this.material);
2754
+ }), o = new q.Mesh(s, this.material);
2371
2755
  this.whiteModelGroup.add(o), this.whiteModelLineGroup.add(
2372
- new M.LineSegments(new M.EdgesGeometry(s), new M.LineBasicMaterial({ color: 0 }))
2756
+ new q.LineSegments(new q.EdgesGeometry(s), new q.LineBasicMaterial({ color: 0 }))
2373
2757
  );
2374
2758
  }), t.originalData.map(({ start: n, end: i, insetionArr: s }) => {
2375
- const o = new p(n.x, n.y).mutiplyScalar(t.scale), r = new p(i.x, i.y).mutiplyScalar(t.scale), { points: a, indices: c, rectIndices: h } = dt(o, r, t.width);
2759
+ const o = new g(n.x, n.y).mutiplyScalar(t.scale), r = new g(i.x, i.y).mutiplyScalar(t.scale), { points: l, indices: c, rectIndices: a } = yt(o, r, t.width);
2376
2760
  return {
2377
- points: a,
2761
+ points: l,
2378
2762
  indices: c,
2379
- rectIndices: h,
2380
- insetions: (s ?? []).map((l) => l.index)
2763
+ rectIndices: a,
2764
+ insetions: (s ?? []).map((h) => h.index)
2381
2765
  };
2382
2766
  }).forEach((n) => {
2383
- const i = new M.Shape();
2384
- n.rectIndices.forEach((r, a) => {
2767
+ const i = new q.Shape();
2768
+ n.rectIndices.forEach((r, l) => {
2385
2769
  const c = n.points[r];
2386
- a === 0 ? i.moveTo(c.x, c.y) : i.lineTo(c.x, c.y);
2770
+ l === 0 ? i.moveTo(c.x, c.y) : i.lineTo(c.x, c.y);
2387
2771
  });
2388
- const s = new M.ExtrudeGeometry(i, {
2772
+ const s = new q.ExtrudeGeometry(i, {
2389
2773
  depth: 2.8,
2390
2774
  bevelSize: 0
2391
2775
  });
2392
2776
  if (s.attributes.position.array.filter((r) => Number.isNaN(r)).length) return;
2393
- const o = new M.Mesh(s);
2777
+ const o = new q.Mesh(s);
2394
2778
  this.originalWhiteMode?.add(o);
2395
2779
  }), this.dispatchEvent({
2396
2780
  type: "updateModel",
@@ -2405,7 +2789,7 @@ class H extends q {
2405
2789
  toOBJ() {
2406
2790
  return new Promise((t) => {
2407
2791
  this.material.opacity = 1, this.material.needsUpdate = !0, setTimeout(() => {
2408
- t(ht.parse(this.whiteModelGroup)), this.material.opacity = 0.8, this.material.transparent = !0;
2792
+ t(mt.parse(this.whiteModelGroup)), this.material.opacity = 0.8, this.material.transparent = !0;
2409
2793
  }, 20);
2410
2794
  });
2411
2795
  }
@@ -2418,7 +2802,7 @@ class H extends q {
2418
2802
  return new Promise((e) => {
2419
2803
  this.material.opacity = 1, this.material.needsUpdate = !0, setTimeout(async () => {
2420
2804
  if (typeof window == "object")
2421
- lt.parse(this.whiteModelGroup.children, (n) => {
2805
+ xt.parse(this.whiteModelGroup.children, (n) => {
2422
2806
  e(n), this.material.opacity = 0.8, this.material.transparent = !0;
2423
2807
  }, () => {
2424
2808
  e(void 0);
@@ -2427,7 +2811,7 @@ class H extends q {
2427
2811
  });
2428
2812
  else if (typeof global != "function")
2429
2813
  try {
2430
- const n = await G("obj2gltf", !0), i = await G("fs", !1), s = await this.toOBJ(), o = Date.now().toString(16) + "-" + Math.floor(Math.random() * 16777215).toString(16);
2814
+ const n = await O("obj2gltf", !0), i = await O("fs", !1), s = await this.toOBJ(), o = Date.now().toString(16) + "-" + Math.floor(Math.random() * 16777215).toString(16);
2431
2815
  i.writeFileSync(o, s ?? "存贮失败");
2432
2816
  const r = await n(o, {
2433
2817
  binary: t
@@ -2470,7 +2854,7 @@ class H extends q {
2470
2854
  n.href = URL.createObjectURL(e), n.download = t, n.click();
2471
2855
  } else if (typeof global < "u") {
2472
2856
  const e = await this.toOBJ();
2473
- e && (await G("fs", !1)).writeFileSync(t, e);
2857
+ e && (await O("fs", !1)).writeFileSync(t, e);
2474
2858
  }
2475
2859
  }
2476
2860
  /**
@@ -2486,11 +2870,11 @@ class H extends q {
2486
2870
  i.href = URL.createObjectURL(n), i.download = t, i.click();
2487
2871
  } else if (typeof global < "u") {
2488
2872
  const n = await this.toGltf(e);
2489
- n && (await G("fs", !1)).writeFileSync(t, e ? n : Buffer.from(n));
2873
+ n && (await O("fs", !1)).writeFileSync(t, e ? n : Buffer.from(n));
2490
2874
  }
2491
2875
  }
2492
2876
  }
2493
- class Z extends q {
2877
+ class it extends V {
2494
2878
  static name = "DetailsPoint";
2495
2879
  Dxf = null;
2496
2880
  WhiteModel = null;
@@ -2541,23 +2925,23 @@ class Z extends q {
2541
2925
  this._timer = null;
2542
2926
  const t = this.parent?.findComponentByName("WhiteModel");
2543
2927
  this.raylines.length = 0, this.desPoints.length = 0, this.data.forEach((e) => {
2544
- const n = new M.Vector3(
2928
+ const n = new q.Vector3(
2545
2929
  e.position.x,
2546
2930
  e.position.y,
2547
2931
  e.position.z
2548
- ), i = new M.Vector3(
2932
+ ), i = new q.Vector3(
2549
2933
  e.direction.x,
2550
2934
  e.direction.y,
2551
2935
  e.direction.z
2552
2936
  ), s = 100;
2553
2937
  this.racasterHelper(n, i, s), i.z = 0;
2554
- const r = new M.Raycaster(n, i, 0, s).intersectObject(t.originalWhiteMode);
2938
+ const r = new q.Raycaster(n, i, 0, s).intersectObject(t.originalWhiteMode);
2555
2939
  if (r.length) {
2556
- const { point: a } = r[0];
2940
+ const { point: l } = r[0];
2557
2941
  this.desPoints.push({
2558
2942
  message: e.desc,
2559
2943
  position: n,
2560
- intersection: a
2944
+ intersection: l
2561
2945
  });
2562
2946
  }
2563
2947
  }), this.dispatchEvent({
@@ -2567,61 +2951,61 @@ class Z extends q {
2567
2951
  }, 50);
2568
2952
  }
2569
2953
  }
2570
- class K extends q {
2954
+ class st extends V {
2571
2955
  static name = "DxfLineModel";
2572
- dxfLineModel = new M.LineSegments();
2573
- dxfDoorsLineModel = new M.LineSegments();
2574
- dxfModelGroup = new M.Group();
2956
+ dxfLineModel = new q.LineSegments();
2957
+ dxfDoorsLineModel = new q.LineSegments();
2958
+ dxfModelGroup = new q.Group();
2575
2959
  onAddFromParent(t) {
2576
2960
  const e = t.findComponentByName("Dxf");
2577
- this.dxfModelGroup.add(this.dxfLineModel), this.dxfModelGroup.add(this.dxfDoorsLineModel), this.dxfDoorsLineModel.material = new M.LineBasicMaterial({ color: 16776960, vertexColors: !0 }), e?.addEventListener("lineOffset", () => this.updateMode());
2961
+ this.dxfModelGroup.add(this.dxfLineModel), this.dxfModelGroup.add(this.dxfDoorsLineModel), this.dxfDoorsLineModel.material = new q.LineBasicMaterial({ color: 16776960, vertexColors: !0 }), e?.addEventListener("lineOffset", () => this.updateMode());
2578
2962
  }
2579
2963
  updateMode() {
2580
2964
  const t = this.parent?.findComponentByName("Dxf");
2581
2965
  this.dxfLineModel.clear();
2582
2966
  const e = t.to3DArray(1 / t.scale, 0);
2583
- this.dxfLineModel.geometry = new M.BufferGeometry().setAttribute("position", new M.BufferAttribute(e, 3, !0));
2967
+ this.dxfLineModel.geometry = new q.BufferGeometry().setAttribute("position", new q.BufferAttribute(e, 3, !0));
2584
2968
  const n = new Float32Array(
2585
2969
  t.doorLineSegment.flatMap(({ start: s, end: o }) => [s.x, s.y, 0, o.x, o.y, 0])
2586
2970
  ).map((s) => s / t.scale), i = new Float32Array(t.doorLineSegment.flatMap(() => [1, 0, 0, 0, 1, 0]));
2587
- this.dxfDoorsLineModel.geometry = new M.BufferGeometry().setAttribute("position", new M.BufferAttribute(n, 3, !0)).setAttribute("color", new M.BufferAttribute(i, 3)), this.dxfModelGroup.position.z = t.originalZAverage, this.dispatchEvent({
2971
+ this.dxfDoorsLineModel.geometry = new q.BufferGeometry().setAttribute("position", new q.BufferAttribute(n, 3, !0)).setAttribute("color", new q.BufferAttribute(i, 3)), this.dxfModelGroup.position.z = t.originalZAverage, this.dispatchEvent({
2588
2972
  type: "modelUpdate",
2589
2973
  model: this.dxfModelGroup
2590
2974
  });
2591
2975
  }
2592
2976
  }
2593
- const ut = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2977
+ const gt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2594
2978
  __proto__: null,
2595
- DetailsPoint: Z,
2596
- DxfLineModel: K,
2597
- WhiteModel: H
2979
+ DetailsPoint: it,
2980
+ DxfLineModel: st,
2981
+ WhiteModel: nt
2598
2982
  }, Symbol.toStringTag, { value: "Module" }));
2599
- function W(g, t = {}) {
2983
+ function Q(M, t = {}) {
2600
2984
  const {
2601
2985
  detailsPoint: e = !0,
2602
2986
  whiteModel: n = !0,
2603
2987
  dxfLineModel: i = !0
2604
2988
  } = t;
2605
- i && g.addComponent(new K()), n && g.addComponent(new H()), e && g.addComponent(new Z());
2989
+ i && M.addComponent(new st()), n && M.addComponent(new nt()), e && M.addComponent(new it());
2606
2990
  }
2607
- const ft = Object.assign(W, {
2608
- create(g = {}) {
2609
- return (t) => W(t, g);
2991
+ const wt = Object.assign(Q, {
2992
+ create(M = {}) {
2993
+ return (t) => Q(t, M);
2610
2994
  }
2611
- }), pt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2995
+ }), Mt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2612
2996
  __proto__: null,
2613
- ModelDataPlugin: ft,
2614
- components: ut
2997
+ ModelDataPlugin: wt,
2998
+ components: gt
2615
2999
  }, Symbol.toStringTag, { value: "Module" }));
2616
- function mt() {
3000
+ function Dt() {
2617
3001
  return import("./index2.js");
2618
3002
  }
2619
- function xt() {
3003
+ function St() {
2620
3004
  return import("./index3.js");
2621
3005
  }
2622
- let z = null;
2623
- async function Et(g, t, e = !1, n) {
2624
- const i = await Promise.resolve().then(() => pt), s = await mt(), o = await xt(), r = new ct().usePlugin(i.ModelDataPlugin.create({
3006
+ let H = null;
3007
+ async function It(M, t, e = !1, n) {
3008
+ const i = await Promise.resolve().then(() => Mt), s = await Dt(), o = await St(), r = new pt().usePlugin(i.ModelDataPlugin.create({
2625
3009
  detailsPoint: !1,
2626
3010
  whiteModel: !0
2627
3011
  })).usePlugin(s.RenderPlugin.create({
@@ -2630,43 +3014,44 @@ async function Et(g, t, e = !1, n) {
2630
3014
  detailsPoint: !1,
2631
3015
  orbitControls: e,
2632
3016
  camera: t
2633
- })).usePlugin(o.Editor.create({ viewPermission: n })), a = r.findComponentByType(s.components.DomContainer);
2634
- return a && g.appendChild(a.domElement), z = r, {
3017
+ })).usePlugin(o.Editor.create({ viewPermission: n })), l = r.findComponentByType(s.components.DomContainer);
3018
+ return l && M.appendChild(l.domElement), H = r, {
2635
3019
  dxfSystem: r,
2636
- getFileAll: () => yt(r)
3020
+ getFileAll: () => Lt(r)
2637
3021
  };
2638
3022
  }
2639
- async function yt(g = z) {
2640
- const t = g.findComponentByName("WhiteModel"), e = new File([await g.AngleCorrectionDxf.toDxfImageBlob()], "img.jpg", { type: "image/jpeg" }), n = new File([g.Dxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" }), i = new File([g.AngleCorrectionDxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" }), s = new File([await t.toOBJBlob()], "model.obj", { type: "application/octet-stream" }), o = new File([await t.toGltfBlob(!0)], "model.glb", { type: "application/octet-stream" }), r = new File([await t.toGltfBlob(!1)], "model.gltf", { type: "application/json" }), a = new File([JSON.stringify(g.Dxf.originalData)], "json.json", { type: "application/json" });
3023
+ async function Lt(M = H) {
3024
+ const t = M.findComponentByName("WhiteModel"), e = new File([await M.AngleCorrectionDxf.toDxfImageBlob()], "img.jpg", { type: "image/jpeg" }), n = new File([M.Dxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" }), i = new File([M.AngleCorrectionDxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" }), s = new File([await t.toOBJBlob()], "model.obj", { type: "application/octet-stream" }), o = new File([await t.toGltfBlob(!0)], "model.glb", { type: "application/octet-stream" }), r = new File([await t.toGltfBlob(!1)], "model.gltf", { type: "application/json" }), l = new File([JSON.stringify(M.Dxf.originalData)], "json.json", { type: "application/json" });
2641
3025
  return {
2642
3026
  dxf: n,
2643
3027
  obj: s,
2644
3028
  glb: o,
2645
3029
  gltf: r,
2646
- json: a,
3030
+ json: l,
2647
3031
  jpg: e,
2648
3032
  correctionDxf: i
2649
3033
  };
2650
3034
  }
2651
- function At() {
2652
- return z;
3035
+ function qt() {
3036
+ return H;
2653
3037
  }
2654
3038
  export {
2655
- v as B,
2656
- q as C,
2657
- ct as D,
2658
- $ as E,
2659
- L,
2660
- ft as M,
2661
- p as P,
2662
- j as Q,
2663
- _ as V,
2664
- H as W,
2665
- Z as a,
3039
+ C as B,
3040
+ V as C,
3041
+ pt as D,
3042
+ tt as E,
3043
+ I as L,
3044
+ wt as M,
3045
+ g as P,
3046
+ T as Q,
3047
+ ft as T,
3048
+ et as V,
3049
+ nt as W,
3050
+ it as a,
2666
3051
  U as b,
2667
- Et as c,
2668
- At as d,
2669
- yt as g,
2670
- ut as i,
2671
- N as u
3052
+ It as c,
3053
+ qt as d,
3054
+ Lt as g,
3055
+ gt as i,
3056
+ k as u
2672
3057
  };