build-dxf 0.0.23 → 0.0.25
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/package.json +1 -1
- package/src/build.js +1313 -1055
- package/src/index.css +1 -1
- package/src/index3.js +687 -828
- package/src/utils/DxfSystem/components/Dxf.d.ts +39 -13
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/VerticalCorrection.d.ts +1 -1
- package/src/utils/DxfSystem/plugin/Editor/components/RenderManager.d.ts +2 -16
- package/src/utils/Quadtree/LineSegment.d.ts +12 -0
package/src/build.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import { EventDispatcher as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { OBJExporter as
|
|
6
|
-
import { GLTFExporter as
|
|
7
|
-
function
|
|
8
|
-
return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(
|
|
9
|
-
var t = Math.random() * 16 | 0, e =
|
|
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
|
|
14
|
-
uuid =
|
|
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
|
|
34
|
+
class V extends tt {
|
|
35
35
|
parent;
|
|
36
36
|
destroyed = !1;
|
|
37
37
|
constructor(...t) {
|
|
@@ -49,7 +49,7 @@ class G extends $ {
|
|
|
49
49
|
this.destroyed = !0;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
class
|
|
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
|
|
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
|
|
120
|
+
class g {
|
|
121
121
|
x;
|
|
122
122
|
y;
|
|
123
123
|
get X() {
|
|
@@ -150,7 +150,7 @@ class x {
|
|
|
150
150
|
* @returns
|
|
151
151
|
*/
|
|
152
152
|
equal(t) {
|
|
153
|
-
return t.x
|
|
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 x {
|
|
|
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,
|
|
211
|
-
return this.x = r + t.x, this.y =
|
|
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 x {
|
|
|
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
|
|
237
|
+
return new g(s, o);
|
|
238
238
|
}
|
|
239
239
|
/**
|
|
240
240
|
* 获取由传入的点到该点的单位方向向量
|
|
@@ -244,7 +244,7 @@ class x {
|
|
|
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
|
|
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 x {
|
|
|
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),
|
|
283
|
-
return e === "radian" ? Math.acos(
|
|
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 x {
|
|
|
302
302
|
* @returns
|
|
303
303
|
*/
|
|
304
304
|
clone() {
|
|
305
|
-
return new
|
|
305
|
+
return new g(this.x, this.y);
|
|
306
306
|
}
|
|
307
307
|
/**
|
|
308
308
|
* 克隆
|
|
@@ -319,23 +319,23 @@ class x {
|
|
|
319
319
|
};
|
|
320
320
|
}
|
|
321
321
|
static from(t) {
|
|
322
|
-
return Array.isArray(t) ? new
|
|
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
|
|
325
|
+
return new g(0, 0);
|
|
326
326
|
}
|
|
327
327
|
}
|
|
328
|
-
class
|
|
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
|
|
336
|
-
new
|
|
337
|
-
new
|
|
338
|
-
new
|
|
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 A {
|
|
|
345
345
|
return this.maxY - this.minY;
|
|
346
346
|
}
|
|
347
347
|
get center() {
|
|
348
|
-
return new
|
|
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 A {
|
|
|
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
|
|
380
|
-
o = Math.max(o, Math.min(
|
|
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
|
|
385
|
-
o = Math.max(o, Math.min(
|
|
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 A {
|
|
|
400
400
|
* @param rectangle
|
|
401
401
|
*/
|
|
402
402
|
intersectRectangle(t) {
|
|
403
|
-
const e =
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
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);
|
|
429
|
+
if (f === 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
|
|
412
|
-
if (
|
|
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
|
-
}
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
return D === 0 ? 0 : D > 0 ? 1 : 2;
|
|
420
|
-
}, l = (u, y, w) => Math.min(u.x, w.x) <= y.x && y.x <= Math.max(u.x, w.x) && Math.min(u.y, w.y) <= y.y && y.y <= Math.max(u.y, w.y), d = h(o, r, a), p = h(o, r, c), f = h(a, c, o), m = h(a, c, r);
|
|
421
|
-
return !!(d !== p && f !== m || d === 0 && l(o, a, r) || p === 0 && l(o, c, r) || f === 0 && l(a, o, c) || m === 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 A {
|
|
|
500
508
|
* @returns
|
|
501
509
|
*/
|
|
502
510
|
clone() {
|
|
503
|
-
return new
|
|
511
|
+
return new C(this.minX, this.maxX, this.minY, this.maxY);
|
|
504
512
|
}
|
|
505
513
|
/**
|
|
506
514
|
*
|
|
@@ -511,7 +519,7 @@ class A {
|
|
|
511
519
|
const e = [], n = [];
|
|
512
520
|
return t.forEach((i) => {
|
|
513
521
|
e.push(i.x), n.push(i.y);
|
|
514
|
-
}), new
|
|
522
|
+
}), new C(
|
|
515
523
|
Math.min(...e),
|
|
516
524
|
Math.max(...e),
|
|
517
525
|
Math.min(...n),
|
|
@@ -525,9 +533,11 @@ class A {
|
|
|
525
533
|
*/
|
|
526
534
|
static fromByLineSegment(...t) {
|
|
527
535
|
const e = [], n = [];
|
|
528
|
-
return t.forEach((i) =>
|
|
529
|
-
|
|
530
|
-
|
|
536
|
+
return t.forEach((i) => {
|
|
537
|
+
i?.points?.forEach((s) => {
|
|
538
|
+
e.push(s.x), n.push(s.y);
|
|
539
|
+
});
|
|
540
|
+
}), new C(
|
|
531
541
|
Math.min(...e),
|
|
532
542
|
Math.max(...e),
|
|
533
543
|
Math.min(...n),
|
|
@@ -535,7 +545,128 @@ class A {
|
|
|
535
545
|
);
|
|
536
546
|
}
|
|
537
547
|
}
|
|
538
|
-
class
|
|
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 {
|
|
539
670
|
points;
|
|
540
671
|
get p0() {
|
|
541
672
|
return this.points[0];
|
|
@@ -558,7 +689,7 @@ class N {
|
|
|
558
689
|
path2D(t) {
|
|
559
690
|
return this.points.flatMap((e, n) => {
|
|
560
691
|
const i = this.points[(n + 1) % this.points.length];
|
|
561
|
-
return t && t(new
|
|
692
|
+
return t && t(new g(e.x, e.y), new g(i.x, i.y)), [e.x, e.y, i.x, i.y];
|
|
562
693
|
});
|
|
563
694
|
}
|
|
564
695
|
createGeometry() {
|
|
@@ -584,17 +715,19 @@ class N {
|
|
|
584
715
|
intersectLineSegment(t) {
|
|
585
716
|
if (t.points.length !== 2)
|
|
586
717
|
throw new Error("LineSegment must have exactly 2 points");
|
|
587
|
-
const [e, n] = t.points, i =
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
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
|
+
}
|
|
598
731
|
}
|
|
599
732
|
return !!this.containsLineSegment(t);
|
|
600
733
|
}
|
|
@@ -609,13 +742,13 @@ class N {
|
|
|
609
742
|
const e = (n) => {
|
|
610
743
|
let i = 0;
|
|
611
744
|
for (let s = 0; s < 4; s++) {
|
|
612
|
-
const o = this.points[s], r = this.points[(s + 1) % 4],
|
|
613
|
-
if (
|
|
614
|
-
const
|
|
615
|
-
if (
|
|
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;
|
|
616
749
|
} else {
|
|
617
|
-
const
|
|
618
|
-
if (i === 0 && (i =
|
|
750
|
+
const h = a > 0 ? 1 : -1;
|
|
751
|
+
if (i === 0 && (i = h), i !== h) return !1;
|
|
619
752
|
}
|
|
620
753
|
}
|
|
621
754
|
return !0;
|
|
@@ -639,7 +772,7 @@ class N {
|
|
|
639
772
|
e.push(o.normal(r));
|
|
640
773
|
}
|
|
641
774
|
function n(s, o) {
|
|
642
|
-
const r = s.points.map((
|
|
775
|
+
const r = s.points.map((l) => l.dot(o));
|
|
643
776
|
return [Math.min(...r), Math.max(...r)];
|
|
644
777
|
}
|
|
645
778
|
function i(s, o) {
|
|
@@ -674,7 +807,7 @@ class N {
|
|
|
674
807
|
let t = 1 / 0, e = -1 / 0, n = 1 / 0, i = -1 / 0;
|
|
675
808
|
return this.points.forEach((s) => {
|
|
676
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);
|
|
677
|
-
}), new
|
|
810
|
+
}), new C(t, e, n, i);
|
|
678
811
|
}
|
|
679
812
|
/**
|
|
680
813
|
*
|
|
@@ -683,80 +816,256 @@ class N {
|
|
|
683
816
|
* @returns
|
|
684
817
|
*/
|
|
685
818
|
static fromByLineSegment(t, e = 0.1, n = !1, i = 0.5) {
|
|
686
|
-
const s = t.points[0], o = t.points[1], r = o.normal(s),
|
|
687
|
-
return new
|
|
688
|
-
new
|
|
689
|
-
new
|
|
690
|
-
new
|
|
691
|
-
new
|
|
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)
|
|
692
825
|
]);
|
|
693
826
|
}
|
|
694
827
|
}
|
|
695
|
-
class
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
set(t, e) {
|
|
715
|
-
return this.start.copy(t), this.end.copy(e), this;
|
|
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;
|
|
716
847
|
}
|
|
717
848
|
/**
|
|
718
|
-
*
|
|
719
|
-
* @param
|
|
720
|
-
* @returns
|
|
849
|
+
* 插入线段节点
|
|
850
|
+
* @param node 线段节点
|
|
721
851
|
*/
|
|
722
|
-
|
|
723
|
-
|
|
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
|
+
}
|
|
724
869
|
}
|
|
725
|
-
/**
|
|
726
|
-
*
|
|
727
|
-
* @param line
|
|
728
|
-
* @returns
|
|
870
|
+
/** 移除
|
|
871
|
+
* @param node
|
|
729
872
|
*/
|
|
730
|
-
|
|
731
|
-
|
|
873
|
+
remove(t) {
|
|
874
|
+
const e = t.parent?.nodes.indexOf(t);
|
|
875
|
+
e > -1 && t.parent?.nodes.splice(e, 1);
|
|
732
876
|
}
|
|
733
877
|
/**
|
|
734
|
-
*
|
|
735
|
-
* @param line
|
|
736
|
-
* @returns
|
|
878
|
+
* 获取线段所属的象限
|
|
879
|
+
* @param line 线段
|
|
880
|
+
* @returns 象限索引(0:西北,1:东北,2:西南,3:东南)或-1(跨多个象限)
|
|
737
881
|
*/
|
|
738
|
-
|
|
739
|
-
|
|
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;
|
|
740
886
|
}
|
|
741
887
|
/**
|
|
742
|
-
*
|
|
743
|
-
* @param line
|
|
744
|
-
* @returns
|
|
888
|
+
* 细分当前节点为四个子节点
|
|
745
889
|
*/
|
|
746
|
-
|
|
747
|
-
|
|
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
|
+
);
|
|
748
915
|
}
|
|
749
|
-
/**
|
|
750
|
-
*
|
|
751
|
-
* @param
|
|
916
|
+
/**
|
|
917
|
+
* 查询与包围盒相交的线段节点
|
|
918
|
+
* @param box2 包围盒
|
|
919
|
+
* @returns 相交的节点数组
|
|
752
920
|
*/
|
|
753
|
-
|
|
754
|
-
const
|
|
755
|
-
|
|
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;
|
|
756
931
|
}
|
|
757
|
-
/**
|
|
758
|
-
*
|
|
759
|
-
* @param
|
|
932
|
+
/**
|
|
933
|
+
* 查询与圆形区域相交的线段节点
|
|
934
|
+
* @param pos 圆心
|
|
935
|
+
* @param radius 半径
|
|
936
|
+
* @returns 相交的节点数组
|
|
937
|
+
*/
|
|
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) {
|
|
1056
|
+
return this.end.equal(t.start) || this.end.equal(t.end);
|
|
1057
|
+
}
|
|
1058
|
+
/** 膨胀
|
|
1059
|
+
* @description 向线段的两个端点分别膨胀 width
|
|
1060
|
+
* @param width
|
|
1061
|
+
*/
|
|
1062
|
+
expansion(t, e = "all") {
|
|
1063
|
+
const n = this.direction().multiplyScalar(t);
|
|
1064
|
+
return (e === "end" || e === "all") && this.end.add(n), (e === "start" || e === "all") && this.start.add(n.multiplyScalar(-1)), this;
|
|
1065
|
+
}
|
|
1066
|
+
/** 向前
|
|
1067
|
+
* @description 向前移动 width
|
|
1068
|
+
* @param width
|
|
760
1069
|
*/
|
|
761
1070
|
forward(t) {
|
|
762
1071
|
const e = this.direction().multiplyScalar(t);
|
|
@@ -785,15 +1094,15 @@ class L {
|
|
|
785
1094
|
* @returns {Rectangle}
|
|
786
1095
|
*/
|
|
787
1096
|
expandToRectangle(t = 0.1, e = "all") {
|
|
788
|
-
const n = this.start, i = this.end, s = i.normal(n), o = e === "bothSides" ?
|
|
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 = [
|
|
789
1098
|
// 第一条线
|
|
790
|
-
new
|
|
791
|
-
new
|
|
1099
|
+
new g(n.x + l, n.y + c).add(r),
|
|
1100
|
+
new g(i.x + l, i.y + c).add(o),
|
|
792
1101
|
// 第二条线
|
|
793
|
-
new
|
|
794
|
-
new
|
|
1102
|
+
new g(n.x - l, n.y - c).add(r),
|
|
1103
|
+
new g(i.x - l, i.y - c).add(o)
|
|
795
1104
|
];
|
|
796
|
-
return new
|
|
1105
|
+
return new J([0, 1, 3, 2].map((h) => a[h]));
|
|
797
1106
|
}
|
|
798
1107
|
/**
|
|
799
1108
|
* 计算线段的长度
|
|
@@ -830,24 +1139,24 @@ class L {
|
|
|
830
1139
|
projectLineSegment(t) {
|
|
831
1140
|
if (t.points.length !== 2 || this.points.length !== 2)
|
|
832
1141
|
throw new Error("每条线段必须由两个点定义");
|
|
833
|
-
const [e, n] = t.points, [i, s] = this.points, o = new
|
|
1142
|
+
const [e, n] = t.points, [i, s] = this.points, o = new g(s.x - i.x, s.y - i.y);
|
|
834
1143
|
if (o.x === 0 && o.y === 0)
|
|
835
1144
|
throw new Error("投影目标线段的两个点不能重合");
|
|
836
1145
|
const r = (f) => {
|
|
837
|
-
const
|
|
838
|
-
return new
|
|
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);
|
|
839
1148
|
};
|
|
840
|
-
let
|
|
841
|
-
const
|
|
842
|
-
const
|
|
843
|
-
return (
|
|
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;
|
|
844
1153
|
};
|
|
845
|
-
let
|
|
846
|
-
const
|
|
847
|
-
const
|
|
848
|
-
return new
|
|
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);
|
|
849
1158
|
};
|
|
850
|
-
return (
|
|
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);
|
|
851
1160
|
}
|
|
852
1161
|
/**
|
|
853
1162
|
* 计算一条线段在另一条直线上的投影
|
|
@@ -856,17 +1165,17 @@ class L {
|
|
|
856
1165
|
* @returns 投影并裁剪后的线段
|
|
857
1166
|
*/
|
|
858
1167
|
projectPoint(t, e = !0) {
|
|
859
|
-
const [n, i] = this.points, s = new
|
|
1168
|
+
const [n, i] = this.points, s = new g(i.x - n.x, i.y - n.y);
|
|
860
1169
|
if (s.x === 0 && s.y === 0)
|
|
861
1170
|
throw new Error("投影目标线段的两个点不能重合");
|
|
862
|
-
let r = ((
|
|
863
|
-
const
|
|
864
|
-
return new
|
|
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);
|
|
865
1174
|
})(t);
|
|
866
1175
|
if (!e) return r;
|
|
867
|
-
let c = ((
|
|
868
|
-
const
|
|
869
|
-
return (
|
|
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;
|
|
870
1179
|
})(r);
|
|
871
1180
|
return c < 0 || c > 1 ? null : r;
|
|
872
1181
|
}
|
|
@@ -878,14 +1187,14 @@ class L {
|
|
|
878
1187
|
*/
|
|
879
1188
|
intersectLineSegment(t, e = !0) {
|
|
880
1189
|
const n = this.start, i = this.end, s = t.start, o = t.end;
|
|
881
|
-
function r(
|
|
882
|
-
return (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);
|
|
883
1192
|
}
|
|
884
|
-
function
|
|
885
|
-
return Math.min(f.x,
|
|
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;
|
|
886
1195
|
}
|
|
887
|
-
const c = r(n, i, s),
|
|
888
|
-
return !!(c *
|
|
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)));
|
|
889
1198
|
}
|
|
890
1199
|
/**
|
|
891
1200
|
* 判断一个点是否在线段上(含端点)
|
|
@@ -905,8 +1214,8 @@ class L {
|
|
|
905
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);
|
|
906
1215
|
if (Math.abs(o) < 1e-10)
|
|
907
1216
|
return null;
|
|
908
|
-
const r = ((e.x - i.x) * (i.y - s.y) - (e.y - i.y) * (i.x - s.x)) / o,
|
|
909
|
-
return new
|
|
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);
|
|
910
1219
|
}
|
|
911
1220
|
/**
|
|
912
1221
|
* 获取两条线段夹角
|
|
@@ -952,29 +1261,214 @@ class L {
|
|
|
952
1261
|
* @returns
|
|
953
1262
|
*/
|
|
954
1263
|
areLinesCoincident(t) {
|
|
955
|
-
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,
|
|
956
|
-
return !isFinite(o) && !isFinite(
|
|
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;
|
|
957
1266
|
}
|
|
958
1267
|
clone() {
|
|
959
|
-
const t = new
|
|
1268
|
+
const t = new I(
|
|
960
1269
|
this.points[0].clone(),
|
|
961
1270
|
this.points[1].clone()
|
|
962
1271
|
);
|
|
963
1272
|
return t.userData = { ...this.userData }, t;
|
|
964
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
|
+
}
|
|
965
1459
|
}
|
|
966
|
-
async function
|
|
1460
|
+
async function O(M, t = !0) {
|
|
967
1461
|
if (typeof global < "u" && typeof require < "u")
|
|
968
|
-
return require(
|
|
1462
|
+
return require(M);
|
|
969
1463
|
{
|
|
970
1464
|
let e = await import(
|
|
971
1465
|
/* @vite-ignore */
|
|
972
|
-
|
|
1466
|
+
M
|
|
973
1467
|
);
|
|
974
1468
|
return t && (e = e.default), e;
|
|
975
1469
|
}
|
|
976
1470
|
}
|
|
977
|
-
const
|
|
1471
|
+
const lt = {
|
|
978
1472
|
Unitless: 1,
|
|
979
1473
|
// 无单位,1米 = 1(无单位)
|
|
980
1474
|
Inches: 39.37007874015748,
|
|
@@ -1018,27 +1512,27 @@ const st = {
|
|
|
1018
1512
|
Parsecs: 3240779289666404e-32
|
|
1019
1513
|
// 秒差距,1米 ≈ 0.00000000000000003240779289666404秒差距
|
|
1020
1514
|
};
|
|
1021
|
-
function
|
|
1515
|
+
function _(M) {
|
|
1022
1516
|
const t = [];
|
|
1023
|
-
for (let e = 0; e <
|
|
1024
|
-
t.push(new
|
|
1025
|
-
|
|
1026
|
-
|
|
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()
|
|
1027
1521
|
));
|
|
1028
1522
|
return t;
|
|
1029
1523
|
}
|
|
1030
|
-
function
|
|
1031
|
-
return
|
|
1524
|
+
function K(M) {
|
|
1525
|
+
return M.flatMap((t, e) => (e === M.length - 1 && [...t.points, M[0].points[0]], [t.points[0]]));
|
|
1032
1526
|
}
|
|
1033
|
-
class
|
|
1527
|
+
class z extends V {
|
|
1034
1528
|
static name = "Dxf";
|
|
1035
1529
|
shortLine = 0.04;
|
|
1036
1530
|
width = 0.04;
|
|
1037
1531
|
scale = 1;
|
|
1038
1532
|
originalData = [];
|
|
1039
1533
|
data = [];
|
|
1040
|
-
originalBox = new
|
|
1041
|
-
box = new
|
|
1534
|
+
originalBox = new C(0, 0, 0, 0);
|
|
1535
|
+
box = new C(0, 0, 0, 0);
|
|
1042
1536
|
pointsGroups = [];
|
|
1043
1537
|
wallsGroup = [];
|
|
1044
1538
|
doors = [];
|
|
@@ -1070,38 +1564,64 @@ class j extends G {
|
|
|
1070
1564
|
constructor(t = 0.04, e = 1) {
|
|
1071
1565
|
super(), this.width = t, this.scale = e, this.shortLine = t * 0.4;
|
|
1072
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
|
+
}
|
|
1073
1594
|
/**
|
|
1074
1595
|
* 设置
|
|
1075
1596
|
* @param data
|
|
1076
1597
|
* @param width
|
|
1077
1598
|
* @param scale
|
|
1078
1599
|
*/
|
|
1079
|
-
async set(t, e = this.width, n = this.scale) {
|
|
1600
|
+
async set(t, e = this.width, n = this.scale, i = !1) {
|
|
1080
1601
|
if (typeof t == "string")
|
|
1081
1602
|
if (typeof global < "u") {
|
|
1082
|
-
const { default:
|
|
1603
|
+
const { default: l } = await import(
|
|
1083
1604
|
/* @vite-ignore */
|
|
1084
1605
|
"fs"
|
|
1085
|
-
),
|
|
1606
|
+
), c = l.readFileSync(t), a = JSON.parse(c.toString("utf-8"));
|
|
1086
1607
|
return this.set(a, e, n);
|
|
1087
1608
|
} else
|
|
1088
1609
|
throw new Error("非node环境不允许使用路径");
|
|
1089
1610
|
this.scale = n, this.width = e, this.originalData = t, this.lineSegments.length = 0;
|
|
1090
|
-
const
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
(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),
|
|
1101
1621
|
a,
|
|
1102
1622
|
h
|
|
1103
1623
|
];
|
|
1104
|
-
}), this.originalZAverage =
|
|
1624
|
+
}), this.originalZAverage = o.reduce((r, l) => r + l, 0) / o.length, this.computedOriginalSize(t, this.originalBox), this.dispatchEvent({
|
|
1105
1625
|
type: "setDta",
|
|
1106
1626
|
originalData: this.originalData,
|
|
1107
1627
|
data: this.data
|
|
@@ -1115,18 +1635,18 @@ class j extends G {
|
|
|
1115
1635
|
* @returns
|
|
1116
1636
|
*/
|
|
1117
1637
|
createGroups() {
|
|
1118
|
-
const t = [], e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map(), s = (o, r,
|
|
1119
|
-
const [c,
|
|
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];
|
|
1120
1640
|
if (e.add(o), d)
|
|
1121
|
-
return i.has(o) || i.set(o, []), i.get(o)?.push(
|
|
1122
|
-
r.push([c,
|
|
1123
|
-
e.has(
|
|
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);
|
|
1124
1644
|
});
|
|
1125
1645
|
};
|
|
1126
1646
|
return this.data.forEach((o, r) => {
|
|
1127
1647
|
if (!e.has(r)) {
|
|
1128
|
-
const
|
|
1129
|
-
s(r,
|
|
1648
|
+
const l = [];
|
|
1649
|
+
s(r, l), t.push(l);
|
|
1130
1650
|
}
|
|
1131
1651
|
}), this.doors = [...n], this.pointsGroups = t, t;
|
|
1132
1652
|
}
|
|
@@ -1136,7 +1656,7 @@ class j extends G {
|
|
|
1136
1656
|
* @returns
|
|
1137
1657
|
*/
|
|
1138
1658
|
computedSize() {
|
|
1139
|
-
const t = this.pointsGroups.flatMap((r) => r.flatMap((
|
|
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);
|
|
1140
1660
|
return this.box.set(n, i, s, o), this.box;
|
|
1141
1661
|
}
|
|
1142
1662
|
/** 线路拓扑
|
|
@@ -1146,11 +1666,11 @@ class j extends G {
|
|
|
1146
1666
|
lineTopology(t) {
|
|
1147
1667
|
const e = [];
|
|
1148
1668
|
function n(s, o) {
|
|
1149
|
-
const [r,
|
|
1150
|
-
e[s] = !0, o.push(
|
|
1669
|
+
const [r, l] = t[s];
|
|
1670
|
+
e[s] = !0, o.push(l);
|
|
1151
1671
|
for (let c = 0; c < t.length; c++) {
|
|
1152
|
-
const [
|
|
1153
|
-
if (!e[c] && Math.abs(
|
|
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)
|
|
1154
1674
|
return n(c, o);
|
|
1155
1675
|
}
|
|
1156
1676
|
}
|
|
@@ -1188,9 +1708,9 @@ class j extends G {
|
|
|
1188
1708
|
const i = t[n - 1], s = t[n];
|
|
1189
1709
|
if (i.distance(s) < this.width * 0.5) {
|
|
1190
1710
|
let r = 0;
|
|
1191
|
-
for (let
|
|
1192
|
-
const c = t[
|
|
1193
|
-
if (c.distance(
|
|
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++;
|
|
1194
1714
|
else break;
|
|
1195
1715
|
}
|
|
1196
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));
|
|
@@ -1212,7 +1732,7 @@ class j extends G {
|
|
|
1212
1732
|
break;
|
|
1213
1733
|
}
|
|
1214
1734
|
}
|
|
1215
|
-
const e = this.mergeSameDirectionLine(
|
|
1735
|
+
const e = this.mergeSameDirectionLine(_(t)), n = [e[0]];
|
|
1216
1736
|
for (let i = 1; i < e.length; i++) {
|
|
1217
1737
|
const s = e[i], o = e[(e.length + i - 1) % e.length];
|
|
1218
1738
|
if (s.length() > this.width * 0.9) {
|
|
@@ -1224,10 +1744,10 @@ class j extends G {
|
|
|
1224
1744
|
n.push(s), n.push(r), i = i + 1;
|
|
1225
1745
|
continue;
|
|
1226
1746
|
}
|
|
1227
|
-
const
|
|
1228
|
-
|
|
1747
|
+
const l = e[i + 2];
|
|
1748
|
+
l && o.includedAngle(l) < 2 ? (i = i + 2, n.push(l)) : n.push(s);
|
|
1229
1749
|
}
|
|
1230
|
-
return n.length > 3 ?
|
|
1750
|
+
return n.length > 3 ? K(this.mergeSameDirectionLine(n)) : [];
|
|
1231
1751
|
}
|
|
1232
1752
|
/**
|
|
1233
1753
|
* 移除短线段
|
|
@@ -1235,48 +1755,48 @@ class j extends G {
|
|
|
1235
1755
|
* @param path
|
|
1236
1756
|
*/
|
|
1237
1757
|
removeShortLine(t, e = this.shortLine) {
|
|
1238
|
-
const n =
|
|
1758
|
+
const n = _(t), i = [], s = Math.PI / 180;
|
|
1239
1759
|
for (let o = 0; o < n.length; o++) {
|
|
1240
|
-
const r = n[o],
|
|
1241
|
-
if (
|
|
1760
|
+
const r = n[o], l = r.length(), c = o;
|
|
1761
|
+
if (l > e || i.length === 0) {
|
|
1242
1762
|
i.push(r);
|
|
1243
1763
|
continue;
|
|
1244
1764
|
}
|
|
1245
|
-
let
|
|
1246
|
-
const
|
|
1765
|
+
let a = n[++o];
|
|
1766
|
+
const h = i[i.length - 1], d = h.direction();
|
|
1247
1767
|
for (; o < n.length; ) {
|
|
1248
|
-
const f = d.angleBetween(
|
|
1249
|
-
if (
|
|
1250
|
-
|
|
1768
|
+
const f = d.angleBetween(a.direction()) / s;
|
|
1769
|
+
if (a.length() <= e || f < 4 || f > 176)
|
|
1770
|
+
a = n[++o];
|
|
1251
1771
|
else break;
|
|
1252
1772
|
}
|
|
1253
|
-
if (!
|
|
1254
|
-
const
|
|
1255
|
-
if (
|
|
1256
|
-
const f =
|
|
1773
|
+
if (!a) continue;
|
|
1774
|
+
const u = n[o - 1];
|
|
1775
|
+
if (h.length() > u.length()) {
|
|
1776
|
+
const f = h.getIntersection(a);
|
|
1257
1777
|
if (f) {
|
|
1258
|
-
const
|
|
1259
|
-
|
|
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));
|
|
1260
1780
|
} else
|
|
1261
|
-
|
|
1262
|
-
i.push(
|
|
1781
|
+
h.points[1].copy(a.points[0]);
|
|
1782
|
+
i.push(a);
|
|
1263
1783
|
} else
|
|
1264
1784
|
o = c;
|
|
1265
1785
|
}
|
|
1266
|
-
return i.length > 3 ?
|
|
1786
|
+
return i.length > 3 ? K(i) : [];
|
|
1267
1787
|
}
|
|
1268
1788
|
/** 线偏移
|
|
1269
1789
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
1270
1790
|
*/
|
|
1271
|
-
lineOffset(t =
|
|
1272
|
-
let i = new
|
|
1273
|
-
const s = new
|
|
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);
|
|
1274
1794
|
return this.pointsGroups.forEach((o) => {
|
|
1275
|
-
const r = this.lineTopology(o).map((
|
|
1795
|
+
const r = this.lineTopology(o).map((l) => l.map((c) => c.clone().mutiplyScalar(n)));
|
|
1276
1796
|
s.AddPaths(r, e, t);
|
|
1277
1797
|
}), s.Execute(i, this.width / 2 * n), this.wallsGroup = i.map((o) => {
|
|
1278
|
-
let r = o.map((
|
|
1279
|
-
return r = this.lineSegmentStraightening(r), t ==
|
|
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;
|
|
1280
1800
|
}), this.dispatchEvent({
|
|
1281
1801
|
type: "lineOffset",
|
|
1282
1802
|
wallsGroup: this.wallsGroup
|
|
@@ -1289,599 +1809,337 @@ class j extends G {
|
|
|
1289
1809
|
const n = [];
|
|
1290
1810
|
return this.wallsGroup.forEach((i) => {
|
|
1291
1811
|
for (let s = 0; s < i.length; s++) {
|
|
1292
|
-
const o = i[s], r = s === i.length - 1 ? 0 : s + 1,
|
|
1293
|
-
n.push(o.X * t, o.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);
|
|
1294
1814
|
}
|
|
1295
1815
|
}), new Float32Array(n);
|
|
1296
1816
|
}
|
|
1297
1817
|
/** 获取角度范围
|
|
1298
1818
|
* @param center
|
|
1299
|
-
* @param p1
|
|
1300
|
-
* @param p2
|
|
1301
|
-
* @returns
|
|
1302
|
-
*/
|
|
1303
|
-
getArcAngleRange(t, e, n) {
|
|
1304
|
-
const i = e.x - t.x, s = e.y - t.y, o = n.x - t.x, r = n.y - t.y;
|
|
1305
|
-
let a = Math.atan2(s, i), c = Math.atan2(r, o);
|
|
1306
|
-
a = a < 0 ? a + 2 * Math.PI : a, c = c < 0 ? c + 2 * Math.PI : c;
|
|
1307
|
-
let h, l;
|
|
1308
|
-
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)];
|
|
1309
|
-
}
|
|
1310
|
-
/**
|
|
1311
|
-
* 转为绘制数据
|
|
1312
|
-
*/
|
|
1313
|
-
toDrawDataJson(t = "Millimeters") {
|
|
1314
|
-
const e = st[t], n = {
|
|
1315
|
-
unit: t,
|
|
1316
|
-
line: [],
|
|
1317
|
-
arc: [],
|
|
1318
|
-
dimensionLine: [],
|
|
1319
|
-
center: this.box.center.toJson(),
|
|
1320
|
-
width: this.box.width * e,
|
|
1321
|
-
height: this.box.height * e,
|
|
1322
|
-
scale: e
|
|
1323
|
-
};
|
|
1324
|
-
let i = "white";
|
|
1325
|
-
function s(c, h) {
|
|
1326
|
-
n.line.push([c.X * e, c.Y * e, h.X * e, h.Y * e, i]);
|
|
1327
|
-
}
|
|
1328
|
-
function o(c, h, l, d) {
|
|
1329
|
-
n.arc.push([
|
|
1330
|
-
c.x * e,
|
|
1331
|
-
c.y * e,
|
|
1332
|
-
h * e,
|
|
1333
|
-
l,
|
|
1334
|
-
d,
|
|
1335
|
-
i
|
|
1336
|
-
]);
|
|
1337
|
-
}
|
|
1338
|
-
for (let c = 0; c < this.originalData.length; c++) {
|
|
1339
|
-
const h = this.originalData[c];
|
|
1340
|
-
if (h.isVerticalReferenceLine) {
|
|
1341
|
-
n.dimensionLine.push([h.start.x * e, h.start.y * e, h.end.x * e, h.end.y * e]);
|
|
1342
|
-
break;
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
this.wallsGroup.forEach((c) => {
|
|
1346
|
-
for (let h = 0; h < c.length; h++) {
|
|
1347
|
-
const l = c[h], d = h === c.length - 1 ? 0 : h + 1, p = c[d];
|
|
1348
|
-
s(l, p);
|
|
1349
|
-
}
|
|
1350
|
-
});
|
|
1351
|
-
const r = this.width * 0.2, a = [];
|
|
1352
|
-
return this.doorLineSegment.forEach((c) => {
|
|
1353
|
-
if (c.length() < 0.4) return;
|
|
1354
|
-
const h = c.clone().expansion(-this.width * 0.5);
|
|
1355
|
-
if (i = "cyan", h.length() < 1.2) {
|
|
1356
|
-
h.expansion(-r * 0.5);
|
|
1357
|
-
const l = c.normal();
|
|
1358
|
-
let d = new L(
|
|
1359
|
-
h.start.clone(),
|
|
1360
|
-
h.start.clone().add(l.clone().multiplyScalar(h.length()))
|
|
1361
|
-
);
|
|
1362
|
-
const p = d.clone().directionMove(d.normal(), h.length() * -0.5).expandToRectangle(h.length(), "bothSides");
|
|
1363
|
-
for (let b = 0; b < a.length; b++)
|
|
1364
|
-
if (a[b].intersectRectangle(p)) {
|
|
1365
|
-
d = new L(
|
|
1366
|
-
h.start.clone(),
|
|
1367
|
-
h.start.clone().add(l.clone().multiplyScalar(-h.length()))
|
|
1368
|
-
);
|
|
1369
|
-
break;
|
|
1370
|
-
}
|
|
1371
|
-
d.expansion(-r * 0.5).expandToRectangle(this.width * 0.2, "bothSides").path2D((b, P) => s(b, P));
|
|
1372
|
-
const f = h.length(), m = d.length(), u = (f ** 2 + m ** 2) / (2 * m), y = d.end.clone().add(d.direction().multiplyScalar(-u)), [w, D] = this.getArcAngleRange(y, h.end, d.end);
|
|
1373
|
-
o(y, u, Math.min(w, D), Math.max(w, D)), a.push(p);
|
|
1374
|
-
} else
|
|
1375
|
-
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));
|
|
1376
|
-
}), i = "yellow", this.lineSegments.forEach((c) => {
|
|
1377
|
-
if (!c.userData.isWindow) return !1;
|
|
1378
|
-
Array.isArray(c.userData.drawWindow) && c.userData.drawWindow.forEach((h) => {
|
|
1379
|
-
const { p: l, width: d } = h, p = x.from(l), f = p.clone().add(c.direction().multiplyScalar(d * 0.5)), m = p.clone().add(c.direction().multiplyScalar(-d * 0.5)), u = new L(f, m);
|
|
1380
|
-
s(u.start, u.end), u.expandToRectangle(this.width, "bothSides").path2D((y, w) => s(y, w));
|
|
1381
|
-
});
|
|
1382
|
-
}), n;
|
|
1383
|
-
}
|
|
1384
|
-
/**
|
|
1385
|
-
*
|
|
1386
|
-
* @param type
|
|
1387
|
-
*/
|
|
1388
|
-
async toDxfImageBlob(t = "Centimeters", e = "image/jpeg", n = "#000") {
|
|
1389
|
-
const i = this.toDrawDataJson(t);
|
|
1390
|
-
let s;
|
|
1391
|
-
if (typeof window < "u")
|
|
1392
|
-
s = document.createElement("canvas");
|
|
1393
|
-
else if (typeof global < "u") {
|
|
1394
|
-
const { createCanvas: c } = await Y("canvas");
|
|
1395
|
-
s = c();
|
|
1396
|
-
} else
|
|
1397
|
-
throw new Error("创建画布失败");
|
|
1398
|
-
const o = 2 * i.scale, r = {
|
|
1399
|
-
cyan: "cyan",
|
|
1400
|
-
yellow: "yellow",
|
|
1401
|
-
white: "white"
|
|
1402
|
-
};
|
|
1403
|
-
s.width = i.width + o * 2, s.height = i.height + o * 2;
|
|
1404
|
-
const a = s.getContext("2d");
|
|
1405
|
-
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, p]) => {
|
|
1406
|
-
a.strokeStyle = r[p], a.beginPath(), a.moveTo(c, h), a.lineTo(l, d), a.closePath(), a.stroke();
|
|
1407
|
-
}), i.arc.forEach(([c, h, l, d, p, f]) => {
|
|
1408
|
-
a.strokeStyle = r[f], a.beginPath(), a.arc(c, h, l, d * (Math.PI / 180), p * (Math.PI / 180)), a.stroke();
|
|
1409
|
-
}), a.beginPath(), i.dimensionLine.forEach((c) => {
|
|
1410
|
-
let [h, l, d, p] = c;
|
|
1411
|
-
const f = Math.min(l, p), m = Math.max(l, p), u = (s.width * 0.5 - 0.4 * i.scale) * (h < 0 ? -1 : 1), y = (m - f) * 0.45;
|
|
1412
|
-
a.fillStyle = "#fff", a.font = `${0.15 * i.scale}px Arial`, a.textAlign = "center", a.textBaseline = "middle", a.fillText((m - f).toFixed(2) + "cm", u, f + (m - f) * 0.5), a.moveTo(u - 0.1 * i.scale, f), a.lineTo(u + 0.1 * i.scale, f), a.moveTo(u, f), a.lineTo(u, y + f), a.moveTo(u, m), a.lineTo(u, m - y), a.moveTo(u - 0.1 * i.scale, m), a.lineTo(u + 0.1 * i.scale, m);
|
|
1413
|
-
}), a.closePath(), a.strokeStyle = "#fff", a.stroke(), "toBlob" in s ? new Promise((c) => {
|
|
1414
|
-
s.toBlob((h) => {
|
|
1415
|
-
c(h);
|
|
1416
|
-
}, e, 1);
|
|
1417
|
-
}) : s.toBuffer(e, { quality: 1 });
|
|
1418
|
-
}
|
|
1419
|
-
/**
|
|
1420
|
-
* 将点json结构转换为Dxf string
|
|
1421
|
-
*/
|
|
1422
|
-
toDxfString(t = "Millimeters") {
|
|
1423
|
-
const e = new R();
|
|
1424
|
-
e.setUnits(t), e.addLayer("cyan", R.ACI.CYAN, "DOTTED"), e.addLayer("yellow", R.ACI.YELLOW, "DOTTED"), e.addLayer("white", R.ACI.WHITE, "DOTTED");
|
|
1425
|
-
const n = this.toDrawDataJson();
|
|
1426
|
-
return n.line.forEach((i) => {
|
|
1427
|
-
let [s, o, r, a, c] = i;
|
|
1428
|
-
e.setActiveLayer(c), e.drawLine(s, o, r, a);
|
|
1429
|
-
}), n.arc.forEach((i) => {
|
|
1430
|
-
const [s, o, r, a, c, h] = i;
|
|
1431
|
-
e.setActiveLayer(h), e.drawArc(s, o, r, a, c);
|
|
1432
|
-
}), e.toDxfString();
|
|
1433
|
-
}
|
|
1434
|
-
/**
|
|
1435
|
-
* 将点云结构转换为DXF格式
|
|
1436
|
-
* @returns
|
|
1437
|
-
*/
|
|
1438
|
-
toDxfBlob(t = "Millimeters") {
|
|
1439
|
-
return new Blob([this.toDxfString(t)]);
|
|
1440
|
-
}
|
|
1441
|
-
/**
|
|
1442
|
-
* 下载
|
|
1443
|
-
* @param filename
|
|
1444
|
-
*/
|
|
1445
|
-
async download(t, e = "Millimeters") {
|
|
1446
|
-
if (typeof window < "u") {
|
|
1447
|
-
const n = this.toDxfBlob(e), i = document.createElement("a");
|
|
1448
|
-
i.href = URL.createObjectURL(n), i.download = t + ".dxf", i.click();
|
|
1449
|
-
} else typeof global < "u" && (await Y("fs", !1)).writeFileSync(t, this.toDxfString(e));
|
|
1450
|
-
}
|
|
1451
|
-
/**
|
|
1452
|
-
* 下载
|
|
1453
|
-
* @param filename
|
|
1454
|
-
*/
|
|
1455
|
-
async downloadImage(t, e = "Centimeters", n = "image/jpeg") {
|
|
1456
|
-
const i = await this.toDxfImageBlob(e, n);
|
|
1457
|
-
if (!i) return !1;
|
|
1458
|
-
if (typeof window < "u") {
|
|
1459
|
-
const s = document.createElement("a");
|
|
1460
|
-
s.href = URL.createObjectURL(i), s.download = t, s.click();
|
|
1461
|
-
} else typeof global < "u" ? (await Y("fs", !1)).writeFileSync(t, i) : console.error("图片下载失败");
|
|
1462
|
-
return !0;
|
|
1463
|
-
}
|
|
1464
|
-
/**
|
|
1465
|
-
* 计算原始数据的边界框
|
|
1466
|
-
* @description 计算所有线段的起点和终点的最小最大值,形成一个边界框
|
|
1467
|
-
* @returns
|
|
1468
|
-
*/
|
|
1469
|
-
computedOriginalSize(t, e = new A(0, 0, 0, 0)) {
|
|
1470
|
-
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);
|
|
1471
|
-
return e.set(s, o, r, a), e;
|
|
1472
|
-
}
|
|
1473
|
-
/**
|
|
1474
|
-
* 创建数据
|
|
1475
|
-
* @param pointsGroups
|
|
1476
|
-
* @returns
|
|
1477
|
-
*/
|
|
1478
|
-
static createData(t, e = !0) {
|
|
1479
|
-
let n = 0;
|
|
1480
|
-
return t.flatMap((s) => {
|
|
1481
|
-
const o = s.map((r, a) => {
|
|
1482
|
-
const c = a === s.length - 1 ? 0 : a + 1, h = s[c];
|
|
1483
|
-
return {
|
|
1484
|
-
start: { x: r.x, y: r.y },
|
|
1485
|
-
end: { x: h.x, y: h.y },
|
|
1486
|
-
insetionArr: [
|
|
1487
|
-
{
|
|
1488
|
-
index: c + n
|
|
1489
|
-
}
|
|
1490
|
-
]
|
|
1491
|
-
};
|
|
1492
|
-
});
|
|
1493
|
-
return n += s.length, e || (o.pop(), o[o.length - 1].insetionArr.length = 0, n--), o;
|
|
1494
|
-
});
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
function V(g) {
|
|
1498
|
-
if (g === null || typeof g != "object") return g;
|
|
1499
|
-
if (g instanceof Date) return new Date(g.getTime());
|
|
1500
|
-
if (Array.isArray(g)) return g.map(V);
|
|
1501
|
-
const t = {};
|
|
1502
|
-
for (const e in g)
|
|
1503
|
-
Object.prototype.hasOwnProperty.call(g, e) && (t[e] = V(g[e]));
|
|
1504
|
-
return t;
|
|
1505
|
-
}
|
|
1506
|
-
const C = new L();
|
|
1507
|
-
class ot extends j {
|
|
1508
|
-
static name = "AngleCorrectionDxf";
|
|
1509
|
-
angle = 0;
|
|
1510
|
-
onAddFromParent(t) {
|
|
1511
|
-
t.findComponentByName("LineAnalysis").addEventListener("analysisCompleted", async () => this.update());
|
|
1512
|
-
}
|
|
1513
|
-
async update() {
|
|
1514
|
-
const t = this.parent, e = t.findComponentByName("Dxf"), n = t.findComponentByName("LineAnalysis");
|
|
1515
|
-
let i = 0, s = null;
|
|
1516
|
-
for (let c = 0; c < e.originalData.length; c++) {
|
|
1517
|
-
const h = e.originalData[c];
|
|
1518
|
-
if (C.start.copy(h.start), C.end.copy(h.end), h.isVerticalReferenceLine) {
|
|
1519
|
-
const [l, d] = h.start.y < h.end.y ? [C.start, C.end] : [C.end, C.start];
|
|
1520
|
-
i = -new L(l, d).direction().angleBetween(new x(0, 1), "angle", "360"), s = null;
|
|
1521
|
-
break;
|
|
1522
|
-
}
|
|
1523
|
-
(!s || C.length() > s.length()) && (s = C.clone(), s.userData.index = c);
|
|
1524
|
-
}
|
|
1525
|
-
if (s) {
|
|
1526
|
-
e.originalData[s.userData.index].isVerticalReferenceLine = !0;
|
|
1527
|
-
const [c, h] = s.start.y < s.end.y ? [s.start, s.end] : [s.end, s.start];
|
|
1528
|
-
i = -new L(c, h).direction().angleBetween(new x(0, 1), "angle", "360");
|
|
1529
|
-
}
|
|
1530
|
-
const o = e.originalBox.center, r = x.zero(), a = e.originalData.map((c) => {
|
|
1531
|
-
const h = r.copy(c.start).division(o).rotate(x.zero(), i * (Math.PI / 180)).toJson(c.start.z), l = r.copy(c.end).division(o).rotate(x.zero(), i * (Math.PI / 180)).toJson(c.end.z), d = Object.assign(V(c), { start: h, end: l });
|
|
1532
|
-
return d.drawWindow && d.drawWindow.forEach((p) => {
|
|
1533
|
-
p.p = r.copy(p.p).division(o).rotate(x.zero(), i * (Math.PI / 180)).toJson(p.p.z), p.p.y = -p.p.y;
|
|
1534
|
-
}), d;
|
|
1535
|
-
});
|
|
1536
|
-
n.appendLineSegmentList.forEach((c) => {
|
|
1537
|
-
const h = c.clone();
|
|
1538
|
-
h.start.division(o).rotate(x.zero(), i * (Math.PI / 180)), h.end.division(o).rotate(x.zero(), i * (Math.PI / 180)), a.push({
|
|
1539
|
-
start: h.start.toJson(e.originalZAverage),
|
|
1540
|
-
end: h.end.toJson(e.originalZAverage),
|
|
1541
|
-
insetionArr: [],
|
|
1542
|
-
length: h.length()
|
|
1543
|
-
});
|
|
1544
|
-
}), a.forEach((c) => {
|
|
1545
|
-
c.start.y = -c.start.y, c.end.y = -c.end.y;
|
|
1546
|
-
}), await this.set(a, e.width, e.scale), this.lineOffset(), this.doorLineSegment = e.doorLineSegment.map((c) => {
|
|
1547
|
-
const h = c.clone();
|
|
1548
|
-
return h.start.division(o).rotate(x.zero(), i * (Math.PI / 180)), h.end.division(o).rotate(x.zero(), i * (Math.PI / 180)), h.start.y = -h.start.y, h.end.y = -h.end.y, h;
|
|
1549
|
-
}), this.angle = i, this.dispatchEvent({
|
|
1550
|
-
type: "updateData"
|
|
1551
|
-
});
|
|
1552
|
-
}
|
|
1553
|
-
}
|
|
1554
|
-
class H extends G {
|
|
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 q {
|
|
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 q(
|
|
1648
|
-
new A(this.bounds.minX, t, this.bounds.minY, e),
|
|
1649
|
-
this.capacity,
|
|
1650
|
-
this.maxDepth,
|
|
1651
|
-
this.depth + 1
|
|
1652
|
-
), this.children[1] = new q(
|
|
1653
|
-
new A(t, this.bounds.maxX, this.bounds.minY, e),
|
|
1654
|
-
this.capacity,
|
|
1655
|
-
this.maxDepth,
|
|
1656
|
-
this.depth + 1
|
|
1657
|
-
), this.children[2] = new q(
|
|
1658
|
-
new A(this.bounds.minX, t, e, this.bounds.maxY),
|
|
1659
|
-
this.capacity,
|
|
1660
|
-
this.maxDepth,
|
|
1661
|
-
this.depth + 1
|
|
1662
|
-
), this.children[3] = new q(
|
|
1663
|
-
new A(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 A(
|
|
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, p = o.y + l * c;
|
|
1705
|
-
t.distance(new x(d, p)) <= 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;
|
|
1727
|
-
}
|
|
1728
|
-
/**
|
|
1729
|
-
* 查询与线段相交的线段节点
|
|
1730
|
-
* @param lineSegment 线段
|
|
1731
|
-
* @returns 相交的节点数组
|
|
1732
|
-
*/
|
|
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;
|
|
1743
|
-
}
|
|
1744
|
-
/**
|
|
1745
|
-
* 包围盒转换为数组
|
|
1746
|
-
* @param array
|
|
1747
|
-
* @param colors
|
|
1819
|
+
* @param p1
|
|
1820
|
+
* @param p2
|
|
1748
1821
|
* @returns
|
|
1749
1822
|
*/
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
}
|
|
1757
|
-
class k {
|
|
1758
|
-
map = /* @__PURE__ */ new Map();
|
|
1759
|
-
gridSize;
|
|
1760
|
-
constructor(t = 2) {
|
|
1761
|
-
this.gridSize = t;
|
|
1823
|
+
getArcAngleRange(t, e, n) {
|
|
1824
|
+
const i = e.x - t.x, s = e.y - t.y, o = n.x - t.x, r = n.y - t.y;
|
|
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)];
|
|
1762
1829
|
}
|
|
1763
1830
|
/**
|
|
1764
|
-
*
|
|
1765
|
-
* @param point
|
|
1766
|
-
* @param userData
|
|
1831
|
+
* 线段数据转为原始json数据
|
|
1767
1832
|
*/
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
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
|
+
});
|
|
1775
1855
|
}
|
|
1776
1856
|
/**
|
|
1777
|
-
*
|
|
1778
|
-
* @param points
|
|
1857
|
+
* 转为绘制数据
|
|
1779
1858
|
*/
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1859
|
+
toDrawDataJson(t = "Millimeters") {
|
|
1860
|
+
const e = lt[t], n = {
|
|
1861
|
+
unit: t,
|
|
1862
|
+
line: [],
|
|
1863
|
+
arc: [],
|
|
1864
|
+
dimensionLine: [],
|
|
1865
|
+
center: this.box.center.toJson(),
|
|
1866
|
+
width: this.box.width * e,
|
|
1867
|
+
height: this.box.height * e,
|
|
1868
|
+
scale: e
|
|
1869
|
+
};
|
|
1870
|
+
let i = "white";
|
|
1871
|
+
function s(c, a) {
|
|
1872
|
+
n.line.push([c.X * e, c.Y * e, a.X * e, a.Y * e, i]);
|
|
1873
|
+
}
|
|
1874
|
+
function o(c, a, h, d) {
|
|
1875
|
+
n.arc.push([
|
|
1876
|
+
c.x * e,
|
|
1877
|
+
c.y * e,
|
|
1878
|
+
a * e,
|
|
1879
|
+
h,
|
|
1880
|
+
d,
|
|
1881
|
+
i
|
|
1882
|
+
]);
|
|
1883
|
+
}
|
|
1884
|
+
for (let c = 0; c < this.originalData.length; c++) {
|
|
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]);
|
|
1888
|
+
break;
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
this.wallsGroup.forEach((c) => {
|
|
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);
|
|
1895
|
+
}
|
|
1896
|
+
});
|
|
1897
|
+
const r = this.width * 0.2, l = [];
|
|
1898
|
+
return this.doorLineSegment.forEach((c) => {
|
|
1899
|
+
if (c.length() < 0.4) return;
|
|
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()))
|
|
1907
|
+
);
|
|
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()))
|
|
1914
|
+
);
|
|
1915
|
+
break;
|
|
1916
|
+
}
|
|
1917
|
+
d.expansion(-r * 0.5).expandToRectangle(this.width * 0.2, "bothSides").path2D((b, P) => s(b, P));
|
|
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;
|
|
1783
1929
|
}
|
|
1784
|
-
/**
|
|
1785
|
-
*
|
|
1930
|
+
/**
|
|
1931
|
+
*
|
|
1932
|
+
* @param type
|
|
1786
1933
|
*/
|
|
1787
|
-
|
|
1788
|
-
const
|
|
1789
|
-
|
|
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 });
|
|
1790
1964
|
}
|
|
1791
1965
|
/**
|
|
1792
|
-
*
|
|
1793
|
-
* @param point
|
|
1794
|
-
* @returns
|
|
1966
|
+
* 将点json结构转换为Dxf string
|
|
1795
1967
|
*/
|
|
1796
|
-
|
|
1797
|
-
const e =
|
|
1798
|
-
|
|
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();
|
|
1799
1979
|
}
|
|
1800
1980
|
/**
|
|
1801
|
-
*
|
|
1802
|
-
* @param gridId
|
|
1981
|
+
* 将点云结构转换为DXF格式
|
|
1803
1982
|
* @returns
|
|
1804
1983
|
*/
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
return new x(e, n);
|
|
1984
|
+
toDxfBlob(t = "Millimeters") {
|
|
1985
|
+
return new Blob([this.toDxfString(t)]);
|
|
1808
1986
|
}
|
|
1809
1987
|
/**
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
if (!this.map.has(c)) continue;
|
|
1820
|
-
this.map.get(c)?.forEach((l) => {
|
|
1821
|
-
t.containsPoint(l.point);
|
|
1822
|
-
});
|
|
1823
|
-
}
|
|
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);
|
|
1824
1997
|
}
|
|
1825
1998
|
/**
|
|
1826
|
-
*
|
|
1827
|
-
* @param
|
|
1828
|
-
* @param radius 半径
|
|
1829
|
-
* @returns 相交的节点数组
|
|
1999
|
+
* 下载
|
|
2000
|
+
* @param filename
|
|
1830
2001
|
*/
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
if (!this.map.has(l)) continue;
|
|
1837
|
-
this.map.get(l)?.forEach((p) => {
|
|
1838
|
-
t.distance(p.point) <= e && a.push(p);
|
|
1839
|
-
});
|
|
1840
|
-
}
|
|
1841
|
-
return a;
|
|
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));
|
|
1842
2007
|
}
|
|
1843
2008
|
/**
|
|
1844
|
-
*
|
|
1845
|
-
* @param
|
|
1846
|
-
* @returns 相交的节点数组
|
|
2009
|
+
* 下载
|
|
2010
|
+
* @param filename
|
|
1847
2011
|
*/
|
|
1848
|
-
|
|
1849
|
-
const
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
});
|
|
1857
|
-
}
|
|
1858
|
-
return o;
|
|
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;
|
|
1859
2020
|
}
|
|
1860
2021
|
/**
|
|
1861
|
-
*
|
|
1862
|
-
* @
|
|
2022
|
+
* 计算原始数据的边界框
|
|
2023
|
+
* @description 计算所有线段的起点和终点的最小最大值,形成一个边界框
|
|
2024
|
+
* @returns
|
|
1863
2025
|
*/
|
|
1864
|
-
|
|
1865
|
-
const
|
|
1866
|
-
return
|
|
1867
|
-
t.equal(s.point) && n.push(s);
|
|
1868
|
-
}), 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;
|
|
1869
2029
|
}
|
|
1870
2030
|
/**
|
|
1871
|
-
*
|
|
1872
|
-
* @param
|
|
2031
|
+
* 创建数据
|
|
2032
|
+
* @param pointsGroups
|
|
2033
|
+
* @returns
|
|
1873
2034
|
*/
|
|
1874
|
-
|
|
1875
|
-
|
|
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
|
+
});
|
|
1876
2052
|
}
|
|
1877
2053
|
}
|
|
1878
|
-
|
|
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());
|
|
2069
|
+
}
|
|
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;
|
|
2079
|
+
}
|
|
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
|
+
});
|
|
2107
|
+
}
|
|
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
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
get(t) {
|
|
2133
|
+
if (t in this) return this[t];
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
class dt {
|
|
1879
2137
|
// 所有可查找的点位
|
|
1880
2138
|
possibleDoorPoints = [];
|
|
1881
2139
|
doorPoint = [];
|
|
1882
2140
|
dxf;
|
|
1883
2141
|
// 包含所有点的虚拟网格
|
|
1884
|
-
pointVirtualGrid = new
|
|
2142
|
+
pointVirtualGrid = new U();
|
|
1885
2143
|
// 只包含可查找点的虚拟网格
|
|
1886
2144
|
findPointVirtualGrid;
|
|
1887
2145
|
quadtree;
|
|
@@ -1894,7 +2152,7 @@ class rt {
|
|
|
1894
2152
|
lineAnalysis;
|
|
1895
2153
|
continueFind = !0;
|
|
1896
2154
|
constructor(t) {
|
|
1897
|
-
if (this.lineAnalysis = t, this.dxf = t.Dxf, this.findPointVirtualGrid = new
|
|
2155
|
+
if (this.lineAnalysis = t, this.dxf = t.Dxf, this.findPointVirtualGrid = new U(), this.quadtree = t.quadtree, this.resultList = t.resultList, this.lineSegments = t.lineSegmentList, this.dxf.doorLineSegment.length = 0, this.lineSegments.forEach((n) => {
|
|
1898
2156
|
this.pointVirtualGrid.insert(n.start, n), this.pointVirtualGrid.insert(n.end, n);
|
|
1899
2157
|
}), this.doorPoint = this.getDoorPoint(), !this.continueFind) return;
|
|
1900
2158
|
const e = this.searchDoubleLinePoint();
|
|
@@ -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
|
|
1914
|
-
if (
|
|
2171
|
+
const a = this.searchAlongDirection(c, i);
|
|
2172
|
+
if (a) return {
|
|
1915
2173
|
start: c.point,
|
|
1916
|
-
end:
|
|
2174
|
+
end: a.point
|
|
1917
2175
|
};
|
|
1918
|
-
const
|
|
1919
|
-
if (
|
|
2176
|
+
const h = this.searchAlongNormalDirection(c, i);
|
|
2177
|
+
if (h) return {
|
|
1920
2178
|
start: c.point,
|
|
1921
|
-
end:
|
|
2179
|
+
end: h.point
|
|
1922
2180
|
};
|
|
1923
2181
|
}).filter((c) => !!c && c.start.distance(c.end) < i)
|
|
1924
2182
|
);
|
|
1925
|
-
const
|
|
2183
|
+
const l = [];
|
|
1926
2184
|
return r.forEach((c) => {
|
|
1927
|
-
const
|
|
1928
|
-
if (
|
|
1929
|
-
const d =
|
|
1930
|
-
for (let
|
|
1931
|
-
const
|
|
1932
|
-
|
|
1933
|
-
|
|
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;
|
|
2188
|
+
for (let y = 0; y < 3; y++) {
|
|
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
|
-
if (
|
|
2193
|
+
if (x.directionMove(d, -0.5), this.quadtree.queryLineSegment(x).length) return;
|
|
1936
2194
|
}
|
|
1937
|
-
|
|
1938
|
-
}),
|
|
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:
|
|
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 =
|
|
1968
|
-
if (
|
|
1969
|
-
const
|
|
1970
|
-
|
|
1971
|
-
const
|
|
1972
|
-
return
|
|
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:
|
|
2235
|
+
uuid: k()
|
|
1978
2236
|
});
|
|
1979
2237
|
} else if (o.doorDirectConnection) {
|
|
1980
2238
|
this.continueFind = !1;
|
|
1981
|
-
const r = new
|
|
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),
|
|
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) !=
|
|
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,94 +2266,94 @@ 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:
|
|
2012
|
-
const b =
|
|
2013
|
-
|
|
2014
|
-
const P = s.queryCircle(
|
|
2015
|
-
for (let
|
|
2016
|
-
const
|
|
2017
|
-
if (
|
|
2018
|
-
|
|
2019
|
-
const
|
|
2020
|
-
if (
|
|
2021
|
-
const
|
|
2022
|
-
P[
|
|
2023
|
-
findData: P[
|
|
2024
|
-
findUuid:
|
|
2025
|
-
doorLine:
|
|
2026
|
-
doorUuid:
|
|
2269
|
+
function r({ point: p, line: x }, D, w) {
|
|
2270
|
+
const b = x.direction();
|
|
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
|
|
2288
|
+
return S;
|
|
2031
2289
|
}
|
|
2032
|
-
function
|
|
2033
|
-
|
|
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
|
|
2037
|
-
const
|
|
2038
|
-
if (
|
|
2039
|
-
const
|
|
2040
|
-
|
|
2041
|
-
} else P.push(
|
|
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((
|
|
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(),
|
|
2046
|
-
t.map((
|
|
2047
|
-
const
|
|
2048
|
-
|
|
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
|
|
2051
|
-
|
|
2052
|
-
if (!c.has(
|
|
2053
|
-
const
|
|
2054
|
-
|
|
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
|
-
|
|
2059
|
-
if (
|
|
2060
|
-
|
|
2061
|
-
for (let
|
|
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
|
|
2065
|
-
|
|
2066
|
-
if (
|
|
2067
|
-
const
|
|
2068
|
-
d.has(
|
|
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
|
-
const
|
|
2072
|
-
return
|
|
2073
|
-
const
|
|
2074
|
-
if (
|
|
2075
|
-
|
|
2076
|
-
const
|
|
2077
|
-
(
|
|
2078
|
-
start:
|
|
2329
|
+
const y = [];
|
|
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
|
|
2083
|
-
|
|
2084
|
-
const
|
|
2085
|
-
(
|
|
2086
|
-
start:
|
|
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((
|
|
2351
|
+
...e.filter((p) => f.indexOf(p.uuid) === -1)
|
|
2094
2352
|
), t.splice(
|
|
2095
2353
|
0,
|
|
2096
2354
|
t.length,
|
|
2097
|
-
...t.filter((
|
|
2098
|
-
),
|
|
2355
|
+
...t.filter((p) => f.indexOf(p.uuid) === -1)
|
|
2356
|
+
), y;
|
|
2099
2357
|
}
|
|
2100
2358
|
/** 方案二: 沿方向查找
|
|
2101
2359
|
* @description
|
|
@@ -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
|
|
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,
|
|
2112
|
-
if (
|
|
2113
|
-
const c =
|
|
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),
|
|
2126
|
-
e.start === t && o.multiplyScalar(-1), e.start === t &&
|
|
2127
|
-
const c = i.queryPoint(
|
|
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
|
|
2130
|
-
if (f.start ===
|
|
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
|
|
2136
|
-
point: d.line.getIntersection(
|
|
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,
|
|
2139
|
-
if (
|
|
2140
|
-
const d =
|
|
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
|
|
2427
|
+
class ut extends V {
|
|
2170
2428
|
static name = "LineAnalysis";
|
|
2171
2429
|
Dxf = null;
|
|
2172
2430
|
Variable = null;
|
|
2173
2431
|
lineSegmentList = [];
|
|
2174
|
-
container = new
|
|
2432
|
+
container = new q.Group();
|
|
2175
2433
|
// 误差角度
|
|
2176
2434
|
errorAngle = 4;
|
|
2177
2435
|
width = 0.4;
|
|
@@ -2180,7 +2438,7 @@ class at extends G {
|
|
|
2180
2438
|
* @param parent
|
|
2181
2439
|
*/
|
|
2182
2440
|
onAddFromParent(t) {
|
|
2183
|
-
this.Dxf = t.findComponentByType(
|
|
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 G {
|
|
|
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,
|
|
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
|
|
2198
|
-
new
|
|
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
|
|
2201
|
-
new
|
|
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 G {
|
|
|
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
|
|
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 G {
|
|
|
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),
|
|
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);
|
|
2224
2482
|
f.multiplyScalar(e.width * 0.5);
|
|
2225
|
-
const
|
|
2226
|
-
if (!(
|
|
2227
|
-
d.set(
|
|
2228
|
-
for (let
|
|
2229
|
-
const b =
|
|
2230
|
-
this.addData(
|
|
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 G {
|
|
|
2237
2495
|
*/
|
|
2238
2496
|
buildQuadtree() {
|
|
2239
2497
|
const t = this.Dxf, e = [];
|
|
2240
|
-
this.quadtree = new
|
|
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 G {
|
|
|
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],
|
|
2258
|
-
t.queryRect(
|
|
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}-${
|
|
2261
|
-
const
|
|
2262
|
-
|
|
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,24 +2530,24 @@ class at extends G {
|
|
|
2272
2530
|
* @returns
|
|
2273
2531
|
*/
|
|
2274
2532
|
projectionAnalysis(t, e, n, i) {
|
|
2275
|
-
const s = i[t], o = n.direction(), r = s.direction(),
|
|
2276
|
-
if (
|
|
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
|
|
2279
|
-
return
|
|
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:
|
|
2285
|
-
project2:
|
|
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:
|
|
2292
|
-
project2:
|
|
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
|
}
|
|
@@ -2298,12 +2556,12 @@ class at extends G {
|
|
|
2298
2556
|
doors = [];
|
|
2299
2557
|
DoorsAnalysis;
|
|
2300
2558
|
doorsAnalysis() {
|
|
2301
|
-
this.DoorsAnalysis = new
|
|
2559
|
+
this.DoorsAnalysis = new dt(this), this.dispatchEvent({
|
|
2302
2560
|
type: "analysisCompleted"
|
|
2303
2561
|
});
|
|
2304
2562
|
}
|
|
2305
2563
|
}
|
|
2306
|
-
class
|
|
2564
|
+
class ft extends V {
|
|
2307
2565
|
static name = "ThreeVJia";
|
|
2308
2566
|
lineSegments = [];
|
|
2309
2567
|
onAddFromParent() {
|
|
@@ -2314,38 +2572,38 @@ class ct extends G {
|
|
|
2314
2572
|
this.parent?.findComponentByName("Renderer");
|
|
2315
2573
|
const n = this.parent?.findComponentByName("AngleCorrectionDxf"), i = /* @__PURE__ */ new Map();
|
|
2316
2574
|
let s = [...e.lineSegments], o = [], r = [];
|
|
2317
|
-
t.resultList.forEach((
|
|
2318
|
-
const
|
|
2319
|
-
|
|
2320
|
-
const
|
|
2321
|
-
|
|
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);
|
|
2322
2580
|
});
|
|
2323
|
-
const
|
|
2324
|
-
s = s.filter((
|
|
2325
|
-
if (r.indexOf(
|
|
2326
|
-
if (i.has(
|
|
2327
|
-
const
|
|
2328
|
-
if (
|
|
2329
|
-
for (let f = 0; f <
|
|
2330
|
-
const
|
|
2331
|
-
|
|
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");
|
|
2332
2590
|
}
|
|
2333
|
-
|
|
2334
|
-
const
|
|
2335
|
-
for (let f = 0; f <
|
|
2336
|
-
const
|
|
2337
|
-
|
|
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));
|
|
2338
2596
|
}
|
|
2339
|
-
|
|
2597
|
+
l.push(d);
|
|
2340
2598
|
}
|
|
2341
2599
|
return !1;
|
|
2342
2600
|
}
|
|
2343
2601
|
return !0;
|
|
2344
|
-
}), s.push(...o), s.push(...
|
|
2602
|
+
}), s.push(...o), s.push(...l.filter((a) => a.length() > 0.05));
|
|
2345
2603
|
const c = e.box.center;
|
|
2346
|
-
s = s.map((
|
|
2347
|
-
const
|
|
2348
|
-
return
|
|
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;
|
|
2349
2607
|
}), this.lineSegments = s;
|
|
2350
2608
|
}
|
|
2351
2609
|
toJson() {
|
|
@@ -2392,9 +2650,9 @@ class ct extends G {
|
|
|
2392
2650
|
};
|
|
2393
2651
|
if (i.userData.isWindow)
|
|
2394
2652
|
return i.userData.drawWindow.map((s) => {
|
|
2395
|
-
const o =
|
|
2653
|
+
const o = g.from(s.p), r = o.clone().add(
|
|
2396
2654
|
i.direction().multiplyScalar(s.width * 0.5)
|
|
2397
|
-
),
|
|
2655
|
+
), l = o.clone().add(
|
|
2398
2656
|
i.direction().multiplyScalar(-s.width * 0.5)
|
|
2399
2657
|
);
|
|
2400
2658
|
return {
|
|
@@ -2405,8 +2663,8 @@ class ct extends G {
|
|
|
2405
2663
|
y: r.y * 1
|
|
2406
2664
|
},
|
|
2407
2665
|
end: {
|
|
2408
|
-
x:
|
|
2409
|
-
y:
|
|
2666
|
+
x: l.x * 1,
|
|
2667
|
+
y: l.y * 1
|
|
2410
2668
|
},
|
|
2411
2669
|
height: 1.6 * 1,
|
|
2412
2670
|
groundClearance: 0.9 * 1,
|
|
@@ -2425,10 +2683,10 @@ class ct extends G {
|
|
|
2425
2683
|
if (typeof window < "u") {
|
|
2426
2684
|
const e = new Blob([JSON.stringify(this.toJson())]), n = document.createElement("a");
|
|
2427
2685
|
n.href = URL.createObjectURL(e), n.download = t, n.click();
|
|
2428
|
-
} else typeof global < "u" && (await
|
|
2686
|
+
} else typeof global < "u" && (await O("fs", !1)).writeFileSync(t, JSON.stringify(this.toJson()));
|
|
2429
2687
|
}
|
|
2430
2688
|
}
|
|
2431
|
-
class
|
|
2689
|
+
class pt extends ct {
|
|
2432
2690
|
Dxf;
|
|
2433
2691
|
AngleCorrectionDxf;
|
|
2434
2692
|
Variable;
|
|
@@ -2439,7 +2697,7 @@ class ht extends it {
|
|
|
2439
2697
|
* @param scale 原始数据缩放比例
|
|
2440
2698
|
*/
|
|
2441
2699
|
constructor(t = 0.1, e = 1) {
|
|
2442
|
-
super(), this.environment = typeof window < "u" ? "browser" : typeof global < "u" ? "node" : "unknown", this.wallWidth = t, this.Dxf = new
|
|
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());
|
|
2443
2701
|
}
|
|
2444
2702
|
usePlugin(t) {
|
|
2445
2703
|
return typeof t == "function" && t.call(this, this), this;
|
|
@@ -2452,33 +2710,33 @@ class ht extends it {
|
|
|
2452
2710
|
});
|
|
2453
2711
|
}
|
|
2454
2712
|
}
|
|
2455
|
-
const
|
|
2456
|
-
function
|
|
2457
|
-
const n = t.normal(
|
|
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;
|
|
2458
2716
|
return {
|
|
2459
2717
|
points: [
|
|
2460
2718
|
// 第一条线
|
|
2461
|
-
new
|
|
2462
|
-
new
|
|
2719
|
+
new g(M.x + o, M.y + r).add(s),
|
|
2720
|
+
new g(t.x + o, t.y + r).add(i),
|
|
2463
2721
|
// 第二条线
|
|
2464
|
-
new
|
|
2465
|
-
new
|
|
2722
|
+
new g(M.x - o, M.y - r).add(s),
|
|
2723
|
+
new g(t.x - o, t.y - r).add(i)
|
|
2466
2724
|
],
|
|
2467
2725
|
indices: [0, 1, 1, 3, 3, 2, 2, 0],
|
|
2468
2726
|
rectIndices: [0, 1, 3, 2, 0]
|
|
2469
2727
|
};
|
|
2470
2728
|
}
|
|
2471
|
-
class
|
|
2729
|
+
class nt extends V {
|
|
2472
2730
|
static name = "WhiteModel";
|
|
2473
2731
|
Dxf = null;
|
|
2474
2732
|
Variable = null;
|
|
2475
2733
|
// dxf数据白模
|
|
2476
|
-
whiteModelGroup = new
|
|
2734
|
+
whiteModelGroup = new q.Group();
|
|
2477
2735
|
// dxf数据白模边缘线
|
|
2478
|
-
whiteModelLineGroup = new
|
|
2736
|
+
whiteModelLineGroup = new q.Group();
|
|
2479
2737
|
// 原始数据白模
|
|
2480
|
-
originalWhiteMode = new
|
|
2481
|
-
material = new
|
|
2738
|
+
originalWhiteMode = new q.Group();
|
|
2739
|
+
material = new q.MeshBasicMaterial({ color: 16777215, transparent: !0, opacity: 0.8, side: q.DoubleSide });
|
|
2482
2740
|
onAddFromParent(t) {
|
|
2483
2741
|
this.Dxf = t.findComponentByName("Dxf"), this.Variable = t.findComponentByName("Variable"), this.originalWhiteMode.visible = !1, this.Dxf?.addEventListener("lineOffset", () => {
|
|
2484
2742
|
this.updateModel();
|
|
@@ -2488,35 +2746,35 @@ class _ extends G {
|
|
|
2488
2746
|
this.Variable?.set("whiteModelVisible", !1);
|
|
2489
2747
|
const t = this.Dxf;
|
|
2490
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) => {
|
|
2491
|
-
const i = new
|
|
2492
|
-
n.forEach((r,
|
|
2493
|
-
const s = new
|
|
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, {
|
|
2494
2752
|
depth: 2.8,
|
|
2495
2753
|
bevelSize: 0
|
|
2496
|
-
}), o = new
|
|
2754
|
+
}), o = new q.Mesh(s, this.material);
|
|
2497
2755
|
this.whiteModelGroup.add(o), this.whiteModelLineGroup.add(
|
|
2498
|
-
new
|
|
2756
|
+
new q.LineSegments(new q.EdgesGeometry(s), new q.LineBasicMaterial({ color: 0 }))
|
|
2499
2757
|
);
|
|
2500
2758
|
}), t.originalData.map(({ start: n, end: i, insetionArr: s }) => {
|
|
2501
|
-
const o = new
|
|
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);
|
|
2502
2760
|
return {
|
|
2503
|
-
points:
|
|
2761
|
+
points: l,
|
|
2504
2762
|
indices: c,
|
|
2505
|
-
rectIndices:
|
|
2506
|
-
insetions: (s ?? []).map((
|
|
2763
|
+
rectIndices: a,
|
|
2764
|
+
insetions: (s ?? []).map((h) => h.index)
|
|
2507
2765
|
};
|
|
2508
2766
|
}).forEach((n) => {
|
|
2509
|
-
const i = new
|
|
2510
|
-
n.rectIndices.forEach((r,
|
|
2767
|
+
const i = new q.Shape();
|
|
2768
|
+
n.rectIndices.forEach((r, l) => {
|
|
2511
2769
|
const c = n.points[r];
|
|
2512
|
-
|
|
2770
|
+
l === 0 ? i.moveTo(c.x, c.y) : i.lineTo(c.x, c.y);
|
|
2513
2771
|
});
|
|
2514
|
-
const s = new
|
|
2772
|
+
const s = new q.ExtrudeGeometry(i, {
|
|
2515
2773
|
depth: 2.8,
|
|
2516
2774
|
bevelSize: 0
|
|
2517
2775
|
});
|
|
2518
2776
|
if (s.attributes.position.array.filter((r) => Number.isNaN(r)).length) return;
|
|
2519
|
-
const o = new
|
|
2777
|
+
const o = new q.Mesh(s);
|
|
2520
2778
|
this.originalWhiteMode?.add(o);
|
|
2521
2779
|
}), this.dispatchEvent({
|
|
2522
2780
|
type: "updateModel",
|
|
@@ -2531,7 +2789,7 @@ class _ extends G {
|
|
|
2531
2789
|
toOBJ() {
|
|
2532
2790
|
return new Promise((t) => {
|
|
2533
2791
|
this.material.opacity = 1, this.material.needsUpdate = !0, setTimeout(() => {
|
|
2534
|
-
t(
|
|
2792
|
+
t(mt.parse(this.whiteModelGroup)), this.material.opacity = 0.8, this.material.transparent = !0;
|
|
2535
2793
|
}, 20);
|
|
2536
2794
|
});
|
|
2537
2795
|
}
|
|
@@ -2544,7 +2802,7 @@ class _ extends G {
|
|
|
2544
2802
|
return new Promise((e) => {
|
|
2545
2803
|
this.material.opacity = 1, this.material.needsUpdate = !0, setTimeout(async () => {
|
|
2546
2804
|
if (typeof window == "object")
|
|
2547
|
-
|
|
2805
|
+
xt.parse(this.whiteModelGroup.children, (n) => {
|
|
2548
2806
|
e(n), this.material.opacity = 0.8, this.material.transparent = !0;
|
|
2549
2807
|
}, () => {
|
|
2550
2808
|
e(void 0);
|
|
@@ -2553,7 +2811,7 @@ class _ extends G {
|
|
|
2553
2811
|
});
|
|
2554
2812
|
else if (typeof global != "function")
|
|
2555
2813
|
try {
|
|
2556
|
-
const n = await
|
|
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);
|
|
2557
2815
|
i.writeFileSync(o, s ?? "存贮失败");
|
|
2558
2816
|
const r = await n(o, {
|
|
2559
2817
|
binary: t
|
|
@@ -2596,7 +2854,7 @@ class _ extends G {
|
|
|
2596
2854
|
n.href = URL.createObjectURL(e), n.download = t, n.click();
|
|
2597
2855
|
} else if (typeof global < "u") {
|
|
2598
2856
|
const e = await this.toOBJ();
|
|
2599
|
-
e && (await
|
|
2857
|
+
e && (await O("fs", !1)).writeFileSync(t, e);
|
|
2600
2858
|
}
|
|
2601
2859
|
}
|
|
2602
2860
|
/**
|
|
@@ -2612,11 +2870,11 @@ class _ extends G {
|
|
|
2612
2870
|
i.href = URL.createObjectURL(n), i.download = t, i.click();
|
|
2613
2871
|
} else if (typeof global < "u") {
|
|
2614
2872
|
const n = await this.toGltf(e);
|
|
2615
|
-
n && (await
|
|
2873
|
+
n && (await O("fs", !1)).writeFileSync(t, e ? n : Buffer.from(n));
|
|
2616
2874
|
}
|
|
2617
2875
|
}
|
|
2618
2876
|
}
|
|
2619
|
-
class
|
|
2877
|
+
class it extends V {
|
|
2620
2878
|
static name = "DetailsPoint";
|
|
2621
2879
|
Dxf = null;
|
|
2622
2880
|
WhiteModel = null;
|
|
@@ -2667,23 +2925,23 @@ class Z extends G {
|
|
|
2667
2925
|
this._timer = null;
|
|
2668
2926
|
const t = this.parent?.findComponentByName("WhiteModel");
|
|
2669
2927
|
this.raylines.length = 0, this.desPoints.length = 0, this.data.forEach((e) => {
|
|
2670
|
-
const n = new
|
|
2928
|
+
const n = new q.Vector3(
|
|
2671
2929
|
e.position.x,
|
|
2672
2930
|
e.position.y,
|
|
2673
2931
|
e.position.z
|
|
2674
|
-
), i = new
|
|
2932
|
+
), i = new q.Vector3(
|
|
2675
2933
|
e.direction.x,
|
|
2676
2934
|
e.direction.y,
|
|
2677
2935
|
e.direction.z
|
|
2678
2936
|
), s = 100;
|
|
2679
2937
|
this.racasterHelper(n, i, s), i.z = 0;
|
|
2680
|
-
const r = new
|
|
2938
|
+
const r = new q.Raycaster(n, i, 0, s).intersectObject(t.originalWhiteMode);
|
|
2681
2939
|
if (r.length) {
|
|
2682
|
-
const { point:
|
|
2940
|
+
const { point: l } = r[0];
|
|
2683
2941
|
this.desPoints.push({
|
|
2684
2942
|
message: e.desc,
|
|
2685
2943
|
position: n,
|
|
2686
|
-
intersection:
|
|
2944
|
+
intersection: l
|
|
2687
2945
|
});
|
|
2688
2946
|
}
|
|
2689
2947
|
}), this.dispatchEvent({
|
|
@@ -2693,61 +2951,61 @@ class Z extends G {
|
|
|
2693
2951
|
}, 50);
|
|
2694
2952
|
}
|
|
2695
2953
|
}
|
|
2696
|
-
class
|
|
2954
|
+
class st extends V {
|
|
2697
2955
|
static name = "DxfLineModel";
|
|
2698
|
-
dxfLineModel = new
|
|
2699
|
-
dxfDoorsLineModel = new
|
|
2700
|
-
dxfModelGroup = new
|
|
2956
|
+
dxfLineModel = new q.LineSegments();
|
|
2957
|
+
dxfDoorsLineModel = new q.LineSegments();
|
|
2958
|
+
dxfModelGroup = new q.Group();
|
|
2701
2959
|
onAddFromParent(t) {
|
|
2702
2960
|
const e = t.findComponentByName("Dxf");
|
|
2703
|
-
this.dxfModelGroup.add(this.dxfLineModel), this.dxfModelGroup.add(this.dxfDoorsLineModel), this.dxfDoorsLineModel.material = new
|
|
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());
|
|
2704
2962
|
}
|
|
2705
2963
|
updateMode() {
|
|
2706
2964
|
const t = this.parent?.findComponentByName("Dxf");
|
|
2707
2965
|
this.dxfLineModel.clear();
|
|
2708
2966
|
const e = t.to3DArray(1 / t.scale, 0);
|
|
2709
|
-
this.dxfLineModel.geometry = new
|
|
2967
|
+
this.dxfLineModel.geometry = new q.BufferGeometry().setAttribute("position", new q.BufferAttribute(e, 3, !0));
|
|
2710
2968
|
const n = new Float32Array(
|
|
2711
2969
|
t.doorLineSegment.flatMap(({ start: s, end: o }) => [s.x, s.y, 0, o.x, o.y, 0])
|
|
2712
2970
|
).map((s) => s / t.scale), i = new Float32Array(t.doorLineSegment.flatMap(() => [1, 0, 0, 0, 1, 0]));
|
|
2713
|
-
this.dxfDoorsLineModel.geometry = new
|
|
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({
|
|
2714
2972
|
type: "modelUpdate",
|
|
2715
2973
|
model: this.dxfModelGroup
|
|
2716
2974
|
});
|
|
2717
2975
|
}
|
|
2718
2976
|
}
|
|
2719
|
-
const
|
|
2977
|
+
const gt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2720
2978
|
__proto__: null,
|
|
2721
|
-
DetailsPoint:
|
|
2722
|
-
DxfLineModel:
|
|
2723
|
-
WhiteModel:
|
|
2979
|
+
DetailsPoint: it,
|
|
2980
|
+
DxfLineModel: st,
|
|
2981
|
+
WhiteModel: nt
|
|
2724
2982
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2725
|
-
function
|
|
2983
|
+
function Q(M, t = {}) {
|
|
2726
2984
|
const {
|
|
2727
2985
|
detailsPoint: e = !0,
|
|
2728
2986
|
whiteModel: n = !0,
|
|
2729
2987
|
dxfLineModel: i = !0
|
|
2730
2988
|
} = t;
|
|
2731
|
-
i &&
|
|
2989
|
+
i && M.addComponent(new st()), n && M.addComponent(new nt()), e && M.addComponent(new it());
|
|
2732
2990
|
}
|
|
2733
|
-
const
|
|
2734
|
-
create(
|
|
2735
|
-
return (t) =>
|
|
2991
|
+
const wt = Object.assign(Q, {
|
|
2992
|
+
create(M = {}) {
|
|
2993
|
+
return (t) => Q(t, M);
|
|
2736
2994
|
}
|
|
2737
|
-
}),
|
|
2995
|
+
}), Mt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2738
2996
|
__proto__: null,
|
|
2739
|
-
ModelDataPlugin:
|
|
2740
|
-
components:
|
|
2997
|
+
ModelDataPlugin: wt,
|
|
2998
|
+
components: gt
|
|
2741
2999
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
2742
|
-
function
|
|
3000
|
+
function Dt() {
|
|
2743
3001
|
return import("./index2.js");
|
|
2744
3002
|
}
|
|
2745
|
-
function
|
|
3003
|
+
function St() {
|
|
2746
3004
|
return import("./index3.js");
|
|
2747
3005
|
}
|
|
2748
|
-
let
|
|
2749
|
-
async function
|
|
2750
|
-
const i = await Promise.resolve().then(() =>
|
|
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({
|
|
2751
3009
|
detailsPoint: !1,
|
|
2752
3010
|
whiteModel: !0
|
|
2753
3011
|
})).usePlugin(s.RenderPlugin.create({
|
|
@@ -2756,44 +3014,44 @@ async function At(g, t, e = !1, n) {
|
|
|
2756
3014
|
detailsPoint: !1,
|
|
2757
3015
|
orbitControls: e,
|
|
2758
3016
|
camera: t
|
|
2759
|
-
})).usePlugin(o.Editor.create({ viewPermission: n })),
|
|
2760
|
-
return
|
|
3017
|
+
})).usePlugin(o.Editor.create({ viewPermission: n })), l = r.findComponentByType(s.components.DomContainer);
|
|
3018
|
+
return l && M.appendChild(l.domElement), H = r, {
|
|
2761
3019
|
dxfSystem: r,
|
|
2762
|
-
getFileAll: () =>
|
|
3020
|
+
getFileAll: () => Lt(r)
|
|
2763
3021
|
};
|
|
2764
3022
|
}
|
|
2765
|
-
async function
|
|
2766
|
-
const t =
|
|
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" });
|
|
2767
3025
|
return {
|
|
2768
3026
|
dxf: n,
|
|
2769
3027
|
obj: s,
|
|
2770
3028
|
glb: o,
|
|
2771
3029
|
gltf: r,
|
|
2772
|
-
json:
|
|
3030
|
+
json: l,
|
|
2773
3031
|
jpg: e,
|
|
2774
3032
|
correctionDxf: i
|
|
2775
3033
|
};
|
|
2776
3034
|
}
|
|
2777
|
-
function
|
|
2778
|
-
return
|
|
3035
|
+
function qt() {
|
|
3036
|
+
return H;
|
|
2779
3037
|
}
|
|
2780
3038
|
export {
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
L,
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
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,
|
|
3051
|
+
U as b,
|
|
3052
|
+
It as c,
|
|
3053
|
+
qt as d,
|
|
3054
|
+
Lt as g,
|
|
3055
|
+
gt as i,
|
|
3056
|
+
k as u
|
|
2799
3057
|
};
|