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