build-dxf 0.1.87 → 0.1.88
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 +134 -151
- package/src/index.css +8 -4
- package/src/utils/DxfSystem/utils/lineHandle/CadPreProcessor/axisAlignCorr.d.ts +0 -3
- package/src/utils/algorithmsStructures/LineSegment.d.ts +8 -1
- package/src/utils/algorithmsStructures/MiniCircles.d.ts +3 -1
- package/src/utils/algorithmsStructures/Point.d.ts +1 -1
- package/src/utils/algorithmsStructures/PointVirtualGrid.d.ts +1 -1
- package/src/utils/algorithmsStructures/UndirectedGraph.d.ts +4 -0
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -377,7 +377,7 @@ class PointVirtualGrid {
|
|
|
377
377
|
* 查找相同点
|
|
378
378
|
* @param point
|
|
379
379
|
*/
|
|
380
|
-
queryPoint(point2, excludeOneself = false) {
|
|
380
|
+
queryPoint(point2, excludeOneself = false, eps = 1e-9) {
|
|
381
381
|
const list = new PvgList();
|
|
382
382
|
let set2;
|
|
383
383
|
if (point2.currentData[this.id]) {
|
|
@@ -387,7 +387,7 @@ class PointVirtualGrid {
|
|
|
387
387
|
if (this.map.has(id)) set2 = this.map.get(id);
|
|
388
388
|
}
|
|
389
389
|
set2?.forEach((item) => {
|
|
390
|
-
if (point2.equal(item.point)) {
|
|
390
|
+
if (point2.equal(item.point, eps)) {
|
|
391
391
|
if (excludeOneself && point2 === item.point) return;
|
|
392
392
|
list.push(item);
|
|
393
393
|
}
|
|
@@ -1706,13 +1706,20 @@ class LineSegment {
|
|
|
1706
1706
|
return (px * dx + py * dy) / len2;
|
|
1707
1707
|
}
|
|
1708
1708
|
/** 获取两条线段夹角
|
|
1709
|
-
* @deprecated
|
|
1709
|
+
* @deprecated 已废弃, 请使用 angle
|
|
1710
1710
|
* @param line
|
|
1711
1711
|
*/
|
|
1712
1712
|
includedAngle(line) {
|
|
1713
1713
|
const d1 = this.direction(), d2 = line.direction();
|
|
1714
1714
|
return d1.angleBetween(d2) / (Math.PI / 180);
|
|
1715
1715
|
}
|
|
1716
|
+
/** 获取两条线段夹角
|
|
1717
|
+
* @param line
|
|
1718
|
+
*/
|
|
1719
|
+
angle(line, opt) {
|
|
1720
|
+
const d1 = this.direction(), d2 = line.direction();
|
|
1721
|
+
return d1.angle(d2, opt);
|
|
1722
|
+
}
|
|
1716
1723
|
/**
|
|
1717
1724
|
* 判断两条线段,是否在同一直线上:
|
|
1718
1725
|
* - 返回 -1:不在同一直线(不共线)
|
|
@@ -2332,7 +2339,7 @@ class Point {
|
|
|
2332
2339
|
* @param point
|
|
2333
2340
|
* @returns
|
|
2334
2341
|
*/
|
|
2335
|
-
equal(point2) {
|
|
2342
|
+
equal(point2, eps = 1e-9) {
|
|
2336
2343
|
return Math.abs(point2.x - this.x) < 1e-9 && Math.abs(point2.y - this.y) < 1e-9;
|
|
2337
2344
|
}
|
|
2338
2345
|
/**
|
|
@@ -2594,8 +2601,8 @@ class Point {
|
|
|
2594
2601
|
}
|
|
2595
2602
|
return num;
|
|
2596
2603
|
}
|
|
2597
|
-
hashCode(fixed =
|
|
2598
|
-
return `${this.x.toFixed(fixed)},${this.y.toFixed(
|
|
2604
|
+
hashCode(fixed = 6) {
|
|
2605
|
+
return `${this.x.toFixed(fixed)},${this.y.toFixed(fixed)}`;
|
|
2599
2606
|
}
|
|
2600
2607
|
/**
|
|
2601
2608
|
* 克隆
|
|
@@ -2641,7 +2648,7 @@ class Point {
|
|
|
2641
2648
|
* @param tolerance
|
|
2642
2649
|
* @returns
|
|
2643
2650
|
*/
|
|
2644
|
-
static adsorb(points, tolerance =
|
|
2651
|
+
static adsorb(points, tolerance = 1e-3, mode = "average") {
|
|
2645
2652
|
const grid = new PointVirtualGrid();
|
|
2646
2653
|
points.forEach((p2) => grid.insert(p2));
|
|
2647
2654
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -2662,7 +2669,6 @@ class Point {
|
|
|
2662
2669
|
results.forEach((p2) => {
|
|
2663
2670
|
p2.set(x, y);
|
|
2664
2671
|
visited.add(p2);
|
|
2665
|
-
grid.update(p2);
|
|
2666
2672
|
grid.remove(p2);
|
|
2667
2673
|
});
|
|
2668
2674
|
}
|
|
@@ -3473,6 +3479,18 @@ class UndirectedGraph {
|
|
|
3473
3479
|
callbackFun(node, neighbors);
|
|
3474
3480
|
}
|
|
3475
3481
|
}
|
|
3482
|
+
/** 遍历边
|
|
3483
|
+
* @param callbackFun
|
|
3484
|
+
*/
|
|
3485
|
+
forEachEdge(callbackFun) {
|
|
3486
|
+
for (const [node, neighbors] of this.adjacencyList.entries()) {
|
|
3487
|
+
for (const neighbor of neighbors) {
|
|
3488
|
+
if (neighbor > node) {
|
|
3489
|
+
callbackFun(node, neighbor);
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3492
|
+
}
|
|
3493
|
+
}
|
|
3476
3494
|
}
|
|
3477
3495
|
class LineSegmentUndirectedGraph extends UndirectedGraph {
|
|
3478
3496
|
// 线段存储:使用规范化 key (小索引-大索引) 避免双向存储
|
|
@@ -3630,7 +3648,7 @@ class LineSegmentUndirectedGraph extends UndirectedGraph {
|
|
|
3630
3648
|
* @returns
|
|
3631
3649
|
*/
|
|
3632
3650
|
static breakpointMerging(lines, callBack, removeLines = /* @__PURE__ */ new Set(), newLines = []) {
|
|
3633
|
-
Point.adsorb(lines.flatMap((line) => line.points));
|
|
3651
|
+
Point.adsorb(lines.flatMap((line) => line.points), 1e-4);
|
|
3634
3652
|
const lud = new LineSegmentUndirectedGraph(lines);
|
|
3635
3653
|
lud.breakpointMerging(callBack, removeLines, newLines);
|
|
3636
3654
|
lines = lud.getLineAll();
|
|
@@ -5915,7 +5933,7 @@ function migration(newLine, oldLine) {
|
|
|
5915
5933
|
}) ?? [];
|
|
5916
5934
|
});
|
|
5917
5935
|
}
|
|
5918
|
-
function lineSegmentClipping(lines, minLen =
|
|
5936
|
+
function lineSegmentClipping(lines, minLen = 1e-9, dedup = true) {
|
|
5919
5937
|
const quadtree = new Quadtree(Box2.fromByLineSegment(...lines));
|
|
5920
5938
|
lines.forEach((line) => quadtree.insert({ line, userData: void 0 }));
|
|
5921
5939
|
let newLines = lines.flatMap((line) => {
|
|
@@ -5952,34 +5970,30 @@ var Side = /* @__PURE__ */ ((Side2) => {
|
|
|
5952
5970
|
})(Side || {});
|
|
5953
5971
|
class MiniCircles {
|
|
5954
5972
|
debug = {
|
|
5955
|
-
angle: false
|
|
5973
|
+
angle: false,
|
|
5974
|
+
edges: false
|
|
5956
5975
|
};
|
|
5976
|
+
scope = 1e-3;
|
|
5957
5977
|
/** 通过并查集,查找为环的一部分边
|
|
5958
5978
|
* @description
|
|
5959
5979
|
* @param lines
|
|
5960
5980
|
*/
|
|
5961
5981
|
findCycleEntryEdges(lineUG_) {
|
|
5962
5982
|
if (!(lineUG_ instanceof LineSegmentUndirectedGraph)) {
|
|
5963
|
-
if (Array.isArray(lineUG_))
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
visited.add(n1);
|
|
5969
|
-
const neighbors = lineUG.getNeighbors(n1);
|
|
5970
|
-
neighbors?.forEach((n2) => {
|
|
5971
|
-
if (visited.has(n2)) return;
|
|
5972
|
-
if (unionFindSet.find(n1) === unionFindSet.find(n2)) {
|
|
5973
|
-
const line = lineUG.getLine(n1, n2);
|
|
5974
|
-
ringEdges.push(line);
|
|
5975
|
-
} else {
|
|
5976
|
-
unionFindSet.union(n1, n2);
|
|
5977
|
-
}
|
|
5978
|
-
});
|
|
5983
|
+
if (Array.isArray(lineUG_)) {
|
|
5984
|
+
lineUG_ = new LineSegmentUndirectedGraph(lineUG_);
|
|
5985
|
+
} else {
|
|
5986
|
+
throw new Error("参数错误");
|
|
5987
|
+
}
|
|
5979
5988
|
}
|
|
5980
|
-
lineUG.
|
|
5981
|
-
|
|
5982
|
-
|
|
5989
|
+
const lineUG = lineUG_, unionFind = new UnionFindSet(lineUG.size), ringEdges = [];
|
|
5990
|
+
lineUG.forEachEdge((n1, n2) => {
|
|
5991
|
+
const line = lineUG.getLine(n1, n2);
|
|
5992
|
+
if (unionFind.find(n1) === unionFind.find(n2)) {
|
|
5993
|
+
ringEdges.push(line);
|
|
5994
|
+
} else {
|
|
5995
|
+
unionFind.union(n1, n2);
|
|
5996
|
+
}
|
|
5983
5997
|
});
|
|
5984
5998
|
return ringEdges;
|
|
5985
5999
|
}
|
|
@@ -6024,7 +6038,7 @@ class MiniCircles {
|
|
|
6024
6038
|
*/
|
|
6025
6039
|
findSameSidePath(opt) {
|
|
6026
6040
|
let count = 0;
|
|
6027
|
-
let { A, B, exitPoint, grid, path = /* @__PURE__ */ new Set() } = opt;
|
|
6041
|
+
let { A, B, exitPoint = A, grid, path = /* @__PURE__ */ new Set() } = opt;
|
|
6028
6042
|
if (Array.isArray(grid)) {
|
|
6029
6043
|
const lines = grid;
|
|
6030
6044
|
grid = new PointVirtualGrid();
|
|
@@ -6036,7 +6050,7 @@ class MiniCircles {
|
|
|
6036
6050
|
return;
|
|
6037
6051
|
}
|
|
6038
6052
|
if (exitPoint.equal(B)) return [...path];
|
|
6039
|
-
const candidates = grid.
|
|
6053
|
+
const candidates = grid.queryCircle(B, this.scope).filter((item) => item.point !== B).filter((item) => !path.has(item.userData));
|
|
6040
6054
|
if (candidates.length === 0) return;
|
|
6041
6055
|
const BA = A.directionFrom(B);
|
|
6042
6056
|
let minAngle = Infinity;
|
|
@@ -6626,7 +6640,7 @@ function initData(lines) {
|
|
|
6626
6640
|
doorLines.push(line);
|
|
6627
6641
|
continue;
|
|
6628
6642
|
}
|
|
6629
|
-
if (line.userData.isBayWindow) {
|
|
6643
|
+
if (line.userData.isBayWindow || line.userData.isWindow && LineGroupType.hasType(line, "bayWindow")) {
|
|
6630
6644
|
bayWindowLines.push(line);
|
|
6631
6645
|
continue;
|
|
6632
6646
|
}
|
|
@@ -6659,11 +6673,11 @@ function getPeDoubleDoorCircles(lines, peDoubleDoorLines) {
|
|
|
6659
6673
|
};
|
|
6660
6674
|
}
|
|
6661
6675
|
function buildDoubleWallGroup_(lines_, clearInternalLine = false) {
|
|
6676
|
+
Point.adsorb(lines_.flatMap((line) => line.points), 5e-4);
|
|
6677
|
+
lines_ = lines_.filter((line) => line.len > 1e-7);
|
|
6662
6678
|
const {
|
|
6663
6679
|
doorLines,
|
|
6664
6680
|
otherLines,
|
|
6665
|
-
// bayWindowLines,
|
|
6666
|
-
// peDoors,
|
|
6667
6681
|
peDoubleDoors
|
|
6668
6682
|
} = initData(lines_);
|
|
6669
6683
|
const { circlesList } = getPeDoubleDoorCircles(otherLines, peDoubleDoors);
|
|
@@ -6689,7 +6703,7 @@ function buildDoubleWallGroup_(lines_, clearInternalLine = false) {
|
|
|
6689
6703
|
});
|
|
6690
6704
|
const internalEdgesSet = new Set(internalEdges);
|
|
6691
6705
|
lines_ = lines_.filter((line) => !internalEdgesSet.has(line));
|
|
6692
|
-
return LineSegmentUndirectedGraph.breakpointMerging(lines_, mergeLineUserData).filter((line) => line.length() > 1e-
|
|
6706
|
+
return LineSegmentUndirectedGraph.breakpointMerging(lines_, mergeLineUserData).filter((line) => line.length() > 1e-9);
|
|
6693
6707
|
}
|
|
6694
6708
|
const buildDoubleWallGroup = Object.assign(buildDoubleWallGroup_, {
|
|
6695
6709
|
setTrajectory(trajectory_) {
|
|
@@ -6792,7 +6806,7 @@ class DoubleWallHelper {
|
|
|
6792
6806
|
}
|
|
6793
6807
|
resultList.forEach((result) => {
|
|
6794
6808
|
const project0 = result.project, project1 = result.project2, line0 = result.source, line1 = result.target;
|
|
6795
|
-
if (project0.
|
|
6809
|
+
if (project0.angle(project1, { unit: "degree", range: "180" }) > 135) {
|
|
6796
6810
|
project1.points = [project1.points[1], project1.points[0]];
|
|
6797
6811
|
}
|
|
6798
6812
|
const newLine1 = new LineSegment(project0.start.clone(), project1.start.clone());
|
|
@@ -6828,7 +6842,7 @@ class DoubleWallHelper {
|
|
|
6828
6842
|
quadtree.clear();
|
|
6829
6843
|
lines.push(...otherLines);
|
|
6830
6844
|
Point.adsorb(lines.flatMap((line) => line.points), 1e-4);
|
|
6831
|
-
return lines.filter((line) => line.length() > 1e-
|
|
6845
|
+
return lines.filter((line) => line.length() > 1e-9);
|
|
6832
6846
|
}
|
|
6833
6847
|
/**
|
|
6834
6848
|
* 创建分组
|
|
@@ -6836,14 +6850,16 @@ class DoubleWallHelper {
|
|
|
6836
6850
|
static buildGroup(lineSegments) {
|
|
6837
6851
|
const doors = [];
|
|
6838
6852
|
lineSegments = lineSegments.filter((line) => {
|
|
6839
|
-
if (line.userData.isDoor) {
|
|
6853
|
+
if (line.userData.isDoor || line.userData.isBalconyRailing || line.userData.isBayWindow) {
|
|
6840
6854
|
doors.push(line);
|
|
6841
6855
|
return false;
|
|
6842
6856
|
}
|
|
6843
6857
|
return true;
|
|
6844
6858
|
});
|
|
6859
|
+
lineSegments = buildDoubleWallGroup(lineSegments, true);
|
|
6845
6860
|
lineSegments = this.complementSide(lineSegments);
|
|
6846
|
-
|
|
6861
|
+
WallInsertObject.recomputed(lineSegments);
|
|
6862
|
+
lineSegments = buildDoubleWallGroup(lineSegments, true);
|
|
6847
6863
|
return [...lineSegments, ...doors];
|
|
6848
6864
|
}
|
|
6849
6865
|
}
|
|
@@ -7477,7 +7493,6 @@ class ThreeVJiaJson extends Pipeline {
|
|
|
7477
7493
|
}
|
|
7478
7494
|
}
|
|
7479
7495
|
function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
7480
|
-
angle = 0;
|
|
7481
7496
|
lineSegments = LineSegmentUndirectedGraph.rotate(lineSegments.map((line) => line.clone()), angle, (line, center, angle2) => {
|
|
7482
7497
|
WallInsertObject.forEachInsertObjectData(line, (data) => {
|
|
7483
7498
|
data.forEach((item) => {
|
|
@@ -8180,7 +8195,7 @@ class DxfDrawPlugin {
|
|
|
8180
8195
|
const line = lineSegment.clone();
|
|
8181
8196
|
const doorThickness = DEFAULT_WALL_WIDTH * 0.2;
|
|
8182
8197
|
const list = [];
|
|
8183
|
-
setColor("
|
|
8198
|
+
setColor("yellow");
|
|
8184
8199
|
if (line.length() < 1.2) {
|
|
8185
8200
|
line.extendAlongDirection(-doorThickness * 0.5);
|
|
8186
8201
|
const normal = lineSegment.normal();
|
|
@@ -8213,7 +8228,7 @@ class DxfDrawPlugin {
|
|
|
8213
8228
|
cad.addDrawHandler({
|
|
8214
8229
|
type: ["window"],
|
|
8215
8230
|
handler: ({ group, drawLine, setColor }) => {
|
|
8216
|
-
setColor("
|
|
8231
|
+
setColor("cyan");
|
|
8217
8232
|
group.lines.forEach((line) => {
|
|
8218
8233
|
drawLine(line.start, line.end);
|
|
8219
8234
|
line.toRectangle(line?.userData?.wallWidth ?? DEFAULT_WALL_WIDTH, "butt").path2D((p1, p2) => drawLine(p1, p2));
|
|
@@ -18751,67 +18766,6 @@ function init(lines, option) {
|
|
|
18751
18766
|
buildDoubleWallGroup.setTrajectory(option.trajectory);
|
|
18752
18767
|
return lines;
|
|
18753
18768
|
}
|
|
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
18769
|
function parallel(line, baseline) {
|
|
18816
18770
|
const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
|
|
18817
18771
|
const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
|
|
@@ -18933,6 +18887,67 @@ class AxisAlignCorr {
|
|
|
18933
18887
|
this.addVisited(line);
|
|
18934
18888
|
}
|
|
18935
18889
|
}
|
|
18890
|
+
class LineQueryer {
|
|
18891
|
+
pointVirtualGrid;
|
|
18892
|
+
quadtree;
|
|
18893
|
+
constructor(lines) {
|
|
18894
|
+
this.pointVirtualGrid = createPointVirtualGrid(lines);
|
|
18895
|
+
this.quadtree = createQuadtree(lines);
|
|
18896
|
+
}
|
|
18897
|
+
update(lines) {
|
|
18898
|
+
this.clear();
|
|
18899
|
+
this.pointVirtualGrid = createPointVirtualGrid(lines);
|
|
18900
|
+
this.quadtree = createQuadtree(lines);
|
|
18901
|
+
}
|
|
18902
|
+
clear() {
|
|
18903
|
+
this.pointVirtualGrid.clear();
|
|
18904
|
+
this.quadtree.clear();
|
|
18905
|
+
}
|
|
18906
|
+
/**
|
|
18907
|
+
* @param point
|
|
18908
|
+
* @param radius
|
|
18909
|
+
* @param opt
|
|
18910
|
+
* @returns
|
|
18911
|
+
*/
|
|
18912
|
+
queryNearestPoint(point2, opt) {
|
|
18913
|
+
if (!point2) throw new Error("请传入查询点");
|
|
18914
|
+
const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
|
|
18915
|
+
const results = this.pointVirtualGrid.queryCircle(point2, radius).filter((item) => item.point !== point2).filter((item) => condition ? condition(item) : true);
|
|
18916
|
+
results.sort((a2, b4) => a2.point.distance(point2, true) - b4.point.distance(point2, true));
|
|
18917
|
+
if (results.length > resultIndex) return {
|
|
18918
|
+
point: results[resultIndex].point,
|
|
18919
|
+
line: results[resultIndex].userData
|
|
18920
|
+
};
|
|
18921
|
+
return null;
|
|
18922
|
+
}
|
|
18923
|
+
/**
|
|
18924
|
+
* @param point
|
|
18925
|
+
* @param radius
|
|
18926
|
+
* @param opt
|
|
18927
|
+
* @returns
|
|
18928
|
+
*/
|
|
18929
|
+
queryNearestLine(point2, opt) {
|
|
18930
|
+
if (!point2) throw new Error("请传入查询点");
|
|
18931
|
+
const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
|
|
18932
|
+
const results = this.quadtree.queryCircle(point2, radius).map((item) => {
|
|
18933
|
+
const projPoint = item.line.projectPoint(point2, false);
|
|
18934
|
+
if (projPoint && (!condition || condition(item, projPoint))) {
|
|
18935
|
+
if (projPoint) return {
|
|
18936
|
+
...item,
|
|
18937
|
+
distance: projPoint.distance(point2) ?? Infinity,
|
|
18938
|
+
projPoint
|
|
18939
|
+
};
|
|
18940
|
+
}
|
|
18941
|
+
return null;
|
|
18942
|
+
}).filter((i) => !!i);
|
|
18943
|
+
results.sort((a2, b4) => a2.distance - b4.distance);
|
|
18944
|
+
if (results.length > resultIndex) return {
|
|
18945
|
+
point: results[resultIndex].projPoint,
|
|
18946
|
+
line: results[resultIndex].line
|
|
18947
|
+
};
|
|
18948
|
+
return null;
|
|
18949
|
+
}
|
|
18950
|
+
}
|
|
18936
18951
|
function shortDistanceLink(lines, radius = 0.1) {
|
|
18937
18952
|
const dpSet = findDiscretePoint(lines.filter((line) => !line.userData.isDoor)), pointVirtualGrid = createPointVirtualGrid(dpSet.map((v2) => v2)), appendLines = [], visited = /* @__PURE__ */ new Set();
|
|
18938
18953
|
const getWeight2 = (target, point2, line) => {
|
|
@@ -19001,22 +19016,6 @@ function adsorption(lines, option) {
|
|
|
19001
19016
|
});
|
|
19002
19017
|
if (result) return modifyManager.setPoint(line, point2, result.point.clone());
|
|
19003
19018
|
}
|
|
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
19019
|
for (let i = 0; i < lines.length; i++) {
|
|
19021
19020
|
const line = lines[i];
|
|
19022
19021
|
line.points.map((point2) => {
|
|
@@ -19025,25 +19024,13 @@ function adsorption(lines, option) {
|
|
|
19025
19024
|
});
|
|
19026
19025
|
}
|
|
19027
19026
|
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
19027
|
lineQueryer.clear();
|
|
19042
|
-
Point.adsorb(lines.flatMap((line) => line.points), 1e-
|
|
19028
|
+
Point.adsorb(lines.flatMap((line) => line.points), 1e-3);
|
|
19043
19029
|
return lines;
|
|
19044
19030
|
}
|
|
19045
19031
|
function removeShortLine(lines, len = 0.01) {
|
|
19046
19032
|
let defaultLines = [], doorLines = [];
|
|
19033
|
+
Point.adsorb(lines.flatMap((line) => line.points), 1e-3);
|
|
19047
19034
|
for (let i = 0; i < lines.length; i++) {
|
|
19048
19035
|
const line = lines[i];
|
|
19049
19036
|
if (line.userData.isDoor) doorLines.push(line);
|
|
@@ -19091,17 +19078,14 @@ function correction(lines, targettLine, option) {
|
|
|
19091
19078
|
newLines = buildBayWindowGroup(newLines, false);
|
|
19092
19079
|
const { wallGroup = true } = option ?? {};
|
|
19093
19080
|
if (wallGroup) {
|
|
19094
|
-
newLines = DoubleWallHelper.
|
|
19095
|
-
WallInsertObject.recomputed(newLines);
|
|
19096
|
-
newLines = buildDoubleWallGroup(newLines, true);
|
|
19081
|
+
newLines = DoubleWallHelper.buildGroup(newLines);
|
|
19097
19082
|
newLines = buildBayWindowGroup(newLines, false);
|
|
19098
19083
|
}
|
|
19099
|
-
new WallInsertObject(
|
|
19084
|
+
new WallInsertObject(newLines).recomputed().merge();
|
|
19100
19085
|
newLines.push(...doorLines);
|
|
19101
|
-
|
|
19102
|
-
|
|
19103
|
-
|
|
19104
|
-
return newLines;
|
|
19086
|
+
newLines = removeShortLine(newLines, 0.05);
|
|
19087
|
+
newLines = breakpointMerging(newLines);
|
|
19088
|
+
return newLines.filter((line) => line.len > 7e-9);
|
|
19105
19089
|
}
|
|
19106
19090
|
function axisAlignCorr(lines, option, verticalReferenceLine) {
|
|
19107
19091
|
verticalReferenceLine = verticalReferenceLine ?? findVerticalReference(lines.filter((line) => !line.userData.isDoor));
|
|
@@ -19288,7 +19272,7 @@ function getNextPoint(point2, line, next, width) {
|
|
|
19288
19272
|
function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
19289
19273
|
const grid = createPointVirtualGrid(lineSegments);
|
|
19290
19274
|
function getIntersInfo(line, point2) {
|
|
19291
|
-
const intersList = grid.
|
|
19275
|
+
const intersList = grid.queryCircle(point2, 1e-4).filter((item) => item.point !== point2);
|
|
19292
19276
|
if (intersList.length == 0) return;
|
|
19293
19277
|
let firstLine = null, firstPoint = null;
|
|
19294
19278
|
let count = 0;
|
|
@@ -19306,7 +19290,7 @@ function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
|
19306
19290
|
if (count !== 1) return;
|
|
19307
19291
|
if (!firstLine || !firstPoint) return;
|
|
19308
19292
|
const firstOtherPoint = firstLine.getAnotherPoint(firstPoint);
|
|
19309
|
-
const nextResult = grid.
|
|
19293
|
+
const nextResult = grid.queryCircle(firstOtherPoint, 1e-4).filter((item) => item.point !== firstOtherPoint);
|
|
19310
19294
|
return {
|
|
19311
19295
|
length: firstLine.length(),
|
|
19312
19296
|
firstLine,
|
|
@@ -19318,17 +19302,18 @@ function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
|
19318
19302
|
parallel: parallel2
|
|
19319
19303
|
};
|
|
19320
19304
|
}
|
|
19321
|
-
const
|
|
19305
|
+
const removeLinesSet = /* @__PURE__ */ new Set();
|
|
19322
19306
|
for (let i = 0; i < lineSegments.length; i++) {
|
|
19323
19307
|
const line = lineSegments[i];
|
|
19308
|
+
if (removeLinesSet.has(line)) continue;
|
|
19324
19309
|
const len = line.length();
|
|
19325
19310
|
if (len > findMinWidth) continue;
|
|
19326
19311
|
const startInfo = getIntersInfo(line, line.start);
|
|
19327
19312
|
if (!startInfo) continue;
|
|
19328
19313
|
const endInfo = getIntersInfo(line, line.end);
|
|
19329
19314
|
if (!endInfo) continue;
|
|
19330
|
-
const angle = startInfo.direction.
|
|
19331
|
-
if (angle <
|
|
19315
|
+
const angle = startInfo.direction.angle(endInfo.direction, { unit: "degree", range: "180" });
|
|
19316
|
+
if (angle < 177) continue;
|
|
19332
19317
|
if (!startInfo.nextOnlyVertical && !endInfo.nextOnlyVertical) continue;
|
|
19333
19318
|
let mainInfo = startInfo, secondaryInfo = endInfo;
|
|
19334
19319
|
if (startInfo.nextOnlyVertical && endInfo.nextOnlyVertical) {
|
|
@@ -19343,13 +19328,13 @@ function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
|
19343
19328
|
const parallel2 = startInfo.parallel.concat(endInfo.parallel);
|
|
19344
19329
|
const newPoint = getNextPoint(mainInfo.firstPoint, mainInfo.firstLine, secondaryInfo.next, secondaryInfo.length);
|
|
19345
19330
|
if (!newPoint) continue;
|
|
19346
|
-
|
|
19331
|
+
removeLinesSet.add(line);
|
|
19347
19332
|
line.points.forEach((p2) => grid.remove(p2));
|
|
19348
19333
|
if (parallel2.length === 0) {
|
|
19349
19334
|
const oldLine = mainInfo.firstLine.clone();
|
|
19350
19335
|
mainInfo.firstPoint.copy(newPoint);
|
|
19351
19336
|
secondaryInfo.next.forEach((d2) => d2.point.copy(newPoint));
|
|
19352
|
-
|
|
19337
|
+
removeLinesSet.add(secondaryInfo.firstLine);
|
|
19353
19338
|
secondaryInfo.firstLine.points.forEach((p2) => grid.remove(p2));
|
|
19354
19339
|
mainInfo.firstLine.points.forEach((p2) => grid.update(p2));
|
|
19355
19340
|
if (typeof onMerge === "function") onMerge(mainInfo.firstLine, line, secondaryInfo.firstLine, oldLine);
|
|
@@ -19363,7 +19348,6 @@ function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
|
19363
19348
|
startInfo.parallel.concat(endInfo.parallel).forEach((item) => grid.update(item.point));
|
|
19364
19349
|
}
|
|
19365
19350
|
}
|
|
19366
|
-
const removeLinesSet = new Set(removeLines);
|
|
19367
19351
|
lineSegments = lineSegments.filter((line) => !removeLinesSet.has(line));
|
|
19368
19352
|
return lineSegments;
|
|
19369
19353
|
}
|
|
@@ -19647,7 +19631,6 @@ class CorrectionDxf extends Dxf {
|
|
|
19647
19631
|
onAddFromParent(parent) {
|
|
19648
19632
|
parent.Dxf.addEventListener("cadChange", (e) => {
|
|
19649
19633
|
e.options.trajectory && this.addPreProcessor(PRE_PROCESSOR.BoundExt);
|
|
19650
|
-
this.addPreProcessor(PRE_PROCESSOR.DoubleWallAlignment);
|
|
19651
19634
|
const lines = parent.Dxf.getLineSegments(true);
|
|
19652
19635
|
this.set(lineDataToOriginalData(lines, parent.Dxf.originalZAverage), {
|
|
19653
19636
|
trajectory: e.options.trajectory,
|
package/src/index.css
CHANGED
|
@@ -387,10 +387,6 @@
|
|
|
387
387
|
height: 20px;
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
.h-\[100\%\] {
|
|
391
|
-
height: 100%;
|
|
392
|
-
}
|
|
393
|
-
|
|
394
390
|
.h-\[100vh\] {
|
|
395
391
|
height: 100vh;
|
|
396
392
|
}
|
|
@@ -399,6 +395,10 @@
|
|
|
399
395
|
height: 100%;
|
|
400
396
|
}
|
|
401
397
|
|
|
398
|
+
.h-screen {
|
|
399
|
+
height: 100vh;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
402
|
.max-h-\[300px\] {
|
|
403
403
|
max-height: 300px;
|
|
404
404
|
}
|
|
@@ -427,6 +427,10 @@
|
|
|
427
427
|
width: 100%;
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
+
.w-screen {
|
|
431
|
+
width: 100vw;
|
|
432
|
+
}
|
|
433
|
+
|
|
430
434
|
.max-w-\[150px\] {
|
|
431
435
|
max-width: 150px;
|
|
432
436
|
}
|
|
@@ -169,10 +169,17 @@ export declare class LineSegment<T = Record<string, any>> {
|
|
|
169
169
|
*/
|
|
170
170
|
projectPointValue(point: Point, eps?: number): number;
|
|
171
171
|
/** 获取两条线段夹角
|
|
172
|
-
* @deprecated
|
|
172
|
+
* @deprecated 已废弃, 请使用 angle
|
|
173
173
|
* @param line
|
|
174
174
|
*/
|
|
175
175
|
includedAngle(line: LineSegment): number;
|
|
176
|
+
/** 获取两条线段夹角
|
|
177
|
+
* @param line
|
|
178
|
+
*/
|
|
179
|
+
angle(line: LineSegment, opt?: {
|
|
180
|
+
unit?: "radian" | "degree" | "cos";
|
|
181
|
+
range?: "180" | "360";
|
|
182
|
+
}): number;
|
|
176
183
|
/**
|
|
177
184
|
* 判断两条线段,是否在同一直线上:
|
|
178
185
|
* - 返回 -1:不在同一直线(不共线)
|
|
@@ -15,7 +15,9 @@ export interface MiniCirclesOption {
|
|
|
15
15
|
export declare class MiniCircles {
|
|
16
16
|
debug: {
|
|
17
17
|
angle: boolean;
|
|
18
|
+
edges: boolean;
|
|
18
19
|
};
|
|
20
|
+
scope: number;
|
|
19
21
|
/** 通过并查集,查找为环的一部分边
|
|
20
22
|
* @description
|
|
21
23
|
* @param lines
|
|
@@ -38,7 +40,7 @@ export declare class MiniCircles {
|
|
|
38
40
|
findSameSidePath(opt: {
|
|
39
41
|
A: Point;
|
|
40
42
|
B: Point;
|
|
41
|
-
exitPoint
|
|
43
|
+
exitPoint?: Point;
|
|
42
44
|
grid: PointVirtualGrid<LineSegment> | LineSegment[];
|
|
43
45
|
path?: Set<LineSegment>;
|
|
44
46
|
}): LineSegment<Record<string, any>>[] | undefined;
|
|
@@ -81,7 +81,7 @@ export declare class PointVirtualGrid<T = Record<string, any>> {
|
|
|
81
81
|
* 查找相同点
|
|
82
82
|
* @param point
|
|
83
83
|
*/
|
|
84
|
-
queryPoint(point: Point, excludeOneself?: boolean): PvgList<T>;
|
|
84
|
+
queryPoint(point: Point, excludeOneself?: boolean, eps?: number): PvgList<T>;
|
|
85
85
|
/** 获取多边形内的点
|
|
86
86
|
* @param polygon
|
|
87
87
|
*/
|
|
@@ -18,6 +18,10 @@ export declare class UndirectedGraph {
|
|
|
18
18
|
* @param callbackFun
|
|
19
19
|
*/
|
|
20
20
|
forEach(callbackFun: (node: number, neighbors: Set<number>) => void): void;
|
|
21
|
+
/** 遍历边
|
|
22
|
+
* @param callbackFun
|
|
23
|
+
*/
|
|
24
|
+
forEachEdge(callbackFun: (u: number, v: number) => void): void;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* 线段无向图
|