build-dxf 0.0.20-15 → 0.0.20-2

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 +1915 -1218
  3. package/src/index.css +629 -1
  4. package/src/index.js +7 -7
  5. package/src/index2.js +528 -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;
1053
+ }
1054
+ if (Math.abs(d2) < 1e-10 && isPointOnSegment(p4, p1, p2)) {
1055
+ return true;
1056
+ }
1057
+ if (Math.abs(d3) < 1e-10 && isPointOnSegment(p1, p3, p4)) {
1058
+ return true;
848
1059
  }
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;
1060
+ if (Math.abs(d4) < 1e-10 && isPointOnSegment(p2, p3, p4)) {
1061
+ return true;
851
1062
  }
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));
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,219 @@ 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 > 2 ? 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();
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;
1500
+ }
1501
+ if (!nextline) continue;
1502
+ const intersectPoint = preLine.getIntersection(nextline);
1503
+ if (intersectPoint) {
1504
+ const p0 = preLine.points[1].clone(), p1 = nextline.points[0].clone();
1505
+ preLine.points[1].copy(intersectPoint);
1506
+ nextline.points[0].copy(intersectPoint);
1507
+ if (preLine.length() < this.width) {
1508
+ preLine.points[1].copy(p0);
1509
+ nextline.points[0].copy(p0);
1510
+ } else if (nextline.length() < this.width) {
1511
+ preLine.points[1].copy(p1);
1512
+ nextline.points[0].copy(p1);
1513
+ }
1514
+ } else {
1515
+ preLine.points[1].copy(nextline.points[0]);
1199
1516
  }
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) : [];
1517
+ filterLines.push(nextline);
1518
+ }
1519
+ return filterLines.length > 2 ? linesToPath(filterLines) : [];
1214
1520
  }
1215
1521
  /** 线偏移
1216
1522
  * @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
1217
1523
  */
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({
1524
+ lineOffset(endType = Dxf.EndType.etOpenSquare, joinType = Dxf.JoinType.jtMiter, scale = 1e4) {
1525
+ let solutions = new ClipperLib.Paths();
1526
+ const offset = new ClipperLib.ClipperOffset(20, 0.25);
1527
+ this.pointsGroups.forEach((points) => {
1528
+ const linePaths = this.lineTopology(points).map((linePath) => linePath.map((p) => p.clone().mutiplyScalar(scale)));
1529
+ offset.AddPaths(linePaths, joinType, endType);
1530
+ });
1531
+ offset.Execute(solutions, this.width / 2 * scale);
1532
+ this.wallsGroup = solutions.map((ps) => {
1533
+ let path = ps.map((p) => Point.from(p).divisionScalar(scale));
1534
+ path = this.lineSegmentStraightening(path);
1535
+ if (endType == Dxf.EndType.etOpenSquare) path = this.squareRemoveBurr(path);
1536
+ path = this.removeShortLine(path);
1537
+ return path;
1538
+ });
1539
+ this.dispatchEvent({
1228
1540
  type: "lineOffset",
1229
1541
  wallsGroup: this.wallsGroup
1230
- }), this.wallsGroup;
1542
+ });
1543
+ return this.wallsGroup;
1231
1544
  }
1232
1545
  /**
1233
1546
  * 将点云结构转换为Float32Array
1234
1547
  */
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);
1548
+ to3DArray(scale, z = this.originalZAverage) {
1549
+ const array = [];
1550
+ this.wallsGroup.forEach((points) => {
1551
+ for (let i = 0; i < points.length; i++) {
1552
+ const point1 = points[i];
1553
+ const nextIndex = i === points.length - 1 ? 0 : i + 1;
1554
+ const point2 = points[nextIndex];
1555
+ array.push(point1.X * scale, point1.Y * scale, z, point2.X * scale, point2.Y * scale, z);
1241
1556
  }
1242
- }), new Float32Array(n);
1557
+ });
1558
+ return new Float32Array(array);
1243
1559
  }
1244
1560
  /** 获取角度范围
1245
1561
  * @param center
@@ -1247,140 +1563,196 @@ class I extends X {
1247
1563
  * @param p2
1248
1564
  * @returns
1249
1565
  */
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)];
1566
+ getArcAngleRange(center, p1, p2) {
1567
+ const x1 = p1.x - center.x;
1568
+ const y1 = p1.y - center.y;
1569
+ const x2 = p2.x - center.x;
1570
+ const y2 = p2.y - center.y;
1571
+ let angle1 = Math.atan2(y1, x1);
1572
+ let angle2 = Math.atan2(y2, x2);
1573
+ angle1 = angle1 < 0 ? angle1 + 2 * Math.PI : angle1;
1574
+ angle2 = angle2 < 0 ? angle2 + 2 * Math.PI : angle2;
1575
+ let r1, r2;
1576
+ const diff = Math.abs(angle2 - angle1);
1577
+ if (diff <= Math.PI) {
1578
+ r1 = Math.min(angle1, angle2);
1579
+ r2 = Math.max(angle1, angle2);
1580
+ } else {
1581
+ r1 = Math.max(angle1, angle2);
1582
+ r2 = Math.min(angle1, angle2) + 2 * Math.PI;
1583
+ }
1584
+ return [r1 / (Math.PI / 180), r2 / (Math.PI / 180)];
1256
1585
  }
1257
1586
  /**
1258
1587
  * 将点云结构转换为string
1259
1588
  */
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);
1589
+ toDxfString(unit = "Millimeters") {
1590
+ const d = new Drawing();
1591
+ d.setUnits("Millimeters");
1592
+ const s = units[unit];
1593
+ function drawLine(p1, p2) {
1594
+ d.drawLine(p1.X * s, p1.Y * s, p2.X * s, p2.Y * s);
1595
+ }
1596
+ this.wallsGroup.forEach((points) => {
1597
+ for (let i = 0; i < points.length; i++) {
1598
+ const point1 = points[i];
1599
+ const nextIndex = i === points.length - 1 ? 0 : i + 1;
1600
+ const point2 = points[nextIndex];
1601
+ drawLine(point1, point2);
1271
1602
  }
1272
1603
  });
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()))
1604
+ const doorThickness = this.width * 0.2;
1605
+ const list = [];
1606
+ d.addLayer("l_cyan", Drawing.ACI.CYAN, "DOTTED");
1607
+ this.doorLineSegment.forEach((lineSegment) => {
1608
+ if (lineSegment.length() < 0.4) return;
1609
+ const line = lineSegment.clone().expansion(-this.width * 0.5);
1610
+ d.setActiveLayer("l_cyan");
1611
+ if (line.length() < 1.2) {
1612
+ line.expansion(-doorThickness * 0.5);
1613
+ const normal = lineSegment.normal();
1614
+ let door = new LineSegment(
1615
+ line.start.clone(),
1616
+ line.start.clone().add(normal.clone().multiplyScalar(line.length()))
1283
1617
  );
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()))
1618
+ const box = door.clone().directionMove(door.normal(), line.length() * -0.5).expandToRectangle(line.length(), "bothSides");
1619
+ for (let j = 0; j < list.length; j++) {
1620
+ if (list[j].intersectRectangle(box)) {
1621
+ door = new LineSegment(
1622
+ line.start.clone(),
1623
+ line.start.clone().add(normal.clone().multiplyScalar(-line.length()))
1290
1624
  );
1291
1625
  break;
1292
1626
  }
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();
1627
+ }
1628
+ door.expansion(-doorThickness * 0.5).expandToRectangle(this.width * 0.2, "bothSides").path2D((p1, p2) => drawLine(p1, p2));
1629
+ 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);
1630
+ d.drawArc(center.x * s, center.y * s, r * s, Math.min(startAngle, endAngle), Math.max(startAngle, endAngle));
1631
+ list.push(box);
1632
+ } else {
1633
+ line.clone().expansion(-this.width * 0.5).expandToRectangle(this.width).path2D((p1, p2) => drawLine(p1, p2));
1634
+ 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));
1635
+ 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));
1636
+ }
1637
+ });
1638
+ d.addLayer("l_yellow", Drawing.ACI.YELLOW, "DOTTED");
1639
+ d.setActiveLayer("l_yellow");
1640
+ this.lineSegments.forEach((line) => {
1641
+ if (!line.userData.isWindow) return false;
1642
+ if (Array.isArray(line.userData.drawDoorData)) {
1643
+ line.userData.drawDoorData.forEach((w) => {
1644
+ const { p, width } = w;
1645
+ const center = Point.from(p);
1646
+ const start = center.clone().add(line.direction().multiplyScalar(width * 0.5));
1647
+ const end = center.clone().add(line.direction().multiplyScalar(-width * 0.5));
1648
+ const blinds = new LineSegment(start, end);
1649
+ drawLine(blinds.start, blinds.end);
1650
+ blinds.expandToRectangle(this.width, "bothSides").path2D((p1, p2) => drawLine(p1, p2));
1651
+ });
1652
+ }
1653
+ });
1654
+ return d.toDxfString();
1305
1655
  }
1306
1656
  /**
1307
1657
  * 将点云结构转换为DXF格式
1308
1658
  * @returns
1309
1659
  */
1310
- toDxfBlob(t = "Millimeters") {
1311
- return new Blob([this.toDxfString(t)]);
1660
+ toDxfBlob(unit = "Millimeters") {
1661
+ const blob = new Blob([this.toDxfString(unit)]);
1662
+ return blob;
1312
1663
  }
1313
1664
  /**
1314
1665
  * 下载
1315
1666
  * @param filename
1316
1667
  */
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));
1668
+ async download(filename, unit = "Millimeters") {
1669
+ if (typeof window !== "undefined") {
1670
+ const blob = this.toDxfBlob(unit);
1671
+ const a = document.createElement("a");
1672
+ a.href = URL.createObjectURL(blob);
1673
+ a.download = filename + ".dxf";
1674
+ a.click();
1675
+ } else if (typeof global !== "undefined") {
1676
+ const fs = await include("fs", false);
1677
+ fs.writeFileSync(filename, this.toDxfString(unit));
1678
+ }
1322
1679
  }
1323
1680
  /**
1324
1681
  * 计算原始数据的边界框
1325
1682
  * @description 计算所有线段的起点和终点的最小最大值,形成一个边界框
1326
1683
  * @returns
1327
1684
  */
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;
1685
+ computedOriginalSize(data, originalBox = new Box2(0, 0, 0, 0)) {
1686
+ const xArr = data.flatMap((item) => [item.start.x, item.end.x]);
1687
+ const yArr = data.flatMap((item) => [item.start.y, item.end.y]);
1688
+ const minX = Math.min(...xArr);
1689
+ const minY = Math.min(...yArr);
1690
+ const maxX = Math.max(...xArr);
1691
+ const maxY = Math.max(...yArr);
1692
+ originalBox.set(minX, minY, maxX, maxY);
1693
+ return originalBox;
1331
1694
  }
1332
1695
  /**
1333
1696
  * 创建数据
1334
1697
  * @param pointsGroups
1335
1698
  * @returns
1336
1699
  */
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];
1700
+ static createData(pointsGroups, sealed = true) {
1701
+ let count = 0;
1702
+ const data = pointsGroups.flatMap((points) => {
1703
+ const lines = points.map((point, index2) => {
1704
+ const nextIndex = index2 === points.length - 1 ? 0 : index2 + 1;
1705
+ const nextPoint = points[nextIndex];
1342
1706
  return {
1343
- start: { x: r.x, y: r.y },
1344
- end: { x: h.x, y: h.y },
1707
+ start: { x: point.x, y: point.y },
1708
+ end: { x: nextPoint.x, y: nextPoint.y },
1345
1709
  insetionArr: [
1346
1710
  {
1347
- index: c + n
1711
+ index: nextIndex + count
1348
1712
  }
1349
1713
  ]
1350
1714
  };
1351
1715
  });
1352
- return n += o.length, e || (s.pop(), s[s.length - 1].insetionArr.length = 0, n--), s;
1716
+ count += points.length;
1717
+ if (!sealed) {
1718
+ lines.pop();
1719
+ lines[lines.length - 1].insetionArr.length = 0;
1720
+ count--;
1721
+ }
1722
+ return lines;
1353
1723
  });
1724
+ return data;
1354
1725
  }
1355
1726
  }
1356
- class k extends X {
1727
+ class Variable extends Component {
1357
1728
  static name = "Variable";
1358
- originalLineVisible = !0;
1359
- dxfVisible = !0;
1360
- whiteModelVisible = !0;
1361
- isLook = !1;
1729
+ originalLineVisible = true;
1730
+ dxfVisible = true;
1731
+ whiteModelVisible = true;
1732
+ isLook = false;
1362
1733
  currentWheel = 0;
1363
1734
  pointerMove = { x: 0, y: 0 };
1364
1735
  currentKeyUp = "";
1365
1736
  currentKeyDown = "";
1366
1737
  currentMouseUp = "";
1367
1738
  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
1739
+ focus = false;
1740
+ set(key, value) {
1741
+ if (key in this) {
1742
+ const oldValue = this[key];
1743
+ this[key] = value;
1744
+ this.dispatchEvent({
1745
+ type: key,
1746
+ value,
1747
+ oldValue
1376
1748
  });
1377
1749
  }
1378
1750
  }
1379
- get(t) {
1380
- if (t in this) return this[t];
1751
+ get(key) {
1752
+ if (key in this) return this[key];
1381
1753
  }
1382
1754
  }
1383
- class B {
1755
+ class Quadtree {
1384
1756
  bounds;
1385
1757
  // 包围盒
1386
1758
  capacity;
@@ -1389,7 +1761,7 @@ class B {
1389
1761
  // 最大深度
1390
1762
  depth;
1391
1763
  // 当前深度
1392
- isLeaf = !0;
1764
+ isLeaf = true;
1393
1765
  // 是否为叶子节点
1394
1766
  children = null;
1395
1767
  // 子节点数组
@@ -1397,72 +1769,110 @@ class B {
1397
1769
  // 存储的节点
1398
1770
  color = [Math.random(), Math.random(), Math.random()];
1399
1771
  // 颜色
1400
- constructor(t, e = 8, n = 10, i = 1) {
1401
- this.bounds = t, this.capacity = e, this.depth = i, this.maxDepth = n;
1772
+ constructor(bounds, capacity = 8, maxDepth = 10, depth = 1) {
1773
+ this.bounds = bounds;
1774
+ this.capacity = capacity;
1775
+ this.depth = depth;
1776
+ this.maxDepth = maxDepth;
1402
1777
  }
1403
1778
  /**
1404
1779
  * 插入线段节点
1405
1780
  * @param node 线段节点
1406
1781
  */
1407
- insert(t) {
1782
+ insert(node) {
1408
1783
  if (!this.isLeaf) {
1409
- const e = this.getQuadrant(t.line);
1410
- if (e !== -1) {
1411
- this.children[e].insert(t);
1784
+ const quadrant = this.getQuadrant(node.line);
1785
+ if (quadrant !== -1) {
1786
+ this.children[quadrant].insert(node);
1412
1787
  return;
1413
1788
  }
1414
1789
  }
1415
- if (this.nodes.push(t), t.parent = this, this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
1790
+ this.nodes.push(node);
1791
+ node.parent = this;
1792
+ if (this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
1416
1793
  this.subdivide();
1417
- const e = this.nodes;
1794
+ const nodes = this.nodes;
1418
1795
  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));
1796
+ for (const n of nodes) {
1797
+ const quadrant = this.getQuadrant(n.line);
1798
+ if (quadrant !== -1) {
1799
+ this.children[quadrant].insert(n);
1800
+ } else {
1801
+ n.parent = this;
1802
+ this.nodes.push(n);
1803
+ }
1422
1804
  }
1423
1805
  }
1424
1806
  }
1425
1807
  /** 移除
1426
1808
  * @param node
1427
1809
  */
1428
- remove(t) {
1429
- const e = t.parent?.nodes.indexOf(t);
1430
- e > -1 && t.parent?.nodes.splice(e, 1);
1810
+ remove(node) {
1811
+ const index2 = node.parent?.nodes.indexOf(node);
1812
+ if (index2 > -1) {
1813
+ node.parent?.nodes.splice(index2, 1);
1814
+ }
1431
1815
  }
1432
1816
  /**
1433
1817
  * 获取线段所属的象限
1434
1818
  * @param line 线段
1435
1819
  * @returns 象限索引(0:西北,1:东北,2:西南,3:东南)或-1(跨多个象限)
1436
1820
  */
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;
1821
+ getQuadrant(line) {
1822
+ const intersectsNW = this.children[0].bounds.intersectLineSegment(line);
1823
+ const intersectsNE = this.children[1].bounds.intersectLineSegment(line);
1824
+ const intersectsSW = this.children[2].bounds.intersectLineSegment(line);
1825
+ const intersectsSE = this.children[3].bounds.intersectLineSegment(line);
1826
+ let count = 0;
1827
+ let quadrant = -1;
1828
+ if (intersectsNW) {
1829
+ count++;
1830
+ quadrant = 0;
1831
+ }
1832
+ if (intersectsNE) {
1833
+ count++;
1834
+ quadrant = 1;
1835
+ }
1836
+ if (intersectsSW) {
1837
+ count++;
1838
+ quadrant = 2;
1839
+ }
1840
+ if (intersectsSE) {
1841
+ count++;
1842
+ quadrant = 3;
1843
+ }
1844
+ if (count === 1) return quadrant;
1845
+ return -1;
1441
1846
  }
1442
1847
  /**
1443
1848
  * 细分当前节点为四个子节点
1444
1849
  */
1445
1850
  subdivide() {
1446
1851
  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),
1852
+ this.isLeaf = false;
1853
+ this.children = [];
1854
+ const midX = (this.bounds.minX + this.bounds.maxX) / 2;
1855
+ const midY = (this.bounds.minY + this.bounds.maxY) / 2;
1856
+ this.children[0] = new Quadtree(
1857
+ new Box2(this.bounds.minX, midX, this.bounds.minY, midY),
1451
1858
  this.capacity,
1452
1859
  this.maxDepth,
1453
1860
  this.depth + 1
1454
- ), this.children[1] = new B(
1455
- new A(t, this.bounds.maxX, this.bounds.minY, e),
1861
+ );
1862
+ this.children[1] = new Quadtree(
1863
+ new Box2(midX, this.bounds.maxX, this.bounds.minY, midY),
1456
1864
  this.capacity,
1457
1865
  this.maxDepth,
1458
1866
  this.depth + 1
1459
- ), this.children[2] = new B(
1460
- new A(this.bounds.minX, t, e, this.bounds.maxY),
1867
+ );
1868
+ this.children[2] = new Quadtree(
1869
+ new Box2(this.bounds.minX, midX, midY, this.bounds.maxY),
1461
1870
  this.capacity,
1462
1871
  this.maxDepth,
1463
1872
  this.depth + 1
1464
- ), this.children[3] = new B(
1465
- new A(t, this.bounds.maxX, e, this.bounds.maxY),
1873
+ );
1874
+ this.children[3] = new Quadtree(
1875
+ new Box2(midX, this.bounds.maxX, midY, this.bounds.maxY),
1466
1876
  this.capacity,
1467
1877
  this.maxDepth,
1468
1878
  this.depth + 1
@@ -1473,16 +1883,22 @@ class B {
1473
1883
  * @param box2 包围盒
1474
1884
  * @returns 相交的节点数组
1475
1885
  */
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;
1886
+ queryBox(box2) {
1887
+ const result = [];
1888
+ if (!this.bounds.intersectBox(box2)) {
1889
+ return result;
1890
+ }
1891
+ for (const node of this.nodes) {
1892
+ if (box2.intersectLineSegment(node.line)) {
1893
+ result.push(node);
1894
+ }
1895
+ }
1896
+ if (!this.isLeaf) {
1897
+ for (const child of this.children) {
1898
+ result.push(...child.queryBox(box2));
1899
+ }
1900
+ }
1901
+ return result;
1486
1902
  }
1487
1903
  /**
1488
1904
  * 查询与圆形区域相交的线段节点
@@ -1490,58 +1906,81 @@ class B {
1490
1906
  * @param radius 半径
1491
1907
  * @returns 相交的节点数组
1492
1908
  */
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
1909
+ queryCircle(pos, radius) {
1910
+ const result = [];
1911
+ const circleBox = new Box2(
1912
+ pos.x - radius,
1913
+ pos.x + radius,
1914
+ pos.y - radius,
1915
+ pos.y + radius
1499
1916
  );
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);
1917
+ if (!this.bounds.intersectBox(circleBox)) {
1918
+ return result;
1919
+ }
1920
+ for (const node of this.nodes) {
1921
+ const [p1, p2] = node.line.points;
1922
+ const dx = p2.x - p1.x;
1923
+ const dy = p2.y - p1.y;
1924
+ const l2 = dx * dx + dy * dy;
1925
+ let t = ((pos.x - p1.x) * dx + (pos.y - p1.y) * dy) / l2;
1926
+ t = Math.max(0, Math.min(1, t));
1927
+ const closestX = p1.x + t * dx;
1928
+ const closestY = p1.y + t * dy;
1929
+ const distance = pos.distance(new Point(closestX, closestY));
1930
+ if (distance <= radius) {
1931
+ result.push(node);
1932
+ }
1933
+ }
1934
+ if (!this.isLeaf) {
1935
+ for (const child of this.children) {
1936
+ result.push(...child.queryCircle(pos, radius));
1937
+ }
1508
1938
  }
1509
- if (!this.isLeaf)
1510
- for (const o of this.children)
1511
- n.push(...o.queryCircle(t, e));
1512
- return n;
1939
+ return result;
1513
1940
  }
1514
1941
  /**
1515
1942
  * 查询与矩形相交的线段节点
1516
1943
  * @param rectangle 矩形
1517
1944
  * @returns 相交的节点数组
1518
1945
  */
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;
1946
+ queryRect(rectangle) {
1947
+ const result = [];
1948
+ if (!this.bounds.intersectRectangle(rectangle)) {
1949
+ return result;
1950
+ }
1951
+ for (const node of this.nodes) {
1952
+ if (rectangle.intersectLineSegment(node.line)) {
1953
+ result.push(node);
1954
+ }
1955
+ }
1956
+ if (!this.isLeaf) {
1957
+ for (const child of this.children) {
1958
+ result.push(...child.queryRect(rectangle));
1959
+ }
1960
+ }
1961
+ return result;
1529
1962
  }
1530
1963
  /**
1531
1964
  * 查询与线段相交的线段节点
1532
1965
  * @param lineSegment 线段
1533
1966
  * @returns 相交的节点数组
1534
1967
  */
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;
1968
+ queryLineSegment(lineSegment) {
1969
+ const result = [];
1970
+ if (!this.bounds.intersectLineSegment(lineSegment)) {
1971
+ return result;
1972
+ }
1973
+ for (const node of this.nodes) {
1974
+ if (lineSegment.intersectLineSegment(node.line)) {
1975
+ result.push(node);
1976
+ }
1977
+ }
1978
+ if (!this.isLeaf) {
1979
+ for (const child of this.children) {
1980
+ result.push(...child.queryLineSegment(lineSegment));
1981
+ }
1982
+ }
1983
+ return result;
1545
1984
  }
1546
1985
  /**
1547
1986
  * 包围盒转换为数组
@@ -1549,80 +1988,96 @@ class B {
1549
1988
  * @param colors
1550
1989
  * @returns
1551
1990
  */
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;
1991
+ boundsToArray(array = [], colors, recursion = true) {
1992
+ if (!this.isLeaf && recursion) {
1993
+ this.children?.forEach((child) => child.boundsToArray(array, colors));
1994
+ }
1995
+ array.push(...this.bounds.points.flatMap((p, i, array2) => {
1996
+ const np = array2[(i + 1) % array2.length];
1997
+ colors?.push(...this.color);
1998
+ colors?.push(...this.color);
1999
+ return [p.x, p.y, 0, np.x, np.y, 0];
2000
+ }));
2001
+ return array;
1557
2002
  }
1558
2003
  }
1559
- class U {
2004
+ class PointVirtualGrid {
1560
2005
  map = /* @__PURE__ */ new Map();
1561
2006
  gridSize;
1562
- constructor(t = 2) {
1563
- this.gridSize = t;
2007
+ constructor(gridSize = 2) {
2008
+ this.gridSize = gridSize;
1564
2009
  }
1565
2010
  /**
1566
2011
  * 插入
1567
2012
  * @param point
1568
2013
  * @param userData
1569
2014
  */
1570
- insert(t, e) {
1571
- if (!t || isNaN(t.x) || isNaN(t.y))
2015
+ insert(point, userData) {
2016
+ if (!point || isNaN(point.x) || isNaN(point.y)) {
1572
2017
  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 };
2018
+ }
2019
+ const id = this.getGridId(point);
2020
+ if (!this.map.has(id)) this.map.set(id, /* @__PURE__ */ new Set());
2021
+ const set = this.map.get(id);
2022
+ const target = { point, userData };
2023
+ set.add(target);
2024
+ point.userData.pointVirtualGrid = { set, target };
1577
2025
  }
1578
2026
  /**
1579
2027
  * 批量加入
1580
2028
  * @param points
1581
2029
  */
1582
- insertBatch(t) {
1583
- for (const { point: e, userData: n } of t)
1584
- this.insert(e, n);
2030
+ insertBatch(points) {
2031
+ for (const { point, userData } of points) {
2032
+ this.insert(point, userData);
2033
+ }
1585
2034
  }
1586
2035
  /** 移除点
1587
2036
  * @param point
1588
2037
  */
1589
- remove(t) {
1590
- const { set: e, target: n } = t?.userData?.pointVirtualGrid;
1591
- e && (e.delete(n), delete t?.userData?.pointVirtualGridMap);
2038
+ remove(point) {
2039
+ const { set, target } = point?.userData?.pointVirtualGrid;
2040
+ if (set) {
2041
+ set.delete(target);
2042
+ delete point?.userData?.pointVirtualGridMap;
2043
+ }
1592
2044
  }
1593
2045
  /**
1594
2046
  * 获取通过坐标,获取唯一网格索引
1595
2047
  * @param point
1596
2048
  * @returns
1597
2049
  */
1598
- getGridId(t) {
1599
- const e = Math.ceil(t.x / this.gridSize), n = Math.ceil(t.y / this.gridSize);
1600
- return `${e}.${n}`;
2050
+ getGridId(point) {
2051
+ const i = Math.ceil(point.x / this.gridSize), j = Math.ceil(point.y / this.gridSize);
2052
+ return `${i}.${j}`;
1601
2053
  }
1602
2054
  /**
1603
2055
  *
1604
2056
  * @param gridId
1605
2057
  * @returns
1606
2058
  */
1607
- decodeGridId(t) {
1608
- const [e, n] = t.split(".").map(Number);
1609
- return new f(e, n);
2059
+ decodeGridId(gridId) {
2060
+ const [i, j] = gridId.split(".").map(Number);
2061
+ return new Point(i, j);
1610
2062
  }
1611
2063
  /**
1612
2064
  * 查询与矩形相交的点
1613
2065
  * @param rectangle 矩形
1614
2066
  * @returns 相交的节点数组
1615
2067
  */
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);
2068
+ queryRect(rectangle) {
2069
+ const box2 = rectangle.toBox();
2070
+ 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);
2071
+ for (let i = minI; i <= maxI; i++) {
2072
+ for (let j = minJ; j <= maxJ; j++) {
2073
+ const id = `${i}.${j}`;
2074
+ if (!this.map.has(id)) continue;
2075
+ const set = this.map.get(id);
2076
+ set?.forEach((item) => {
2077
+ if (rectangle.containsPoint(item.point)) ;
1624
2078
  });
1625
2079
  }
2080
+ }
1626
2081
  }
1627
2082
  /**
1628
2083
  * 查询与圆形区域相交的点
@@ -1630,53 +2085,62 @@ class U {
1630
2085
  * @param radius 半径
1631
2086
  * @returns 相交的节点数组
1632
2087
  */
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);
2088
+ queryCircle(pos, radius) {
2089
+ const box2 = new Box2(pos.x - radius, pos.x + radius, pos.y - radius, pos.y + radius);
2090
+ 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 = [];
2091
+ for (let i = minI; i <= maxI; i++) {
2092
+ for (let j = minJ; j <= maxJ; j++) {
2093
+ const id = `${i}.${j}`;
2094
+ if (!this.map.has(id)) continue;
2095
+ const set = this.map.get(id);
2096
+ set?.forEach((item) => {
2097
+ if (pos.distance(item.point) <= radius) list.push(item);
1641
2098
  });
1642
2099
  }
1643
- return a;
2100
+ }
2101
+ return list;
1644
2102
  }
1645
2103
  /**
1646
2104
  * 查询与包围盒相交的点
1647
2105
  * @param box2 包围盒
1648
2106
  * @returns 相交的节点数组
1649
2107
  */
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);
2108
+ queryBox(box2) {
2109
+ 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 = [];
2110
+ for (let i = minI; i <= maxI; i++) {
2111
+ for (let j = minJ; j <= maxJ; j++) {
2112
+ const id = `${i}.${j}`;
2113
+ if (!this.map.has(id)) continue;
2114
+ const set = this.map.get(id);
2115
+ set?.forEach((item) => {
2116
+ if (box2.containsPoint(item.point)) list.push(item);
1658
2117
  });
1659
2118
  }
1660
- return s;
2119
+ }
2120
+ return list;
1661
2121
  }
1662
2122
  /**
1663
2123
  * 查找相同点
1664
2124
  * @param point
1665
2125
  */
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;
2126
+ queryPoint(point) {
2127
+ const id = this.getGridId(point), list = [];
2128
+ if (this.map.has(id)) {
2129
+ const set = this.map.get(id);
2130
+ set?.forEach((item) => {
2131
+ if (point.equal(item.point)) list.push(item);
2132
+ });
2133
+ }
2134
+ return list;
1671
2135
  }
1672
2136
  }
1673
- class it {
2137
+ class DoorsAnalysis {
1674
2138
  // 所有可查找的点位
1675
2139
  possibleDoorPoints = [];
1676
2140
  doorPoint = [];
1677
2141
  dxf;
1678
2142
  // 包含所有点的虚拟网格
1679
- pointVirtualGrid = new U();
2143
+ pointVirtualGrid = new PointVirtualGrid();
1680
2144
  // 只包含可查找点的虚拟网格
1681
2145
  findPointVirtualGrid;
1682
2146
  quadtree;
@@ -1687,111 +2151,158 @@ class it {
1687
2151
  doorSearchDistance = 2;
1688
2152
  doors = [];
1689
2153
  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();
2154
+ continueFind = true;
2155
+ constructor(lineAnalysis) {
2156
+ this.lineAnalysis = lineAnalysis;
2157
+ this.dxf = lineAnalysis.Dxf;
2158
+ this.findPointVirtualGrid = new PointVirtualGrid();
2159
+ this.quadtree = lineAnalysis.quadtree;
2160
+ this.resultList = lineAnalysis.resultList;
2161
+ this.lineSegments = lineAnalysis.lineSegmentList;
2162
+ this.dxf.doorLineSegment.length = 0;
2163
+ this.lineSegments.forEach((line) => {
2164
+ this.pointVirtualGrid.insert(line.start, line);
2165
+ this.pointVirtualGrid.insert(line.end, line);
2166
+ });
2167
+ this.doorPoint = this.getDoorPoint();
2168
+ if (!this.continueFind) return;
2169
+ const excludeIndexMap = this.searchDoubleLinePoint();
2170
+ this.addPointsExcludeRule((line, _2, pointIndex) => {
2171
+ const index2 = this.lineSegments.indexOf(line);
2172
+ const excludeMode = excludeIndexMap.get(index2);
2173
+ if (typeof excludeMode === "number") {
2174
+ return excludeMode === -1 || excludeMode === pointIndex;
2175
+ }
2176
+ return false;
2177
+ });
2178
+ this.addPointsExcludeRule((_1, point) => {
2179
+ return !!this.doorPoint.find((p1) => p1.point.equal(point));
2180
+ });
2181
+ this.possibleDoorPoints = this.getPossiblePoints();
2182
+ this.possibleDoorPoints.forEach((p) => this.findPointVirtualGrid.insert(p.point, p.line));
2183
+ this.handle();
1700
2184
  }
1701
2185
  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
2186
+ this.dxf.doorLineSegment.push(...this.search(this.doorPoint, this.possibleDoorPoints, 0.5));
2187
+ if (this.doorPoint.length < 2) this.dxf.doorLineSegment.push(...this.search(this.possibleDoorPoints, this.possibleDoorPoints, 0.6));
2188
+ }
2189
+ search(doorPoints, possibleDoorPoints = [], minDoorWidth = 0.6, doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
2190
+ const dxf = this.dxf;
2191
+ const doors = this.searchNearby(doorPoints, possibleDoorPoints, doorSearchDistance, doorSearchNearAngle);
2192
+ doors.push(
2193
+ ...doorPoints.map((item) => {
2194
+ const res2 = this.searchAlongDirection(item, doorSearchDistance);
2195
+ if (res2) return {
2196
+ start: item.point,
2197
+ end: res2.point
1712
2198
  };
1713
- const l = this.searchAlongNormalDirection(c, i);
1714
- if (l) return {
1715
- start: c.point,
1716
- end: l.point
2199
+ const res3 = this.searchAlongNormalDirection(item, doorSearchDistance);
2200
+ if (res3) return {
2201
+ start: item.point,
2202
+ end: res3.point
1717
2203
  };
1718
- }).filter((c) => !!c && c.start.distance(c.end) < i)
2204
+ }).filter((i) => !!i && i.start.distance(i.end) < doorSearchDistance)
1719
2205
  );
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))
2206
+ const doorLineSegment = [];
2207
+ doors.forEach((p) => {
2208
+ const line = new LineSegment(p?.start, p?.end);
2209
+ const len = line.length();
2210
+ if (len < minDoorWidth) return;
2211
+ const normal = line.normal(), direction = line.direction(), step = (len - dxf.width * 2) / 2;
2212
+ for (let i = 0; i < 3; i++) {
2213
+ const point = line.start.clone().add(direction.clone().multiplyScalar(dxf.width + step * i));
2214
+ const rLine = new LineSegment(
2215
+ point,
2216
+ point.clone().add(normal.clone().multiplyScalar(1))
1729
2217
  );
1730
- if (m.directionMove(d, -0.5), this.quadtree.queryLineSegment(m).length) return;
2218
+ rLine.directionMove(normal, -0.5);
2219
+ const res = this.quadtree.queryLineSegment(rLine);
2220
+ if (res.length) return;
1731
2221
  }
1732
- a.push(h);
1733
- }), a;
2222
+ doorLineSegment.push(line);
2223
+ });
2224
+ return doorLineSegment;
1734
2225
  }
1735
2226
  /** 添加可查找点的过滤规则
1736
2227
  * @param rule
1737
2228
  */
1738
- addPointsExcludeRule(t) {
1739
- this._pointsExcludeRule.push(t);
2229
+ addPointsExcludeRule(rule) {
2230
+ this._pointsExcludeRule.push(rule);
1740
2231
  }
1741
2232
  _pointsExcludeRule = [];
1742
2233
  /**
1743
2234
  * 查找所有可能为门的点位
1744
2235
  */
1745
2236
  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() });
2237
+ const doorPoints = [];
2238
+ this.lineSegments.forEach((line) => {
2239
+ line.points.forEach((p, j) => {
2240
+ for (let i = 0; i < this._pointsExcludeRule.length; i++) if (this._pointsExcludeRule[i](line, p, j)) return;
2241
+ const res = this.pointVirtualGrid.queryPoint(p).filter((d) => d.userData !== line);
2242
+ if (res.length === 0) {
2243
+ doorPoints.push({ line, point: p, uuid: uuid() });
2244
+ }
1751
2245
  });
1752
- }), t;
2246
+ });
2247
+ return doorPoints;
1753
2248
  }
1754
2249
  /**
1755
2250
  * 查找已知为门的点位
1756
2251
  */
1757
2252
  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;
1768
- });
1769
- c.length && t.push({
1770
- line: c[0].userData,
1771
- point: r,
1772
- uuid: T()
2253
+ const doorPoints = [], dxf = this.dxf, pointVirtualGrid = this.pointVirtualGrid;
2254
+ dxf.doors.forEach((item) => {
2255
+ const doorLine = dxf.lineSegments[item[4]];
2256
+ const doorData = dxf.originalData[item[4]];
2257
+ if (doorData.drawDoorData) {
2258
+ const point = Point.from(doorData.drawDoorData.start);
2259
+ const direct = Point.from(doorData.drawDoorData.n);
2260
+ const resList = pointVirtualGrid.queryPoint(point).filter((res) => {
2261
+ if (res.userData === doorLine) return false;
2262
+ const line = res.userData;
2263
+ const direct2 = line.direction();
2264
+ if (line.start.equal(point)) direct2.multiplyScalar(-1);
2265
+ const angle = direct.angleBetween(direct2, "angle");
2266
+ return angle > 80 || angle < 10;
1773
2267
  });
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;
2268
+ if (resList.length) {
2269
+ doorPoints.push({
2270
+ line: resList[0].userData,
2271
+ point,
2272
+ uuid: uuid()
2273
+ });
2274
+ }
2275
+ } else if (doorData.doorDirectConnection) {
2276
+ this.continueFind = false;
2277
+ const line = new LineSegment(Point.from(doorData.start), Point.from(doorData.end));
2278
+ line.userData = {
2279
+ doorDirectConnection: true,
2280
+ isDoor: true
2281
+ };
2282
+ this.dxf.doorLineSegment.push(line);
2283
+ } else {
2284
+ console.warn(`门的线段顺序${item[4]} 没有drawDoorData属性`);
2285
+ }
2286
+ });
2287
+ console.log("门点位数量:", doorPoints.length);
2288
+ return doorPoints;
1784
2289
  }
1785
2290
  /**
1786
2291
  * 查找双线墙的点位
1787
2292
  * @returns
1788
2293
  */
1789
2294
  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;
2295
+ const excludeIndexMap = /* @__PURE__ */ new Map();
2296
+ this.resultList.flatMap((p) => {
2297
+ 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;
2298
+ if (excludeIndexMap.has(p.sourceIndex)) {
2299
+ if (excludeIndexMap.get(p.sourceIndex) != mode0) excludeIndexMap.set(p.sourceIndex, -1);
2300
+ } else excludeIndexMap.set(p.sourceIndex, mode0);
2301
+ if (excludeIndexMap.has(p.targetIndex)) {
2302
+ if (excludeIndexMap.get(p.targetIndex) != mode1) excludeIndexMap.set(p.targetIndex, -1);
2303
+ } else excludeIndexMap.set(p.targetIndex, mode1);
2304
+ });
2305
+ return excludeIndexMap;
1795
2306
  }
1796
2307
  /** 查找方案一:最近点查找
1797
2308
  * @description 以点为圆心,查找半径内符合角度的点
@@ -1801,113 +2312,160 @@ class it {
1801
2312
  * @param doorSearchNearAngle 查找的角度
1802
2313
  * @returns
1803
2314
  */
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
- }));
2315
+ searchNearby(doorPoints, possibleDoorPoints = [], doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
2316
+ const findPointVirtualGrid = this.findPointVirtualGrid, quadtree = this.quadtree;
2317
+ function find({ point, line }, doorIndex, record2) {
2318
+ const direct = line.direction();
2319
+ if (line.start === point) direct.multiplyScalar(-1);
2320
+ const res = findPointVirtualGrid.queryCircle(point, doorSearchDistance).filter((r) => r.userData !== line).sort((a, b) => a.point.distance(point) - b.point.distance(point));
2321
+ const list = [];
2322
+ for (let i = 0; i < res.length; i++) {
2323
+ const doorIndex2 = possibleDoorPoints.findIndex((p) => p.point === res[i].point);
2324
+ const id1 = doorPoints[doorIndex].uuid, id2 = possibleDoorPoints[doorIndex2].uuid;
2325
+ if (record2.has(`${id1}.${id2}`)) continue;
2326
+ record2.add(`${id1}.${id2}`);
2327
+ record2.add(`${id2}.${id1}`);
2328
+ const targetPoint = res[i].point, line2 = new LineSegment(point.clone(), targetPoint.clone()), angle = line2.direction().angleBetween(direct, "angle");
2329
+ if (angle < doorSearchNearAngle) {
2330
+ const direct2 = doorPoints[doorIndex2].line.direction();
2331
+ const line22 = res[i].userData;
2332
+ if (line22.start.equal(res[i].point)) direct2.multiplyScalar(-1);
2333
+ const angle2 = line2.direction().multiplyScalar(-1).angleBetween(direct2, "angle");
2334
+ if (angle2 < doorSearchNearAngle) {
2335
+ if (!quadtree.queryLineSegment(line2).length) {
2336
+ list.push({
2337
+ findData: res[i],
2338
+ findUuid: id2,
2339
+ doorLine: line2,
2340
+ doorUuid: id1
2341
+ });
2342
+ }
2343
+ }
1823
2344
  }
1824
2345
  }
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);
2346
+ return list;
2347
+ }
2348
+ function deepSearchNearHandle(uuid2, snFindRecord2, list, record2, other) {
2349
+ record2.add(uuid2);
2350
+ const newList = [];
2351
+ if (other) newList.push(other);
2352
+ for (let i = 0; i < list.length; i++) {
2353
+ const item = list[i];
2354
+ if (snFindRecord2.has(item.findUuid)) {
2355
+ const list2 = snFindRecord2.get(item.findUuid);
2356
+ if (deepSearchNearHandle(item.findUuid, snFindRecord2, list2, record2, item)) newList.push(item);
2357
+ } else newList.push(item);
2358
+ }
2359
+ newList.sort((a, b) => a.doorLine.length() - b.doorLine.length());
2360
+ if (other && newList[0] === other) {
2361
+ list.splice(0);
2362
+ return true;
1837
2363
  }
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);
2364
+ list.splice(1);
2365
+ return false;
2366
+ }
2367
+ const record = /* @__PURE__ */ new Set();
2368
+ const snFindRecord = /* @__PURE__ */ new Map();
2369
+ doorPoints.map((p, index2) => {
2370
+ const list = find(p, index2, record);
2371
+ if (list.length) snFindRecord.set(p.uuid, list);
2372
+ });
2373
+ record.clear();
2374
+ const temMap = /* @__PURE__ */ new Map();
2375
+ snFindRecord.forEach((list, key) => {
2376
+ if (!record.has(key) && list.length) {
2377
+ deepSearchNearHandle(key, snFindRecord, list, record);
2378
+ }
2379
+ if (list.length) {
2380
+ const item = list[0];
2381
+ if (!temMap.has(item.doorUuid)) temMap.set(item.doorUuid, []);
2382
+ temMap.get(item.doorUuid)?.push(item);
2383
+ if (!temMap.has(item.findUuid)) temMap.set(item.findUuid, []);
2384
+ temMap.get(item.findUuid)?.push(item);
1850
2385
  }
1851
2386
  });
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]);
2387
+ const deleteSet = /* @__PURE__ */ new Set();
2388
+ temMap.forEach((list) => {
2389
+ if (list.length > 1) {
2390
+ list.sort((a, b) => a.doorLine.length() - b.doorLine.length());
2391
+ for (let i = 1; i < list.length; i++) deleteSet.add(list[i]);
1857
2392
  }
1858
2393
  });
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));
2394
+ const searchNearRasult = [], removeDoorPointsUuid = [];
2395
+ snFindRecord.forEach((list) => {
2396
+ if (list.length) {
2397
+ const item = list[0];
2398
+ if (!deleteSet.has(item)) {
2399
+ searchNearRasult.push(item);
2400
+ removeDoorPointsUuid.push(item.doorUuid, item.findUuid);
2401
+ }
1864
2402
  }
1865
2403
  });
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
- });
2404
+ const doors = [];
2405
+ searchNearRasult.forEach((item) => {
2406
+ const doorIndex = doorPoints.findIndex((p2) => p2.uuid === item.doorUuid);
2407
+ const findDoorIndex = possibleDoorPoints.findIndex((p2) => p2.uuid === item.findUuid);
2408
+ const start = doorPoints[doorIndex].point.clone();
2409
+ const end = possibleDoorPoints[findDoorIndex].point.clone();
2410
+ const startLine = this.findLongLineSegment(doorPoints[doorIndex].line);
2411
+ const endLine = this.findLongLineSegment(possibleDoorPoints[findDoorIndex].line);
2412
+ const p = startLine.projectPoint(end);
2413
+ if (p) {
2414
+ start.copy(p);
2415
+ const l = new LineSegment(start, end);
2416
+ const angle = endLine.includedAngle(l);
2417
+ if (angle < 10 || angle > 170 || Math.abs(90 - angle) < 10) {
2418
+ doors.push({
2419
+ start,
2420
+ end
2421
+ });
2422
+ }
1876
2423
  } 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
- });
2424
+ const p2 = endLine.projectPoint(start);
2425
+ if (p2) end.copy(p2);
2426
+ const l = new LineSegment(start, end);
2427
+ const angle = startLine.includedAngle(l);
2428
+ if (angle < 10 || angle > 170 || Math.abs(90 - angle) < 10) {
2429
+ doors.push({
2430
+ start,
2431
+ end
2432
+ });
2433
+ }
1884
2434
  }
1885
- }), e.splice(
2435
+ });
2436
+ possibleDoorPoints.splice(
1886
2437
  0,
1887
- e.length,
1888
- ...e.filter((u) => p.indexOf(u.uuid) === -1)
1889
- ), t.splice(
2438
+ possibleDoorPoints.length,
2439
+ ...possibleDoorPoints.filter((p) => removeDoorPointsUuid.indexOf(p.uuid) === -1)
2440
+ );
2441
+ doorPoints.splice(
1890
2442
  0,
1891
- t.length,
1892
- ...t.filter((u) => p.indexOf(u.uuid) === -1)
1893
- ), w;
2443
+ doorPoints.length,
2444
+ ...doorPoints.filter((p) => removeDoorPointsUuid.indexOf(p.uuid) === -1)
2445
+ );
2446
+ return doors;
1894
2447
  }
1895
2448
  /** 方案二: 沿方向查找
1896
2449
  * @description
1897
2450
  * @param param0
1898
2451
  * @returns
1899
2452
  */
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;
2453
+ searchAlongDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
2454
+ const quadtree = this.quadtree;
2455
+ const direct = line.direction();
2456
+ if (line.start === point) direct.multiplyScalar(-1);
2457
+ const endPoint = point.clone().add(direct.clone().multiplyScalar(doorSearchDistance)), rline = new LineSegment(point.clone(), endPoint), result = quadtree.queryLineSegment(rline).map((l) => {
2458
+ const res = l.line.getIntersection(rline);
2459
+ return {
2460
+ point: res,
2461
+ line: l.line
2462
+ };
2463
+ }).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
2464
+ if (result.length) {
2465
+ const item = result[0];
2466
+ if (Math.abs(90 - item.line.direction().angleBetween(direct, "angle")) < 5) {
2467
+ return item;
2468
+ }
1911
2469
  }
1912
2470
  }
1913
2471
  /** 方案三: 沿法线方向查找
@@ -1916,25 +2474,35 @@ class it {
1916
2474
  * @param doorSearchDistance
1917
2475
  * @returns
1918
2476
  */
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);
2477
+ searchAlongNormalDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
2478
+ const pointVirtualGrid = this.pointVirtualGrid, quadtree = this.quadtree, direct = line.direction(), normal = line.start.normal(line.end), prePoint = line.start.clone();
2479
+ if (line.start === point) direct.multiplyScalar(-1);
2480
+ if (line.start === point) prePoint.copy(line.end);
2481
+ const result = pointVirtualGrid.queryPoint(prePoint).filter((r) => r.userData !== line);
2482
+ for (let i = 0; i < result.length; i++) {
2483
+ const element = result[i];
2484
+ const l = element.userData;
2485
+ const d1 = l.direction();
2486
+ if (l.start === element.point) direct.multiplyScalar(-1);
2487
+ const angle = d1.angleBetween(normal) / (Math.PI / 180);
2488
+ if (angle > 90) {
2489
+ normal.multiplyScalar(-1);
1927
2490
  break;
1928
2491
  }
1929
2492
  }
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;
2493
+ const rline3 = new LineSegment(point.clone(), point.clone().add(normal.multiplyScalar(doorSearchDistance)));
2494
+ const r3 = quadtree.queryLineSegment(rline3).map((l) => {
2495
+ const res = l.line.getIntersection(rline3);
2496
+ return {
2497
+ point: res,
2498
+ line: l.line
2499
+ };
2500
+ }).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
2501
+ if (r3.length) {
2502
+ const item = r3[0];
2503
+ if (Math.abs(90 - item.line.direction().angleBetween(normal, "angle")) < 5) {
2504
+ return item;
2505
+ }
1938
2506
  }
1939
2507
  }
1940
2508
  /**
@@ -1942,31 +2510,37 @@ class it {
1942
2510
  * @param line
1943
2511
  * @returns
1944
2512
  */
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);
2513
+ findLongLineSegment(line) {
2514
+ const resLine = line.clone();
2515
+ const res1 = this.pointVirtualGrid.queryPoint(line.start);
2516
+ const res2 = this.pointVirtualGrid.queryPoint(line.end);
2517
+ for (let i = 0; i < res1.length; i++) {
2518
+ const { userData: line2 } = res1[i];
2519
+ if (line2 === line) continue;
2520
+ if (line2 && line2.directionEqual(line)) {
2521
+ if (line2.start.equal(line.start)) resLine.start.copy(line2.end);
2522
+ else resLine.start.copy(line2.start);
1951
2523
  break;
1952
2524
  }
1953
2525
  }
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);
2526
+ for (let i = 0; i < res2.length; i++) {
2527
+ const { userData: line2 } = res2[i];
2528
+ if (line2 === line) continue;
2529
+ if (line2 && line2.directionEqual(line)) {
2530
+ if (line2.end.equal(line.end)) resLine.end.copy(line2.start);
2531
+ else resLine.end.copy(line2.end);
1958
2532
  break;
1959
2533
  }
1960
2534
  }
1961
- return e;
2535
+ return resLine;
1962
2536
  }
1963
2537
  }
1964
- class st extends X {
2538
+ class LineAnalysis extends Component {
1965
2539
  static name = "LineAnalysis";
1966
2540
  Dxf = null;
1967
2541
  Variable = null;
1968
2542
  lineSegmentList = [];
1969
- container = new M.Group();
2543
+ container = new THREE.Group();
1970
2544
  // 误差角度
1971
2545
  errorAngle = 4;
1972
2546
  width = 0.4;
@@ -1974,8 +2548,11 @@ class st extends X {
1974
2548
  *
1975
2549
  * @param parent
1976
2550
  */
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));
2551
+ onAddFromParent(parent) {
2552
+ this.Dxf = parent.findComponentByType(Dxf);
2553
+ this.Variable = this.parent?.findComponentByType(Variable);
2554
+ this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this));
2555
+ this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
1979
2556
  }
1980
2557
  /**
1981
2558
  *
@@ -1984,16 +2561,20 @@ class st extends X {
1984
2561
  * @param width
1985
2562
  * @returns
1986
2563
  */
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;
2564
+ expandLineSegment(p1, p2, width = 0.1) {
2565
+ const normal = p2.normal(p1);
2566
+ const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
2567
+ const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
2568
+ const offsetX = normal.x * width * 0.5;
2569
+ const offsetY = normal.y * width * 0.5;
1989
2570
  return {
1990
2571
  points: [
1991
2572
  // 第一条线
1992
- new f(t.x + r, t.y + a).add(s),
1993
- new f(e.x + r, e.y + a).add(o),
2573
+ new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
2574
+ new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
1994
2575
  // 第二条线
1995
- new f(t.x - r, t.y - a).add(s),
1996
- new f(e.x - r, e.y - a).add(o)
2576
+ new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
2577
+ new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
1997
2578
  ],
1998
2579
  indices: [0, 1, 1, 3, 3, 2, 2, 0],
1999
2580
  rectIndices: [0, 1, 3, 2, 0]
@@ -2005,25 +2586,31 @@ class st extends X {
2005
2586
  * @param p1
2006
2587
  * @param p2
2007
2588
  */
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()));
2589
+ addData(p1, p2) {
2590
+ const dxf = this.Dxf;
2591
+ dxf.data.push([p1.clone(), p2.clone(), [], false, dxf.data.length]);
2592
+ this.appendLineSegmentList.push(new LineSegment(p1.clone(), p2.clone()));
2011
2593
  }
2012
2594
  /** 结果分析创建矩形
2013
2595
  * @param result
2014
2596
  */
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
- }
2597
+ createRectangle(result) {
2598
+ const dxf = this.Dxf;
2599
+ const project0 = result.project, project1 = result.project2;
2600
+ if (project0.includedAngle(project1) > 135) {
2601
+ project1.points = [project1.points[1], project1.points[0]];
2602
+ }
2603
+ this.addData(project0.points[0], project1.points[0]);
2604
+ this.addData(project0.points[1], project1.points[1]);
2605
+ 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);
2606
+ direction.multiplyScalar(dxf.width * 0.5);
2607
+ const _leftP = leftP.clone().add(direction), _rightP = rightP.clone().add(direction.multiplyScalar(-1)), d1 = leftP.direction(rightP), d2 = _leftP.direction(_rightP);
2608
+ 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;
2609
+ leftP.set(_leftP.x, _leftP.y);
2610
+ rightP.set(_rightP.x, _rightP.y);
2611
+ for (let i = 1; i < count; i++) {
2612
+ const left = leftDirection.clone().multiplyScalar(leftFragment * i), right = rightDirection.clone().multiplyScalar(rightFragment * i), p1 = leftP.clone().add(left), p2 = rightP.clone().add(right);
2613
+ this.addData(p1, p2);
2027
2614
  }
2028
2615
  }
2029
2616
  quadtree;
@@ -2031,13 +2618,18 @@ class st extends X {
2031
2618
  * 构建线段四叉树,快速查找,
2032
2619
  */
2033
2620
  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;
2621
+ const dxf = this.Dxf;
2622
+ const lineSegmentList = [];
2623
+ this.quadtree = new Quadtree(dxf.originalBox, 2);
2624
+ dxf.lineSegments.forEach((lineSegment) => {
2625
+ if (lineSegment.userData?.isDoor) return;
2626
+ this.quadtree?.insert({
2627
+ line: lineSegment,
2628
+ userData: lineSegmentList.length
2629
+ });
2630
+ lineSegmentList.push(lineSegment);
2631
+ });
2632
+ this.lineSegmentList = lineSegmentList;
2041
2633
  }
2042
2634
  resultList = [];
2043
2635
  mergeWallLines = [];
@@ -2047,18 +2639,24 @@ class st extends X {
2047
2639
  */
2048
2640
  lineAnalysis() {
2049
2641
  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) => {
2642
+ const quadtree = this.quadtree;
2643
+ const lineSegmentList = this.lineSegmentList;
2644
+ const visited = /* @__PURE__ */ new Set(), resultList = [];
2645
+ lineSegmentList.forEach((_0, i) => {
2646
+ 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);
2647
+ ids.forEach((id) => {
2054
2648
  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 {
2649
+ if (visited.has(`${i}-${id}`) || visited.has(`${id}-${i}`)) return;
2650
+ const res = this.projectionAnalysis(id, i, sourceLineSegment, lineSegmentList);
2651
+ if (res) resultList.push(res);
2652
+ visited.add(`${i}-${id}`);
2653
+ } catch (error) {
2059
2654
  }
2060
2655
  });
2061
- }), this.appendLineSegmentList.length = 0, i.forEach(this.createRectangle.bind(this)), this.resultList = i;
2656
+ });
2657
+ this.appendLineSegmentList.length = 0;
2658
+ resultList.forEach(this.createRectangle.bind(this));
2659
+ this.resultList = resultList;
2062
2660
  }
2063
2661
  /** 线段投影分析
2064
2662
  * @param index
@@ -2066,36 +2664,42 @@ class st extends X {
2066
2664
  * @param lineSegmentList
2067
2665
  * @returns
2068
2666
  */
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;
2667
+ projectionAnalysis(index2, sourceIndex, sourceLineSegment, lineSegmentList) {
2668
+ const temLineSegment = lineSegmentList[index2], direct = sourceLineSegment.direction(), temDirect = temLineSegment.direction(), angle = direct.angleBetween(temDirect) / (Math.PI / 180);
2669
+ if (angle < this.errorAngle || angle > 180 - this.errorAngle) {
2670
+ let data;
2671
+ const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment);
2672
+ if (p1.getLength() > p2.getLength()) {
2673
+ data = {
2674
+ target: temLineSegment,
2675
+ targetIndex: index2,
2676
+ source: sourceLineSegment,
2677
+ sourceIndex,
2678
+ project: p1,
2679
+ project2: p2
2680
+ };
2681
+ } else {
2682
+ data = {
2683
+ target: sourceLineSegment,
2684
+ targetIndex: sourceIndex,
2685
+ source: temLineSegment,
2686
+ sourceIndex: index2,
2687
+ project: p2,
2688
+ project2: p1
2689
+ };
2690
+ }
2691
+ if (!data || data.project.getLength() < 0.2 || data.project2.getLength() < 0.2) return;
2692
+ return data;
2089
2693
  }
2090
2694
  }
2091
2695
  doorSearchNearAngle = 110;
2092
2696
  doorSearchDistance = 2;
2093
2697
  doors = [];
2094
2698
  doorsAnalysis() {
2095
- new it(this);
2699
+ new DoorsAnalysis(this);
2096
2700
  }
2097
2701
  }
2098
- class ot extends et {
2702
+ class DxfSystem extends ComponentManager {
2099
2703
  Dxf;
2100
2704
  Variable;
2101
2705
  wallWidth;
@@ -2104,87 +2708,116 @@ class ot extends et {
2104
2708
  * @param wallWidth 输出墙壁厚度,该墙壁厚度不受缩放影响
2105
2709
  * @param scale 原始数据缩放比例
2106
2710
  */
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());
2711
+ constructor(wallWidth = 0.1, scale = 1) {
2712
+ super();
2713
+ this.environment = typeof window !== "undefined" ? "browser" : typeof global !== "undefined" ? "node" : "unknown";
2714
+ this.wallWidth = wallWidth;
2715
+ this.Dxf = new Dxf(this.wallWidth, scale);
2716
+ this.Variable = new Variable();
2717
+ this.addComponent(this.Variable);
2718
+ this.addComponent(this.Dxf);
2719
+ this.addComponent(new LineAnalysis());
2109
2720
  }
2110
- usePlugin(t) {
2111
- return typeof t == "function" && t.call(this, this), this;
2721
+ usePlugin(plugin) {
2722
+ if (typeof plugin === "function") plugin.call(this, this);
2723
+ return this;
2112
2724
  }
2113
2725
  destroy() {
2114
- [...this.components].forEach((t) => {
2115
- t.destroy();
2116
- }), [...this.components].forEach((t) => {
2117
- this.removeComponent(t);
2726
+ [...this.components].forEach((com) => {
2727
+ com.destroy();
2728
+ });
2729
+ [...this.components].forEach((com) => {
2730
+ this.removeComponent(com);
2118
2731
  });
2119
2732
  }
2120
2733
  }
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;
2734
+ const exporter = new OBJExporter();
2735
+ const glbExporter = new GLTFExporter();
2736
+ function lineSqueezing(p1, p2, width = 0.1) {
2737
+ const normal = p2.normal(p1);
2738
+ const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
2739
+ const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
2740
+ const offsetX = normal.x * width * 0.5;
2741
+ const offsetY = normal.y * width * 0.5;
2124
2742
  return {
2125
2743
  points: [
2126
2744
  // 第一条线
2127
- new f(g.x + s, g.y + r).add(o),
2128
- new f(t.x + s, t.y + r).add(i),
2745
+ new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
2746
+ new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
2129
2747
  // 第二条线
2130
- new f(g.x - s, g.y - r).add(o),
2131
- new f(t.x - s, t.y - r).add(i)
2748
+ new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
2749
+ new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
2132
2750
  ],
2133
2751
  indices: [0, 1, 1, 3, 3, 2, 2, 0],
2134
2752
  rectIndices: [0, 1, 3, 2, 0]
2135
2753
  };
2136
2754
  }
2137
- class J extends X {
2755
+ class WhiteModel extends Component {
2138
2756
  static name = "WhiteModel";
2139
2757
  Dxf = null;
2140
2758
  Variable = null;
2141
2759
  // dxf数据白模
2142
- whiteModelGroup = new M.Group();
2760
+ whiteModelGroup = new THREE.Group();
2143
2761
  // dxf数据白模边缘线
2144
- whiteModelLineGroup = new M.Group();
2762
+ whiteModelLineGroup = new THREE.Group();
2145
2763
  // 原始数据白模
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", () => {
2764
+ originalWhiteMode = new THREE.Group();
2765
+ material = new THREE.MeshBasicMaterial({ color: 16777215, transparent: true, opacity: 0.8, side: THREE.DoubleSide });
2766
+ onAddFromParent(parent) {
2767
+ this.Dxf = parent.findComponentByName("Dxf");
2768
+ this.Variable = parent.findComponentByName("Variable");
2769
+ this.originalWhiteMode.visible = false;
2770
+ this.Dxf?.addEventListener("lineOffset", () => {
2150
2771
  this.updateModel();
2151
2772
  });
2152
2773
  }
2153
2774
  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, {
2775
+ this.Variable?.set("whiteModelVisible", false);
2776
+ const dxf = this.Dxf;
2777
+ this.originalWhiteMode.clear();
2778
+ this.whiteModelGroup.clear();
2779
+ this.whiteModelLineGroup.clear();
2780
+ this.whiteModelGroup.add(this.whiteModelLineGroup);
2781
+ this.whiteModelGroup.position.z = dxf.originalZAverage;
2782
+ this.originalWhiteMode.position.z = dxf.originalZAverage;
2783
+ dxf.wallsGroup.forEach((points) => {
2784
+ const shape = new THREE.Shape();
2785
+ 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));
2786
+ const geometry = new THREE.ExtrudeGeometry(shape, {
2160
2787
  depth: 2.8,
2161
2788
  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 }))
2789
+ });
2790
+ const mesh = new THREE.Mesh(geometry, this.material);
2791
+ this.whiteModelGroup.add(mesh);
2792
+ this.whiteModelLineGroup.add(
2793
+ new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({ color: 0 }))
2165
2794
  );
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);
2795
+ });
2796
+ const walls = dxf.originalData.map(({ start, end, insetionArr }) => {
2797
+ 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
2798
  return {
2169
- points: a,
2170
- indices: c,
2171
- rectIndices: h,
2172
- insetions: (o ?? []).map((l) => l.index)
2799
+ points,
2800
+ indices,
2801
+ rectIndices,
2802
+ insetions: (insetionArr ?? []).map((insetion) => insetion.index)
2173
2803
  };
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);
2804
+ });
2805
+ walls.forEach((wall) => {
2806
+ const shape = new THREE.Shape();
2807
+ wall.rectIndices.forEach((index2, i) => {
2808
+ const p = wall.points[index2];
2809
+ if (i === 0) shape.moveTo(p.x, p.y);
2810
+ else shape.lineTo(p.x, p.y);
2179
2811
  });
2180
- const o = new M.ExtrudeGeometry(i, {
2812
+ const geometry = new THREE.ExtrudeGeometry(shape, {
2181
2813
  depth: 2.8,
2182
2814
  bevelSize: 0
2183
2815
  });
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({
2816
+ if (geometry.attributes.position.array.filter((num) => Number.isNaN(num)).length) return;
2817
+ const mesh = new THREE.Mesh(geometry);
2818
+ this.originalWhiteMode?.add(mesh);
2819
+ });
2820
+ this.dispatchEvent({
2188
2821
  type: "updateModel",
2189
2822
  originalWhiteMode: this.originalWhiteMode,
2190
2823
  whiteModelGroup: this.whiteModelGroup
@@ -2195,9 +2828,13 @@ class J extends X {
2195
2828
  * @returns
2196
2829
  */
2197
2830
  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;
2831
+ return new Promise((resolve) => {
2832
+ this.material.opacity = 1;
2833
+ this.material.needsUpdate = true;
2834
+ setTimeout(() => {
2835
+ resolve(exporter.parse(this.whiteModelGroup));
2836
+ this.material.opacity = 0.8;
2837
+ this.material.transparent = true;
2201
2838
  }, 20);
2202
2839
  });
2203
2840
  }
@@ -2206,28 +2843,38 @@ class J extends X {
2206
2843
  * @param binary
2207
2844
  * @returns
2208
2845
  */
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;
2846
+ toGltf(binary = true) {
2847
+ return new Promise((resolve) => {
2848
+ this.material.opacity = 1;
2849
+ this.material.needsUpdate = true;
2850
+ setTimeout(async () => {
2851
+ if (typeof window === "object") {
2852
+ glbExporter.parse(this.whiteModelGroup.children, (gltf) => {
2853
+ resolve(gltf);
2854
+ this.material.opacity = 0.8;
2855
+ this.material.transparent = true;
2215
2856
  }, () => {
2216
- e(void 0);
2857
+ resolve(void 0);
2217
2858
  }, {
2218
- binary: t
2859
+ binary
2219
2860
  });
2220
- else if (typeof global != "function")
2861
+ } else if (typeof global !== "function") {
2221
2862
  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
2863
+ const obj2gltf = await include("obj2gltf", true);
2864
+ const fs = await include("fs", false);
2865
+ const obj = await this.toOBJ();
2866
+ fs.writeFileSync(this.uuid, obj);
2867
+ const result = await obj2gltf(this.uuid, {
2868
+ binary
2226
2869
  });
2227
- i.unlinkSync(this.uuid), e(t ? s : JSON.stringify(s));
2228
- } catch (n) {
2229
- e(void 0), console.log(n);
2870
+ fs.unlinkSync(this.uuid);
2871
+ if (binary) resolve(result);
2872
+ else resolve(JSON.stringify(result));
2873
+ } catch (error) {
2874
+ resolve(void 0);
2875
+ console.log(error);
2230
2876
  }
2877
+ }
2231
2878
  }, 20);
2232
2879
  });
2233
2880
  }
@@ -2236,33 +2883,40 @@ class J extends X {
2236
2883
  * @returns
2237
2884
  */
2238
2885
  async toOBJBlob() {
2239
- const t = await this.toOBJ();
2240
- if (t)
2241
- return new Blob([t], { type: "application/octet-stream" });
2886
+ const buffer = await this.toOBJ();
2887
+ if (buffer) {
2888
+ return new Blob([buffer], { type: "application/octet-stream" });
2889
+ }
2242
2890
  }
2243
2891
  /**
2244
2892
  * 转为 GltfBlob
2245
2893
  * @returns
2246
2894
  */
2247
- async toGltfBlob(t = !0) {
2248
- const e = await this.toGltf(t);
2249
- if (e)
2250
- return new Blob([e], { type: "application/octet-stream" });
2895
+ async toGltfBlob(binary = true) {
2896
+ const buffer = await this.toGltf(binary);
2897
+ if (buffer) {
2898
+ return new Blob([buffer], { type: "application/octet-stream" });
2899
+ }
2251
2900
  }
2252
2901
  /**
2253
2902
  * 下载 OBJ
2254
2903
  * @param filename
2255
2904
  * @returns
2256
2905
  */
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);
2906
+ async downloadOBJ(filename) {
2907
+ if (typeof window !== "undefined") {
2908
+ const blob = await this.toOBJBlob();
2909
+ if (!blob) return;
2910
+ const a = document.createElement("a");
2911
+ a.href = URL.createObjectURL(blob);
2912
+ a.download = filename;
2913
+ a.click();
2914
+ } else if (typeof global !== "undefined") {
2915
+ const buffer = await this.toOBJ();
2916
+ if (buffer) {
2917
+ const fs = await include("fs", false);
2918
+ fs.writeFileSync(filename, buffer);
2919
+ }
2266
2920
  }
2267
2921
  }
2268
2922
  /**
@@ -2270,19 +2924,24 @@ class J extends X {
2270
2924
  * @param filename
2271
2925
  * @returns
2272
2926
  */
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));
2927
+ async downloadGltf(filename, binary = true) {
2928
+ if (typeof window !== "undefined") {
2929
+ const blob = await this.toGltfBlob(binary);
2930
+ if (!blob) return;
2931
+ const a = document.createElement("a");
2932
+ a.href = URL.createObjectURL(blob);
2933
+ a.download = filename;
2934
+ a.click();
2935
+ } else if (typeof global !== "undefined") {
2936
+ const buffer = await this.toGltf(binary);
2937
+ if (buffer) {
2938
+ const fs = await include("fs", false);
2939
+ fs.writeFileSync(filename, binary ? buffer : Buffer.from(buffer));
2940
+ }
2282
2941
  }
2283
2942
  }
2284
2943
  }
2285
- class _ extends X {
2944
+ class DetailsPoint extends Component {
2286
2945
  static name = "DetailsPoint";
2287
2946
  Dxf = null;
2288
2947
  WhiteModel = null;
@@ -2290,8 +2949,10 @@ class _ extends X {
2290
2949
  desPoints = [];
2291
2950
  raylines = [];
2292
2951
  data = [];
2293
- onAddFromParent(t) {
2294
- this.Dxf = t.findComponentByName("Dxf"), this.Variable = t.findComponentByName("Variable"), this.Dxf?.addEventListener("setDta", () => {
2952
+ onAddFromParent(parent) {
2953
+ this.Dxf = parent.findComponentByName("Dxf");
2954
+ this.Variable = parent.findComponentByName("Variable");
2955
+ this.Dxf?.addEventListener("setDta", () => {
2295
2956
  this.updateModel();
2296
2957
  });
2297
2958
  }
@@ -2299,29 +2960,37 @@ class _ extends X {
2299
2960
  * 设置值
2300
2961
  * @param data
2301
2962
  */
2302
- async set(t) {
2303
- if (typeof t == "string")
2304
- if (typeof global < "u") {
2305
- const { default: n } = await import(
2963
+ async set(data) {
2964
+ if (typeof data === "string") {
2965
+ if (typeof global !== "undefined") {
2966
+ const packageName = "fs";
2967
+ const { default: fs } = await import(
2306
2968
  /* @vite-ignore */
2307
- "fs"
2308
- ), i = n.readFileSync(t), o = JSON.parse(i.toString("utf-8"));
2309
- this.set(o);
2969
+ packageName
2970
+ );
2971
+ const buffer = fs.readFileSync(data);
2972
+ const json = JSON.parse(buffer.toString("utf-8"));
2973
+ this.set(json);
2310
2974
  return;
2311
- } else
2975
+ } else {
2312
2976
  throw new Error("非node环境不允许使用路径");
2313
- this.data = t, this.updateModel();
2977
+ }
2978
+ }
2979
+ this.data = data;
2980
+ this.updateModel();
2314
2981
  }
2315
2982
  /**
2316
2983
  * 设置射线辅助
2317
2984
  */
2318
- racasterHelper(t, e, n) {
2985
+ racasterHelper(position, direction, far) {
2319
2986
  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))
2987
+ position.clone(),
2988
+ position.clone().add(direction.clone().multiplyScalar(far))
2989
+ ]);
2990
+ direction.z = 0;
2991
+ this.raylines.push([
2992
+ position.clone(),
2993
+ position.clone().add(direction.clone().multiplyScalar(far))
2325
2994
  ]);
2326
2995
  }
2327
2996
  _timer = null;
@@ -2329,133 +2998,161 @@ class _ extends X {
2329
2998
  * 更新模型
2330
2999
  */
2331
3000
  updateModel() {
2332
- this._timer && clearTimeout(this._timer), this._timer = setTimeout(() => {
3001
+ if (this._timer) clearTimeout(this._timer);
3002
+ this._timer = setTimeout(() => {
2333
3003
  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];
3004
+ const whiteModel = this.parent?.findComponentByName("WhiteModel");
3005
+ this.raylines.length = 0;
3006
+ this.desPoints.length = 0;
3007
+ this.data.forEach((item) => {
3008
+ const position = new THREE.Vector3(
3009
+ item.position.x,
3010
+ item.position.y,
3011
+ item.position.z
3012
+ );
3013
+ const direction = new THREE.Vector3(
3014
+ item.direction.x,
3015
+ item.direction.y,
3016
+ item.direction.z
3017
+ );
3018
+ const far = 100;
3019
+ this.racasterHelper(position, direction, far);
3020
+ direction.z = 0;
3021
+ const raycaster = new THREE.Raycaster(position, direction, 0, far);
3022
+ const list = raycaster.intersectObject(whiteModel.originalWhiteMode);
3023
+ if (list.length) {
3024
+ const { point } = list[0];
2349
3025
  this.desPoints.push({
2350
- message: e.desc,
2351
- position: n,
2352
- intersection: a
3026
+ message: item.desc,
3027
+ position,
3028
+ intersection: point
2353
3029
  });
2354
3030
  }
2355
- }), this.dispatchEvent({
3031
+ });
3032
+ this.dispatchEvent({
2356
3033
  type: "handleSuccess",
2357
3034
  desPoints: this.desPoints
2358
3035
  });
2359
3036
  }, 50);
2360
3037
  }
2361
3038
  }
2362
- class H extends X {
3039
+ class DxfLineModel extends Component {
2363
3040
  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());
3041
+ dxfLineModel = new THREE.LineSegments();
3042
+ dxfDoorsLineModel = new THREE.LineSegments();
3043
+ dxfModelGroup = new THREE.Group();
3044
+ onAddFromParent(parent) {
3045
+ const dxf = parent.findComponentByName("Dxf");
3046
+ this.dxfModelGroup.add(this.dxfLineModel);
3047
+ this.dxfModelGroup.add(this.dxfDoorsLineModel);
3048
+ this.dxfDoorsLineModel.material = new THREE.LineBasicMaterial({ color: 16776960, vertexColors: true });
3049
+ dxf?.addEventListener("lineOffset", () => this.updateMode());
2370
3050
  }
2371
3051
  updateMode() {
2372
- const t = this.parent?.findComponentByName("Dxf");
3052
+ const dxf = this.parent?.findComponentByName("Dxf");
2373
3053
  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({
3054
+ const dxfArray = dxf.to3DArray(1 / dxf.scale, 0);
3055
+ this.dxfLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(dxfArray, 3, true));
3056
+ const doorsArray = new Float32Array(
3057
+ dxf.doorLineSegment.flatMap(({ start, end }) => [start.x, start.y, 0, end.x, end.y, 0])
3058
+ ).map((n) => n / dxf.scale);
3059
+ const doorsColorArray = new Float32Array(dxf.doorLineSegment.flatMap(() => [1, 0, 0, 0, 1, 0]));
3060
+ this.dxfDoorsLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(doorsArray, 3, true)).setAttribute("color", new THREE.BufferAttribute(doorsColorArray, 3));
3061
+ this.dxfModelGroup.position.z = dxf.originalZAverage;
3062
+ this.dispatchEvent({
2380
3063
  type: "modelUpdate",
2381
3064
  model: this.dxfModelGroup
2382
3065
  });
2383
3066
  }
2384
3067
  }
2385
- const ht = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3068
+ const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2386
3069
  __proto__: null,
2387
- DetailsPoint: _,
2388
- DxfLineModel: H,
2389
- WhiteModel: J
3070
+ DetailsPoint,
3071
+ DxfLineModel,
3072
+ WhiteModel
2390
3073
  }, Symbol.toStringTag, { value: "Module" }));
2391
- function W(g, t = {}) {
3074
+ function ModelDataPlugin_(dxfSystem, option = {}) {
2392
3075
  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 _());
3076
+ detailsPoint = true,
3077
+ whiteModel = true,
3078
+ dxfLineModel = true
3079
+ } = option;
3080
+ dxfLineModel && dxfSystem.addComponent(new DxfLineModel());
3081
+ whiteModel && dxfSystem.addComponent(new WhiteModel());
3082
+ detailsPoint && dxfSystem.addComponent(new DetailsPoint());
2398
3083
  }
2399
- const lt = Object.assign(W, {
2400
- create(g = {}) {
2401
- return (t) => W(t, g);
3084
+ const ModelDataPlugin = Object.assign(ModelDataPlugin_, {
3085
+ create(option = {}) {
3086
+ return (dxfSystem) => ModelDataPlugin_(dxfSystem, option);
2402
3087
  }
2403
- }), dt = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
3088
+ });
3089
+ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
2404
3090
  __proto__: null,
2405
- ModelDataPlugin: lt,
2406
- components: ht
3091
+ ModelDataPlugin,
3092
+ components: index$1
2407
3093
  }, Symbol.toStringTag, { value: "Module" }));
2408
- function ut() {
3094
+ function loadRenderPlugin() {
2409
3095
  return import("./index2.js");
2410
3096
  }
2411
- function ft() {
3097
+ function loadEditorPlugin() {
2412
3098
  return import("./index3.js");
2413
3099
  }
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)
3100
+ let gloabalDxfSystem = null;
3101
+ async function createEditor(dom, camera, orbitControls = false, viewPermission) {
3102
+ const mp = await Promise.resolve().then(() => index);
3103
+ const rp = await loadRenderPlugin();
3104
+ const editor = await loadEditorPlugin();
3105
+ const dxfSystem = new DxfSystem().usePlugin(mp.ModelDataPlugin.create({
3106
+ detailsPoint: false,
3107
+ whiteModel: true
3108
+ })).usePlugin(rp.RenderPlugin.create({
3109
+ originalLine: false,
3110
+ modelData: false,
3111
+ detailsPoint: false,
3112
+ orbitControls,
3113
+ camera
3114
+ })).usePlugin(editor.Editor.create({ viewPermission }));
3115
+ const domContainer = dxfSystem.findComponentByType(rp.components.DomContainer);
3116
+ domContainer && dom.appendChild(domContainer.domElement);
3117
+ gloabalDxfSystem = dxfSystem;
3118
+ return {
3119
+ dxfSystem,
3120
+ getFileAll: () => getFileAll(dxfSystem)
2429
3121
  };
2430
3122
  }
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" });
3123
+ async function getFileAll(dxfSystem = gloabalDxfSystem) {
3124
+ const whiteModel = dxfSystem.findComponentByName("WhiteModel");
3125
+ const dxf = new File([dxfSystem.Dxf.toDxfBlob()], "dxf.dxf", { type: "application/dxf" });
3126
+ const obj = new File([await whiteModel.toOBJBlob()], "model.obj", { type: "application/octet-stream" });
3127
+ const glb = new File([await whiteModel.toGltfBlob(true)], "model.glb", { type: "application/octet-stream" });
3128
+ const gltf = new File([await whiteModel.toGltfBlob(false)], "model.gltf", { type: "application/json" });
3129
+ const json = new File([JSON.stringify(dxfSystem.Dxf.originalData)], "json.json", { type: "application/json" });
2433
3130
  return {
2434
- dxf: e,
2435
- obj: n,
2436
- glb: i,
2437
- gltf: o,
2438
- json: s
3131
+ dxf,
3132
+ obj,
3133
+ glb,
3134
+ gltf,
3135
+ json
2439
3136
  };
2440
3137
  }
2441
- function bt() {
2442
- return O;
3138
+ function getGlobalDxfSystem() {
3139
+ return gloabalDxfSystem;
2443
3140
  }
2444
3141
  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
3142
+ Box2 as B,
3143
+ Component as C,
3144
+ DxfSystem as D,
3145
+ EventDispatcher as E,
3146
+ LineSegment as L,
3147
+ ModelDataPlugin as M,
3148
+ Point as P,
3149
+ Quadtree as Q,
3150
+ Variable as V,
3151
+ WhiteModel as W,
3152
+ DetailsPoint as a,
3153
+ PointVirtualGrid as b,
3154
+ createEditor as c,
3155
+ getGlobalDxfSystem as d,
3156
+ getFileAll as g,
3157
+ index$1 as i
2461
3158
  };