build-dxf 0.0.20-15 → 0.0.20-23

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.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/src/build.js +1920 -1218
  3. package/src/index.css +625 -1
  4. package/src/index.js +7 -7
  5. package/src/index2.js +517 -327
  6. package/src/index3.js +1714 -1728
  7. package/src/selectLocalFile.js +3145 -1955
  8. package/src/utils/CommandManager/CommandFlow.d.ts +0 -17
  9. package/src/utils/CommandManager/CommandManager.d.ts +0 -23
  10. package/src/utils/DxfSystem/components/Dxf.d.ts +0 -1
  11. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/CommandFlowComponent.d.ts +1 -4
  12. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/Default.d.ts +20 -0
  13. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawDoorLine.d.ts +4 -24
  14. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawLine.d.ts +4 -20
  15. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawWindow.d.ts +2 -25
  16. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/PointDrag.d.ts +1 -14
  17. package/src/utils/DxfSystem/plugin/Editor/components/index.d.ts +0 -1
  18. package/src/utils/Quadtree/LineSegment.d.ts +0 -19
  19. package/src/utils/Quadtree/Point.d.ts +1 -2
  20. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/ConnectionLine.d.ts +0 -33
  21. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DeleteSelectLine.d.ts +0 -28
  22. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DeleteSelectWindow.d.ts +0 -33
  23. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/IntersectionConnectionLine.d.ts +0 -33
  24. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/MergeLine.d.ts +0 -33
  25. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/SelectAll.d.ts +0 -30
  26. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/VerticalCorrection.d.ts +0 -76
  27. package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/ViewAngle.d.ts +0 -21
package/src/build.js CHANGED
@@ -1,55 +1,70 @@
1
- import * as M from "three";
2
- import { EventDispatcher as K } from "three";
3
- import V from "clipper-lib";
4
- import N from "dxf-writer";
5
- import { OBJExporter as Q } from "three/examples/jsm/exporters/OBJExporter.js";
6
- import { GLTFExporter as tt } from "three/examples/jsm/exporters/GLTFExporter.js";
7
- function T() {
8
- return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(g) {
9
- var t = Math.random() * 16 | 0, e = g == "x" ? t : t & 3 | 8;
10
- return e.toString(16);
1
+ import * as THREE from "three";
2
+ import { EventDispatcher as EventDispatcher$1 } from "three";
3
+ import ClipperLib from "clipper-lib";
4
+ import Drawing from "dxf-writer";
5
+ import { OBJExporter } from "three/examples/jsm/exporters/OBJExporter.js";
6
+ import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
7
+ function uuid() {
8
+ return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(c) {
9
+ var r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
10
+ return v.toString(16);
11
11
  });
12
12
  }
13
- class $ extends K {
14
- uuid = T();
15
- addEventListener(t, e, n) {
16
- const { once: i = !1 } = n ?? {}, o = (r) => {
17
- e(r), i && s();
18
- }, s = () => this.removeEventListener(t, o);
19
- return super.addEventListener(t, o), s;
13
+ class EventDispatcher extends EventDispatcher$1 {
14
+ uuid = uuid();
15
+ addEventListener(type, listener, option) {
16
+ const { once = false } = option ?? {};
17
+ const callBack = (event) => {
18
+ listener(event);
19
+ once && canceCallBack();
20
+ };
21
+ const canceCallBack = () => this.removeEventListener(type, callBack);
22
+ super.addEventListener(type, callBack);
23
+ return canceCallBack;
20
24
  }
21
25
  eventRecordStack = /* @__PURE__ */ new Map();
22
- addEventRecord(t, ...e) {
23
- this.eventRecordStack.has(t) || this.eventRecordStack.set(t, []), e.forEach((i) => {
24
- this.eventRecordStack.get(t)?.push(i);
26
+ addEventRecord(name, ...cancels) {
27
+ if (!this.eventRecordStack.has(name)) this.eventRecordStack.set(name, []);
28
+ cancels.forEach((cancel) => {
29
+ this.eventRecordStack.get(name)?.push(cancel);
25
30
  });
26
- const n = (i) => (this.addEventRecord(t, i), { add: n });
27
- return { add: n };
31
+ const add = (cancel) => {
32
+ this.addEventRecord(name, cancel);
33
+ return { add };
34
+ };
35
+ return { add };
28
36
  }
29
- canceEventRecord(t) {
30
- const e = this.eventRecordStack.get(t);
31
- e && (e.forEach((n) => n()), this.eventRecordStack.delete(t));
37
+ canceEventRecord(name) {
38
+ const list = this.eventRecordStack.get(name);
39
+ if (list) {
40
+ list.forEach((cancel) => cancel());
41
+ this.eventRecordStack.delete(name);
42
+ }
32
43
  }
33
44
  }
34
- class X extends $ {
45
+ class Component extends EventDispatcher {
35
46
  parent;
36
- destroyed = !1;
37
- constructor(...t) {
38
- super(), this.addEventListener("addFromParent", (e) => {
39
- this.parent = e.parent, this.onAddFromParent(e.parent);
40
- }), this.addEventListener("removeFromParent", (e) => {
41
- this.parent = void 0, this.onRemoveFromParent(e.parent);
47
+ destroyed = false;
48
+ constructor(...arg) {
49
+ super();
50
+ this.addEventListener("addFromParent", (e) => {
51
+ this.parent = e.parent;
52
+ this.onAddFromParent(e.parent);
53
+ });
54
+ this.addEventListener("removeFromParent", (e) => {
55
+ this.parent = void 0;
56
+ this.onRemoveFromParent(e.parent);
42
57
  });
43
58
  }
44
- onAddFromParent(t) {
59
+ onAddFromParent(parent) {
45
60
  }
46
- onRemoveFromParent(t) {
61
+ onRemoveFromParent(parent) {
47
62
  }
48
63
  destroy() {
49
- this.destroyed = !0;
64
+ this.destroyed = true;
50
65
  }
51
66
  }
52
- class et extends $ {
67
+ class ComponentManager extends EventDispatcher {
53
68
  static EventType = {
54
69
  ADD_COMPONENT: "addComponent"
55
70
  };
@@ -58,66 +73,75 @@ class et extends $ {
58
73
  * 添加组件
59
74
  * @param component
60
75
  */
61
- addComponent(t) {
62
- return t && (this.components.push(t), this.dispatchEvent({
63
- type: "addComponent",
64
- component: t
65
- }), t.dispatchEvent({
66
- type: "addFromParent",
67
- parent: this
68
- })), this;
76
+ addComponent(component) {
77
+ if (component) {
78
+ this.components.push(component);
79
+ this.dispatchEvent({
80
+ type: "addComponent",
81
+ component
82
+ });
83
+ component.dispatchEvent({
84
+ type: "addFromParent",
85
+ parent: this
86
+ });
87
+ }
88
+ return this;
69
89
  }
70
90
  /**
71
91
  * 移除组件
72
92
  * @param component
73
93
  */
74
- removeComponent(t) {
75
- if (t instanceof X) {
76
- const e = this.components.indexOf(t);
77
- e > -1 && (this.components.splice(e, 1), this.dispatchEvent({
78
- type: "removeComponent",
79
- component: t
80
- }), t.dispatchEvent({
81
- type: "removeFromParent",
82
- parent: this
83
- }));
94
+ removeComponent(component) {
95
+ if (component instanceof Component) {
96
+ const index2 = this.components.indexOf(component);
97
+ if (index2 > -1) {
98
+ this.components.splice(index2, 1);
99
+ this.dispatchEvent({
100
+ type: "removeComponent",
101
+ component
102
+ });
103
+ component.dispatchEvent({
104
+ type: "removeFromParent",
105
+ parent: this
106
+ });
107
+ }
84
108
  }
85
109
  }
86
110
  /**
87
111
  * 查找符合条件的第一个组件
88
112
  * @param callBack
89
113
  */
90
- findComponent(t) {
91
- for (let e = 0; e < this.components.length; e++) {
92
- const n = this.components[e];
93
- if (t(n, e)) return n;
114
+ findComponent(predicate) {
115
+ for (let i = 0; i < this.components.length; i++) {
116
+ const component = this.components[i];
117
+ if (predicate(component, i)) return component;
94
118
  }
95
119
  }
96
120
  /**
97
121
  * 查找所有符合条件的组件
98
122
  * @param callBack
99
123
  */
100
- findComponents(t) {
101
- return this.components.filter(t);
124
+ findComponents(predicate) {
125
+ return this.components.filter(predicate);
102
126
  }
103
127
  /**
104
128
  *
105
129
  * @param type
106
130
  */
107
- findComponentByType(t) {
108
- const e = this.findComponent((n) => n instanceof t);
109
- return e || null;
131
+ findComponentByType(type) {
132
+ const component = this.findComponent((c) => c instanceof type);
133
+ return component ? component : null;
110
134
  }
111
135
  /**
112
136
  *
113
137
  * @param type
114
138
  */
115
- findComponentByName(t) {
116
- const e = this.findComponent((n) => n.constructor.name === t);
117
- return e || null;
139
+ findComponentByName(name) {
140
+ const component = this.findComponent((c) => c.constructor.name === name);
141
+ return component ? component : null;
118
142
  }
119
143
  }
120
- class f {
144
+ class Point {
121
145
  x;
122
146
  y;
123
147
  get X() {
@@ -132,32 +156,39 @@ class f {
132
156
  * @param x
133
157
  * @param y
134
158
  */
135
- constructor(t = 0, e = 0) {
136
- this.x = t, this.y = e;
159
+ constructor(x = 0, y = 0) {
160
+ this.x = x;
161
+ this.y = y;
137
162
  }
138
- set(t, e) {
139
- return this.x = t, this.y = e, this;
163
+ set(x, y) {
164
+ this.x = x;
165
+ this.y = y;
166
+ return this;
140
167
  }
141
- setX(t) {
142
- return this.x = t, this;
168
+ setX(x) {
169
+ this.x = x;
170
+ return this;
143
171
  }
144
- setY(t) {
145
- return this.y = t, this;
172
+ setY(y) {
173
+ this.y = y;
174
+ return this;
146
175
  }
147
176
  /**
148
177
  *
149
178
  * @param point
150
179
  * @returns
151
180
  */
152
- equal(t) {
153
- return t.x === this.x && t.y === this.y;
181
+ equal(point) {
182
+ return point.x === this.x && point.y === this.y;
154
183
  }
155
184
  /**
156
185
  *
157
186
  * @param arr
158
187
  */
159
- setByArray(t) {
160
- return this.x = t[0], this.y = t[1], this;
188
+ setByArray(arr) {
189
+ this.x = arr[0];
190
+ this.y = arr[1];
191
+ return this;
161
192
  }
162
193
  /**
163
194
  *
@@ -169,19 +200,25 @@ class f {
169
200
  * multiplyScalar
170
201
  * @param scalar
171
202
  */
172
- mutiplyScalar(t) {
173
- return this.x *= t, this.y *= t, this;
203
+ mutiplyScalar(scalar) {
204
+ this.x *= scalar;
205
+ this.y *= scalar;
206
+ return this;
174
207
  }
175
- multiplyScalar(t) {
176
- return this.x *= t, this.y *= t, this;
208
+ multiplyScalar(scalar) {
209
+ this.x *= scalar;
210
+ this.y *= scalar;
211
+ return this;
177
212
  }
178
213
  /**
179
214
  *
180
215
  * @param scalar
181
216
  * @returns
182
217
  */
183
- divisionScalar(t) {
184
- return this.x /= t, this.y /= t, this;
218
+ divisionScalar(scalar) {
219
+ this.x /= scalar;
220
+ this.y /= scalar;
221
+ return this;
185
222
  }
186
223
  /**
187
224
  * 减法
@@ -189,8 +226,10 @@ class f {
189
226
  * @param point
190
227
  * @returns
191
228
  */
192
- division(t) {
193
- return this.x -= t.x, this.y -= t.y, this;
229
+ division(point) {
230
+ this.x -= point.x;
231
+ this.y -= point.y;
232
+ return this;
194
233
  }
195
234
  /**
196
235
  * 加法
@@ -198,15 +237,19 @@ class f {
198
237
  * @param point
199
238
  * @returns
200
239
  */
201
- add(t) {
202
- return this.x += t.x, this.y += t.y, this;
240
+ add(point) {
241
+ this.x += point.x;
242
+ this.y += point.y;
243
+ return this;
203
244
  }
204
245
  /**
205
246
  * 保留小数位数
206
247
  * @param count
207
248
  */
208
- fixed(t) {
209
- return this.x = Number(this.x.toFixed(t)), this.y = Number(this.y.toFixed(t)), this;
249
+ fixed(count) {
250
+ this.x = Number(this.x.toFixed(count));
251
+ this.y = Number(this.y.toFixed(count));
252
+ return this;
210
253
  }
211
254
  /**
212
255
  * 归一化
@@ -214,8 +257,11 @@ class f {
214
257
  * @returns
215
258
  */
216
259
  normalize() {
217
- const t = Math.sqrt(this.x * this.x + this.y * this.y);
218
- return t === 0 ? this : (this.x /= t, this.y /= t, this);
260
+ const length = Math.sqrt(this.x * this.x + this.y * this.y);
261
+ if (length === 0) return this;
262
+ this.x /= length;
263
+ this.y /= length;
264
+ return this;
219
265
  }
220
266
  /**
221
267
  * 获取单位法向量
@@ -223,9 +269,13 @@ class f {
223
269
  * @param point
224
270
  * @returns
225
271
  */
226
- normal(t) {
227
- const e = this.x - t.x, n = this.y - t.y, i = Math.sqrt(e * e + n * n), o = -n / i, s = e / i;
228
- return new f(o, s);
272
+ normal(point) {
273
+ const dx = this.x - point.x;
274
+ const dy = this.y - point.y;
275
+ const length = Math.sqrt(dx * dx + dy * dy);
276
+ const nx = -dy / length;
277
+ const ny = dx / length;
278
+ return new Point(nx, ny);
229
279
  }
230
280
  /**
231
281
  * 获取由传入的点到该点的单位方向向量
@@ -233,9 +283,12 @@ class f {
233
283
  * @param point
234
284
  * @returns
235
285
  */
236
- direction(t) {
237
- const e = this.x - t.x, n = this.y - t.y, i = Math.sqrt(e * e + n * n);
238
- return i === 0 ? new f(0, 0) : new f(e / i, n / i);
286
+ direction(point) {
287
+ const dx = this.x - point.x;
288
+ const dy = this.y - point.y;
289
+ const length = Math.sqrt(dx * dx + dy * dy);
290
+ if (length === 0) return new Point(0, 0);
291
+ return new Point(dx / length, dy / length);
239
292
  }
240
293
  /**
241
294
  * 计算模长
@@ -249,8 +302,8 @@ class f {
249
302
  * @param point
250
303
  * @returns
251
304
  */
252
- dot(t) {
253
- return this.x * t.x + this.y * t.y;
305
+ dot(point) {
306
+ return this.x * point.x + this.y * point.y;
254
307
  }
255
308
  /** 求两个点叉积
256
309
  * @description 如果叉积大于 0,a 到 b 为逆时针方向。
@@ -258,8 +311,8 @@ class f {
258
311
  * @param point
259
312
  * @returns
260
313
  */
261
- cross(t) {
262
- return this.x * t.y - this.y * this.x;
314
+ cross(point) {
315
+ return this.x * point.y - this.y * this.x;
263
316
  }
264
317
  /** 计算两个向量夹角
265
318
  * @description 公式:a · b = |a| × |b| × cosθ
@@ -267,25 +320,34 @@ class f {
267
320
  * @param point
268
321
  * @returns
269
322
  */
270
- angleBetween(t, e = "radian", n = "180") {
271
- const i = this.dot(t), o = this.magnitude(), s = t.magnitude();
272
- if (o === 0 || s === 0) return 0;
273
- const r = i / (o * s), a = Math.max(-1, Math.min(1, r));
274
- return e === "radian" ? Math.acos(a) : e === "cos" ? a : n === "180" || this.cross(t) < 0 ? Math.acos(a) / (Math.PI / 180) : 360 - Math.acos(a) / (Math.PI / 180);
323
+ angleBetween(point, type = "radian", angle = "180") {
324
+ const dotProduct = this.dot(point);
325
+ const magnitude1 = this.magnitude();
326
+ const magnitude2 = point.magnitude();
327
+ if (magnitude1 === 0 || magnitude2 === 0) return 0;
328
+ const cosTheta = dotProduct / (magnitude1 * magnitude2);
329
+ const clampedCosTheta = Math.max(-1, Math.min(1, cosTheta));
330
+ if (type === "radian") return Math.acos(clampedCosTheta);
331
+ if (type === "cos") return clampedCosTheta;
332
+ if (angle === "180" || this.cross(point) < 0) return Math.acos(clampedCosTheta) / (Math.PI / 180);
333
+ return 360 - Math.acos(clampedCosTheta) / (Math.PI / 180);
275
334
  }
276
335
  /** 获取向量长度
277
336
  */
278
337
  length() {
279
- const t = Math.sqrt(this.x * this.x + this.y * this.y);
280
- return Math.abs(t - Math.round(t)) < 1e-9 ? Math.round(t) : t;
338
+ const magnitude = Math.sqrt(this.x * this.x + this.y * this.y);
339
+ if (Math.abs(magnitude - Math.round(magnitude)) < 1e-9) {
340
+ return Math.round(magnitude);
341
+ }
342
+ return magnitude;
281
343
  }
282
344
  /**
283
345
  * 获取两个点长度
284
346
  * @param point
285
347
  */
286
- distance(t) {
348
+ distance(point) {
287
349
  return Math.sqrt(
288
- (this.x - t.x) * (this.x - t.x) + (this.y - t.y) * (this.y - t.y)
350
+ (this.x - point.x) * (this.x - point.x) + (this.y - point.y) * (this.y - point.y)
289
351
  );
290
352
  }
291
353
  /**
@@ -293,40 +355,47 @@ class f {
293
355
  * @returns
294
356
  */
295
357
  clone() {
296
- return new f(this.x, this.y);
358
+ return new Point(this.x, this.y);
297
359
  }
298
360
  /**
299
361
  * 克隆
300
362
  * @returns
301
363
  */
302
- copy(t) {
303
- this.x = t.x ?? 0, this.y = t.y ?? 0;
364
+ copy(p) {
365
+ this.x = p.x ?? 0;
366
+ this.y = p.y ?? 0;
304
367
  }
305
- toJson(t = 0) {
368
+ toJson() {
306
369
  return {
307
370
  x: this.x,
308
- y: this.y,
309
- z: t
371
+ y: this.y
310
372
  };
311
373
  }
312
- static from(t) {
313
- return Array.isArray(t) ? new f(t[0], t[1]) : "x" in t && "y" in t ? new f(t.x, t.y) : "X" in t && "Y" in t ? new f(t.X, t.Y) : this.zero();
374
+ static from(arr) {
375
+ if (Array.isArray(arr)) {
376
+ return new Point(arr[0], arr[1]);
377
+ } else if ("x" in arr && "y" in arr) {
378
+ return new Point(arr.x, arr.y);
379
+ } else if ("X" in arr && "Y" in arr) {
380
+ return new Point(arr.X, arr.Y);
381
+ }
382
+ return this.zero();
314
383
  }
315
384
  static zero() {
316
- return new f(0, 0);
385
+ return new Point(0, 0);
317
386
  }
318
387
  }
319
- class A {
388
+ class Box2 {
320
389
  minX = 0;
321
390
  maxX = 0;
322
391
  minY = 0;
323
392
  maxY = 0;
324
393
  get points() {
325
394
  return [
326
- new f(this.minX, this.minY),
327
- new f(this.maxX, this.minY),
328
- new f(this.maxX, this.maxY),
329
- new f(this.minX, this.maxY)
395
+ new Point(this.minX, this.minY),
396
+ new Point(this.maxX, this.minY),
397
+ new Point(this.maxX, this.maxY),
398
+ new Point(this.minX, this.maxY)
330
399
  ];
331
400
  }
332
401
  get width() {
@@ -336,122 +405,163 @@ class A {
336
405
  return this.maxY - this.minY;
337
406
  }
338
407
  get center() {
339
- return new f(
408
+ return new Point(
340
409
  this.minX + (this.maxX - this.minX) * 0.5,
341
410
  this.minY + (this.maxY - this.minY) * 0.5
342
411
  );
343
412
  }
344
- constructor(t = 0, e = 0, n = 0, i = 0) {
345
- this.minX = t, this.maxX = e, this.minY = n, this.maxY = i;
413
+ constructor(minX = 0, maxX = 0, minY = 0, maxY = 0) {
414
+ this.minX = minX;
415
+ this.maxX = maxX;
416
+ this.minY = minY;
417
+ this.maxY = maxY;
346
418
  }
347
419
  /**
348
420
  *
349
421
  * @param z
350
422
  * @returns
351
423
  */
352
- getPaths3D(t = 0) {
353
- const e = this.points, n = [];
354
- return e.forEach((i, o) => {
355
- const s = e[(o + 1) % e.length];
356
- n.push(i.x, i.y, t), n.push(s.x, s.y, t);
357
- }), n;
424
+ getPaths3D(z = 0) {
425
+ const points = this.points, list = [];
426
+ points.forEach((p, i) => {
427
+ const nextP = points[(i + 1) % points.length];
428
+ list.push(p.x, p.y, z);
429
+ list.push(nextP.x, nextP.y, z);
430
+ });
431
+ return list;
358
432
  }
359
433
  /**
360
434
  * 判断线段是与包围盒相交
361
435
  * @description Liang-Barsky算法的变种
362
436
  * @param line
363
437
  */
364
- intersectLineSegment(t) {
365
- const e = t.points[0], n = t.points[1], i = n.x - e.x, o = n.y - e.y;
366
- if (i === 0 && o === 0)
367
- return this.minX <= e.x && e.x <= this.maxX && this.minY <= e.y && e.y <= this.maxY;
368
- let s = Number.NEGATIVE_INFINITY, r = Number.POSITIVE_INFINITY;
369
- if (i !== 0) {
370
- const a = (this.minX - e.x) / i, c = (this.maxX - e.x) / i;
371
- s = Math.max(s, Math.min(a, c)), r = Math.min(r, Math.max(a, c));
372
- } else if (e.x < this.minX || e.x > this.maxX)
373
- return !1;
374
- if (o !== 0) {
375
- const a = (this.minY - e.y) / o, c = (this.maxY - e.y) / o;
376
- s = Math.max(s, Math.min(a, c)), r = Math.min(r, Math.max(a, c));
377
- } else if (e.y < this.minY || e.y > this.maxY)
378
- return !1;
379
- return s <= r && s <= 1 && r >= 0;
438
+ intersectLineSegment(line) {
439
+ const p1 = line.points[0];
440
+ const p2 = line.points[1];
441
+ const dx = p2.x - p1.x;
442
+ const dy = p2.y - p1.y;
443
+ if (dx === 0 && dy === 0) {
444
+ return this.minX <= p1.x && p1.x <= this.maxX && this.minY <= p1.y && p1.y <= this.maxY;
445
+ }
446
+ let tNear = Number.NEGATIVE_INFINITY;
447
+ let tFar = Number.POSITIVE_INFINITY;
448
+ if (dx !== 0) {
449
+ const tx1 = (this.minX - p1.x) / dx;
450
+ const tx2 = (this.maxX - p1.x) / dx;
451
+ tNear = Math.max(tNear, Math.min(tx1, tx2));
452
+ tFar = Math.min(tFar, Math.max(tx1, tx2));
453
+ } else if (p1.x < this.minX || p1.x > this.maxX) {
454
+ return false;
455
+ }
456
+ if (dy !== 0) {
457
+ const ty1 = (this.minY - p1.y) / dy;
458
+ const ty2 = (this.maxY - p1.y) / dy;
459
+ tNear = Math.max(tNear, Math.min(ty1, ty2));
460
+ tFar = Math.min(tFar, Math.max(ty1, ty2));
461
+ } else if (p1.y < this.minY || p1.y > this.maxY) {
462
+ return false;
463
+ }
464
+ return tNear <= tFar && tNear <= 1 && tFar >= 0;
380
465
  }
381
466
  /**
382
467
  * 判断线段是在包围盒内
383
468
  * @param line
384
469
  */
385
- containsLineSegment(t) {
386
- const [e, n] = t.points;
387
- return this.minX <= e.x && e.x <= this.maxX && this.minY <= e.y && e.y <= this.maxY && this.minX <= n.x && n.x <= this.maxX && this.minY <= n.y && n.y <= this.maxY;
470
+ containsLineSegment(line) {
471
+ const [p1, p2] = line.points;
472
+ return this.minX <= p1.x && p1.x <= this.maxX && this.minY <= p1.y && p1.y <= this.maxY && this.minX <= p2.x && p2.x <= this.maxX && this.minY <= p2.y && p2.y <= this.maxY;
388
473
  }
389
474
  /**
390
475
  * 判断矩形与包围盒相交
391
476
  * @param rectangle
392
477
  */
393
- intersectRectangle(t) {
394
- const e = (s) => this.minX <= s.x && s.x <= this.maxX && this.minY <= s.y && s.y <= this.maxY, n = (s) => {
395
- let r = 0;
396
- for (let a = 0; a < 4; a++) {
397
- const c = t.points[a], h = t.points[(a + 1) % 4], l = { x: h.x - c.x, y: h.y - c.y }, d = { x: s.x - c.x, y: s.y - c.y }, x = l.x * d.y - l.y * d.x;
398
- if (x === 0) {
399
- const p = l.x !== 0 ? (s.x - c.x) / l.x : (s.y - c.y) / l.y;
400
- if (p >= 0 && p <= 1) return !0;
478
+ intersectRectangle(rectangle) {
479
+ const isPointInBox = (p) => this.minX <= p.x && p.x <= this.maxX && this.minY <= p.y && p.y <= this.maxY;
480
+ const isPointInRect = (point) => {
481
+ let sign = 0;
482
+ for (let i = 0; i < 4; i++) {
483
+ const p1 = rectangle.points[i];
484
+ const p2 = rectangle.points[(i + 1) % 4];
485
+ const edge = { x: p2.x - p1.x, y: p2.y - p1.y };
486
+ const toPoint = { x: point.x - p1.x, y: point.y - p1.y };
487
+ const cross = edge.x * toPoint.y - edge.y * toPoint.x;
488
+ if (cross === 0) {
489
+ const t = edge.x !== 0 ? (point.x - p1.x) / edge.x : (point.y - p1.y) / edge.y;
490
+ if (t >= 0 && t <= 1) return true;
401
491
  } else {
402
- const p = x > 0 ? 1 : -1;
403
- if (r === 0 && (r = p), r !== p) return !1;
492
+ const currentSign = cross > 0 ? 1 : -1;
493
+ if (sign === 0) sign = currentSign;
494
+ if (sign !== currentSign) return false;
404
495
  }
405
496
  }
406
- return !0;
407
- }, i = (s, r, a, c) => {
408
- const h = (u, m, y) => {
409
- const S = (m.y - u.y) * (y.x - m.x) - (m.x - u.x) * (y.y - m.y);
410
- return S === 0 ? 0 : S > 0 ? 1 : 2;
411
- }, l = (u, m, y) => Math.min(u.x, y.x) <= m.x && m.x <= Math.max(u.x, y.x) && Math.min(u.y, y.y) <= m.y && m.y <= Math.max(u.y, y.y), d = h(s, r, a), x = h(s, r, c), p = h(a, c, s), w = h(a, c, r);
412
- return !!(d !== x && p !== w || d === 0 && l(s, a, r) || x === 0 && l(s, c, r) || p === 0 && l(a, s, c) || w === 0 && l(a, r, c));
413
- }, o = this.points;
414
- for (let s = 0; s < 4; s++) {
415
- const r = o[s], a = o[(s + 1) % 4];
416
- for (let c = 0; c < 4; c++) {
417
- const h = t.points[c], l = t.points[(c + 1) % 4];
418
- if (i(r, a, h, l)) return !0;
497
+ return true;
498
+ };
499
+ const doIntersect = (l1p1, l1p2, l2p1, l2p2) => {
500
+ const orientation = (p, q, r) => {
501
+ const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
502
+ if (val === 0) return 0;
503
+ return val > 0 ? 1 : 2;
504
+ };
505
+ const onSegment = (p, q, r) => {
506
+ return Math.min(p.x, r.x) <= q.x && q.x <= Math.max(p.x, r.x) && Math.min(p.y, r.y) <= q.y && q.y <= Math.max(p.y, r.y);
507
+ };
508
+ const o1 = orientation(l1p1, l1p2, l2p1);
509
+ const o2 = orientation(l1p1, l1p2, l2p2);
510
+ const o3 = orientation(l2p1, l2p2, l1p1);
511
+ const o4 = orientation(l2p1, l2p2, l1p2);
512
+ if (o1 !== o2 && o3 !== o4) return true;
513
+ if (o1 === 0 && onSegment(l1p1, l2p1, l1p2)) return true;
514
+ if (o2 === 0 && onSegment(l1p1, l2p2, l1p2)) return true;
515
+ if (o3 === 0 && onSegment(l2p1, l1p1, l2p2)) return true;
516
+ if (o4 === 0 && onSegment(l2p1, l1p2, l2p2)) return true;
517
+ return false;
518
+ };
519
+ const boxPoints = this.points;
520
+ for (let i = 0; i < 4; i++) {
521
+ const bp1 = boxPoints[i];
522
+ const bp2 = boxPoints[(i + 1) % 4];
523
+ for (let j = 0; j < 4; j++) {
524
+ const rp1 = rectangle.points[j];
525
+ const rp2 = rectangle.points[(j + 1) % 4];
526
+ if (doIntersect(bp1, bp2, rp1, rp2)) return true;
419
527
  }
420
528
  }
421
- for (let s of t.points)
422
- if (e(s)) return !0;
423
- for (let s of o)
424
- if (n(s)) return !0;
425
- return !1;
529
+ for (let p of rectangle.points) {
530
+ if (isPointInBox(p)) return true;
531
+ }
532
+ for (let p of boxPoints) {
533
+ if (isPointInRect(p)) return true;
534
+ }
535
+ return false;
426
536
  }
427
537
  /**
428
538
  * 判断矩形是在包围盒内
429
539
  * @param rectangle
430
540
  */
431
- containsRectangle(t) {
432
- return t.points.every(
433
- (e) => this.minX <= e.x && e.x <= this.maxX && this.minY <= e.y && e.y <= this.maxY
541
+ containsRectangle(rectangle) {
542
+ return rectangle.points.every(
543
+ (p) => this.minX <= p.x && p.x <= this.maxX && this.minY <= p.y && p.y <= this.maxY
434
544
  );
435
545
  }
436
546
  /**
437
547
  * 判断包围盒与包围盒相交
438
548
  * @param box
439
549
  */
440
- intersectBox(t) {
441
- return !(this.maxX < t.minX || this.minX > t.maxX || this.maxY < t.minY || this.minY > t.maxY);
550
+ intersectBox(box) {
551
+ return !(this.maxX < box.minX || this.minX > box.maxX || this.maxY < box.minY || this.minY > box.maxY);
442
552
  }
443
553
  /**
444
554
  * 判断包围盒是在包围盒内
445
555
  * @param box
446
556
  */
447
- containsBox(t) {
448
- return this.minX <= t.minX && t.maxX <= this.maxX && this.minY <= t.minY && t.maxY <= this.maxY;
557
+ containsBox(box) {
558
+ return this.minX <= box.minX && box.maxX <= this.maxX && this.minY <= box.minY && box.maxY <= this.maxY;
449
559
  }
450
560
  /** 判断点是在包围盒内
451
561
  * @param point
452
562
  */
453
- containsPoint(t) {
454
- return t.x >= this.minX && t.x <= this.maxX && t.y >= this.minY && t.y <= this.maxY;
563
+ containsPoint(point) {
564
+ return point.x >= this.minX && point.x <= this.maxX && point.y >= this.minY && point.y <= this.maxY;
455
565
  }
456
566
  /**
457
567
  *
@@ -461,8 +571,12 @@ class A {
461
571
  * @param maxY
462
572
  * @returns
463
573
  */
464
- set(t, e, n, i) {
465
- return this.minX = t, this.minY = e, this.maxX = n, this.maxY = i, this;
574
+ set(minX, minY, maxX, maxY) {
575
+ this.minX = minX;
576
+ this.minY = minY;
577
+ this.maxX = maxX;
578
+ this.maxY = maxY;
579
+ return this;
466
580
  }
467
581
  /**
468
582
  *
@@ -471,46 +585,57 @@ class A {
471
585
  * @param mode
472
586
  * @returns
473
587
  */
474
- scaleSize(t, e, n = "min") {
475
- const i = t / this.width, o = e / this.height;
476
- return Math[n](i, o);
588
+ scaleSize(maxWidth, maxHeight, mode = "min") {
589
+ const scaleX = maxWidth / this.width;
590
+ const scaleY = maxHeight / this.height;
591
+ return Math[mode](scaleX, scaleY);
477
592
  }
478
593
  /**
479
594
  *
480
595
  * @param scalar
481
596
  * @returns
482
597
  */
483
- multiplyScalar(t) {
484
- return this.minX *= t, this.minY *= t, this.maxX *= t, this.maxY *= t, this;
598
+ multiplyScalar(scalar) {
599
+ this.minX *= scalar;
600
+ this.minY *= scalar;
601
+ this.maxX *= scalar;
602
+ this.maxY *= scalar;
603
+ return this;
485
604
  }
486
- expansion(t) {
487
- return this.minX -= t, this.minY -= t, this.maxX += t, this.maxY += t, this;
605
+ expansion(w) {
606
+ this.minX -= w;
607
+ this.minY -= w;
608
+ this.maxX += w;
609
+ this.maxY += w;
610
+ return this;
488
611
  }
489
612
  /**
490
613
  *
491
614
  * @returns
492
615
  */
493
616
  clone() {
494
- return new A(this.minX, this.maxX, this.minY, this.maxY);
617
+ return new Box2(this.minX, this.maxX, this.minY, this.maxY);
495
618
  }
496
619
  /**
497
620
  *
498
621
  * @param points
499
622
  * @returns
500
623
  */
501
- static fromByPoints(...t) {
502
- const e = [], n = [];
503
- return t.forEach((i) => {
504
- e.push(i.x), n.push(i.y);
505
- }), new A(
506
- Math.min(...e),
507
- Math.max(...e),
508
- Math.min(...n),
509
- Math.max(...n)
624
+ static fromByPoints(...points) {
625
+ const xList = [], yList = [];
626
+ points.forEach((p) => {
627
+ xList.push(p.x);
628
+ yList.push(p.y);
629
+ });
630
+ return new Box2(
631
+ Math.min(...xList),
632
+ Math.max(...xList),
633
+ Math.min(...yList),
634
+ Math.max(...yList)
510
635
  );
511
636
  }
512
637
  }
513
- class C {
638
+ class Rectangle {
514
639
  points;
515
640
  get p0() {
516
641
  return this.points[0];
@@ -525,15 +650,16 @@ class C {
525
650
  return this.points[3];
526
651
  }
527
652
  get path() {
528
- return this.points.flatMap((t, e) => {
529
- const n = this.points[(e + 1) % this.points.length];
530
- return [t.x, t.y, 0, n.x, n.y, 0];
653
+ return this.points.flatMap((p, i) => {
654
+ const np = this.points[(i + 1) % this.points.length];
655
+ return [p.x, p.y, 0, np.x, np.y, 0];
531
656
  });
532
657
  }
533
- path2D(t) {
534
- return this.points.flatMap((e, n) => {
535
- const i = this.points[(n + 1) % this.points.length];
536
- return t && t(new f(e.x, e.y), new f(i.x, i.y)), [e.x, e.y, i.x, i.y];
658
+ path2D(callback) {
659
+ return this.points.flatMap((p, i) => {
660
+ const np = this.points[(i + 1) % this.points.length];
661
+ callback && callback(new Point(p.x, p.y), new Point(np.x, np.y));
662
+ return [p.x, p.y, np.x, np.y];
537
663
  });
538
664
  }
539
665
  createGeometry() {
@@ -544,58 +670,85 @@ class C {
544
670
  this.p2,
545
671
  this.p0,
546
672
  this.p3
547
- ].flatMap((t) => [t.x, t.y, 0]);
673
+ ].flatMap((p) => [p.x, p.y, 0]);
548
674
  }
549
- constructor(t) {
550
- if (t.length !== 4)
675
+ constructor(points) {
676
+ if (points.length !== 4) {
551
677
  throw new Error("Rectangle must be defined by exactly 4 points");
552
- this.points = t;
678
+ }
679
+ this.points = points;
553
680
  }
554
681
  /**
555
682
  * 判断线段是否与矩形相交
556
683
  * @param line 线段
557
684
  * @returns 是否与矩形相交
558
685
  */
559
- intersectLineSegment(t) {
560
- if (t.points.length !== 2)
686
+ intersectLineSegment(line) {
687
+ if (line.points.length !== 2) {
561
688
  throw new Error("LineSegment must have exactly 2 points");
562
- const [e, n] = t.points, i = (o, s, r, a) => {
563
- const c = (w, u, m) => {
564
- const y = (u.y - w.y) * (m.x - u.x) - (u.x - w.x) * (m.y - u.y);
565
- return y === 0 ? 0 : y > 0 ? 1 : 2;
566
- }, h = (w, u, m) => Math.min(w.x, m.x) <= u.x && u.x <= Math.max(w.x, m.x) && Math.min(w.y, m.y) <= u.y && u.y <= Math.max(w.y, m.y), l = c(o, s, r), d = c(o, s, a), x = c(r, a, o), p = c(r, a, s);
567
- return !!(l !== d && x !== p || l === 0 && h(o, r, s) || d === 0 && h(o, a, s) || x === 0 && h(r, o, a) || p === 0 && h(r, s, a));
689
+ }
690
+ const [p1, p2] = line.points;
691
+ const doIntersect = (l1p1, l1p2, l2p1, l2p2) => {
692
+ const orientation = (p, q, r) => {
693
+ const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
694
+ if (val === 0) return 0;
695
+ return val > 0 ? 1 : 2;
696
+ };
697
+ const onSegment = (p, q, r) => {
698
+ return Math.min(p.x, r.x) <= q.x && q.x <= Math.max(p.x, r.x) && Math.min(p.y, r.y) <= q.y && q.y <= Math.max(p.y, r.y);
699
+ };
700
+ const o1 = orientation(l1p1, l1p2, l2p1);
701
+ const o2 = orientation(l1p1, l1p2, l2p2);
702
+ const o3 = orientation(l2p1, l2p2, l1p1);
703
+ const o4 = orientation(l2p1, l2p2, l1p2);
704
+ if (o1 !== o2 && o3 !== o4) return true;
705
+ if (o1 === 0 && onSegment(l1p1, l2p1, l1p2)) return true;
706
+ if (o2 === 0 && onSegment(l1p1, l2p2, l1p2)) return true;
707
+ if (o3 === 0 && onSegment(l2p1, l1p1, l2p2)) return true;
708
+ if (o4 === 0 && onSegment(l2p1, l1p2, l2p2)) return true;
709
+ return false;
568
710
  };
569
- for (let o = 0; o < 4; o++) {
570
- const s = this.points[o], r = this.points[(o + 1) % 4];
571
- if (i(e, n, s, r))
572
- return !0;
711
+ for (let i = 0; i < 4; i++) {
712
+ const rectP1 = this.points[i];
713
+ const rectP2 = this.points[(i + 1) % 4];
714
+ if (doIntersect(p1, p2, rectP1, rectP2)) {
715
+ return true;
716
+ }
573
717
  }
574
- return !!this.containsLineSegment(t);
718
+ if (this.containsLineSegment(line)) {
719
+ return true;
720
+ }
721
+ return false;
575
722
  }
576
723
  /**
577
724
  * 判断线段是否完全位于矩形内部
578
725
  * @param line 线段
579
726
  * @returns 是否完全在矩形内部
580
727
  */
581
- containsLineSegment(t) {
582
- if (t.points.length !== 2)
728
+ containsLineSegment(line) {
729
+ if (line.points.length !== 2) {
583
730
  throw new Error("LineSegment must have exactly 2 points");
584
- const e = (n) => {
585
- let i = 0;
586
- for (let o = 0; o < 4; o++) {
587
- const s = this.points[o], r = this.points[(o + 1) % 4], a = { x: r.x - s.x, y: r.y - s.y }, c = { x: n.x - s.x, y: n.y - s.y }, h = a.x * c.y - a.y * c.x;
588
- if (h === 0) {
589
- const l = a.x !== 0 ? (n.x - s.x) / a.x : (n.y - s.y) / a.y;
590
- if (l >= 0 && l <= 1) return !0;
731
+ }
732
+ const isPointInRectangle = (point) => {
733
+ let sign = 0;
734
+ for (let i = 0; i < 4; i++) {
735
+ const p1 = this.points[i];
736
+ const p2 = this.points[(i + 1) % 4];
737
+ const edge = { x: p2.x - p1.x, y: p2.y - p1.y };
738
+ const toPoint = { x: point.x - p1.x, y: point.y - p1.y };
739
+ const cross = edge.x * toPoint.y - edge.y * toPoint.x;
740
+ if (cross === 0) {
741
+ const t = edge.x !== 0 ? (point.x - p1.x) / edge.x : (point.y - p1.y) / edge.y;
742
+ if (t >= 0 && t <= 1) return true;
591
743
  } else {
592
- const l = h > 0 ? 1 : -1;
593
- if (i === 0 && (i = l), i !== l) return !1;
744
+ const currentSign = cross > 0 ? 1 : -1;
745
+ if (sign === 0) sign = currentSign;
746
+ if (sign !== currentSign) return false;
594
747
  }
595
748
  }
596
- return !0;
749
+ return true;
597
750
  };
598
- return e(t.points[0]) && e(t.points[1]);
751
+ return isPointInRectangle(line.points[0]) && isPointInRectangle(line.points[1]);
599
752
  }
600
753
  /**
601
754
  * 判断矩形是否与矩形相交
@@ -603,53 +756,64 @@ class C {
603
756
  * @param rectangle 矩形
604
757
  * @returns 是否与矩形相交
605
758
  */
606
- intersectRectangle(t) {
607
- const e = [];
608
- for (let o = 0; o < 4; o++) {
609
- const s = this.points[o], r = this.points[(o + 1) % 4];
610
- e.push(s.normal(r));
759
+ intersectRectangle(rectangle) {
760
+ const axes = [];
761
+ for (let i = 0; i < 4; i++) {
762
+ const p1 = this.points[i];
763
+ const p2 = this.points[(i + 1) % 4];
764
+ axes.push(p1.normal(p2));
611
765
  }
612
- for (let o = 0; o < 4; o++) {
613
- const s = t.points[o], r = t.points[(o + 1) % 4];
614
- e.push(s.normal(r));
766
+ for (let i = 0; i < 4; i++) {
767
+ const p1 = rectangle.points[i];
768
+ const p2 = rectangle.points[(i + 1) % 4];
769
+ axes.push(p1.normal(p2));
615
770
  }
616
- function n(o, s) {
617
- const r = o.points.map((a) => a.dot(s));
618
- return [Math.min(...r), Math.max(...r)];
771
+ function projectRectangle(rect, axis) {
772
+ const projections = rect.points.map((point) => point.dot(axis));
773
+ return [Math.min(...projections), Math.max(...projections)];
619
774
  }
620
- function i(o, s) {
621
- return o[0] < s[1] && s[0] < o[1];
775
+ function isProjectionOverlap(proj1, proj2) {
776
+ return proj1[0] < proj2[1] && proj2[0] < proj1[1];
622
777
  }
623
- for (const o of e) {
624
- const s = n(this, o), r = n(t, o);
625
- if (!i(s, r))
626
- return !1;
778
+ for (const axis of axes) {
779
+ const proj1 = projectRectangle(this, axis);
780
+ const proj2 = projectRectangle(rectangle, axis);
781
+ if (!isProjectionOverlap(proj1, proj2)) {
782
+ return false;
783
+ }
627
784
  }
628
- return !0;
785
+ return true;
629
786
  }
630
787
  /**
631
788
  * 判断点是否完全位于矩形内部
632
789
  * @param point
633
790
  */
634
- containsPoint(t) {
635
- let e = 0, n = 0;
791
+ containsPoint(point) {
792
+ let positiveCount = 0;
793
+ let negativeCount = 0;
636
794
  for (let i = 0; i < 4; i++) {
637
- const o = this.points[i], s = this.points[(i + 1) % 4], r = (s.x - o.x) * (t.y - o.y) - (s.y - o.y) * (t.x - o.x);
638
- if (r > 0) e++;
639
- else if (r < 0) n++;
640
- else return !1;
795
+ const p1 = this.points[i];
796
+ const p2 = this.points[(i + 1) % 4];
797
+ const cross = (p2.x - p1.x) * (point.y - p1.y) - (p2.y - p1.y) * (point.x - p1.x);
798
+ if (cross > 0) positiveCount++;
799
+ else if (cross < 0) negativeCount++;
800
+ else return false;
641
801
  }
642
- return e === 4 || n === 4;
802
+ return positiveCount === 4 || negativeCount === 4;
643
803
  }
644
804
  /**
645
805
  *
646
806
  * @returns
647
807
  */
648
808
  toBox() {
649
- let t = 1 / 0, e = -1 / 0, n = 1 / 0, i = -1 / 0;
650
- return this.points.forEach((o) => {
651
- e = Math.max(o.x, e), t = Math.min(o.x, t), i = Math.max(o.x, i), n = Math.min(o.x, n);
652
- }), new A(t, e, n, i);
809
+ let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
810
+ this.points.forEach((p) => {
811
+ maxX = Math.max(p.x, maxX);
812
+ minX = Math.min(p.x, minX);
813
+ maxY = Math.max(p.x, maxY);
814
+ minY = Math.min(p.x, minY);
815
+ });
816
+ return new Box2(minX, maxX, minY, maxY);
653
817
  }
654
818
  /**
655
819
  *
@@ -657,22 +821,24 @@ class C {
657
821
  * @param width
658
822
  * @returns
659
823
  */
660
- static fromByLineSegment(t, e = 0.1, n = !1, i = 0.5) {
661
- const o = t.points[0], s = t.points[1], r = s.normal(o), a = n ? s.direction(o).mutiplyScalar(e * i) : f.zero(), c = n ? o.direction(s).mutiplyScalar(e * i) : f.zero(), h = r.x * e * 0.5, l = r.y * e * 0.5;
662
- return new C([
663
- new f(o.x + h, o.y + l).add(c),
664
- new f(s.x + h, s.y + l).add(a),
665
- new f(s.x - h, s.y - l).add(a),
666
- new f(o.x - h, o.y - l).add(c)
824
+ static fromByLineSegment(line, width = 0.1, horizontal = false, hScale = 0.5) {
825
+ const p1 = line.points[0], p2 = line.points[1], normal = p2.normal(p1), pDirect = horizontal ? p2.direction(p1).mutiplyScalar(width * hScale) : Point.zero(), nDirect = horizontal ? p1.direction(p2).mutiplyScalar(width * hScale) : Point.zero();
826
+ const offsetX = normal.x * width * 0.5;
827
+ const offsetY = normal.y * width * 0.5;
828
+ return new Rectangle([
829
+ new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
830
+ new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
831
+ new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect),
832
+ new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect)
667
833
  ]);
668
834
  }
669
835
  }
670
- class b {
671
- points = [new f(), new f()];
836
+ class LineSegment {
837
+ points = [new Point(), new Point()];
672
838
  userData = {};
673
839
  line;
674
840
  get center() {
675
- return new f(
841
+ return new Point(
676
842
  this.points[0].x + (this.points[1].x - this.points[0].x) * 0.5,
677
843
  this.points[0].y + (this.points[1].y - this.points[0].y) * 0.5
678
844
  );
@@ -683,84 +849,71 @@ class b {
683
849
  get end() {
684
850
  return this.points[1];
685
851
  }
686
- constructor(t = new f(), e = new f()) {
687
- this.points = [t, e];
688
- }
689
- set(t, e) {
690
- this.start.copy(t), this.end.copy(e);
691
- }
692
- /**
693
- * 是否有相同端点
694
- * @param line
695
- * @returns
696
- */
697
- sameEndpoint(t) {
698
- return this.start.equal(t.start) || this.start.equal(t.end) || this.end.equal(t.start) || this.end.equal(t.end);
699
- }
700
- /**
701
- * 相同端点是否为开始
702
- * @param line
703
- * @returns
704
- */
705
- sameEndpointAsStart(t) {
706
- return this.start.equal(t.start) || this.start.equal(t.end);
707
- }
708
- /**
709
- * 相同端点是否为结束
710
- * @param line
711
- * @returns
712
- */
713
- sameEndpointAsEnd(t) {
714
- return this.end.equal(t.start) || this.end.equal(t.end);
852
+ constructor(p1 = new Point(), p2 = new Point()) {
853
+ this.points = [p1, p2];
715
854
  }
716
855
  /** 膨胀
717
856
  * @description 向线段的两个端点分别膨胀 width
718
857
  * @param width
719
858
  */
720
- expansion(t, e = "all") {
721
- const n = this.direction().multiplyScalar(t);
722
- return (e === "end" || e === "all") && this.end.add(n), (e === "start" || e === "all") && this.start.add(n.multiplyScalar(-1)), this;
859
+ expansion(width, direction = "all") {
860
+ const step = this.direction().multiplyScalar(width);
861
+ if (direction === "end" || direction === "all") this.end.add(step);
862
+ if (direction === "start" || direction === "all") this.start.add(step.multiplyScalar(-1));
863
+ return this;
723
864
  }
724
865
  /** 向前
725
866
  * @description 向前移动 width
726
867
  * @param width
727
868
  */
728
- forward(t) {
729
- const e = this.direction().multiplyScalar(t);
730
- return this.start.add(e), this.end.add(e), this;
869
+ forward(width) {
870
+ const step = this.direction().multiplyScalar(width);
871
+ this.start.add(step);
872
+ this.end.add(step);
873
+ return this;
731
874
  }
732
875
  /** 向前
733
876
  * @description 向前移动 width
734
877
  * @param width
735
878
  */
736
- backward(t) {
737
- const e = this.direction().multiplyScalar(-t);
738
- return this.start.add(e), this.end.add(e), this;
879
+ backward(width) {
880
+ const step = this.direction().multiplyScalar(-width);
881
+ this.start.add(step);
882
+ this.end.add(step);
883
+ return this;
739
884
  }
740
885
  /**
741
886
  * 向指定方向平移
742
887
  * @param direct
743
888
  * @param size
744
889
  */
745
- directionMove(t, e) {
746
- const n = t.clone().multiplyScalar(e);
747
- return this.start.add(n), this.end.add(n), this;
890
+ directionMove(direct, size) {
891
+ const step = direct.clone().multiplyScalar(size);
892
+ this.start.add(step);
893
+ this.end.add(step);
894
+ return this;
748
895
  }
749
896
  /** 膨胀为矩形
750
897
  *
751
898
  * @param width
752
899
  * @returns {Rectangle}
753
900
  */
754
- expandToRectangle(t = 0.1, e = "all") {
755
- const n = this.start, i = this.end, o = i.normal(n), s = e === "bothSides" ? f.zero() : i.direction(n).mutiplyScalar(t * 0.5), r = e === "bothSides" ? f.zero() : n.direction(i).mutiplyScalar(t * 0.5), a = o.x * t * 0.5, c = o.y * t * 0.5, h = [
901
+ expandToRectangle(width = 0.1, direct = "all") {
902
+ const p1 = this.start, p2 = this.end;
903
+ const normal = p2.normal(p1);
904
+ const pDirect = direct === "bothSides" ? Point.zero() : p2.direction(p1).mutiplyScalar(width * 0.5);
905
+ const nDirect = direct === "bothSides" ? Point.zero() : p1.direction(p2).mutiplyScalar(width * 0.5);
906
+ const offsetX = normal.x * width * 0.5;
907
+ const offsetY = normal.y * width * 0.5;
908
+ const point = [
756
909
  // 第一条线
757
- new f(n.x + a, n.y + c).add(r),
758
- new f(i.x + a, i.y + c).add(s),
910
+ new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
911
+ new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
759
912
  // 第二条线
760
- new f(n.x - a, n.y - c).add(r),
761
- new f(i.x - a, i.y - c).add(s)
913
+ new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
914
+ new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
762
915
  ];
763
- return new C([0, 1, 3, 2].map((l) => h[l]));
916
+ return new Rectangle([0, 1, 3, 2].map((i) => point[i]));
764
917
  }
765
918
  /**
766
919
  * 计算线段的长度
@@ -794,27 +947,50 @@ class b {
794
947
  * @param line 要投影的线段
795
948
  * @returns 投影并裁剪后的线段
796
949
  */
797
- projectLineSegment(t) {
798
- if (t.points.length !== 2 || this.points.length !== 2)
950
+ projectLineSegment(line) {
951
+ if (line.points.length !== 2 || this.points.length !== 2) {
799
952
  throw new Error("每条线段必须由两个点定义");
800
- const [e, n] = t.points, [i, o] = this.points, s = new f(o.x - i.x, o.y - i.y);
801
- if (s.x === 0 && s.y === 0)
953
+ }
954
+ const [p1, p2] = line.points;
955
+ const [q1, q2] = this.points;
956
+ const dir = new Point(q2.x - q1.x, q2.y - q1.y);
957
+ if (dir.x === 0 && dir.y === 0) {
802
958
  throw new Error("投影目标线段的两个点不能重合");
803
- const r = (p) => {
804
- const w = new f(p.x - i.x, p.y - i.y), u = s.x * s.x + s.y * s.y, y = (w.x * s.x + w.y * s.y) / u, S = i.x + y * s.x, D = i.y + y * s.y;
805
- return new f(S, D);
959
+ }
960
+ const projectPoint = (point) => {
961
+ const pq = new Point(point.x - q1.x, point.y - q1.y);
962
+ const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
963
+ const dotProduct = pq.x * dir.x + pq.y * dir.y;
964
+ const t = dotProduct / dirLengthSquared;
965
+ const projX = q1.x + t * dir.x;
966
+ const projY = q1.y + t * dir.y;
967
+ return new Point(projX, projY);
806
968
  };
807
- let a = r(e), c = r(n);
808
- const h = (p) => {
809
- const w = new f(p.x - i.x, p.y - i.y), u = s.x * s.x + s.y * s.y;
810
- return (w.x * s.x + w.y * s.y) / u;
969
+ let projP1 = projectPoint(p1);
970
+ let projP2 = projectPoint(p2);
971
+ const getT = (point) => {
972
+ const pq = new Point(point.x - q1.x, point.y - q1.y);
973
+ const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
974
+ return (pq.x * dir.x + pq.y * dir.y) / dirLengthSquared;
811
975
  };
812
- let l = h(a), d = h(c);
813
- const x = (p) => {
814
- const w = Math.max(0, Math.min(1, p)), u = i.x + w * s.x, m = i.y + w * s.y;
815
- return new f(u, m);
976
+ let t1 = getT(projP1);
977
+ let t2 = getT(projP2);
978
+ const clampPoint = (t) => {
979
+ const clampedT = Math.max(0, Math.min(1, t));
980
+ const x = q1.x + clampedT * dir.x;
981
+ const y = q1.y + clampedT * dir.y;
982
+ return new Point(x, y);
816
983
  };
817
- return (l < 0 || l > 1) && (a = x(l)), (d < 0 || d > 1) && (c = x(d)), a.x === c.x && a.y === c.y ? new b(a, a) : new b(a, c);
984
+ if (t1 < 0 || t1 > 1) {
985
+ projP1 = clampPoint(t1);
986
+ }
987
+ if (t2 < 0 || t2 > 1) {
988
+ projP2 = clampPoint(t2);
989
+ }
990
+ if (projP1.x === projP2.x && projP1.y === projP2.y) {
991
+ return new LineSegment(projP1, projP1);
992
+ }
993
+ return new LineSegment(projP1, projP2);
818
994
  }
819
995
  /**
820
996
  * 计算一条线段在另一条直线上的投影
@@ -822,106 +998,155 @@ class b {
822
998
  * @param clip 是否裁剪超出目标线段的部分,默认裁剪
823
999
  * @returns 投影并裁剪后的线段
824
1000
  */
825
- projectPoint(t, e = !0) {
826
- const [n, i] = this.points, o = new f(i.x - n.x, i.y - n.y);
827
- if (o.x === 0 && o.y === 0)
1001
+ projectPoint(p1, clip = true) {
1002
+ const [q1, q2] = this.points;
1003
+ const dir = new Point(q2.x - q1.x, q2.y - q1.y);
1004
+ if (dir.x === 0 && dir.y === 0) {
828
1005
  throw new Error("投影目标线段的两个点不能重合");
829
- let r = ((h) => {
830
- const l = new f(h.x - n.x, h.y - n.y), d = o.x * o.x + o.y * o.y, p = (l.x * o.x + l.y * o.y) / d, w = n.x + p * o.x, u = n.y + p * o.y;
831
- return new f(w, u);
832
- })(t);
833
- if (!e) return r;
834
- let c = ((h) => {
835
- const l = new f(h.x - n.x, h.y - n.y), d = o.x * o.x + o.y * o.y;
836
- return (l.x * o.x + l.y * o.y) / d;
837
- })(r);
838
- return c < 0 || c > 1 ? null : r;
1006
+ }
1007
+ const projectPoint = (point) => {
1008
+ const pq = new Point(point.x - q1.x, point.y - q1.y);
1009
+ const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
1010
+ const dotProduct = pq.x * dir.x + pq.y * dir.y;
1011
+ const t = dotProduct / dirLengthSquared;
1012
+ const projX = q1.x + t * dir.x;
1013
+ const projY = q1.y + t * dir.y;
1014
+ return new Point(projX, projY);
1015
+ };
1016
+ let projP1 = projectPoint(p1);
1017
+ if (!clip) return projP1;
1018
+ const getT = (point) => {
1019
+ const pq = new Point(point.x - q1.x, point.y - q1.y);
1020
+ const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
1021
+ return (pq.x * dir.x + pq.y * dir.y) / dirLengthSquared;
1022
+ };
1023
+ let t1 = getT(projP1);
1024
+ if (t1 < 0 || t1 > 1) {
1025
+ return null;
1026
+ }
1027
+ return projP1;
839
1028
  }
840
1029
  /**
841
1030
  * 判断线段是否与另一条线段相交(包含共用端点或部分重合的情况)
842
1031
  * @param line
843
1032
  */
844
- intersectLineSegment(t) {
845
- const e = this.start, n = this.end, i = t.start, o = t.end;
846
- function s(d, x, p) {
847
- return (x.x - d.x) * (p.y - d.y) - (x.y - d.y) * (p.x - d.x);
1033
+ intersectLineSegment(line) {
1034
+ const p1 = this.start;
1035
+ const p2 = this.end;
1036
+ const p3 = line.start;
1037
+ const p4 = line.end;
1038
+ function crossProduct(a, b, c) {
1039
+ return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
1040
+ }
1041
+ function isPointOnSegment(pt, segStart, segEnd) {
1042
+ return Math.min(segStart.x, segEnd.x) - 1e-10 <= pt.x && pt.x <= Math.max(segStart.x, segEnd.x) + 1e-10 && Math.min(segStart.y, segEnd.y) - 1e-10 <= pt.y && pt.y <= Math.max(segStart.y, segEnd.y) + 1e-10;
1043
+ }
1044
+ const d1 = crossProduct(p1, p2, p3);
1045
+ const d2 = crossProduct(p1, p2, p4);
1046
+ const d3 = crossProduct(p3, p4, p1);
1047
+ const d4 = crossProduct(p3, p4, p2);
1048
+ if (d1 * d2 < 0 && d3 * d4 < 0) {
1049
+ return true;
1050
+ }
1051
+ if (Math.abs(d1) < 1e-10 && isPointOnSegment(p3, p1, p2)) {
1052
+ return true;
848
1053
  }
849
- function r(d, x, p) {
850
- return Math.min(x.x, p.x) - 1e-10 <= d.x && d.x <= Math.max(x.x, p.x) + 1e-10 && Math.min(x.y, p.y) - 1e-10 <= d.y && d.y <= Math.max(x.y, p.y) + 1e-10;
1054
+ if (Math.abs(d2) < 1e-10 && isPointOnSegment(p4, p1, p2)) {
1055
+ return true;
851
1056
  }
852
- const a = s(e, n, i), c = s(e, n, o), h = s(i, o, e), l = s(i, o, n);
853
- return !!(a * c < 0 && h * l < 0 || Math.abs(a) < 1e-10 && r(i, e, n) || Math.abs(c) < 1e-10 && r(o, e, n) || Math.abs(h) < 1e-10 && r(e, i, o) || Math.abs(l) < 1e-10 && r(n, i, o));
1057
+ if (Math.abs(d3) < 1e-10 && isPointOnSegment(p1, p3, p4)) {
1058
+ return true;
1059
+ }
1060
+ if (Math.abs(d4) < 1e-10 && isPointOnSegment(p2, p3, p4)) {
1061
+ return true;
1062
+ }
1063
+ return false;
854
1064
  }
855
1065
  /**
856
1066
  * 获取交点
857
1067
  * @param line
858
1068
  * @returns
859
1069
  */
860
- getIntersection(t) {
861
- const e = this.start, n = this.end, i = t.start, o = t.end, s = (e.x - n.x) * (i.y - o.y) - (e.y - n.y) * (i.x - o.x);
862
- if (Math.abs(s) < 1e-10)
1070
+ getIntersection(line) {
1071
+ const p1 = this.start;
1072
+ const p2 = this.end;
1073
+ const p3 = line.start;
1074
+ const p4 = line.end;
1075
+ const denom = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x);
1076
+ if (Math.abs(denom) < 1e-10) {
863
1077
  return null;
864
- const r = ((e.x - i.x) * (i.y - o.y) - (e.y - i.y) * (i.x - o.x)) / s, a = e.x + r * (n.x - e.x), c = e.y + r * (n.y - e.y);
865
- return new f(a, c);
1078
+ }
1079
+ const t = ((p1.x - p3.x) * (p3.y - p4.y) - (p1.y - p3.y) * (p3.x - p4.x)) / denom;
1080
+ const x = p1.x + t * (p2.x - p1.x);
1081
+ const y = p1.y + t * (p2.y - p1.y);
1082
+ return new Point(x, y);
866
1083
  }
867
1084
  /**
868
1085
  * 获取两条线段夹角
869
1086
  * @param line
870
1087
  */
871
- includedAngle(t) {
872
- const e = this.direction(), n = t.direction();
873
- return e.angleBetween(n) / (Math.PI / 180);
1088
+ includedAngle(line) {
1089
+ const d1 = this.direction(), d2 = line.direction();
1090
+ return d1.angleBetween(d2) / (Math.PI / 180);
874
1091
  }
875
1092
  /**
876
1093
  * 两条线段方向是否一致
877
1094
  * @param line
878
1095
  */
879
- directionEqual(t, e = 0.1) {
880
- return this.includedAngle(t) < e;
1096
+ directionEqual(line, errAngle = 0.1) {
1097
+ return this.includedAngle(line) < errAngle;
881
1098
  }
882
1099
  /**
883
1100
  * 两条线段方向相反否一致
884
1101
  * @param line
885
1102
  */
886
- directionOpposite(t, e = 0.1) {
887
- return 180 - this.includedAngle(t) < e;
1103
+ directionOpposite(line, errAngle = 0.1) {
1104
+ return 180 - this.includedAngle(line) < errAngle;
888
1105
  }
889
1106
  /**
890
1107
  * 判断两条线是否平行
891
1108
  * @param line
892
1109
  */
893
- isParallel(t, e = 4) {
894
- const n = this.includedAngle(t);
895
- return n < e || n > 180 - e;
1110
+ isParallel(line, errAngle = 4) {
1111
+ const angle = this.includedAngle(line);
1112
+ return angle < errAngle || angle > 180 - errAngle;
896
1113
  }
897
1114
  /**
898
1115
  * 判断两条直线是否重合
899
1116
  * @param line
900
1117
  * @returns
901
1118
  */
902
- areLinesCoincident(t) {
903
- const e = this.start, n = this.end, i = t.start, o = t.end, s = (n.y - e.y) / (n.x - e.x), r = e.y - s * e.x, a = (o.y - i.y) / (o.x - i.x), c = i.y - a * i.x;
904
- return !isFinite(s) && !isFinite(a) ? e.x === i.x && n.x === i.x : Math.abs(s - a) < 1e-3 && Math.abs(r - c) < 1e-3;
1119
+ areLinesCoincident(line) {
1120
+ const p1 = this.start, p2 = this.end, p3 = line.start, p4 = line.end;
1121
+ const m1 = (p2.y - p1.y) / (p2.x - p1.x);
1122
+ const b1 = p1.y - m1 * p1.x;
1123
+ const m2 = (p4.y - p3.y) / (p4.x - p3.x);
1124
+ const b2 = p3.y - m2 * p3.x;
1125
+ if (!isFinite(m1) && !isFinite(m2)) {
1126
+ return p1.x === p3.x && p2.x === p3.x;
1127
+ }
1128
+ return Math.abs(m1 - m2) < 1e-3 && Math.abs(b1 - b2) < 1e-3;
905
1129
  }
906
1130
  clone() {
907
- return new b(
1131
+ return new LineSegment(
908
1132
  this.points[0].clone(),
909
1133
  this.points[1].clone()
910
1134
  );
911
1135
  }
912
1136
  }
913
- async function q(g, t = !0) {
914
- if (typeof global < "u" && typeof require < "u")
915
- return require(g);
916
- {
917
- let e = await import(
1137
+ async function include(path, exportDefault = true) {
1138
+ if (typeof global !== "undefined" && typeof require !== "undefined") {
1139
+ return require(path);
1140
+ } else {
1141
+ let pack = await import(
918
1142
  /* @vite-ignore */
919
- g
1143
+ path
920
1144
  );
921
- return t && (e = e.default), e;
1145
+ if (exportDefault) pack = pack.default;
1146
+ return pack;
922
1147
  }
923
1148
  }
924
- const nt = {
1149
+ const units = {
925
1150
  Unitless: 1,
926
1151
  // 无单位,1米 = 1(无单位)
927
1152
  Inches: 39.37007874015748,
@@ -965,27 +1190,31 @@ const nt = {
965
1190
  Parsecs: 3240779289666404e-32
966
1191
  // 秒差距,1米 ≈ 0.00000000000000003240779289666404秒差距
967
1192
  };
968
- function F(g) {
969
- const t = [];
970
- for (let e = 0; e < g.length; e++)
971
- t.push(new b(
972
- g[e].clone(),
973
- g[(e + 1) % g.length].clone()
1193
+ function pathToLines(path) {
1194
+ const lineSegments = [];
1195
+ for (let i = 0; i < path.length; i++) {
1196
+ lineSegments.push(new LineSegment(
1197
+ path[i].clone(),
1198
+ path[(i + 1) % path.length].clone()
974
1199
  ));
975
- return t;
1200
+ }
1201
+ return lineSegments;
976
1202
  }
977
- function z(g) {
978
- return g.flatMap((t, e) => (e === g.length - 1 && [...t.points, g[0].points[0]], [t.points[0]]));
1203
+ function linesToPath(lineSegments) {
1204
+ return lineSegments.flatMap((line, index2) => {
1205
+ if (index2 === lineSegments.length - 1) [...line.points, lineSegments[0].points[0]];
1206
+ return [line.points[0]];
1207
+ });
979
1208
  }
980
- class I extends X {
1209
+ class Dxf extends Component {
981
1210
  static name = "Dxf";
982
1211
  shortLine = 0.04;
983
1212
  width = 0.04;
984
1213
  scale = 1;
985
1214
  originalData = [];
986
1215
  data = [];
987
- originalBox = new A(0, 0, 0, 0);
988
- box = new A(0, 0, 0, 0);
1216
+ originalBox = new Box2(0, 0, 0, 0);
1217
+ box = new Box2(0, 0, 0, 0);
989
1218
  pointsGroups = [];
990
1219
  wallsGroup = [];
991
1220
  doors = [];
@@ -1014,8 +1243,11 @@ class I extends X {
1014
1243
  * @param width 墙体宽度
1015
1244
  * @param scale 缩放比例
1016
1245
  */
1017
- constructor(t = 0.04, e = 1) {
1018
- super(), this.width = t, this.scale = e, this.shortLine = t * 0.4;
1246
+ constructor(width = 0.04, scale = 1) {
1247
+ super();
1248
+ this.width = width;
1249
+ this.scale = scale;
1250
+ this.shortLine = width * 0.4;
1019
1251
  }
1020
1252
  /**
1021
1253
  * 设置
@@ -1023,36 +1255,52 @@ class I extends X {
1023
1255
  * @param width
1024
1256
  * @param scale
1025
1257
  */
1026
- async set(t, e = this.width, n = this.scale) {
1027
- if (typeof t == "string")
1028
- if (typeof global < "u") {
1029
- const { default: s } = await import(
1258
+ async set(data, width = this.width, scale = this.scale) {
1259
+ if (typeof data === "string") {
1260
+ if (typeof global !== "undefined") {
1261
+ const packageName = "fs";
1262
+ const { default: fs } = await import(
1030
1263
  /* @vite-ignore */
1031
- "fs"
1032
- ), r = s.readFileSync(t), a = JSON.parse(r.toString("utf-8"));
1033
- return this.set(a, e, n);
1034
- } else
1264
+ packageName
1265
+ );
1266
+ const buffer = fs.readFileSync(data);
1267
+ const json = JSON.parse(buffer.toString("utf-8"));
1268
+ return this.set(json, width, scale);
1269
+ } else {
1035
1270
  throw new Error("非node环境不允许使用路径");
1036
- this.scale = n, this.width = e, this.originalData = t, this.lineSegments.length = 0;
1037
- const i = [];
1038
- this.data = t.map(({ start: o, end: s, insetionArr: r, isDoor: a = !1, isWindow: c, drawDoorData: h }, l) => {
1039
- i.push(o.z ?? 0, s.z ?? 0);
1040
- const d = new b(
1041
- f.from(o).mutiplyScalar(n),
1042
- f.from(s).mutiplyScalar(n)
1271
+ }
1272
+ }
1273
+ this.scale = scale;
1274
+ this.width = width;
1275
+ this.originalData = data;
1276
+ this.lineSegments.length = 0;
1277
+ const zList = [];
1278
+ this.data = data.map(({ start, end, insetionArr, isDoor = false, isWindow, drawDoorData }, index2) => {
1279
+ zList.push(start.z ?? 0, end.z ?? 0);
1280
+ const lineSegment = new LineSegment(
1281
+ Point.from(start).mutiplyScalar(scale),
1282
+ Point.from(end).mutiplyScalar(scale)
1043
1283
  );
1044
- return d.userData = { isDoor: a, isWindow: c, drawDoorData: h }, this.lineSegments.push(d), [
1045
- d.points[0],
1046
- d.points[1],
1047
- (r ?? []).map((x) => x.index),
1048
- a,
1049
- l
1284
+ lineSegment.userData = { isDoor, isWindow, drawDoorData };
1285
+ this.lineSegments.push(lineSegment);
1286
+ return [
1287
+ lineSegment.points[0],
1288
+ lineSegment.points[1],
1289
+ (insetionArr ?? []).map((i) => i.index),
1290
+ isDoor,
1291
+ index2
1050
1292
  ];
1051
- }), this.originalZAverage = i.reduce((o, s) => o + s, 0) / i.length, this.computedOriginalSize(t, this.originalBox), this.dispatchEvent({
1293
+ });
1294
+ this.originalZAverage = zList.reduce((count, num) => count + num, 0) / zList.length;
1295
+ this.computedOriginalSize(data, this.originalBox);
1296
+ this.dispatchEvent({
1052
1297
  type: "setDta",
1053
1298
  originalData: this.originalData,
1054
1299
  data: this.data
1055
- }), this.createGroups(), this.computedSize(), this.dispatchEvent({
1300
+ });
1301
+ this.createGroups();
1302
+ this.computedSize();
1303
+ this.dispatchEvent({
1056
1304
  type: "createGroup",
1057
1305
  groups: this.pointsGroups
1058
1306
  });
@@ -1062,20 +1310,32 @@ class I extends X {
1062
1310
  * @returns
1063
1311
  */
1064
1312
  createGroups() {
1065
- const t = [], e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Map(), o = (s, r, a = -1) => {
1066
- const [c, h, l, d] = this.data[s];
1067
- if (e.add(s), d)
1068
- return i.has(s) || i.set(s, []), i.get(s)?.push(a), n.add(this.data[s]);
1069
- r.push([c, h]), l.forEach((x) => {
1070
- e.has(x) || o(x, r, s);
1313
+ const groups = [], visited = /* @__PURE__ */ new Set(), doorSet = /* @__PURE__ */ new Set(), doorVisitedRecord = /* @__PURE__ */ new Map();
1314
+ const dfs = (index2, group, preIndex = -1) => {
1315
+ const [start, end, insetionArr, isDoor] = this.data[index2];
1316
+ visited.add(index2);
1317
+ if (isDoor) {
1318
+ if (!doorVisitedRecord.has(index2)) doorVisitedRecord.set(index2, []);
1319
+ doorVisitedRecord.get(index2)?.push(preIndex);
1320
+ return doorSet.add(this.data[index2]);
1321
+ }
1322
+ group.push([start, end]);
1323
+ insetionArr.forEach((i) => {
1324
+ if (!visited.has(i)) {
1325
+ dfs(i, group, index2);
1326
+ }
1071
1327
  });
1072
1328
  };
1073
- return this.data.forEach((s, r) => {
1074
- if (!e.has(r)) {
1075
- const a = [];
1076
- o(r, a), t.push(a);
1329
+ this.data.forEach((_, index2) => {
1330
+ if (!visited.has(index2)) {
1331
+ const group = [];
1332
+ dfs(index2, group);
1333
+ groups.push(group);
1077
1334
  }
1078
- }), this.doors = [...n], this.pointsGroups = t, t;
1335
+ });
1336
+ this.doors = [...doorSet];
1337
+ this.pointsGroups = groups;
1338
+ return groups;
1079
1339
  }
1080
1340
  /** 计算当前墙体数据的边界框
1081
1341
  * @description 根据分组数据pointsGroups,计算包围盒, pointsGroups数据为缩放后数据。
@@ -1083,163 +1343,224 @@ class I extends X {
1083
1343
  * @returns
1084
1344
  */
1085
1345
  computedSize() {
1086
- const t = this.pointsGroups.flatMap((r) => r.flatMap((a) => [a[0].x, a[1].x])), e = this.pointsGroups.flatMap((r) => r.flatMap((a) => [a[0].y, a[1].y])), n = Math.min(...t), i = Math.min(...e), o = Math.max(...t), s = Math.max(...e);
1087
- return this.box.set(n, i, o, s), this.box;
1346
+ const xArr = this.pointsGroups.flatMap((points) => points.flatMap((p) => [p[0].x, p[1].x]));
1347
+ const yArr = this.pointsGroups.flatMap((points) => points.flatMap((p) => [p[0].y, p[1].y]));
1348
+ const minX = Math.min(...xArr);
1349
+ const minY = Math.min(...yArr);
1350
+ const maxX = Math.max(...xArr);
1351
+ const maxY = Math.max(...yArr);
1352
+ this.box.set(minX, minY, maxX, maxY);
1353
+ return this.box;
1088
1354
  }
1089
1355
  /** 线路拓扑
1090
1356
  * @description 处理线路拓扑,使线路有序链接,形成长路径
1091
1357
  * @param lines
1092
1358
  */
1093
- lineTopology(t) {
1094
- const e = [];
1095
- function n(o, s) {
1096
- const [r, a] = t[o];
1097
- e[o] = !0, s.push(a);
1098
- for (let c = 0; c < t.length; c++) {
1099
- const [h, l] = t[c];
1100
- if (!e[c] && Math.abs(a.x - h.x) < 1e-6 && Math.abs(a.y - h.y) < 1e-6)
1101
- return n(c, s);
1359
+ lineTopology(lines) {
1360
+ const visited = [];
1361
+ function dfs(index2, linePath) {
1362
+ const [_0, a2] = lines[index2];
1363
+ visited[index2] = true;
1364
+ linePath.push(a2);
1365
+ for (let i = 0; i < lines.length; i++) {
1366
+ const [b1, _1] = lines[i];
1367
+ if (!visited[i]) {
1368
+ if (Math.abs(a2.x - b1.x) < 1e-6 && Math.abs(a2.y - b1.y) < 1e-6) {
1369
+ return dfs(i, linePath);
1370
+ }
1371
+ }
1102
1372
  }
1103
1373
  }
1104
- const i = [];
1105
- for (let o = 0; o < t.length; o++)
1106
- if (!e[o]) {
1107
- const s = [t[o][0]];
1108
- n(o, s), i.push(s);
1374
+ const linePaths = [];
1375
+ for (let i = 0; i < lines.length; i++) {
1376
+ if (!visited[i]) {
1377
+ const linePath = [lines[i][0]];
1378
+ dfs(i, linePath);
1379
+ linePaths.push(linePath);
1109
1380
  }
1110
- return i;
1381
+ }
1382
+ return linePaths;
1111
1383
  }
1112
1384
  /** 合并方向相同的线段
1113
1385
  * @param lines
1114
1386
  * @param errAngle
1115
1387
  */
1116
- mergeSameDirectionLine(t, e = 3) {
1117
- if (t[0].includedAngle(t[t.length - 1]) < 0.1) {
1118
- const i = t.pop();
1119
- i.end.copy(t[0].end), t.splice(0, 1, i);
1388
+ mergeSameDirectionLine(lines, errAngle = 3) {
1389
+ if (lines[0].includedAngle(lines[lines.length - 1]) < 0.1) {
1390
+ const line = lines.pop();
1391
+ line.end.copy(lines[0].end);
1392
+ lines.splice(0, 1, line);
1120
1393
  }
1121
- const n = [t[0]];
1122
- for (let i = 1; i < t.length; i++) {
1123
- const o = t[i], s = t[i - 1];
1124
- s.includedAngle(o) < e ? s.end.copy(o.end) : n.push(o);
1394
+ const filterLines = [lines[0]];
1395
+ for (let i = 1; i < lines.length; i++) {
1396
+ const line = lines[i];
1397
+ const preLine = lines[i - 1];
1398
+ if (preLine.includedAngle(line) < errAngle) {
1399
+ preLine.end.copy(line.end);
1400
+ } else {
1401
+ filterLines.push(line);
1402
+ }
1125
1403
  }
1126
- return n;
1404
+ return filterLines;
1127
1405
  }
1128
1406
  /** etOpenRound 去除毛刺
1129
1407
  * @description 检查连续的短线段数量,去除合并后产生的毛刺
1130
1408
  */
1131
- squareRemoveBurr(t) {
1132
- if (t.length < 3) return t;
1133
- const e = [t[0]];
1134
- for (let n = 1; n < t.length; n++) {
1135
- const i = t[n - 1], o = t[n];
1136
- if (i.distance(o) < this.width * 0.5) {
1137
- let r = 0;
1138
- for (let a = n + 1; a < t.length; a++) {
1139
- const c = t[a - 1], h = t[a];
1140
- if (c.distance(h) < this.width * 0.8) r++;
1409
+ squareRemoveBurr(path) {
1410
+ if (path.length < 3) return path;
1411
+ const filterLines = [path[0]];
1412
+ for (let i = 1; i < path.length; i++) {
1413
+ const prev = path[i - 1];
1414
+ const curr = path[i];
1415
+ const len = prev.distance(curr);
1416
+ if (len < this.width * 0.5) {
1417
+ let count = 0;
1418
+ for (let j = i + 1; j < path.length; j++) {
1419
+ const prev2 = path[j - 1];
1420
+ const curr2 = path[j];
1421
+ const len2 = prev2.distance(curr2);
1422
+ if (len2 < this.width * 0.8) count++;
1141
1423
  else break;
1142
1424
  }
1143
- 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(o));
1144
- } else
1145
- e.push(o);
1425
+ if (count === 0 && i + count === path.length - 1) ;
1426
+ else if (i == 1 && count === 1) ;
1427
+ else if (count === 3) {
1428
+ filterLines.push(path[i + 1]);
1429
+ i += count;
1430
+ } else if (count === 5) {
1431
+ filterLines.push(path[i + 2]);
1432
+ i += count;
1433
+ } else {
1434
+ filterLines.push(curr);
1435
+ }
1436
+ } else {
1437
+ filterLines.push(curr);
1438
+ }
1146
1439
  }
1147
- return e;
1440
+ return filterLines;
1148
1441
  }
1149
1442
  /**
1150
1443
  * 线段矫直, 线段中心突刺
1151
1444
  * @description 突变长度小于墙体宽度,该线段可能为突起线段,
1152
1445
  * @description 判断后续第2线段与上一条线段是否方向相同,相同就为突刺
1153
1446
  */
1154
- lineSegmentStraightening(t) {
1155
- for (let i = 0; i < t.length; i++) {
1156
- const o = t[i], s = t[(i + 1) % t.length];
1157
- if (o.distance(s) > this.shortLine) {
1158
- t.push(...t.slice(0, i + 1)), t.splice(0, i + 1);
1447
+ lineSegmentStraightening(path) {
1448
+ for (let i = 0; i < path.length; i++) {
1449
+ const p1 = path[i];
1450
+ const p2 = path[(i + 1) % path.length];
1451
+ if (p1.distance(p2) > this.shortLine) {
1452
+ path.push(...path.slice(0, i + 1));
1453
+ path.splice(0, i + 1);
1159
1454
  break;
1160
1455
  }
1161
1456
  }
1162
- const e = this.mergeSameDirectionLine(F(t)), n = [e[0]];
1163
- for (let i = 1; i < e.length; i++) {
1164
- const o = e[i], s = e[(e.length + i - 1) % e.length];
1165
- if (o.length() > this.width * 0.9) {
1166
- n.push(o);
1457
+ const lines = this.mergeSameDirectionLine(pathToLines(path)), filterLines = [lines[0]];
1458
+ for (let i = 1; i < lines.length; i++) {
1459
+ const line = lines[i];
1460
+ const preLine = lines[(lines.length + i - 1) % lines.length];
1461
+ if (line.length() > this.width * 0.9) {
1462
+ filterLines.push(line);
1167
1463
  continue;
1168
1464
  }
1169
- const r = e[i + 1];
1170
- if (r && r.length() > this.width * 0.9) {
1171
- n.push(o), n.push(r), i = i + 1;
1465
+ const line1 = lines[i + 1];
1466
+ if (line1 && line1.length() > this.width * 0.9) {
1467
+ filterLines.push(line);
1468
+ filterLines.push(line1);
1469
+ i = i + 1;
1172
1470
  continue;
1173
1471
  }
1174
- const a = e[i + 2];
1175
- a && s.includedAngle(a) < 2 ? (i = i + 2, n.push(a)) : n.push(o);
1472
+ const line2 = lines[i + 2];
1473
+ if (line2 && preLine.includedAngle(line2) < 2) {
1474
+ i = i + 2;
1475
+ filterLines.push(line2);
1476
+ } else filterLines.push(line);
1176
1477
  }
1177
- return n.length > 3 ? z(this.mergeSameDirectionLine(n)) : [];
1478
+ return filterLines.length > 3 ? linesToPath(this.mergeSameDirectionLine(filterLines)) : [];
1178
1479
  }
1179
1480
  /**
1180
1481
  * 移除短线段
1181
1482
  * @todo 根据线段两端线段长度,选取参照物_|▔▔
1182
1483
  * @param path
1183
1484
  */
1184
- removeShortLine(t, e = this.shortLine) {
1185
- const n = F(t), i = [], o = Math.PI / 180;
1186
- for (let s = 0; s < n.length; s++) {
1187
- const r = n[s], a = r.length(), c = s;
1188
- if (a > e || i.length === 0) {
1189
- i.push(r);
1485
+ removeShortLine(path, shortLine = this.shortLine) {
1486
+ const lines = pathToLines(path), filterLines = [], PI_1 = Math.PI / 180;
1487
+ for (let i = 0; i < lines.length; i++) {
1488
+ const line = lines[i], len = line.length(), currentIndex = i;
1489
+ if (len > shortLine || filterLines.length === 0) {
1490
+ filterLines.push(line);
1190
1491
  continue;
1191
1492
  }
1192
- let h = n[++s];
1193
- const l = i[i.length - 1], d = l.direction();
1194
- for (; s < n.length; ) {
1195
- const p = d.angleBetween(h.direction()) / o;
1196
- if (h.length() <= e || p < 4 || p > 176)
1197
- h = n[++s];
1198
- else break;
1493
+ let nextline = lines[++i];
1494
+ const preLine = filterLines[filterLines.length - 1], d1 = preLine.direction();
1495
+ while (i < lines.length) {
1496
+ const angle = d1.angleBetween(nextline.direction()) / PI_1;
1497
+ if (nextline.length() <= shortLine || angle < 4 || angle > 180 - 4) {
1498
+ nextline = lines[++i];
1499
+ } else break;
1199
1500
  }
1200
- if (!h) continue;
1201
- const x = n[s - 1];
1202
- if (l.length() > x.length()) {
1203
- const p = l.getIntersection(h);
1204
- if (p) {
1205
- const w = l.points[1].clone(), u = h.points[0].clone();
1206
- l.points[1].copy(p), h.points[0].copy(p), l.length() < this.width ? (l.points[1].copy(w), h.points[0].copy(w)) : h.length() < this.width && (l.points[1].copy(u), h.points[0].copy(u));
1207
- } else
1208
- l.points[1].copy(h.points[0]);
1209
- i.push(h);
1210
- } else
1211
- s = c;
1212
- }
1213
- return i.length > 3 ? z(i) : [];
1501
+ if (!nextline) continue;
1502
+ const targetLine = lines[i - 1];
1503
+ if (preLine.length() > targetLine.length()) {
1504
+ const intersectPoint = preLine.getIntersection(nextline);
1505
+ if (intersectPoint) {
1506
+ const p0 = preLine.points[1].clone(), p1 = nextline.points[0].clone();
1507
+ preLine.points[1].copy(intersectPoint);
1508
+ nextline.points[0].copy(intersectPoint);
1509
+ if (preLine.length() < this.width) {
1510
+ preLine.points[1].copy(p0);
1511
+ nextline.points[0].copy(p0);
1512
+ } else if (nextline.length() < this.width) {
1513
+ preLine.points[1].copy(p1);
1514
+ nextline.points[0].copy(p1);
1515
+ }
1516
+ } else {
1517
+ preLine.points[1].copy(nextline.points[0]);
1518
+ }
1519
+ filterLines.push(nextline);
1520
+ } else {
1521
+ i = currentIndex;
1522
+ }
1523
+ }
1524
+ return filterLines.length > 3 ? linesToPath(filterLines) : [];
1214
1525
  }
1215
1526
  /** 线偏移
1216
1527
  * @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
1217
1528
  */
1218
- lineOffset(t = I.EndType.etOpenSquare, e = I.JoinType.jtMiter, n = 1e4) {
1219
- let i = new V.Paths();
1220
- const o = new V.ClipperOffset(20, 0.25);
1221
- return this.pointsGroups.forEach((s) => {
1222
- const r = this.lineTopology(s).map((a) => a.map((c) => c.clone().mutiplyScalar(n)));
1223
- o.AddPaths(r, e, t);
1224
- }), o.Execute(i, this.width / 2 * n), this.wallsGroup = i.map((s) => {
1225
- let r = s.map((a) => f.from(a).divisionScalar(n));
1226
- return r = this.lineSegmentStraightening(r), t == I.EndType.etOpenSquare && (r = this.squareRemoveBurr(r)), r = this.removeShortLine(r), r;
1227
- }), this.dispatchEvent({
1529
+ lineOffset(endType = Dxf.EndType.etOpenSquare, joinType = Dxf.JoinType.jtMiter, scale = 1e4) {
1530
+ let solutions = new ClipperLib.Paths();
1531
+ const offset = new ClipperLib.ClipperOffset(20, 0.25);
1532
+ this.pointsGroups.forEach((points) => {
1533
+ const linePaths = this.lineTopology(points).map((linePath) => linePath.map((p) => p.clone().mutiplyScalar(scale)));
1534
+ offset.AddPaths(linePaths, joinType, endType);
1535
+ });
1536
+ offset.Execute(solutions, this.width / 2 * scale);
1537
+ this.wallsGroup = solutions.map((ps) => {
1538
+ let path = ps.map((p) => Point.from(p).divisionScalar(scale));
1539
+ path = this.lineSegmentStraightening(path);
1540
+ if (endType == Dxf.EndType.etOpenSquare) path = this.squareRemoveBurr(path);
1541
+ path = this.removeShortLine(path);
1542
+ return path;
1543
+ });
1544
+ this.dispatchEvent({
1228
1545
  type: "lineOffset",
1229
1546
  wallsGroup: this.wallsGroup
1230
- }), this.wallsGroup;
1547
+ });
1548
+ return this.wallsGroup;
1231
1549
  }
1232
1550
  /**
1233
1551
  * 将点云结构转换为Float32Array
1234
1552
  */
1235
- to3DArray(t, e = this.originalZAverage) {
1236
- const n = [];
1237
- return this.wallsGroup.forEach((i) => {
1238
- for (let o = 0; o < i.length; o++) {
1239
- const s = i[o], r = o === i.length - 1 ? 0 : o + 1, a = i[r];
1240
- n.push(s.X * t, s.Y * t, e, a.X * t, a.Y * t, e);
1553
+ to3DArray(scale, z = this.originalZAverage) {
1554
+ const array = [];
1555
+ this.wallsGroup.forEach((points) => {
1556
+ for (let i = 0; i < points.length; i++) {
1557
+ const point1 = points[i];
1558
+ const nextIndex = i === points.length - 1 ? 0 : i + 1;
1559
+ const point2 = points[nextIndex];
1560
+ array.push(point1.X * scale, point1.Y * scale, z, point2.X * scale, point2.Y * scale, z);
1241
1561
  }
1242
- }), new Float32Array(n);
1562
+ });
1563
+ return new Float32Array(array);
1243
1564
  }
1244
1565
  /** 获取角度范围
1245
1566
  * @param center
@@ -1247,140 +1568,196 @@ class I extends X {
1247
1568
  * @param p2
1248
1569
  * @returns
1249
1570
  */
1250
- getArcAngleRange(t, e, n) {
1251
- const i = e.x - t.x, o = e.y - t.y, s = n.x - t.x, r = n.y - t.y;
1252
- let a = Math.atan2(o, i), c = Math.atan2(r, s);
1253
- a = a < 0 ? a + 2 * Math.PI : a, c = c < 0 ? c + 2 * Math.PI : c;
1254
- let h, l;
1255
- return Math.abs(c - a) <= Math.PI ? (h = Math.min(a, c), l = Math.max(a, c)) : (h = Math.max(a, c), l = Math.min(a, c) + 2 * Math.PI), [h / (Math.PI / 180), l / (Math.PI / 180)];
1571
+ getArcAngleRange(center, p1, p2) {
1572
+ const x1 = p1.x - center.x;
1573
+ const y1 = p1.y - center.y;
1574
+ const x2 = p2.x - center.x;
1575
+ const y2 = p2.y - center.y;
1576
+ let angle1 = Math.atan2(y1, x1);
1577
+ let angle2 = Math.atan2(y2, x2);
1578
+ angle1 = angle1 < 0 ? angle1 + 2 * Math.PI : angle1;
1579
+ angle2 = angle2 < 0 ? angle2 + 2 * Math.PI : angle2;
1580
+ let r1, r2;
1581
+ const diff = Math.abs(angle2 - angle1);
1582
+ if (diff <= Math.PI) {
1583
+ r1 = Math.min(angle1, angle2);
1584
+ r2 = Math.max(angle1, angle2);
1585
+ } else {
1586
+ r1 = Math.max(angle1, angle2);
1587
+ r2 = Math.min(angle1, angle2) + 2 * Math.PI;
1588
+ }
1589
+ return [r1 / (Math.PI / 180), r2 / (Math.PI / 180)];
1256
1590
  }
1257
1591
  /**
1258
1592
  * 将点云结构转换为string
1259
1593
  */
1260
- toDxfString(t = "Millimeters") {
1261
- const e = new N();
1262
- e.setUnits("Millimeters");
1263
- const n = nt[t];
1264
- function i(r, a) {
1265
- e.drawLine(r.X * n, r.Y * n, a.X * n, a.Y * n);
1266
- }
1267
- this.wallsGroup.forEach((r) => {
1268
- for (let a = 0; a < r.length; a++) {
1269
- const c = r[a], h = a === r.length - 1 ? 0 : a + 1, l = r[h];
1270
- i(c, l);
1594
+ toDxfString(unit = "Millimeters") {
1595
+ const d = new Drawing();
1596
+ d.setUnits("Millimeters");
1597
+ const s = units[unit];
1598
+ function drawLine(p1, p2) {
1599
+ d.drawLine(p1.X * s, p1.Y * s, p2.X * s, p2.Y * s);
1600
+ }
1601
+ this.wallsGroup.forEach((points) => {
1602
+ for (let i = 0; i < points.length; i++) {
1603
+ const point1 = points[i];
1604
+ const nextIndex = i === points.length - 1 ? 0 : i + 1;
1605
+ const point2 = points[nextIndex];
1606
+ drawLine(point1, point2);
1271
1607
  }
1272
1608
  });
1273
- const o = this.width * 0.2, s = [];
1274
- return e.addLayer("l_cyan", N.ACI.CYAN, "DOTTED"), this.doorLineSegment.forEach((r) => {
1275
- if (r.length() < 0.4) return;
1276
- const a = r.clone().expansion(-this.width * 0.5);
1277
- if (e.setActiveLayer("l_cyan"), a.length() < 1.2) {
1278
- a.expansion(-o * 0.5);
1279
- const c = r.normal();
1280
- let h = new b(
1281
- a.start.clone(),
1282
- a.start.clone().add(c.clone().multiplyScalar(a.length()))
1609
+ const doorThickness = this.width * 0.2;
1610
+ const list = [];
1611
+ d.addLayer("l_cyan", Drawing.ACI.CYAN, "DOTTED");
1612
+ this.doorLineSegment.forEach((lineSegment) => {
1613
+ if (lineSegment.length() < 0.4) return;
1614
+ const line = lineSegment.clone().expansion(-this.width * 0.5);
1615
+ d.setActiveLayer("l_cyan");
1616
+ if (line.length() < 1.2) {
1617
+ line.expansion(-doorThickness * 0.5);
1618
+ const normal = lineSegment.normal();
1619
+ let door = new LineSegment(
1620
+ line.start.clone(),
1621
+ line.start.clone().add(normal.clone().multiplyScalar(line.length()))
1283
1622
  );
1284
- const l = h.clone().directionMove(h.normal(), a.length() * -0.5).expandToRectangle(a.length(), "bothSides");
1285
- for (let y = 0; y < s.length; y++)
1286
- if (s[y].intersectRectangle(l)) {
1287
- h = new b(
1288
- a.start.clone(),
1289
- a.start.clone().add(c.clone().multiplyScalar(-a.length()))
1623
+ const box = door.clone().directionMove(door.normal(), line.length() * -0.5).expandToRectangle(line.length(), "bothSides");
1624
+ for (let j = 0; j < list.length; j++) {
1625
+ if (list[j].intersectRectangle(box)) {
1626
+ door = new LineSegment(
1627
+ line.start.clone(),
1628
+ line.start.clone().add(normal.clone().multiplyScalar(-line.length()))
1290
1629
  );
1291
1630
  break;
1292
1631
  }
1293
- h.expansion(-o * 0.5).expandToRectangle(this.width * 0.2, "bothSides").path2D((y, S) => i(y, S));
1294
- const d = a.length(), x = h.length(), p = (d ** 2 + x ** 2) / (2 * x), w = h.end.clone().add(h.direction().multiplyScalar(-p)), [u, m] = this.getArcAngleRange(w, a.end, h.end);
1295
- e.drawArc(w.x * n, w.y * n, p * n, Math.min(u, m), Math.max(u, m)), s.push(l);
1296
- } else
1297
- a.clone().expansion(-this.width * 0.5).expandToRectangle(this.width).path2D((c, h) => i(c, h)), a.clone().directionMove(a.normal(), o * 0.5).directionMove(a.direction(), o * 0.5).expansion(-a.length() * 0.45, "end").forward(o * 0.5).expandToRectangle(o).path2D((c, h) => i(c, h)), a.clone().directionMove(a.normal(), -o * 0.5).directionMove(a.direction(), -o * 0.5).expansion(-a.length() * 0.45, "start").forward(-o * 0.5).expandToRectangle(o).path2D((c, h) => i(c, h));
1298
- }), e.addLayer("l_yellow", N.ACI.YELLOW, "DOTTED"), e.setActiveLayer("l_yellow"), this.lineSegments.forEach((r) => {
1299
- if (!r.userData.isWindow) return !1;
1300
- Array.isArray(r.userData.drawDoorData) && r.userData.drawDoorData.forEach((a) => {
1301
- const { p: c, width: h } = a, l = f.from(c), d = l.clone().add(r.direction().multiplyScalar(h * 0.5)), x = l.clone().add(r.direction().multiplyScalar(-h * 0.5)), p = new b(d, x);
1302
- i(p.start, p.end), p.expandToRectangle(this.width, "bothSides").path2D((w, u) => i(w, u));
1303
- });
1304
- }), e.toDxfString();
1632
+ }
1633
+ door.expansion(-doorThickness * 0.5).expandToRectangle(this.width * 0.2, "bothSides").path2D((p1, p2) => drawLine(p1, p2));
1634
+ const a = line.length(), b = door.length(), r = (a ** 2 + b ** 2) / (2 * b), center = door.end.clone().add(door.direction().multiplyScalar(-r)), [startAngle, endAngle] = this.getArcAngleRange(center, line.end, door.end);
1635
+ d.drawArc(center.x * s, center.y * s, r * s, Math.min(startAngle, endAngle), Math.max(startAngle, endAngle));
1636
+ list.push(box);
1637
+ } else {
1638
+ line.clone().expansion(-this.width * 0.5).expandToRectangle(this.width).path2D((p1, p2) => drawLine(p1, p2));
1639
+ line.clone().directionMove(line.normal(), doorThickness * 0.5).directionMove(line.direction(), doorThickness * 0.5).expansion(-line.length() * 0.45, "end").forward(doorThickness * 0.5).expandToRectangle(doorThickness).path2D((p1, p2) => drawLine(p1, p2));
1640
+ line.clone().directionMove(line.normal(), -doorThickness * 0.5).directionMove(line.direction(), -doorThickness * 0.5).expansion(-line.length() * 0.45, "start").forward(-doorThickness * 0.5).expandToRectangle(doorThickness).path2D((p1, p2) => drawLine(p1, p2));
1641
+ }
1642
+ });
1643
+ d.addLayer("l_yellow", Drawing.ACI.YELLOW, "DOTTED");
1644
+ d.setActiveLayer("l_yellow");
1645
+ this.lineSegments.forEach((line) => {
1646
+ if (!line.userData.isWindow) return false;
1647
+ if (Array.isArray(line.userData.drawDoorData)) {
1648
+ line.userData.drawDoorData.forEach((w) => {
1649
+ const { p, width } = w;
1650
+ const center = Point.from(p);
1651
+ const start = center.clone().add(line.direction().multiplyScalar(width * 0.5));
1652
+ const end = center.clone().add(line.direction().multiplyScalar(-width * 0.5));
1653
+ const blinds = new LineSegment(start, end);
1654
+ drawLine(blinds.start, blinds.end);
1655
+ blinds.expandToRectangle(this.width, "bothSides").path2D((p1, p2) => drawLine(p1, p2));
1656
+ });
1657
+ }
1658
+ });
1659
+ return d.toDxfString();
1305
1660
  }
1306
1661
  /**
1307
1662
  * 将点云结构转换为DXF格式
1308
1663
  * @returns
1309
1664
  */
1310
- toDxfBlob(t = "Millimeters") {
1311
- return new Blob([this.toDxfString(t)]);
1665
+ toDxfBlob(unit = "Millimeters") {
1666
+ const blob = new Blob([this.toDxfString(unit)]);
1667
+ return blob;
1312
1668
  }
1313
1669
  /**
1314
1670
  * 下载
1315
1671
  * @param filename
1316
1672
  */
1317
- async download(t, e = "Millimeters") {
1318
- if (typeof window < "u") {
1319
- const n = this.toDxfBlob(e), i = document.createElement("a");
1320
- i.href = URL.createObjectURL(n), i.download = t + ".dxf", i.click();
1321
- } else typeof global < "u" && (await q("fs", !1)).writeFileSync(t, this.toDxfString(e));
1673
+ async download(filename, unit = "Millimeters") {
1674
+ if (typeof window !== "undefined") {
1675
+ const blob = this.toDxfBlob(unit);
1676
+ const a = document.createElement("a");
1677
+ a.href = URL.createObjectURL(blob);
1678
+ a.download = filename + ".dxf";
1679
+ a.click();
1680
+ } else if (typeof global !== "undefined") {
1681
+ const fs = await include("fs", false);
1682
+ fs.writeFileSync(filename, this.toDxfString(unit));
1683
+ }
1322
1684
  }
1323
1685
  /**
1324
1686
  * 计算原始数据的边界框
1325
1687
  * @description 计算所有线段的起点和终点的最小最大值,形成一个边界框
1326
1688
  * @returns
1327
1689
  */
1328
- computedOriginalSize(t, e = new A(0, 0, 0, 0)) {
1329
- const n = t.flatMap((c) => [c.start.x, c.end.x]), i = t.flatMap((c) => [c.start.y, c.end.y]), o = Math.min(...n), s = Math.min(...i), r = Math.max(...n), a = Math.max(...i);
1330
- return e.set(o, s, r, a), e;
1690
+ computedOriginalSize(data, originalBox = new Box2(0, 0, 0, 0)) {
1691
+ const xArr = data.flatMap((item) => [item.start.x, item.end.x]);
1692
+ const yArr = data.flatMap((item) => [item.start.y, item.end.y]);
1693
+ const minX = Math.min(...xArr);
1694
+ const minY = Math.min(...yArr);
1695
+ const maxX = Math.max(...xArr);
1696
+ const maxY = Math.max(...yArr);
1697
+ originalBox.set(minX, minY, maxX, maxY);
1698
+ return originalBox;
1331
1699
  }
1332
1700
  /**
1333
1701
  * 创建数据
1334
1702
  * @param pointsGroups
1335
1703
  * @returns
1336
1704
  */
1337
- static createData(t, e = !0) {
1338
- let n = 0;
1339
- return t.flatMap((o) => {
1340
- const s = o.map((r, a) => {
1341
- const c = a === o.length - 1 ? 0 : a + 1, h = o[c];
1705
+ static createData(pointsGroups, sealed = true) {
1706
+ let count = 0;
1707
+ const data = pointsGroups.flatMap((points) => {
1708
+ const lines = points.map((point, index2) => {
1709
+ const nextIndex = index2 === points.length - 1 ? 0 : index2 + 1;
1710
+ const nextPoint = points[nextIndex];
1342
1711
  return {
1343
- start: { x: r.x, y: r.y },
1344
- end: { x: h.x, y: h.y },
1712
+ start: { x: point.x, y: point.y },
1713
+ end: { x: nextPoint.x, y: nextPoint.y },
1345
1714
  insetionArr: [
1346
1715
  {
1347
- index: c + n
1716
+ index: nextIndex + count
1348
1717
  }
1349
1718
  ]
1350
1719
  };
1351
1720
  });
1352
- return n += o.length, e || (s.pop(), s[s.length - 1].insetionArr.length = 0, n--), s;
1721
+ count += points.length;
1722
+ if (!sealed) {
1723
+ lines.pop();
1724
+ lines[lines.length - 1].insetionArr.length = 0;
1725
+ count--;
1726
+ }
1727
+ return lines;
1353
1728
  });
1729
+ return data;
1354
1730
  }
1355
1731
  }
1356
- class k extends X {
1732
+ class Variable extends Component {
1357
1733
  static name = "Variable";
1358
- originalLineVisible = !0;
1359
- dxfVisible = !0;
1360
- whiteModelVisible = !0;
1361
- isLook = !1;
1734
+ originalLineVisible = true;
1735
+ dxfVisible = true;
1736
+ whiteModelVisible = true;
1737
+ isLook = false;
1362
1738
  currentWheel = 0;
1363
1739
  pointerMove = { x: 0, y: 0 };
1364
1740
  currentKeyUp = "";
1365
1741
  currentKeyDown = "";
1366
1742
  currentMouseUp = "";
1367
1743
  currentMouseDown = "";
1368
- focus = !1;
1369
- set(t, e) {
1370
- if (t in this) {
1371
- const n = this[t];
1372
- this[t] = e, this.dispatchEvent({
1373
- type: t,
1374
- value: e,
1375
- oldValue: n
1744
+ focus = false;
1745
+ set(key, value) {
1746
+ if (key in this) {
1747
+ const oldValue = this[key];
1748
+ this[key] = value;
1749
+ this.dispatchEvent({
1750
+ type: key,
1751
+ value,
1752
+ oldValue
1376
1753
  });
1377
1754
  }
1378
1755
  }
1379
- get(t) {
1380
- if (t in this) return this[t];
1756
+ get(key) {
1757
+ if (key in this) return this[key];
1381
1758
  }
1382
1759
  }
1383
- class B {
1760
+ class Quadtree {
1384
1761
  bounds;
1385
1762
  // 包围盒
1386
1763
  capacity;
@@ -1389,7 +1766,7 @@ class B {
1389
1766
  // 最大深度
1390
1767
  depth;
1391
1768
  // 当前深度
1392
- isLeaf = !0;
1769
+ isLeaf = true;
1393
1770
  // 是否为叶子节点
1394
1771
  children = null;
1395
1772
  // 子节点数组
@@ -1397,72 +1774,110 @@ class B {
1397
1774
  // 存储的节点
1398
1775
  color = [Math.random(), Math.random(), Math.random()];
1399
1776
  // 颜色
1400
- constructor(t, e = 8, n = 10, i = 1) {
1401
- this.bounds = t, this.capacity = e, this.depth = i, this.maxDepth = n;
1777
+ constructor(bounds, capacity = 8, maxDepth = 10, depth = 1) {
1778
+ this.bounds = bounds;
1779
+ this.capacity = capacity;
1780
+ this.depth = depth;
1781
+ this.maxDepth = maxDepth;
1402
1782
  }
1403
1783
  /**
1404
1784
  * 插入线段节点
1405
1785
  * @param node 线段节点
1406
1786
  */
1407
- insert(t) {
1787
+ insert(node) {
1408
1788
  if (!this.isLeaf) {
1409
- const e = this.getQuadrant(t.line);
1410
- if (e !== -1) {
1411
- this.children[e].insert(t);
1789
+ const quadrant = this.getQuadrant(node.line);
1790
+ if (quadrant !== -1) {
1791
+ this.children[quadrant].insert(node);
1412
1792
  return;
1413
1793
  }
1414
1794
  }
1415
- if (this.nodes.push(t), t.parent = this, this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
1795
+ this.nodes.push(node);
1796
+ node.parent = this;
1797
+ if (this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
1416
1798
  this.subdivide();
1417
- const e = this.nodes;
1799
+ const nodes = this.nodes;
1418
1800
  this.nodes = [];
1419
- for (const n of e) {
1420
- const i = this.getQuadrant(n.line);
1421
- i !== -1 ? this.children[i].insert(n) : (n.parent = this, this.nodes.push(n));
1801
+ for (const n of nodes) {
1802
+ const quadrant = this.getQuadrant(n.line);
1803
+ if (quadrant !== -1) {
1804
+ this.children[quadrant].insert(n);
1805
+ } else {
1806
+ n.parent = this;
1807
+ this.nodes.push(n);
1808
+ }
1422
1809
  }
1423
1810
  }
1424
1811
  }
1425
1812
  /** 移除
1426
1813
  * @param node
1427
1814
  */
1428
- remove(t) {
1429
- const e = t.parent?.nodes.indexOf(t);
1430
- e > -1 && t.parent?.nodes.splice(e, 1);
1815
+ remove(node) {
1816
+ const index2 = node.parent?.nodes.indexOf(node);
1817
+ if (index2 > -1) {
1818
+ node.parent?.nodes.splice(index2, 1);
1819
+ }
1431
1820
  }
1432
1821
  /**
1433
1822
  * 获取线段所属的象限
1434
1823
  * @param line 线段
1435
1824
  * @returns 象限索引(0:西北,1:东北,2:西南,3:东南)或-1(跨多个象限)
1436
1825
  */
1437
- getQuadrant(t) {
1438
- const e = this.children[0].bounds.intersectLineSegment(t), n = this.children[1].bounds.intersectLineSegment(t), i = this.children[2].bounds.intersectLineSegment(t), o = this.children[3].bounds.intersectLineSegment(t);
1439
- let s = 0, r = -1;
1440
- return e && (s++, r = 0), n && (s++, r = 1), i && (s++, r = 2), o && (s++, r = 3), s === 1 ? r : -1;
1826
+ getQuadrant(line) {
1827
+ const intersectsNW = this.children[0].bounds.intersectLineSegment(line);
1828
+ const intersectsNE = this.children[1].bounds.intersectLineSegment(line);
1829
+ const intersectsSW = this.children[2].bounds.intersectLineSegment(line);
1830
+ const intersectsSE = this.children[3].bounds.intersectLineSegment(line);
1831
+ let count = 0;
1832
+ let quadrant = -1;
1833
+ if (intersectsNW) {
1834
+ count++;
1835
+ quadrant = 0;
1836
+ }
1837
+ if (intersectsNE) {
1838
+ count++;
1839
+ quadrant = 1;
1840
+ }
1841
+ if (intersectsSW) {
1842
+ count++;
1843
+ quadrant = 2;
1844
+ }
1845
+ if (intersectsSE) {
1846
+ count++;
1847
+ quadrant = 3;
1848
+ }
1849
+ if (count === 1) return quadrant;
1850
+ return -1;
1441
1851
  }
1442
1852
  /**
1443
1853
  * 细分当前节点为四个子节点
1444
1854
  */
1445
1855
  subdivide() {
1446
1856
  if (!this.isLeaf) return;
1447
- this.isLeaf = !1, this.children = [];
1448
- const t = (this.bounds.minX + this.bounds.maxX) / 2, e = (this.bounds.minY + this.bounds.maxY) / 2;
1449
- this.children[0] = new B(
1450
- new A(this.bounds.minX, t, this.bounds.minY, e),
1857
+ this.isLeaf = false;
1858
+ this.children = [];
1859
+ const midX = (this.bounds.minX + this.bounds.maxX) / 2;
1860
+ const midY = (this.bounds.minY + this.bounds.maxY) / 2;
1861
+ this.children[0] = new Quadtree(
1862
+ new Box2(this.bounds.minX, midX, this.bounds.minY, midY),
1451
1863
  this.capacity,
1452
1864
  this.maxDepth,
1453
1865
  this.depth + 1
1454
- ), this.children[1] = new B(
1455
- new A(t, this.bounds.maxX, this.bounds.minY, e),
1866
+ );
1867
+ this.children[1] = new Quadtree(
1868
+ new Box2(midX, this.bounds.maxX, this.bounds.minY, midY),
1456
1869
  this.capacity,
1457
1870
  this.maxDepth,
1458
1871
  this.depth + 1
1459
- ), this.children[2] = new B(
1460
- new A(this.bounds.minX, t, e, this.bounds.maxY),
1872
+ );
1873
+ this.children[2] = new Quadtree(
1874
+ new Box2(this.bounds.minX, midX, midY, this.bounds.maxY),
1461
1875
  this.capacity,
1462
1876
  this.maxDepth,
1463
1877
  this.depth + 1
1464
- ), this.children[3] = new B(
1465
- new A(t, this.bounds.maxX, e, this.bounds.maxY),
1878
+ );
1879
+ this.children[3] = new Quadtree(
1880
+ new Box2(midX, this.bounds.maxX, midY, this.bounds.maxY),
1466
1881
  this.capacity,
1467
1882
  this.maxDepth,
1468
1883
  this.depth + 1
@@ -1473,16 +1888,22 @@ class B {
1473
1888
  * @param box2 包围盒
1474
1889
  * @returns 相交的节点数组
1475
1890
  */
1476
- queryBox(t) {
1477
- const e = [];
1478
- if (!this.bounds.intersectBox(t))
1479
- return e;
1480
- for (const n of this.nodes)
1481
- t.intersectLineSegment(n.line) && e.push(n);
1482
- if (!this.isLeaf)
1483
- for (const n of this.children)
1484
- e.push(...n.queryBox(t));
1485
- return e;
1891
+ queryBox(box2) {
1892
+ const result = [];
1893
+ if (!this.bounds.intersectBox(box2)) {
1894
+ return result;
1895
+ }
1896
+ for (const node of this.nodes) {
1897
+ if (box2.intersectLineSegment(node.line)) {
1898
+ result.push(node);
1899
+ }
1900
+ }
1901
+ if (!this.isLeaf) {
1902
+ for (const child of this.children) {
1903
+ result.push(...child.queryBox(box2));
1904
+ }
1905
+ }
1906
+ return result;
1486
1907
  }
1487
1908
  /**
1488
1909
  * 查询与圆形区域相交的线段节点
@@ -1490,58 +1911,81 @@ class B {
1490
1911
  * @param radius 半径
1491
1912
  * @returns 相交的节点数组
1492
1913
  */
1493
- queryCircle(t, e) {
1494
- const n = [], i = new A(
1495
- t.x - e,
1496
- t.x + e,
1497
- t.y - e,
1498
- t.y + e
1914
+ queryCircle(pos, radius) {
1915
+ const result = [];
1916
+ const circleBox = new Box2(
1917
+ pos.x - radius,
1918
+ pos.x + radius,
1919
+ pos.y - radius,
1920
+ pos.y + radius
1499
1921
  );
1500
- if (!this.bounds.intersectBox(i))
1501
- return n;
1502
- for (const o of this.nodes) {
1503
- const [s, r] = o.line.points, a = r.x - s.x, c = r.y - s.y, h = a * a + c * c;
1504
- let l = ((t.x - s.x) * a + (t.y - s.y) * c) / h;
1505
- l = Math.max(0, Math.min(1, l));
1506
- const d = s.x + l * a, x = s.y + l * c;
1507
- t.distance(new f(d, x)) <= e && n.push(o);
1922
+ if (!this.bounds.intersectBox(circleBox)) {
1923
+ return result;
1924
+ }
1925
+ for (const node of this.nodes) {
1926
+ const [p1, p2] = node.line.points;
1927
+ const dx = p2.x - p1.x;
1928
+ const dy = p2.y - p1.y;
1929
+ const l2 = dx * dx + dy * dy;
1930
+ let t = ((pos.x - p1.x) * dx + (pos.y - p1.y) * dy) / l2;
1931
+ t = Math.max(0, Math.min(1, t));
1932
+ const closestX = p1.x + t * dx;
1933
+ const closestY = p1.y + t * dy;
1934
+ const distance = pos.distance(new Point(closestX, closestY));
1935
+ if (distance <= radius) {
1936
+ result.push(node);
1937
+ }
1938
+ }
1939
+ if (!this.isLeaf) {
1940
+ for (const child of this.children) {
1941
+ result.push(...child.queryCircle(pos, radius));
1942
+ }
1508
1943
  }
1509
- if (!this.isLeaf)
1510
- for (const o of this.children)
1511
- n.push(...o.queryCircle(t, e));
1512
- return n;
1944
+ return result;
1513
1945
  }
1514
1946
  /**
1515
1947
  * 查询与矩形相交的线段节点
1516
1948
  * @param rectangle 矩形
1517
1949
  * @returns 相交的节点数组
1518
1950
  */
1519
- queryRect(t) {
1520
- const e = [];
1521
- if (!this.bounds.intersectRectangle(t))
1522
- return e;
1523
- for (const n of this.nodes)
1524
- t.intersectLineSegment(n.line) && e.push(n);
1525
- if (!this.isLeaf)
1526
- for (const n of this.children)
1527
- e.push(...n.queryRect(t));
1528
- return e;
1951
+ queryRect(rectangle) {
1952
+ const result = [];
1953
+ if (!this.bounds.intersectRectangle(rectangle)) {
1954
+ return result;
1955
+ }
1956
+ for (const node of this.nodes) {
1957
+ if (rectangle.intersectLineSegment(node.line)) {
1958
+ result.push(node);
1959
+ }
1960
+ }
1961
+ if (!this.isLeaf) {
1962
+ for (const child of this.children) {
1963
+ result.push(...child.queryRect(rectangle));
1964
+ }
1965
+ }
1966
+ return result;
1529
1967
  }
1530
1968
  /**
1531
1969
  * 查询与线段相交的线段节点
1532
1970
  * @param lineSegment 线段
1533
1971
  * @returns 相交的节点数组
1534
1972
  */
1535
- queryLineSegment(t) {
1536
- const e = [];
1537
- if (!this.bounds.intersectLineSegment(t))
1538
- return e;
1539
- for (const n of this.nodes)
1540
- t.intersectLineSegment(n.line) && e.push(n);
1541
- if (!this.isLeaf)
1542
- for (const n of this.children)
1543
- e.push(...n.queryLineSegment(t));
1544
- return e;
1973
+ queryLineSegment(lineSegment) {
1974
+ const result = [];
1975
+ if (!this.bounds.intersectLineSegment(lineSegment)) {
1976
+ return result;
1977
+ }
1978
+ for (const node of this.nodes) {
1979
+ if (lineSegment.intersectLineSegment(node.line)) {
1980
+ result.push(node);
1981
+ }
1982
+ }
1983
+ if (!this.isLeaf) {
1984
+ for (const child of this.children) {
1985
+ result.push(...child.queryLineSegment(lineSegment));
1986
+ }
1987
+ }
1988
+ return result;
1545
1989
  }
1546
1990
  /**
1547
1991
  * 包围盒转换为数组
@@ -1549,80 +1993,96 @@ class B {
1549
1993
  * @param colors
1550
1994
  * @returns
1551
1995
  */
1552
- boundsToArray(t = [], e, n = !0) {
1553
- return !this.isLeaf && n && this.children?.forEach((i) => i.boundsToArray(t, e)), t.push(...this.bounds.points.flatMap((i, o, s) => {
1554
- const r = s[(o + 1) % s.length];
1555
- return e?.push(...this.color), e?.push(...this.color), [i.x, i.y, 0, r.x, r.y, 0];
1556
- })), t;
1996
+ boundsToArray(array = [], colors, recursion = true) {
1997
+ if (!this.isLeaf && recursion) {
1998
+ this.children?.forEach((child) => child.boundsToArray(array, colors));
1999
+ }
2000
+ array.push(...this.bounds.points.flatMap((p, i, array2) => {
2001
+ const np = array2[(i + 1) % array2.length];
2002
+ colors?.push(...this.color);
2003
+ colors?.push(...this.color);
2004
+ return [p.x, p.y, 0, np.x, np.y, 0];
2005
+ }));
2006
+ return array;
1557
2007
  }
1558
2008
  }
1559
- class U {
2009
+ class PointVirtualGrid {
1560
2010
  map = /* @__PURE__ */ new Map();
1561
2011
  gridSize;
1562
- constructor(t = 2) {
1563
- this.gridSize = t;
2012
+ constructor(gridSize = 2) {
2013
+ this.gridSize = gridSize;
1564
2014
  }
1565
2015
  /**
1566
2016
  * 插入
1567
2017
  * @param point
1568
2018
  * @param userData
1569
2019
  */
1570
- insert(t, e) {
1571
- if (!t || isNaN(t.x) || isNaN(t.y))
2020
+ insert(point, userData) {
2021
+ if (!point || isNaN(point.x) || isNaN(point.y)) {
1572
2022
  throw new Error("无效的点坐标");
1573
- const n = this.getGridId(t);
1574
- this.map.has(n) || this.map.set(n, /* @__PURE__ */ new Set());
1575
- const i = this.map.get(n), o = { point: t, userData: e };
1576
- i.add(o), t.userData.pointVirtualGrid = { set: i, target: o };
2023
+ }
2024
+ const id = this.getGridId(point);
2025
+ if (!this.map.has(id)) this.map.set(id, /* @__PURE__ */ new Set());
2026
+ const set = this.map.get(id);
2027
+ const target = { point, userData };
2028
+ set.add(target);
2029
+ point.userData.pointVirtualGrid = { set, target };
1577
2030
  }
1578
2031
  /**
1579
2032
  * 批量加入
1580
2033
  * @param points
1581
2034
  */
1582
- insertBatch(t) {
1583
- for (const { point: e, userData: n } of t)
1584
- this.insert(e, n);
2035
+ insertBatch(points) {
2036
+ for (const { point, userData } of points) {
2037
+ this.insert(point, userData);
2038
+ }
1585
2039
  }
1586
2040
  /** 移除点
1587
2041
  * @param point
1588
2042
  */
1589
- remove(t) {
1590
- const { set: e, target: n } = t?.userData?.pointVirtualGrid;
1591
- e && (e.delete(n), delete t?.userData?.pointVirtualGridMap);
2043
+ remove(point) {
2044
+ const { set, target } = point?.userData?.pointVirtualGrid;
2045
+ if (set) {
2046
+ set.delete(target);
2047
+ delete point?.userData?.pointVirtualGridMap;
2048
+ }
1592
2049
  }
1593
2050
  /**
1594
2051
  * 获取通过坐标,获取唯一网格索引
1595
2052
  * @param point
1596
2053
  * @returns
1597
2054
  */
1598
- getGridId(t) {
1599
- const e = Math.ceil(t.x / this.gridSize), n = Math.ceil(t.y / this.gridSize);
1600
- return `${e}.${n}`;
2055
+ getGridId(point) {
2056
+ const i = Math.ceil(point.x / this.gridSize), j = Math.ceil(point.y / this.gridSize);
2057
+ return `${i}.${j}`;
1601
2058
  }
1602
2059
  /**
1603
2060
  *
1604
2061
  * @param gridId
1605
2062
  * @returns
1606
2063
  */
1607
- decodeGridId(t) {
1608
- const [e, n] = t.split(".").map(Number);
1609
- return new f(e, n);
2064
+ decodeGridId(gridId) {
2065
+ const [i, j] = gridId.split(".").map(Number);
2066
+ return new Point(i, j);
1610
2067
  }
1611
2068
  /**
1612
2069
  * 查询与矩形相交的点
1613
2070
  * @param rectangle 矩形
1614
2071
  * @returns 相交的节点数组
1615
2072
  */
1616
- queryRect(t) {
1617
- const e = t.toBox(), n = Math.ceil(e.minX / this.gridSize), i = Math.ceil(e.maxX / this.gridSize), o = Math.ceil(e.minY / this.gridSize), s = Math.ceil(e.maxY / this.gridSize);
1618
- for (let r = n; r <= i; r++)
1619
- for (let a = o; a <= s; a++) {
1620
- const c = `${r}.${a}`;
1621
- if (!this.map.has(c)) continue;
1622
- this.map.get(c)?.forEach((l) => {
1623
- t.containsPoint(l.point);
2073
+ queryRect(rectangle) {
2074
+ const box2 = rectangle.toBox();
2075
+ const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize);
2076
+ for (let i = minI; i <= maxI; i++) {
2077
+ for (let j = minJ; j <= maxJ; j++) {
2078
+ const id = `${i}.${j}`;
2079
+ if (!this.map.has(id)) continue;
2080
+ const set = this.map.get(id);
2081
+ set?.forEach((item) => {
2082
+ if (rectangle.containsPoint(item.point)) ;
1624
2083
  });
1625
2084
  }
2085
+ }
1626
2086
  }
1627
2087
  /**
1628
2088
  * 查询与圆形区域相交的点
@@ -1630,53 +2090,62 @@ class U {
1630
2090
  * @param radius 半径
1631
2091
  * @returns 相交的节点数组
1632
2092
  */
1633
- queryCircle(t, e) {
1634
- const n = new A(t.x - e, t.x + e, t.y - e, t.y + e), i = Math.ceil(n.minX / this.gridSize), o = Math.ceil(n.maxX / this.gridSize), s = Math.ceil(n.minY / this.gridSize), r = Math.ceil(n.maxY / this.gridSize), a = [];
1635
- for (let c = i; c <= o; c++)
1636
- for (let h = s; h <= r; h++) {
1637
- const l = `${c}.${h}`;
1638
- if (!this.map.has(l)) continue;
1639
- this.map.get(l)?.forEach((x) => {
1640
- t.distance(x.point) <= e && a.push(x);
2093
+ queryCircle(pos, radius) {
2094
+ const box2 = new Box2(pos.x - radius, pos.x + radius, pos.y - radius, pos.y + radius);
2095
+ const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize), list = [];
2096
+ for (let i = minI; i <= maxI; i++) {
2097
+ for (let j = minJ; j <= maxJ; j++) {
2098
+ const id = `${i}.${j}`;
2099
+ if (!this.map.has(id)) continue;
2100
+ const set = this.map.get(id);
2101
+ set?.forEach((item) => {
2102
+ if (pos.distance(item.point) <= radius) list.push(item);
1641
2103
  });
1642
2104
  }
1643
- return a;
2105
+ }
2106
+ return list;
1644
2107
  }
1645
2108
  /**
1646
2109
  * 查询与包围盒相交的点
1647
2110
  * @param box2 包围盒
1648
2111
  * @returns 相交的节点数组
1649
2112
  */
1650
- queryBox(t) {
1651
- const e = Math.ceil(t.minX / this.gridSize), n = Math.ceil(t.maxX / this.gridSize), i = Math.ceil(t.minY / this.gridSize), o = Math.ceil(t.maxY / this.gridSize), s = [];
1652
- for (let r = e; r <= n; r++)
1653
- for (let a = i; a <= o; a++) {
1654
- const c = `${r}.${a}`;
1655
- if (!this.map.has(c)) continue;
1656
- this.map.get(c)?.forEach((l) => {
1657
- t.containsPoint(l.point) && s.push(l);
2113
+ queryBox(box2) {
2114
+ const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize), list = [];
2115
+ for (let i = minI; i <= maxI; i++) {
2116
+ for (let j = minJ; j <= maxJ; j++) {
2117
+ const id = `${i}.${j}`;
2118
+ if (!this.map.has(id)) continue;
2119
+ const set = this.map.get(id);
2120
+ set?.forEach((item) => {
2121
+ if (box2.containsPoint(item.point)) list.push(item);
1658
2122
  });
1659
2123
  }
1660
- return s;
2124
+ }
2125
+ return list;
1661
2126
  }
1662
2127
  /**
1663
2128
  * 查找相同点
1664
2129
  * @param point
1665
2130
  */
1666
- queryPoint(t) {
1667
- const e = this.getGridId(t), n = [];
1668
- return this.map.has(e) && this.map.get(e)?.forEach((o) => {
1669
- t.equal(o.point) && n.push(o);
1670
- }), n;
2131
+ queryPoint(point) {
2132
+ const id = this.getGridId(point), list = [];
2133
+ if (this.map.has(id)) {
2134
+ const set = this.map.get(id);
2135
+ set?.forEach((item) => {
2136
+ if (point.equal(item.point)) list.push(item);
2137
+ });
2138
+ }
2139
+ return list;
1671
2140
  }
1672
2141
  }
1673
- class it {
2142
+ class DoorsAnalysis {
1674
2143
  // 所有可查找的点位
1675
2144
  possibleDoorPoints = [];
1676
2145
  doorPoint = [];
1677
2146
  dxf;
1678
2147
  // 包含所有点的虚拟网格
1679
- pointVirtualGrid = new U();
2148
+ pointVirtualGrid = new PointVirtualGrid();
1680
2149
  // 只包含可查找点的虚拟网格
1681
2150
  findPointVirtualGrid;
1682
2151
  quadtree;
@@ -1687,111 +2156,158 @@ class it {
1687
2156
  doorSearchDistance = 2;
1688
2157
  doors = [];
1689
2158
  lineAnalysis;
1690
- continueFind = !0;
1691
- constructor(t) {
1692
- if (this.lineAnalysis = t, this.dxf = t.Dxf, this.findPointVirtualGrid = new U(), this.quadtree = t.quadtree, this.resultList = t.resultList, this.lineSegments = t.lineSegmentList, this.dxf.doorLineSegment.length = 0, this.lineSegments.forEach((n) => {
1693
- this.pointVirtualGrid.insert(n.start, n), this.pointVirtualGrid.insert(n.end, n);
1694
- }), this.doorPoint = this.getDoorPoint(), !this.continueFind) return;
1695
- const e = this.searchDoubleLinePoint();
1696
- this.addPointsExcludeRule((n, i, o) => {
1697
- const s = this.lineSegments.indexOf(n), r = e.get(s);
1698
- return typeof r == "number" ? r === -1 || r === o : !1;
1699
- }), this.addPointsExcludeRule((n, i) => !!this.doorPoint.find((o) => o.point.equal(i))), this.possibleDoorPoints = this.getPossiblePoints(), this.possibleDoorPoints.forEach((n) => this.findPointVirtualGrid.insert(n.point, n.line)), this.handle();
2159
+ continueFind = true;
2160
+ constructor(lineAnalysis) {
2161
+ this.lineAnalysis = lineAnalysis;
2162
+ this.dxf = lineAnalysis.Dxf;
2163
+ this.findPointVirtualGrid = new PointVirtualGrid();
2164
+ this.quadtree = lineAnalysis.quadtree;
2165
+ this.resultList = lineAnalysis.resultList;
2166
+ this.lineSegments = lineAnalysis.lineSegmentList;
2167
+ this.dxf.doorLineSegment.length = 0;
2168
+ this.lineSegments.forEach((line) => {
2169
+ this.pointVirtualGrid.insert(line.start, line);
2170
+ this.pointVirtualGrid.insert(line.end, line);
2171
+ });
2172
+ this.doorPoint = this.getDoorPoint();
2173
+ if (!this.continueFind) return;
2174
+ const excludeIndexMap = this.searchDoubleLinePoint();
2175
+ this.addPointsExcludeRule((line, _2, pointIndex) => {
2176
+ const index2 = this.lineSegments.indexOf(line);
2177
+ const excludeMode = excludeIndexMap.get(index2);
2178
+ if (typeof excludeMode === "number") {
2179
+ return excludeMode === -1 || excludeMode === pointIndex;
2180
+ }
2181
+ return false;
2182
+ });
2183
+ this.addPointsExcludeRule((_1, point) => {
2184
+ return !!this.doorPoint.find((p1) => p1.point.equal(point));
2185
+ });
2186
+ this.possibleDoorPoints = this.getPossiblePoints();
2187
+ this.possibleDoorPoints.forEach((p) => this.findPointVirtualGrid.insert(p.point, p.line));
2188
+ this.handle();
1700
2189
  }
1701
2190
  handle() {
1702
- this.dxf.doorLineSegment.push(...this.search(this.doorPoint, this.possibleDoorPoints, 0.5)), this.doorPoint.length < 2 && this.dxf.doorLineSegment.push(...this.search(this.possibleDoorPoints, this.possibleDoorPoints, 0.6));
1703
- }
1704
- search(t, e = [], n = 0.6, i = this.doorSearchDistance, o = this.doorSearchNearAngle) {
1705
- const s = this.dxf, r = this.searchNearby(t, e, i, o);
1706
- r.push(
1707
- ...t.map((c) => {
1708
- const h = this.searchAlongDirection(c, i);
1709
- if (h) return {
1710
- start: c.point,
1711
- end: h.point
2191
+ this.dxf.doorLineSegment.push(...this.search(this.doorPoint, this.possibleDoorPoints, 0.5));
2192
+ if (this.doorPoint.length < 2) this.dxf.doorLineSegment.push(...this.search(this.possibleDoorPoints, this.possibleDoorPoints, 0.6));
2193
+ }
2194
+ search(doorPoints, possibleDoorPoints = [], minDoorWidth = 0.6, doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
2195
+ const dxf = this.dxf;
2196
+ const doors = this.searchNearby(doorPoints, possibleDoorPoints, doorSearchDistance, doorSearchNearAngle);
2197
+ doors.push(
2198
+ ...doorPoints.map((item) => {
2199
+ const res2 = this.searchAlongDirection(item, doorSearchDistance);
2200
+ if (res2) return {
2201
+ start: item.point,
2202
+ end: res2.point
1712
2203
  };
1713
- const l = this.searchAlongNormalDirection(c, i);
1714
- if (l) return {
1715
- start: c.point,
1716
- end: l.point
2204
+ const res3 = this.searchAlongNormalDirection(item, doorSearchDistance);
2205
+ if (res3) return {
2206
+ start: item.point,
2207
+ end: res3.point
1717
2208
  };
1718
- }).filter((c) => !!c && c.start.distance(c.end) < i)
2209
+ }).filter((i) => !!i && i.start.distance(i.end) < doorSearchDistance)
1719
2210
  );
1720
- const a = [];
1721
- return r.forEach((c) => {
1722
- const h = new b(c?.start, c?.end), l = h.length();
1723
- if (l < n) return;
1724
- const d = h.normal(), x = h.direction(), p = (l - s.width * 2) / 2;
1725
- for (let w = 0; w < 3; w++) {
1726
- const u = h.start.clone().add(x.clone().multiplyScalar(s.width + p * w)), m = new b(
1727
- u,
1728
- u.clone().add(d.clone().multiplyScalar(1))
2211
+ const doorLineSegment = [];
2212
+ doors.forEach((p) => {
2213
+ const line = new LineSegment(p?.start, p?.end);
2214
+ const len = line.length();
2215
+ if (len < minDoorWidth) return;
2216
+ const normal = line.normal(), direction = line.direction(), step = (len - dxf.width * 2) / 2;
2217
+ for (let i = 0; i < 3; i++) {
2218
+ const point = line.start.clone().add(direction.clone().multiplyScalar(dxf.width + step * i));
2219
+ const rLine = new LineSegment(
2220
+ point,
2221
+ point.clone().add(normal.clone().multiplyScalar(1))
1729
2222
  );
1730
- if (m.directionMove(d, -0.5), this.quadtree.queryLineSegment(m).length) return;
2223
+ rLine.directionMove(normal, -0.5);
2224
+ const res = this.quadtree.queryLineSegment(rLine);
2225
+ if (res.length) return;
1731
2226
  }
1732
- a.push(h);
1733
- }), a;
2227
+ doorLineSegment.push(line);
2228
+ });
2229
+ return doorLineSegment;
1734
2230
  }
1735
2231
  /** 添加可查找点的过滤规则
1736
2232
  * @param rule
1737
2233
  */
1738
- addPointsExcludeRule(t) {
1739
- this._pointsExcludeRule.push(t);
2234
+ addPointsExcludeRule(rule) {
2235
+ this._pointsExcludeRule.push(rule);
1740
2236
  }
1741
2237
  _pointsExcludeRule = [];
1742
2238
  /**
1743
2239
  * 查找所有可能为门的点位
1744
2240
  */
1745
2241
  getPossiblePoints() {
1746
- const t = [];
1747
- return this.lineSegments.forEach((e) => {
1748
- e.points.forEach((n, i) => {
1749
- for (let s = 0; s < this._pointsExcludeRule.length; s++) if (this._pointsExcludeRule[s](e, n, i)) return;
1750
- this.pointVirtualGrid.queryPoint(n).filter((s) => s.userData !== e).length === 0 && t.push({ line: e, point: n, uuid: T() });
2242
+ const doorPoints = [];
2243
+ this.lineSegments.forEach((line) => {
2244
+ line.points.forEach((p, j) => {
2245
+ for (let i = 0; i < this._pointsExcludeRule.length; i++) if (this._pointsExcludeRule[i](line, p, j)) return;
2246
+ const res = this.pointVirtualGrid.queryPoint(p).filter((d) => d.userData !== line);
2247
+ if (res.length === 0) {
2248
+ doorPoints.push({ line, point: p, uuid: uuid() });
2249
+ }
1751
2250
  });
1752
- }), t;
2251
+ });
2252
+ return doorPoints;
1753
2253
  }
1754
2254
  /**
1755
2255
  * 查找已知为门的点位
1756
2256
  */
1757
2257
  getDoorPoint() {
1758
- const t = [], e = this.dxf, n = this.pointVirtualGrid;
1759
- return e.doors.forEach((i) => {
1760
- const o = e.lineSegments[i[4]], s = e.originalData[i[4]];
1761
- if (s.drawDoorData) {
1762
- const r = f.from(s.drawDoorData.start), a = f.from(s.drawDoorData.n), c = n.queryPoint(r).filter((h) => {
1763
- if (h.userData === o) return !1;
1764
- const l = h.userData, d = l.direction();
1765
- l.start.equal(r) && d.multiplyScalar(-1);
1766
- const x = a.angleBetween(d, "angle");
1767
- return x > 80 || x < 10;
2258
+ const doorPoints = [], dxf = this.dxf, pointVirtualGrid = this.pointVirtualGrid;
2259
+ dxf.doors.forEach((item) => {
2260
+ const doorLine = dxf.lineSegments[item[4]];
2261
+ const doorData = dxf.originalData[item[4]];
2262
+ if (doorData.drawDoorData) {
2263
+ const point = Point.from(doorData.drawDoorData.start);
2264
+ const direct = Point.from(doorData.drawDoorData.n);
2265
+ const resList = pointVirtualGrid.queryPoint(point).filter((res) => {
2266
+ if (res.userData === doorLine) return false;
2267
+ const line = res.userData;
2268
+ const direct2 = line.direction();
2269
+ if (line.start.equal(point)) direct2.multiplyScalar(-1);
2270
+ const angle = direct.angleBetween(direct2, "angle");
2271
+ return angle > 80 || angle < 10;
1768
2272
  });
1769
- c.length && t.push({
1770
- line: c[0].userData,
1771
- point: r,
1772
- uuid: T()
1773
- });
1774
- } else if (s.doorDirectConnection) {
1775
- this.continueFind = !1;
1776
- const r = new b(f.from(s.start), f.from(s.end));
1777
- r.userData = {
1778
- doorDirectConnection: !0,
1779
- isDoor: !0
1780
- }, this.dxf.doorLineSegment.push(r);
1781
- } else
1782
- console.warn(`门的线段顺序${i[4]} 没有drawDoorData属性`);
1783
- }), t;
2273
+ if (resList.length) {
2274
+ doorPoints.push({
2275
+ line: resList[0].userData,
2276
+ point,
2277
+ uuid: uuid()
2278
+ });
2279
+ }
2280
+ } else if (doorData.doorDirectConnection) {
2281
+ this.continueFind = false;
2282
+ const line = new LineSegment(Point.from(doorData.start), Point.from(doorData.end));
2283
+ line.userData = {
2284
+ doorDirectConnection: true,
2285
+ isDoor: true
2286
+ };
2287
+ this.dxf.doorLineSegment.push(line);
2288
+ } else {
2289
+ console.warn(`门的线段顺序${item[4]} 没有drawDoorData属性`);
2290
+ }
2291
+ });
2292
+ console.log("门点位数量:", doorPoints.length);
2293
+ return doorPoints;
1784
2294
  }
1785
2295
  /**
1786
2296
  * 查找双线墙的点位
1787
2297
  * @returns
1788
2298
  */
1789
2299
  searchDoubleLinePoint() {
1790
- const t = /* @__PURE__ */ new Map();
1791
- return this.resultList.flatMap((e) => {
1792
- const n = this.lineSegments[e.sourceIndex], i = this.lineSegments[e.targetIndex], o = i.projectPoint(n.start), s = i.projectPoint(n.end), r = n.projectPoint(i.start), a = n.projectPoint(i.end), c = o && s ? -1 : o ? 0 : s ? 1 : -1, h = r && a ? -1 : r ? 0 : a ? 1 : -1;
1793
- t.has(e.sourceIndex) ? t.get(e.sourceIndex) != c && t.set(e.sourceIndex, -1) : t.set(e.sourceIndex, c), t.has(e.targetIndex) ? t.get(e.targetIndex) != h && t.set(e.targetIndex, -1) : t.set(e.targetIndex, h);
1794
- }), t;
2300
+ const excludeIndexMap = /* @__PURE__ */ new Map();
2301
+ this.resultList.flatMap((p) => {
2302
+ const line0 = this.lineSegments[p.sourceIndex], line1 = this.lineSegments[p.targetIndex], start0 = line1.projectPoint(line0.start), end0 = line1.projectPoint(line0.end), start1 = line0.projectPoint(line1.start), end1 = line0.projectPoint(line1.end), mode0 = start0 && end0 ? -1 : start0 ? 0 : end0 ? 1 : -1, mode1 = start1 && end1 ? -1 : start1 ? 0 : end1 ? 1 : -1;
2303
+ if (excludeIndexMap.has(p.sourceIndex)) {
2304
+ if (excludeIndexMap.get(p.sourceIndex) != mode0) excludeIndexMap.set(p.sourceIndex, -1);
2305
+ } else excludeIndexMap.set(p.sourceIndex, mode0);
2306
+ if (excludeIndexMap.has(p.targetIndex)) {
2307
+ if (excludeIndexMap.get(p.targetIndex) != mode1) excludeIndexMap.set(p.targetIndex, -1);
2308
+ } else excludeIndexMap.set(p.targetIndex, mode1);
2309
+ });
2310
+ return excludeIndexMap;
1795
2311
  }
1796
2312
  /** 查找方案一:最近点查找
1797
2313
  * @description 以点为圆心,查找半径内符合角度的点
@@ -1801,113 +2317,160 @@ class it {
1801
2317
  * @param doorSearchNearAngle 查找的角度
1802
2318
  * @returns
1803
2319
  */
1804
- searchNearby(t, e = [], n = this.doorSearchDistance, i = this.doorSearchNearAngle) {
1805
- const o = this.findPointVirtualGrid, s = this.quadtree;
1806
- function r({ point: u, line: m }, y, S) {
1807
- const D = m.direction();
1808
- m.start === u && D.multiplyScalar(-1);
1809
- const P = o.queryCircle(u, n).filter((L) => L.userData !== m).sort((L, E) => L.point.distance(u) - E.point.distance(u)), v = [];
1810
- for (let L = 0; L < P.length; L++) {
1811
- const E = e.findIndex((R) => R.point === P[L].point), Y = t[y].uuid, G = e[E].uuid;
1812
- if (S.has(`${Y}.${G}`)) continue;
1813
- S.add(`${Y}.${G}`), S.add(`${G}.${Y}`);
1814
- const Z = P[L].point, j = new b(u.clone(), Z.clone());
1815
- if (j.direction().angleBetween(D, "angle") < i) {
1816
- const R = t[E].line.direction();
1817
- P[L].userData.start.equal(P[L].point) && R.multiplyScalar(-1), j.direction().multiplyScalar(-1).angleBetween(R, "angle") < i && (s.queryLineSegment(j).length || v.push({
1818
- findData: P[L],
1819
- findUuid: G,
1820
- doorLine: j,
1821
- doorUuid: Y
1822
- }));
2320
+ searchNearby(doorPoints, possibleDoorPoints = [], doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
2321
+ const findPointVirtualGrid = this.findPointVirtualGrid, quadtree = this.quadtree;
2322
+ function find({ point, line }, doorIndex, record2) {
2323
+ const direct = line.direction();
2324
+ if (line.start === point) direct.multiplyScalar(-1);
2325
+ const res = findPointVirtualGrid.queryCircle(point, doorSearchDistance).filter((r) => r.userData !== line).sort((a, b) => a.point.distance(point) - b.point.distance(point));
2326
+ const list = [];
2327
+ for (let i = 0; i < res.length; i++) {
2328
+ const doorIndex2 = possibleDoorPoints.findIndex((p) => p.point === res[i].point);
2329
+ const id1 = doorPoints[doorIndex].uuid, id2 = possibleDoorPoints[doorIndex2].uuid;
2330
+ if (record2.has(`${id1}.${id2}`)) continue;
2331
+ record2.add(`${id1}.${id2}`);
2332
+ record2.add(`${id2}.${id1}`);
2333
+ const targetPoint = res[i].point, line2 = new LineSegment(point.clone(), targetPoint.clone()), angle = line2.direction().angleBetween(direct, "angle");
2334
+ if (angle < doorSearchNearAngle) {
2335
+ const direct2 = doorPoints[doorIndex2].line.direction();
2336
+ const line22 = res[i].userData;
2337
+ if (line22.start.equal(res[i].point)) direct2.multiplyScalar(-1);
2338
+ const angle2 = line2.direction().multiplyScalar(-1).angleBetween(direct2, "angle");
2339
+ if (angle2 < doorSearchNearAngle) {
2340
+ if (!quadtree.queryLineSegment(line2).length) {
2341
+ list.push({
2342
+ findData: res[i],
2343
+ findUuid: id2,
2344
+ doorLine: line2,
2345
+ doorUuid: id1
2346
+ });
2347
+ }
2348
+ }
1823
2349
  }
1824
2350
  }
1825
- return v;
1826
- }
1827
- function a(u, m, y, S, D) {
1828
- S.add(u);
1829
- const P = [];
1830
- D && P.push(D);
1831
- for (let v = 0; v < y.length; v++) {
1832
- const L = y[v];
1833
- if (m.has(L.findUuid)) {
1834
- const E = m.get(L.findUuid);
1835
- a(L.findUuid, m, E, S, L) && P.push(L);
1836
- } else P.push(L);
2351
+ return list;
2352
+ }
2353
+ function deepSearchNearHandle(uuid2, snFindRecord2, list, record2, other) {
2354
+ record2.add(uuid2);
2355
+ const newList = [];
2356
+ if (other) newList.push(other);
2357
+ for (let i = 0; i < list.length; i++) {
2358
+ const item = list[i];
2359
+ if (snFindRecord2.has(item.findUuid)) {
2360
+ const list2 = snFindRecord2.get(item.findUuid);
2361
+ if (deepSearchNearHandle(item.findUuid, snFindRecord2, list2, record2, item)) newList.push(item);
2362
+ } else newList.push(item);
2363
+ }
2364
+ newList.sort((a, b) => a.doorLine.length() - b.doorLine.length());
2365
+ if (other && newList[0] === other) {
2366
+ list.splice(0);
2367
+ return true;
1837
2368
  }
1838
- return P.sort((v, L) => v.doorLine.length() - L.doorLine.length()), D && P[0] === D ? (y.splice(0), !0) : (y.splice(1), !1);
1839
- }
1840
- const c = /* @__PURE__ */ new Set(), h = /* @__PURE__ */ new Map();
1841
- t.map((u, m) => {
1842
- const y = r(u, m, c);
1843
- y.length && h.set(u.uuid, y);
1844
- }), c.clear();
1845
- const l = /* @__PURE__ */ new Map();
1846
- h.forEach((u, m) => {
1847
- if (!c.has(m) && u.length && a(m, h, u, c), u.length) {
1848
- const y = u[0];
1849
- l.has(y.doorUuid) || l.set(y.doorUuid, []), l.get(y.doorUuid)?.push(y), l.has(y.findUuid) || l.set(y.findUuid, []), l.get(y.findUuid)?.push(y);
2369
+ list.splice(1);
2370
+ return false;
2371
+ }
2372
+ const record = /* @__PURE__ */ new Set();
2373
+ const snFindRecord = /* @__PURE__ */ new Map();
2374
+ doorPoints.map((p, index2) => {
2375
+ const list = find(p, index2, record);
2376
+ if (list.length) snFindRecord.set(p.uuid, list);
2377
+ });
2378
+ record.clear();
2379
+ const temMap = /* @__PURE__ */ new Map();
2380
+ snFindRecord.forEach((list, key) => {
2381
+ if (!record.has(key) && list.length) {
2382
+ deepSearchNearHandle(key, snFindRecord, list, record);
2383
+ }
2384
+ if (list.length) {
2385
+ const item = list[0];
2386
+ if (!temMap.has(item.doorUuid)) temMap.set(item.doorUuid, []);
2387
+ temMap.get(item.doorUuid)?.push(item);
2388
+ if (!temMap.has(item.findUuid)) temMap.set(item.findUuid, []);
2389
+ temMap.get(item.findUuid)?.push(item);
1850
2390
  }
1851
2391
  });
1852
- const d = /* @__PURE__ */ new Set();
1853
- l.forEach((u) => {
1854
- if (u.length > 1) {
1855
- u.sort((m, y) => m.doorLine.length() - y.doorLine.length());
1856
- for (let m = 1; m < u.length; m++) d.add(u[m]);
2392
+ const deleteSet = /* @__PURE__ */ new Set();
2393
+ temMap.forEach((list) => {
2394
+ if (list.length > 1) {
2395
+ list.sort((a, b) => a.doorLine.length() - b.doorLine.length());
2396
+ for (let i = 1; i < list.length; i++) deleteSet.add(list[i]);
1857
2397
  }
1858
2398
  });
1859
- const x = [], p = [];
1860
- h.forEach((u) => {
1861
- if (u.length) {
1862
- const m = u[0];
1863
- d.has(m) || (x.push(m), p.push(m.doorUuid, m.findUuid));
2399
+ const searchNearRasult = [], removeDoorPointsUuid = [];
2400
+ snFindRecord.forEach((list) => {
2401
+ if (list.length) {
2402
+ const item = list[0];
2403
+ if (!deleteSet.has(item)) {
2404
+ searchNearRasult.push(item);
2405
+ removeDoorPointsUuid.push(item.doorUuid, item.findUuid);
2406
+ }
1864
2407
  }
1865
2408
  });
1866
- const w = [];
1867
- return x.forEach((u) => {
1868
- const m = t.findIndex((E) => E.uuid === u.doorUuid), y = e.findIndex((E) => E.uuid === u.findUuid), S = t[m].point.clone(), D = e[y].point.clone(), P = this.findLongLineSegment(t[m].line), v = this.findLongLineSegment(e[y].line), L = P.projectPoint(D);
1869
- if (L) {
1870
- S.copy(L);
1871
- const E = new b(S, D), Y = v.includedAngle(E);
1872
- (Y < 10 || Y > 170 || Math.abs(90 - Y) < 10) && w.push({
1873
- start: S,
1874
- end: D
1875
- });
2409
+ const doors = [];
2410
+ searchNearRasult.forEach((item) => {
2411
+ const doorIndex = doorPoints.findIndex((p2) => p2.uuid === item.doorUuid);
2412
+ const findDoorIndex = possibleDoorPoints.findIndex((p2) => p2.uuid === item.findUuid);
2413
+ const start = doorPoints[doorIndex].point.clone();
2414
+ const end = possibleDoorPoints[findDoorIndex].point.clone();
2415
+ const startLine = this.findLongLineSegment(doorPoints[doorIndex].line);
2416
+ const endLine = this.findLongLineSegment(possibleDoorPoints[findDoorIndex].line);
2417
+ const p = startLine.projectPoint(end);
2418
+ if (p) {
2419
+ start.copy(p);
2420
+ const l = new LineSegment(start, end);
2421
+ const angle = endLine.includedAngle(l);
2422
+ if (angle < 10 || angle > 170 || Math.abs(90 - angle) < 10) {
2423
+ doors.push({
2424
+ start,
2425
+ end
2426
+ });
2427
+ }
1876
2428
  } else {
1877
- const E = v.projectPoint(S);
1878
- E && D.copy(E);
1879
- const Y = new b(S, D), G = P.includedAngle(Y);
1880
- (G < 10 || G > 170 || Math.abs(90 - G) < 10) && w.push({
1881
- start: S,
1882
- end: D
1883
- });
2429
+ const p2 = endLine.projectPoint(start);
2430
+ if (p2) end.copy(p2);
2431
+ const l = new LineSegment(start, end);
2432
+ const angle = startLine.includedAngle(l);
2433
+ if (angle < 10 || angle > 170 || Math.abs(90 - angle) < 10) {
2434
+ doors.push({
2435
+ start,
2436
+ end
2437
+ });
2438
+ }
1884
2439
  }
1885
- }), e.splice(
2440
+ });
2441
+ possibleDoorPoints.splice(
1886
2442
  0,
1887
- e.length,
1888
- ...e.filter((u) => p.indexOf(u.uuid) === -1)
1889
- ), t.splice(
2443
+ possibleDoorPoints.length,
2444
+ ...possibleDoorPoints.filter((p) => removeDoorPointsUuid.indexOf(p.uuid) === -1)
2445
+ );
2446
+ doorPoints.splice(
1890
2447
  0,
1891
- t.length,
1892
- ...t.filter((u) => p.indexOf(u.uuid) === -1)
1893
- ), w;
2448
+ doorPoints.length,
2449
+ ...doorPoints.filter((p) => removeDoorPointsUuid.indexOf(p.uuid) === -1)
2450
+ );
2451
+ return doors;
1894
2452
  }
1895
2453
  /** 方案二: 沿方向查找
1896
2454
  * @description
1897
2455
  * @param param0
1898
2456
  * @returns
1899
2457
  */
1900
- searchAlongDirection({ point: t, line: e }, n = this.doorSearchDistance) {
1901
- const i = this.quadtree, o = e.direction();
1902
- e.start === t && o.multiplyScalar(-1);
1903
- const s = t.clone().add(o.clone().multiplyScalar(n)), r = new b(t.clone(), s), a = i.queryLineSegment(r).map((c) => ({
1904
- point: c.line.getIntersection(r),
1905
- line: c.line
1906
- })).filter((c) => c.point).sort((c, h) => t.distance(c.point) - t.distance(h.point));
1907
- if (a.length) {
1908
- const c = a[0];
1909
- if (Math.abs(90 - c.line.direction().angleBetween(o, "angle")) < 5)
1910
- return c;
2458
+ searchAlongDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
2459
+ const quadtree = this.quadtree;
2460
+ const direct = line.direction();
2461
+ if (line.start === point) direct.multiplyScalar(-1);
2462
+ const endPoint = point.clone().add(direct.clone().multiplyScalar(doorSearchDistance)), rline = new LineSegment(point.clone(), endPoint), result = quadtree.queryLineSegment(rline).map((l) => {
2463
+ const res = l.line.getIntersection(rline);
2464
+ return {
2465
+ point: res,
2466
+ line: l.line
2467
+ };
2468
+ }).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
2469
+ if (result.length) {
2470
+ const item = result[0];
2471
+ if (Math.abs(90 - item.line.direction().angleBetween(direct, "angle")) < 5) {
2472
+ return item;
2473
+ }
1911
2474
  }
1912
2475
  }
1913
2476
  /** 方案三: 沿法线方向查找
@@ -1916,25 +2479,35 @@ class it {
1916
2479
  * @param doorSearchDistance
1917
2480
  * @returns
1918
2481
  */
1919
- searchAlongNormalDirection({ point: t, line: e }, n = this.doorSearchDistance) {
1920
- const i = this.pointVirtualGrid, o = this.quadtree, s = e.direction(), r = e.start.normal(e.end), a = e.start.clone();
1921
- e.start === t && s.multiplyScalar(-1), e.start === t && a.copy(e.end);
1922
- const c = i.queryPoint(a).filter((d) => d.userData !== e);
1923
- for (let d = 0; d < c.length; d++) {
1924
- const x = c[d], p = x.userData, w = p.direction();
1925
- if (p.start === x.point && s.multiplyScalar(-1), w.angleBetween(r) / (Math.PI / 180) > 90) {
1926
- r.multiplyScalar(-1);
2482
+ searchAlongNormalDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
2483
+ const pointVirtualGrid = this.pointVirtualGrid, quadtree = this.quadtree, direct = line.direction(), normal = line.start.normal(line.end), prePoint = line.start.clone();
2484
+ if (line.start === point) direct.multiplyScalar(-1);
2485
+ if (line.start === point) prePoint.copy(line.end);
2486
+ const result = pointVirtualGrid.queryPoint(prePoint).filter((r) => r.userData !== line);
2487
+ for (let i = 0; i < result.length; i++) {
2488
+ const element = result[i];
2489
+ const l = element.userData;
2490
+ const d1 = l.direction();
2491
+ if (l.start === element.point) direct.multiplyScalar(-1);
2492
+ const angle = d1.angleBetween(normal) / (Math.PI / 180);
2493
+ if (angle > 90) {
2494
+ normal.multiplyScalar(-1);
1927
2495
  break;
1928
2496
  }
1929
2497
  }
1930
- const h = new b(t.clone(), t.clone().add(r.multiplyScalar(n))), l = o.queryLineSegment(h).map((d) => ({
1931
- point: d.line.getIntersection(h),
1932
- line: d.line
1933
- })).filter((d) => d.point).sort((d, x) => t.distance(d.point) - t.distance(x.point));
1934
- if (l.length) {
1935
- const d = l[0];
1936
- if (Math.abs(90 - d.line.direction().angleBetween(r, "angle")) < 5)
1937
- return d;
2498
+ const rline3 = new LineSegment(point.clone(), point.clone().add(normal.multiplyScalar(doorSearchDistance)));
2499
+ const r3 = quadtree.queryLineSegment(rline3).map((l) => {
2500
+ const res = l.line.getIntersection(rline3);
2501
+ return {
2502
+ point: res,
2503
+ line: l.line
2504
+ };
2505
+ }).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
2506
+ if (r3.length) {
2507
+ const item = r3[0];
2508
+ if (Math.abs(90 - item.line.direction().angleBetween(normal, "angle")) < 5) {
2509
+ return item;
2510
+ }
1938
2511
  }
1939
2512
  }
1940
2513
  /**
@@ -1942,31 +2515,37 @@ class it {
1942
2515
  * @param line
1943
2516
  * @returns
1944
2517
  */
1945
- findLongLineSegment(t) {
1946
- const e = t.clone(), n = this.pointVirtualGrid.queryPoint(t.start), i = this.pointVirtualGrid.queryPoint(t.end);
1947
- for (let o = 0; o < n.length; o++) {
1948
- const { userData: s } = n[o];
1949
- if (s !== t && s && s.directionEqual(t)) {
1950
- s.start.equal(t.start) ? e.start.copy(s.end) : e.start.copy(s.start);
2518
+ findLongLineSegment(line) {
2519
+ const resLine = line.clone();
2520
+ const res1 = this.pointVirtualGrid.queryPoint(line.start);
2521
+ const res2 = this.pointVirtualGrid.queryPoint(line.end);
2522
+ for (let i = 0; i < res1.length; i++) {
2523
+ const { userData: line2 } = res1[i];
2524
+ if (line2 === line) continue;
2525
+ if (line2 && line2.directionEqual(line)) {
2526
+ if (line2.start.equal(line.start)) resLine.start.copy(line2.end);
2527
+ else resLine.start.copy(line2.start);
1951
2528
  break;
1952
2529
  }
1953
2530
  }
1954
- for (let o = 0; o < i.length; o++) {
1955
- const { userData: s } = i[o];
1956
- if (s !== t && s && s.directionEqual(t)) {
1957
- s.end.equal(t.end) ? e.end.copy(s.start) : e.end.copy(s.end);
2531
+ for (let i = 0; i < res2.length; i++) {
2532
+ const { userData: line2 } = res2[i];
2533
+ if (line2 === line) continue;
2534
+ if (line2 && line2.directionEqual(line)) {
2535
+ if (line2.end.equal(line.end)) resLine.end.copy(line2.start);
2536
+ else resLine.end.copy(line2.end);
1958
2537
  break;
1959
2538
  }
1960
2539
  }
1961
- return e;
2540
+ return resLine;
1962
2541
  }
1963
2542
  }
1964
- class st extends X {
2543
+ class LineAnalysis extends Component {
1965
2544
  static name = "LineAnalysis";
1966
2545
  Dxf = null;
1967
2546
  Variable = null;
1968
2547
  lineSegmentList = [];
1969
- container = new M.Group();
2548
+ container = new THREE.Group();
1970
2549
  // 误差角度
1971
2550
  errorAngle = 4;
1972
2551
  width = 0.4;
@@ -1974,8 +2553,11 @@ class st extends X {
1974
2553
  *
1975
2554
  * @param parent
1976
2555
  */
1977
- onAddFromParent(t) {
1978
- this.Dxf = t.findComponentByType(I), this.Variable = this.parent?.findComponentByType(k), this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this)), this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
2556
+ onAddFromParent(parent) {
2557
+ this.Dxf = parent.findComponentByType(Dxf);
2558
+ this.Variable = this.parent?.findComponentByType(Variable);
2559
+ this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this));
2560
+ this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
1979
2561
  }
1980
2562
  /**
1981
2563
  *
@@ -1984,16 +2566,20 @@ class st extends X {
1984
2566
  * @param width
1985
2567
  * @returns
1986
2568
  */
1987
- expandLineSegment(t, e, n = 0.1) {
1988
- const i = e.normal(t), o = e.direction(t).mutiplyScalar(n * 0.5), s = t.direction(e).mutiplyScalar(n * 0.5), r = i.x * n * 0.5, a = i.y * n * 0.5;
2569
+ expandLineSegment(p1, p2, width = 0.1) {
2570
+ const normal = p2.normal(p1);
2571
+ const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
2572
+ const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
2573
+ const offsetX = normal.x * width * 0.5;
2574
+ const offsetY = normal.y * width * 0.5;
1989
2575
  return {
1990
2576
  points: [
1991
2577
  // 第一条线
1992
- new f(t.x + r, t.y + a).add(s),
1993
- new f(e.x + r, e.y + a).add(o),
2578
+ new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
2579
+ new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
1994
2580
  // 第二条线
1995
- new f(t.x - r, t.y - a).add(s),
1996
- new f(e.x - r, e.y - a).add(o)
2581
+ new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
2582
+ new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
1997
2583
  ],
1998
2584
  indices: [0, 1, 1, 3, 3, 2, 2, 0],
1999
2585
  rectIndices: [0, 1, 3, 2, 0]
@@ -2005,25 +2591,31 @@ class st extends X {
2005
2591
  * @param p1
2006
2592
  * @param p2
2007
2593
  */
2008
- addData(t, e) {
2009
- const n = this.Dxf;
2010
- n.data.push([t.clone(), e.clone(), [], !1, n.data.length]), this.appendLineSegmentList.push(new b(t.clone(), e.clone()));
2594
+ addData(p1, p2) {
2595
+ const dxf = this.Dxf;
2596
+ dxf.data.push([p1.clone(), p2.clone(), [], false, dxf.data.length]);
2597
+ this.appendLineSegmentList.push(new LineSegment(p1.clone(), p2.clone()));
2011
2598
  }
2012
2599
  /** 结果分析创建矩形
2013
2600
  * @param result
2014
2601
  */
2015
- createRectangle(t) {
2016
- const e = this.Dxf, n = t.project, i = t.project2;
2017
- 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]);
2018
- const o = n.points[0].distance(i.points[0]), s = n.points[1].distance(i.points[1]), r = Math.ceil(Math.max(o, s) / e.width), a = o / r, c = s / r, h = i.points[0].direction(n.points[0]), l = i.points[1].direction(n.points[1]), d = n.points[0].clone(), x = n.points[1].clone(), p = x.direction(d);
2019
- p.multiplyScalar(e.width * 0.5);
2020
- const w = d.clone().add(p), u = x.clone().add(p.multiplyScalar(-1)), m = d.direction(x), y = w.direction(u);
2021
- if (!(m.x > 0 && y.x < 0 || m.x < 0 && y.x > 0 || m.y > 0 && y.y < 0 || m.y < 0 && y.y > 0)) {
2022
- d.set(w.x, w.y), x.set(u.x, u.y);
2023
- for (let S = 1; S < r; S++) {
2024
- const D = h.clone().multiplyScalar(a * S), P = l.clone().multiplyScalar(c * S), v = d.clone().add(D), L = x.clone().add(P);
2025
- this.addData(v, L);
2026
- }
2602
+ createRectangle(result) {
2603
+ const dxf = this.Dxf;
2604
+ const project0 = result.project, project1 = result.project2;
2605
+ if (project0.includedAngle(project1) > 135) {
2606
+ project1.points = [project1.points[1], project1.points[0]];
2607
+ }
2608
+ this.addData(project0.points[0], project1.points[0]);
2609
+ this.addData(project0.points[1], project1.points[1]);
2610
+ const leftHeight = project0.points[0].distance(project1.points[0]), rightHeight = project0.points[1].distance(project1.points[1]), count = Math.ceil(Math.max(leftHeight, rightHeight) / dxf.width), leftFragment = leftHeight / count, rightFragment = rightHeight / count, leftDirection = project1.points[0].direction(project0.points[0]), rightDirection = project1.points[1].direction(project0.points[1]), leftP = project0.points[0].clone(), rightP = project0.points[1].clone(), direction = rightP.direction(leftP);
2611
+ direction.multiplyScalar(dxf.width * 0.5);
2612
+ const _leftP = leftP.clone().add(direction), _rightP = rightP.clone().add(direction.multiplyScalar(-1)), d1 = leftP.direction(rightP), d2 = _leftP.direction(_rightP);
2613
+ if (d1.x > 0 && d2.x < 0 || d1.x < 0 && d2.x > 0 || d1.y > 0 && d2.y < 0 || d1.y < 0 && d2.y > 0) return;
2614
+ leftP.set(_leftP.x, _leftP.y);
2615
+ rightP.set(_rightP.x, _rightP.y);
2616
+ for (let i = 1; i < count; i++) {
2617
+ const left = leftDirection.clone().multiplyScalar(leftFragment * i), right = rightDirection.clone().multiplyScalar(rightFragment * i), p1 = leftP.clone().add(left), p2 = rightP.clone().add(right);
2618
+ this.addData(p1, p2);
2027
2619
  }
2028
2620
  }
2029
2621
  quadtree;
@@ -2031,13 +2623,18 @@ class st extends X {
2031
2623
  * 构建线段四叉树,快速查找,
2032
2624
  */
2033
2625
  buildQuadtree() {
2034
- const t = this.Dxf, e = [];
2035
- this.quadtree = new B(t.originalBox, 2), t.lineSegments.forEach((n) => {
2036
- n.userData?.isDoor || (this.quadtree?.insert({
2037
- line: n,
2038
- userData: e.length
2039
- }), e.push(n));
2040
- }), this.lineSegmentList = e;
2626
+ const dxf = this.Dxf;
2627
+ const lineSegmentList = [];
2628
+ this.quadtree = new Quadtree(dxf.originalBox, 2);
2629
+ dxf.lineSegments.forEach((lineSegment) => {
2630
+ if (lineSegment.userData?.isDoor) return;
2631
+ this.quadtree?.insert({
2632
+ line: lineSegment,
2633
+ userData: lineSegmentList.length
2634
+ });
2635
+ lineSegmentList.push(lineSegment);
2636
+ });
2637
+ this.lineSegmentList = lineSegmentList;
2041
2638
  }
2042
2639
  resultList = [];
2043
2640
  mergeWallLines = [];
@@ -2047,18 +2644,24 @@ class st extends X {
2047
2644
  */
2048
2645
  lineAnalysis() {
2049
2646
  this.buildQuadtree();
2050
- const t = this.quadtree, e = this.lineSegmentList, n = /* @__PURE__ */ new Set(), i = [];
2051
- e.forEach((o, s) => {
2052
- const r = e[s], a = C.fromByLineSegment(r, this.width * 2, !1, -0.01);
2053
- t.queryRect(a).map((h) => h.userData).filter((h) => h !== s).forEach((h) => {
2647
+ const quadtree = this.quadtree;
2648
+ const lineSegmentList = this.lineSegmentList;
2649
+ const visited = /* @__PURE__ */ new Set(), resultList = [];
2650
+ lineSegmentList.forEach((_0, i) => {
2651
+ const sourceLineSegment = lineSegmentList[i], rectangle = Rectangle.fromByLineSegment(sourceLineSegment, this.width * 2, false, -0.01), ids = quadtree.queryRect(rectangle).map((i2) => i2.userData).filter((index2) => index2 !== i);
2652
+ ids.forEach((id) => {
2054
2653
  try {
2055
- if (n.has(`${s}-${h}`) || n.has(`${h}-${s}`)) return;
2056
- const l = this.projectionAnalysis(h, s, r, e);
2057
- l && i.push(l), n.add(`${s}-${h}`);
2058
- } catch {
2654
+ if (visited.has(`${i}-${id}`) || visited.has(`${id}-${i}`)) return;
2655
+ const res = this.projectionAnalysis(id, i, sourceLineSegment, lineSegmentList);
2656
+ if (res) resultList.push(res);
2657
+ visited.add(`${i}-${id}`);
2658
+ } catch (error) {
2059
2659
  }
2060
2660
  });
2061
- }), this.appendLineSegmentList.length = 0, i.forEach(this.createRectangle.bind(this)), this.resultList = i;
2661
+ });
2662
+ this.appendLineSegmentList.length = 0;
2663
+ resultList.forEach(this.createRectangle.bind(this));
2664
+ this.resultList = resultList;
2062
2665
  }
2063
2666
  /** 线段投影分析
2064
2667
  * @param index
@@ -2066,36 +2669,42 @@ class st extends X {
2066
2669
  * @param lineSegmentList
2067
2670
  * @returns
2068
2671
  */
2069
- projectionAnalysis(t, e, n, i) {
2070
- const o = i[t], s = n.direction(), r = o.direction(), a = s.angleBetween(r) / (Math.PI / 180);
2071
- if (a < this.errorAngle || a > 180 - this.errorAngle) {
2072
- let c;
2073
- const h = o.projectLineSegment(n), l = n.projectLineSegment(o);
2074
- return h.getLength() > l.getLength() ? c = {
2075
- target: o,
2076
- targetIndex: t,
2077
- source: n,
2078
- sourceIndex: e,
2079
- project: h,
2080
- project2: l
2081
- } : c = {
2082
- target: n,
2083
- targetIndex: e,
2084
- source: o,
2085
- sourceIndex: t,
2086
- project: l,
2087
- project2: h
2088
- }, !c || c.project.getLength() < 0.2 || c.project2.getLength() < 0.2 ? void 0 : c;
2672
+ projectionAnalysis(index2, sourceIndex, sourceLineSegment, lineSegmentList) {
2673
+ const temLineSegment = lineSegmentList[index2], direct = sourceLineSegment.direction(), temDirect = temLineSegment.direction(), angle = direct.angleBetween(temDirect) / (Math.PI / 180);
2674
+ if (angle < this.errorAngle || angle > 180 - this.errorAngle) {
2675
+ let data;
2676
+ const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment);
2677
+ if (p1.getLength() > p2.getLength()) {
2678
+ data = {
2679
+ target: temLineSegment,
2680
+ targetIndex: index2,
2681
+ source: sourceLineSegment,
2682
+ sourceIndex,
2683
+ project: p1,
2684
+ project2: p2
2685
+ };
2686
+ } else {
2687
+ data = {
2688
+ target: sourceLineSegment,
2689
+ targetIndex: sourceIndex,
2690
+ source: temLineSegment,
2691
+ sourceIndex: index2,
2692
+ project: p2,
2693
+ project2: p1
2694
+ };
2695
+ }
2696
+ if (!data || data.project.getLength() < 0.2 || data.project2.getLength() < 0.2) return;
2697
+ return data;
2089
2698
  }
2090
2699
  }
2091
2700
  doorSearchNearAngle = 110;
2092
2701
  doorSearchDistance = 2;
2093
2702
  doors = [];
2094
2703
  doorsAnalysis() {
2095
- new it(this);
2704
+ new DoorsAnalysis(this);
2096
2705
  }
2097
2706
  }
2098
- class ot extends et {
2707
+ class DxfSystem extends ComponentManager {
2099
2708
  Dxf;
2100
2709
  Variable;
2101
2710
  wallWidth;
@@ -2104,87 +2713,116 @@ class ot extends et {
2104
2713
  * @param wallWidth 输出墙壁厚度,该墙壁厚度不受缩放影响
2105
2714
  * @param scale 原始数据缩放比例
2106
2715
  */
2107
- constructor(t = 0.1, e = 1) {
2108
- super(), this.environment = typeof window < "u" ? "browser" : typeof global < "u" ? "node" : "unknown", this.wallWidth = t, this.Dxf = new I(this.wallWidth, e), this.Variable = new k(), this.addComponent(this.Variable), this.addComponent(this.Dxf), this.addComponent(new st());
2716
+ constructor(wallWidth = 0.1, scale = 1) {
2717
+ super();
2718
+ this.environment = typeof window !== "undefined" ? "browser" : typeof global !== "undefined" ? "node" : "unknown";
2719
+ this.wallWidth = wallWidth;
2720
+ this.Dxf = new Dxf(this.wallWidth, scale);
2721
+ this.Variable = new Variable();
2722
+ this.addComponent(this.Variable);
2723
+ this.addComponent(this.Dxf);
2724
+ this.addComponent(new LineAnalysis());
2109
2725
  }
2110
- usePlugin(t) {
2111
- return typeof t == "function" && t.call(this, this), this;
2726
+ usePlugin(plugin) {
2727
+ if (typeof plugin === "function") plugin.call(this, this);
2728
+ return this;
2112
2729
  }
2113
2730
  destroy() {
2114
- [...this.components].forEach((t) => {
2115
- t.destroy();
2116
- }), [...this.components].forEach((t) => {
2117
- this.removeComponent(t);
2731
+ [...this.components].forEach((com) => {
2732
+ com.destroy();
2733
+ });
2734
+ [...this.components].forEach((com) => {
2735
+ this.removeComponent(com);
2118
2736
  });
2119
2737
  }
2120
2738
  }
2121
- const rt = new Q(), at = new tt();
2122
- function ct(g, t, e = 0.1) {
2123
- const n = t.normal(g), i = t.direction(g).mutiplyScalar(e * 0.5), o = g.direction(t).mutiplyScalar(e * 0.5), s = n.x * e * 0.5, r = n.y * e * 0.5;
2739
+ const exporter = new OBJExporter();
2740
+ const glbExporter = new GLTFExporter();
2741
+ function lineSqueezing(p1, p2, width = 0.1) {
2742
+ const normal = p2.normal(p1);
2743
+ const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
2744
+ const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
2745
+ const offsetX = normal.x * width * 0.5;
2746
+ const offsetY = normal.y * width * 0.5;
2124
2747
  return {
2125
2748
  points: [
2126
2749
  // 第一条线
2127
- new f(g.x + s, g.y + r).add(o),
2128
- new f(t.x + s, t.y + r).add(i),
2750
+ new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
2751
+ new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
2129
2752
  // 第二条线
2130
- new f(g.x - s, g.y - r).add(o),
2131
- new f(t.x - s, t.y - r).add(i)
2753
+ new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
2754
+ new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
2132
2755
  ],
2133
2756
  indices: [0, 1, 1, 3, 3, 2, 2, 0],
2134
2757
  rectIndices: [0, 1, 3, 2, 0]
2135
2758
  };
2136
2759
  }
2137
- class J extends X {
2760
+ class WhiteModel extends Component {
2138
2761
  static name = "WhiteModel";
2139
2762
  Dxf = null;
2140
2763
  Variable = null;
2141
2764
  // dxf数据白模
2142
- whiteModelGroup = new M.Group();
2765
+ whiteModelGroup = new THREE.Group();
2143
2766
  // dxf数据白模边缘线
2144
- whiteModelLineGroup = new M.Group();
2767
+ whiteModelLineGroup = new THREE.Group();
2145
2768
  // 原始数据白模
2146
- originalWhiteMode = new M.Group();
2147
- material = new M.MeshBasicMaterial({ color: 16777215, transparent: !0, opacity: 0.8, side: M.DoubleSide });
2148
- onAddFromParent(t) {
2149
- this.Dxf = t.findComponentByName("Dxf"), this.Variable = t.findComponentByName("Variable"), this.originalWhiteMode.visible = !1, this.Dxf?.addEventListener("lineOffset", () => {
2769
+ originalWhiteMode = new THREE.Group();
2770
+ material = new THREE.MeshBasicMaterial({ color: 16777215, transparent: true, opacity: 0.8, side: THREE.DoubleSide });
2771
+ onAddFromParent(parent) {
2772
+ this.Dxf = parent.findComponentByName("Dxf");
2773
+ this.Variable = parent.findComponentByName("Variable");
2774
+ this.originalWhiteMode.visible = false;
2775
+ this.Dxf?.addEventListener("lineOffset", () => {
2150
2776
  this.updateModel();
2151
2777
  });
2152
2778
  }
2153
2779
  updateModel() {
2154
- this.Variable?.set("whiteModelVisible", !1);
2155
- const t = this.Dxf;
2156
- 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) => {
2157
- const i = new M.Shape();
2158
- n.forEach((r, a) => a === 0 ? i.moveTo(r.x / t.scale, r.y / t.scale) : i.lineTo(r.x / t.scale, r.y / t.scale));
2159
- const o = new M.ExtrudeGeometry(i, {
2780
+ this.Variable?.set("whiteModelVisible", false);
2781
+ const dxf = this.Dxf;
2782
+ this.originalWhiteMode.clear();
2783
+ this.whiteModelGroup.clear();
2784
+ this.whiteModelLineGroup.clear();
2785
+ this.whiteModelGroup.add(this.whiteModelLineGroup);
2786
+ this.whiteModelGroup.position.z = dxf.originalZAverage;
2787
+ this.originalWhiteMode.position.z = dxf.originalZAverage;
2788
+ dxf.wallsGroup.forEach((points) => {
2789
+ const shape = new THREE.Shape();
2790
+ points.forEach((p, i) => i === 0 ? shape.moveTo(p.x / dxf.scale, p.y / dxf.scale) : shape.lineTo(p.x / dxf.scale, p.y / dxf.scale));
2791
+ const geometry = new THREE.ExtrudeGeometry(shape, {
2160
2792
  depth: 2.8,
2161
2793
  bevelSize: 0
2162
- }), s = new M.Mesh(o, this.material);
2163
- this.whiteModelGroup.add(s), this.whiteModelLineGroup.add(
2164
- new M.LineSegments(new M.EdgesGeometry(o), new M.LineBasicMaterial({ color: 0 }))
2794
+ });
2795
+ const mesh = new THREE.Mesh(geometry, this.material);
2796
+ this.whiteModelGroup.add(mesh);
2797
+ this.whiteModelLineGroup.add(
2798
+ new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({ color: 0 }))
2165
2799
  );
2166
- }), t.originalData.map(({ start: n, end: i, insetionArr: o }) => {
2167
- const s = new f(n.x, n.y).mutiplyScalar(t.scale), r = new f(i.x, i.y).mutiplyScalar(t.scale), { points: a, indices: c, rectIndices: h } = ct(s, r, t.width);
2800
+ });
2801
+ const walls = dxf.originalData.map(({ start, end, insetionArr }) => {
2802
+ const startVec3 = new Point(start.x, start.y).mutiplyScalar(dxf.scale), endVec3 = new Point(end.x, end.y).mutiplyScalar(dxf.scale), { points, indices, rectIndices } = lineSqueezing(startVec3, endVec3, dxf.width);
2168
2803
  return {
2169
- points: a,
2170
- indices: c,
2171
- rectIndices: h,
2172
- insetions: (o ?? []).map((l) => l.index)
2804
+ points,
2805
+ indices,
2806
+ rectIndices,
2807
+ insetions: (insetionArr ?? []).map((insetion) => insetion.index)
2173
2808
  };
2174
- }).forEach((n) => {
2175
- const i = new M.Shape();
2176
- n.rectIndices.forEach((r, a) => {
2177
- const c = n.points[r];
2178
- a === 0 ? i.moveTo(c.x, c.y) : i.lineTo(c.x, c.y);
2809
+ });
2810
+ walls.forEach((wall) => {
2811
+ const shape = new THREE.Shape();
2812
+ wall.rectIndices.forEach((index2, i) => {
2813
+ const p = wall.points[index2];
2814
+ if (i === 0) shape.moveTo(p.x, p.y);
2815
+ else shape.lineTo(p.x, p.y);
2179
2816
  });
2180
- const o = new M.ExtrudeGeometry(i, {
2817
+ const geometry = new THREE.ExtrudeGeometry(shape, {
2181
2818
  depth: 2.8,
2182
2819
  bevelSize: 0
2183
2820
  });
2184
- if (o.attributes.position.array.filter((r) => Number.isNaN(r)).length) return;
2185
- const s = new M.Mesh(o);
2186
- this.originalWhiteMode?.add(s);
2187
- }), this.dispatchEvent({
2821
+ if (geometry.attributes.position.array.filter((num) => Number.isNaN(num)).length) return;
2822
+ const mesh = new THREE.Mesh(geometry);
2823
+ this.originalWhiteMode?.add(mesh);
2824
+ });
2825
+ this.dispatchEvent({
2188
2826
  type: "updateModel",
2189
2827
  originalWhiteMode: this.originalWhiteMode,
2190
2828
  whiteModelGroup: this.whiteModelGroup
@@ -2195,9 +2833,13 @@ class J extends X {
2195
2833
  * @returns
2196
2834
  */
2197
2835
  toOBJ() {
2198
- return new Promise((t) => {
2199
- this.material.opacity = 1, this.material.needsUpdate = !0, setTimeout(() => {
2200
- t(rt.parse(this.whiteModelGroup)), this.material.opacity = 0.8, this.material.transparent = !0;
2836
+ return new Promise((resolve) => {
2837
+ this.material.opacity = 1;
2838
+ this.material.needsUpdate = true;
2839
+ setTimeout(() => {
2840
+ resolve(exporter.parse(this.whiteModelGroup));
2841
+ this.material.opacity = 0.8;
2842
+ this.material.transparent = true;
2201
2843
  }, 20);
2202
2844
  });
2203
2845
  }
@@ -2206,28 +2848,38 @@ class J extends X {
2206
2848
  * @param binary
2207
2849
  * @returns
2208
2850
  */
2209
- toGltf(t = !0) {
2210
- return new Promise((e) => {
2211
- this.material.opacity = 1, this.material.needsUpdate = !0, setTimeout(async () => {
2212
- if (typeof window == "object")
2213
- at.parse(this.whiteModelGroup.children, (n) => {
2214
- e(n), this.material.opacity = 0.8, this.material.transparent = !0;
2851
+ toGltf(binary = true) {
2852
+ return new Promise((resolve) => {
2853
+ this.material.opacity = 1;
2854
+ this.material.needsUpdate = true;
2855
+ setTimeout(async () => {
2856
+ if (typeof window === "object") {
2857
+ glbExporter.parse(this.whiteModelGroup.children, (gltf) => {
2858
+ resolve(gltf);
2859
+ this.material.opacity = 0.8;
2860
+ this.material.transparent = true;
2215
2861
  }, () => {
2216
- e(void 0);
2862
+ resolve(void 0);
2217
2863
  }, {
2218
- binary: t
2864
+ binary
2219
2865
  });
2220
- else if (typeof global != "function")
2866
+ } else if (typeof global !== "function") {
2221
2867
  try {
2222
- const n = await q("obj2gltf", !0), i = await q("fs", !1), o = await this.toOBJ();
2223
- i.writeFileSync(this.uuid, o);
2224
- const s = await n(this.uuid, {
2225
- binary: t
2868
+ const obj2gltf = await include("obj2gltf", true);
2869
+ const fs = await include("fs", false);
2870
+ const obj = await this.toOBJ();
2871
+ fs.writeFileSync(this.uuid, obj);
2872
+ const result = await obj2gltf(this.uuid, {
2873
+ binary
2226
2874
  });
2227
- i.unlinkSync(this.uuid), e(t ? s : JSON.stringify(s));
2228
- } catch (n) {
2229
- e(void 0), console.log(n);
2875
+ fs.unlinkSync(this.uuid);
2876
+ if (binary) resolve(result);
2877
+ else resolve(JSON.stringify(result));
2878
+ } catch (error) {
2879
+ resolve(void 0);
2880
+ console.log(error);
2230
2881
  }
2882
+ }
2231
2883
  }, 20);
2232
2884
  });
2233
2885
  }
@@ -2236,33 +2888,40 @@ class J extends X {
2236
2888
  * @returns
2237
2889
  */
2238
2890
  async toOBJBlob() {
2239
- const t = await this.toOBJ();
2240
- if (t)
2241
- return new Blob([t], { type: "application/octet-stream" });
2891
+ const buffer = await this.toOBJ();
2892
+ if (buffer) {
2893
+ return new Blob([buffer], { type: "application/octet-stream" });
2894
+ }
2242
2895
  }
2243
2896
  /**
2244
2897
  * 转为 GltfBlob
2245
2898
  * @returns
2246
2899
  */
2247
- async toGltfBlob(t = !0) {
2248
- const e = await this.toGltf(t);
2249
- if (e)
2250
- return new Blob([e], { type: "application/octet-stream" });
2900
+ async toGltfBlob(binary = true) {
2901
+ const buffer = await this.toGltf(binary);
2902
+ if (buffer) {
2903
+ return new Blob([buffer], { type: "application/octet-stream" });
2904
+ }
2251
2905
  }
2252
2906
  /**
2253
2907
  * 下载 OBJ
2254
2908
  * @param filename
2255
2909
  * @returns
2256
2910
  */
2257
- async downloadOBJ(t) {
2258
- if (typeof window < "u") {
2259
- const e = await this.toOBJBlob();
2260
- if (!e) return;
2261
- const n = document.createElement("a");
2262
- n.href = URL.createObjectURL(e), n.download = t, n.click();
2263
- } else if (typeof global < "u") {
2264
- const e = await this.toOBJ();
2265
- e && (await q("fs", !1)).writeFileSync(t, e);
2911
+ async downloadOBJ(filename) {
2912
+ if (typeof window !== "undefined") {
2913
+ const blob = await this.toOBJBlob();
2914
+ if (!blob) return;
2915
+ const a = document.createElement("a");
2916
+ a.href = URL.createObjectURL(blob);
2917
+ a.download = filename;
2918
+ a.click();
2919
+ } else if (typeof global !== "undefined") {
2920
+ const buffer = await this.toOBJ();
2921
+ if (buffer) {
2922
+ const fs = await include("fs", false);
2923
+ fs.writeFileSync(filename, buffer);
2924
+ }
2266
2925
  }
2267
2926
  }
2268
2927
  /**
@@ -2270,19 +2929,24 @@ class J extends X {
2270
2929
  * @param filename
2271
2930
  * @returns
2272
2931
  */
2273
- async downloadGltf(t, e = !0) {
2274
- if (typeof window < "u") {
2275
- const n = await this.toGltfBlob(e);
2276
- if (!n) return;
2277
- const i = document.createElement("a");
2278
- i.href = URL.createObjectURL(n), i.download = t, i.click();
2279
- } else if (typeof global < "u") {
2280
- const n = await this.toGltf(e);
2281
- n && (await q("fs", !1)).writeFileSync(t, e ? n : Buffer.from(n));
2932
+ async downloadGltf(filename, binary = true) {
2933
+ if (typeof window !== "undefined") {
2934
+ const blob = await this.toGltfBlob(binary);
2935
+ if (!blob) return;
2936
+ const a = document.createElement("a");
2937
+ a.href = URL.createObjectURL(blob);
2938
+ a.download = filename;
2939
+ a.click();
2940
+ } else if (typeof global !== "undefined") {
2941
+ const buffer = await this.toGltf(binary);
2942
+ if (buffer) {
2943
+ const fs = await include("fs", false);
2944
+ fs.writeFileSync(filename, binary ? buffer : Buffer.from(buffer));
2945
+ }
2282
2946
  }
2283
2947
  }
2284
2948
  }
2285
- class _ extends X {
2949
+ class DetailsPoint extends Component {
2286
2950
  static name = "DetailsPoint";
2287
2951
  Dxf = null;
2288
2952
  WhiteModel = null;
@@ -2290,8 +2954,10 @@ class _ extends X {
2290
2954
  desPoints = [];
2291
2955
  raylines = [];
2292
2956
  data = [];
2293
- onAddFromParent(t) {
2294
- this.Dxf = t.findComponentByName("Dxf"), this.Variable = t.findComponentByName("Variable"), this.Dxf?.addEventListener("setDta", () => {
2957
+ onAddFromParent(parent) {
2958
+ this.Dxf = parent.findComponentByName("Dxf");
2959
+ this.Variable = parent.findComponentByName("Variable");
2960
+ this.Dxf?.addEventListener("setDta", () => {
2295
2961
  this.updateModel();
2296
2962
  });
2297
2963
  }
@@ -2299,29 +2965,37 @@ class _ extends X {
2299
2965
  * 设置值
2300
2966
  * @param data
2301
2967
  */
2302
- async set(t) {
2303
- if (typeof t == "string")
2304
- if (typeof global < "u") {
2305
- const { default: n } = await import(
2968
+ async set(data) {
2969
+ if (typeof data === "string") {
2970
+ if (typeof global !== "undefined") {
2971
+ const packageName = "fs";
2972
+ const { default: fs } = await import(
2306
2973
  /* @vite-ignore */
2307
- "fs"
2308
- ), i = n.readFileSync(t), o = JSON.parse(i.toString("utf-8"));
2309
- this.set(o);
2974
+ packageName
2975
+ );
2976
+ const buffer = fs.readFileSync(data);
2977
+ const json = JSON.parse(buffer.toString("utf-8"));
2978
+ this.set(json);
2310
2979
  return;
2311
- } else
2980
+ } else {
2312
2981
  throw new Error("非node环境不允许使用路径");
2313
- this.data = t, this.updateModel();
2982
+ }
2983
+ }
2984
+ this.data = data;
2985
+ this.updateModel();
2314
2986
  }
2315
2987
  /**
2316
2988
  * 设置射线辅助
2317
2989
  */
2318
- racasterHelper(t, e, n) {
2990
+ racasterHelper(position, direction, far) {
2319
2991
  this.raylines.push([
2320
- t.clone(),
2321
- t.clone().add(e.clone().multiplyScalar(n))
2322
- ]), e.z = 0, this.raylines.push([
2323
- t.clone(),
2324
- t.clone().add(e.clone().multiplyScalar(n))
2992
+ position.clone(),
2993
+ position.clone().add(direction.clone().multiplyScalar(far))
2994
+ ]);
2995
+ direction.z = 0;
2996
+ this.raylines.push([
2997
+ position.clone(),
2998
+ position.clone().add(direction.clone().multiplyScalar(far))
2325
2999
  ]);
2326
3000
  }
2327
3001
  _timer = null;
@@ -2329,133 +3003,161 @@ class _ extends X {
2329
3003
  * 更新模型
2330
3004
  */
2331
3005
  updateModel() {
2332
- this._timer && clearTimeout(this._timer), this._timer = setTimeout(() => {
3006
+ if (this._timer) clearTimeout(this._timer);
3007
+ this._timer = setTimeout(() => {
2333
3008
  this._timer = null;
2334
- const t = this.parent?.findComponentByName("WhiteModel");
2335
- this.raylines.length = 0, this.desPoints.length = 0, this.data.forEach((e) => {
2336
- const n = new M.Vector3(
2337
- e.position.x,
2338
- e.position.y,
2339
- e.position.z
2340
- ), i = new M.Vector3(
2341
- e.direction.x,
2342
- e.direction.y,
2343
- e.direction.z
2344
- ), o = 100;
2345
- this.racasterHelper(n, i, o), i.z = 0;
2346
- const r = new M.Raycaster(n, i, 0, o).intersectObject(t.originalWhiteMode);
2347
- if (r.length) {
2348
- const { point: a } = r[0];
3009
+ const whiteModel = this.parent?.findComponentByName("WhiteModel");
3010
+ this.raylines.length = 0;
3011
+ this.desPoints.length = 0;
3012
+ this.data.forEach((item) => {
3013
+ const position = new THREE.Vector3(
3014
+ item.position.x,
3015
+ item.position.y,
3016
+ item.position.z
3017
+ );
3018
+ const direction = new THREE.Vector3(
3019
+ item.direction.x,
3020
+ item.direction.y,
3021
+ item.direction.z
3022
+ );
3023
+ const far = 100;
3024
+ this.racasterHelper(position, direction, far);
3025
+ direction.z = 0;
3026
+ const raycaster = new THREE.Raycaster(position, direction, 0, far);
3027
+ const list = raycaster.intersectObject(whiteModel.originalWhiteMode);
3028
+ if (list.length) {
3029
+ const { point } = list[0];
2349
3030
  this.desPoints.push({
2350
- message: e.desc,
2351
- position: n,
2352
- intersection: a
3031
+ message: item.desc,
3032
+ position,
3033
+ intersection: point
2353
3034
  });
2354
3035
  }
2355
- }), this.dispatchEvent({
3036
+ });
3037
+ this.dispatchEvent({
2356
3038
  type: "handleSuccess",
2357
3039
  desPoints: this.desPoints
2358
3040
  });
2359
3041
  }, 50);
2360
3042
  }
2361
3043
  }
2362
- class H extends X {
3044
+ class DxfLineModel extends Component {
2363
3045
  static name = "DxfLineModel";
2364
- dxfLineModel = new M.LineSegments();
2365
- dxfDoorsLineModel = new M.LineSegments();
2366
- dxfModelGroup = new M.Group();
2367
- onAddFromParent(t) {
2368
- const e = t.findComponentByName("Dxf");
2369
- this.dxfModelGroup.add(this.dxfLineModel), this.dxfModelGroup.add(this.dxfDoorsLineModel), this.dxfDoorsLineModel.material = new M.LineBasicMaterial({ color: 16776960, vertexColors: !0 }), e?.addEventListener("lineOffset", () => this.updateMode());
3046
+ dxfLineModel = new THREE.LineSegments();
3047
+ dxfDoorsLineModel = new THREE.LineSegments();
3048
+ dxfModelGroup = new THREE.Group();
3049
+ onAddFromParent(parent) {
3050
+ const dxf = parent.findComponentByName("Dxf");
3051
+ this.dxfModelGroup.add(this.dxfLineModel);
3052
+ this.dxfModelGroup.add(this.dxfDoorsLineModel);
3053
+ this.dxfDoorsLineModel.material = new THREE.LineBasicMaterial({ color: 16776960, vertexColors: true });
3054
+ dxf?.addEventListener("lineOffset", () => this.updateMode());
2370
3055
  }
2371
3056
  updateMode() {
2372
- const t = this.parent?.findComponentByName("Dxf");
3057
+ const dxf = this.parent?.findComponentByName("Dxf");
2373
3058
  this.dxfLineModel.clear();
2374
- const e = t.to3DArray(1 / t.scale, 0);
2375
- this.dxfLineModel.geometry = new M.BufferGeometry().setAttribute("position", new M.BufferAttribute(e, 3, !0));
2376
- const n = new Float32Array(
2377
- t.doorLineSegment.flatMap(({ start: o, end: s }) => [o.x, o.y, 0, s.x, s.y, 0])
2378
- ).map((o) => o / t.scale), i = new Float32Array(t.doorLineSegment.flatMap(() => [1, 0, 0, 0, 1, 0]));
2379
- this.dxfDoorsLineModel.geometry = new M.BufferGeometry().setAttribute("position", new M.BufferAttribute(n, 3, !0)).setAttribute("color", new M.BufferAttribute(i, 3)), this.dxfModelGroup.position.z = t.originalZAverage, this.dispatchEvent({
3059
+ const dxfArray = dxf.to3DArray(1 / dxf.scale, 0);
3060
+ this.dxfLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(dxfArray, 3, true));
3061
+ const doorsArray = new Float32Array(
3062
+ dxf.doorLineSegment.flatMap(({ start, end }) => [start.x, start.y, 0, end.x, end.y, 0])
3063
+ ).map((n) => n / dxf.scale);
3064
+ const doorsColorArray = new Float32Array(dxf.doorLineSegment.flatMap(() => [1, 0, 0, 0, 1, 0]));
3065
+ this.dxfDoorsLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(doorsArray, 3, true)).setAttribute("color", new THREE.BufferAttribute(doorsColorArray, 3));
3066
+ this.dxfModelGroup.position.z = dxf.originalZAverage;
3067
+ this.dispatchEvent({
2380
3068
  type: "modelUpdate",
2381
3069
  model: this.dxfModelGroup
2382
3070
  });
2383
3071
  }
2384
3072
  }
2385
- const ht = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3073
+ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2386
3074
  __proto__: null,
2387
- DetailsPoint: _,
2388
- DxfLineModel: H,
2389
- WhiteModel: J
3075
+ DetailsPoint,
3076
+ DxfLineModel,
3077
+ WhiteModel
2390
3078
  }, Symbol.toStringTag, { value: "Module" }));
2391
- function W(g, t = {}) {
3079
+ function ModelDataPlugin_(dxfSystem, option = {}) {
2392
3080
  const {
2393
- detailsPoint: e = !0,
2394
- whiteModel: n = !0,
2395
- dxfLineModel: i = !0
2396
- } = t;
2397
- i && g.addComponent(new H()), n && g.addComponent(new J()), e && g.addComponent(new _());
3081
+ detailsPoint = true,
3082
+ whiteModel = true,
3083
+ dxfLineModel = true
3084
+ } = option;
3085
+ dxfLineModel && dxfSystem.addComponent(new DxfLineModel());
3086
+ whiteModel && dxfSystem.addComponent(new WhiteModel());
3087
+ detailsPoint && dxfSystem.addComponent(new DetailsPoint());
2398
3088
  }
2399
- const lt = Object.assign(W, {
2400
- create(g = {}) {
2401
- return (t) => W(t, g);
3089
+ const ModelDataPlugin = Object.assign(ModelDataPlugin_, {
3090
+ create(option = {}) {
3091
+ return (dxfSystem) => ModelDataPlugin_(dxfSystem, option);
2402
3092
  }
2403
- }), dt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3093
+ });
3094
+ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2404
3095
  __proto__: null,
2405
- ModelDataPlugin: lt,
2406
- components: ht
3096
+ ModelDataPlugin,
3097
+ components: index$1
2407
3098
  }, Symbol.toStringTag, { value: "Module" }));
2408
- function ut() {
3099
+ function loadRenderPlugin() {
2409
3100
  return import("./index2.js");
2410
3101
  }
2411
- function ft() {
3102
+ function loadEditorPlugin() {
2412
3103
  return import("./index3.js");
2413
3104
  }
2414
- let O = null;
2415
- async function Dt(g, t, e = !1, n) {
2416
- const i = await Promise.resolve().then(() => dt), o = await ut(), s = await ft(), r = new ot().usePlugin(i.ModelDataPlugin.create({
2417
- detailsPoint: !1,
2418
- whiteModel: !0
2419
- })).usePlugin(o.RenderPlugin.create({
2420
- originalLine: !1,
2421
- modelData: !1,
2422
- detailsPoint: !1,
2423
- orbitControls: e,
2424
- camera: t
2425
- })).usePlugin(s.Editor.create({ viewPermission: n })), a = r.findComponentByType(o.components.DomContainer);
2426
- return a && g.appendChild(a.domElement), O = r, {
2427
- dxfSystem: r,
2428
- getFileAll: () => pt(r)
3105
+ let gloabalDxfSystem = null;
3106
+ async function createEditor(dom, camera, orbitControls = false, viewPermission) {
3107
+ const mp = await Promise.resolve().then(() => index);
3108
+ const rp = await loadRenderPlugin();
3109
+ const editor = await loadEditorPlugin();
3110
+ const dxfSystem = new DxfSystem().usePlugin(mp.ModelDataPlugin.create({
3111
+ detailsPoint: false,
3112
+ whiteModel: true
3113
+ })).usePlugin(rp.RenderPlugin.create({
3114
+ originalLine: false,
3115
+ modelData: false,
3116
+ detailsPoint: false,
3117
+ orbitControls,
3118
+ camera
3119
+ })).usePlugin(editor.Editor.create({ viewPermission }));
3120
+ const domContainer = dxfSystem.findComponentByType(rp.components.DomContainer);
3121
+ domContainer && dom.appendChild(domContainer.domElement);
3122
+ gloabalDxfSystem = dxfSystem;
3123
+ return {
3124
+ dxfSystem,
3125
+ getFileAll: () => getFileAll(dxfSystem)
2429
3126
  };
2430
3127
  }
2431
- async function pt(g = O) {
2432
- const t = g.findComponentByName("WhiteModel"), e = new File([g.Dxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" }), n = new File([await t.toOBJBlob()], "model.obj", { type: "application/octet-stream" }), i = new File([await t.toGltfBlob(!0)], "model.glb", { type: "application/octet-stream" }), o = new File([await t.toGltfBlob(!1)], "model.gltf", { type: "application/json" }), s = new File([JSON.stringify(g.Dxf.originalData)], "json.json", { type: "application/json" });
3128
+ async function getFileAll(dxfSystem = gloabalDxfSystem) {
3129
+ const whiteModel = dxfSystem.findComponentByName("WhiteModel");
3130
+ const dxf = new File([dxfSystem.Dxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" });
3131
+ const obj = new File([await whiteModel.toOBJBlob()], "model.obj", { type: "application/octet-stream" });
3132
+ const glb = new File([await whiteModel.toGltfBlob(true)], "model.glb", { type: "application/octet-stream" });
3133
+ const gltf = new File([await whiteModel.toGltfBlob(false)], "model.gltf", { type: "application/json" });
3134
+ const json = new File([JSON.stringify(dxfSystem.Dxf.originalData)], "json.json", { type: "application/json" });
2433
3135
  return {
2434
- dxf: e,
2435
- obj: n,
2436
- glb: i,
2437
- gltf: o,
2438
- json: s
3136
+ dxf,
3137
+ obj,
3138
+ glb,
3139
+ gltf,
3140
+ json
2439
3141
  };
2440
3142
  }
2441
- function bt() {
2442
- return O;
3143
+ function getGlobalDxfSystem() {
3144
+ return gloabalDxfSystem;
2443
3145
  }
2444
3146
  export {
2445
- A as B,
2446
- X as C,
2447
- ot as D,
2448
- $ as E,
2449
- b as L,
2450
- lt as M,
2451
- f as P,
2452
- B as Q,
2453
- k as V,
2454
- J as W,
2455
- _ as a,
2456
- U as b,
2457
- Dt as c,
2458
- bt as d,
2459
- pt as g,
2460
- ht as i
3147
+ Box2 as B,
3148
+ Component as C,
3149
+ DxfSystem as D,
3150
+ EventDispatcher as E,
3151
+ LineSegment as L,
3152
+ ModelDataPlugin as M,
3153
+ Point as P,
3154
+ Quadtree as Q,
3155
+ Variable as V,
3156
+ WhiteModel as W,
3157
+ DetailsPoint as a,
3158
+ PointVirtualGrid as b,
3159
+ createEditor as c,
3160
+ getGlobalDxfSystem as d,
3161
+ getFileAll as g,
3162
+ index$1 as i
2461
3163
  };