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