build-dxf 0.1.84 → 0.1.86
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 +386 -257
- package/src/utils/DxfSystem/utils/index.d.ts +0 -1
- package/src/utils/DxfSystem/utils/lineHandle/CadPreProcessor/axisAlignCorr.d.ts +11 -1
- package/src/utils/DxfSystem/utils/tools/lineDataToThreeVJiaJson.d.ts +1 -1
- package/src/utils/algorithmsStructures/LineSegment.d.ts +2 -2
- package/src/utils/algorithmsStructures/Point.d.ts +4 -0
- package/src/utils/modelScenario/scenario.d.ts +2 -2
- package/src/utils/DxfSystem/utils/lineHandle/AxisAlignCorr.d.ts +0 -12
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -1562,19 +1562,21 @@ class LineSegment {
|
|
|
1562
1562
|
* 两条线段或角度是否平行,忽略方向
|
|
1563
1563
|
* @param line
|
|
1564
1564
|
*/
|
|
1565
|
-
isParallelTo(
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1565
|
+
isParallelTo(line, eps = 1) {
|
|
1566
|
+
const d1 = this.direction();
|
|
1567
|
+
const d2 = line.direction();
|
|
1568
|
+
const angle = d1.angle(d2, { unit: "degree", range: "180" });
|
|
1569
|
+
return Math.min(angle, 180 - angle) < eps;
|
|
1569
1570
|
}
|
|
1570
1571
|
/** 两条线段或角度是否 垂直, 忽略方向
|
|
1571
1572
|
* @param line
|
|
1572
1573
|
* @param errAngle
|
|
1573
1574
|
* @returns
|
|
1574
1575
|
*/
|
|
1575
|
-
isPerpendicularTo(
|
|
1576
|
-
|
|
1577
|
-
|
|
1576
|
+
isPerpendicularTo(line, eps = 1) {
|
|
1577
|
+
const d1 = this.direction();
|
|
1578
|
+
const d2 = line.direction();
|
|
1579
|
+
const angle = d1.angle(d2, { unit: "degree", range: "180" });
|
|
1578
1580
|
return Math.abs(angle - 90) < eps;
|
|
1579
1581
|
}
|
|
1580
1582
|
/**
|
|
@@ -2286,6 +2288,7 @@ class LineSegment {
|
|
|
2286
2288
|
};
|
|
2287
2289
|
}
|
|
2288
2290
|
}
|
|
2291
|
+
const PRECISION = 1e-6;
|
|
2289
2292
|
class Point {
|
|
2290
2293
|
x;
|
|
2291
2294
|
y;
|
|
@@ -2428,6 +2431,14 @@ class Point {
|
|
|
2428
2431
|
this.y = Number(this.y.toFixed(count));
|
|
2429
2432
|
return this;
|
|
2430
2433
|
}
|
|
2434
|
+
/** 精度处理
|
|
2435
|
+
* @returns
|
|
2436
|
+
*/
|
|
2437
|
+
precision() {
|
|
2438
|
+
this.x = Math.round(this.x / PRECISION) * PRECISION;
|
|
2439
|
+
this.y = Math.round(this.y / PRECISION) * PRECISION;
|
|
2440
|
+
return this;
|
|
2441
|
+
}
|
|
2431
2442
|
/**
|
|
2432
2443
|
* 归一化
|
|
2433
2444
|
* @description 将当前点的坐标归一化为单位向量
|
|
@@ -3310,7 +3321,7 @@ function findDiscretePointLine2(lines, lineSet, deep = false) {
|
|
|
3310
3321
|
lines.forEach((line) => {
|
|
3311
3322
|
if (lineSet.size && lineSet.has(line)) return;
|
|
3312
3323
|
line.points.forEach((p2) => {
|
|
3313
|
-
const id = p2.hashCode();
|
|
3324
|
+
const id = p2.hashCode(4);
|
|
3314
3325
|
if (!map.has(id)) map.set(id, /* @__PURE__ */ new Set());
|
|
3315
3326
|
map.get(id)?.add(line);
|
|
3316
3327
|
});
|
|
@@ -6655,8 +6666,7 @@ function buildDoubleWallGroup_(lines_, clearInternalLine = false) {
|
|
|
6655
6666
|
// peDoors,
|
|
6656
6667
|
peDoubleDoors
|
|
6657
6668
|
} = initData(lines_);
|
|
6658
|
-
const {
|
|
6659
|
-
otherLines.push(...notFoundLines);
|
|
6669
|
+
const { circlesList } = getPeDoubleDoorCircles(otherLines, peDoubleDoors);
|
|
6660
6670
|
let { internalEdges, circles } = maxiCircles.maxiCircles(otherLines, (circles2) => circles2.filter(isPolyHasTrajectoryPoint));
|
|
6661
6671
|
const { circles: finalCircles } = maxiCircles.mergeCircles([...circlesList, ...circles], internalEdges);
|
|
6662
6672
|
lines_.forEach((line) => LineGroupType.removeByTypes(line, ["doubleWall", "wall"]));
|
|
@@ -6817,7 +6827,8 @@ class DoubleWallHelper {
|
|
|
6817
6827
|
lines = lineSegmentClipping(lines, 1e-9);
|
|
6818
6828
|
quadtree.clear();
|
|
6819
6829
|
lines.push(...otherLines);
|
|
6820
|
-
|
|
6830
|
+
Point.adsorb(lines.flatMap((line) => line.points), 1e-4);
|
|
6831
|
+
return lines.filter((line) => line.length() > 1e-5);
|
|
6821
6832
|
}
|
|
6822
6833
|
/**
|
|
6823
6834
|
* 创建分组
|
|
@@ -7398,6 +7409,7 @@ class ThreeVJiaJson extends Pipeline {
|
|
|
7398
7409
|
*/
|
|
7399
7410
|
wallHoleHandle({ data: { lines, json } }) {
|
|
7400
7411
|
lines.forEach((line) => {
|
|
7412
|
+
if (line.length() < 1e-4) return;
|
|
7401
7413
|
let type = holeTypeMap[line.userData.type] ?? "WALL_HOLE";
|
|
7402
7414
|
const hole = {
|
|
7403
7415
|
id: this.index++,
|
|
@@ -7418,8 +7430,8 @@ class ThreeVJiaJson extends Pipeline {
|
|
|
7418
7430
|
* @param param0
|
|
7419
7431
|
* @returns
|
|
7420
7432
|
*/
|
|
7421
|
-
balconyRailing({ data }) {
|
|
7422
|
-
|
|
7433
|
+
balconyRailing({ data: { lines }, cache }) {
|
|
7434
|
+
cache.wallLines.push(...lines);
|
|
7423
7435
|
}
|
|
7424
7436
|
/** 转换
|
|
7425
7437
|
* @returns
|
|
@@ -7447,7 +7459,7 @@ class ThreeVJiaJson extends Pipeline {
|
|
|
7447
7459
|
ID: this.index++,
|
|
7448
7460
|
start: line.start.toJson2D(),
|
|
7449
7461
|
end: line.end.toJson2D(),
|
|
7450
|
-
thickness: line.userData.wallWidth ? line.userData.wallWidth : 0.12,
|
|
7462
|
+
thickness: Math.max(line.userData.wallWidth ? line.userData.wallWidth : 0.12, 0.12),
|
|
7451
7463
|
type: "LINE",
|
|
7452
7464
|
isDoor: false,
|
|
7453
7465
|
loadBearingWall: false,
|
|
@@ -8297,236 +8309,6 @@ class DxfDataPlugin extends Pipeline {
|
|
|
8297
8309
|
DxfDataPlugin.initData(cad, this.lines);
|
|
8298
8310
|
}
|
|
8299
8311
|
}
|
|
8300
|
-
function parallel(line, baseline) {
|
|
8301
|
-
const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
|
|
8302
|
-
const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
|
|
8303
|
-
let diff = targetAngle - currentAngle;
|
|
8304
|
-
while (diff > Math.PI) diff -= 2 * Math.PI;
|
|
8305
|
-
while (diff < -Math.PI) diff += 2 * Math.PI;
|
|
8306
|
-
const center = line.center;
|
|
8307
|
-
line.start.rotate(center, diff);
|
|
8308
|
-
line.end.rotate(center, diff);
|
|
8309
|
-
if (Math.abs(diff) > Math.PI / 2) line.swapValue();
|
|
8310
|
-
return line;
|
|
8311
|
-
}
|
|
8312
|
-
function vertical(line, baseline) {
|
|
8313
|
-
const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
|
|
8314
|
-
const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
|
|
8315
|
-
let diff1 = targetAngle + Math.PI / 2 - currentAngle;
|
|
8316
|
-
let diff2 = targetAngle - Math.PI / 2 - currentAngle;
|
|
8317
|
-
while (diff1 > Math.PI) diff1 -= 2 * Math.PI;
|
|
8318
|
-
while (diff1 < -Math.PI) diff1 += 2 * Math.PI;
|
|
8319
|
-
while (diff2 > Math.PI) diff2 -= 2 * Math.PI;
|
|
8320
|
-
while (diff2 < -Math.PI) diff2 += 2 * Math.PI;
|
|
8321
|
-
const diff = Math.abs(diff1) < Math.abs(diff2) ? diff1 : diff2;
|
|
8322
|
-
const center = line.center;
|
|
8323
|
-
line.start.rotate(center, diff);
|
|
8324
|
-
line.end.rotate(center, diff);
|
|
8325
|
-
if (Math.abs(diff) > Math.PI / 2) line.swapValue();
|
|
8326
|
-
return line;
|
|
8327
|
-
}
|
|
8328
|
-
class AxisAlignCorr {
|
|
8329
|
-
static start(lines, targettLine) {
|
|
8330
|
-
return new AxisAlignCorr(lines, targettLine).start();
|
|
8331
|
-
}
|
|
8332
|
-
lines;
|
|
8333
|
-
baseline;
|
|
8334
|
-
grid;
|
|
8335
|
-
constructor(lines, baseline) {
|
|
8336
|
-
this.lines = lines;
|
|
8337
|
-
this.baseline = baseline;
|
|
8338
|
-
this.grid = createPointVirtualGrid(lines);
|
|
8339
|
-
}
|
|
8340
|
-
visited = /* @__PURE__ */ new Set();
|
|
8341
|
-
newLines = [];
|
|
8342
|
-
start() {
|
|
8343
|
-
for (let i = 0; i < this.lines.length; i++) {
|
|
8344
|
-
const line = this.lines[i];
|
|
8345
|
-
if (this.visited.has(line)) continue;
|
|
8346
|
-
this.correction(line);
|
|
8347
|
-
}
|
|
8348
|
-
return [
|
|
8349
|
-
...this.lines,
|
|
8350
|
-
...this.newLines
|
|
8351
|
-
];
|
|
8352
|
-
}
|
|
8353
|
-
/** 添加
|
|
8354
|
-
* @param lines
|
|
8355
|
-
* @returns
|
|
8356
|
-
*/
|
|
8357
|
-
addVisited(lines) {
|
|
8358
|
-
if (lines instanceof LineSegment) lines = [lines];
|
|
8359
|
-
lines.forEach((line) => this.visited.add(line));
|
|
8360
|
-
return this;
|
|
8361
|
-
}
|
|
8362
|
-
queryPoint(point2) {
|
|
8363
|
-
return this.grid.queryPoint(point2, true).filter((item) => !this.visited.has(item.userData));
|
|
8364
|
-
}
|
|
8365
|
-
/** 纠正
|
|
8366
|
-
* @param line
|
|
8367
|
-
* @param targettLine
|
|
8368
|
-
*/
|
|
8369
|
-
correction(line) {
|
|
8370
|
-
const startConnectList = this.queryPoint(line.start);
|
|
8371
|
-
const endConnectLines = this.queryPoint(line.end);
|
|
8372
|
-
this.rotate(line);
|
|
8373
|
-
startConnectList.forEach(({ userData: queryLine, point: point2 }) => {
|
|
8374
|
-
this.recursion(queryLine, point2, line, line.start);
|
|
8375
|
-
});
|
|
8376
|
-
endConnectLines.forEach(({ userData: queryLine, point: point2 }) => {
|
|
8377
|
-
this.recursion(queryLine, point2, line, line.end);
|
|
8378
|
-
});
|
|
8379
|
-
}
|
|
8380
|
-
/** 递归执行
|
|
8381
|
-
* @param line
|
|
8382
|
-
* @param enterPoint
|
|
8383
|
-
*/
|
|
8384
|
-
recursion(line, enterPoint, nextLine, nextPoint) {
|
|
8385
|
-
const otherPoint = line.getAnotherPoint(enterPoint);
|
|
8386
|
-
const connectList = this.queryPoint(otherPoint);
|
|
8387
|
-
this.rotate(line);
|
|
8388
|
-
this.establishConnection(enterPoint, line, nextLine, nextPoint);
|
|
8389
|
-
connectList.forEach(({ userData: queryLine, point: point2 }) => {
|
|
8390
|
-
this.recursion(queryLine, point2, line, otherPoint);
|
|
8391
|
-
});
|
|
8392
|
-
}
|
|
8393
|
-
/** 构建连接
|
|
8394
|
-
*/
|
|
8395
|
-
establishConnection(point2, line, nextLine, nextPoint) {
|
|
8396
|
-
if (line.isParallelTo(nextLine)) {
|
|
8397
|
-
const interPoint2 = nextLine.projectPoint(point2, false);
|
|
8398
|
-
const newLine = new LineSegment(point2.clone(), interPoint2?.clone() ?? nextPoint.clone());
|
|
8399
|
-
newLine.length() > 1e-9 && this.newLines.push(newLine);
|
|
8400
|
-
return;
|
|
8401
|
-
}
|
|
8402
|
-
const interPoint = nextLine.projectPoint(point2, false);
|
|
8403
|
-
if (!interPoint) return;
|
|
8404
|
-
point2.copy(interPoint);
|
|
8405
|
-
if (nextLine.isPointOnSegment(interPoint)) return;
|
|
8406
|
-
nextPoint.copy(interPoint);
|
|
8407
|
-
}
|
|
8408
|
-
point = new Point();
|
|
8409
|
-
/** 旋转
|
|
8410
|
-
* @param line
|
|
8411
|
-
* @param errAngle
|
|
8412
|
-
*/
|
|
8413
|
-
rotate(line, errAngle = 45) {
|
|
8414
|
-
const baseline = this.baseline;
|
|
8415
|
-
this.point.copy(line.start);
|
|
8416
|
-
if (line.isParallelTo(baseline, errAngle)) parallel(line, baseline);
|
|
8417
|
-
else vertical(line, baseline);
|
|
8418
|
-
this.addVisited(line);
|
|
8419
|
-
}
|
|
8420
|
-
}
|
|
8421
|
-
function shortDistanceLink(lines, radius = 0.1) {
|
|
8422
|
-
const dpSet = findDiscretePoint(lines.filter((line) => !line.userData.isDoor)), pointVirtualGrid = createPointVirtualGrid(dpSet.map((v2) => v2)), appendLines = [], visited = /* @__PURE__ */ new Set();
|
|
8423
|
-
const getWeight2 = (target, point2, line) => {
|
|
8424
|
-
if (target.weight) return target.weight;
|
|
8425
|
-
const targetLine = target.userData, targetPoint = target.point;
|
|
8426
|
-
const direct1 = line.getAnotherPoint(point2).directionFrom(point2), direct2 = targetLine.getAnotherPoint(targetPoint).directionFrom(targetPoint), direct3 = targetPoint.directionFrom(point2), angle = direct1.angleBetween(direct2), angle2 = direct1.angleBetween(direct3), length = point2.distance(target.point), weight = 1 - length / radius + angle / Math.PI * 1.2 + (1 - angle2 / Math.PI) * 1.2;
|
|
8427
|
-
target.weight = weight;
|
|
8428
|
-
return weight;
|
|
8429
|
-
};
|
|
8430
|
-
for (const [point2, line] of dpSet) {
|
|
8431
|
-
if (line.userData.isDoor) continue;
|
|
8432
|
-
if (visited.has(point2)) continue;
|
|
8433
|
-
const list = pointVirtualGrid.queryCircle(point2, radius, true).map((item) => Object.assign({}, item)).filter((item) => {
|
|
8434
|
-
const targetLine2 = item.userData, targetPoint2 = item.point, direct1 = line.getAnotherPoint(point2).directionFrom(point2), direct2 = targetLine2.getAnotherPoint(targetPoint2).directionFrom(targetPoint2), angle = direct1.angleBetween(direct2, "angle");
|
|
8435
|
-
return angle > 90;
|
|
8436
|
-
}).sort((a2, b4) => getWeight2(b4, point2, line) - getWeight2(a2, point2, line));
|
|
8437
|
-
if (list.length === 0) continue;
|
|
8438
|
-
const { point: targetPoint } = list[0];
|
|
8439
|
-
const targetLine = list[0].userData;
|
|
8440
|
-
visited.add(point2);
|
|
8441
|
-
visited.add(targetPoint);
|
|
8442
|
-
const projectLine1 = line.projectLineSegment(targetLine), projectLine2 = targetLine.projectLineSegment(line), len1 = projectLine1.length(), len2 = projectLine2.length();
|
|
8443
|
-
if (len1 === 0 && len2 === 0) appendLines.push(new LineSegment(point2.clone(), list[0].point.clone()));
|
|
8444
|
-
else appendLines.push(new LineSegment(projectLine1.center, projectLine2.center));
|
|
8445
|
-
}
|
|
8446
|
-
return [...lines, ...appendLines];
|
|
8447
|
-
}
|
|
8448
|
-
function preprocessing(lines) {
|
|
8449
|
-
const pointVirtualGrid = new PointVirtualGrid(), quadtree = new Quadtree(Box2.fromByLineSegment(...lines)), doors = [];
|
|
8450
|
-
lines.forEach((line) => {
|
|
8451
|
-
if (line.userData.isDoor) doors.push(line);
|
|
8452
|
-
else {
|
|
8453
|
-
line.points.forEach((p2) => pointVirtualGrid.insert(p2, line));
|
|
8454
|
-
quadtree.insert(line);
|
|
8455
|
-
}
|
|
8456
|
-
});
|
|
8457
|
-
doors.forEach((door) => {
|
|
8458
|
-
const startIntersection = pointVirtualGrid.queryPoint(door.start);
|
|
8459
|
-
const endIntersection = pointVirtualGrid.queryPoint(door.end);
|
|
8460
|
-
if (startIntersection.length) door.userData.startIntersection = startIntersection[0].userData;
|
|
8461
|
-
else door.userData.startIntersection = quadtree.queryPoint(door.start)[0]?.line;
|
|
8462
|
-
if (endIntersection.length) door.userData.endIntersection = endIntersection[0].userData;
|
|
8463
|
-
else door.userData.endIntersection = quadtree.queryPoint(door.end)[0]?.line;
|
|
8464
|
-
});
|
|
8465
|
-
lines = shortDistanceLink(lines, 0.4);
|
|
8466
|
-
pointVirtualGrid.clear();
|
|
8467
|
-
quadtree.clear();
|
|
8468
|
-
return lines;
|
|
8469
|
-
}
|
|
8470
|
-
function removeShortLine(lines, len = 0.01) {
|
|
8471
|
-
let defaultLines = [], doorLines = [];
|
|
8472
|
-
for (let i = 0; i < lines.length; i++) {
|
|
8473
|
-
const line = lines[i];
|
|
8474
|
-
if (line.userData.isDoor) doorLines.push(line);
|
|
8475
|
-
else defaultLines.push(line);
|
|
8476
|
-
}
|
|
8477
|
-
const lineSet = findDiscretePointLine2(lines);
|
|
8478
|
-
const grid = createPointVirtualGrid([...lineSet]);
|
|
8479
|
-
for (let i = 0; i < doorLines.length; i++) {
|
|
8480
|
-
const doorLine = doorLines[i];
|
|
8481
|
-
doorLine.points.forEach((p2) => {
|
|
8482
|
-
grid.queryPoint(p2, true).forEach((item) => lineSet.delete(item.userData));
|
|
8483
|
-
});
|
|
8484
|
-
}
|
|
8485
|
-
defaultLines = defaultLines.filter((line) => !lineSet.has(line) || line.length() > len);
|
|
8486
|
-
defaultLines = LineSegmentUndirectedGraph.breakpointMerging(defaultLines, (newLine, lines2) => {
|
|
8487
|
-
lines2 = lines2.filter((line) => line.length() > 0);
|
|
8488
|
-
mergeLineUserData(newLine, lines2);
|
|
8489
|
-
newLine.userData.isBayWindow = lines2.some((line) => line.userData.isBayWindow);
|
|
8490
|
-
});
|
|
8491
|
-
WallInsertObject.recomputed(defaultLines);
|
|
8492
|
-
return [...defaultLines, ...doorLines];
|
|
8493
|
-
}
|
|
8494
|
-
function breakpointMerging(lines) {
|
|
8495
|
-
let defaultLines = [], doorLines = [];
|
|
8496
|
-
for (let i = 0; i < lines.length; i++) {
|
|
8497
|
-
const line = lines[i];
|
|
8498
|
-
if (line.userData.isDoor) doorLines.push(line);
|
|
8499
|
-
else defaultLines.push(line);
|
|
8500
|
-
}
|
|
8501
|
-
defaultLines = LineSegmentUndirectedGraph.breakpointMerging(defaultLines, mergeLineUserData);
|
|
8502
|
-
doorLines = LineSegmentUndirectedGraph.breakpointMerging(doorLines, mergeLineUserData);
|
|
8503
|
-
return [...defaultLines, ...doorLines];
|
|
8504
|
-
}
|
|
8505
|
-
function axisAlignCorr$1(lines, targettLine, option) {
|
|
8506
|
-
lines = lines.map((line) => line.clone());
|
|
8507
|
-
lines = breakpointMerging(lines);
|
|
8508
|
-
lines = lineSegmentClipping(lines, 1e-9);
|
|
8509
|
-
lines = preprocessing(lines);
|
|
8510
|
-
lines = AxisAlignCorr.start(lines, targettLine);
|
|
8511
|
-
lines = lineSegmentClipping(lines, 1e-9);
|
|
8512
|
-
lines = removeShortLine(lines, 0.15);
|
|
8513
|
-
let newLines = lines.filter((line) => !line.userData.isDoor);
|
|
8514
|
-
let doorLines = lines.filter((line) => line.userData.isDoor);
|
|
8515
|
-
newLines = buildBayWindowGroup(newLines, false);
|
|
8516
|
-
const { wallGroup = true } = option ?? {};
|
|
8517
|
-
if (wallGroup) {
|
|
8518
|
-
newLines = DoubleWallHelper.complementSide(newLines);
|
|
8519
|
-
WallInsertObject.recomputed(newLines);
|
|
8520
|
-
newLines = buildDoubleWallGroup(newLines, true);
|
|
8521
|
-
newLines = buildBayWindowGroup(newLines, false);
|
|
8522
|
-
}
|
|
8523
|
-
new WallInsertObject(lines).recomputed().merge();
|
|
8524
|
-
newLines.push(...doorLines);
|
|
8525
|
-
Point.adsorb(newLines.flatMap((line) => line.points), 1e-4);
|
|
8526
|
-
lines = removeShortLine(lines, 0.05);
|
|
8527
|
-
lines = breakpointMerging(lines);
|
|
8528
|
-
return newLines;
|
|
8529
|
-
}
|
|
8530
8312
|
class BoundExt {
|
|
8531
8313
|
/** 通过轨迹点查找外墙
|
|
8532
8314
|
* @param lines
|
|
@@ -10231,8 +10013,8 @@ class Scenario {
|
|
|
10231
10013
|
}
|
|
10232
10014
|
windowTreatment1(dblWin, mesh, wallHeight) {
|
|
10233
10015
|
const doorList = dblWin;
|
|
10234
|
-
const MobileX = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, doorList.userData.wallWidth ? doorList.userData.wallWidth + 1e-
|
|
10235
|
-
const MobileY = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, doorList.userData.wallWidth ? doorList.userData.wallWidth + 1e-
|
|
10016
|
+
const MobileX = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, doorList.userData.wallWidth ? doorList.userData.wallWidth + 1e-3 : 0.5, true);
|
|
10017
|
+
const MobileY = this.angleToXAxisDegrees(doorList.start.x, doorList.start.y, doorList.end.x, doorList.end.y, doorList.userData.wallWidth ? doorList.userData.wallWidth + 1e-3 : 0.5, false);
|
|
10236
10018
|
let startingPoint = BayWindow.Instance.xinLine(MobileX, MobileY, doorList.start, wallHeight);
|
|
10237
10019
|
let finishLine = BayWindow.Instance.xinLine(MobileX, MobileY, doorList.end, wallHeight);
|
|
10238
10020
|
startingPoint.push(finishLine[1]);
|
|
@@ -10651,14 +10433,12 @@ class Scenario {
|
|
|
10651
10433
|
xinLine1(x, y, pointa, pointb, num, wallHeight) {
|
|
10652
10434
|
let point1;
|
|
10653
10435
|
let point2;
|
|
10654
|
-
let xx = x > 0 ? x + -1e-3 : 1e-3;
|
|
10655
|
-
let yy = y > 0 ? y + -1e-3 : 1e-3;
|
|
10656
10436
|
if (num === 0) {
|
|
10657
|
-
point1 = new THREE.Vector3(pointa.x -
|
|
10658
|
-
point2 = new THREE.Vector3(pointb.x -
|
|
10437
|
+
point1 = new THREE.Vector3(pointa.x - x, pointa.y - y, wallHeight);
|
|
10438
|
+
point2 = new THREE.Vector3(pointb.x - x, pointb.y - y, wallHeight);
|
|
10659
10439
|
} else {
|
|
10660
|
-
point1 = new THREE.Vector3(pointa.x +
|
|
10661
|
-
point2 = new THREE.Vector3(pointb.x +
|
|
10440
|
+
point1 = new THREE.Vector3(pointa.x + x, pointa.y + y, wallHeight);
|
|
10441
|
+
point2 = new THREE.Vector3(pointb.x + x, pointb.y + y, wallHeight);
|
|
10662
10442
|
}
|
|
10663
10443
|
return [point1, point2];
|
|
10664
10444
|
}
|
|
@@ -10888,7 +10668,6 @@ class Scenario {
|
|
|
10888
10668
|
//
|
|
10889
10669
|
createAPlane(lines, menList) {
|
|
10890
10670
|
const lineList = lines;
|
|
10891
|
-
console.log("初始数据", lines);
|
|
10892
10671
|
let precision = lineList.map((pos) => {
|
|
10893
10672
|
pos.start.x = parseFloat(pos.start.x.toFixed(3));
|
|
10894
10673
|
pos.start.y = parseFloat(pos.start.y.toFixed(3));
|
|
@@ -18972,11 +18751,363 @@ function init(lines, option) {
|
|
|
18972
18751
|
buildDoubleWallGroup.setTrajectory(option.trajectory);
|
|
18973
18752
|
return lines;
|
|
18974
18753
|
}
|
|
18754
|
+
class LineQueryer {
|
|
18755
|
+
pointVirtualGrid;
|
|
18756
|
+
quadtree;
|
|
18757
|
+
constructor(lines) {
|
|
18758
|
+
this.pointVirtualGrid = createPointVirtualGrid(lines);
|
|
18759
|
+
this.quadtree = createQuadtree(lines);
|
|
18760
|
+
}
|
|
18761
|
+
update(lines) {
|
|
18762
|
+
this.clear();
|
|
18763
|
+
this.pointVirtualGrid = createPointVirtualGrid(lines);
|
|
18764
|
+
this.quadtree = createQuadtree(lines);
|
|
18765
|
+
}
|
|
18766
|
+
clear() {
|
|
18767
|
+
this.pointVirtualGrid.clear();
|
|
18768
|
+
this.quadtree.clear();
|
|
18769
|
+
}
|
|
18770
|
+
/**
|
|
18771
|
+
* @param point
|
|
18772
|
+
* @param radius
|
|
18773
|
+
* @param opt
|
|
18774
|
+
* @returns
|
|
18775
|
+
*/
|
|
18776
|
+
queryNearestPoint(point2, opt) {
|
|
18777
|
+
if (!point2) throw new Error("请传入查询点");
|
|
18778
|
+
const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
|
|
18779
|
+
const results = this.pointVirtualGrid.queryCircle(point2, radius).filter((item) => item.point !== point2).filter((item) => condition ? condition(item) : true);
|
|
18780
|
+
results.sort((a2, b4) => a2.point.distance(point2, true) - b4.point.distance(point2, true));
|
|
18781
|
+
if (results.length > resultIndex) return {
|
|
18782
|
+
point: results[resultIndex].point,
|
|
18783
|
+
line: results[resultIndex].userData
|
|
18784
|
+
};
|
|
18785
|
+
return null;
|
|
18786
|
+
}
|
|
18787
|
+
/**
|
|
18788
|
+
* @param point
|
|
18789
|
+
* @param radius
|
|
18790
|
+
* @param opt
|
|
18791
|
+
* @returns
|
|
18792
|
+
*/
|
|
18793
|
+
queryNearestLine(point2, opt) {
|
|
18794
|
+
if (!point2) throw new Error("请传入查询点");
|
|
18795
|
+
const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
|
|
18796
|
+
const results = this.quadtree.queryCircle(point2, radius).map((item) => {
|
|
18797
|
+
const projPoint = item.line.projectPoint(point2, false);
|
|
18798
|
+
if (projPoint && (!condition || condition(item, projPoint))) {
|
|
18799
|
+
if (projPoint) return {
|
|
18800
|
+
...item,
|
|
18801
|
+
distance: projPoint.distance(point2) ?? Infinity,
|
|
18802
|
+
projPoint
|
|
18803
|
+
};
|
|
18804
|
+
}
|
|
18805
|
+
return null;
|
|
18806
|
+
}).filter((i) => !!i);
|
|
18807
|
+
results.sort((a2, b4) => a2.distance - b4.distance);
|
|
18808
|
+
if (results.length > resultIndex) return {
|
|
18809
|
+
point: results[resultIndex].projPoint,
|
|
18810
|
+
line: results[resultIndex].line
|
|
18811
|
+
};
|
|
18812
|
+
return null;
|
|
18813
|
+
}
|
|
18814
|
+
}
|
|
18815
|
+
function parallel(line, baseline) {
|
|
18816
|
+
const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
|
|
18817
|
+
const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
|
|
18818
|
+
let diff = targetAngle - currentAngle;
|
|
18819
|
+
while (diff > Math.PI) diff -= 2 * Math.PI;
|
|
18820
|
+
while (diff < -Math.PI) diff += 2 * Math.PI;
|
|
18821
|
+
const center = line.center;
|
|
18822
|
+
line.start.rotate(center, diff);
|
|
18823
|
+
line.end.rotate(center, diff);
|
|
18824
|
+
if (Math.abs(diff) > Math.PI / 2) line.swapValue();
|
|
18825
|
+
return line;
|
|
18826
|
+
}
|
|
18827
|
+
function vertical(line, baseline) {
|
|
18828
|
+
const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
|
|
18829
|
+
const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
|
|
18830
|
+
let diff1 = targetAngle + Math.PI / 2 - currentAngle;
|
|
18831
|
+
let diff2 = targetAngle - Math.PI / 2 - currentAngle;
|
|
18832
|
+
while (diff1 > Math.PI) diff1 -= 2 * Math.PI;
|
|
18833
|
+
while (diff1 < -Math.PI) diff1 += 2 * Math.PI;
|
|
18834
|
+
while (diff2 > Math.PI) diff2 -= 2 * Math.PI;
|
|
18835
|
+
while (diff2 < -Math.PI) diff2 += 2 * Math.PI;
|
|
18836
|
+
const diff = Math.abs(diff1) < Math.abs(diff2) ? diff1 : diff2;
|
|
18837
|
+
const center = line.center;
|
|
18838
|
+
line.start.rotate(center, diff);
|
|
18839
|
+
line.end.rotate(center, diff);
|
|
18840
|
+
if (Math.abs(diff) > Math.PI / 2) line.swapValue();
|
|
18841
|
+
return line;
|
|
18842
|
+
}
|
|
18843
|
+
class AxisAlignCorr {
|
|
18844
|
+
static start(lines, targettLine) {
|
|
18845
|
+
return new AxisAlignCorr(lines, targettLine).start();
|
|
18846
|
+
}
|
|
18847
|
+
lines;
|
|
18848
|
+
baseline;
|
|
18849
|
+
grid;
|
|
18850
|
+
constructor(lines, baseline) {
|
|
18851
|
+
this.lines = lines;
|
|
18852
|
+
this.baseline = baseline;
|
|
18853
|
+
this.grid = createPointVirtualGrid(lines);
|
|
18854
|
+
}
|
|
18855
|
+
visited = /* @__PURE__ */ new Set();
|
|
18856
|
+
newLines = [];
|
|
18857
|
+
start() {
|
|
18858
|
+
for (let i = 0; i < this.lines.length; i++) {
|
|
18859
|
+
const line = this.lines[i];
|
|
18860
|
+
if (this.visited.has(line)) continue;
|
|
18861
|
+
this.correction(line);
|
|
18862
|
+
}
|
|
18863
|
+
return [
|
|
18864
|
+
...this.lines,
|
|
18865
|
+
...this.newLines
|
|
18866
|
+
];
|
|
18867
|
+
}
|
|
18868
|
+
/** 添加
|
|
18869
|
+
* @param lines
|
|
18870
|
+
* @returns
|
|
18871
|
+
*/
|
|
18872
|
+
addVisited(lines) {
|
|
18873
|
+
if (lines instanceof LineSegment) lines = [lines];
|
|
18874
|
+
lines.forEach((line) => this.visited.add(line));
|
|
18875
|
+
return this;
|
|
18876
|
+
}
|
|
18877
|
+
queryPoint(point2) {
|
|
18878
|
+
return this.grid.queryPoint(point2, true).filter((item) => !this.visited.has(item.userData));
|
|
18879
|
+
}
|
|
18880
|
+
/** 纠正
|
|
18881
|
+
* @param line
|
|
18882
|
+
* @param targettLine
|
|
18883
|
+
*/
|
|
18884
|
+
correction(line) {
|
|
18885
|
+
const startConnectList = this.queryPoint(line.start);
|
|
18886
|
+
const endConnectLines = this.queryPoint(line.end);
|
|
18887
|
+
this.rotate(line);
|
|
18888
|
+
startConnectList.forEach(({ userData: queryLine, point: point2 }) => {
|
|
18889
|
+
this.recursion(queryLine, point2, line, line.start);
|
|
18890
|
+
});
|
|
18891
|
+
endConnectLines.forEach(({ userData: queryLine, point: point2 }) => {
|
|
18892
|
+
this.recursion(queryLine, point2, line, line.end);
|
|
18893
|
+
});
|
|
18894
|
+
}
|
|
18895
|
+
/** 递归执行
|
|
18896
|
+
* @param line
|
|
18897
|
+
* @param enterPoint
|
|
18898
|
+
*/
|
|
18899
|
+
recursion(line, enterPoint, nextLine, nextPoint) {
|
|
18900
|
+
const otherPoint = line.getAnotherPoint(enterPoint);
|
|
18901
|
+
const connectList = this.queryPoint(otherPoint);
|
|
18902
|
+
this.rotate(line);
|
|
18903
|
+
this.establishConnection(enterPoint, line, nextLine, nextPoint);
|
|
18904
|
+
connectList.forEach(({ userData: queryLine, point: point2 }) => {
|
|
18905
|
+
this.recursion(queryLine, point2, line, otherPoint);
|
|
18906
|
+
});
|
|
18907
|
+
}
|
|
18908
|
+
/** 构建连接
|
|
18909
|
+
*/
|
|
18910
|
+
establishConnection(point2, line, nextLine, nextPoint) {
|
|
18911
|
+
if (line.isParallelTo(nextLine)) {
|
|
18912
|
+
const interPoint2 = nextLine.projectPoint(point2, false);
|
|
18913
|
+
const newLine = new LineSegment(point2.clone(), interPoint2?.clone() ?? nextPoint.clone());
|
|
18914
|
+
newLine.length() > 1e-9 && this.newLines.push(newLine);
|
|
18915
|
+
return;
|
|
18916
|
+
}
|
|
18917
|
+
const interPoint = nextLine.projectPoint(point2, false);
|
|
18918
|
+
if (!interPoint) return;
|
|
18919
|
+
point2.copy(interPoint);
|
|
18920
|
+
if (nextLine.isPointOnSegment(interPoint)) return;
|
|
18921
|
+
nextPoint.copy(interPoint);
|
|
18922
|
+
}
|
|
18923
|
+
point = new Point();
|
|
18924
|
+
/** 旋转
|
|
18925
|
+
* @param line
|
|
18926
|
+
* @param errAngle
|
|
18927
|
+
*/
|
|
18928
|
+
rotate(line, errAngle = 45) {
|
|
18929
|
+
const baseline = this.baseline;
|
|
18930
|
+
this.point.copy(line.start);
|
|
18931
|
+
if (line.isParallelTo(baseline, errAngle)) parallel(line, baseline);
|
|
18932
|
+
else vertical(line, baseline);
|
|
18933
|
+
this.addVisited(line);
|
|
18934
|
+
}
|
|
18935
|
+
}
|
|
18936
|
+
function shortDistanceLink(lines, radius = 0.1) {
|
|
18937
|
+
const dpSet = findDiscretePoint(lines.filter((line) => !line.userData.isDoor)), pointVirtualGrid = createPointVirtualGrid(dpSet.map((v2) => v2)), appendLines = [], visited = /* @__PURE__ */ new Set();
|
|
18938
|
+
const getWeight2 = (target, point2, line) => {
|
|
18939
|
+
if (target.weight) return target.weight;
|
|
18940
|
+
const targetLine = target.userData, targetPoint = target.point;
|
|
18941
|
+
const direct1 = line.getAnotherPoint(point2).directionFrom(point2), direct2 = targetLine.getAnotherPoint(targetPoint).directionFrom(targetPoint), direct3 = targetPoint.directionFrom(point2), angle = direct1.angleBetween(direct2), angle2 = direct1.angleBetween(direct3), length = point2.distance(target.point), weight = 1 - length / radius + angle / Math.PI * 1.2 + (1 - angle2 / Math.PI) * 1.2;
|
|
18942
|
+
target.weight = weight;
|
|
18943
|
+
return weight;
|
|
18944
|
+
};
|
|
18945
|
+
for (const [point2, line] of dpSet) {
|
|
18946
|
+
if (line.userData.isDoor) continue;
|
|
18947
|
+
if (visited.has(point2)) continue;
|
|
18948
|
+
const list = pointVirtualGrid.queryCircle(point2, radius, true).map((item) => Object.assign({}, item)).filter((item) => {
|
|
18949
|
+
const targetLine2 = item.userData, targetPoint2 = item.point, direct1 = line.getAnotherPoint(point2).directionFrom(point2), direct2 = targetLine2.getAnotherPoint(targetPoint2).directionFrom(targetPoint2), angle = direct1.angleBetween(direct2, "angle");
|
|
18950
|
+
return angle > 90;
|
|
18951
|
+
}).sort((a2, b4) => getWeight2(b4, point2, line) - getWeight2(a2, point2, line));
|
|
18952
|
+
if (list.length === 0) continue;
|
|
18953
|
+
const { point: targetPoint } = list[0];
|
|
18954
|
+
const targetLine = list[0].userData;
|
|
18955
|
+
visited.add(point2);
|
|
18956
|
+
visited.add(targetPoint);
|
|
18957
|
+
const projectLine1 = line.projectLineSegment(targetLine), projectLine2 = targetLine.projectLineSegment(line), len1 = projectLine1.length(), len2 = projectLine2.length();
|
|
18958
|
+
if (len1 === 0 && len2 === 0) appendLines.push(new LineSegment(point2.clone(), list[0].point.clone()));
|
|
18959
|
+
else appendLines.push(new LineSegment(projectLine1.center, projectLine2.center));
|
|
18960
|
+
}
|
|
18961
|
+
return [...lines, ...appendLines];
|
|
18962
|
+
}
|
|
18963
|
+
function preprocessing(lines) {
|
|
18964
|
+
const pointVirtualGrid = new PointVirtualGrid(), quadtree = new Quadtree(Box2.fromByLineSegment(...lines)), doors = [];
|
|
18965
|
+
lines.forEach((line) => {
|
|
18966
|
+
if (line.userData.isDoor) doors.push(line);
|
|
18967
|
+
else {
|
|
18968
|
+
line.points.forEach((p2) => pointVirtualGrid.insert(p2, line));
|
|
18969
|
+
quadtree.insert(line);
|
|
18970
|
+
}
|
|
18971
|
+
});
|
|
18972
|
+
doors.forEach((door) => {
|
|
18973
|
+
const startIntersection = pointVirtualGrid.queryPoint(door.start);
|
|
18974
|
+
const endIntersection = pointVirtualGrid.queryPoint(door.end);
|
|
18975
|
+
if (startIntersection.length) door.userData.startIntersection = startIntersection[0].userData;
|
|
18976
|
+
else door.userData.startIntersection = quadtree.queryPoint(door.start)[0]?.line;
|
|
18977
|
+
if (endIntersection.length) door.userData.endIntersection = endIntersection[0].userData;
|
|
18978
|
+
else door.userData.endIntersection = quadtree.queryPoint(door.end)[0]?.line;
|
|
18979
|
+
});
|
|
18980
|
+
lines = shortDistanceLink(lines, 0.4);
|
|
18981
|
+
pointVirtualGrid.clear();
|
|
18982
|
+
quadtree.clear();
|
|
18983
|
+
return lines;
|
|
18984
|
+
}
|
|
18985
|
+
function adsorption(lines, option) {
|
|
18986
|
+
const { snapThreshold: threshold = 0.2 } = option ?? {}, lineQueryer = new LineQueryer(lines), modifyManager = LineSegment.createModifyManager();
|
|
18987
|
+
function adsorptLine(point2, line) {
|
|
18988
|
+
const otherPoint = line.getAnotherPoint(point2);
|
|
18989
|
+
const direct = otherPoint.directionFrom(point2);
|
|
18990
|
+
const len = line.length();
|
|
18991
|
+
const result = lineQueryer.queryNearestLine(point2, {
|
|
18992
|
+
radius: threshold,
|
|
18993
|
+
condition: (node, projPoint) => {
|
|
18994
|
+
if (line !== node.line && node.line.isPerpendicularTo(line, 35)) {
|
|
18995
|
+
if (projPoint.distance(point2) < len) return true;
|
|
18996
|
+
const direct2 = projPoint.directionFrom(point2);
|
|
18997
|
+
return direct2.angleBetween(direct) > Math.PI * 0.5;
|
|
18998
|
+
}
|
|
18999
|
+
return false;
|
|
19000
|
+
}
|
|
19001
|
+
});
|
|
19002
|
+
if (result) return modifyManager.setPoint(line, point2, result.point.clone());
|
|
19003
|
+
}
|
|
19004
|
+
function adsorptPoint(point2, line) {
|
|
19005
|
+
const result = lineQueryer.queryNearestPoint(point2, {
|
|
19006
|
+
radius: threshold,
|
|
19007
|
+
condition(node) {
|
|
19008
|
+
const line2 = node.userData;
|
|
19009
|
+
return line2.isPerpendicularTo(line, 15);
|
|
19010
|
+
}
|
|
19011
|
+
});
|
|
19012
|
+
if (result) {
|
|
19013
|
+
const propPoint = result.line.projectPoint(point2, false);
|
|
19014
|
+
if (propPoint) {
|
|
19015
|
+
modifyManager.setPoint(line, point2, propPoint);
|
|
19016
|
+
modifyManager.setPoint(result.line, result.point, propPoint);
|
|
19017
|
+
}
|
|
19018
|
+
}
|
|
19019
|
+
}
|
|
19020
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19021
|
+
const line = lines[i];
|
|
19022
|
+
line.points.map((point2) => {
|
|
19023
|
+
let results = lineQueryer.pointVirtualGrid.queryPoint(point2, true);
|
|
19024
|
+
if (results.length === 0 && lineQueryer.quadtree.queryCircle(point2, 1e-4).length < 2) adsorptLine(point2, line);
|
|
19025
|
+
});
|
|
19026
|
+
}
|
|
19027
|
+
modifyManager.modify();
|
|
19028
|
+
lines = lines.filter((line) => line.length() > 1e-9);
|
|
19029
|
+
const dpls = [...findDiscretePointLine2(lines)];
|
|
19030
|
+
lineQueryer.update(lines);
|
|
19031
|
+
for (let i = 0; i < dpls.length; i++) {
|
|
19032
|
+
const line = dpls[i];
|
|
19033
|
+
line.points.map((point2) => {
|
|
19034
|
+
let results = lineQueryer.pointVirtualGrid.queryPoint(point2, true);
|
|
19035
|
+
if (results.length === 0 && lineQueryer.quadtree.queryCircle(point2, 1e-4).length < 2) {
|
|
19036
|
+
adsorptPoint(point2, line);
|
|
19037
|
+
}
|
|
19038
|
+
});
|
|
19039
|
+
}
|
|
19040
|
+
modifyManager.modify();
|
|
19041
|
+
lineQueryer.clear();
|
|
19042
|
+
Point.adsorb(lines.flatMap((line) => line.points), 1e-4, "first");
|
|
19043
|
+
return lines;
|
|
19044
|
+
}
|
|
19045
|
+
function removeShortLine(lines, len = 0.01) {
|
|
19046
|
+
let defaultLines = [], doorLines = [];
|
|
19047
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19048
|
+
const line = lines[i];
|
|
19049
|
+
if (line.userData.isDoor) doorLines.push(line);
|
|
19050
|
+
else defaultLines.push(line);
|
|
19051
|
+
}
|
|
19052
|
+
const lineSet = findDiscretePointLine2(lines);
|
|
19053
|
+
const grid = createPointVirtualGrid([...lineSet]);
|
|
19054
|
+
for (let i = 0; i < doorLines.length; i++) {
|
|
19055
|
+
const doorLine = doorLines[i];
|
|
19056
|
+
doorLine.points.forEach((p2) => {
|
|
19057
|
+
grid.queryPoint(p2, true).forEach((item) => lineSet.delete(item.userData));
|
|
19058
|
+
});
|
|
19059
|
+
}
|
|
19060
|
+
defaultLines = defaultLines.filter((line) => !lineSet.has(line) || line.length() > len);
|
|
19061
|
+
defaultLines = LineSegmentUndirectedGraph.breakpointMerging(defaultLines, (newLine, lines2) => {
|
|
19062
|
+
lines2 = lines2.filter((line) => line.length() > 0);
|
|
19063
|
+
mergeLineUserData(newLine, lines2);
|
|
19064
|
+
newLine.userData.isBayWindow = lines2.some((line) => line.userData.isBayWindow);
|
|
19065
|
+
});
|
|
19066
|
+
WallInsertObject.recomputed(defaultLines);
|
|
19067
|
+
return [...defaultLines, ...doorLines];
|
|
19068
|
+
}
|
|
19069
|
+
function breakpointMerging(lines) {
|
|
19070
|
+
let defaultLines = [], doorLines = [];
|
|
19071
|
+
for (let i = 0; i < lines.length; i++) {
|
|
19072
|
+
const line = lines[i];
|
|
19073
|
+
if (line.userData.isDoor) doorLines.push(line);
|
|
19074
|
+
else defaultLines.push(line);
|
|
19075
|
+
}
|
|
19076
|
+
defaultLines = LineSegmentUndirectedGraph.breakpointMerging(defaultLines, mergeLineUserData);
|
|
19077
|
+
doorLines = LineSegmentUndirectedGraph.breakpointMerging(doorLines, mergeLineUserData);
|
|
19078
|
+
return [...defaultLines, ...doorLines];
|
|
19079
|
+
}
|
|
19080
|
+
function correction(lines, targettLine, option) {
|
|
19081
|
+
lines = lines.map((line) => line.clone());
|
|
19082
|
+
lines = breakpointMerging(lines);
|
|
19083
|
+
lines = lineSegmentClipping(lines, 1e-9);
|
|
19084
|
+
lines = preprocessing(lines);
|
|
19085
|
+
lines = AxisAlignCorr.start(lines, targettLine);
|
|
19086
|
+
lines = adsorption(lines, option);
|
|
19087
|
+
lines = lineSegmentClipping(lines, 1e-9);
|
|
19088
|
+
lines = removeShortLine(lines, 0.15);
|
|
19089
|
+
let newLines = lines.filter((line) => !line.userData.isDoor);
|
|
19090
|
+
let doorLines = lines.filter((line) => line.userData.isDoor);
|
|
19091
|
+
newLines = buildBayWindowGroup(newLines, false);
|
|
19092
|
+
const { wallGroup = true } = option ?? {};
|
|
19093
|
+
if (wallGroup) {
|
|
19094
|
+
newLines = DoubleWallHelper.complementSide(newLines);
|
|
19095
|
+
WallInsertObject.recomputed(newLines);
|
|
19096
|
+
newLines = buildDoubleWallGroup(newLines, true);
|
|
19097
|
+
newLines = buildBayWindowGroup(newLines, false);
|
|
19098
|
+
}
|
|
19099
|
+
new WallInsertObject(lines).recomputed().merge();
|
|
19100
|
+
newLines.push(...doorLines);
|
|
19101
|
+
Point.adsorb(newLines.flatMap((line) => line.points), 1e-4);
|
|
19102
|
+
lines = removeShortLine(lines, 0.05);
|
|
19103
|
+
lines = breakpointMerging(lines);
|
|
19104
|
+
return newLines;
|
|
19105
|
+
}
|
|
18975
19106
|
function axisAlignCorr(lines, option, verticalReferenceLine) {
|
|
18976
19107
|
verticalReferenceLine = verticalReferenceLine ?? findVerticalReference(lines.filter((line) => !line.userData.isDoor));
|
|
18977
19108
|
if (verticalReferenceLine) {
|
|
18978
19109
|
const t2 = performance.now();
|
|
18979
|
-
const lineSegments =
|
|
19110
|
+
const lineSegments = correction(lines, verticalReferenceLine, option);
|
|
18980
19111
|
console.log("垂直纠正总消耗时间:", (performance.now() - t2).toFixed(2), "ms", "处理线段数量:", lines.length);
|
|
18981
19112
|
return lineSegments;
|
|
18982
19113
|
} else {
|
|
@@ -19164,7 +19295,7 @@ function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
|
19164
19295
|
let parallel2 = new PvgList();
|
|
19165
19296
|
for (let i = 0; i < intersList.length; i++) {
|
|
19166
19297
|
const res = intersList[i];
|
|
19167
|
-
if (line.isPerpendicularTo(res.userData)) {
|
|
19298
|
+
if (line.isPerpendicularTo(res.userData, 5)) {
|
|
19168
19299
|
count++;
|
|
19169
19300
|
firstLine = res.userData;
|
|
19170
19301
|
firstPoint = res.point;
|
|
@@ -21817,7 +21948,6 @@ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
21817
21948
|
Side,
|
|
21818
21949
|
UndirectedGraph,
|
|
21819
21950
|
UnionFindSet,
|
|
21820
|
-
axisAlignCorr: axisAlignCorr$1,
|
|
21821
21951
|
buildBayWindowGroup,
|
|
21822
21952
|
buildDoubleWallGroup,
|
|
21823
21953
|
buildDoubleWallGroup_,
|
|
@@ -22031,7 +22161,6 @@ async function buildJson(opt) {
|
|
|
22031
22161
|
if (opt.axisAlignCorr !== false) {
|
|
22032
22162
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
|
|
22033
22163
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.LinesSmoothing);
|
|
22034
|
-
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.RemoveShortDoubleWall);
|
|
22035
22164
|
}
|
|
22036
22165
|
if (trajectory2) {
|
|
22037
22166
|
if (typeof trajectory2 === "string") {
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { LineSegment } from '../../../../algorithmsStructures/LineSegment';
|
|
2
|
-
import {
|
|
2
|
+
import { SetDataOption, LineUserData } from '../../../type';
|
|
3
|
+
/**
|
|
4
|
+
* 门的障碍物清理
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 轴对齐垂直修正
|
|
8
|
+
* @param lines 待调整线段组
|
|
9
|
+
* @param targettLine 轴线段
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export declare function correction(lines: LineSegment<LineUserData>[], targettLine: LineSegment<LineUserData>, option?: SetDataOption): LineSegment<any>[];
|
|
3
13
|
/** 轴对齐垂直纠正
|
|
4
14
|
* @param lines
|
|
5
15
|
* @param option
|
|
@@ -99,7 +99,7 @@ export declare class ThreeVJiaJson extends Pipeline<DataOption, ICache> {
|
|
|
99
99
|
* @param param0
|
|
100
100
|
* @returns
|
|
101
101
|
*/
|
|
102
|
-
balconyRailing({ data }: HandlerContext<DataOption>):
|
|
102
|
+
balconyRailing({ data: { lines }, cache }: HandlerContext<DataOption, ICache>): void;
|
|
103
103
|
/** 转换
|
|
104
104
|
* @returns
|
|
105
105
|
*/
|
|
@@ -139,13 +139,13 @@ export declare class LineSegment<T = Record<string, any>> {
|
|
|
139
139
|
* 两条线段或角度是否平行,忽略方向
|
|
140
140
|
* @param line
|
|
141
141
|
*/
|
|
142
|
-
isParallelTo(
|
|
142
|
+
isParallelTo(line: LineSegment, eps?: number): boolean;
|
|
143
143
|
/** 两条线段或角度是否 垂直, 忽略方向
|
|
144
144
|
* @param line
|
|
145
145
|
* @param errAngle
|
|
146
146
|
* @returns
|
|
147
147
|
*/
|
|
148
|
-
isPerpendicularTo(
|
|
148
|
+
isPerpendicularTo(line: LineSegment, eps?: number): boolean;
|
|
149
149
|
/**
|
|
150
150
|
* @param line
|
|
151
151
|
* @param eps
|
|
@@ -47,7 +47,7 @@ export default class Scenario {
|
|
|
47
47
|
executionOffset(data: any, index: number, wallHeight: number): THREE.Mesh<THREE.ExtrudeGeometry, THREE.MeshStandardMaterial, THREE.Object3DEventMap> | null | undefined;
|
|
48
48
|
windowTreatment(dblWin: any, mesh: any, wallHeight: number): Brush;
|
|
49
49
|
windowTreatment1(dblWin: any, mesh: any, wallHeight: number): Brush;
|
|
50
|
-
TheHandlingOfTheDoor1(data: LineSegment<LineUserData>):
|
|
50
|
+
TheHandlingOfTheDoor1(data: LineSegment<LineUserData>): any[];
|
|
51
51
|
TheHandlingOfTheDoor(data: LineSegment<LineUserData>[]): void;
|
|
52
52
|
doorCenterOffset(distanceFromB: number, point: any, pointc: THREE.Vector3): THREE.Vector3;
|
|
53
53
|
installWindows(data: any, index: string): void;
|
|
@@ -60,7 +60,7 @@ export default class Scenario {
|
|
|
60
60
|
doorHoleOpening(wallHeight: number, data: any, data1: any, groundHeight?: number, Height?: number, distance?: number, center?: THREE.Vector3, angleRad?: any, index?: string, doorList?: LineSegment): void;
|
|
61
61
|
angleToXAxisDegrees(x1: number, y1: number, x2: number, y2: number, wide: number, cd: boolean): number;
|
|
62
62
|
xinLine(x: number, y: number, point: THREE.Vector3 | Point, wallHeight: number): THREE.Vector3[];
|
|
63
|
-
xinLine1(x: number, y: number, pointa: THREE.Vector3, pointb: THREE.Vector3, num: number, wallHeight: number):
|
|
63
|
+
xinLine1(x: number, y: number, pointa: THREE.Vector3, pointb: THREE.Vector3, num: number, wallHeight: number): any[];
|
|
64
64
|
createParallelepipedFromBase(points: any, height: number): THREE.ExtrudeGeometry;
|
|
65
65
|
correctionSorting(bitem: any): {
|
|
66
66
|
dian: THREE.Vector3;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { LineSegment } from '../../../algorithmsStructures/LineSegment';
|
|
2
|
-
import { SetDataOption, LineUserData } from '../../type';
|
|
3
|
-
/**
|
|
4
|
-
* 门的障碍物清理
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* 轴对齐垂直修正
|
|
8
|
-
* @param lines 待调整线段组
|
|
9
|
-
* @param targettLine 轴线段
|
|
10
|
-
* @returns
|
|
11
|
-
*/
|
|
12
|
-
export declare function axisAlignCorr(lines: LineSegment<LineUserData>[], targettLine: LineSegment<LineUserData>, option?: SetDataOption): LineSegment<any>[];
|