build-dxf 0.0.18 → 0.0.19-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -0
- package/package.json +1 -3
- package/src/build.d.ts +10 -1
- package/src/build.js +555 -471
- package/src/components/Editor.vue.d.ts +26 -0
- package/src/index.js +3 -2
- package/src/index2.js +373 -3426
- package/src/index3.js +1937 -0
- package/src/pages/Editor.vue.d.ts +2 -0
- package/src/pages/Editor02.vue.d.ts +4 -0
- package/src/selectLocalFile.js +3745 -0
- package/src/utils/CommandManager/CommandFlow.d.ts +23 -0
- package/src/utils/CommandManager/CommandManager.d.ts +59 -0
- package/src/utils/CommandManager/index.d.ts +2 -0
- package/src/utils/ComponentManager/EventDispatcher.d.ts +11 -1
- package/src/utils/DxfSystem/components/Dxf.d.ts +15 -12
- package/src/utils/DxfSystem/components/LineAnalysis.d.ts +1 -20
- package/src/utils/DxfSystem/components/Variable.d.ts +8 -0
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/CommandFlowComponent.d.ts +36 -0
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/Default.d.ts +57 -0
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawDoorLine.d.ts +19 -0
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawLine.d.ts +20 -0
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/DrawWindow.d.ts +25 -0
- package/src/utils/DxfSystem/plugin/Editor/components/CommandFlow/PointDrag.d.ts +27 -0
- package/src/utils/DxfSystem/plugin/Editor/components/Editor.d.ts +22 -3
- package/src/utils/DxfSystem/plugin/Editor/components/RenderManager.d.ts +88 -0
- package/src/utils/DxfSystem/plugin/Editor/components/index.d.ts +6 -0
- package/src/utils/DxfSystem/plugin/Editor/pages/EditorTool.vue.d.ts +6 -0
- package/src/utils/DxfSystem/plugin/ModelDataPlugin/components/DxfLineModel.d.ts +7 -3
- package/src/utils/DxfSystem/plugin/ModelDataPlugin/index.d.ts +9 -1
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/DomContainer.d.ts +1 -0
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/DomEventRegister.d.ts +20 -1
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/EventInput.d.ts +74 -0
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/Renderer.d.ts +0 -11
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/index.d.ts +1 -0
- package/src/utils/DxfSystem/plugin/RenderPlugin/index.d.ts +11 -1
- package/src/utils/PointVirtualGrid/index.d.ts +10 -4
- package/src/utils/Quadtree/Box2.d.ts +3 -2
- package/src/utils/Quadtree/LineSegment.d.ts +11 -9
- package/src/utils/Quadtree/Point.d.ts +11 -6
- package/src/utils/Quadtree/Quadtree.d.ts +5 -0
- package/src/utils/Quadtree/Rectangle.d.ts +5 -4
package/src/build.js
CHANGED
|
@@ -12,6 +12,35 @@ function uuid() {
|
|
|
12
12
|
}
|
|
13
13
|
class EventDispatcher extends EventDispatcher$1 {
|
|
14
14
|
uuid = uuid();
|
|
15
|
+
addEventListener(type, listener, option) {
|
|
16
|
+
const { once = false } = option ?? {};
|
|
17
|
+
const callBack = (event) => {
|
|
18
|
+
listener(event);
|
|
19
|
+
once && canceCallBack();
|
|
20
|
+
};
|
|
21
|
+
const canceCallBack = () => this.removeEventListener(type, callBack);
|
|
22
|
+
super.addEventListener(type, callBack);
|
|
23
|
+
return canceCallBack;
|
|
24
|
+
}
|
|
25
|
+
eventRecordStack = /* @__PURE__ */ new Map();
|
|
26
|
+
addEventRecord(name, ...cancels) {
|
|
27
|
+
if (!this.eventRecordStack.has(name)) this.eventRecordStack.set(name, []);
|
|
28
|
+
cancels.forEach((cancel) => {
|
|
29
|
+
this.eventRecordStack.get(name)?.push(cancel);
|
|
30
|
+
});
|
|
31
|
+
const add = (cancel) => {
|
|
32
|
+
this.addEventRecord(name, cancel);
|
|
33
|
+
return { add };
|
|
34
|
+
};
|
|
35
|
+
return { add };
|
|
36
|
+
}
|
|
37
|
+
canceEventRecord(name) {
|
|
38
|
+
const list = this.eventRecordStack.get(name);
|
|
39
|
+
if (list) {
|
|
40
|
+
list.forEach((cancel) => cancel());
|
|
41
|
+
this.eventRecordStack.delete(name);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
15
44
|
}
|
|
16
45
|
class Component extends EventDispatcher {
|
|
17
46
|
parent;
|
|
@@ -119,6 +148,7 @@ class Point {
|
|
|
119
148
|
get Y() {
|
|
120
149
|
return this.y;
|
|
121
150
|
}
|
|
151
|
+
userData = {};
|
|
122
152
|
/**
|
|
123
153
|
*
|
|
124
154
|
* @param x
|
|
@@ -333,6 +363,12 @@ class Point {
|
|
|
333
363
|
this.x = p.x ?? 0;
|
|
334
364
|
this.y = p.y ?? 0;
|
|
335
365
|
}
|
|
366
|
+
toJson() {
|
|
367
|
+
return {
|
|
368
|
+
x: this.x,
|
|
369
|
+
y: this.y
|
|
370
|
+
};
|
|
371
|
+
}
|
|
336
372
|
static from(arr) {
|
|
337
373
|
if (Array.isArray(arr)) {
|
|
338
374
|
return new Point(arr[0], arr[1]);
|
|
@@ -564,12 +600,19 @@ class Box2 {
|
|
|
564
600
|
this.maxY *= scalar;
|
|
565
601
|
return this;
|
|
566
602
|
}
|
|
603
|
+
expansion(w) {
|
|
604
|
+
this.minX -= w;
|
|
605
|
+
this.minY -= w;
|
|
606
|
+
this.maxX += w;
|
|
607
|
+
this.maxY += w;
|
|
608
|
+
return this;
|
|
609
|
+
}
|
|
567
610
|
/**
|
|
568
611
|
*
|
|
569
612
|
* @returns
|
|
570
613
|
*/
|
|
571
614
|
clone() {
|
|
572
|
-
return new Box2(this.minX, this.
|
|
615
|
+
return new Box2(this.minX, this.maxX, this.minY, this.maxY);
|
|
573
616
|
}
|
|
574
617
|
/**
|
|
575
618
|
*
|
|
@@ -617,6 +660,16 @@ class Rectangle {
|
|
|
617
660
|
return [p.x, p.y, np.x, np.y];
|
|
618
661
|
});
|
|
619
662
|
}
|
|
663
|
+
createGeometry() {
|
|
664
|
+
return [
|
|
665
|
+
this.p0,
|
|
666
|
+
this.p2,
|
|
667
|
+
this.p1,
|
|
668
|
+
this.p2,
|
|
669
|
+
this.p0,
|
|
670
|
+
this.p3
|
|
671
|
+
].flatMap((p) => [p.x, p.y, 0]);
|
|
672
|
+
}
|
|
620
673
|
constructor(points) {
|
|
621
674
|
if (points.length !== 4) {
|
|
622
675
|
throw new Error("Rectangle must be defined by exactly 4 points");
|
|
@@ -781,6 +834,7 @@ class Rectangle {
|
|
|
781
834
|
class LineSegment {
|
|
782
835
|
points = [new Point(), new Point()];
|
|
783
836
|
userData = {};
|
|
837
|
+
line;
|
|
784
838
|
get center() {
|
|
785
839
|
return new Point(
|
|
786
840
|
this.points[0].x + (this.points[1].x - this.points[0].x) * 0.5,
|
|
@@ -937,11 +991,12 @@ class LineSegment {
|
|
|
937
991
|
return new LineSegment(projP1, projP2);
|
|
938
992
|
}
|
|
939
993
|
/**
|
|
940
|
-
*
|
|
941
|
-
* @param
|
|
994
|
+
* 计算一条线段在另一条直线上的投影
|
|
995
|
+
* @param p1 要投影的点
|
|
996
|
+
* @param clip 是否裁剪超出目标线段的部分,默认裁剪
|
|
942
997
|
* @returns 投影并裁剪后的线段
|
|
943
998
|
*/
|
|
944
|
-
projectPoint(p1) {
|
|
999
|
+
projectPoint(p1, clip = true) {
|
|
945
1000
|
const [q1, q2] = this.points;
|
|
946
1001
|
const dir = new Point(q2.x - q1.x, q2.y - q1.y);
|
|
947
1002
|
if (dir.x === 0 && dir.y === 0) {
|
|
@@ -957,6 +1012,7 @@ class LineSegment {
|
|
|
957
1012
|
return new Point(projX, projY);
|
|
958
1013
|
};
|
|
959
1014
|
let projP1 = projectPoint(p1);
|
|
1015
|
+
if (!clip) return projP1;
|
|
960
1016
|
const getT = (point) => {
|
|
961
1017
|
const pq = new Point(point.x - q1.x, point.y - q1.y);
|
|
962
1018
|
const dirLengthSquared = dir.x * dir.x + dir.y * dir.y;
|
|
@@ -1199,13 +1255,13 @@ class Dxf extends Component {
|
|
|
1199
1255
|
this.originalData = data;
|
|
1200
1256
|
this.lineSegments.length = 0;
|
|
1201
1257
|
const zList = [];
|
|
1202
|
-
this.data = data.map(({ start, end, insetionArr, isDoor = false, isWindow }, index2) => {
|
|
1258
|
+
this.data = data.map(({ start, end, insetionArr, isDoor = false, isWindow, drawDoorData }, index2) => {
|
|
1203
1259
|
zList.push(start.z ?? 0, end.z ?? 0);
|
|
1204
1260
|
const lineSegment = new LineSegment(
|
|
1205
1261
|
Point.from(start).mutiplyScalar(scale),
|
|
1206
1262
|
Point.from(end).mutiplyScalar(scale)
|
|
1207
1263
|
);
|
|
1208
|
-
lineSegment.userData = { isDoor, isWindow };
|
|
1264
|
+
lineSegment.userData = { isDoor, isWindow, drawDoorData };
|
|
1209
1265
|
this.lineSegments.push(lineSegment);
|
|
1210
1266
|
return [
|
|
1211
1267
|
lineSegment.points[0],
|
|
@@ -1470,14 +1526,14 @@ class Dxf extends Component {
|
|
|
1470
1526
|
/**
|
|
1471
1527
|
* 将点云结构转换为Float32Array
|
|
1472
1528
|
*/
|
|
1473
|
-
to3DArray(scale) {
|
|
1529
|
+
to3DArray(scale, z = this.originalZAverage) {
|
|
1474
1530
|
const array = [];
|
|
1475
1531
|
this.wallsGroup.forEach((points) => {
|
|
1476
1532
|
for (let i = 0; i < points.length; i++) {
|
|
1477
1533
|
const point1 = points[i];
|
|
1478
1534
|
const nextIndex = i === points.length - 1 ? 0 : i + 1;
|
|
1479
1535
|
const point2 = points[nextIndex];
|
|
1480
|
-
array.push(point1.X * scale, point1.Y * scale,
|
|
1536
|
+
array.push(point1.X * scale, point1.Y * scale, z, point2.X * scale, point2.Y * scale, z);
|
|
1481
1537
|
}
|
|
1482
1538
|
});
|
|
1483
1539
|
return new Float32Array(array);
|
|
@@ -1562,6 +1618,20 @@ class Dxf extends Component {
|
|
|
1562
1618
|
});
|
|
1563
1619
|
d.addLayer("l_yellow", Drawing.ACI.YELLOW, "DOTTED");
|
|
1564
1620
|
d.setActiveLayer("l_yellow");
|
|
1621
|
+
this.lineSegments.forEach((line) => {
|
|
1622
|
+
if (!line.userData.isWindow) return false;
|
|
1623
|
+
if (Array.isArray(line.userData.drawDoorData)) {
|
|
1624
|
+
line.userData.drawDoorData.forEach((w) => {
|
|
1625
|
+
const { p, width } = w;
|
|
1626
|
+
const center = Point.from(p);
|
|
1627
|
+
const start = center.clone().add(line.direction().multiplyScalar(width * 0.5));
|
|
1628
|
+
const end = center.clone().add(line.direction().multiplyScalar(-width * 0.5));
|
|
1629
|
+
const blinds = new LineSegment(start, end);
|
|
1630
|
+
drawLine(blinds.start, blinds.end);
|
|
1631
|
+
blinds.expandToRectangle(this.width, "bothSides").path2D((p1, p2) => drawLine(p1, p2));
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
});
|
|
1565
1635
|
return d.toDxfString();
|
|
1566
1636
|
}
|
|
1567
1637
|
/**
|
|
@@ -1644,6 +1714,10 @@ class Variable extends Component {
|
|
|
1644
1714
|
currentWheel = 0;
|
|
1645
1715
|
pointerMove = { x: 0, y: 0 };
|
|
1646
1716
|
currentKeyUp = "";
|
|
1717
|
+
currentKeyDown = "";
|
|
1718
|
+
currentMouseUp = "";
|
|
1719
|
+
currentMouseDown = "";
|
|
1720
|
+
focus = false;
|
|
1647
1721
|
set(key, value) {
|
|
1648
1722
|
if (key in this) {
|
|
1649
1723
|
const oldValue = this[key];
|
|
@@ -1695,6 +1769,7 @@ class Quadtree {
|
|
|
1695
1769
|
}
|
|
1696
1770
|
}
|
|
1697
1771
|
this.nodes.push(node);
|
|
1772
|
+
node.parent = this;
|
|
1698
1773
|
if (this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
|
|
1699
1774
|
this.subdivide();
|
|
1700
1775
|
const nodes = this.nodes;
|
|
@@ -1704,11 +1779,21 @@ class Quadtree {
|
|
|
1704
1779
|
if (quadrant !== -1) {
|
|
1705
1780
|
this.children[quadrant].insert(n);
|
|
1706
1781
|
} else {
|
|
1782
|
+
n.parent = this;
|
|
1707
1783
|
this.nodes.push(n);
|
|
1708
1784
|
}
|
|
1709
1785
|
}
|
|
1710
1786
|
}
|
|
1711
1787
|
}
|
|
1788
|
+
/** 移除
|
|
1789
|
+
* @param node
|
|
1790
|
+
*/
|
|
1791
|
+
remove(node) {
|
|
1792
|
+
const index2 = node.parent?.nodes.indexOf(node);
|
|
1793
|
+
if (index2 > -1) {
|
|
1794
|
+
node.parent?.nodes.splice(index2, 1);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1712
1797
|
/**
|
|
1713
1798
|
* 获取线段所属的象限
|
|
1714
1799
|
* @param line 线段
|
|
@@ -1915,7 +2000,9 @@ class PointVirtualGrid {
|
|
|
1915
2000
|
const id = this.getGridId(point);
|
|
1916
2001
|
if (!this.map.has(id)) this.map.set(id, /* @__PURE__ */ new Set());
|
|
1917
2002
|
const set = this.map.get(id);
|
|
1918
|
-
|
|
2003
|
+
const target = { point, userData };
|
|
2004
|
+
set.add(target);
|
|
2005
|
+
point.userData.pointVirtualGrid = { set, target };
|
|
1919
2006
|
}
|
|
1920
2007
|
/**
|
|
1921
2008
|
* 批量加入
|
|
@@ -1926,6 +2013,16 @@ class PointVirtualGrid {
|
|
|
1926
2013
|
this.insert(point, userData);
|
|
1927
2014
|
}
|
|
1928
2015
|
}
|
|
2016
|
+
/** 移除点
|
|
2017
|
+
* @param point
|
|
2018
|
+
*/
|
|
2019
|
+
remove(point) {
|
|
2020
|
+
const { set, target } = point?.userData?.pointVirtualGrid;
|
|
2021
|
+
if (set) {
|
|
2022
|
+
set.delete(target);
|
|
2023
|
+
delete point?.userData?.pointVirtualGridMap;
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
1929
2026
|
/**
|
|
1930
2027
|
* 获取通过坐标,获取唯一网格索引
|
|
1931
2028
|
* @param point
|
|
@@ -2018,219 +2115,167 @@ class PointVirtualGrid {
|
|
|
2018
2115
|
return list;
|
|
2019
2116
|
}
|
|
2020
2117
|
}
|
|
2021
|
-
class
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
// 误差角度
|
|
2028
|
-
errorAngle = 4;
|
|
2029
|
-
width = 0.4;
|
|
2030
|
-
/**
|
|
2031
|
-
*
|
|
2032
|
-
* @param parent
|
|
2033
|
-
*/
|
|
2034
|
-
onAddFromParent(parent) {
|
|
2035
|
-
this.Dxf = parent.findComponentByType(Dxf);
|
|
2036
|
-
this.Variable = this.parent?.findComponentByType(Variable);
|
|
2037
|
-
this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this));
|
|
2038
|
-
this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
|
|
2039
|
-
}
|
|
2040
|
-
/**
|
|
2041
|
-
*
|
|
2042
|
-
* @param p1
|
|
2043
|
-
* @param p2
|
|
2044
|
-
* @param width
|
|
2045
|
-
* @returns
|
|
2046
|
-
*/
|
|
2047
|
-
expandLineSegment(p1, p2, width = 0.1) {
|
|
2048
|
-
const normal = p2.normal(p1);
|
|
2049
|
-
const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
|
|
2050
|
-
const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
|
|
2051
|
-
const offsetX = normal.x * width * 0.5;
|
|
2052
|
-
const offsetY = normal.y * width * 0.5;
|
|
2053
|
-
return {
|
|
2054
|
-
points: [
|
|
2055
|
-
// 第一条线
|
|
2056
|
-
new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
|
|
2057
|
-
new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
|
|
2058
|
-
// 第二条线
|
|
2059
|
-
new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
|
|
2060
|
-
new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
|
|
2061
|
-
],
|
|
2062
|
-
indices: [0, 1, 1, 3, 3, 2, 2, 0],
|
|
2063
|
-
rectIndices: [0, 1, 3, 2, 0]
|
|
2064
|
-
};
|
|
2065
|
-
}
|
|
2066
|
-
appendLineSegmentList = [];
|
|
2067
|
-
/**
|
|
2068
|
-
* 追加数据
|
|
2069
|
-
* @param p1
|
|
2070
|
-
* @param p2
|
|
2071
|
-
*/
|
|
2072
|
-
addData(p1, p2) {
|
|
2073
|
-
const dxf = this.Dxf;
|
|
2074
|
-
dxf.data.push([p1.clone(), p2.clone(), [], false, dxf.data.length]);
|
|
2075
|
-
this.appendLineSegmentList.push(new LineSegment(p1.clone(), p2.clone()));
|
|
2076
|
-
}
|
|
2077
|
-
/** 结果分析创建矩形
|
|
2078
|
-
* @param result
|
|
2079
|
-
*/
|
|
2080
|
-
createRectangle(result) {
|
|
2081
|
-
const dxf = this.Dxf;
|
|
2082
|
-
const project0 = result.project, project1 = result.project2;
|
|
2083
|
-
if (project0.includedAngle(project1) > 135) {
|
|
2084
|
-
project1.points = [project1.points[1], project1.points[0]];
|
|
2085
|
-
}
|
|
2086
|
-
this.addData(project0.points[0], project1.points[0]);
|
|
2087
|
-
this.addData(project0.points[1], project1.points[1]);
|
|
2088
|
-
const leftHeight = project0.points[0].distance(project1.points[0]), rightHeight = project0.points[1].distance(project1.points[1]), count = Math.ceil(Math.max(leftHeight, rightHeight) / dxf.width), leftFragment = leftHeight / count, rightFragment = rightHeight / count, leftDirection = project1.points[0].direction(project0.points[0]), rightDirection = project1.points[1].direction(project0.points[1]), leftP = project0.points[0].clone(), rightP = project0.points[1].clone(), direction = rightP.direction(leftP);
|
|
2089
|
-
direction.multiplyScalar(dxf.width * 0.5);
|
|
2090
|
-
const _leftP = leftP.clone().add(direction), _rightP = rightP.clone().add(direction.multiplyScalar(-1)), d1 = leftP.direction(rightP), d2 = _leftP.direction(_rightP);
|
|
2091
|
-
if (d1.x > 0 && d2.x < 0 || d1.x < 0 && d2.x > 0 || d1.y > 0 && d2.y < 0 || d1.y < 0 && d2.y > 0) return;
|
|
2092
|
-
leftP.set(_leftP.x, _leftP.y);
|
|
2093
|
-
rightP.set(_rightP.x, _rightP.y);
|
|
2094
|
-
for (let i = 1; i < count; i++) {
|
|
2095
|
-
const left = leftDirection.clone().multiplyScalar(leftFragment * i), right = rightDirection.clone().multiplyScalar(rightFragment * i), p1 = leftP.clone().add(left), p2 = rightP.clone().add(right);
|
|
2096
|
-
this.addData(p1, p2);
|
|
2097
|
-
}
|
|
2098
|
-
}
|
|
2118
|
+
class DoorsAnalysis {
|
|
2119
|
+
// 所有可查找的点位
|
|
2120
|
+
possibleDoorPoints = [];
|
|
2121
|
+
doorPoint = [];
|
|
2122
|
+
dxf;
|
|
2123
|
+
// 包含所有点的虚拟网格
|
|
2099
2124
|
pointVirtualGrid = new PointVirtualGrid();
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2125
|
+
// 只包含可查找点的虚拟网格
|
|
2126
|
+
findPointVirtualGrid;
|
|
2127
|
+
quadtree;
|
|
2128
|
+
resultList;
|
|
2129
|
+
// 已过滤门的线段
|
|
2130
|
+
lineSegments;
|
|
2131
|
+
doorSearchNearAngle = 110;
|
|
2132
|
+
doorSearchDistance = 2;
|
|
2133
|
+
doors = [];
|
|
2134
|
+
lineAnalysis;
|
|
2135
|
+
continueFind = true;
|
|
2136
|
+
constructor(lineAnalysis) {
|
|
2137
|
+
this.lineAnalysis = lineAnalysis;
|
|
2138
|
+
this.dxf = lineAnalysis.Dxf;
|
|
2139
|
+
this.findPointVirtualGrid = new PointVirtualGrid();
|
|
2140
|
+
this.quadtree = lineAnalysis.quadtree;
|
|
2141
|
+
this.resultList = lineAnalysis.resultList;
|
|
2142
|
+
this.lineSegments = lineAnalysis.lineSegmentList;
|
|
2143
|
+
this.dxf.doorLineSegment.length = 0;
|
|
2144
|
+
this.lineSegments.forEach((line) => {
|
|
2145
|
+
this.pointVirtualGrid.insert(line.start, line);
|
|
2146
|
+
this.pointVirtualGrid.insert(line.end, line);
|
|
2147
|
+
});
|
|
2148
|
+
this.doorPoint = this.getDoorPoint();
|
|
2149
|
+
if (!this.continueFind) return;
|
|
2150
|
+
const excludeIndexMap = this.searchDoubleLinePoint();
|
|
2151
|
+
this.addPointsExcludeRule((line, _2, pointIndex) => {
|
|
2152
|
+
const index2 = this.lineSegments.indexOf(line);
|
|
2153
|
+
const excludeMode = excludeIndexMap.get(index2);
|
|
2154
|
+
if (typeof excludeMode === "number") {
|
|
2155
|
+
return excludeMode === -1 || excludeMode === pointIndex;
|
|
2156
|
+
}
|
|
2157
|
+
return false;
|
|
2158
|
+
});
|
|
2159
|
+
this.addPointsExcludeRule((_1, point) => {
|
|
2160
|
+
return !!this.doorPoint.find((p1) => p1.point.equal(point));
|
|
2161
|
+
});
|
|
2162
|
+
this.possibleDoorPoints = this.getPossiblePoints();
|
|
2163
|
+
this.possibleDoorPoints.forEach((p) => this.findPointVirtualGrid.insert(p.point, p.line));
|
|
2164
|
+
this.handle();
|
|
2165
|
+
}
|
|
2166
|
+
handle() {
|
|
2167
|
+
this.dxf.doorLineSegment.push(...this.search(this.doorPoint, this.possibleDoorPoints, 0.5));
|
|
2168
|
+
if (this.doorPoint.length < 2) this.dxf.doorLineSegment.push(...this.search(this.possibleDoorPoints, this.possibleDoorPoints, 0.6));
|
|
2169
|
+
}
|
|
2170
|
+
search(doorPoints, possibleDoorPoints = [], minDoorWidth = 0.6, doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
|
|
2171
|
+
const dxf = this.dxf;
|
|
2172
|
+
const doors = this.searchNearby(doorPoints, possibleDoorPoints, doorSearchDistance, doorSearchNearAngle);
|
|
2173
|
+
doors.push(
|
|
2174
|
+
...doorPoints.map((item) => {
|
|
2175
|
+
const res2 = this.searchAlongDirection(item, doorSearchDistance);
|
|
2176
|
+
if (res2) return {
|
|
2177
|
+
start: item.point,
|
|
2178
|
+
end: res2.point
|
|
2179
|
+
};
|
|
2180
|
+
const res3 = this.searchAlongNormalDirection(item, doorSearchDistance);
|
|
2181
|
+
if (res3) return {
|
|
2182
|
+
start: item.point,
|
|
2183
|
+
end: res3.point
|
|
2184
|
+
};
|
|
2185
|
+
}).filter((i) => !!i && i.start.distance(i.end) < doorSearchDistance)
|
|
2186
|
+
);
|
|
2187
|
+
const doorLineSegment = [];
|
|
2188
|
+
doors.forEach((p) => {
|
|
2189
|
+
const line = new LineSegment(p?.start, p?.end);
|
|
2190
|
+
const len = line.length();
|
|
2191
|
+
if (len < minDoorWidth) return;
|
|
2192
|
+
const normal = line.normal(), direction = line.direction(), step = (len - dxf.width * 2) / 2;
|
|
2193
|
+
for (let i = 0; i < 3; i++) {
|
|
2194
|
+
const point = line.start.clone().add(direction.clone().multiplyScalar(dxf.width + step * i));
|
|
2195
|
+
const rLine = new LineSegment(
|
|
2196
|
+
point,
|
|
2197
|
+
point.clone().add(normal.clone().multiplyScalar(1))
|
|
2198
|
+
);
|
|
2199
|
+
rLine.directionMove(normal, -0.5);
|
|
2200
|
+
const res = this.quadtree.queryLineSegment(rLine);
|
|
2201
|
+
if (res.length) return;
|
|
2202
|
+
}
|
|
2203
|
+
doorLineSegment.push(line);
|
|
2111
2204
|
});
|
|
2112
|
-
|
|
2205
|
+
return doorLineSegment;
|
|
2113
2206
|
}
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
* 构建线段四叉树,快速查找,
|
|
2207
|
+
/** 添加可查找点的过滤规则
|
|
2208
|
+
* @param rule
|
|
2117
2209
|
*/
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
const lineSegmentList = [];
|
|
2121
|
-
this.quadtree = new Quadtree(dxf.originalBox, 2);
|
|
2122
|
-
dxf.lineSegments.forEach((lineSegment) => {
|
|
2123
|
-
if (lineSegment.userData?.isDoor) return;
|
|
2124
|
-
this.quadtree?.insert({
|
|
2125
|
-
line: lineSegment,
|
|
2126
|
-
userData: lineSegmentList.length
|
|
2127
|
-
});
|
|
2128
|
-
lineSegmentList.push(lineSegment);
|
|
2129
|
-
});
|
|
2130
|
-
this.lineSegmentList = lineSegmentList;
|
|
2210
|
+
addPointsExcludeRule(rule) {
|
|
2211
|
+
this._pointsExcludeRule.push(rule);
|
|
2131
2212
|
}
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
* @description 判断两条线段距离是否较短且趋近平行,然后查找两条线段的重合部分的投影线,以此判断两根线是否需要合并
|
|
2136
|
-
* @param data
|
|
2213
|
+
_pointsExcludeRule = [];
|
|
2214
|
+
/**
|
|
2215
|
+
* 查找所有可能为门的点位
|
|
2137
2216
|
*/
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
this.
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
ids.forEach((id) => {
|
|
2147
|
-
try {
|
|
2148
|
-
if (visited.has(`${i}-${id}`) || visited.has(`${id}-${i}`)) return;
|
|
2149
|
-
const res = this.projectionAnalysis(id, i, sourceLineSegment, lineSegmentList);
|
|
2150
|
-
if (res) resultList.push(res);
|
|
2151
|
-
visited.add(`${i}-${id}`);
|
|
2152
|
-
} catch (error) {
|
|
2217
|
+
getPossiblePoints() {
|
|
2218
|
+
const doorPoints = [];
|
|
2219
|
+
this.lineSegments.forEach((line) => {
|
|
2220
|
+
line.points.forEach((p, j) => {
|
|
2221
|
+
for (let i = 0; i < this._pointsExcludeRule.length; i++) if (this._pointsExcludeRule[i](line, p, j)) return;
|
|
2222
|
+
const res = this.pointVirtualGrid.queryPoint(p).filter((d) => d.userData !== line);
|
|
2223
|
+
if (res.length === 0) {
|
|
2224
|
+
doorPoints.push({ line, point: p, uuid: uuid() });
|
|
2153
2225
|
}
|
|
2154
2226
|
});
|
|
2155
2227
|
});
|
|
2156
|
-
|
|
2157
|
-
resultList.forEach(this.createRectangle.bind(this));
|
|
2158
|
-
this.resultList = resultList;
|
|
2159
|
-
}
|
|
2160
|
-
/** 线段投影分析
|
|
2161
|
-
* @param index
|
|
2162
|
-
* @param sourceLineSegment
|
|
2163
|
-
* @param lineSegmentList
|
|
2164
|
-
* @returns
|
|
2165
|
-
*/
|
|
2166
|
-
projectionAnalysis(index2, sourceIndex, sourceLineSegment, lineSegmentList) {
|
|
2167
|
-
const temLineSegment = lineSegmentList[index2], direct = sourceLineSegment.direction(), temDirect = temLineSegment.direction(), angle = direct.angleBetween(temDirect) / (Math.PI / 180);
|
|
2168
|
-
if (angle < this.errorAngle || angle > 180 - this.errorAngle) {
|
|
2169
|
-
let data;
|
|
2170
|
-
const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment);
|
|
2171
|
-
if (p1.getLength() > p2.getLength()) {
|
|
2172
|
-
data = {
|
|
2173
|
-
target: temLineSegment,
|
|
2174
|
-
targetIndex: index2,
|
|
2175
|
-
source: sourceLineSegment,
|
|
2176
|
-
sourceIndex,
|
|
2177
|
-
project: p1,
|
|
2178
|
-
project2: p2
|
|
2179
|
-
};
|
|
2180
|
-
} else {
|
|
2181
|
-
data = {
|
|
2182
|
-
target: sourceLineSegment,
|
|
2183
|
-
targetIndex: sourceIndex,
|
|
2184
|
-
source: temLineSegment,
|
|
2185
|
-
sourceIndex: index2,
|
|
2186
|
-
project: p2,
|
|
2187
|
-
project2: p1
|
|
2188
|
-
};
|
|
2189
|
-
}
|
|
2190
|
-
if (!data || data.project.getLength() < 0.2 || data.project2.getLength() < 0.2) return;
|
|
2191
|
-
return data;
|
|
2192
|
-
}
|
|
2228
|
+
return doorPoints;
|
|
2193
2229
|
}
|
|
2194
|
-
doorSearchNearAngle = 110;
|
|
2195
|
-
doorSearchDistance = 2;
|
|
2196
|
-
doors = [];
|
|
2197
2230
|
/**
|
|
2198
|
-
*
|
|
2231
|
+
* 查找已知为门的点位
|
|
2199
2232
|
*/
|
|
2200
|
-
|
|
2201
|
-
this.
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
const
|
|
2205
|
-
const doorData = dxf.originalData[index2];
|
|
2233
|
+
getDoorPoint() {
|
|
2234
|
+
const doorPoints = [], dxf = this.dxf, pointVirtualGrid = this.pointVirtualGrid;
|
|
2235
|
+
dxf.doors.forEach((item) => {
|
|
2236
|
+
const doorLine = dxf.lineSegments[item[4]];
|
|
2237
|
+
const doorData = dxf.originalData[item[4]];
|
|
2206
2238
|
if (doorData.drawDoorData) {
|
|
2207
2239
|
const point = Point.from(doorData.drawDoorData.start);
|
|
2208
2240
|
const direct = Point.from(doorData.drawDoorData.n);
|
|
2209
2241
|
const resList = pointVirtualGrid.queryPoint(point).filter((res) => {
|
|
2210
|
-
if (res.userData
|
|
2211
|
-
const line =
|
|
2242
|
+
if (res.userData === doorLine) return false;
|
|
2243
|
+
const line = res.userData;
|
|
2212
2244
|
const direct2 = line.direction();
|
|
2213
2245
|
if (line.start.equal(point)) direct2.multiplyScalar(-1);
|
|
2214
2246
|
const angle = direct.angleBetween(direct2, "angle");
|
|
2215
2247
|
return angle > 80 || angle < 10;
|
|
2216
2248
|
});
|
|
2217
2249
|
if (resList.length) {
|
|
2218
|
-
const index22 = resList[0].userData?.index;
|
|
2219
2250
|
doorPoints.push({
|
|
2220
|
-
line:
|
|
2221
|
-
point
|
|
2222
|
-
|
|
2223
|
-
direct,
|
|
2224
|
-
sure: true
|
|
2251
|
+
line: resList[0].userData,
|
|
2252
|
+
point,
|
|
2253
|
+
uuid: uuid()
|
|
2225
2254
|
});
|
|
2226
|
-
return [point];
|
|
2227
2255
|
}
|
|
2256
|
+
} else if (doorData.doorDirectConnection) {
|
|
2257
|
+
this.continueFind = false;
|
|
2258
|
+
const line = new LineSegment(Point.from(doorData.start), Point.from(doorData.end));
|
|
2259
|
+
line.userData = {
|
|
2260
|
+
doorDirectConnection: true,
|
|
2261
|
+
isDoor: true
|
|
2262
|
+
};
|
|
2263
|
+
this.dxf.doorLineSegment.push(line);
|
|
2264
|
+
} else {
|
|
2265
|
+
console.warn(`门的线段顺序${item[4]} 没有drawDoorData属性`);
|
|
2228
2266
|
}
|
|
2229
|
-
return [];
|
|
2230
2267
|
});
|
|
2268
|
+
console.log("门点位数量:", doorPoints.length);
|
|
2269
|
+
return doorPoints;
|
|
2270
|
+
}
|
|
2271
|
+
/**
|
|
2272
|
+
* 查找双线墙的点位
|
|
2273
|
+
* @returns
|
|
2274
|
+
*/
|
|
2275
|
+
searchDoubleLinePoint() {
|
|
2231
2276
|
const excludeIndexMap = /* @__PURE__ */ new Map();
|
|
2232
2277
|
this.resultList.flatMap((p) => {
|
|
2233
|
-
const line0 = this.
|
|
2278
|
+
const line0 = this.lineSegments[p.sourceIndex], line1 = this.lineSegments[p.targetIndex], start0 = line1.projectPoint(line0.start), end0 = line1.projectPoint(line0.end), start1 = line0.projectPoint(line1.start), end1 = line0.projectPoint(line1.end), mode0 = start0 && end0 ? -1 : start0 ? 0 : end0 ? 1 : -1, mode1 = start1 && end1 ? -1 : start1 ? 0 : end1 ? 1 : -1;
|
|
2234
2279
|
if (excludeIndexMap.has(p.sourceIndex)) {
|
|
2235
2280
|
if (excludeIndexMap.get(p.sourceIndex) != mode0) excludeIndexMap.set(p.sourceIndex, -1);
|
|
2236
2281
|
} else excludeIndexMap.set(p.sourceIndex, mode0);
|
|
@@ -2238,57 +2283,42 @@ class LineAnalysis extends Component {
|
|
|
2238
2283
|
if (excludeIndexMap.get(p.targetIndex) != mode1) excludeIndexMap.set(p.targetIndex, -1);
|
|
2239
2284
|
} else excludeIndexMap.set(p.targetIndex, mode1);
|
|
2240
2285
|
});
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
line,
|
|
2255
|
-
point: p,
|
|
2256
|
-
index: i
|
|
2257
|
-
});
|
|
2258
|
-
}
|
|
2259
|
-
});
|
|
2260
|
-
});
|
|
2261
|
-
function searchNearby({ point, line, index: index2 }, doorIndex, record2) {
|
|
2286
|
+
return excludeIndexMap;
|
|
2287
|
+
}
|
|
2288
|
+
/** 查找方案一:最近点查找
|
|
2289
|
+
* @description 以点为圆心,查找半径内符合角度的点
|
|
2290
|
+
* @param doorPoints
|
|
2291
|
+
* @param possibleDoorPoints
|
|
2292
|
+
* @param doorSearchDistance 查找的距离(半径)
|
|
2293
|
+
* @param doorSearchNearAngle 查找的角度
|
|
2294
|
+
* @returns
|
|
2295
|
+
*/
|
|
2296
|
+
searchNearby(doorPoints, possibleDoorPoints = [], doorSearchDistance = this.doorSearchDistance, doorSearchNearAngle = this.doorSearchNearAngle) {
|
|
2297
|
+
const findPointVirtualGrid = this.findPointVirtualGrid, quadtree = this.quadtree;
|
|
2298
|
+
function find({ point, line }, doorIndex, record2) {
|
|
2262
2299
|
const direct = line.direction();
|
|
2263
2300
|
if (line.start === point) direct.multiplyScalar(-1);
|
|
2264
|
-
const res =
|
|
2265
|
-
(r) => (
|
|
2266
|
-
// 不能是自己
|
|
2267
|
-
r.userData?.index !== index2 && // 存在于可疑点位内,且不能是已知门的点位
|
|
2268
|
-
!!doorPoints.find((p) => !p.sure && p.point === r.point)
|
|
2269
|
-
)
|
|
2270
|
-
).sort((a, b) => a.point.distance(point) - b.point.distance(point));
|
|
2301
|
+
const res = findPointVirtualGrid.queryCircle(point, doorSearchDistance).filter((r) => r.userData !== line).sort((a, b) => a.point.distance(point) - b.point.distance(point));
|
|
2271
2302
|
const list = [];
|
|
2272
2303
|
for (let i = 0; i < res.length; i++) {
|
|
2273
|
-
const doorIndex2 =
|
|
2274
|
-
|
|
2275
|
-
record2.
|
|
2276
|
-
record2.add(`${
|
|
2304
|
+
const doorIndex2 = possibleDoorPoints.findIndex((p) => p.point === res[i].point);
|
|
2305
|
+
const id1 = doorPoints[doorIndex].uuid, id2 = possibleDoorPoints[doorIndex2].uuid;
|
|
2306
|
+
if (record2.has(`${id1}.${id2}`)) continue;
|
|
2307
|
+
record2.add(`${id1}.${id2}`);
|
|
2308
|
+
record2.add(`${id2}.${id1}`);
|
|
2277
2309
|
const targetPoint = res[i].point, line2 = new LineSegment(point.clone(), targetPoint.clone()), angle = line2.direction().angleBetween(direct, "angle");
|
|
2278
2310
|
if (angle < doorSearchNearAngle) {
|
|
2279
2311
|
const direct2 = doorPoints[doorIndex2].line.direction();
|
|
2280
|
-
const line22 =
|
|
2312
|
+
const line22 = res[i].userData;
|
|
2281
2313
|
if (line22.start.equal(res[i].point)) direct2.multiplyScalar(-1);
|
|
2282
2314
|
const angle2 = line2.direction().multiplyScalar(-1).angleBetween(direct2, "angle");
|
|
2283
2315
|
if (angle2 < doorSearchNearAngle) {
|
|
2284
2316
|
if (!quadtree.queryLineSegment(line2).length) {
|
|
2285
2317
|
list.push({
|
|
2286
2318
|
findData: res[i],
|
|
2287
|
-
|
|
2288
|
-
findAngle: angle2,
|
|
2289
|
-
doorAngle: angle,
|
|
2319
|
+
findUuid: id2,
|
|
2290
2320
|
doorLine: line2,
|
|
2291
|
-
|
|
2321
|
+
doorUuid: id1
|
|
2292
2322
|
});
|
|
2293
2323
|
}
|
|
2294
2324
|
}
|
|
@@ -2296,65 +2326,15 @@ class LineAnalysis extends Component {
|
|
|
2296
2326
|
}
|
|
2297
2327
|
return list;
|
|
2298
2328
|
}
|
|
2299
|
-
function
|
|
2300
|
-
|
|
2301
|
-
if (line.start === point) direct.multiplyScalar(-1);
|
|
2302
|
-
const endPoint = point.clone().add(direct.clone().multiplyScalar(doorSearchDistance)), rline = new LineSegment(point.clone(), endPoint), result = quadtree.queryLineSegment(rline).map((l) => {
|
|
2303
|
-
const res = l.line.getIntersection(rline);
|
|
2304
|
-
return {
|
|
2305
|
-
point: res,
|
|
2306
|
-
line: l.line
|
|
2307
|
-
};
|
|
2308
|
-
}).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
|
|
2309
|
-
if (result.length) {
|
|
2310
|
-
const item = result[0];
|
|
2311
|
-
if (Math.abs(90 - item.line.direction().angleBetween(direct, "angle")) < 5) {
|
|
2312
|
-
return item;
|
|
2313
|
-
}
|
|
2314
|
-
}
|
|
2315
|
-
}
|
|
2316
|
-
function searchAlongNormalDirection({ point, line, index: index2 }) {
|
|
2317
|
-
const direct = line.direction();
|
|
2318
|
-
if (line.start === point) direct.multiplyScalar(-1);
|
|
2319
|
-
const normal = line.start.normal(line.end);
|
|
2320
|
-
const prePoint = line.start.clone();
|
|
2321
|
-
if (line.start === point) prePoint.copy(line.end);
|
|
2322
|
-
const result = pointVirtualGrid.queryPoint(prePoint).filter((r) => r.userData?.index !== index2);
|
|
2323
|
-
for (let i = 0; i < result.length; i++) {
|
|
2324
|
-
const element = result[i];
|
|
2325
|
-
const l = dxf.lineSegments[element.userData?.index ?? 0];
|
|
2326
|
-
const d1 = l.direction();
|
|
2327
|
-
if (l.start === element.point) direct.multiplyScalar(-1);
|
|
2328
|
-
const angle = d1.angleBetween(normal) / (Math.PI / 180);
|
|
2329
|
-
if (angle > 90) {
|
|
2330
|
-
normal.multiplyScalar(-1);
|
|
2331
|
-
break;
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
const rline3 = new LineSegment(point.clone(), point.clone().add(normal.multiplyScalar(doorSearchDistance)));
|
|
2335
|
-
const r3 = quadtree.queryLineSegment(rline3).map((l) => {
|
|
2336
|
-
const res = l.line.getIntersection(rline3);
|
|
2337
|
-
return {
|
|
2338
|
-
point: res,
|
|
2339
|
-
line: l.line
|
|
2340
|
-
};
|
|
2341
|
-
}).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
|
|
2342
|
-
if (r3.length) {
|
|
2343
|
-
const item = r3[0];
|
|
2344
|
-
if (Math.abs(90 - item.line.direction().angleBetween(normal, "angle")) < 5) {
|
|
2345
|
-
return item;
|
|
2346
|
-
}
|
|
2347
|
-
}
|
|
2348
|
-
}
|
|
2349
|
-
function deepSearchNearHandle(index2, snFindRecord2, list, record2, other) {
|
|
2350
|
-
record2.add(`${index2}`);
|
|
2329
|
+
function deepSearchNearHandle(uuid2, snFindRecord2, list, record2, other) {
|
|
2330
|
+
record2.add(uuid2);
|
|
2351
2331
|
const newList = [];
|
|
2352
2332
|
if (other) newList.push(other);
|
|
2353
2333
|
for (let i = 0; i < list.length; i++) {
|
|
2354
2334
|
const item = list[i];
|
|
2355
|
-
if (snFindRecord2.has(item.
|
|
2356
|
-
const list2 = snFindRecord2.get(item.
|
|
2357
|
-
if (deepSearchNearHandle(item.
|
|
2335
|
+
if (snFindRecord2.has(item.findUuid)) {
|
|
2336
|
+
const list2 = snFindRecord2.get(item.findUuid);
|
|
2337
|
+
if (deepSearchNearHandle(item.findUuid, snFindRecord2, list2, record2, item)) newList.push(item);
|
|
2358
2338
|
} else newList.push(item);
|
|
2359
2339
|
}
|
|
2360
2340
|
newList.sort((a, b) => a.doorLine.length() - b.doorLine.length());
|
|
@@ -2368,22 +2348,21 @@ class LineAnalysis extends Component {
|
|
|
2368
2348
|
const record = /* @__PURE__ */ new Set();
|
|
2369
2349
|
const snFindRecord = /* @__PURE__ */ new Map();
|
|
2370
2350
|
doorPoints.map((p, index2) => {
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
if (list.length) snFindRecord.set(index2, list);
|
|
2351
|
+
const list = find(p, index2, record);
|
|
2352
|
+
if (list.length) snFindRecord.set(p.uuid, list);
|
|
2374
2353
|
});
|
|
2375
2354
|
record.clear();
|
|
2376
2355
|
const temMap = /* @__PURE__ */ new Map();
|
|
2377
2356
|
snFindRecord.forEach((list, key) => {
|
|
2378
|
-
if (!record.has(
|
|
2357
|
+
if (!record.has(key) && list.length) {
|
|
2379
2358
|
deepSearchNearHandle(key, snFindRecord, list, record);
|
|
2380
2359
|
}
|
|
2381
2360
|
if (list.length) {
|
|
2382
2361
|
const item = list[0];
|
|
2383
|
-
if (!temMap.has(item.
|
|
2384
|
-
temMap.get(item.
|
|
2385
|
-
if (!temMap.has(item.
|
|
2386
|
-
temMap.get(item.
|
|
2362
|
+
if (!temMap.has(item.doorUuid)) temMap.set(item.doorUuid, []);
|
|
2363
|
+
temMap.get(item.doorUuid)?.push(item);
|
|
2364
|
+
if (!temMap.has(item.findUuid)) temMap.set(item.findUuid, []);
|
|
2365
|
+
temMap.get(item.findUuid)?.push(item);
|
|
2387
2366
|
}
|
|
2388
2367
|
});
|
|
2389
2368
|
const deleteSet = /* @__PURE__ */ new Set();
|
|
@@ -2393,38 +2372,24 @@ class LineAnalysis extends Component {
|
|
|
2393
2372
|
for (let i = 1; i < list.length; i++) deleteSet.add(list[i]);
|
|
2394
2373
|
}
|
|
2395
2374
|
});
|
|
2396
|
-
const searchNearRasult = [],
|
|
2375
|
+
const searchNearRasult = [], removeDoorPointsUuid = [];
|
|
2397
2376
|
snFindRecord.forEach((list) => {
|
|
2398
2377
|
if (list.length) {
|
|
2399
2378
|
const item = list[0];
|
|
2400
2379
|
if (!deleteSet.has(item)) {
|
|
2401
2380
|
searchNearRasult.push(item);
|
|
2402
|
-
|
|
2381
|
+
removeDoorPointsUuid.push(item.doorUuid, item.findUuid);
|
|
2403
2382
|
}
|
|
2404
2383
|
}
|
|
2405
2384
|
});
|
|
2406
|
-
const
|
|
2407
|
-
if (removeDoorPointsIndex.includes(index2)) return;
|
|
2408
|
-
if (dxf.doors.length >= 2 && !item.sure) return;
|
|
2409
|
-
const res2 = searchAlongDirection(item);
|
|
2410
|
-
if (res2) return {
|
|
2411
|
-
start: item.point,
|
|
2412
|
-
end: res2.point,
|
|
2413
|
-
index: item.index
|
|
2414
|
-
};
|
|
2415
|
-
const res3 = searchAlongNormalDirection(item);
|
|
2416
|
-
if (res3) return {
|
|
2417
|
-
start: item.point,
|
|
2418
|
-
end: res3.point,
|
|
2419
|
-
index: item.index
|
|
2420
|
-
};
|
|
2421
|
-
}).filter((i) => !!i && i.start.distance(i.end) < doorSearchDistance);
|
|
2422
|
-
doors.push(...doors_);
|
|
2385
|
+
const doors = [];
|
|
2423
2386
|
searchNearRasult.forEach((item) => {
|
|
2424
|
-
const
|
|
2425
|
-
const
|
|
2426
|
-
const
|
|
2427
|
-
const
|
|
2387
|
+
const doorIndex = doorPoints.findIndex((p2) => p2.uuid === item.doorUuid);
|
|
2388
|
+
const findDoorIndex = possibleDoorPoints.findIndex((p2) => p2.uuid === item.findUuid);
|
|
2389
|
+
const start = doorPoints[doorIndex].point.clone();
|
|
2390
|
+
const end = possibleDoorPoints[findDoorIndex].point.clone();
|
|
2391
|
+
const startLine = this.findLongLineSegment(doorPoints[doorIndex].line);
|
|
2392
|
+
const endLine = this.findLongLineSegment(possibleDoorPoints[findDoorIndex].line);
|
|
2428
2393
|
const p = startLine.projectPoint(end);
|
|
2429
2394
|
if (p) {
|
|
2430
2395
|
start.copy(p);
|
|
@@ -2433,8 +2398,7 @@ class LineAnalysis extends Component {
|
|
|
2433
2398
|
if (angle < 10 || angle > 170 || Math.abs(90 - angle) < 10) {
|
|
2434
2399
|
doors.push({
|
|
2435
2400
|
start,
|
|
2436
|
-
end
|
|
2437
|
-
index: doorPoints[item.doorIndex].index
|
|
2401
|
+
end
|
|
2438
2402
|
});
|
|
2439
2403
|
}
|
|
2440
2404
|
} else {
|
|
@@ -2445,30 +2409,82 @@ class LineAnalysis extends Component {
|
|
|
2445
2409
|
if (angle < 10 || angle > 170 || Math.abs(90 - angle) < 10) {
|
|
2446
2410
|
doors.push({
|
|
2447
2411
|
start,
|
|
2448
|
-
end
|
|
2449
|
-
index: doorPoints[item.doorIndex].index
|
|
2412
|
+
end
|
|
2450
2413
|
});
|
|
2451
2414
|
}
|
|
2452
2415
|
}
|
|
2453
2416
|
});
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2417
|
+
possibleDoorPoints.splice(
|
|
2418
|
+
0,
|
|
2419
|
+
possibleDoorPoints.length,
|
|
2420
|
+
...possibleDoorPoints.filter((p) => removeDoorPointsUuid.indexOf(p.uuid) === -1)
|
|
2421
|
+
);
|
|
2422
|
+
doorPoints.splice(
|
|
2423
|
+
0,
|
|
2424
|
+
doorPoints.length,
|
|
2425
|
+
...doorPoints.filter((p) => removeDoorPointsUuid.indexOf(p.uuid) === -1)
|
|
2426
|
+
);
|
|
2427
|
+
return doors;
|
|
2428
|
+
}
|
|
2429
|
+
/** 方案二: 沿方向查找
|
|
2430
|
+
* @description
|
|
2431
|
+
* @param param0
|
|
2432
|
+
* @returns
|
|
2433
|
+
*/
|
|
2434
|
+
searchAlongDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
|
|
2435
|
+
const quadtree = this.quadtree;
|
|
2436
|
+
const direct = line.direction();
|
|
2437
|
+
if (line.start === point) direct.multiplyScalar(-1);
|
|
2438
|
+
const endPoint = point.clone().add(direct.clone().multiplyScalar(doorSearchDistance)), rline = new LineSegment(point.clone(), endPoint), result = quadtree.queryLineSegment(rline).map((l) => {
|
|
2439
|
+
const res = l.line.getIntersection(rline);
|
|
2440
|
+
return {
|
|
2441
|
+
point: res,
|
|
2442
|
+
line: l.line
|
|
2443
|
+
};
|
|
2444
|
+
}).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
|
|
2445
|
+
if (result.length) {
|
|
2446
|
+
const item = result[0];
|
|
2447
|
+
if (Math.abs(90 - item.line.direction().angleBetween(direct, "angle")) < 5) {
|
|
2448
|
+
return item;
|
|
2469
2449
|
}
|
|
2470
|
-
|
|
2471
|
-
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
/** 方案三: 沿法线方向查找
|
|
2453
|
+
* @description
|
|
2454
|
+
* @param param0
|
|
2455
|
+
* @param doorSearchDistance
|
|
2456
|
+
* @returns
|
|
2457
|
+
*/
|
|
2458
|
+
searchAlongNormalDirection({ point, line }, doorSearchDistance = this.doorSearchDistance) {
|
|
2459
|
+
const pointVirtualGrid = this.pointVirtualGrid, quadtree = this.quadtree, direct = line.direction(), normal = line.start.normal(line.end), prePoint = line.start.clone();
|
|
2460
|
+
if (line.start === point) direct.multiplyScalar(-1);
|
|
2461
|
+
if (line.start === point) prePoint.copy(line.end);
|
|
2462
|
+
const result = pointVirtualGrid.queryPoint(prePoint).filter((r) => r.userData !== line);
|
|
2463
|
+
for (let i = 0; i < result.length; i++) {
|
|
2464
|
+
const element = result[i];
|
|
2465
|
+
const l = element.userData;
|
|
2466
|
+
const d1 = l.direction();
|
|
2467
|
+
if (l.start === element.point) direct.multiplyScalar(-1);
|
|
2468
|
+
const angle = d1.angleBetween(normal) / (Math.PI / 180);
|
|
2469
|
+
if (angle > 90) {
|
|
2470
|
+
normal.multiplyScalar(-1);
|
|
2471
|
+
break;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
const rline3 = new LineSegment(point.clone(), point.clone().add(normal.multiplyScalar(doorSearchDistance)));
|
|
2475
|
+
const r3 = quadtree.queryLineSegment(rline3).map((l) => {
|
|
2476
|
+
const res = l.line.getIntersection(rline3);
|
|
2477
|
+
return {
|
|
2478
|
+
point: res,
|
|
2479
|
+
line: l.line
|
|
2480
|
+
};
|
|
2481
|
+
}).filter((i) => i.point).sort((a, b) => point.distance(a.point) - point.distance(b.point));
|
|
2482
|
+
if (r3.length) {
|
|
2483
|
+
const item = r3[0];
|
|
2484
|
+
if (Math.abs(90 - item.line.direction().angleBetween(normal, "angle")) < 5) {
|
|
2485
|
+
return item;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2472
2488
|
}
|
|
2473
2489
|
/**
|
|
2474
2490
|
*
|
|
@@ -2476,13 +2492,11 @@ class LineAnalysis extends Component {
|
|
|
2476
2492
|
* @returns
|
|
2477
2493
|
*/
|
|
2478
2494
|
findLongLineSegment(line) {
|
|
2479
|
-
const dxf = this.Dxf;
|
|
2480
2495
|
const resLine = line.clone();
|
|
2481
2496
|
const res1 = this.pointVirtualGrid.queryPoint(line.start);
|
|
2482
2497
|
const res2 = this.pointVirtualGrid.queryPoint(line.end);
|
|
2483
2498
|
for (let i = 0; i < res1.length; i++) {
|
|
2484
|
-
const { userData } = res1[i];
|
|
2485
|
-
const line2 = dxf.lineSegments[userData?.index];
|
|
2499
|
+
const { userData: line2 } = res1[i];
|
|
2486
2500
|
if (line2 === line) continue;
|
|
2487
2501
|
if (line2 && line2.directionEqual(line)) {
|
|
2488
2502
|
if (line2.start.equal(line.start)) resLine.start.copy(line2.end);
|
|
@@ -2491,8 +2505,7 @@ class LineAnalysis extends Component {
|
|
|
2491
2505
|
}
|
|
2492
2506
|
}
|
|
2493
2507
|
for (let i = 0; i < res2.length; i++) {
|
|
2494
|
-
const { userData } = res2[i];
|
|
2495
|
-
const line2 = dxf.lineSegments[userData?.index];
|
|
2508
|
+
const { userData: line2 } = res2[i];
|
|
2496
2509
|
if (line2 === line) continue;
|
|
2497
2510
|
if (line2 && line2.directionEqual(line)) {
|
|
2498
2511
|
if (line2.end.equal(line.end)) resLine.end.copy(line2.start);
|
|
@@ -2502,144 +2515,169 @@ class LineAnalysis extends Component {
|
|
|
2502
2515
|
}
|
|
2503
2516
|
return resLine;
|
|
2504
2517
|
}
|
|
2505
|
-
doorsAnalysis2() {
|
|
2506
|
-
const renderer = this.parent?.findComponentByName("Renderer");
|
|
2507
|
-
const dxf = this.Dxf, pointVirtualGrid = this.pointVirtualGrid, quadtree = this.quadtree;
|
|
2508
|
-
this.doorSearchNearAngle;
|
|
2509
|
-
this.doorSearchDistance;
|
|
2510
|
-
const doorsAnalysis = new DoorsAnalysis(dxf, pointVirtualGrid, quadtree, this.resultList, this.lineSegmentList);
|
|
2511
|
-
const possiblePoints = doorsAnalysis.searchPossiblePoints();
|
|
2512
|
-
possiblePoints.forEach((l) => {
|
|
2513
|
-
renderer.createPointMesh(l.point).position.z = dxf.originalZAverage;
|
|
2514
|
-
});
|
|
2515
|
-
}
|
|
2516
2518
|
}
|
|
2517
|
-
class
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
this.
|
|
2532
|
-
this.
|
|
2533
|
-
this.
|
|
2534
|
-
this.
|
|
2535
|
-
this.lineSegments = lineSegments;
|
|
2536
|
-
this.addPointsExcludeRule((line) => line.userData.isDoor);
|
|
2537
|
-
const excludeIndexMap = this.searchDoubleLinePoint();
|
|
2538
|
-
this.addPointsExcludeRule((_1, _2, index2, pointIndex) => {
|
|
2539
|
-
const excludeMode = excludeIndexMap.get(index2);
|
|
2540
|
-
if (typeof excludeMode === "number") {
|
|
2541
|
-
return excludeMode === -1 || excludeMode === pointIndex;
|
|
2542
|
-
}
|
|
2543
|
-
return false;
|
|
2544
|
-
});
|
|
2545
|
-
this.doorPoint = this.searchDoorPoint();
|
|
2546
|
-
this.addPointsExcludeRule((_1, point) => {
|
|
2547
|
-
return !!this.doorPoint.find((p1) => p1.point.equal(point));
|
|
2548
|
-
});
|
|
2549
|
-
this.possibleDoorPoints = this.searchPossiblePoints();
|
|
2550
|
-
if (dxf.doors.length < 2) ;
|
|
2519
|
+
class LineAnalysis extends Component {
|
|
2520
|
+
static name = "LineAnalysis";
|
|
2521
|
+
Dxf = null;
|
|
2522
|
+
Variable = null;
|
|
2523
|
+
lineSegmentList = [];
|
|
2524
|
+
container = new THREE.Group();
|
|
2525
|
+
// 误差角度
|
|
2526
|
+
errorAngle = 4;
|
|
2527
|
+
width = 0.4;
|
|
2528
|
+
/**
|
|
2529
|
+
*
|
|
2530
|
+
* @param parent
|
|
2531
|
+
*/
|
|
2532
|
+
onAddFromParent(parent) {
|
|
2533
|
+
this.Dxf = parent.findComponentByType(Dxf);
|
|
2534
|
+
this.Variable = this.parent?.findComponentByType(Variable);
|
|
2535
|
+
this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this));
|
|
2536
|
+
this.Dxf.addEventListener("createGroup", this.doorsAnalysis.bind(this));
|
|
2551
2537
|
}
|
|
2552
2538
|
/**
|
|
2553
2539
|
*
|
|
2554
|
-
* @param
|
|
2540
|
+
* @param p1
|
|
2541
|
+
* @param p2
|
|
2542
|
+
* @param width
|
|
2543
|
+
* @returns
|
|
2555
2544
|
*/
|
|
2556
|
-
|
|
2557
|
-
|
|
2545
|
+
expandLineSegment(p1, p2, width = 0.1) {
|
|
2546
|
+
const normal = p2.normal(p1);
|
|
2547
|
+
const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
|
|
2548
|
+
const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
|
|
2549
|
+
const offsetX = normal.x * width * 0.5;
|
|
2550
|
+
const offsetY = normal.y * width * 0.5;
|
|
2551
|
+
return {
|
|
2552
|
+
points: [
|
|
2553
|
+
// 第一条线
|
|
2554
|
+
new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
|
|
2555
|
+
new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
|
|
2556
|
+
// 第二条线
|
|
2557
|
+
new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
|
|
2558
|
+
new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
|
|
2559
|
+
],
|
|
2560
|
+
indices: [0, 1, 1, 3, 3, 2, 2, 0],
|
|
2561
|
+
rectIndices: [0, 1, 3, 2, 0]
|
|
2562
|
+
};
|
|
2558
2563
|
}
|
|
2559
|
-
|
|
2564
|
+
appendLineSegmentList = [];
|
|
2560
2565
|
/**
|
|
2561
|
-
*
|
|
2566
|
+
* 追加数据
|
|
2567
|
+
* @param p1
|
|
2568
|
+
* @param p2
|
|
2562
2569
|
*/
|
|
2563
|
-
|
|
2564
|
-
const dxf = this.
|
|
2565
|
-
dxf.
|
|
2566
|
-
|
|
2567
|
-
for (let i2 = 0; i2 < this._pointsExcludeRule.length; i2++)
|
|
2568
|
-
if (this._pointsExcludeRule[i2](line, p, i2, j)) return;
|
|
2569
|
-
const res = this.pointVirtualGrid.queryPoint(p).filter((d) => d.userData?.index !== i);
|
|
2570
|
-
if (res.length === 0) {
|
|
2571
|
-
doorPoints.push({
|
|
2572
|
-
line,
|
|
2573
|
-
point: p,
|
|
2574
|
-
index: i
|
|
2575
|
-
});
|
|
2576
|
-
}
|
|
2577
|
-
});
|
|
2578
|
-
});
|
|
2579
|
-
return doorPoints;
|
|
2570
|
+
addData(p1, p2) {
|
|
2571
|
+
const dxf = this.Dxf;
|
|
2572
|
+
dxf.data.push([p1.clone(), p2.clone(), [], false, dxf.data.length]);
|
|
2573
|
+
this.appendLineSegmentList.push(new LineSegment(p1.clone(), p2.clone()));
|
|
2580
2574
|
}
|
|
2575
|
+
/** 结果分析创建矩形
|
|
2576
|
+
* @param result
|
|
2577
|
+
*/
|
|
2578
|
+
createRectangle(result) {
|
|
2579
|
+
const dxf = this.Dxf;
|
|
2580
|
+
const project0 = result.project, project1 = result.project2;
|
|
2581
|
+
if (project0.includedAngle(project1) > 135) {
|
|
2582
|
+
project1.points = [project1.points[1], project1.points[0]];
|
|
2583
|
+
}
|
|
2584
|
+
this.addData(project0.points[0], project1.points[0]);
|
|
2585
|
+
this.addData(project0.points[1], project1.points[1]);
|
|
2586
|
+
const leftHeight = project0.points[0].distance(project1.points[0]), rightHeight = project0.points[1].distance(project1.points[1]), count = Math.ceil(Math.max(leftHeight, rightHeight) / dxf.width), leftFragment = leftHeight / count, rightFragment = rightHeight / count, leftDirection = project1.points[0].direction(project0.points[0]), rightDirection = project1.points[1].direction(project0.points[1]), leftP = project0.points[0].clone(), rightP = project0.points[1].clone(), direction = rightP.direction(leftP);
|
|
2587
|
+
direction.multiplyScalar(dxf.width * 0.5);
|
|
2588
|
+
const _leftP = leftP.clone().add(direction), _rightP = rightP.clone().add(direction.multiplyScalar(-1)), d1 = leftP.direction(rightP), d2 = _leftP.direction(_rightP);
|
|
2589
|
+
if (d1.x > 0 && d2.x < 0 || d1.x < 0 && d2.x > 0 || d1.y > 0 && d2.y < 0 || d1.y < 0 && d2.y > 0) return;
|
|
2590
|
+
leftP.set(_leftP.x, _leftP.y);
|
|
2591
|
+
rightP.set(_rightP.x, _rightP.y);
|
|
2592
|
+
for (let i = 1; i < count; i++) {
|
|
2593
|
+
const left = leftDirection.clone().multiplyScalar(leftFragment * i), right = rightDirection.clone().multiplyScalar(rightFragment * i), p1 = leftP.clone().add(left), p2 = rightP.clone().add(right);
|
|
2594
|
+
this.addData(p1, p2);
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
quadtree;
|
|
2581
2598
|
/**
|
|
2582
|
-
*
|
|
2599
|
+
* 构建线段四叉树,快速查找,
|
|
2583
2600
|
*/
|
|
2584
|
-
|
|
2585
|
-
const
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
if (
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
const direct2 = line.direction();
|
|
2596
|
-
if (line.start.equal(point)) direct2.multiplyScalar(-1);
|
|
2597
|
-
const angle = direct.angleBetween(direct2, "angle");
|
|
2598
|
-
return angle > 80 || angle < 10;
|
|
2599
|
-
});
|
|
2600
|
-
if (resList.length) {
|
|
2601
|
-
const index22 = resList[0].userData?.index;
|
|
2602
|
-
doorPoints.push({
|
|
2603
|
-
line: dxf.lineSegments[index22],
|
|
2604
|
-
point: Point.from(doorData.drawDoorData.start),
|
|
2605
|
-
index: index22,
|
|
2606
|
-
direct,
|
|
2607
|
-
sure: true
|
|
2608
|
-
});
|
|
2609
|
-
}
|
|
2610
|
-
}
|
|
2601
|
+
buildQuadtree() {
|
|
2602
|
+
const dxf = this.Dxf;
|
|
2603
|
+
const lineSegmentList = [];
|
|
2604
|
+
this.quadtree = new Quadtree(dxf.originalBox, 2);
|
|
2605
|
+
dxf.lineSegments.forEach((lineSegment) => {
|
|
2606
|
+
if (lineSegment.userData?.isDoor) return;
|
|
2607
|
+
this.quadtree?.insert({
|
|
2608
|
+
line: lineSegment,
|
|
2609
|
+
userData: lineSegmentList.length
|
|
2610
|
+
});
|
|
2611
|
+
lineSegmentList.push(lineSegment);
|
|
2611
2612
|
});
|
|
2612
|
-
|
|
2613
|
+
this.lineSegmentList = lineSegmentList;
|
|
2613
2614
|
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2615
|
+
resultList = [];
|
|
2616
|
+
mergeWallLines = [];
|
|
2617
|
+
/** 线段分析
|
|
2618
|
+
* @description 判断两条线段距离是否较短且趋近平行,然后查找两条线段的重合部分的投影线,以此判断两根线是否需要合并
|
|
2619
|
+
* @param data
|
|
2617
2620
|
*/
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
this.
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2621
|
+
lineAnalysis() {
|
|
2622
|
+
this.buildQuadtree();
|
|
2623
|
+
const quadtree = this.quadtree;
|
|
2624
|
+
const lineSegmentList = this.lineSegmentList;
|
|
2625
|
+
const visited = /* @__PURE__ */ new Set(), resultList = [];
|
|
2626
|
+
lineSegmentList.forEach((_0, i) => {
|
|
2627
|
+
const sourceLineSegment = lineSegmentList[i], rectangle = Rectangle.fromByLineSegment(sourceLineSegment, this.width * 2, false, -0.01), ids = quadtree.queryRect(rectangle).map((i2) => i2.userData).filter((index2) => index2 !== i);
|
|
2628
|
+
ids.forEach((id) => {
|
|
2629
|
+
try {
|
|
2630
|
+
if (visited.has(`${i}-${id}`) || visited.has(`${id}-${i}`)) return;
|
|
2631
|
+
const res = this.projectionAnalysis(id, i, sourceLineSegment, lineSegmentList);
|
|
2632
|
+
if (res) resultList.push(res);
|
|
2633
|
+
visited.add(`${i}-${id}`);
|
|
2634
|
+
} catch (error) {
|
|
2635
|
+
}
|
|
2636
|
+
});
|
|
2628
2637
|
});
|
|
2629
|
-
|
|
2638
|
+
this.appendLineSegmentList.length = 0;
|
|
2639
|
+
resultList.forEach(this.createRectangle.bind(this));
|
|
2640
|
+
this.resultList = resultList;
|
|
2630
2641
|
}
|
|
2631
|
-
/**
|
|
2632
|
-
* @
|
|
2633
|
-
* @param
|
|
2634
|
-
* @param
|
|
2635
|
-
* @param record
|
|
2642
|
+
/** 线段投影分析
|
|
2643
|
+
* @param index
|
|
2644
|
+
* @param sourceLineSegment
|
|
2645
|
+
* @param lineSegmentList
|
|
2636
2646
|
* @returns
|
|
2637
2647
|
*/
|
|
2638
|
-
|
|
2639
|
-
const
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2648
|
+
projectionAnalysis(index2, sourceIndex, sourceLineSegment, lineSegmentList) {
|
|
2649
|
+
const temLineSegment = lineSegmentList[index2], direct = sourceLineSegment.direction(), temDirect = temLineSegment.direction(), angle = direct.angleBetween(temDirect) / (Math.PI / 180);
|
|
2650
|
+
if (angle < this.errorAngle || angle > 180 - this.errorAngle) {
|
|
2651
|
+
let data;
|
|
2652
|
+
const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment);
|
|
2653
|
+
if (p1.getLength() > p2.getLength()) {
|
|
2654
|
+
data = {
|
|
2655
|
+
target: temLineSegment,
|
|
2656
|
+
targetIndex: index2,
|
|
2657
|
+
source: sourceLineSegment,
|
|
2658
|
+
sourceIndex,
|
|
2659
|
+
project: p1,
|
|
2660
|
+
project2: p2
|
|
2661
|
+
};
|
|
2662
|
+
} else {
|
|
2663
|
+
data = {
|
|
2664
|
+
target: sourceLineSegment,
|
|
2665
|
+
targetIndex: sourceIndex,
|
|
2666
|
+
source: temLineSegment,
|
|
2667
|
+
sourceIndex: index2,
|
|
2668
|
+
project: p2,
|
|
2669
|
+
project2: p1
|
|
2670
|
+
};
|
|
2671
|
+
}
|
|
2672
|
+
if (!data || data.project.getLength() < 0.2 || data.project2.getLength() < 0.2) return;
|
|
2673
|
+
return data;
|
|
2674
|
+
}
|
|
2675
|
+
}
|
|
2676
|
+
doorSearchNearAngle = 110;
|
|
2677
|
+
doorSearchDistance = 2;
|
|
2678
|
+
doors = [];
|
|
2679
|
+
doorsAnalysis() {
|
|
2680
|
+
new DoorsAnalysis(this);
|
|
2643
2681
|
}
|
|
2644
2682
|
}
|
|
2645
2683
|
class DxfSystem extends ComponentManager {
|
|
@@ -2992,38 +3030,84 @@ class DxfLineModel extends Component {
|
|
|
2992
3030
|
updateMode() {
|
|
2993
3031
|
const dxf = this.parent?.findComponentByName("Dxf");
|
|
2994
3032
|
this.dxfLineModel.clear();
|
|
2995
|
-
const dxfArray = dxf.to3DArray(1 / dxf.scale);
|
|
3033
|
+
const dxfArray = dxf.to3DArray(1 / dxf.scale, 0);
|
|
2996
3034
|
this.dxfLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(dxfArray, 3, true));
|
|
2997
3035
|
const doorsArray = new Float32Array(
|
|
2998
|
-
dxf.doorLineSegment.flatMap(({ start, end }) => [start.x, start.y,
|
|
3036
|
+
dxf.doorLineSegment.flatMap(({ start, end }) => [start.x, start.y, 0, end.x, end.y, 0])
|
|
2999
3037
|
).map((n) => n / dxf.scale);
|
|
3000
3038
|
const doorsColorArray = new Float32Array(dxf.doorLineSegment.flatMap(() => [1, 0, 0, 0, 1, 0]));
|
|
3001
3039
|
this.dxfDoorsLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(doorsArray, 3, true)).setAttribute("color", new THREE.BufferAttribute(doorsColorArray, 3));
|
|
3040
|
+
this.dxfModelGroup.position.z = dxf.originalZAverage;
|
|
3041
|
+
this.dispatchEvent({
|
|
3042
|
+
type: "modelUpdate",
|
|
3043
|
+
model: this.dxfModelGroup
|
|
3044
|
+
});
|
|
3002
3045
|
}
|
|
3003
3046
|
}
|
|
3004
|
-
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3047
|
+
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3005
3048
|
__proto__: null,
|
|
3006
3049
|
DetailsPoint,
|
|
3007
3050
|
DxfLineModel,
|
|
3008
3051
|
WhiteModel
|
|
3009
3052
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
3010
|
-
function
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3053
|
+
function ModelDataPlugin_(dxfSystem, option = {}) {
|
|
3054
|
+
const {
|
|
3055
|
+
detailsPoint = true,
|
|
3056
|
+
whiteModel = true,
|
|
3057
|
+
dxfLineModel = true
|
|
3058
|
+
} = option;
|
|
3059
|
+
dxfLineModel && dxfSystem.addComponent(new DxfLineModel());
|
|
3060
|
+
whiteModel && dxfSystem.addComponent(new WhiteModel());
|
|
3061
|
+
detailsPoint && dxfSystem.addComponent(new DetailsPoint());
|
|
3014
3062
|
}
|
|
3063
|
+
const ModelDataPlugin = Object.assign(ModelDataPlugin_, {
|
|
3064
|
+
create(option = {}) {
|
|
3065
|
+
return (dxfSystem) => ModelDataPlugin_(dxfSystem, option);
|
|
3066
|
+
}
|
|
3067
|
+
});
|
|
3068
|
+
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
3069
|
+
__proto__: null,
|
|
3070
|
+
ModelDataPlugin,
|
|
3071
|
+
components: index$1
|
|
3072
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
3015
3073
|
function loadRenderPlugin() {
|
|
3016
3074
|
return import("./index2.js");
|
|
3017
3075
|
}
|
|
3076
|
+
function loadEditorPlugin() {
|
|
3077
|
+
return import("./index3.js");
|
|
3078
|
+
}
|
|
3079
|
+
async function createEditor(dom, camera) {
|
|
3080
|
+
const mp = await Promise.resolve().then(() => index);
|
|
3081
|
+
const rp = await loadRenderPlugin();
|
|
3082
|
+
const editor = await loadEditorPlugin();
|
|
3083
|
+
const dxfSystem = new DxfSystem().usePlugin(mp.ModelDataPlugin.create({
|
|
3084
|
+
detailsPoint: false,
|
|
3085
|
+
whiteModel: false
|
|
3086
|
+
})).usePlugin(rp.RenderPlugin.create({
|
|
3087
|
+
originalLine: false,
|
|
3088
|
+
modelData: false,
|
|
3089
|
+
detailsPoint: false,
|
|
3090
|
+
camera
|
|
3091
|
+
})).usePlugin(editor.Editor);
|
|
3092
|
+
const domContainer = dxfSystem.findComponentByType(rp.components.DomContainer);
|
|
3093
|
+
domContainer && dom.appendChild(domContainer.domElement);
|
|
3094
|
+
return {
|
|
3095
|
+
dxfSystem
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
3018
3098
|
export {
|
|
3019
3099
|
Box2 as B,
|
|
3020
3100
|
Component as C,
|
|
3021
3101
|
DxfSystem as D,
|
|
3102
|
+
EventDispatcher as E,
|
|
3103
|
+
LineSegment as L,
|
|
3022
3104
|
ModelDataPlugin as M,
|
|
3023
3105
|
Point as P,
|
|
3106
|
+
Quadtree as Q,
|
|
3024
3107
|
Variable as V,
|
|
3025
3108
|
WhiteModel as W,
|
|
3026
3109
|
DetailsPoint as a,
|
|
3027
|
-
|
|
3028
|
-
|
|
3110
|
+
PointVirtualGrid as b,
|
|
3111
|
+
createEditor as c,
|
|
3112
|
+
index$1 as i
|
|
3029
3113
|
};
|