build-dxf 0.1.84 → 0.1.85
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 +156 -24
- 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/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 = 0.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 将当前点的坐标归一化为单位向量
|
|
@@ -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,
|
|
@@ -7465,7 +7477,6 @@ class ThreeVJiaJson extends Pipeline {
|
|
|
7465
7477
|
}
|
|
7466
7478
|
}
|
|
7467
7479
|
function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
7468
|
-
angle = 0;
|
|
7469
7480
|
lineSegments = LineSegmentUndirectedGraph.rotate(lineSegments.map((line) => line.clone()), angle, (line, center, angle2) => {
|
|
7470
7481
|
WallInsertObject.forEachInsertObjectData(line, (data) => {
|
|
7471
7482
|
data.forEach((item) => {
|
|
@@ -8297,6 +8308,67 @@ class DxfDataPlugin extends Pipeline {
|
|
|
8297
8308
|
DxfDataPlugin.initData(cad, this.lines);
|
|
8298
8309
|
}
|
|
8299
8310
|
}
|
|
8311
|
+
class LineQueryer {
|
|
8312
|
+
pointVirtualGrid;
|
|
8313
|
+
quadtree;
|
|
8314
|
+
constructor(lines) {
|
|
8315
|
+
this.pointVirtualGrid = createPointVirtualGrid(lines);
|
|
8316
|
+
this.quadtree = createQuadtree(lines);
|
|
8317
|
+
}
|
|
8318
|
+
update(lines) {
|
|
8319
|
+
this.clear();
|
|
8320
|
+
this.pointVirtualGrid = createPointVirtualGrid(lines);
|
|
8321
|
+
this.quadtree = createQuadtree(lines);
|
|
8322
|
+
}
|
|
8323
|
+
clear() {
|
|
8324
|
+
this.pointVirtualGrid.clear();
|
|
8325
|
+
this.quadtree.clear();
|
|
8326
|
+
}
|
|
8327
|
+
/**
|
|
8328
|
+
* @param point
|
|
8329
|
+
* @param radius
|
|
8330
|
+
* @param opt
|
|
8331
|
+
* @returns
|
|
8332
|
+
*/
|
|
8333
|
+
queryNearestPoint(point2, opt) {
|
|
8334
|
+
if (!point2) throw new Error("请传入查询点");
|
|
8335
|
+
const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
|
|
8336
|
+
const results = this.pointVirtualGrid.queryCircle(point2, radius).filter((item) => item.point !== point2).filter((item) => condition ? condition(item) : true);
|
|
8337
|
+
results.sort((a2, b4) => a2.point.distance(point2, true) - b4.point.distance(point2, true));
|
|
8338
|
+
if (results.length > resultIndex) return {
|
|
8339
|
+
point: results[resultIndex].point,
|
|
8340
|
+
line: results[resultIndex].userData
|
|
8341
|
+
};
|
|
8342
|
+
return null;
|
|
8343
|
+
}
|
|
8344
|
+
/**
|
|
8345
|
+
* @param point
|
|
8346
|
+
* @param radius
|
|
8347
|
+
* @param opt
|
|
8348
|
+
* @returns
|
|
8349
|
+
*/
|
|
8350
|
+
queryNearestLine(point2, opt) {
|
|
8351
|
+
if (!point2) throw new Error("请传入查询点");
|
|
8352
|
+
const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
|
|
8353
|
+
const results = this.quadtree.queryCircle(point2, radius).map((item) => {
|
|
8354
|
+
const projPoint = item.line.projectPoint(point2, false);
|
|
8355
|
+
if (projPoint && (!condition || condition(item, projPoint))) {
|
|
8356
|
+
if (projPoint) return {
|
|
8357
|
+
...item,
|
|
8358
|
+
distance: projPoint.distance(point2) ?? Infinity,
|
|
8359
|
+
projPoint
|
|
8360
|
+
};
|
|
8361
|
+
}
|
|
8362
|
+
return null;
|
|
8363
|
+
}).filter((i) => !!i);
|
|
8364
|
+
results.sort((a2, b4) => a2.distance - b4.distance);
|
|
8365
|
+
if (results.length > resultIndex) return {
|
|
8366
|
+
point: results[resultIndex].projPoint,
|
|
8367
|
+
line: results[resultIndex].line
|
|
8368
|
+
};
|
|
8369
|
+
return null;
|
|
8370
|
+
}
|
|
8371
|
+
}
|
|
8300
8372
|
function parallel(line, baseline) {
|
|
8301
8373
|
const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
|
|
8302
8374
|
const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
|
|
@@ -8467,6 +8539,66 @@ function preprocessing(lines) {
|
|
|
8467
8539
|
quadtree.clear();
|
|
8468
8540
|
return lines;
|
|
8469
8541
|
}
|
|
8542
|
+
function adsorption(lines, option) {
|
|
8543
|
+
const { snapThreshold: threshold = 0.2 } = option ?? {}, lineQueryer = new LineQueryer(lines), modifyManager = LineSegment.createModifyManager();
|
|
8544
|
+
function adsorptLine(point2, line) {
|
|
8545
|
+
const otherPoint = line.getAnotherPoint(point2);
|
|
8546
|
+
const direct = otherPoint.directionFrom(point2);
|
|
8547
|
+
const len = line.length();
|
|
8548
|
+
const result = lineQueryer.queryNearestLine(point2, {
|
|
8549
|
+
radius: threshold,
|
|
8550
|
+
condition: (node, projPoint) => {
|
|
8551
|
+
if (line !== node.line && node.line.isPerpendicularTo(line, 35)) {
|
|
8552
|
+
if (projPoint.distance(point2) < len) return true;
|
|
8553
|
+
const direct2 = projPoint.directionFrom(point2);
|
|
8554
|
+
return direct2.angleBetween(direct) > Math.PI * 0.5;
|
|
8555
|
+
}
|
|
8556
|
+
return false;
|
|
8557
|
+
}
|
|
8558
|
+
});
|
|
8559
|
+
if (result) return modifyManager.setPoint(line, point2, result.point.clone());
|
|
8560
|
+
}
|
|
8561
|
+
function adsorptPoint(point2, line) {
|
|
8562
|
+
const result = lineQueryer.queryNearestPoint(point2, {
|
|
8563
|
+
radius: threshold,
|
|
8564
|
+
condition(node) {
|
|
8565
|
+
const line2 = node.userData;
|
|
8566
|
+
return line2.isPerpendicularTo(line, 15);
|
|
8567
|
+
}
|
|
8568
|
+
});
|
|
8569
|
+
if (result) {
|
|
8570
|
+
const propPoint = result.line.projectPoint(point2, false);
|
|
8571
|
+
if (propPoint) {
|
|
8572
|
+
modifyManager.setPoint(line, point2, propPoint);
|
|
8573
|
+
modifyManager.setPoint(result.line, result.point, propPoint);
|
|
8574
|
+
}
|
|
8575
|
+
}
|
|
8576
|
+
}
|
|
8577
|
+
for (let i = 0; i < lines.length; i++) {
|
|
8578
|
+
const line = lines[i];
|
|
8579
|
+
line.points.map((point2) => {
|
|
8580
|
+
let results = lineQueryer.pointVirtualGrid.queryPoint(point2, true);
|
|
8581
|
+
if (results.length === 0 && lineQueryer.quadtree.queryCircle(point2, 1e-4).length < 2) adsorptLine(point2, line);
|
|
8582
|
+
});
|
|
8583
|
+
}
|
|
8584
|
+
modifyManager.modify();
|
|
8585
|
+
lines = lines.filter((line) => line.length() > 1e-9);
|
|
8586
|
+
const dpls = [...findDiscretePointLine2(lines)];
|
|
8587
|
+
lineQueryer.update(lines);
|
|
8588
|
+
for (let i = 0; i < dpls.length; i++) {
|
|
8589
|
+
const line = dpls[i];
|
|
8590
|
+
line.points.map((point2) => {
|
|
8591
|
+
let results = lineQueryer.pointVirtualGrid.queryPoint(point2, true);
|
|
8592
|
+
if (results.length === 0 && lineQueryer.quadtree.queryCircle(point2, 1e-4).length < 2) {
|
|
8593
|
+
adsorptPoint(point2, line);
|
|
8594
|
+
}
|
|
8595
|
+
});
|
|
8596
|
+
}
|
|
8597
|
+
modifyManager.modify();
|
|
8598
|
+
lineQueryer.clear();
|
|
8599
|
+
Point.adsorb(lines.flatMap((line) => line.points), 1e-4, "first");
|
|
8600
|
+
return lines;
|
|
8601
|
+
}
|
|
8470
8602
|
function removeShortLine(lines, len = 0.01) {
|
|
8471
8603
|
let defaultLines = [], doorLines = [];
|
|
8472
8604
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -8508,6 +8640,7 @@ function axisAlignCorr$1(lines, targettLine, option) {
|
|
|
8508
8640
|
lines = lineSegmentClipping(lines, 1e-9);
|
|
8509
8641
|
lines = preprocessing(lines);
|
|
8510
8642
|
lines = AxisAlignCorr.start(lines, targettLine);
|
|
8643
|
+
lines = adsorption(lines, option);
|
|
8511
8644
|
lines = lineSegmentClipping(lines, 1e-9);
|
|
8512
8645
|
lines = removeShortLine(lines, 0.15);
|
|
8513
8646
|
let newLines = lines.filter((line) => !line.userData.isDoor);
|
|
@@ -10231,8 +10364,8 @@ class Scenario {
|
|
|
10231
10364
|
}
|
|
10232
10365
|
windowTreatment1(dblWin, mesh, wallHeight) {
|
|
10233
10366
|
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-
|
|
10367
|
+
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);
|
|
10368
|
+
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
10369
|
let startingPoint = BayWindow.Instance.xinLine(MobileX, MobileY, doorList.start, wallHeight);
|
|
10237
10370
|
let finishLine = BayWindow.Instance.xinLine(MobileX, MobileY, doorList.end, wallHeight);
|
|
10238
10371
|
startingPoint.push(finishLine[1]);
|
|
@@ -10651,14 +10784,12 @@ class Scenario {
|
|
|
10651
10784
|
xinLine1(x, y, pointa, pointb, num, wallHeight) {
|
|
10652
10785
|
let point1;
|
|
10653
10786
|
let point2;
|
|
10654
|
-
let xx = x > 0 ? x + -1e-3 : 1e-3;
|
|
10655
|
-
let yy = y > 0 ? y + -1e-3 : 1e-3;
|
|
10656
10787
|
if (num === 0) {
|
|
10657
|
-
point1 = new THREE.Vector3(pointa.x -
|
|
10658
|
-
point2 = new THREE.Vector3(pointb.x -
|
|
10788
|
+
point1 = new THREE.Vector3(pointa.x - x, pointa.y - y, wallHeight);
|
|
10789
|
+
point2 = new THREE.Vector3(pointb.x - x, pointb.y - y, wallHeight);
|
|
10659
10790
|
} else {
|
|
10660
|
-
point1 = new THREE.Vector3(pointa.x +
|
|
10661
|
-
point2 = new THREE.Vector3(pointb.x +
|
|
10791
|
+
point1 = new THREE.Vector3(pointa.x + x, pointa.y + y, wallHeight);
|
|
10792
|
+
point2 = new THREE.Vector3(pointb.x + x, pointb.y + y, wallHeight);
|
|
10662
10793
|
}
|
|
10663
10794
|
return [point1, point2];
|
|
10664
10795
|
}
|
|
@@ -10888,7 +11019,6 @@ class Scenario {
|
|
|
10888
11019
|
//
|
|
10889
11020
|
createAPlane(lines, menList) {
|
|
10890
11021
|
const lineList = lines;
|
|
10891
|
-
console.log("初始数据", lines);
|
|
10892
11022
|
let precision = lineList.map((pos) => {
|
|
10893
11023
|
pos.start.x = parseFloat(pos.start.x.toFixed(3));
|
|
10894
11024
|
pos.start.y = parseFloat(pos.start.y.toFixed(3));
|
|
@@ -19267,6 +19397,9 @@ function stepEliminationMerge(target, _, source, oldLine) {
|
|
|
19267
19397
|
function linesSmoothing(lines, _) {
|
|
19268
19398
|
repetitiveTask(2, () => lines = stepElimination(lines, 0.1, stepEliminationMerge));
|
|
19269
19399
|
WallInsertObject.recomputed(lines);
|
|
19400
|
+
TEST = true;
|
|
19401
|
+
lines = stepElimination(lines, 0.1, stepEliminationMerge);
|
|
19402
|
+
TEST = false;
|
|
19270
19403
|
return lines;
|
|
19271
19404
|
}
|
|
19272
19405
|
const PRE_PROCESSOR = {
|
|
@@ -22031,7 +22164,6 @@ async function buildJson(opt) {
|
|
|
22031
22164
|
if (opt.axisAlignCorr !== false) {
|
|
22032
22165
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
|
|
22033
22166
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.LinesSmoothing);
|
|
22034
|
-
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.RemoveShortDoubleWall);
|
|
22035
22167
|
}
|
|
22036
22168
|
if (trajectory2) {
|
|
22037
22169
|
if (typeof trajectory2 === "string") {
|
|
@@ -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;
|