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