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