build-dxf 0.1.12 → 0.1.14
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/package.json +1 -1
- package/src/build.js +538 -419
- package/src/constants.d.ts +1 -0
- package/src/index3.js +1 -0
- package/src/utils/DxfSystem/components/Dxf.d.ts +15 -19
- package/src/utils/DxfSystem/type.d.ts +18 -1
- package/src/utils/DxfSystem/utils/HeightQuery.d.ts +9 -0
- package/src/utils/LineSegment.d.ts +8 -0
- package/src/utils/modelScenario/scenario.d.ts +9 -6
package/src/build.js
CHANGED
|
@@ -8,6 +8,7 @@ import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
|
8
8
|
import { GLTFExporter } from "three/addons/exporters/GLTFExporter.js";
|
|
9
9
|
const VITE_OSS_BASEURL = "https://image.cnyang.cn/common-assets/".endsWith("/") ? "https://image.cnyang.cn/common-assets/" : "https://image.cnyang.cn/common-assets//";
|
|
10
10
|
const DEFAULT_WALL_WIDTH = 0.12;
|
|
11
|
+
const DEFAULT_WALL_HEIGHT = 2.8;
|
|
11
12
|
const DEFAULT_DOOR_HEIGHT = 2.1;
|
|
12
13
|
const DOOR_GROUND_CLEARANCE_HEIGHT = 0;
|
|
13
14
|
const DEFAULT_WINDOW_HEIGHT = 0.8;
|
|
@@ -170,20 +171,20 @@ class PointVirtualGrid {
|
|
|
170
171
|
* @param point
|
|
171
172
|
* @param userData
|
|
172
173
|
*/
|
|
173
|
-
insert(
|
|
174
|
-
if (!
|
|
174
|
+
insert(point2, userData) {
|
|
175
|
+
if (!point2 || isNaN(point2.x) || isNaN(point2.y)) {
|
|
175
176
|
console.error("无效的点坐标");
|
|
176
177
|
return;
|
|
177
178
|
}
|
|
178
|
-
if (
|
|
179
|
-
const id = this.getGridId(
|
|
179
|
+
if (point2.currentData[this.id]) this.remove(point2);
|
|
180
|
+
const id = this.getGridId(point2);
|
|
180
181
|
if (!this.map.has(id)) this.map.set(id, /* @__PURE__ */ new Set());
|
|
181
182
|
const set2 = this.map.get(id);
|
|
182
|
-
const target = { point, userData };
|
|
183
|
+
const target = { point: point2, userData };
|
|
183
184
|
set2.add(target);
|
|
184
185
|
const opt = { set: set2, target, id };
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
point2.currentData.pointVirtualGrid = opt;
|
|
187
|
+
point2.currentData[this.id] = opt;
|
|
187
188
|
return this;
|
|
188
189
|
}
|
|
189
190
|
/**
|
|
@@ -191,29 +192,29 @@ class PointVirtualGrid {
|
|
|
191
192
|
* @param points
|
|
192
193
|
*/
|
|
193
194
|
insertBatch(points) {
|
|
194
|
-
for (const { point, userData } of points) {
|
|
195
|
-
this.insert(
|
|
195
|
+
for (const { point: point2, userData } of points) {
|
|
196
|
+
this.insert(point2, userData);
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
199
|
/** 移除点
|
|
199
200
|
* @param point
|
|
200
201
|
*/
|
|
201
|
-
remove(
|
|
202
|
-
if (
|
|
203
|
-
const { target, set: set2, id } =
|
|
202
|
+
remove(point2) {
|
|
203
|
+
if (point2.currentData[this.id]) {
|
|
204
|
+
const { target, set: set2, id } = point2.currentData[this.id];
|
|
204
205
|
if (set2) {
|
|
205
206
|
set2.delete(target);
|
|
206
|
-
delete
|
|
207
|
-
delete
|
|
207
|
+
delete point2?.userData?.pointVirtualGridMap;
|
|
208
|
+
delete point2.currentData[this.id];
|
|
208
209
|
if (set2.size === 0) this.map.delete(id);
|
|
209
210
|
}
|
|
210
211
|
}
|
|
211
212
|
return this;
|
|
212
213
|
}
|
|
213
|
-
update(
|
|
214
|
-
const { target, set: set2 } =
|
|
214
|
+
update(point2) {
|
|
215
|
+
const { target, set: set2 } = point2.currentData[this.id];
|
|
215
216
|
if (!target) return false;
|
|
216
|
-
const id = this.getGridId(
|
|
217
|
+
const id = this.getGridId(point2);
|
|
217
218
|
let newSet = this.map.get(id);
|
|
218
219
|
if (newSet === set2) return false;
|
|
219
220
|
set2.delete(target);
|
|
@@ -222,8 +223,8 @@ class PointVirtualGrid {
|
|
|
222
223
|
this.map.set(id, newSet);
|
|
223
224
|
}
|
|
224
225
|
newSet.add(target);
|
|
225
|
-
|
|
226
|
-
|
|
226
|
+
point2.currentData[this.id].set = newSet;
|
|
227
|
+
point2.currentData[this.id].id = id;
|
|
227
228
|
return true;
|
|
228
229
|
}
|
|
229
230
|
/**
|
|
@@ -231,8 +232,8 @@ class PointVirtualGrid {
|
|
|
231
232
|
* @param point
|
|
232
233
|
* @returns
|
|
233
234
|
*/
|
|
234
|
-
getGridId(
|
|
235
|
-
const i = Math.ceil(
|
|
235
|
+
getGridId(point2) {
|
|
236
|
+
const i = Math.ceil(point2.x / this.gridSize), j = Math.ceil(point2.y / this.gridSize);
|
|
236
237
|
return `${i}.${j}`;
|
|
237
238
|
}
|
|
238
239
|
/**
|
|
@@ -320,18 +321,18 @@ class PointVirtualGrid {
|
|
|
320
321
|
* 查找相同点
|
|
321
322
|
* @param point
|
|
322
323
|
*/
|
|
323
|
-
queryPoint(
|
|
324
|
+
queryPoint(point2, excludeOneself = false) {
|
|
324
325
|
const list = new PvgList();
|
|
325
326
|
let set2;
|
|
326
|
-
if (
|
|
327
|
-
set2 =
|
|
327
|
+
if (point2.currentData[this.id]) {
|
|
328
|
+
set2 = point2.currentData[this.id]?.set;
|
|
328
329
|
} else {
|
|
329
|
-
const id = this.getGridId(
|
|
330
|
+
const id = this.getGridId(point2);
|
|
330
331
|
if (this.map.has(id)) set2 = this.map.get(id);
|
|
331
332
|
}
|
|
332
333
|
set2?.forEach((item) => {
|
|
333
|
-
if (
|
|
334
|
-
if (excludeOneself &&
|
|
334
|
+
if (point2.equal(item.point)) {
|
|
335
|
+
if (excludeOneself && point2 === item.point) return;
|
|
335
336
|
list.push(item);
|
|
336
337
|
}
|
|
337
338
|
});
|
|
@@ -349,9 +350,9 @@ class PointVirtualGrid {
|
|
|
349
350
|
* 查找点自己
|
|
350
351
|
* @param point
|
|
351
352
|
*/
|
|
352
|
-
queryPointSelf(
|
|
353
|
-
if (
|
|
354
|
-
const { target } =
|
|
353
|
+
queryPointSelf(point2) {
|
|
354
|
+
if (point2.currentData[this.id]) {
|
|
355
|
+
const { target } = point2.currentData[this.id];
|
|
355
356
|
return target;
|
|
356
357
|
}
|
|
357
358
|
return null;
|
|
@@ -496,16 +497,16 @@ class Rectangle {
|
|
|
496
497
|
if (line.points.length !== 2) {
|
|
497
498
|
throw new Error("LineSegment must have exactly 2 points");
|
|
498
499
|
}
|
|
499
|
-
const isPointInRectangle = (
|
|
500
|
+
const isPointInRectangle = (point2) => {
|
|
500
501
|
let sign = 0;
|
|
501
502
|
for (let i = 0; i < 4; i++) {
|
|
502
503
|
const p1 = this.points[i];
|
|
503
504
|
const p2 = this.points[(i + 1) % 4];
|
|
504
505
|
const edge = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
505
|
-
const toPoint = { x:
|
|
506
|
+
const toPoint = { x: point2.x - p1.x, y: point2.y - p1.y };
|
|
506
507
|
const cross = edge.x * toPoint.y - edge.y * toPoint.x;
|
|
507
508
|
if (cross === 0) {
|
|
508
|
-
const t = edge.x !== 0 ? (
|
|
509
|
+
const t = edge.x !== 0 ? (point2.x - p1.x) / edge.x : (point2.y - p1.y) / edge.y;
|
|
509
510
|
if (t >= 0 && t <= 1) return true;
|
|
510
511
|
} else {
|
|
511
512
|
const currentSign = cross > 0 ? 1 : -1;
|
|
@@ -536,7 +537,7 @@ class Rectangle {
|
|
|
536
537
|
axes.push(p1.normal(p2));
|
|
537
538
|
}
|
|
538
539
|
function projectRectangle(rect, axis) {
|
|
539
|
-
const projections = rect.points.map((
|
|
540
|
+
const projections = rect.points.map((point2) => point2.dot(axis));
|
|
540
541
|
return [Math.min(...projections), Math.max(...projections)];
|
|
541
542
|
}
|
|
542
543
|
function isProjectionOverlap(proj1, proj2) {
|
|
@@ -555,13 +556,13 @@ class Rectangle {
|
|
|
555
556
|
* 判断点是否完全位于矩形内部
|
|
556
557
|
* @param point
|
|
557
558
|
*/
|
|
558
|
-
containsPoint(
|
|
559
|
+
containsPoint(point2) {
|
|
559
560
|
let positiveCount = 0;
|
|
560
561
|
let negativeCount = 0;
|
|
561
562
|
for (let i = 0; i < 4; i++) {
|
|
562
563
|
const p1 = this.points[i];
|
|
563
564
|
const p2 = this.points[(i + 1) % 4];
|
|
564
|
-
const cross = (p2.x - p1.x) * (
|
|
565
|
+
const cross = (p2.x - p1.x) * (point2.y - p1.y) - (p2.y - p1.y) * (point2.x - p1.x);
|
|
565
566
|
if (cross > 0) positiveCount++;
|
|
566
567
|
else if (cross < 0) negativeCount++;
|
|
567
568
|
else return false;
|
|
@@ -828,17 +829,17 @@ class Quadtree {
|
|
|
828
829
|
* @param point 圆心
|
|
829
830
|
* @returns 相交的节点数组
|
|
830
831
|
*/
|
|
831
|
-
queryPoint(
|
|
832
|
+
queryPoint(point2) {
|
|
832
833
|
const result = [];
|
|
833
|
-
if (
|
|
834
|
+
if (point2.x < this.bounds.minX || point2.x > this.bounds.maxX || point2.y < this.bounds.minY || point2.y > this.bounds.maxY) {
|
|
834
835
|
return result;
|
|
835
836
|
}
|
|
836
837
|
for (const node of this.nodes) {
|
|
837
|
-
if (node.line.isPointOnSegment(
|
|
838
|
+
if (node.line.isPointOnSegment(point2)) result.push(node);
|
|
838
839
|
}
|
|
839
840
|
if (!this.isLeaf) {
|
|
840
841
|
for (const child of this.children) {
|
|
841
|
-
result.push(...child.queryPoint(
|
|
842
|
+
result.push(...child.queryPoint(point2));
|
|
842
843
|
}
|
|
843
844
|
}
|
|
844
845
|
return result;
|
|
@@ -1102,10 +1103,26 @@ class LineSegment {
|
|
|
1102
1103
|
this.end.copy(p2);
|
|
1103
1104
|
return this;
|
|
1104
1105
|
}
|
|
1105
|
-
getAnotherPoint(
|
|
1106
|
-
if (
|
|
1106
|
+
getAnotherPoint(point2) {
|
|
1107
|
+
if (point2 === this.start) return this.end;
|
|
1107
1108
|
else return this.start;
|
|
1108
1109
|
}
|
|
1110
|
+
/** 开始点向线段内收缩 width
|
|
1111
|
+
* @param width
|
|
1112
|
+
*/
|
|
1113
|
+
startShrink(width) {
|
|
1114
|
+
const d = this.end.direction(this.start);
|
|
1115
|
+
this.start.add(d.multiplyScalar(width));
|
|
1116
|
+
return this;
|
|
1117
|
+
}
|
|
1118
|
+
/** 结束点向线段内收缩 width
|
|
1119
|
+
* @param width
|
|
1120
|
+
*/
|
|
1121
|
+
endShrink(width) {
|
|
1122
|
+
const d = this.start.direction(this.end);
|
|
1123
|
+
this.end.add(d.multiplyScalar(width));
|
|
1124
|
+
return this;
|
|
1125
|
+
}
|
|
1109
1126
|
/**
|
|
1110
1127
|
* 是否有相同端点
|
|
1111
1128
|
* @param line
|
|
@@ -1139,13 +1156,13 @@ class LineSegment {
|
|
|
1139
1156
|
* @param point 要判断的点
|
|
1140
1157
|
* @returns 如果点在当前线段上则返回 true,否则返回 false
|
|
1141
1158
|
*/
|
|
1142
|
-
isPointOnSegment(
|
|
1159
|
+
isPointOnSegment(point2) {
|
|
1143
1160
|
const { start, end } = this;
|
|
1144
|
-
const cross = (
|
|
1161
|
+
const cross = (point2.y - start.y) * (end.x - start.x) - (point2.x - start.x) * (end.y - start.y);
|
|
1145
1162
|
if (Math.abs(cross) > 1e-10) {
|
|
1146
1163
|
return false;
|
|
1147
1164
|
}
|
|
1148
|
-
const dot = (
|
|
1165
|
+
const dot = (point2.x - start.x) * (point2.x - end.x) + (point2.y - start.y) * (point2.y - end.y);
|
|
1149
1166
|
return dot <= 1e-10;
|
|
1150
1167
|
}
|
|
1151
1168
|
/**
|
|
@@ -1229,7 +1246,7 @@ class LineSegment {
|
|
|
1229
1246
|
const nDirect = direct === "bothSides" ? Point.zero() : p1.direction(p2).mutiplyScalar(width * 0.5);
|
|
1230
1247
|
const offsetX = normal.x * width * 0.5;
|
|
1231
1248
|
const offsetY = normal.y * width * 0.5;
|
|
1232
|
-
const
|
|
1249
|
+
const point2 = [
|
|
1233
1250
|
// 第一条线
|
|
1234
1251
|
new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
|
|
1235
1252
|
new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
|
|
@@ -1237,7 +1254,7 @@ class LineSegment {
|
|
|
1237
1254
|
new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
|
|
1238
1255
|
new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
|
|
1239
1256
|
];
|
|
1240
|
-
return new Rectangle([0, 1, 3, 2].map((i) =>
|
|
1257
|
+
return new Rectangle([0, 1, 3, 2].map((i) => point2[i]));
|
|
1241
1258
|
}
|
|
1242
1259
|
/**
|
|
1243
1260
|
* 计算线段的长度
|
|
@@ -1288,8 +1305,8 @@ class LineSegment {
|
|
|
1288
1305
|
console.error("投影目标线段的两个点不能重合");
|
|
1289
1306
|
return new LineSegment();
|
|
1290
1307
|
}
|
|
1291
|
-
const projectPoint = (
|
|
1292
|
-
const pq = new Point(
|
|
1308
|
+
const projectPoint = (point2) => {
|
|
1309
|
+
const pq = new Point(point2.x - q1.x, point2.y - q1.y);
|
|
1293
1310
|
const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
|
|
1294
1311
|
const dotProduct = pq.x * dir.x + pq.y * dir.y;
|
|
1295
1312
|
const t = dotProduct / dirLengthSquared;
|
|
@@ -1299,8 +1316,8 @@ class LineSegment {
|
|
|
1299
1316
|
};
|
|
1300
1317
|
let projP1 = projectPoint(p1);
|
|
1301
1318
|
let projP2 = projectPoint(p2);
|
|
1302
|
-
const getT = (
|
|
1303
|
-
const pq = new Point(
|
|
1319
|
+
const getT = (point2) => {
|
|
1320
|
+
const pq = new Point(point2.x - q1.x, point2.y - q1.y);
|
|
1304
1321
|
const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
|
|
1305
1322
|
return (pq.x * dir.x + pq.y * dir.y) / dirLengthSquared;
|
|
1306
1323
|
};
|
|
@@ -1335,8 +1352,8 @@ class LineSegment {
|
|
|
1335
1352
|
if (dir.x === 0 && dir.y === 0) {
|
|
1336
1353
|
return null;
|
|
1337
1354
|
}
|
|
1338
|
-
const projectPoint = (
|
|
1339
|
-
const pq = new Point(
|
|
1355
|
+
const projectPoint = (point2) => {
|
|
1356
|
+
const pq = new Point(point2.x - q1.x, point2.y - q1.y);
|
|
1340
1357
|
const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
|
|
1341
1358
|
const dotProduct = pq.x * dir.x + pq.y * dir.y;
|
|
1342
1359
|
const t = dotProduct / dirLengthSquared;
|
|
@@ -1346,8 +1363,8 @@ class LineSegment {
|
|
|
1346
1363
|
};
|
|
1347
1364
|
let projP1 = projectPoint(p1);
|
|
1348
1365
|
if (!clip) return projP1;
|
|
1349
|
-
const getT = (
|
|
1350
|
-
const pq = new Point(
|
|
1366
|
+
const getT = (point2) => {
|
|
1367
|
+
const pq = new Point(point2.x - q1.x, point2.y - q1.y);
|
|
1351
1368
|
const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
|
|
1352
1369
|
return (pq.x * dir.x + pq.y * dir.y) / dirLengthSquared;
|
|
1353
1370
|
};
|
|
@@ -1359,13 +1376,13 @@ class LineSegment {
|
|
|
1359
1376
|
}
|
|
1360
1377
|
/** 获取点的投影值
|
|
1361
1378
|
*/
|
|
1362
|
-
projectValue(
|
|
1379
|
+
projectValue(point2) {
|
|
1363
1380
|
const [q1, q2] = this.points;
|
|
1364
1381
|
const dir = new Point(q2.x - q1.x, q2.y - q1.y);
|
|
1365
1382
|
if (dir.x === 0 && dir.y === 0) {
|
|
1366
1383
|
return 0;
|
|
1367
1384
|
}
|
|
1368
|
-
const pq = new Point(
|
|
1385
|
+
const pq = new Point(point2.x - q1.x, point2.y - q1.y);
|
|
1369
1386
|
const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
|
|
1370
1387
|
const dotProduct = pq.x * dir.x + pq.y * dir.y;
|
|
1371
1388
|
return dotProduct / dirLengthSquared;
|
|
@@ -1507,10 +1524,10 @@ class LineSegment {
|
|
|
1507
1524
|
/** 判断点在当前线段的左边还是右边,或者线段上
|
|
1508
1525
|
* @param point
|
|
1509
1526
|
*/
|
|
1510
|
-
pointPosition(
|
|
1527
|
+
pointPosition(point2) {
|
|
1511
1528
|
const p1 = this.start;
|
|
1512
1529
|
const p2 = this.end;
|
|
1513
|
-
const cross = (p2.x - p1.x) * (
|
|
1530
|
+
const cross = (p2.x - p1.x) * (point2.y - p1.y) - (p2.y - p1.y) * (point2.x - p1.x);
|
|
1514
1531
|
if (Math.abs(cross) < 1e-10) {
|
|
1515
1532
|
return "on";
|
|
1516
1533
|
}
|
|
@@ -1683,8 +1700,8 @@ class LineSegment {
|
|
|
1683
1700
|
static groupByPath(lines) {
|
|
1684
1701
|
const pointVirtualGrid = new PointVirtualGrid();
|
|
1685
1702
|
lines.forEach((line) => line.points.forEach((p) => pointVirtualGrid.insert(p, line)));
|
|
1686
|
-
function dfs(
|
|
1687
|
-
const list = pointVirtualGrid.queryPoint(
|
|
1703
|
+
function dfs(point2, group2, visted2) {
|
|
1704
|
+
const list = pointVirtualGrid.queryPoint(point2, true);
|
|
1688
1705
|
list.forEach((item) => {
|
|
1689
1706
|
const line = item.userData;
|
|
1690
1707
|
if (visted2.has(line)) return;
|
|
@@ -1713,8 +1730,8 @@ class LineSegment {
|
|
|
1713
1730
|
static groupByPoint(lines) {
|
|
1714
1731
|
const unionFindSet = new UnionFindSet(lines.length), map = /* @__PURE__ */ new Map();
|
|
1715
1732
|
for (let i = 0; i < lines.length; i++) {
|
|
1716
|
-
lines[i].points.forEach((
|
|
1717
|
-
const id =
|
|
1733
|
+
lines[i].points.forEach((point2) => {
|
|
1734
|
+
const id = point2.hashCode();
|
|
1718
1735
|
if (map.has(id)) unionFindSet.union(map.get(id), i);
|
|
1719
1736
|
map.set(id, i);
|
|
1720
1737
|
});
|
|
@@ -1729,8 +1746,8 @@ class LineSegment {
|
|
|
1729
1746
|
Point.adsorb(lines.flatMap((line) => line.points));
|
|
1730
1747
|
const grid = new PointVirtualGrid(), visited = /* @__PURE__ */ new Set();
|
|
1731
1748
|
lines.forEach((line) => line.points.forEach((p) => grid.insert(p, line)));
|
|
1732
|
-
function dfs(
|
|
1733
|
-
const list = grid.queryPoint(
|
|
1749
|
+
function dfs(point2, path, maxPath = []) {
|
|
1750
|
+
const list = grid.queryPoint(point2, true);
|
|
1734
1751
|
if (list.length === 0) {
|
|
1735
1752
|
if (maxPath.length < path.size) {
|
|
1736
1753
|
maxPath.length = 0;
|
|
@@ -1807,8 +1824,8 @@ class LineSegment {
|
|
|
1807
1824
|
), crossAxisMap = /* @__PURE__ */ new Map(), crossValueList = [], principalAxisStartMap = /* @__PURE__ */ new Map(), principalAxisEndMap = /* @__PURE__ */ new Map();
|
|
1808
1825
|
lines.forEach((line) => {
|
|
1809
1826
|
const value = crossAxis.projectValue(line.start);
|
|
1810
|
-
const
|
|
1811
|
-
const opt = { value, line, point, index: -1 };
|
|
1827
|
+
const point2 = crossAxis.projectPoint(line.start, false);
|
|
1828
|
+
const opt = { value, line, point: point2, index: -1 };
|
|
1812
1829
|
crossAxisMap.set(line, opt);
|
|
1813
1830
|
crossValueList.push(opt);
|
|
1814
1831
|
line.points.forEach((p, i) => {
|
|
@@ -1857,8 +1874,8 @@ class LineSegment {
|
|
|
1857
1874
|
}
|
|
1858
1875
|
let index2 = 1;
|
|
1859
1876
|
for (; index2 < list.length; index2++) {
|
|
1860
|
-
const { point } = list[index2];
|
|
1861
|
-
if (list[0].point.distance(
|
|
1877
|
+
const { point: point2 } = list[index2];
|
|
1878
|
+
if (list[0].point.distance(point2) > distanceThreshold) break;
|
|
1862
1879
|
}
|
|
1863
1880
|
return [list.slice(0, index2).map((o) => o.line), list.slice(index2).map((o) => o.line)];
|
|
1864
1881
|
}).flat(1);
|
|
@@ -2088,8 +2105,8 @@ class Point {
|
|
|
2088
2105
|
* @param point
|
|
2089
2106
|
* @returns
|
|
2090
2107
|
*/
|
|
2091
|
-
equal(
|
|
2092
|
-
return Math.abs(
|
|
2108
|
+
equal(point2) {
|
|
2109
|
+
return Math.abs(point2.x - this.x) < 1e-9 && Math.abs(point2.y - this.y) < 1e-9;
|
|
2093
2110
|
}
|
|
2094
2111
|
/**
|
|
2095
2112
|
*
|
|
@@ -2136,9 +2153,9 @@ class Point {
|
|
|
2136
2153
|
* @param point
|
|
2137
2154
|
* @returns
|
|
2138
2155
|
*/
|
|
2139
|
-
division(
|
|
2140
|
-
this.x -=
|
|
2141
|
-
this.y -=
|
|
2156
|
+
division(point2) {
|
|
2157
|
+
this.x -= point2.x;
|
|
2158
|
+
this.y -= point2.y;
|
|
2142
2159
|
return this;
|
|
2143
2160
|
}
|
|
2144
2161
|
/**
|
|
@@ -2147,9 +2164,9 @@ class Point {
|
|
|
2147
2164
|
* @param point
|
|
2148
2165
|
* @returns
|
|
2149
2166
|
*/
|
|
2150
|
-
subtract(
|
|
2151
|
-
this.x -=
|
|
2152
|
-
this.y -=
|
|
2167
|
+
subtract(point2) {
|
|
2168
|
+
this.x -= point2.x;
|
|
2169
|
+
this.y -= point2.y;
|
|
2153
2170
|
return this;
|
|
2154
2171
|
}
|
|
2155
2172
|
/**
|
|
@@ -2158,9 +2175,9 @@ class Point {
|
|
|
2158
2175
|
* @param point
|
|
2159
2176
|
* @returns
|
|
2160
2177
|
*/
|
|
2161
|
-
add(
|
|
2162
|
-
this.x +=
|
|
2163
|
-
this.y +=
|
|
2178
|
+
add(point2) {
|
|
2179
|
+
this.x += point2.x;
|
|
2180
|
+
this.y += point2.y;
|
|
2164
2181
|
return this;
|
|
2165
2182
|
}
|
|
2166
2183
|
parseInt() {
|
|
@@ -2173,15 +2190,15 @@ class Point {
|
|
|
2173
2190
|
* @param point
|
|
2174
2191
|
* @param angle 旋转角度,单位为弧度
|
|
2175
2192
|
*/
|
|
2176
|
-
rotate(
|
|
2177
|
-
const dx = this.x -
|
|
2178
|
-
const dy = this.y -
|
|
2193
|
+
rotate(point2, angle) {
|
|
2194
|
+
const dx = this.x - point2.x;
|
|
2195
|
+
const dy = this.y - point2.y;
|
|
2179
2196
|
const cosAngle = Math.cos(angle);
|
|
2180
2197
|
const sinAngle = Math.sin(angle);
|
|
2181
2198
|
const rotatedX = dx * cosAngle - dy * sinAngle;
|
|
2182
2199
|
const rotatedY = dx * sinAngle + dy * cosAngle;
|
|
2183
|
-
this.x = rotatedX +
|
|
2184
|
-
this.y = rotatedY +
|
|
2200
|
+
this.x = rotatedX + point2.x;
|
|
2201
|
+
this.y = rotatedY + point2.y;
|
|
2185
2202
|
return this;
|
|
2186
2203
|
}
|
|
2187
2204
|
/**
|
|
@@ -2211,9 +2228,9 @@ class Point {
|
|
|
2211
2228
|
* @param point
|
|
2212
2229
|
* @returns
|
|
2213
2230
|
*/
|
|
2214
|
-
normal(
|
|
2215
|
-
const dx = this.x -
|
|
2216
|
-
const dy = this.y -
|
|
2231
|
+
normal(point2) {
|
|
2232
|
+
const dx = this.x - point2.x;
|
|
2233
|
+
const dy = this.y - point2.y;
|
|
2217
2234
|
const length = Math.sqrt(dx * dx + dy * dy);
|
|
2218
2235
|
if (length === 0) return Point.zero();
|
|
2219
2236
|
const nx = -dy / length;
|
|
@@ -2226,9 +2243,9 @@ class Point {
|
|
|
2226
2243
|
* @param point
|
|
2227
2244
|
* @returns
|
|
2228
2245
|
*/
|
|
2229
|
-
direction(
|
|
2230
|
-
const dx = this.x -
|
|
2231
|
-
const dy = this.y -
|
|
2246
|
+
direction(point2) {
|
|
2247
|
+
const dx = this.x - point2.x;
|
|
2248
|
+
const dy = this.y - point2.y;
|
|
2232
2249
|
const length = Math.sqrt(dx * dx + dy * dy);
|
|
2233
2250
|
if (length === 0) return new Point(0, 0);
|
|
2234
2251
|
return new Point(dx / length, dy / length);
|
|
@@ -2254,8 +2271,8 @@ class Point {
|
|
|
2254
2271
|
* @param point
|
|
2255
2272
|
* @returns
|
|
2256
2273
|
*/
|
|
2257
|
-
dot(
|
|
2258
|
-
return this.x *
|
|
2274
|
+
dot(point2) {
|
|
2275
|
+
return this.x * point2.x + this.y * point2.y;
|
|
2259
2276
|
}
|
|
2260
2277
|
/** 求两个点叉积
|
|
2261
2278
|
* @description 如果叉积大于 0,a 到 b 为逆时针方向。
|
|
@@ -2263,8 +2280,8 @@ class Point {
|
|
|
2263
2280
|
* @param point
|
|
2264
2281
|
* @returns
|
|
2265
2282
|
*/
|
|
2266
|
-
cross(
|
|
2267
|
-
return this.x *
|
|
2283
|
+
cross(point2) {
|
|
2284
|
+
return this.x * point2.y - this.y * this.x;
|
|
2268
2285
|
}
|
|
2269
2286
|
/** 计算两个向量夹角
|
|
2270
2287
|
* @description 公式:a · b = |a| × |b| × cosθ
|
|
@@ -2272,28 +2289,28 @@ class Point {
|
|
|
2272
2289
|
* @param point
|
|
2273
2290
|
* @returns
|
|
2274
2291
|
*/
|
|
2275
|
-
angleBetween(
|
|
2276
|
-
const dotProduct = this.dot(
|
|
2292
|
+
angleBetween(point2, type = "radian", angle = "180") {
|
|
2293
|
+
const dotProduct = this.dot(point2);
|
|
2277
2294
|
const magnitude1 = this.magnitude();
|
|
2278
|
-
const magnitude2 =
|
|
2295
|
+
const magnitude2 = point2.magnitude();
|
|
2279
2296
|
if (magnitude1 === 0 || magnitude2 === 0) return 0;
|
|
2280
2297
|
const cosTheta = dotProduct / (magnitude1 * magnitude2);
|
|
2281
2298
|
const clampedCosTheta = Math.max(-1, Math.min(1, cosTheta));
|
|
2282
2299
|
if (type === "radian") return Math.acos(clampedCosTheta);
|
|
2283
2300
|
if (type === "cos") return clampedCosTheta;
|
|
2284
|
-
if (angle === "180" || this.cross(
|
|
2301
|
+
if (angle === "180" || this.cross(point2) < 0) return Math.acos(clampedCosTheta) / (Math.PI / 180);
|
|
2285
2302
|
return 360 - Math.acos(clampedCosTheta) / (Math.PI / 180);
|
|
2286
2303
|
}
|
|
2287
2304
|
/**
|
|
2288
2305
|
* @param point
|
|
2289
2306
|
* @returns
|
|
2290
2307
|
*/
|
|
2291
|
-
angleBetween2(
|
|
2308
|
+
angleBetween2(point2) {
|
|
2292
2309
|
const magnitude1 = Math.hypot(this.x, this.y);
|
|
2293
|
-
const magnitude2 = Math.hypot(
|
|
2310
|
+
const magnitude2 = Math.hypot(point2.x, point2.y);
|
|
2294
2311
|
if (magnitude1 === 0 || magnitude2 === 0) return 0;
|
|
2295
|
-
const dot = this.x *
|
|
2296
|
-
const cross = this.x *
|
|
2312
|
+
const dot = this.x * point2.x + this.y * point2.y;
|
|
2313
|
+
const cross = this.x * point2.y - this.y * point2.x;
|
|
2297
2314
|
return Math.atan2(cross, dot);
|
|
2298
2315
|
}
|
|
2299
2316
|
/** 获取向量长度
|
|
@@ -2310,13 +2327,13 @@ class Point {
|
|
|
2310
2327
|
* @param point
|
|
2311
2328
|
*/
|
|
2312
2329
|
_distanceMap = /* @__PURE__ */ new Map();
|
|
2313
|
-
distance(
|
|
2314
|
-
if (cached && this._distanceMap.has(
|
|
2330
|
+
distance(point2, cached = true) {
|
|
2331
|
+
if (cached && this._distanceMap.has(point2)) return this._distanceMap.get(point2);
|
|
2315
2332
|
const num = Math.sqrt(
|
|
2316
|
-
(this.x -
|
|
2333
|
+
(this.x - point2.x) * (this.x - point2.x) + (this.y - point2.y) * (this.y - point2.y)
|
|
2317
2334
|
);
|
|
2318
2335
|
if (cached) {
|
|
2319
|
-
this._distanceMap.set(
|
|
2336
|
+
this._distanceMap.set(point2, num);
|
|
2320
2337
|
Point.addDistanceCacheClear(this);
|
|
2321
2338
|
}
|
|
2322
2339
|
return num;
|
|
@@ -2352,19 +2369,19 @@ class Point {
|
|
|
2352
2369
|
points.forEach((p) => grid.insert(p));
|
|
2353
2370
|
const visited = /* @__PURE__ */ new Set();
|
|
2354
2371
|
for (let i = 0; i < points.length; i++) {
|
|
2355
|
-
const
|
|
2356
|
-
if (visited.has(
|
|
2357
|
-
const results = grid.queryCircle(
|
|
2372
|
+
const point2 = points[i];
|
|
2373
|
+
if (visited.has(point2)) continue;
|
|
2374
|
+
const results = grid.queryCircle(point2, tolerance).map((item) => item.point);
|
|
2358
2375
|
let countX = 0, countY = 0;
|
|
2359
|
-
results.forEach((
|
|
2360
|
-
countX +=
|
|
2361
|
-
countY +=
|
|
2376
|
+
results.forEach((point22) => {
|
|
2377
|
+
countX += point22.x;
|
|
2378
|
+
countY += point22.y;
|
|
2362
2379
|
});
|
|
2363
2380
|
const x = countX / results.length, y = countY / results.length;
|
|
2364
|
-
results.forEach((
|
|
2365
|
-
|
|
2366
|
-
visited.add(
|
|
2367
|
-
grid.remove(
|
|
2381
|
+
results.forEach((point22) => {
|
|
2382
|
+
point22.set(x, y);
|
|
2383
|
+
visited.add(point22);
|
|
2384
|
+
grid.remove(point22);
|
|
2368
2385
|
});
|
|
2369
2386
|
}
|
|
2370
2387
|
visited.clear();
|
|
@@ -2526,15 +2543,15 @@ class Box2 {
|
|
|
2526
2543
|
if (p.x >= this.minX && p.x <= this.maxX && p.y >= this.minY && p.y <= this.maxY)
|
|
2527
2544
|
return true;
|
|
2528
2545
|
}
|
|
2529
|
-
const isPointInRect = (
|
|
2546
|
+
const isPointInRect = (point2) => {
|
|
2530
2547
|
let sign = 0;
|
|
2531
2548
|
for (let i = 0; i < 4; i++) {
|
|
2532
2549
|
const p1 = rPoints[i];
|
|
2533
2550
|
const p2 = rPoints[(i + 1) % 4];
|
|
2534
|
-
const cross = (p2.x - p1.x) * (
|
|
2551
|
+
const cross = (p2.x - p1.x) * (point2.y - p1.y) - (p2.y - p1.y) * (point2.x - p1.x);
|
|
2535
2552
|
if (cross === 0) {
|
|
2536
2553
|
const denom = Math.abs(p2.x - p1.x) > 1e-10 ? p2.x - p1.x : p2.y - p1.y;
|
|
2537
|
-
const t = denom ? (
|
|
2554
|
+
const t = denom ? (point2.x - p1.x) / denom : 0;
|
|
2538
2555
|
if (t >= 0 && t <= 1) return true;
|
|
2539
2556
|
} else {
|
|
2540
2557
|
const currentSign = cross > 0 ? 1 : -1;
|
|
@@ -2575,8 +2592,8 @@ class Box2 {
|
|
|
2575
2592
|
/** 判断点是在包围盒内
|
|
2576
2593
|
* @param point
|
|
2577
2594
|
*/
|
|
2578
|
-
containsPoint(
|
|
2579
|
-
return
|
|
2595
|
+
containsPoint(point2) {
|
|
2596
|
+
return point2.x >= this.minX && point2.x <= this.maxX && point2.y >= this.minY && point2.y <= this.maxY;
|
|
2580
2597
|
}
|
|
2581
2598
|
/**
|
|
2582
2599
|
*
|
|
@@ -2737,16 +2754,16 @@ class Polygon extends Array {
|
|
|
2737
2754
|
* @param point
|
|
2738
2755
|
* @returns 'on' 边上,'inside' 内部,'outside' 外部
|
|
2739
2756
|
*/
|
|
2740
|
-
pointPosition(
|
|
2757
|
+
pointPosition(point2) {
|
|
2741
2758
|
if (this.length < 3) return "outside";
|
|
2742
2759
|
const eps = 1e-10;
|
|
2743
2760
|
for (let i = 0, j = this.length - 1; i < this.length; j = i++) {
|
|
2744
2761
|
const a = this[j], b = this[i];
|
|
2745
|
-
const cross = (b.x - a.x) * (
|
|
2762
|
+
const cross = (b.x - a.x) * (point2.y - a.y) - (b.y - a.y) * (point2.x - a.x);
|
|
2746
2763
|
if (Math.abs(cross) < eps) {
|
|
2747
2764
|
const minX = Math.min(a.x, b.x), maxX = Math.max(a.x, b.x);
|
|
2748
2765
|
const minY = Math.min(a.y, b.y), maxY = Math.max(a.y, b.y);
|
|
2749
|
-
if (
|
|
2766
|
+
if (point2.x >= minX - eps && point2.x <= maxX + eps && point2.y >= minY - eps && point2.y <= maxY + eps) {
|
|
2750
2767
|
return "on";
|
|
2751
2768
|
}
|
|
2752
2769
|
}
|
|
@@ -2755,9 +2772,9 @@ class Polygon extends Array {
|
|
|
2755
2772
|
for (let i = 0, j = this.length - 1; i < this.length; j = i++) {
|
|
2756
2773
|
const xi2 = this[i].x, yi2 = this[i].y;
|
|
2757
2774
|
const xj = this[j].x, yj = this[j].y;
|
|
2758
|
-
if (yi2 >
|
|
2759
|
-
const intersectionX = (xj - xi2) * (
|
|
2760
|
-
if (
|
|
2775
|
+
if (yi2 > point2.y !== yj > point2.y) {
|
|
2776
|
+
const intersectionX = (xj - xi2) * (point2.y - yi2) / (yj - yi2) + xi2;
|
|
2777
|
+
if (point2.x < intersectionX) {
|
|
2761
2778
|
inside = !inside;
|
|
2762
2779
|
}
|
|
2763
2780
|
}
|
|
@@ -2810,15 +2827,15 @@ class Polygon extends Array {
|
|
|
2810
2827
|
* @param point
|
|
2811
2828
|
* @returns
|
|
2812
2829
|
*/
|
|
2813
|
-
pointIn(
|
|
2814
|
-
return this.pointPosition(
|
|
2830
|
+
pointIn(point2) {
|
|
2831
|
+
return this.pointPosition(point2) !== "outside";
|
|
2815
2832
|
}
|
|
2816
2833
|
/** 点在多边形内部,不包括路径上
|
|
2817
2834
|
* @param point
|
|
2818
2835
|
* @returns
|
|
2819
2836
|
*/
|
|
2820
|
-
pointWithin(
|
|
2821
|
-
return this.pointPosition(
|
|
2837
|
+
pointWithin(point2) {
|
|
2838
|
+
return this.pointPosition(point2) !== "inside";
|
|
2822
2839
|
}
|
|
2823
2840
|
/** 缩放
|
|
2824
2841
|
* @param scale
|
|
@@ -2879,8 +2896,8 @@ class Polygon extends Array {
|
|
|
2879
2896
|
while (true) {
|
|
2880
2897
|
const list = grid.queryPoint(current, true);
|
|
2881
2898
|
if (list.length !== 1) break;
|
|
2882
|
-
const { point, userData } = list[0];
|
|
2883
|
-
current = userData?.getAnotherPoint(
|
|
2899
|
+
const { point: point2, userData } = list[0];
|
|
2900
|
+
current = userData?.getAnotherPoint(point2);
|
|
2884
2901
|
if (points.has(current)) break;
|
|
2885
2902
|
points.add(current);
|
|
2886
2903
|
}
|
|
@@ -3280,10 +3297,10 @@ function mergeWindow(...windowLines) {
|
|
|
3280
3297
|
windowLine.currentData.wd = w;
|
|
3281
3298
|
return windowLine;
|
|
3282
3299
|
}), points = windowLines2.flatMap((l) => {
|
|
3283
|
-
const points2 = l.points.map((
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
return
|
|
3300
|
+
const points2 = l.points.map((point2) => {
|
|
3301
|
+
point2.currentData.line = l;
|
|
3302
|
+
point2.currentData.distance = point2.distance(line.start);
|
|
3303
|
+
return point2;
|
|
3287
3304
|
});
|
|
3288
3305
|
points2.sort((a, b) => a.currentData.distance - b.currentData.distance);
|
|
3289
3306
|
points2.forEach((p, index2) => p.currentData.index = index2);
|
|
@@ -3295,16 +3312,16 @@ function mergeWindow(...windowLines) {
|
|
|
3295
3312
|
const newWindowLines = [];
|
|
3296
3313
|
let activeCount = 0, mergeStart = null, lineSet = /* @__PURE__ */ new Set();
|
|
3297
3314
|
for (let i = 0; i < points.length; i++) {
|
|
3298
|
-
const
|
|
3299
|
-
if (!mergeStart) mergeStart =
|
|
3300
|
-
if (
|
|
3315
|
+
const point2 = points[i];
|
|
3316
|
+
if (!mergeStart) mergeStart = point2;
|
|
3317
|
+
if (point2.currentData.index === 0) {
|
|
3301
3318
|
activeCount++;
|
|
3302
|
-
lineSet.add(
|
|
3319
|
+
lineSet.add(point2.currentData.line);
|
|
3303
3320
|
continue;
|
|
3304
3321
|
}
|
|
3305
3322
|
activeCount--;
|
|
3306
3323
|
if (activeCount === 0) {
|
|
3307
|
-
const newWindowLine = new LineSegment(mergeStart,
|
|
3324
|
+
const newWindowLine = new LineSegment(mergeStart, point2);
|
|
3308
3325
|
newWindowLine.currentData.wds = [...lineSet].map((line2) => line2.currentData.wd);
|
|
3309
3326
|
newWindowLines.push(newWindowLine);
|
|
3310
3327
|
mergeStart = null;
|
|
@@ -3328,8 +3345,8 @@ function clippingLineUserData(line1, line2) {
|
|
|
3328
3345
|
if (drawWindow) {
|
|
3329
3346
|
if (!line1.userData.drawWindow) line1.userData.drawWindow = [];
|
|
3330
3347
|
drawWindow.forEach((item) => {
|
|
3331
|
-
const
|
|
3332
|
-
const projp = line1.projectPoint(
|
|
3348
|
+
const point2 = Point.from(item.p);
|
|
3349
|
+
const projp = line1.projectPoint(point2);
|
|
3333
3350
|
if (projp) line1.userData.drawWindow?.push(item);
|
|
3334
3351
|
});
|
|
3335
3352
|
recomputedWindow(line1);
|
|
@@ -3465,10 +3482,10 @@ function segmentationPath(lines, clipLine) {
|
|
|
3465
3482
|
removeLines.add(line);
|
|
3466
3483
|
continue;
|
|
3467
3484
|
}
|
|
3468
|
-
const
|
|
3469
|
-
if (
|
|
3470
|
-
if (line.start.equal(
|
|
3471
|
-
const newLines = LineSegment.clipping(line, [
|
|
3485
|
+
const point2 = line.getIntersection(queryLine);
|
|
3486
|
+
if (point2) {
|
|
3487
|
+
if (line.start.equal(point2) || line.end.equal(point2)) continue;
|
|
3488
|
+
const newLines = LineSegment.clipping(line, [point2], clippingLineUserData);
|
|
3472
3489
|
removeLines.add(line);
|
|
3473
3490
|
newLines.forEach((line2) => fractureLines.add(line2));
|
|
3474
3491
|
}
|
|
@@ -3538,32 +3555,24 @@ function doubleWallPoint(grid, line) {
|
|
|
3538
3555
|
function winDrawLine(line, grid) {
|
|
3539
3556
|
if (line.userData.isWindow && Array.isArray(line.userData.drawWindow)) {
|
|
3540
3557
|
mergeWindow(line);
|
|
3558
|
+
const list = grid && doubleWallPoint(grid, line), dwh = defaultWallWidth$1 * 0.5;
|
|
3541
3559
|
return line.userData.drawWindow.map(({ full, width, p, height, groundClearance }) => {
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
if (full) {
|
|
3545
|
-
const dwh = defaultWallWidth$1 * 0.5;
|
|
3546
|
-
width = line.length();
|
|
3547
|
-
if (grid) {
|
|
3548
|
-
const list = doubleWallPoint(grid, line);
|
|
3549
|
-
if (list[0] === 0) {
|
|
3550
|
-
width += dwh;
|
|
3551
|
-
offset -= dwh * 0.5;
|
|
3552
|
-
} else if (list[0] === 1) {
|
|
3553
|
-
width -= dwh;
|
|
3554
|
-
offset += dwh * 0.5;
|
|
3555
|
-
}
|
|
3556
|
-
if (list[1] === 0) {
|
|
3557
|
-
width += dwh;
|
|
3558
|
-
offset += dwh * 0.5;
|
|
3559
|
-
} else if (list[1] === 1) {
|
|
3560
|
-
width -= dwh;
|
|
3561
|
-
offset -= dwh * 0.5;
|
|
3562
|
-
}
|
|
3563
|
-
}
|
|
3564
|
-
}
|
|
3565
|
-
const winLine = point.expandAsLine(direct, width).directionMove(direct, -width * 0.5 + offset);
|
|
3560
|
+
if (full) width = line.length();
|
|
3561
|
+
const point2 = Point.from(p), direct = line.direction(), winLine = point2.expandAsLine(direct, width).directionMove(direct, -width * 0.5);
|
|
3566
3562
|
winLine.userData = { wallWidth: defaultWallWidth$1, height, groundClearance };
|
|
3563
|
+
winLine.start.copy(line.projectPoint(winLine.start, false));
|
|
3564
|
+
winLine.end.copy(line.projectPoint(winLine.end, false));
|
|
3565
|
+
if (!list) return winLine;
|
|
3566
|
+
const startDistance = winLine.start.distance(line.start);
|
|
3567
|
+
if (startDistance < dwh && list[0] === 1) {
|
|
3568
|
+
const diff = dwh - startDistance;
|
|
3569
|
+
winLine.startShrink(diff);
|
|
3570
|
+
}
|
|
3571
|
+
const endDistance = winLine.end.distance(line.end);
|
|
3572
|
+
if (endDistance < dwh && list[1] === 1) {
|
|
3573
|
+
const diff = dwh - endDistance;
|
|
3574
|
+
winLine.endShrink(diff);
|
|
3575
|
+
}
|
|
3567
3576
|
return winLine;
|
|
3568
3577
|
}).filter((line2) => line2.length() > defaultWallWidth$1);
|
|
3569
3578
|
}
|
|
@@ -3580,9 +3589,9 @@ function doubleWinDrawLine(lines) {
|
|
|
3580
3589
|
mergeLineUserData(newLine, lines);
|
|
3581
3590
|
mergeWindow(newLine);
|
|
3582
3591
|
return (newLine.userData?.drawWindow?.map(({ full, width, p, height, groundClearance }) => {
|
|
3583
|
-
const
|
|
3592
|
+
const point2 = Point.from(p), direct = newLine.direction();
|
|
3584
3593
|
if (full) width = newLine.length();
|
|
3585
|
-
const winLine2 =
|
|
3594
|
+
const winLine2 = point2.expandAsLine(direct, width).directionMove(direct, -width * 0.5);
|
|
3586
3595
|
try {
|
|
3587
3596
|
winLine2.start.copy(newLine.projectPoint(winLine2.start, false));
|
|
3588
3597
|
winLine2.end.copy(newLine.projectPoint(winLine2.end, false));
|
|
@@ -3951,7 +3960,7 @@ class CAD {
|
|
|
3951
3960
|
drawDottedLine(p2C, p2, 0.04, 0.05, "line2");
|
|
3952
3961
|
drawLine2(p1C, p2C);
|
|
3953
3962
|
color = "white";
|
|
3954
|
-
drawText2((length *
|
|
3963
|
+
drawText2((length * 100).toFixed(2) + "cm", line.center);
|
|
3955
3964
|
}
|
|
3956
3965
|
function drawArc(pos, radius, startAngle, endAngle) {
|
|
3957
3966
|
data.arcs.push([
|
|
@@ -4412,21 +4421,21 @@ class LineSegmentUndirectedGraph extends UndirectedGraph {
|
|
|
4412
4421
|
/**
|
|
4413
4422
|
* 获取或创建点的索引
|
|
4414
4423
|
*/
|
|
4415
|
-
getOrCreateIndex(
|
|
4416
|
-
const code =
|
|
4424
|
+
getOrCreateIndex(point2) {
|
|
4425
|
+
const code = point2.hashCode();
|
|
4417
4426
|
let index2 = this.pointToIndex.get(code);
|
|
4418
4427
|
if (index2 === void 0) {
|
|
4419
4428
|
index2 = this.nextIndex++;
|
|
4420
4429
|
this.pointToIndex.set(code, index2);
|
|
4421
|
-
this.indexToPoint.set(index2,
|
|
4430
|
+
this.indexToPoint.set(index2, point2);
|
|
4422
4431
|
}
|
|
4423
4432
|
return index2;
|
|
4424
4433
|
}
|
|
4425
4434
|
/**
|
|
4426
4435
|
* 安全获取点索引(已存在才返回)
|
|
4427
4436
|
*/
|
|
4428
|
-
getIndex(
|
|
4429
|
-
return this.pointToIndex.get(
|
|
4437
|
+
getIndex(point2) {
|
|
4438
|
+
return this.pointToIndex.get(point2.hashCode());
|
|
4430
4439
|
}
|
|
4431
4440
|
/**
|
|
4432
4441
|
* @param index
|
|
@@ -4500,17 +4509,17 @@ function smallestCircle(lines, ringEdges, halfCircle = false) {
|
|
|
4500
4509
|
const center = line.center, direct = line.normal(), otherPoint = line.getAnotherPoint(startPoint), lineDirect = otherPoint.direction(startPoint);
|
|
4501
4510
|
temLine.start.copy(center);
|
|
4502
4511
|
temLine.end.copy(center).add(direct.clone().multiplyScalar(1));
|
|
4503
|
-
const
|
|
4504
|
-
temLine.end.copy(
|
|
4512
|
+
const point2 = preInnerDirect.getIntersection(temLine);
|
|
4513
|
+
temLine.end.copy(point2);
|
|
4505
4514
|
if (preInnerDirect.direction().angleBetween(lineDirect) > PI_1 * 170) temLine.mirror();
|
|
4506
4515
|
return temLine.clone();
|
|
4507
4516
|
}
|
|
4508
|
-
function dfs(edge, line,
|
|
4517
|
+
function dfs(edge, line, point2, preInnerDirect, path, isPreInnerDirect = true) {
|
|
4509
4518
|
if (path.length > lines.length) return;
|
|
4510
4519
|
if (visited.has(line)) return;
|
|
4511
4520
|
visited.add(line);
|
|
4512
|
-
let innerDirect = isPreInnerDirect ? getInnerDirect(line,
|
|
4513
|
-
const otherPoint = line.getAnotherPoint(
|
|
4521
|
+
let innerDirect = isPreInnerDirect ? getInnerDirect(line, point2, preInnerDirect) : preInnerDirect;
|
|
4522
|
+
const otherPoint = line.getAnotherPoint(point2);
|
|
4514
4523
|
let result = grid.queryPoint(otherPoint, true);
|
|
4515
4524
|
if (result.length === 1) {
|
|
4516
4525
|
const item = result[0], nextLine = item.userData;
|
|
@@ -4548,8 +4557,8 @@ function smallestCircle(lines, ringEdges, halfCircle = false) {
|
|
|
4548
4557
|
visited.clear();
|
|
4549
4558
|
const directLine = directLines[i], d0 = directLine.direction(), path = [line];
|
|
4550
4559
|
if (dfs(line, line, line.start, directLine, path, false)) {
|
|
4551
|
-
const
|
|
4552
|
-
if (path.length > 5 && !Polygon.fromByLines(path).pointIn(
|
|
4560
|
+
const point2 = center.clone().add(d0.multiplyScalar(5e-4));
|
|
4561
|
+
if (path.length > 5 && !Polygon.fromByLines(path).pointIn(point2)) {
|
|
4553
4562
|
continue;
|
|
4554
4563
|
} else {
|
|
4555
4564
|
ringList.push(path);
|
|
@@ -4719,15 +4728,15 @@ function migration(newLine, oldLine) {
|
|
|
4719
4728
|
if (oldLine.userData.isWindow) {
|
|
4720
4729
|
newLine.userData.isWindow = true;
|
|
4721
4730
|
newLine.userData.drawWindow = oldLine.userData.drawWindow?.filter((w) => {
|
|
4722
|
-
const
|
|
4723
|
-
return !!newLine.projectPoint(
|
|
4731
|
+
const point2 = Point.from(w.p);
|
|
4732
|
+
return !!newLine.projectPoint(point2);
|
|
4724
4733
|
}) ?? [];
|
|
4725
4734
|
}
|
|
4726
4735
|
if (oldLine.currentData.isFittedLine) {
|
|
4727
4736
|
const userDataList = oldLine.currentData.userDataList;
|
|
4728
4737
|
newLine.userData.isBayWindow = false;
|
|
4729
|
-
userDataList.forEach((userData,
|
|
4730
|
-
if (newLine.projectPoint(
|
|
4738
|
+
userDataList.forEach((userData, point2) => {
|
|
4739
|
+
if (newLine.projectPoint(point2)) {
|
|
4731
4740
|
if (userData.isBayWindow) {
|
|
4732
4741
|
newLine.userData.isBayWindow = true;
|
|
4733
4742
|
}
|
|
@@ -4741,9 +4750,9 @@ function lineSegmentClipping(lines, minLen = 0.03) {
|
|
|
4741
4750
|
const result = lines.flatMap((line) => {
|
|
4742
4751
|
const points = quadtree.queryLineSegment(line, true).map((res) => {
|
|
4743
4752
|
if (res.line === line) return;
|
|
4744
|
-
const
|
|
4745
|
-
if (!
|
|
4746
|
-
return
|
|
4753
|
+
const point2 = res.line.getIntersection(line);
|
|
4754
|
+
if (!point2 || line.start.equal(point2) || line.end.equal(point2)) return;
|
|
4755
|
+
return point2;
|
|
4747
4756
|
}).filter((i) => !!i);
|
|
4748
4757
|
if (points.length) {
|
|
4749
4758
|
const cloneLine = line.clone();
|
|
@@ -4898,17 +4907,17 @@ function shortDistanceLink(lines, radius = 0.1, pointVirtualGrid) {
|
|
|
4898
4907
|
for (let i = 0; i < lines.length; i++) {
|
|
4899
4908
|
const line = lines[i], distanceMap = /* @__PURE__ */ new Map();
|
|
4900
4909
|
if (line.userData.isDoor) continue;
|
|
4901
|
-
line.points.forEach((
|
|
4902
|
-
if (visited.has(
|
|
4903
|
-
if (pointVirtualGrid.queryPoint(
|
|
4904
|
-
const list = pointVirtualGrid.queryCircle(
|
|
4910
|
+
line.points.forEach((point2) => {
|
|
4911
|
+
if (visited.has(point2)) return false;
|
|
4912
|
+
if (pointVirtualGrid.queryPoint(point2).length > 1) return;
|
|
4913
|
+
const list = pointVirtualGrid.queryCircle(point2, radius).filter((item) => {
|
|
4905
4914
|
if (visited.has(item.point)) return false;
|
|
4906
4915
|
const resLine = item.userData;
|
|
4907
4916
|
if (resLine === line || !line.parallel(resLine, 25)) return false;
|
|
4908
4917
|
if (pointVirtualGrid.queryPoint(item.point).length > 1) return false;
|
|
4909
|
-
const distance =
|
|
4918
|
+
const distance = point2.distance(item.point);
|
|
4910
4919
|
if (distance < 1e-3) return false;
|
|
4911
|
-
const direct1 =
|
|
4920
|
+
const direct1 = point2.direction(line.getAnotherPoint(point2)), direct2 = item.point.direction(resLine.getAnotherPoint(item.point));
|
|
4912
4921
|
if (180 - direct1.angleBetween(direct2, "angle") < 25) {
|
|
4913
4922
|
distanceMap.set(item.point, distance);
|
|
4914
4923
|
return true;
|
|
@@ -4918,11 +4927,11 @@ function shortDistanceLink(lines, radius = 0.1, pointVirtualGrid) {
|
|
|
4918
4927
|
return aDistance - bDistance;
|
|
4919
4928
|
});
|
|
4920
4929
|
if (list.length === 0) return;
|
|
4921
|
-
visited.add(
|
|
4930
|
+
visited.add(point2);
|
|
4922
4931
|
visited.add(list[0].point);
|
|
4923
4932
|
const targetLine = list[0].userData;
|
|
4924
4933
|
const projectLine1 = line.projectLineSegment(targetLine), projectLine2 = targetLine.projectLineSegment(line), len1 = projectLine1.length(), len2 = projectLine2.length();
|
|
4925
|
-
if (len1 === 0 && len2 === 0) appendLines.push(new LineSegment(
|
|
4934
|
+
if (len1 === 0 && len2 === 0) appendLines.push(new LineSegment(point2.clone(), list[0].point.clone()));
|
|
4926
4935
|
else appendLines.push(new LineSegment(projectLine1.center, projectLine2.center));
|
|
4927
4936
|
});
|
|
4928
4937
|
}
|
|
@@ -5052,11 +5061,11 @@ function correction$1(targettLine, lines, intersectMap, errAngle = 15) {
|
|
|
5052
5061
|
function groupByAxis(lines, principalAxis, crossAxis, principalAxisThreshold, crossAxistThreshold) {
|
|
5053
5062
|
const projectPoints = [], crossAxisMap = /* @__PURE__ */ new Map();
|
|
5054
5063
|
lines.forEach((line) => {
|
|
5055
|
-
const
|
|
5056
|
-
if (
|
|
5057
|
-
|
|
5058
|
-
projectPoints.push(
|
|
5059
|
-
crossAxisMap.set(line,
|
|
5064
|
+
const point2 = crossAxis.projectPoint(line.start, false);
|
|
5065
|
+
if (point2) {
|
|
5066
|
+
point2.userData = line;
|
|
5067
|
+
projectPoints.push(point2);
|
|
5068
|
+
crossAxisMap.set(line, point2);
|
|
5060
5069
|
}
|
|
5061
5070
|
});
|
|
5062
5071
|
projectPoints.sort((a, b) => {
|
|
@@ -5064,27 +5073,27 @@ function groupByAxis(lines, principalAxis, crossAxis, principalAxisThreshold, cr
|
|
|
5064
5073
|
});
|
|
5065
5074
|
const groups = [], group2 = [];
|
|
5066
5075
|
for (let i = 0; i < projectPoints.length; i++) {
|
|
5067
|
-
const
|
|
5076
|
+
const point2 = projectPoints[i];
|
|
5068
5077
|
if (i === 0) {
|
|
5069
|
-
group2.push(
|
|
5078
|
+
group2.push(point2);
|
|
5070
5079
|
continue;
|
|
5071
5080
|
}
|
|
5072
5081
|
const prePoint = projectPoints[i - 1];
|
|
5073
|
-
if (prePoint.distance(
|
|
5082
|
+
if (prePoint.distance(point2) < crossAxistThreshold) group2.push(point2);
|
|
5074
5083
|
else {
|
|
5075
5084
|
groups.push([...group2]);
|
|
5076
5085
|
group2.length = 0;
|
|
5077
|
-
group2.push(
|
|
5086
|
+
group2.push(point2);
|
|
5078
5087
|
}
|
|
5079
5088
|
if (i === projectPoints.length - 1) groups.push(group2);
|
|
5080
5089
|
}
|
|
5081
5090
|
return groups.flatMap((group3) => {
|
|
5082
|
-
const points = group3.flatMap((
|
|
5083
|
-
const line =
|
|
5091
|
+
const points = group3.flatMap((point2) => {
|
|
5092
|
+
const line = point2.userData;
|
|
5084
5093
|
return line.points.map((p) => {
|
|
5085
|
-
const
|
|
5086
|
-
|
|
5087
|
-
return
|
|
5094
|
+
const point22 = principalAxis.projectPoint(p, false);
|
|
5095
|
+
point22.userData = line;
|
|
5096
|
+
return point22;
|
|
5088
5097
|
});
|
|
5089
5098
|
});
|
|
5090
5099
|
points.sort((a, b) => {
|
|
@@ -5092,15 +5101,15 @@ function groupByAxis(lines, principalAxis, crossAxis, principalAxisThreshold, cr
|
|
|
5092
5101
|
});
|
|
5093
5102
|
const map = /* @__PURE__ */ new Map(), newGroup = [];
|
|
5094
5103
|
let newGroups = [];
|
|
5095
|
-
points.forEach((
|
|
5104
|
+
points.forEach((point2, i) => {
|
|
5096
5105
|
if (map.size === 0 && i > 0) {
|
|
5097
5106
|
const prePoint = points[i - 1];
|
|
5098
|
-
if (prePoint.distance(
|
|
5107
|
+
if (prePoint.distance(point2) > principalAxisThreshold) {
|
|
5099
5108
|
newGroups.push([...newGroup]);
|
|
5100
5109
|
newGroup.length = 0;
|
|
5101
5110
|
}
|
|
5102
5111
|
}
|
|
5103
|
-
map.set(
|
|
5112
|
+
map.set(point2.userData, (map.get(point2.userData) ?? 0) + 1);
|
|
5104
5113
|
for (const v of map.values()) if (v !== 2) return;
|
|
5105
5114
|
newGroup.push(...map.keys());
|
|
5106
5115
|
map.clear();
|
|
@@ -5113,8 +5122,8 @@ function groupByCrossAxis(lines, principalAxis, crossAxis, crossAxistThreshold)
|
|
|
5113
5122
|
const crossAxisMap = /* @__PURE__ */ new Map(), crossValueList = [], principalAxisStartMap = /* @__PURE__ */ new Map(), principalAxisEndMap = /* @__PURE__ */ new Map();
|
|
5114
5123
|
lines.forEach((line) => {
|
|
5115
5124
|
const value = crossAxis.projectValue(line.start);
|
|
5116
|
-
const
|
|
5117
|
-
const opt = { value, line, point, index: -1 };
|
|
5125
|
+
const point2 = crossAxis.projectPoint(line.start, false);
|
|
5126
|
+
const opt = { value, line, point: point2, index: -1 };
|
|
5118
5127
|
crossAxisMap.set(line, opt);
|
|
5119
5128
|
crossValueList.push(opt);
|
|
5120
5129
|
line.points.forEach((p, i) => {
|
|
@@ -5163,8 +5172,8 @@ function groupByCrossAxis(lines, principalAxis, crossAxis, crossAxistThreshold)
|
|
|
5163
5172
|
}
|
|
5164
5173
|
let index2 = 1;
|
|
5165
5174
|
for (; index2 < list.length; index2++) {
|
|
5166
|
-
const { point } = list[index2];
|
|
5167
|
-
if (list[0].point.distance(
|
|
5175
|
+
const { point: point2 } = list[index2];
|
|
5176
|
+
if (list[0].point.distance(point2) > crossAxistThreshold) break;
|
|
5168
5177
|
}
|
|
5169
5178
|
return [list.slice(0, index2).map((o) => o.line), list.slice(index2).map((o) => o.line)];
|
|
5170
5179
|
}).flat(1);
|
|
@@ -5287,50 +5296,50 @@ function adsorption(lines, intersectionMap, option) {
|
|
|
5287
5296
|
lines.forEach((line) => {
|
|
5288
5297
|
if (line.userData.isDoor) return;
|
|
5289
5298
|
quadtree.insert(line);
|
|
5290
|
-
line.points.forEach((
|
|
5299
|
+
line.points.forEach((point2) => pointVirtualGrid.insert(point2, line));
|
|
5291
5300
|
});
|
|
5292
5301
|
function setPoint(line, line1) {
|
|
5293
5302
|
if (!map.has(line)) map.set(line, []);
|
|
5294
5303
|
map.get(line)?.push(line1);
|
|
5295
5304
|
}
|
|
5296
|
-
function getAdsorptionPointByLine(
|
|
5297
|
-
if (quadtree.queryPoint(
|
|
5305
|
+
function getAdsorptionPointByLine(point2, line) {
|
|
5306
|
+
if (quadtree.queryPoint(point2).length > 1) return;
|
|
5298
5307
|
const direction = line.direction().multiplyScalar(threshold);
|
|
5299
|
-
queryLine.set(
|
|
5308
|
+
queryLine.set(point2, point2);
|
|
5300
5309
|
queryLine.start.add(direction);
|
|
5301
5310
|
queryLine.end.add(direction.multiplyScalar(-1));
|
|
5302
5311
|
const map2 = /* @__PURE__ */ new Map();
|
|
5303
5312
|
const list = quadtree.queryLineSegment(queryLine).filter((res) => res.line !== line).map((res) => {
|
|
5304
|
-
const
|
|
5305
|
-
map2.set(res.line,
|
|
5313
|
+
const point22 = res.line.getIntersection(queryLine);
|
|
5314
|
+
map2.set(res.line, point22);
|
|
5306
5315
|
return res.line;
|
|
5307
5316
|
}).sort((line1, line2) => {
|
|
5308
5317
|
const point1 = map2.get(line1);
|
|
5309
|
-
const
|
|
5310
|
-
if (point1 &&
|
|
5318
|
+
const point22 = map2.get(line2);
|
|
5319
|
+
if (point1 && point22) return point1.distance(point2) - point22.distance(point2);
|
|
5311
5320
|
return 0;
|
|
5312
5321
|
});
|
|
5313
5322
|
if (list.length) return map2.get(list[0]);
|
|
5314
5323
|
}
|
|
5315
|
-
function getObtainNearestAbsorbableLine(
|
|
5316
|
-
let newPoint = getAdsorptionPointByLine(
|
|
5324
|
+
function getObtainNearestAbsorbableLine(point2, line) {
|
|
5325
|
+
let newPoint = getAdsorptionPointByLine(point2, line);
|
|
5317
5326
|
if (newPoint) {
|
|
5318
|
-
return setPoint(line, new LineSegment(
|
|
5327
|
+
return setPoint(line, new LineSegment(point2.clone(), newPoint.clone()));
|
|
5319
5328
|
}
|
|
5320
|
-
if (pointVirtualGrid.queryPoint(
|
|
5321
|
-
const list0 = quadtree.queryCircle(
|
|
5329
|
+
if (pointVirtualGrid.queryPoint(point2).filter((item) => item.userData !== line).length !== 0) return;
|
|
5330
|
+
const list0 = quadtree.queryCircle(point2, 1e-3).filter((item) => item.line !== line);
|
|
5322
5331
|
if (list0.length > 0) return;
|
|
5323
|
-
const list = pointVirtualGrid.queryCircle(
|
|
5332
|
+
const list = pointVirtualGrid.queryCircle(point2, threshold).filter((item) => item.userData !== line && item.userData?.vertical(line)).sort((item02, item1) => item02.point.distance(point2) - item1.point.distance(point2));
|
|
5324
5333
|
if (!list.length) return;
|
|
5325
5334
|
const item0 = list[0];
|
|
5326
|
-
const pPoint = item0.userData?.projectPoint(
|
|
5335
|
+
const pPoint = item0.userData?.projectPoint(point2, false);
|
|
5327
5336
|
if (pPoint) {
|
|
5328
5337
|
const line0 = item0.userData;
|
|
5329
|
-
setPoint(line, new LineSegment(
|
|
5338
|
+
setPoint(line, new LineSegment(point2.clone(), pPoint.clone()));
|
|
5330
5339
|
setPoint(line0, new LineSegment(item0.point.clone(), pPoint.clone()));
|
|
5331
5340
|
}
|
|
5332
5341
|
}
|
|
5333
|
-
function handle(line,
|
|
5342
|
+
function handle(line, point2, intersectList) {
|
|
5334
5343
|
return null;
|
|
5335
5344
|
}
|
|
5336
5345
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -5341,12 +5350,12 @@ function adsorption(lines, intersectionMap, option) {
|
|
|
5341
5350
|
else groups2[1].push(item);
|
|
5342
5351
|
return groups2;
|
|
5343
5352
|
}, [[], []]);
|
|
5344
|
-
const [isStart, isEnd] = line.points.map((
|
|
5345
|
-
if (!pointVirtualGrid.queryPoint(
|
|
5346
|
-
const newPoint = handle(line,
|
|
5353
|
+
const [isStart, isEnd] = line.points.map((point2, j) => {
|
|
5354
|
+
if (!pointVirtualGrid.queryPoint(point2, true).length) {
|
|
5355
|
+
const newPoint = handle(line, point2, groups[j]);
|
|
5347
5356
|
if (newPoint) {
|
|
5348
|
-
|
|
5349
|
-
pointVirtualGrid.update(
|
|
5357
|
+
point2.copy(newPoint);
|
|
5358
|
+
pointVirtualGrid.update(point2);
|
|
5350
5359
|
quadtree.update(line);
|
|
5351
5360
|
} else return false;
|
|
5352
5361
|
}
|
|
@@ -5392,8 +5401,8 @@ function doorRecover(doorLines) {
|
|
|
5392
5401
|
doorLine.start.copy(startIntersection.end);
|
|
5393
5402
|
}
|
|
5394
5403
|
} else {
|
|
5395
|
-
const
|
|
5396
|
-
|
|
5404
|
+
const point2 = startIntersection.projectPoint(doorLine.start);
|
|
5405
|
+
point2 && doorLine.start.copy(point2);
|
|
5397
5406
|
}
|
|
5398
5407
|
if (doorLine.parallel(endIntersection, 45)) {
|
|
5399
5408
|
if (doorLine.end.distance(endIntersection.start) < doorLine.end.distance(endIntersection.end)) {
|
|
@@ -5402,8 +5411,8 @@ function doorRecover(doorLines) {
|
|
|
5402
5411
|
doorLine.end.copy(endIntersection.end);
|
|
5403
5412
|
}
|
|
5404
5413
|
} else {
|
|
5405
|
-
const
|
|
5406
|
-
|
|
5414
|
+
const point2 = endIntersection.projectPoint(doorLine.end);
|
|
5415
|
+
point2 && doorLine.end.copy(point2);
|
|
5407
5416
|
}
|
|
5408
5417
|
lines.push(startIntersection, endIntersection);
|
|
5409
5418
|
}
|
|
@@ -5414,32 +5423,32 @@ function doorAdsorption(lines, doorLines) {
|
|
|
5414
5423
|
const quadtree = createQuadtree(lines);
|
|
5415
5424
|
for (let i = 0; i < doorLines.length; i++) {
|
|
5416
5425
|
const doorLine = doorLines[i];
|
|
5417
|
-
doorLine.points.map((
|
|
5418
|
-
if (quadtree.queryPoint(
|
|
5419
|
-
const otherPoint = doorLine.getAnotherPoint(
|
|
5426
|
+
doorLine.points.map((point2) => {
|
|
5427
|
+
if (quadtree.queryPoint(point2).length !== 0) return;
|
|
5428
|
+
const otherPoint = doorLine.getAnotherPoint(point2), queryLine = point2.expandAsLine(point2.direction(otherPoint), 0.4);
|
|
5420
5429
|
const list = grid.queryCircle(queryLine.center, 0.4).flatMap((item) => {
|
|
5421
5430
|
if (item.userData?.vertical(doorLine, 35)) {
|
|
5422
|
-
const pPoint = item.userData.projectPoint(
|
|
5431
|
+
const pPoint = item.userData.projectPoint(point2);
|
|
5423
5432
|
if (pPoint) {
|
|
5424
5433
|
return [item.point, pPoint];
|
|
5425
5434
|
}
|
|
5426
5435
|
}
|
|
5427
5436
|
return [item.point];
|
|
5428
|
-
}).sort((a, b) => a.distance(
|
|
5437
|
+
}).sort((a, b) => a.distance(point2) - b.distance(point2));
|
|
5429
5438
|
if (list.length) {
|
|
5430
|
-
|
|
5439
|
+
point2.copy(list[0]);
|
|
5431
5440
|
} else {
|
|
5432
5441
|
const list2 = quadtree.queryLineSegment(queryLine).flatMap((item) => {
|
|
5433
5442
|
if (item.line.vertical(doorLine, 35)) {
|
|
5434
|
-
const pPoint = item.line.projectPoint(
|
|
5443
|
+
const pPoint = item.line.projectPoint(point2);
|
|
5435
5444
|
if (pPoint) {
|
|
5436
5445
|
return [pPoint];
|
|
5437
5446
|
}
|
|
5438
5447
|
}
|
|
5439
5448
|
return [];
|
|
5440
|
-
}).sort((a, b) => a.distance(
|
|
5449
|
+
}).sort((a, b) => a.distance(point2) - b.distance(point2));
|
|
5441
5450
|
if (list2.length) {
|
|
5442
|
-
|
|
5451
|
+
point2.copy(list2[0]);
|
|
5443
5452
|
}
|
|
5444
5453
|
}
|
|
5445
5454
|
});
|
|
@@ -5552,21 +5561,21 @@ function getIntersection(line, mode, cell) {
|
|
|
5552
5561
|
}, [-1, -1, -1]);
|
|
5553
5562
|
}
|
|
5554
5563
|
function createNewLine(cell, reference, opt, appendLines, grid) {
|
|
5555
|
-
const { point } = cell[opt[0]];
|
|
5556
|
-
const newLine = new LineSegment(
|
|
5564
|
+
const { point: point2 } = cell[opt[0]];
|
|
5565
|
+
const newLine = new LineSegment(point2.clone(), reference.clone());
|
|
5557
5566
|
newLine.points.forEach((p) => grid.insert(p, newLine));
|
|
5558
5567
|
appendLines.push(newLine);
|
|
5559
5568
|
return newLine;
|
|
5560
5569
|
}
|
|
5561
5570
|
function setSameDirection(cell, reference, opt, grid) {
|
|
5562
|
-
const { point } = cell[opt[1]];
|
|
5563
|
-
|
|
5564
|
-
grid.update(
|
|
5571
|
+
const { point: point2 } = cell[opt[1]];
|
|
5572
|
+
point2.copy(reference);
|
|
5573
|
+
grid.update(point2);
|
|
5565
5574
|
}
|
|
5566
5575
|
function setDifferentDirection(cell, reference, opt, grid) {
|
|
5567
|
-
const { point } = cell[opt[2]];
|
|
5568
|
-
|
|
5569
|
-
grid.update(
|
|
5576
|
+
const { point: point2 } = cell[opt[2]];
|
|
5577
|
+
point2.copy(reference);
|
|
5578
|
+
grid.update(point2);
|
|
5570
5579
|
}
|
|
5571
5580
|
function modify(reference, cell, opt, appendLines, grid) {
|
|
5572
5581
|
const hasParallel = opt[0] > -1, hasSameDirection = opt[1] > -1, hasDifferentDirection = opt[2] > -1;
|
|
@@ -5623,9 +5632,9 @@ class BoundExt {
|
|
|
5623
5632
|
}
|
|
5624
5633
|
const center = line.center;
|
|
5625
5634
|
const set2 = /* @__PURE__ */ new Set();
|
|
5626
|
-
for (const
|
|
5635
|
+
for (const point2 of trajectoryPoints) {
|
|
5627
5636
|
if (set2.size === 2) break;
|
|
5628
|
-
const lineA = new LineSegment(center,
|
|
5637
|
+
const lineA = new LineSegment(center, point2);
|
|
5629
5638
|
const list = quadtree.queryLineSegment(lineA).filter((target) => {
|
|
5630
5639
|
if (target.line === line) return false;
|
|
5631
5640
|
if (LineGroupType.hasGroup(line)) return true;
|
|
@@ -5638,7 +5647,7 @@ class BoundExt {
|
|
|
5638
5647
|
return true;
|
|
5639
5648
|
});
|
|
5640
5649
|
if (!list.length) {
|
|
5641
|
-
const position = line.pointPosition(
|
|
5650
|
+
const position = line.pointPosition(point2);
|
|
5642
5651
|
position !== "on" && set2.add(position);
|
|
5643
5652
|
}
|
|
5644
5653
|
}
|
|
@@ -5729,16 +5738,16 @@ function findMinRing(lines, ringEdges) {
|
|
|
5729
5738
|
const center = line.center, direct = line.normal();
|
|
5730
5739
|
temLine.start.copy(center);
|
|
5731
5740
|
temLine.end.copy(center).add(direct.clone().multiplyScalar(1));
|
|
5732
|
-
const
|
|
5733
|
-
temLine.end.copy(
|
|
5741
|
+
const point2 = preDirect.getIntersection(temLine);
|
|
5742
|
+
temLine.end.copy(point2);
|
|
5734
5743
|
return temLine.clone();
|
|
5735
5744
|
}
|
|
5736
|
-
function find(edge, line,
|
|
5745
|
+
function find(edge, line, point2, preLine, preDirect, path, isPreDirect = true) {
|
|
5737
5746
|
if (path.length > lines.length) return;
|
|
5738
5747
|
if (visited.has(line)) return;
|
|
5739
5748
|
visited.add(line);
|
|
5740
5749
|
let direct;
|
|
5741
|
-
const otherPoint = line.getAnotherPoint(
|
|
5750
|
+
const otherPoint = line.getAnotherPoint(point2);
|
|
5742
5751
|
if (isPreDirect) {
|
|
5743
5752
|
if (line.vertical(preLine)) direct = getDirect(line, preDirect);
|
|
5744
5753
|
else {
|
|
@@ -5751,7 +5760,7 @@ function findMinRing(lines, ringEdges) {
|
|
|
5751
5760
|
const item = result[0], nextLine = item.userData, otherPoint1 = nextLine.getAnotherPoint(item.point), d0 = otherPoint1.direction(item.point);
|
|
5752
5761
|
if (edge === nextLine) return path;
|
|
5753
5762
|
if (nextLine.vertical(line)) {
|
|
5754
|
-
const d1 = otherPoint.direction(
|
|
5763
|
+
const d1 = otherPoint.direction(point2), center = nextLine.center, isSameDirection = d0.angleBetween(direct.direction()) < 1e-9;
|
|
5755
5764
|
direct.start.copy(center);
|
|
5756
5765
|
direct.end.copy(center).add(d1.multiplyScalar(0.02));
|
|
5757
5766
|
if (isSameDirection) direct.end.rotate(direct.start, Math.PI);
|
|
@@ -6010,9 +6019,9 @@ function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
|
6010
6019
|
newLines = LineSegmentUndirectedGraph.rotate(newLines, angle, (line, center, angle2) => {
|
|
6011
6020
|
if (line.userData.drawWindow) {
|
|
6012
6021
|
line.userData.drawWindow.forEach((windowItem) => {
|
|
6013
|
-
const
|
|
6014
|
-
|
|
6015
|
-
windowItem.p =
|
|
6022
|
+
const point2 = Point.from(windowItem.p);
|
|
6023
|
+
point2.rotate(center, angle2 * (Math.PI / 180));
|
|
6024
|
+
windowItem.p = point2.toJson(windowItem.p.z);
|
|
6016
6025
|
});
|
|
6017
6026
|
}
|
|
6018
6027
|
});
|
|
@@ -6023,6 +6032,38 @@ function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
|
6023
6032
|
}
|
|
6024
6033
|
};
|
|
6025
6034
|
}
|
|
6035
|
+
const point = new Point();
|
|
6036
|
+
class HeightQuery {
|
|
6037
|
+
static query(line, rootTopContourInfo) {
|
|
6038
|
+
const inLinePoints = [], len = line.length(), newLine = line.clone(), center = line.center;
|
|
6039
|
+
newLine.startShrink(len * 0.2);
|
|
6040
|
+
newLine.endShrink(len * 0.2);
|
|
6041
|
+
inLinePoints.push([center.x, center.y], [newLine.start.x, newLine.start.y], [newLine.end.x, newLine.end.y]);
|
|
6042
|
+
const contoursData = this.whichContourContainsPoint(inLinePoints, rootTopContourInfo);
|
|
6043
|
+
contoursData.sort((a, b) => a.averagePz - b.averagePz);
|
|
6044
|
+
const height = contoursData[0]?.averagePz ?? DEFAULT_WALL_HEIGHT;
|
|
6045
|
+
return height;
|
|
6046
|
+
}
|
|
6047
|
+
static whichContourContainsPoint(points, rootTopContourInfo) {
|
|
6048
|
+
const contoursData = [], { contours, maxContourIndex, quadtree } = rootTopContourInfo;
|
|
6049
|
+
points.filter((p) => {
|
|
6050
|
+
point.set(p[0], p[1]);
|
|
6051
|
+
for (let i = 0; i < contours.length; i++) {
|
|
6052
|
+
const { contour, polygon } = contours[i];
|
|
6053
|
+
if (!contour.length || i === maxContourIndex) continue;
|
|
6054
|
+
if (polygon?.pointIn(point)) contoursData.push({ i, averagePz: contours[i].averagePz });
|
|
6055
|
+
}
|
|
6056
|
+
});
|
|
6057
|
+
if (contoursData.length) return contoursData;
|
|
6058
|
+
points.filter((p) => {
|
|
6059
|
+
point.set(p[0], p[1]);
|
|
6060
|
+
new Array(...new Set(quadtree?.queryCircle(point, 0.4).map((item) => item.line.currentData.contourIndex))).forEach((index2) => {
|
|
6061
|
+
contoursData.push({ i: index2, averagePz: contours[index2].averagePz });
|
|
6062
|
+
});
|
|
6063
|
+
});
|
|
6064
|
+
return contoursData;
|
|
6065
|
+
}
|
|
6066
|
+
}
|
|
6026
6067
|
const PRE_PROCESSOR = {
|
|
6027
6068
|
DoorsAnalysis(lines) {
|
|
6028
6069
|
return lines;
|
|
@@ -6085,8 +6126,6 @@ class Dxf extends Component {
|
|
|
6085
6126
|
verticalReferenceLine;
|
|
6086
6127
|
originalZAverage = 0;
|
|
6087
6128
|
_preProcessorSet = /* @__PURE__ */ new Set();
|
|
6088
|
-
trajectory = null;
|
|
6089
|
-
onBoundExt;
|
|
6090
6129
|
/** 原始数据组
|
|
6091
6130
|
*/
|
|
6092
6131
|
get lines() {
|
|
@@ -6099,9 +6138,25 @@ class Dxf extends Component {
|
|
|
6099
6138
|
super();
|
|
6100
6139
|
this.width = width;
|
|
6101
6140
|
}
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
|
|
6141
|
+
/** 添加预处理
|
|
6142
|
+
* @param handler
|
|
6143
|
+
*/
|
|
6144
|
+
addPreProcessor(handler) {
|
|
6145
|
+
this._preProcessorSet.add(handler);
|
|
6146
|
+
return this;
|
|
6147
|
+
}
|
|
6148
|
+
/** 删除预处理
|
|
6149
|
+
* @param handler
|
|
6150
|
+
*/
|
|
6151
|
+
removePreProcessor(handler) {
|
|
6152
|
+
this._preProcessorSet.delete(handler);
|
|
6153
|
+
return this;
|
|
6154
|
+
}
|
|
6155
|
+
/** 清空预处理
|
|
6156
|
+
* @returns
|
|
6157
|
+
*/
|
|
6158
|
+
clearPreProcessor() {
|
|
6159
|
+
this._preProcessorSet.clear();
|
|
6105
6160
|
return this;
|
|
6106
6161
|
}
|
|
6107
6162
|
/** 完整线段数据
|
|
@@ -6128,8 +6183,27 @@ class Dxf extends Component {
|
|
|
6128
6183
|
preprocessing(data, options) {
|
|
6129
6184
|
let { lineSegments, originalZAverage } = originalDataToLineData(data);
|
|
6130
6185
|
this.originalZAverage = originalZAverage;
|
|
6186
|
+
if (options?.publicInfo?.rootTopContourInfo) {
|
|
6187
|
+
const polygons = options.publicInfo.rootTopContourInfo.contours.map((item) => {
|
|
6188
|
+
if (!item.polygon) Object.defineProperty(item, "polygon", { value: new Polygon(Point.fromByList(item.contour)) });
|
|
6189
|
+
return item.polygon;
|
|
6190
|
+
});
|
|
6191
|
+
if (!options.publicInfo.rootTopContourInfo.quadtree) {
|
|
6192
|
+
const lines = polygons.flatMap((polygon, index2) => {
|
|
6193
|
+
const lines2 = polygon?.toLines() ?? [];
|
|
6194
|
+
lines2.forEach((line) => line.currentData.contourIndex = index2);
|
|
6195
|
+
return lines2;
|
|
6196
|
+
});
|
|
6197
|
+
const quadtree = createQuadtree(lines);
|
|
6198
|
+
Object.defineProperty(options.publicInfo.rootTopContourInfo, "quadtree", { value: quadtree });
|
|
6199
|
+
}
|
|
6200
|
+
}
|
|
6131
6201
|
lineSegments.forEach((line) => {
|
|
6132
6202
|
if (line.userData.isDoor && line.userData.doorDirectConnection) this.doorLineSegment.push(line);
|
|
6203
|
+
if (!("height" in line.userData)) {
|
|
6204
|
+
if (typeof line.userData.rooftopPz === "number") line.userData.height = Math.abs(line.userData.rooftopPz - originalZAverage);
|
|
6205
|
+
else if (options?.publicInfo?.rootTopContourInfo) line.userData.height = HeightQuery.query(line, options.publicInfo.rootTopContourInfo);
|
|
6206
|
+
}
|
|
6133
6207
|
});
|
|
6134
6208
|
this._preProcessorSet.forEach((handler) => {
|
|
6135
6209
|
lineSegments = handler(lineSegments, options);
|
|
@@ -6138,27 +6212,6 @@ class Dxf extends Component {
|
|
|
6138
6212
|
this.verticalReferenceLine.userData.isVerticalReferenceLine = true;
|
|
6139
6213
|
return { lineSegments, data };
|
|
6140
6214
|
}
|
|
6141
|
-
/** 添加预处理
|
|
6142
|
-
* @param handler
|
|
6143
|
-
*/
|
|
6144
|
-
addPreProcessor(handler) {
|
|
6145
|
-
this._preProcessorSet.add(handler);
|
|
6146
|
-
return this;
|
|
6147
|
-
}
|
|
6148
|
-
/** 删除预处理
|
|
6149
|
-
* @param handler
|
|
6150
|
-
*/
|
|
6151
|
-
removePreProcessor(handler) {
|
|
6152
|
-
this._preProcessorSet.delete(handler);
|
|
6153
|
-
return this;
|
|
6154
|
-
}
|
|
6155
|
-
/** 清空预处理
|
|
6156
|
-
* @returns
|
|
6157
|
-
*/
|
|
6158
|
-
clearPreProcessor() {
|
|
6159
|
-
this._preProcessorSet.clear();
|
|
6160
|
-
return this;
|
|
6161
|
-
}
|
|
6162
6215
|
/** 设置
|
|
6163
6216
|
* @param data 房屋结构数据,node环境可以为路径
|
|
6164
6217
|
* @param width 墙体宽度
|
|
@@ -6167,6 +6220,7 @@ class Dxf extends Component {
|
|
|
6167
6220
|
* @param option
|
|
6168
6221
|
* @returns
|
|
6169
6222
|
*/
|
|
6223
|
+
options = {};
|
|
6170
6224
|
async set(data, options = {}) {
|
|
6171
6225
|
if (typeof data === "string") {
|
|
6172
6226
|
if (typeof global !== "undefined") {
|
|
@@ -6183,6 +6237,7 @@ class Dxf extends Component {
|
|
|
6183
6237
|
if (data.length === 0) return;
|
|
6184
6238
|
this.doorLineSegment.length = 0;
|
|
6185
6239
|
this.cad = null;
|
|
6240
|
+
this.options = options;
|
|
6186
6241
|
if (data.length === 0) {
|
|
6187
6242
|
this.lineSegments = [];
|
|
6188
6243
|
this.originalData = data;
|
|
@@ -6199,12 +6254,14 @@ class Dxf extends Component {
|
|
|
6199
6254
|
this.dispatchEvent({
|
|
6200
6255
|
type: "dataChange",
|
|
6201
6256
|
originalData: this.originalData,
|
|
6202
|
-
data: this.data
|
|
6257
|
+
data: this.data,
|
|
6258
|
+
options
|
|
6203
6259
|
});
|
|
6204
6260
|
this.dispatchEvent({
|
|
6205
6261
|
type: "setDta",
|
|
6206
6262
|
originalData: this.originalData,
|
|
6207
|
-
data: this.data
|
|
6263
|
+
data: this.data,
|
|
6264
|
+
options
|
|
6208
6265
|
});
|
|
6209
6266
|
let lines = this.getLineSegments(true);
|
|
6210
6267
|
const doors = lines.filter((line) => line.userData.isDoor);
|
|
@@ -6214,11 +6271,13 @@ class Dxf extends Component {
|
|
|
6214
6271
|
this.cad = new CAD().usePlugin(new DxfDataPlugin(lines)).usePlugin(new DxfDrawPlugin());
|
|
6215
6272
|
this.dispatchEvent({
|
|
6216
6273
|
type: "cadChange",
|
|
6217
|
-
cad: this.cad
|
|
6274
|
+
cad: this.cad,
|
|
6275
|
+
options
|
|
6218
6276
|
});
|
|
6219
6277
|
this.dispatchEvent({
|
|
6220
6278
|
type: "lineOffset",
|
|
6221
|
-
cad: this.cad
|
|
6279
|
+
cad: this.cad,
|
|
6280
|
+
options
|
|
6222
6281
|
});
|
|
6223
6282
|
}
|
|
6224
6283
|
/**
|
|
@@ -6383,11 +6442,11 @@ class DoorsAnalysis {
|
|
|
6383
6442
|
}
|
|
6384
6443
|
return false;
|
|
6385
6444
|
});
|
|
6386
|
-
this.addPointsExcludeRule((_1,
|
|
6387
|
-
return !!this.doorPoint.find((p1) => p1.point.equal(
|
|
6445
|
+
this.addPointsExcludeRule((_1, point2) => {
|
|
6446
|
+
return !!this.doorPoint.find((p1) => p1.point.equal(point2));
|
|
6388
6447
|
});
|
|
6389
|
-
this.addPointsExcludeRule((_1,
|
|
6390
|
-
return !!this.calculatedDoorPoint.find((p1) => p1.point.equal(
|
|
6448
|
+
this.addPointsExcludeRule((_1, point2) => {
|
|
6449
|
+
return !!this.calculatedDoorPoint.find((p1) => p1.point.equal(point2));
|
|
6391
6450
|
});
|
|
6392
6451
|
this.possibleDoorPoints = this.getPossiblePoints();
|
|
6393
6452
|
this.possibleDoorPoints.forEach((p) => {
|
|
@@ -6430,10 +6489,10 @@ class DoorsAnalysis {
|
|
|
6430
6489
|
if (len < minDoorWidth) return;
|
|
6431
6490
|
const normal = line.normal(), direction = line.direction(), step = (len - dxf.width * 2) / 2;
|
|
6432
6491
|
for (let i = 0; i < 3; i++) {
|
|
6433
|
-
const
|
|
6492
|
+
const point2 = line.start.clone().add(direction.clone().multiplyScalar(dxf.width + step * i));
|
|
6434
6493
|
const rLine = new LineSegment(
|
|
6435
|
-
|
|
6436
|
-
|
|
6494
|
+
point2,
|
|
6495
|
+
point2.clone().add(normal.clone().multiplyScalar(1))
|
|
6437
6496
|
);
|
|
6438
6497
|
rLine.directionMove(normal, -0.5);
|
|
6439
6498
|
const res = this.quadtree.queryLineSegment(rLine);
|
|
@@ -6478,8 +6537,8 @@ class DoorsAnalysis {
|
|
|
6478
6537
|
if (doorData.doorDirectConnection) {
|
|
6479
6538
|
this.continueFind = false;
|
|
6480
6539
|
this.dxf.doorLineSegment.push(doorLine);
|
|
6481
|
-
doorLine.points.forEach((
|
|
6482
|
-
const res = pointVirtualGrid.queryPoint(
|
|
6540
|
+
doorLine.points.forEach((point2) => {
|
|
6541
|
+
const res = pointVirtualGrid.queryPoint(point2);
|
|
6483
6542
|
if (res.length) {
|
|
6484
6543
|
calculatedDoorPoint.push({
|
|
6485
6544
|
line: res[0].userData,
|
|
@@ -6489,19 +6548,19 @@ class DoorsAnalysis {
|
|
|
6489
6548
|
}
|
|
6490
6549
|
});
|
|
6491
6550
|
} else if (doorData.drawDoorData) {
|
|
6492
|
-
const
|
|
6551
|
+
const point2 = Point.from(doorData.drawDoorData.start);
|
|
6493
6552
|
const direct = Point.from(doorData.drawDoorData.n);
|
|
6494
|
-
const resList = pointVirtualGrid.queryPoint(
|
|
6553
|
+
const resList = pointVirtualGrid.queryPoint(point2).filter((res) => {
|
|
6495
6554
|
if (res.userData === doorLine) return false;
|
|
6496
6555
|
const line = res.userData;
|
|
6497
6556
|
const direct2 = line.direction();
|
|
6498
|
-
if (line.start.equal(
|
|
6557
|
+
if (line.start.equal(point2)) direct2.multiplyScalar(-1);
|
|
6499
6558
|
const angle = direct.angleBetween(direct2, "angle");
|
|
6500
6559
|
return angle > 180 - 10 || angle < 10;
|
|
6501
6560
|
});
|
|
6502
6561
|
if (resList.length) doorPoints.push({
|
|
6503
6562
|
line: resList[0].userData,
|
|
6504
|
-
point,
|
|
6563
|
+
point: point2,
|
|
6505
6564
|
uuid: uuid()
|
|
6506
6565
|
});
|
|
6507
6566
|
} else {
|
|
@@ -6537,10 +6596,10 @@ class DoorsAnalysis {
|
|
|
6537
6596
|
*/
|
|
6538
6597
|
searchNearby(doorPoints, possibleDoorPoints = [], doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
|
|
6539
6598
|
const findPointVirtualGrid = this.findPointVirtualGrid, quadtree = this.quadtree;
|
|
6540
|
-
function find({ point, line }, doorIndex, record2) {
|
|
6599
|
+
function find({ point: point2, line }, doorIndex, record2) {
|
|
6541
6600
|
const direct = line.direction();
|
|
6542
|
-
if (line.start ===
|
|
6543
|
-
const res = findPointVirtualGrid.queryCircle(
|
|
6601
|
+
if (line.start === point2) direct.multiplyScalar(-1);
|
|
6602
|
+
const res = findPointVirtualGrid.queryCircle(point2, doorSearchDistance).filter((r) => r.userData !== line).sort((a, b) => a.point.distance(point2) - b.point.distance(point2));
|
|
6544
6603
|
const list = [];
|
|
6545
6604
|
for (let i = 0; i < res.length; i++) {
|
|
6546
6605
|
const doorIndex2 = possibleDoorPoints.findIndex((p) => p.point === res[i].point);
|
|
@@ -6549,7 +6608,7 @@ class DoorsAnalysis {
|
|
|
6549
6608
|
if (record2.has(`${id1}.${id2}`)) continue;
|
|
6550
6609
|
record2.add(`${id1}.${id2}`);
|
|
6551
6610
|
record2.add(`${id2}.${id1}`);
|
|
6552
|
-
const targetPoint = res[i].point, line2 = new LineSegment(
|
|
6611
|
+
const targetPoint = res[i].point, line2 = new LineSegment(point2.clone(), targetPoint.clone()), angle = line2.direction().angleBetween(direct, "angle");
|
|
6553
6612
|
if (angle < doorSearchNearAngle) {
|
|
6554
6613
|
const direct2 = doorPoints[doorIndex].line.direction();
|
|
6555
6614
|
const line22 = res[i].userData;
|
|
@@ -6557,7 +6616,7 @@ class DoorsAnalysis {
|
|
|
6557
6616
|
const angle2 = line2.direction().multiplyScalar(-1).angleBetween(direct2, "angle");
|
|
6558
6617
|
if (angle2 < doorSearchNearAngle) {
|
|
6559
6618
|
const queryList = quadtree.queryLineSegment(line2).filter((item) => {
|
|
6560
|
-
if (item.line.start.equal(
|
|
6619
|
+
if (item.line.start.equal(point2) || item.line.end.equal(point2)) return false;
|
|
6561
6620
|
if (item.line === line22) return false;
|
|
6562
6621
|
return true;
|
|
6563
6622
|
});
|
|
@@ -6679,17 +6738,17 @@ class DoorsAnalysis {
|
|
|
6679
6738
|
* @param param0
|
|
6680
6739
|
* @returns
|
|
6681
6740
|
*/
|
|
6682
|
-
searchAlongDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
|
|
6741
|
+
searchAlongDirection({ point: point2, line }, doorSearchDistance = this.doorSearchDistance) {
|
|
6683
6742
|
const quadtree = this.quadtree;
|
|
6684
6743
|
const direct = line.direction();
|
|
6685
|
-
if (line.start ===
|
|
6686
|
-
const endPoint =
|
|
6744
|
+
if (line.start === point2) direct.multiplyScalar(-1);
|
|
6745
|
+
const endPoint = point2.clone().add(direct.clone().multiplyScalar(doorSearchDistance)), rline = new LineSegment(point2.clone(), endPoint), result = quadtree.queryLineSegment(rline).map((l) => {
|
|
6687
6746
|
const res = l.line.getIntersection(rline);
|
|
6688
6747
|
return {
|
|
6689
6748
|
point: res,
|
|
6690
6749
|
line: l.line
|
|
6691
6750
|
};
|
|
6692
|
-
}).filter((i) => i.point).sort((a, b) =>
|
|
6751
|
+
}).filter((i) => i.point).sort((a, b) => point2.distance(a.point) - point2.distance(b.point));
|
|
6693
6752
|
if (result.length) {
|
|
6694
6753
|
const item = result[0];
|
|
6695
6754
|
if (Math.abs(90 - item.line.direction().angleBetween(direct, "angle")) < 5) {
|
|
@@ -6703,10 +6762,10 @@ class DoorsAnalysis {
|
|
|
6703
6762
|
* @param doorSearchDistance
|
|
6704
6763
|
* @returns
|
|
6705
6764
|
*/
|
|
6706
|
-
searchAlongNormalDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
|
|
6765
|
+
searchAlongNormalDirection({ point: point2, line }, doorSearchDistance = this.doorSearchDistance) {
|
|
6707
6766
|
const pointVirtualGrid = this.pointVirtualGrid, quadtree = this.quadtree, direct = line.direction(), normal = line.start.normal(line.end), prePoint = line.start.clone();
|
|
6708
|
-
if (line.start ===
|
|
6709
|
-
if (line.start ===
|
|
6767
|
+
if (line.start === point2) direct.multiplyScalar(-1);
|
|
6768
|
+
if (line.start === point2) prePoint.copy(line.end);
|
|
6710
6769
|
const result = pointVirtualGrid.queryPoint(prePoint).filter((r) => r.userData !== line);
|
|
6711
6770
|
for (let i = 0; i < result.length; i++) {
|
|
6712
6771
|
const element = result[i];
|
|
@@ -6719,14 +6778,14 @@ class DoorsAnalysis {
|
|
|
6719
6778
|
break;
|
|
6720
6779
|
}
|
|
6721
6780
|
}
|
|
6722
|
-
const rline3 = new LineSegment(
|
|
6781
|
+
const rline3 = new LineSegment(point2.clone(), point2.clone().add(normal.multiplyScalar(doorSearchDistance)));
|
|
6723
6782
|
const r3 = quadtree.queryLineSegment(rline3).map((l) => {
|
|
6724
6783
|
const res = l.line.getIntersection(rline3);
|
|
6725
6784
|
return {
|
|
6726
6785
|
point: res,
|
|
6727
6786
|
line: l.line
|
|
6728
6787
|
};
|
|
6729
|
-
}).filter((i) => i.point).sort((a, b) =>
|
|
6788
|
+
}).filter((i) => i.point).sort((a, b) => point2.distance(a.point) - point2.distance(b.point));
|
|
6730
6789
|
if (r3.length) {
|
|
6731
6790
|
const item = r3[0];
|
|
6732
6791
|
if (Math.abs(90 - item.line.direction().angleBetween(normal, "angle")) < 5) {
|
|
@@ -6927,25 +6986,25 @@ function drawLines$1(lines, parameters, offset = 1e-3) {
|
|
|
6927
6986
|
}
|
|
6928
6987
|
}
|
|
6929
6988
|
}
|
|
6930
|
-
function drawPoint(
|
|
6989
|
+
function drawPoint(point2, parameters, offset = 1e-3) {
|
|
6931
6990
|
const dxfSystem = DxfSystem.finalInstance;
|
|
6932
6991
|
if (dxfSystem) {
|
|
6933
6992
|
const renderer = dxfSystem.findComponentByName("Renderer");
|
|
6934
6993
|
if (renderer) {
|
|
6935
6994
|
const editor = dxfSystem.findComponentByName("Editor");
|
|
6936
|
-
const obj3d = renderer.createCircle(
|
|
6995
|
+
const obj3d = renderer.createCircle(point2, parameters, editor?.container);
|
|
6937
6996
|
obj3d.position.z = offset;
|
|
6938
6997
|
return obj3d;
|
|
6939
6998
|
}
|
|
6940
6999
|
}
|
|
6941
7000
|
}
|
|
6942
|
-
function drawText$1(text,
|
|
7001
|
+
function drawText$1(text, point2, style, offset = 1e-3) {
|
|
6943
7002
|
const dxfSystem = DxfSystem.finalInstance;
|
|
6944
7003
|
if (dxfSystem) {
|
|
6945
7004
|
const renderer = dxfSystem.findComponentByName("Renderer");
|
|
6946
7005
|
const editor = dxfSystem.findComponentByName("Editor");
|
|
6947
7006
|
if (renderer) {
|
|
6948
|
-
const obj3d = renderer.createText(text,
|
|
7007
|
+
const obj3d = renderer.createText(text, point2, style, editor?.container);
|
|
6949
7008
|
obj3d.position.z = offset;
|
|
6950
7009
|
return obj3d;
|
|
6951
7010
|
}
|
|
@@ -7091,6 +7150,7 @@ class Scenario {
|
|
|
7091
7150
|
// 饮水机
|
|
7092
7151
|
height;
|
|
7093
7152
|
expandedList;
|
|
7153
|
+
wallHeight;
|
|
7094
7154
|
static _instance;
|
|
7095
7155
|
static get Instance() {
|
|
7096
7156
|
return Scenario._instance;
|
|
@@ -7126,6 +7186,7 @@ class Scenario {
|
|
|
7126
7186
|
this.WindowGroundHeight = WINDOW_GROUND_CLEARANCE_HEIGHT;
|
|
7127
7187
|
this.height = 0;
|
|
7128
7188
|
this.expandedList = [];
|
|
7189
|
+
this.wallHeight = DEFAULT_WALL_HEIGHT;
|
|
7129
7190
|
}
|
|
7130
7191
|
// 绘制图形
|
|
7131
7192
|
async drawGraphics(lines, z, trajectoryJson) {
|
|
@@ -7187,6 +7248,15 @@ class Scenario {
|
|
|
7187
7248
|
this.TheHandlingOfTheDoor(menList);
|
|
7188
7249
|
this.overallTreatmentOfSingleLineWalls(singleLineWall);
|
|
7189
7250
|
for (const g in groups) {
|
|
7251
|
+
let wallHeight = 20;
|
|
7252
|
+
for (const x in groups[g]) {
|
|
7253
|
+
if (groups[g][x].userData.height < wallHeight) {
|
|
7254
|
+
wallHeight = groups[g][x].userData.height;
|
|
7255
|
+
}
|
|
7256
|
+
}
|
|
7257
|
+
if (wallHeight === 20) {
|
|
7258
|
+
wallHeight = this.wallHeight;
|
|
7259
|
+
}
|
|
7190
7260
|
const a = clippingDoubleWall(groups[g]);
|
|
7191
7261
|
for (const i in a) {
|
|
7192
7262
|
let bitem = a[i].slice();
|
|
@@ -7241,7 +7311,7 @@ class Scenario {
|
|
|
7241
7311
|
}
|
|
7242
7312
|
return false;
|
|
7243
7313
|
});
|
|
7244
|
-
const Mesh = this.drawTheModel(E, 0, Number(i));
|
|
7314
|
+
const Mesh = this.drawTheModel(E, 0, Number(i), wallHeight);
|
|
7245
7315
|
Mesh.material.envMap = texture;
|
|
7246
7316
|
Mesh.material.needsUpdate = true;
|
|
7247
7317
|
const doubleLinesWindow = doubleWinDrawLine(a[i]);
|
|
@@ -7249,23 +7319,23 @@ class Scenario {
|
|
|
7249
7319
|
let houMesh = null;
|
|
7250
7320
|
for (const x in doubleLinesWindow) {
|
|
7251
7321
|
if (doubleLinesWindow.length === 1) {
|
|
7252
|
-
const edges = new THREE.EdgesGeometry(this.windowTreatment(doubleLinesWindow[x], Mesh).geometry);
|
|
7322
|
+
const edges = new THREE.EdgesGeometry(this.windowTreatment(doubleLinesWindow[x], Mesh, wallHeight).geometry);
|
|
7253
7323
|
new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0 }));
|
|
7254
7324
|
this.installWindows(doubleLinesWindow[x], x);
|
|
7255
|
-
this.group.add(this.windowTreatment(doubleLinesWindow[x], Mesh));
|
|
7325
|
+
this.group.add(this.windowTreatment(doubleLinesWindow[x], Mesh, wallHeight));
|
|
7256
7326
|
} else if (houMesh) {
|
|
7257
7327
|
if (Number(x) === doubleLinesWindow.length - 1) {
|
|
7258
|
-
const edges = new THREE.EdgesGeometry(this.windowTreatment(doubleLinesWindow[x], houMesh).geometry);
|
|
7328
|
+
const edges = new THREE.EdgesGeometry(this.windowTreatment(doubleLinesWindow[x], houMesh, wallHeight).geometry);
|
|
7259
7329
|
new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0 }));
|
|
7260
7330
|
this.installWindows(doubleLinesWindow[x], x);
|
|
7261
|
-
this.group.add(this.windowTreatment(doubleLinesWindow[x], houMesh));
|
|
7331
|
+
this.group.add(this.windowTreatment(doubleLinesWindow[x], houMesh, wallHeight));
|
|
7262
7332
|
} else {
|
|
7263
7333
|
this.installWindows(doubleLinesWindow[x], x);
|
|
7264
|
-
houMesh = this.windowTreatment(doubleLinesWindow[x], houMesh);
|
|
7334
|
+
houMesh = this.windowTreatment(doubleLinesWindow[x], houMesh, wallHeight);
|
|
7265
7335
|
}
|
|
7266
7336
|
} else {
|
|
7267
7337
|
this.installWindows(doubleLinesWindow[x], x);
|
|
7268
|
-
houMesh = this.windowTreatment(doubleLinesWindow[x], Mesh);
|
|
7338
|
+
houMesh = this.windowTreatment(doubleLinesWindow[x], Mesh, wallHeight);
|
|
7269
7339
|
}
|
|
7270
7340
|
}
|
|
7271
7341
|
} else {
|
|
@@ -7275,7 +7345,7 @@ class Scenario {
|
|
|
7275
7345
|
}
|
|
7276
7346
|
}
|
|
7277
7347
|
// 绘制模型
|
|
7278
|
-
drawTheModel(data, num, index2) {
|
|
7348
|
+
drawTheModel(data, num, index2, wallHeight) {
|
|
7279
7349
|
const basePoints = [
|
|
7280
7350
|
new THREE.Vector3(data[0].x, data[0].y, this.height ? this.height : 0),
|
|
7281
7351
|
new THREE.Vector3(data[1].x, data[1].y, this.height ? this.height : 0),
|
|
@@ -7283,7 +7353,7 @@ class Scenario {
|
|
|
7283
7353
|
// 可以不是矩形
|
|
7284
7354
|
new THREE.Vector3(data[3].x, data[3].y, this.height ? this.height : 0)
|
|
7285
7355
|
];
|
|
7286
|
-
const geometry = this.createParallelepipedFromBase(basePoints,
|
|
7356
|
+
const geometry = this.createParallelepipedFromBase(basePoints, wallHeight);
|
|
7287
7357
|
const material = new THREE.MeshStandardMaterial({
|
|
7288
7358
|
color: this.color,
|
|
7289
7359
|
side: THREE.DoubleSide
|
|
@@ -7307,10 +7377,11 @@ class Scenario {
|
|
|
7307
7377
|
return cube;
|
|
7308
7378
|
}
|
|
7309
7379
|
// 执行偏移
|
|
7310
|
-
executionOffset(data, index2) {
|
|
7380
|
+
executionOffset(data, index2, wallHeight) {
|
|
7381
|
+
const wallHeightc = wallHeight ? wallHeight : this.wallHeight;
|
|
7311
7382
|
const points = [];
|
|
7312
|
-
points.push(new THREE.Vector3(data.start.x, data.start.y,
|
|
7313
|
-
points.push(new THREE.Vector3(data.end.x, data.end.y,
|
|
7383
|
+
points.push(new THREE.Vector3(data.start.x, data.start.y, wallHeightc));
|
|
7384
|
+
points.push(new THREE.Vector3(data.end.x, data.end.y, wallHeightc));
|
|
7314
7385
|
new THREE.BufferGeometry().setFromPoints(points);
|
|
7315
7386
|
new THREE.LineBasicMaterial({
|
|
7316
7387
|
color: 65280
|
|
@@ -7322,12 +7393,12 @@ class Scenario {
|
|
|
7322
7393
|
const grid = createPointVirtualGrid(this.lines);
|
|
7323
7394
|
const isDouble = grid.queryCircle(Point.from(data.start), 1e-3).some((item) => LineGroupType.hasType(item.userData, "doubleWall") || item.userData?.userData.isDoor);
|
|
7324
7395
|
const isDouble1 = grid.queryCircle(Point.from(data.end), 1e-3).some((item) => LineGroupType.hasType(item.userData, "doubleWall") || item.userData?.userData.isDoor);
|
|
7325
|
-
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 0);
|
|
7326
|
-
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 1);
|
|
7396
|
+
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 0, wallHeightc);
|
|
7397
|
+
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 1, wallHeightc);
|
|
7327
7398
|
if (isDouble && isDouble1) {
|
|
7328
7399
|
startingPoint.push(finishLine[1]);
|
|
7329
7400
|
startingPoint.push(finishLine[0]);
|
|
7330
|
-
return this.drawTheModel(startingPoint, 1, index2);
|
|
7401
|
+
return this.drawTheModel(startingPoint, 1, index2, wallHeightc);
|
|
7331
7402
|
}
|
|
7332
7403
|
if (isDouble && !isDouble1) {
|
|
7333
7404
|
let status = false;
|
|
@@ -7337,15 +7408,15 @@ class Scenario {
|
|
|
7337
7408
|
}
|
|
7338
7409
|
}
|
|
7339
7410
|
if (status) {
|
|
7340
|
-
finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7411
|
+
finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7341
7412
|
startingPoint.push(finishLine1[1]);
|
|
7342
7413
|
startingPoint.push(finishLine1[0]);
|
|
7343
|
-
return this.drawTheModel(startingPoint, 1, index2);
|
|
7414
|
+
return this.drawTheModel(startingPoint, 1, index2, wallHeightc);
|
|
7344
7415
|
} else {
|
|
7345
7416
|
this.expandedList.push(data.end);
|
|
7346
7417
|
startingPoint.push(finishLine1[1]);
|
|
7347
7418
|
startingPoint.push(finishLine1[0]);
|
|
7348
|
-
return this.drawTheModel(startingPoint, 1, index2);
|
|
7419
|
+
return this.drawTheModel(startingPoint, 1, index2, wallHeightc);
|
|
7349
7420
|
}
|
|
7350
7421
|
}
|
|
7351
7422
|
if (!isDouble && isDouble1) {
|
|
@@ -7356,15 +7427,15 @@ class Scenario {
|
|
|
7356
7427
|
}
|
|
7357
7428
|
}
|
|
7358
7429
|
if (status) {
|
|
7359
|
-
startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7430
|
+
startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7360
7431
|
startingPoint1.push(finishLine[1]);
|
|
7361
7432
|
startingPoint1.push(finishLine[0]);
|
|
7362
|
-
return this.drawTheModel(startingPoint1, 1, index2);
|
|
7433
|
+
return this.drawTheModel(startingPoint1, 1, index2, wallHeightc);
|
|
7363
7434
|
} else {
|
|
7364
7435
|
this.expandedList.push(data.start);
|
|
7365
7436
|
startingPoint1.push(finishLine[1]);
|
|
7366
7437
|
startingPoint1.push(finishLine[0]);
|
|
7367
|
-
return this.drawTheModel(startingPoint1, 1, index2);
|
|
7438
|
+
return this.drawTheModel(startingPoint1, 1, index2, wallHeightc);
|
|
7368
7439
|
}
|
|
7369
7440
|
}
|
|
7370
7441
|
if (!isDouble && !isDouble1) {
|
|
@@ -7379,50 +7450,51 @@ class Scenario {
|
|
|
7379
7450
|
}
|
|
7380
7451
|
}
|
|
7381
7452
|
if (statua && statub) {
|
|
7382
|
-
startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7383
|
-
finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7453
|
+
startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7454
|
+
finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7384
7455
|
startingPoint1.push(finishLine1[1]);
|
|
7385
7456
|
startingPoint1.push(finishLine1[0]);
|
|
7386
|
-
return this.drawTheModel(startingPoint1, 1, index2);
|
|
7457
|
+
return this.drawTheModel(startingPoint1, 1, index2, wallHeightc);
|
|
7387
7458
|
} else if (statua && !statub) {
|
|
7388
7459
|
this.expandedList.push(data.end);
|
|
7389
|
-
startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7460
|
+
startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7390
7461
|
startingPoint1.push(finishLine1[1]);
|
|
7391
7462
|
startingPoint1.push(finishLine1[0]);
|
|
7392
|
-
return this.drawTheModel(startingPoint1, 1, index2);
|
|
7463
|
+
return this.drawTheModel(startingPoint1, 1, index2, wallHeightc);
|
|
7393
7464
|
} else if (!statua && statub) {
|
|
7394
7465
|
this.expandedList.push(data.start);
|
|
7395
|
-
finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7466
|
+
finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7396
7467
|
startingPoint1.push(finishLine1[1]);
|
|
7397
7468
|
startingPoint1.push(finishLine1[0]);
|
|
7398
|
-
return this.drawTheModel(startingPoint1, 1, index2);
|
|
7469
|
+
return this.drawTheModel(startingPoint1, 1, index2, wallHeightc);
|
|
7399
7470
|
} else if (!statua && !statub) {
|
|
7400
7471
|
this.expandedList.push(data.start);
|
|
7401
7472
|
this.expandedList.push(data.end);
|
|
7402
7473
|
startingPoint1.push(finishLine1[1]);
|
|
7403
7474
|
startingPoint1.push(finishLine1[0]);
|
|
7404
|
-
return this.drawTheModel(startingPoint1, 1, index2);
|
|
7475
|
+
return this.drawTheModel(startingPoint1, 1, index2, wallHeightc);
|
|
7405
7476
|
}
|
|
7406
7477
|
}
|
|
7407
7478
|
}
|
|
7408
7479
|
// 窗的处理
|
|
7409
|
-
windowTreatment(dblWin, mesh) {
|
|
7480
|
+
windowTreatment(dblWin, mesh, wallHeight) {
|
|
7410
7481
|
const doorList = dblWin;
|
|
7411
7482
|
const MobileX = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, doorList.userData.wallWidth ? doorList.userData.wallWidth + 1e-4 : 0.5, true);
|
|
7412
7483
|
const MobileY = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, doorList.userData.wallWidth ? doorList.userData.wallWidth + 1e-4 : 0.5, false);
|
|
7413
|
-
let startingPoint = this.xinLine(MobileX, MobileY, doorList.start,
|
|
7414
|
-
let finishLine = this.xinLine(MobileX, MobileY, doorList.end,
|
|
7484
|
+
let startingPoint = this.xinLine(MobileX, MobileY, doorList.start, wallHeight);
|
|
7485
|
+
let finishLine = this.xinLine(MobileX, MobileY, doorList.end, wallHeight);
|
|
7415
7486
|
startingPoint.push(finishLine[1]);
|
|
7416
7487
|
startingPoint.push(finishLine[0]);
|
|
7417
7488
|
return this.winHoleOpening(startingPoint, mesh, dblWin.userData.groundClearance, dblWin.userData.height);
|
|
7418
7489
|
}
|
|
7419
7490
|
// 门体的处理
|
|
7420
7491
|
TheHandlingOfTheDoor1(data) {
|
|
7492
|
+
const wallHeightc = data.userData.height ? data.userData.height : this.wallHeight;
|
|
7421
7493
|
const doorList = data;
|
|
7422
7494
|
const MobileX = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, DEFAULT_WALL_HALF_WIDTH + 1e-3, true);
|
|
7423
7495
|
const MobileY = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, DEFAULT_WALL_HALF_WIDTH + 1e-3, false);
|
|
7424
|
-
let startingPoint = this.xinLine(MobileX, MobileY, doorList.start,
|
|
7425
|
-
let finishLine = this.xinLine(MobileX, MobileY, doorList.end,
|
|
7496
|
+
let startingPoint = this.xinLine(MobileX, MobileY, doorList.start, doorList.userData.height ? doorList.userData.height : this.wallHeight);
|
|
7497
|
+
let finishLine = this.xinLine(MobileX, MobileY, doorList.end, doorList.userData.height ? doorList.userData.height : this.wallHeight);
|
|
7426
7498
|
const quadtree = createQuadtree(this.lines);
|
|
7427
7499
|
const doorPoint = doorList.start;
|
|
7428
7500
|
const doorPoint1 = doorList.end;
|
|
@@ -7435,18 +7507,18 @@ class Scenario {
|
|
|
7435
7507
|
return item.line.vertical(doorList, 20) && !LineGroupType.hasType(item.line, "doubleWall");
|
|
7436
7508
|
});
|
|
7437
7509
|
if (statua && !statub) {
|
|
7438
|
-
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7510
|
+
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7439
7511
|
startingPoint1.push(finishLine[1]);
|
|
7440
7512
|
startingPoint1.push(finishLine[0]);
|
|
7441
7513
|
return startingPoint1;
|
|
7442
7514
|
} else if (!statua && statub) {
|
|
7443
|
-
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7515
|
+
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7444
7516
|
startingPoint.push(finishLine1[1]);
|
|
7445
7517
|
startingPoint.push(finishLine1[0]);
|
|
7446
7518
|
return startingPoint;
|
|
7447
7519
|
} else if (statua && statub) {
|
|
7448
|
-
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7449
|
-
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7520
|
+
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7521
|
+
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7450
7522
|
startingPoint1.push(finishLine1[1]);
|
|
7451
7523
|
startingPoint1.push(finishLine1[0]);
|
|
7452
7524
|
return startingPoint1;
|
|
@@ -7460,6 +7532,7 @@ class Scenario {
|
|
|
7460
7532
|
TheHandlingOfTheDoor(data) {
|
|
7461
7533
|
const doorList = data;
|
|
7462
7534
|
for (const i in doorList) {
|
|
7535
|
+
const wallHeightc = data[i].userData.height ? data[i].userData.height : this.wallHeight;
|
|
7463
7536
|
const point1 = new THREE.Vector3(doorList[i].start.x, doorList[i].start.y, 0);
|
|
7464
7537
|
const point2 = new THREE.Vector3(doorList[i].end.x, doorList[i].end.y, 0);
|
|
7465
7538
|
const point3 = new THREE.Vector3(doorList[i].center.x, doorList[i].center.y, 0);
|
|
@@ -7469,8 +7542,8 @@ class Scenario {
|
|
|
7469
7542
|
const distance = point1.distanceTo(point2);
|
|
7470
7543
|
const MobileX = this.angleToXAxisDegrees(doorList[i].start.x, doorList[i].start.y, doorList[i].end.x, doorList[i].end.y, DEFAULT_WALL_HALF_WIDTH, true);
|
|
7471
7544
|
const MobileY = this.angleToXAxisDegrees(doorList[i].start.x, doorList[i].start.y, doorList[i].end.x, doorList[i].end.y, DEFAULT_WALL_HALF_WIDTH, false);
|
|
7472
|
-
let startingPoint = this.xinLine(MobileX, MobileY, doorList[i].start,
|
|
7473
|
-
let finishLine = this.xinLine(MobileX, MobileY, doorList[i].end,
|
|
7545
|
+
let startingPoint = this.xinLine(MobileX, MobileY, doorList[i].start, doorList[i].userData.height ? doorList[i].userData.height : this.wallHeight);
|
|
7546
|
+
let finishLine = this.xinLine(MobileX, MobileY, doorList[i].end, doorList[i].userData.height ? doorList[i].userData.height : this.wallHeight);
|
|
7474
7547
|
const quadtree = createQuadtree(this.lines);
|
|
7475
7548
|
const doorPoint = doorList[i].start;
|
|
7476
7549
|
const doorPoint1 = doorList[i].end;
|
|
@@ -7483,32 +7556,32 @@ class Scenario {
|
|
|
7483
7556
|
return item.line.vertical(doorList[i], 20) && !LineGroupType.hasType(item.line, "doubleWall");
|
|
7484
7557
|
});
|
|
7485
7558
|
if (statua && !statub) {
|
|
7486
|
-
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7559
|
+
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7487
7560
|
startingPoint1.push(finishLine[1]);
|
|
7488
7561
|
startingPoint1.push(finishLine[0]);
|
|
7489
|
-
this.doorHoleOpening(startingPoint1, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData?.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance - DEFAULT_WALL_HALF_WIDTH, this.doorCenterOffset(0.03, doorList[i].end, point3), angleRad, i);
|
|
7562
|
+
this.doorHoleOpening(wallHeightc, startingPoint1, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData?.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance - DEFAULT_WALL_HALF_WIDTH, this.doorCenterOffset(0.03, doorList[i].end, point3), angleRad, i);
|
|
7490
7563
|
} else if (!statua && statub) {
|
|
7491
|
-
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7564
|
+
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7492
7565
|
startingPoint.push(finishLine1[1]);
|
|
7493
7566
|
startingPoint.push(finishLine1[0]);
|
|
7494
|
-
this.doorHoleOpening(startingPoint, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance - DEFAULT_WALL_HALF_WIDTH, this.doorCenterOffset(0.03, doorList[i].start, point3), angleRad, i);
|
|
7567
|
+
this.doorHoleOpening(wallHeightc, startingPoint, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance - DEFAULT_WALL_HALF_WIDTH, this.doorCenterOffset(0.03, doorList[i].start, point3), angleRad, i);
|
|
7495
7568
|
} else if (statua && statub) {
|
|
7496
|
-
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1);
|
|
7497
|
-
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0);
|
|
7569
|
+
let startingPoint1 = this.xinLine1(MobileY, MobileX, startingPoint[0], startingPoint[1], 1, wallHeightc);
|
|
7570
|
+
let finishLine1 = this.xinLine1(MobileY, MobileX, finishLine[0], finishLine[1], 0, wallHeightc);
|
|
7498
7571
|
startingPoint1.push(finishLine1[1]);
|
|
7499
7572
|
startingPoint1.push(finishLine1[0]);
|
|
7500
|
-
this.doorHoleOpening(startingPoint1, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance - DEFAULT_WALL_WIDTH, point3, angleRad, i);
|
|
7573
|
+
this.doorHoleOpening(wallHeightc, startingPoint1, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance - DEFAULT_WALL_WIDTH, point3, angleRad, i);
|
|
7501
7574
|
} else {
|
|
7502
7575
|
startingPoint.push(finishLine[1]);
|
|
7503
7576
|
startingPoint.push(finishLine[0]);
|
|
7504
|
-
this.doorHoleOpening(startingPoint, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance, point3, angleRad, i);
|
|
7577
|
+
this.doorHoleOpening(wallHeightc, startingPoint, this.TheHandlingOfTheDoor1(doorList[i]), doorList[i].userData.drawDoorData?.groundClearance, doorList[i].userData.drawDoorData?.height, distance, point3, angleRad, i);
|
|
7505
7578
|
}
|
|
7506
7579
|
}
|
|
7507
7580
|
}
|
|
7508
7581
|
// 门中心偏移
|
|
7509
|
-
doorCenterOffset(distanceFromB,
|
|
7510
|
-
|
|
7511
|
-
const direction = new THREE.Vector3().subVectors(pointc,
|
|
7582
|
+
doorCenterOffset(distanceFromB, point2, pointc) {
|
|
7583
|
+
point2 = new THREE.Vector3(point2.x, point2.y, 0);
|
|
7584
|
+
const direction = new THREE.Vector3().subVectors(pointc, point2).normalize();
|
|
7512
7585
|
const point3 = new THREE.Vector3().copy(pointc).addScaledVector(direction.negate(), distanceFromB);
|
|
7513
7586
|
return point3;
|
|
7514
7587
|
}
|
|
@@ -7607,7 +7680,7 @@ class Scenario {
|
|
|
7607
7680
|
return result;
|
|
7608
7681
|
}
|
|
7609
7682
|
// 门扣洞
|
|
7610
|
-
doorHoleOpening(data, data1, groundHeight, Height, distance, center, angleRad, index2) {
|
|
7683
|
+
doorHoleOpening(wallHeight, data, data1, groundHeight, Height, distance, center, angleRad, index2) {
|
|
7611
7684
|
groundHeight = (groundHeight ?? this.doorGroundHeight) + this.height;
|
|
7612
7685
|
const basePoints = [
|
|
7613
7686
|
new THREE.Vector3(data[0].x, data[0].y, groundHeight),
|
|
@@ -7630,7 +7703,7 @@ class Scenario {
|
|
|
7630
7703
|
// 可以不是矩形
|
|
7631
7704
|
new THREE.Vector3(data[3].x, data1[3].y, groundHeight)
|
|
7632
7705
|
];
|
|
7633
|
-
const geometry = this.createParallelepipedFromBase(basePoints,
|
|
7706
|
+
const geometry = this.createParallelepipedFromBase(basePoints, wallHeight);
|
|
7634
7707
|
const geometry1 = this.createParallelepipedFromBase(basePoints1, Height ? Height : this.doorHeight);
|
|
7635
7708
|
const geometry2 = this.createParallelepipedFromBase(basePoints2, Height ? Height : this.doorHeight);
|
|
7636
7709
|
const brush1 = new Brush(geometry);
|
|
@@ -7693,21 +7766,21 @@ class Scenario {
|
|
|
7693
7766
|
}
|
|
7694
7767
|
}
|
|
7695
7768
|
// 外偏移点坐标
|
|
7696
|
-
xinLine(x, y,
|
|
7697
|
-
const point1 = new THREE.Vector3(
|
|
7698
|
-
const
|
|
7699
|
-
return [point1,
|
|
7769
|
+
xinLine(x, y, point2, wallHeight) {
|
|
7770
|
+
const point1 = new THREE.Vector3(point2.x + x, point2.y - y, wallHeight);
|
|
7771
|
+
const point22 = new THREE.Vector3(point2.x - x, point2.y + y, wallHeight);
|
|
7772
|
+
return [point1, point22];
|
|
7700
7773
|
}
|
|
7701
7774
|
// 内偏移点坐标
|
|
7702
|
-
xinLine1(x, y, pointa, pointb, num) {
|
|
7775
|
+
xinLine1(x, y, pointa, pointb, num, wallHeight) {
|
|
7703
7776
|
let point1;
|
|
7704
7777
|
let point2;
|
|
7705
7778
|
if (num === 0) {
|
|
7706
|
-
point1 = new THREE.Vector3(pointa.x - x, pointa.y - y,
|
|
7707
|
-
point2 = new THREE.Vector3(pointb.x - x, pointb.y - y,
|
|
7779
|
+
point1 = new THREE.Vector3(pointa.x - x, pointa.y - y, wallHeight);
|
|
7780
|
+
point2 = new THREE.Vector3(pointb.x - x, pointb.y - y, wallHeight);
|
|
7708
7781
|
} else {
|
|
7709
|
-
point1 = new THREE.Vector3(pointa.x + x, pointa.y + y,
|
|
7710
|
-
point2 = new THREE.Vector3(pointb.x + x, pointb.y + y,
|
|
7782
|
+
point1 = new THREE.Vector3(pointa.x + x, pointa.y + y, wallHeight);
|
|
7783
|
+
point2 = new THREE.Vector3(pointb.x + x, pointb.y + y, wallHeight);
|
|
7711
7784
|
}
|
|
7712
7785
|
return [point1, point2];
|
|
7713
7786
|
}
|
|
@@ -7736,22 +7809,22 @@ class Scenario {
|
|
|
7736
7809
|
if (listS.length === 0) {
|
|
7737
7810
|
const b = new THREE.Vector3(bitem[i].start.x, bitem[i].start.y, bitem[i].start.z);
|
|
7738
7811
|
const c = new THREE.Vector3(bitem[i].end.x, bitem[i].end.y, bitem[i].end.z);
|
|
7739
|
-
listS.push({ dian: b, zhong: i });
|
|
7740
|
-
listS.push({ dian: c, zhong: i });
|
|
7812
|
+
listS.push({ dian: b, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7813
|
+
listS.push({ dian: c, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7741
7814
|
} else {
|
|
7742
7815
|
const b = new THREE.Vector3(bitem[i].start.x, bitem[i].start.y, bitem[i].start.z);
|
|
7743
7816
|
const c = new THREE.Vector3(bitem[i].end.x, bitem[i].end.y, bitem[i].end.z);
|
|
7744
7817
|
const distanceAB = listS[listS.length - 1].dian.distanceTo(b);
|
|
7745
7818
|
const distanceAC = listS[listS.length - 1].dian.distanceTo(c);
|
|
7746
7819
|
if (distanceAB < distanceAC) {
|
|
7747
|
-
listS.push({ dian: b, zhong: i });
|
|
7748
|
-
listS.push({ dian: c, zhong: i });
|
|
7820
|
+
listS.push({ dian: b, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7821
|
+
listS.push({ dian: c, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7749
7822
|
} else if (distanceAC < distanceAB) {
|
|
7750
|
-
listS.push({ dian: c, zhong: i });
|
|
7751
|
-
listS.push({ dian: b, zhong: i });
|
|
7823
|
+
listS.push({ dian: c, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7824
|
+
listS.push({ dian: b, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7752
7825
|
} else {
|
|
7753
|
-
listS.push({ dian: b, zhong: i });
|
|
7754
|
-
listS.push({ dian: c, zhong: i });
|
|
7826
|
+
listS.push({ dian: b, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7827
|
+
listS.push({ dian: c, zhong: i, wallHeight: bitem[i].userData.height ? bitem[i].userData.height : this.wallHeight });
|
|
7755
7828
|
}
|
|
7756
7829
|
}
|
|
7757
7830
|
}
|
|
@@ -7789,34 +7862,35 @@ class Scenario {
|
|
|
7789
7862
|
} else {
|
|
7790
7863
|
a = { start: listS[x].dian, end: listS[Number(x) + 1].dian, isTheFirst: true, index: x };
|
|
7791
7864
|
}
|
|
7792
|
-
|
|
7865
|
+
const wallHeight = listS[x].wallHeight;
|
|
7866
|
+
let Mesh = this.executionOffset(a, Number(x) / 2, wallHeight);
|
|
7793
7867
|
if (winDraw && winDraw.length > 0) {
|
|
7794
7868
|
let houMesh = null;
|
|
7795
7869
|
for (const x2 in winDraw) {
|
|
7796
7870
|
if (winDraw.length === 1) {
|
|
7797
|
-
const edges = new THREE.EdgesGeometry(this.windowTreatment(winDraw[x2], Mesh).geometry);
|
|
7871
|
+
const edges = new THREE.EdgesGeometry(this.windowTreatment(winDraw[x2], Mesh, wallHeight).geometry);
|
|
7798
7872
|
new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0 }));
|
|
7799
7873
|
this.installWindows(winDraw[x2], x2);
|
|
7800
|
-
let mesh = this.windowTreatment(winDraw[x2], Mesh);
|
|
7874
|
+
let mesh = this.windowTreatment(winDraw[x2], Mesh, wallHeight);
|
|
7801
7875
|
mesh.name = `单线墙_${Number(x2) / 2}`;
|
|
7802
7876
|
mesh.userData.category = "wall";
|
|
7803
7877
|
this.group.add(mesh);
|
|
7804
7878
|
} else if (houMesh) {
|
|
7805
7879
|
if (Number(x2) === winDraw.length - 1) {
|
|
7806
|
-
const edges = new THREE.EdgesGeometry(this.windowTreatment(winDraw[x2], houMesh).geometry);
|
|
7880
|
+
const edges = new THREE.EdgesGeometry(this.windowTreatment(winDraw[x2], houMesh, wallHeight).geometry);
|
|
7807
7881
|
this.installWindows(winDraw[x2], x2);
|
|
7808
7882
|
new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ color: 0 }));
|
|
7809
|
-
let mesh = this.windowTreatment(winDraw[x2], houMesh);
|
|
7883
|
+
let mesh = this.windowTreatment(winDraw[x2], houMesh, wallHeight);
|
|
7810
7884
|
mesh.name = `单线墙_${Number(x2) / 2}`;
|
|
7811
7885
|
mesh.userData.category = "wall";
|
|
7812
7886
|
this.group.add(mesh);
|
|
7813
7887
|
} else {
|
|
7814
7888
|
this.installWindows(winDraw[x2], x2);
|
|
7815
|
-
houMesh = this.windowTreatment(winDraw[x2], houMesh);
|
|
7889
|
+
houMesh = this.windowTreatment(winDraw[x2], houMesh, wallHeight);
|
|
7816
7890
|
}
|
|
7817
7891
|
} else {
|
|
7818
7892
|
this.installWindows(winDraw[x2], x2);
|
|
7819
|
-
houMesh = this.windowTreatment(winDraw[x2], Mesh);
|
|
7893
|
+
houMesh = this.windowTreatment(winDraw[x2], Mesh, wallHeight);
|
|
7820
7894
|
}
|
|
7821
7895
|
}
|
|
7822
7896
|
} else {
|
|
@@ -7827,6 +7901,50 @@ class Scenario {
|
|
|
7827
7901
|
}
|
|
7828
7902
|
}
|
|
7829
7903
|
}
|
|
7904
|
+
//
|
|
7905
|
+
createAPlane(lines, menList) {
|
|
7906
|
+
const lineList = lines;
|
|
7907
|
+
console.log("初始数据", lines);
|
|
7908
|
+
let precision = lineList.map((pos) => {
|
|
7909
|
+
pos.start.x = parseFloat(pos.start.x.toFixed(3));
|
|
7910
|
+
pos.start.y = parseFloat(pos.start.y.toFixed(3));
|
|
7911
|
+
pos.end.x = parseFloat(pos.end.x.toFixed(3));
|
|
7912
|
+
pos.end.y = parseFloat(pos.end.y.toFixed(3));
|
|
7913
|
+
return pos;
|
|
7914
|
+
});
|
|
7915
|
+
let points = [];
|
|
7916
|
+
let head = null;
|
|
7917
|
+
let theTail = null;
|
|
7918
|
+
for (const x in precision) {
|
|
7919
|
+
if (x === "0") {
|
|
7920
|
+
head = precision[x].start;
|
|
7921
|
+
theTail = precision[x].end;
|
|
7922
|
+
points.push([precision[x].start.x, precision[x].start.y]);
|
|
7923
|
+
points.push([precision[x].end.x, precision[x].end.y]);
|
|
7924
|
+
} else {
|
|
7925
|
+
if (precision[x].start.x === head.x && precision[x].start.y === head.y) {
|
|
7926
|
+
points.push([precision[x].end.x, precision[x].end.y]);
|
|
7927
|
+
theTail = precision[x].end;
|
|
7928
|
+
} else if (precision[x].end.x === head.x && precision[x].end.y === head.y) {
|
|
7929
|
+
points.push([precision[x].start.x, precision[x].start.y]);
|
|
7930
|
+
head = precision[x].start;
|
|
7931
|
+
} else if (precision[x].start.x === theTail.x && precision[x].start.y === theTail.y) {
|
|
7932
|
+
points.push([precision[x].end.x, precision[x].end.y]);
|
|
7933
|
+
head = theTail;
|
|
7934
|
+
theTail = precision[x].end;
|
|
7935
|
+
} else if (precision[x].end.x === theTail.x && precision[x].end.y === theTail.y) {
|
|
7936
|
+
points.push([precision[x].start.x, precision[x].start.y]);
|
|
7937
|
+
head = precision[x].start;
|
|
7938
|
+
} else {
|
|
7939
|
+
points.push([precision[x].start.x, precision[x].start.y]);
|
|
7940
|
+
head = precision[x].start;
|
|
7941
|
+
points.push([precision[x].end.x, precision[x].end.y]);
|
|
7942
|
+
theTail = precision[x].end;
|
|
7943
|
+
}
|
|
7944
|
+
}
|
|
7945
|
+
}
|
|
7946
|
+
return;
|
|
7947
|
+
}
|
|
7830
7948
|
// 获取门模型
|
|
7831
7949
|
async modelLoader() {
|
|
7832
7950
|
this.doorModely = await LoadModel.loadGlb("door");
|
|
@@ -15059,7 +15177,8 @@ class WhiteModel extends Component {
|
|
|
15059
15177
|
onAddFromParent(parent) {
|
|
15060
15178
|
this.Dxf = parent.findComponentByName("Dxf");
|
|
15061
15179
|
this.Variable = parent.findComponentByName("Variable");
|
|
15062
|
-
this.Dxf?.addEventListener("cadChange", () => {
|
|
15180
|
+
this.Dxf?.addEventListener("cadChange", ({ options }) => {
|
|
15181
|
+
this.setItemList(options?.publicInfo ?? []);
|
|
15063
15182
|
this.promise = this.updateModel();
|
|
15064
15183
|
});
|
|
15065
15184
|
}
|
|
@@ -15708,13 +15827,13 @@ async function buildJson(opt) {
|
|
|
15708
15827
|
trajectory = JSON.parse(buffer.toString("utf-8"));
|
|
15709
15828
|
} else throw new Error("非node环境不允许使用路径");
|
|
15710
15829
|
}
|
|
15711
|
-
dxfSystem.CorrectionDxf.setTrajectory(trajectory);
|
|
15712
15830
|
}
|
|
15713
15831
|
await dxfSystem.Dxf.set(json, {
|
|
15714
15832
|
groupMethod: "cross",
|
|
15715
15833
|
fittingMethod: "max",
|
|
15716
15834
|
crossAxistThreshold: 0.08,
|
|
15717
|
-
...axisAlignCorrOption
|
|
15835
|
+
...axisAlignCorrOption,
|
|
15836
|
+
trajectory
|
|
15718
15837
|
});
|
|
15719
15838
|
download?.json && await dxfSystem.Dxf.downloadOriginalData(download.json);
|
|
15720
15839
|
download?.dxf && await dxfSystem.Dxf.downloadDxf(download.dxf);
|