build-dxf 0.1.58 → 0.1.60
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 +508 -127
- package/src/utils/DxfSystem/components/ThreeVJia.d.ts +1 -1
- package/src/utils/DxfSystem/type.d.ts +3 -0
- package/src/utils/DxfSystem/utils/BayWindowHelper.d.ts +1 -2
- package/src/utils/DxfSystem/utils/CAD.d.ts +3 -3
- package/src/utils/DxfSystem/utils/DoorFind.d.ts +4 -1
- package/src/utils/DxfSystem/utils/WallGroupManager.d.ts +15 -0
- package/src/utils/DxfSystem/utils/lineDataToThreeVJiaJson.d.ts +56 -10
- package/src/utils/DxfSystem/utils/lineDataToThreeVJiaJsonOld.d.ts +52 -0
- package/src/utils/HandlerFlow.d.ts +10 -0
- package/src/utils/Point.d.ts +4 -0
- package/src/utils/PointVirtualGrid.d.ts +1 -4
- package/src/utils/Polygon.d.ts +1 -0
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -340,7 +340,7 @@ class PointVirtualGrid {
|
|
|
340
340
|
*/
|
|
341
341
|
queryCircle(pos, radius, excludeOneself = false) {
|
|
342
342
|
const box2 = new Box2(pos.x - radius, pos.x + radius, pos.y - radius, pos.y + radius);
|
|
343
|
-
const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize), list =
|
|
343
|
+
const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize), list = new PvgList();
|
|
344
344
|
for (let i = minI; i <= maxI; i++) {
|
|
345
345
|
for (let j = minJ; j <= maxJ; j++) {
|
|
346
346
|
const id = `${i}.${j}`;
|
|
@@ -2619,6 +2619,12 @@ class Point {
|
|
|
2619
2619
|
z
|
|
2620
2620
|
};
|
|
2621
2621
|
}
|
|
2622
|
+
toJson2D() {
|
|
2623
|
+
return {
|
|
2624
|
+
x: this.x,
|
|
2625
|
+
y: this.y
|
|
2626
|
+
};
|
|
2627
|
+
}
|
|
2622
2628
|
toVector3(z = 0) {
|
|
2623
2629
|
return new Vector3(this.x, this.y, z);
|
|
2624
2630
|
}
|
|
@@ -4778,6 +4784,12 @@ class Polygon extends Array {
|
|
|
4778
4784
|
}
|
|
4779
4785
|
return Math.abs(area2) / 2;
|
|
4780
4786
|
}
|
|
4787
|
+
closedLoop() {
|
|
4788
|
+
if (this.length < 2) return false;
|
|
4789
|
+
const first = this[0];
|
|
4790
|
+
const last = this[this.length - 1];
|
|
4791
|
+
return first.equal(last);
|
|
4792
|
+
}
|
|
4781
4793
|
/**
|
|
4782
4794
|
* 获取点相对于多边形的位置
|
|
4783
4795
|
* @param point
|
|
@@ -6198,7 +6210,7 @@ class CAD {
|
|
|
6198
6210
|
/** 添加组并执行偏移
|
|
6199
6211
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
6200
6212
|
*/
|
|
6201
|
-
|
|
6213
|
+
addGroupAndOffset(lines, joinType = "jtMiter", endType = "etOpenButt", scale2 = 1e5) {
|
|
6202
6214
|
const groups = LineSegment.groupByPoint(lines);
|
|
6203
6215
|
const polygons = groups.flatMap((group2) => Polygon.multipleFromByLines(group2));
|
|
6204
6216
|
const offset2 = new ClipperLib.ClipperOffset(2, 0.25);
|
|
@@ -6735,7 +6747,7 @@ class DxfDataPlugin {
|
|
|
6735
6747
|
line.end.add(direct.clone().multiplyScalar(-DEFAULT_WALL_WIDTH * 0.5));
|
|
6736
6748
|
}
|
|
6737
6749
|
});
|
|
6738
|
-
cad.
|
|
6750
|
+
cad.addGroupAndOffset(wall);
|
|
6739
6751
|
cad.addGroups(doubleWallGroup, "doubleWall");
|
|
6740
6752
|
cad.unionGroupAll();
|
|
6741
6753
|
cad.addGroup(doors, "door");
|
|
@@ -7000,13 +7012,15 @@ function buildDoubleWallGroup(lines, doorLines = [], grouped = true, clearIntern
|
|
|
7000
7012
|
}
|
|
7001
7013
|
function buildBayWindowGroup(lines, clear = true) {
|
|
7002
7014
|
const bayWindowLines = lines.filter((line) => line.userData.isBayWindow), groupedLineSet = /* @__PURE__ */ new Set();
|
|
7015
|
+
const removeSet = findDiscretePointLine2(lines, null, true);
|
|
7016
|
+
const lines_ = lines.filter((line) => !removeSet.has(line));
|
|
7003
7017
|
bayWindowLines.forEach((bayWindowLine) => {
|
|
7004
|
-
let { circles } = maxiCircles.miniCircle(
|
|
7018
|
+
let { circles } = maxiCircles.miniCircle(lines_, { circleEdges: [bayWindowLine] });
|
|
7005
7019
|
circles = circles.filter((group2) => group2.some((line) => line.userData.isWindow && LineGroupType.hasType(line, "bayWindow")));
|
|
7006
7020
|
if (circles.length === 0 && bayWindowLine.userData?.outSize) {
|
|
7007
7021
|
const direct = Point.from(bayWindowLine.userData.outSize.direction), point2 = bayWindowLine.center.add(direct.multiplyScalar(1e-8));
|
|
7008
7022
|
circles.push([bayWindowLine]);
|
|
7009
|
-
bayWindowLine.points.map((p2) => {
|
|
7023
|
+
const paths = bayWindowLine.points.map((p2) => {
|
|
7010
7024
|
const path = /* @__PURE__ */ new Set();
|
|
7011
7025
|
maxiCircles.findSameSidePath({
|
|
7012
7026
|
path,
|
|
@@ -7016,8 +7030,33 @@ function buildBayWindowGroup(lines, clear = true) {
|
|
|
7016
7030
|
exitPoint: p2,
|
|
7017
7031
|
grid: lines
|
|
7018
7032
|
});
|
|
7019
|
-
|
|
7020
|
-
});
|
|
7033
|
+
return [...path];
|
|
7034
|
+
}).filter((path) => path.length);
|
|
7035
|
+
circles[0].push(...paths.flat(2));
|
|
7036
|
+
if (paths.length === 2) {
|
|
7037
|
+
const line1 = paths[0][paths[0].length - 1], line2 = paths[1][paths[1].length - 1];
|
|
7038
|
+
let point1, point22, min = Infinity;
|
|
7039
|
+
line1.points.forEach((p2) => {
|
|
7040
|
+
line2.points.forEach((p22) => {
|
|
7041
|
+
const distance2 = p2.distance(p22);
|
|
7042
|
+
if (distance2 < min && distance2 < 0.3) {
|
|
7043
|
+
point1 = p2;
|
|
7044
|
+
point22 = p22;
|
|
7045
|
+
min = distance2;
|
|
7046
|
+
}
|
|
7047
|
+
});
|
|
7048
|
+
});
|
|
7049
|
+
if (point1 && point22) {
|
|
7050
|
+
const point3 = line1.projectPoint(point22, false);
|
|
7051
|
+
if (point3) {
|
|
7052
|
+
const newLine = new LineSegment(point3.clone(), point22.clone());
|
|
7053
|
+
lines.push(newLine);
|
|
7054
|
+
circles[0].push(newLine);
|
|
7055
|
+
point1.copy(point3);
|
|
7056
|
+
newLine.userData.isWindowWall = true;
|
|
7057
|
+
}
|
|
7058
|
+
}
|
|
7059
|
+
}
|
|
7021
7060
|
}
|
|
7022
7061
|
const id = uuid();
|
|
7023
7062
|
if (circles.length) {
|
|
@@ -7185,6 +7224,14 @@ class DoubleWallHelper {
|
|
|
7185
7224
|
* @returns
|
|
7186
7225
|
*/
|
|
7187
7226
|
static complementSide(lines, wallWidth = 0.4) {
|
|
7227
|
+
const otherLines = [];
|
|
7228
|
+
lines = lines.filter((line) => {
|
|
7229
|
+
if (line.userData.isBayWindow || line.userData.isBalconyRailing) {
|
|
7230
|
+
otherLines.push(line);
|
|
7231
|
+
return false;
|
|
7232
|
+
}
|
|
7233
|
+
return true;
|
|
7234
|
+
});
|
|
7188
7235
|
let { resultList, quadtree } = this.findDoubleLine(lines, wallWidth), removeLines = /* @__PURE__ */ new Set(), clipingMap = /* @__PURE__ */ new Map(), appendLines = [];
|
|
7189
7236
|
function addClipingMap(line, line1) {
|
|
7190
7237
|
if (!clipingMap.has(line)) clipingMap.set(line, []);
|
|
@@ -7240,6 +7287,7 @@ class DoubleWallHelper {
|
|
|
7240
7287
|
lines.push(...appendLines);
|
|
7241
7288
|
lines = lineSegmentClipping(lines, 1e-9);
|
|
7242
7289
|
quadtree.clear();
|
|
7290
|
+
lines.push(...otherLines);
|
|
7243
7291
|
return lines;
|
|
7244
7292
|
}
|
|
7245
7293
|
/**
|
|
@@ -7877,124 +7925,308 @@ class BoundExt {
|
|
|
7877
7925
|
};
|
|
7878
7926
|
}
|
|
7879
7927
|
}
|
|
7880
|
-
function
|
|
7881
|
-
|
|
7882
|
-
const
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
|
|
7928
|
+
function createGeometry(points, options) {
|
|
7929
|
+
points = points.map((p2) => p2 instanceof Point ? new THREE.Vector2(p2.x, p2.y) : p2);
|
|
7930
|
+
const shape = new THREE.Shape(points);
|
|
7931
|
+
const extrudeGeometry = new THREE.ExtrudeGeometry(shape, {
|
|
7932
|
+
bevelEnabled: false,
|
|
7933
|
+
...options
|
|
7934
|
+
});
|
|
7935
|
+
return extrudeGeometry;
|
|
7936
|
+
}
|
|
7937
|
+
class ExtrudeMesh extends THREE.Mesh {
|
|
7938
|
+
geometry;
|
|
7939
|
+
options;
|
|
7940
|
+
constructor(points, options, material) {
|
|
7941
|
+
const geometry = createGeometry(points, options);
|
|
7942
|
+
super(geometry, material);
|
|
7943
|
+
this.geometry = geometry;
|
|
7944
|
+
this.options = options;
|
|
7945
|
+
}
|
|
7946
|
+
setPoints(points, options = this.options) {
|
|
7947
|
+
const geometry = createGeometry(points, options);
|
|
7948
|
+
this.geometry = geometry;
|
|
7949
|
+
}
|
|
7950
|
+
}
|
|
7951
|
+
class BayWindowHelper {
|
|
7952
|
+
/** 获取绘制数据
|
|
7953
|
+
* @param lines
|
|
7954
|
+
* @returns
|
|
7955
|
+
*/
|
|
7956
|
+
static getDrawData(lines) {
|
|
7957
|
+
lines = LineSegmentUndirectedGraph.breakpointMerging(lines.map((line) => line.clone()), mergeLineUserData);
|
|
7958
|
+
if (lines.length === 4) {
|
|
7959
|
+
let bayWindowLine = null;
|
|
7960
|
+
let windowLine = null;
|
|
7961
|
+
let deptLine = null;
|
|
7962
|
+
for (let i = 0; i < lines.length; i++) {
|
|
7963
|
+
const line = lines[i];
|
|
7964
|
+
if (line.userData.isBayWindow) bayWindowLine = line;
|
|
7965
|
+
else if (line.userData.isWindow && line.userData.drawWindow) windowLine = line;
|
|
7966
|
+
else deptLine = line;
|
|
7967
|
+
}
|
|
7968
|
+
if (bayWindowLine && windowLine && deptLine) {
|
|
7969
|
+
const { width, height, groundClearance } = windowLine.userData.drawWindow[0];
|
|
7970
|
+
const direction = Point.zero();
|
|
7971
|
+
if (deptLine.sameEndpointAsEnd(bayWindowLine)) {
|
|
7972
|
+
deptLine.start.direction(deptLine.end, direction);
|
|
7973
|
+
} else {
|
|
7974
|
+
deptLine.end.direction(deptLine.start, direction);
|
|
7975
|
+
}
|
|
7976
|
+
return {
|
|
7977
|
+
height1: bayWindowLine.userData.topClearance ?? 0,
|
|
7978
|
+
height2: height,
|
|
7979
|
+
height3: groundClearance,
|
|
7980
|
+
depth: deptLine.length(),
|
|
7981
|
+
windowWidth: width,
|
|
7982
|
+
windowHeight: height,
|
|
7983
|
+
bayWindowLine,
|
|
7984
|
+
windowLine,
|
|
7985
|
+
deptLine,
|
|
7986
|
+
direction
|
|
7987
|
+
};
|
|
7988
|
+
}
|
|
7989
|
+
}
|
|
7990
|
+
return null;
|
|
7991
|
+
}
|
|
7992
|
+
/** 获取所有绘制数据
|
|
7993
|
+
* @param lineSegments
|
|
7994
|
+
* @returns
|
|
7995
|
+
*/
|
|
7996
|
+
static getDrawDataAll(lineSegments) {
|
|
7997
|
+
const groups = LineGroupType.getGroupsByType(lineSegments, "bayWindow");
|
|
7998
|
+
const drawDataList = groups.map(this.getDrawData);
|
|
7999
|
+
return groups.map((group2, indxe) => ({
|
|
8000
|
+
group: group2,
|
|
8001
|
+
drawData: drawDataList[indxe]
|
|
8002
|
+
})).filter((item) => item.drawData);
|
|
8003
|
+
}
|
|
8004
|
+
/** 绘制数据转模型
|
|
8005
|
+
* @param drawData
|
|
8006
|
+
* @returns
|
|
8007
|
+
*/
|
|
8008
|
+
static drawDataToModel(drawData) {
|
|
8009
|
+
const pos = drawData.bayWindowLine.center, dirct = drawData.bayWindowLine.direction(), length = drawData.bayWindowLine.length(), bayWindowLine = Point.zero().expandAsLine(dirct, length).directionMove(dirct.multiplyScalar(-1), length * 0.5), winGroup = new THREE.Group(), material = new THREE.MeshBasicMaterial({ color: 16777215 });
|
|
8010
|
+
winGroup.position.set(pos.x, pos.y, 0);
|
|
8011
|
+
const rectangle = bayWindowLine.expandToRectangle(DEFAULT_WALL_WIDTH), extrudeMesh = new ExtrudeMesh(rectangle.points, { depth: drawData.height3 }, material);
|
|
8012
|
+
winGroup.add(extrudeMesh);
|
|
8013
|
+
const rectangle2 = bayWindowLine.clone().directionMove(drawData.direction, drawData.depth).expandToRectangle(DEFAULT_WALL_WIDTH), extrudeMesh2 = new ExtrudeMesh(rectangle2.points, { depth: drawData.height2 }, new THREE.MeshPhongMaterial({ color: 16777215, transparent: true, opacity: 0.2 }));
|
|
8014
|
+
extrudeMesh2.position.z = drawData.height3;
|
|
8015
|
+
winGroup.add(extrudeMesh2);
|
|
8016
|
+
const rectangle3 = bayWindowLine.start.expandAsLine(drawData.direction, drawData.depth).directionMove(drawData.direction, -0.06).expandToRectangle(DEFAULT_WALL_WIDTH, "bothSides"), extrudeMesh3 = new ExtrudeMesh(rectangle3.points, { depth: drawData.height2 }, material);
|
|
8017
|
+
extrudeMesh3.position.z = drawData.height3;
|
|
8018
|
+
winGroup.add(extrudeMesh3);
|
|
8019
|
+
const rectangle4 = bayWindowLine.end.expandAsLine(drawData.direction, drawData.depth).directionMove(drawData.direction, -0.06).expandToRectangle(DEFAULT_WALL_WIDTH, "bothSides"), extrudeMesh4 = new ExtrudeMesh(rectangle4.points, { depth: drawData.height2 }, material);
|
|
8020
|
+
extrudeMesh4.position.z = drawData.height3;
|
|
8021
|
+
winGroup.add(extrudeMesh4);
|
|
8022
|
+
const extrudeMesh5 = new ExtrudeMesh(rectangle.points, { depth: drawData.height1 }, material);
|
|
8023
|
+
extrudeMesh5.position.z = drawData.height3 + drawData.height2;
|
|
8024
|
+
winGroup.add(extrudeMesh5);
|
|
8025
|
+
const rectangle6 = bayWindowLine.clone().directionMove(drawData.direction, drawData.depth * 0.5).expandToRectangle(drawData.depth - DEFAULT_WALL_WIDTH, "bothSides"), extrudeMesh6 = new ExtrudeMesh(rectangle6.points, { depth: 1e-3 }, material);
|
|
8026
|
+
extrudeMesh6.position.z = drawData.height3;
|
|
8027
|
+
winGroup.add(extrudeMesh6);
|
|
8028
|
+
const extrudeMesh7 = new ExtrudeMesh(rectangle6.points, { depth: 1e-3 }, material);
|
|
8029
|
+
extrudeMesh7.position.z = drawData.height3 + drawData.height2;
|
|
8030
|
+
winGroup.add(extrudeMesh7);
|
|
8031
|
+
return winGroup;
|
|
8032
|
+
}
|
|
8033
|
+
}
|
|
8034
|
+
class WallGroupManager {
|
|
8035
|
+
[Symbol.iterator]() {
|
|
8036
|
+
return this.groups[Symbol.iterator]();
|
|
8037
|
+
}
|
|
8038
|
+
groups = [];
|
|
8039
|
+
add(group2) {
|
|
8040
|
+
this.groups.push(group2);
|
|
8041
|
+
}
|
|
8042
|
+
static fromByLines(lineSegments) {
|
|
8043
|
+
const wallGroupManager = new WallGroupManager();
|
|
8044
|
+
const removeLines = [];
|
|
8045
|
+
BayWindowHelper.getDrawDataAll(lineSegments).forEach(({ group: group2, drawData }) => {
|
|
8046
|
+
wallGroupManager.add({
|
|
8047
|
+
type: "bayWindow",
|
|
8048
|
+
lines: group2,
|
|
8049
|
+
data: drawData
|
|
8050
|
+
});
|
|
8051
|
+
removeLines.push(...group2);
|
|
7888
8052
|
});
|
|
7889
|
-
|
|
7890
|
-
|
|
7891
|
-
|
|
8053
|
+
const doors = lineSegments.filter((line) => line.userData.isDoor);
|
|
8054
|
+
wallGroupManager.add({ type: "door", lines: doors });
|
|
8055
|
+
removeLines.push(...doors);
|
|
8056
|
+
const doubleWalls = LineGroupType.getGroupsByType(lineSegments, "doubleWall");
|
|
8057
|
+
doubleWalls.forEach((doubleWall) => {
|
|
8058
|
+
wallGroupManager.add({ type: "doubleWall", lines: doubleWall });
|
|
8059
|
+
removeLines.push(...doubleWall);
|
|
8060
|
+
});
|
|
8061
|
+
const set2 = new Set(removeLines);
|
|
8062
|
+
const walls = lineSegments.filter((line) => !set2.has(line));
|
|
8063
|
+
wallGroupManager.add({ type: "wall", lines: walls.filter((line) => !line.userData.isWindow) });
|
|
8064
|
+
wallGroupManager.add({ type: "window", lines: walls.filter((line) => line.userData.isWindow) });
|
|
8065
|
+
return wallGroupManager;
|
|
8066
|
+
}
|
|
8067
|
+
forEach(fun) {
|
|
8068
|
+
for (let i = 0; i < this.groups.length; i++) {
|
|
8069
|
+
fun(this.groups[i], i);
|
|
8070
|
+
}
|
|
8071
|
+
}
|
|
8072
|
+
map(fun) {
|
|
8073
|
+
const list = [];
|
|
8074
|
+
for (let i = 0; i < this.groups.length; i++) {
|
|
8075
|
+
list.push(fun(this.groups[i], i));
|
|
8076
|
+
}
|
|
8077
|
+
return list;
|
|
8078
|
+
}
|
|
7892
8079
|
}
|
|
7893
|
-
|
|
7894
|
-
|
|
7895
|
-
|
|
7896
|
-
|
|
7897
|
-
|
|
7898
|
-
|
|
7899
|
-
|
|
7900
|
-
|
|
7901
|
-
|
|
7902
|
-
}
|
|
7903
|
-
|
|
7904
|
-
|
|
8080
|
+
class HandlerFlow {
|
|
8081
|
+
handlerMap = new ArrayMap();
|
|
8082
|
+
addHandler(handler) {
|
|
8083
|
+
this.handlerMap.append(handler.type, handler);
|
|
8084
|
+
}
|
|
8085
|
+
handle(type, data, option) {
|
|
8086
|
+
const list = this.handlerMap.get(type);
|
|
8087
|
+
if (list) list.forEach((handler) => data = handler.handle(data, option));
|
|
8088
|
+
return data;
|
|
8089
|
+
}
|
|
8090
|
+
}
|
|
8091
|
+
class ThreeVJiaJson extends HandlerFlow {
|
|
8092
|
+
manager;
|
|
8093
|
+
index = 0;
|
|
8094
|
+
constructor(lines) {
|
|
8095
|
+
super();
|
|
8096
|
+
this.manager = WallGroupManager.fromByLines(lines);
|
|
8097
|
+
this.addHandler({ type: "bayWindow", handle: this.bayWindowHandle.bind(this) });
|
|
8098
|
+
this.addHandler({ type: "doubleWall", handle: this.doubleWallHandle.bind(this) });
|
|
8099
|
+
this.addHandler({ type: "wall", handle: this.wallHandle.bind(this) });
|
|
8100
|
+
this.addHandler({ type: "door", handle: this.doorHandle.bind(this) });
|
|
8101
|
+
this.addHandler({ type: "window", handle: this.windowHandle.bind(this) });
|
|
8102
|
+
}
|
|
8103
|
+
/** 双线墙处理
|
|
8104
|
+
* @param param0
|
|
8105
|
+
* @returns
|
|
8106
|
+
*/
|
|
8107
|
+
doubleWallHandle({ lines }) {
|
|
7905
8108
|
const groups = clippingDoubleWall(lines);
|
|
7906
|
-
groups.
|
|
7907
|
-
if (lines2.length < 4) return
|
|
8109
|
+
const newLines = groups.flatMap((lines2) => {
|
|
8110
|
+
if (lines2.length < 4) return lines2;
|
|
7908
8111
|
lines2 = lines2.sort((a2, b4) => a2.length() - b4.length());
|
|
7909
8112
|
const line1 = lines2[0], line2 = lines2[1];
|
|
7910
8113
|
const newLine = new LineSegment(line1.center.clone(), line2.center.clone());
|
|
7911
8114
|
mergeLineUserData(newLine, lines2);
|
|
7912
8115
|
newLine.userData.wallWidth = line1.length();
|
|
7913
|
-
newlines.push(newLine);
|
|
7914
8116
|
mergeWindow(newLine);
|
|
8117
|
+
return [newLine];
|
|
7915
8118
|
});
|
|
7916
|
-
|
|
7917
|
-
|
|
7918
|
-
|
|
7919
|
-
}
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
|
|
8119
|
+
const windowLines = newLines.filter((line) => line.userData.isWindow);
|
|
8120
|
+
this.manager.add({ type: "window", lines: windowLines });
|
|
8121
|
+
return newLines.filter((line) => !line.userData.isWindow);
|
|
8122
|
+
}
|
|
8123
|
+
/**
|
|
8124
|
+
* 单线墙处理
|
|
8125
|
+
* @param param0
|
|
8126
|
+
*/
|
|
8127
|
+
wallHandle({ lines }) {
|
|
8128
|
+
return lines;
|
|
8129
|
+
}
|
|
8130
|
+
/**
|
|
8131
|
+
* 门线处理
|
|
8132
|
+
* @param param0
|
|
8133
|
+
*/
|
|
8134
|
+
doorHandle({ lines }, option) {
|
|
8135
|
+
lines.forEach((line) => {
|
|
8136
|
+
option.holes.push({
|
|
8137
|
+
id: this.index++,
|
|
8138
|
+
type: "DOOR",
|
|
8139
|
+
openSide: "RIGHT",
|
|
8140
|
+
start: line.start.toJson2D(),
|
|
8141
|
+
end: line.end.toJson2D(),
|
|
8142
|
+
height: line.userData.drawDoorData?.height ?? DEFAULT_DOOR_HEIGHT,
|
|
8143
|
+
sillHeight: line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT,
|
|
8144
|
+
groundClearance: line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT
|
|
8145
|
+
});
|
|
8146
|
+
});
|
|
8147
|
+
return [];
|
|
8148
|
+
}
|
|
8149
|
+
/**
|
|
8150
|
+
* 窗线处理
|
|
8151
|
+
* @param param0
|
|
8152
|
+
*/
|
|
8153
|
+
windowHandle({ lines }, option) {
|
|
8154
|
+
lines.forEach((line) => {
|
|
8155
|
+
line.userData.drawWindow?.forEach((item) => {
|
|
8156
|
+
const center = Point.from(item.p);
|
|
8157
|
+
const start = center.clone().add(line.direction().multiplyScalar(item.width * 0.5));
|
|
8158
|
+
const end = center.clone().add(line.direction().multiplyScalar(-item.width * 0.5));
|
|
8159
|
+
option?.holes.push({
|
|
8160
|
+
id: this.index++,
|
|
8161
|
+
type: "WINDOW",
|
|
8162
|
+
start: start.toJson2D(),
|
|
8163
|
+
end: end.toJson2D(),
|
|
8164
|
+
height: item.height ?? DEFAULT_WINDOW_HEIGHT,
|
|
8165
|
+
groundClearance: item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT,
|
|
8166
|
+
sillHeight: item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT
|
|
8167
|
+
});
|
|
8168
|
+
});
|
|
8169
|
+
});
|
|
8170
|
+
return lines;
|
|
8171
|
+
}
|
|
8172
|
+
/** 飘窗处理
|
|
8173
|
+
* @param data
|
|
8174
|
+
* @returns
|
|
8175
|
+
*/
|
|
8176
|
+
bayWindowHandle({ lines, data }, option) {
|
|
8177
|
+
const bayWindows = lines.filter((line) => line.userData.isBayWindow);
|
|
8178
|
+
if (bayWindows.length) {
|
|
8179
|
+
option?.holes.push({
|
|
8180
|
+
type: "BAY_WINDOW",
|
|
8181
|
+
id: this.index++,
|
|
8182
|
+
start: bayWindows[0].start,
|
|
8183
|
+
end: bayWindows[0].end,
|
|
8184
|
+
height1: data?.height1,
|
|
8185
|
+
height2: data?.height2,
|
|
8186
|
+
height3: data?.height3,
|
|
8187
|
+
depth: data?.depth,
|
|
8188
|
+
windowWidth: data?.windowWidth,
|
|
8189
|
+
windowHeight: data?.windowHeight
|
|
8190
|
+
// direction: data?.direction.toJson2D(),
|
|
8191
|
+
});
|
|
8192
|
+
}
|
|
8193
|
+
return [];
|
|
8194
|
+
}
|
|
8195
|
+
/** 装换
|
|
8196
|
+
* @returns
|
|
8197
|
+
*/
|
|
8198
|
+
transform() {
|
|
8199
|
+
const option = {
|
|
8200
|
+
version: "2",
|
|
8201
|
+
name: "",
|
|
8202
|
+
communityName: "",
|
|
8203
|
+
city: "",
|
|
8204
|
+
province: "",
|
|
8205
|
+
height: 0,
|
|
8206
|
+
walls: [],
|
|
8207
|
+
pillars: [],
|
|
8208
|
+
beams: [],
|
|
8209
|
+
holes: [],
|
|
8210
|
+
rooms: []
|
|
8211
|
+
};
|
|
8212
|
+
const lines = this.manager.map((group2) => this.handle(group2.type, group2, option)).flat(4);
|
|
8213
|
+
lines.forEach((line) => {
|
|
8214
|
+
option.walls.push({
|
|
8215
|
+
ID: this.index++,
|
|
8216
|
+
start: line.start.toJson2D(),
|
|
8217
|
+
end: line.end.toJson2D(),
|
|
8218
|
+
thickness: line.userData.wallWidth ? line.userData.wallWidth : 0.12,
|
|
7938
8219
|
type: "LINE",
|
|
7939
|
-
isDoor:
|
|
8220
|
+
isDoor: false,
|
|
7940
8221
|
loadBearingWall: false,
|
|
7941
|
-
height:
|
|
7942
|
-
};
|
|
7943
|
-
})
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
holes: lineSegments.flatMap((line) => {
|
|
7947
|
-
if (line.userData.isDoor && line.userData.doorDirectConnection) {
|
|
7948
|
-
return {
|
|
7949
|
-
id: index2++,
|
|
7950
|
-
type: "DOOR",
|
|
7951
|
-
openSide: "RIGHT",
|
|
7952
|
-
start: {
|
|
7953
|
-
x: line.start.x * scale2,
|
|
7954
|
-
y: line.start.y * scale2
|
|
7955
|
-
},
|
|
7956
|
-
end: {
|
|
7957
|
-
x: line.end.x * scale2,
|
|
7958
|
-
y: line.end.y * scale2
|
|
7959
|
-
},
|
|
7960
|
-
height: (line.userData.drawDoorData?.height ?? DEFAULT_DOOR_HEIGHT) * scale2,
|
|
7961
|
-
qroundClearance: (line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT) * scale2,
|
|
7962
|
-
sillHeight: (line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT) * scale2
|
|
7963
|
-
};
|
|
7964
|
-
} else if (line.userData.isWindow && line.userData.drawWindow) {
|
|
7965
|
-
return line.userData.drawWindow.map((item) => {
|
|
7966
|
-
const center = Point.from(item.p);
|
|
7967
|
-
const start = center.clone().add(
|
|
7968
|
-
line.direction().multiplyScalar(item.width * 0.5)
|
|
7969
|
-
);
|
|
7970
|
-
const end = center.clone().add(
|
|
7971
|
-
line.direction().multiplyScalar(-item.width * 0.5)
|
|
7972
|
-
);
|
|
7973
|
-
return {
|
|
7974
|
-
id: index2++,
|
|
7975
|
-
type: "WINDOW",
|
|
7976
|
-
start: {
|
|
7977
|
-
x: start.x * scale2,
|
|
7978
|
-
y: start.y * scale2
|
|
7979
|
-
},
|
|
7980
|
-
end: {
|
|
7981
|
-
x: end.x * scale2,
|
|
7982
|
-
y: end.y * scale2
|
|
7983
|
-
},
|
|
7984
|
-
height: (item.height ?? DEFAULT_WINDOW_HEIGHT) * scale2,
|
|
7985
|
-
groundClearance: (item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT) * scale2,
|
|
7986
|
-
sillHeight: (item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT) * scale2
|
|
7987
|
-
};
|
|
7988
|
-
});
|
|
7989
|
-
}
|
|
7990
|
-
}).filter((i) => !!i),
|
|
7991
|
-
rooms: []
|
|
7992
|
-
};
|
|
8222
|
+
height: line.userData.height ?? DEFAULT_WALL_HEIGHT
|
|
8223
|
+
});
|
|
8224
|
+
});
|
|
8225
|
+
return option;
|
|
8226
|
+
}
|
|
7993
8227
|
}
|
|
7994
|
-
function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
7995
|
-
|
|
7996
|
-
let newLines = handleGroup(group2);
|
|
7997
|
-
newLines = LineSegmentUndirectedGraph.rotate(newLines, angle, (line, center, angle2) => {
|
|
8228
|
+
function lineDataToThreeVJiaJson$1(lineSegments, angle = 0, updateGroup = true) {
|
|
8229
|
+
lineSegments = LineSegmentUndirectedGraph.rotate(lineSegments.map((line) => line.clone()), angle, (line, center, angle2) => {
|
|
7998
8230
|
if (line.userData.drawWindow) {
|
|
7999
8231
|
line.userData.drawWindow.forEach((windowItem) => {
|
|
8000
8232
|
const point2 = Point.from(windowItem.p);
|
|
@@ -8003,10 +8235,15 @@ function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
|
8003
8235
|
});
|
|
8004
8236
|
}
|
|
8005
8237
|
});
|
|
8238
|
+
if (updateGroup) lineSegments = DoubleWallHelper.buildGroup(lineSegments);
|
|
8239
|
+
const threeVJiaJson = new ThreeVJiaJson(lineSegments);
|
|
8006
8240
|
return {
|
|
8007
|
-
lines:
|
|
8241
|
+
lines: [],
|
|
8008
8242
|
toJson(name = "测试", communityName = "") {
|
|
8009
|
-
|
|
8243
|
+
const json = threeVJiaJson.transform();
|
|
8244
|
+
json.name = name;
|
|
8245
|
+
json.communityName = communityName;
|
|
8246
|
+
return json;
|
|
8010
8247
|
}
|
|
8011
8248
|
};
|
|
8012
8249
|
}
|
|
@@ -16658,6 +16895,7 @@ class SceneAutoGenerat {
|
|
|
16658
16895
|
mesh.position.z = this.z;
|
|
16659
16896
|
mesh.name = `平面_out_${i}_${j}`;
|
|
16660
16897
|
mesh.userData.category = "plane";
|
|
16898
|
+
mesh.userData.area = poly.area();
|
|
16661
16899
|
this.scene.add(mesh);
|
|
16662
16900
|
});
|
|
16663
16901
|
});
|
|
@@ -16667,6 +16905,7 @@ class SceneAutoGenerat {
|
|
|
16667
16905
|
mesh.position.z = this.z;
|
|
16668
16906
|
mesh.name = `平面_${i}_${j}`;
|
|
16669
16907
|
mesh.userData.category = "plane";
|
|
16908
|
+
mesh.userData.area = Polygon.fromByLines2(circle).area();
|
|
16670
16909
|
mesh.userData.room = true;
|
|
16671
16910
|
this.scene.add(mesh);
|
|
16672
16911
|
});
|
|
@@ -16834,6 +17073,7 @@ class DoorFind {
|
|
|
16834
17073
|
const openDoors = doors.filter((line) => !line.userData.doorDirectConnection), closeDoors = doors.filter((line) => line.userData.doorDirectConnection);
|
|
16835
17074
|
this.grid = createPointVirtualGrid(noDoorLines);
|
|
16836
17075
|
this.quadtree = createQuadtree([...noDoorLines, ...closeDoors]);
|
|
17076
|
+
openDoors.forEach((l) => l.userData.doorDirectConnection = true);
|
|
16837
17077
|
closeDoors.forEach((line) => this.findCloseDoors(line));
|
|
16838
17078
|
openDoors.forEach((line) => this.findOpenDoors(line));
|
|
16839
17079
|
}
|
|
@@ -16889,7 +17129,7 @@ class DoorFind {
|
|
|
16889
17129
|
const { point: point2 } = searchedList[result.userData];
|
|
16890
17130
|
const dir2 = item.point.direction(point2);
|
|
16891
17131
|
const dir3 = item.linePoint.direction(item.line.getAnotherPoint(item.linePoint));
|
|
16892
|
-
return dir2.angleBetween(dir3) > Math.PI / 180 *
|
|
17132
|
+
return dir2.angleBetween(dir3) > Math.PI / 180 * 135;
|
|
16893
17133
|
});
|
|
16894
17134
|
if (list.length) {
|
|
16895
17135
|
const item2 = searchedList[list[0].userData];
|
|
@@ -16934,7 +17174,10 @@ class DoorFind {
|
|
|
16934
17174
|
findOpenDoors(line) {
|
|
16935
17175
|
let dock;
|
|
16936
17176
|
const queryList = (point22) => {
|
|
16937
|
-
let list = this.grid.
|
|
17177
|
+
let list = this.grid.queryPoint(point22, true);
|
|
17178
|
+
if (list.length === 1) return list;
|
|
17179
|
+
list = this.grid.queryCircle(point22, 0.6, true);
|
|
17180
|
+
list = list.filter((item) => !item.userData?.userData.isDoor && !item.userData?.userData.isBayWindow).filter((item) => {
|
|
16938
17181
|
return !this.grid.queryPoint(item.point, true).some((i) => i.userData?.parallel(item.userData));
|
|
16939
17182
|
}).filter((item) => {
|
|
16940
17183
|
const line2 = item.userData, direct1 = line.getAnotherPoint(point22).direction(item.point), direct2 = line2.getAnotherPoint(item.point).direction(item.point), angle = direct1.angleBetween(direct2, "angle");
|
|
@@ -16981,22 +17224,22 @@ class DoorFind {
|
|
|
16981
17224
|
const d1 = item.point.direction(dock.point);
|
|
16982
17225
|
return d1.angleBetween(targetDirect, "angle") > 70;
|
|
16983
17226
|
}).filter((item) => {
|
|
16984
|
-
const line2 = item.userData, d1 =
|
|
16985
|
-
return d1.angleBetween(d2, "angle")
|
|
17227
|
+
const line2 = item.userData, d1 = item.point.direction(dock.point), d2 = line2.getAnotherPoint(item.point).direction(item.point), d3 = dock.dockPoint.direction(dock.dockLine.getAnotherPoint(dock.dockPoint));
|
|
17228
|
+
return d1.angleBetween(d2, "angle") < maxAngle && d3.angleBetween(d2, "angle") < maxAngle;
|
|
16986
17229
|
}).filter((item) => {
|
|
16987
|
-
const
|
|
16988
|
-
|
|
16989
|
-
return this.quadtree.queryLineSegment(
|
|
17230
|
+
const queryLine = new LineSegment(item.point.clone(), dock.point.clone());
|
|
17231
|
+
queryLine.startShrink(0.01).endShrink(1e-3);
|
|
17232
|
+
return this.quadtree.queryLineSegment(queryLine).length === 0;
|
|
16990
17233
|
}).filter((item) => {
|
|
16991
17234
|
return item.point.distance(dock.point) / length > 0.5;
|
|
16992
17235
|
}).filter((item) => {
|
|
16993
|
-
const
|
|
17236
|
+
const normal = item.point.normal(dock.point), center = new Point((item.point.x + dock.point.x) / 2, (item.point.y + dock.point.y) / 2), length2 = item.point.distance(dock.point);
|
|
16994
17237
|
const normalLine = new LineSegment(
|
|
16995
17238
|
center,
|
|
16996
|
-
center.clone().add(
|
|
17239
|
+
center.clone().add(normal.clone().multiplyScalar(length2))
|
|
16997
17240
|
);
|
|
16998
|
-
normalLine.directionMove(
|
|
16999
|
-
const results = this.quadtree.queryLineSegment(normalLine).filter((
|
|
17241
|
+
normalLine.directionMove(normal, -length2 * 0.5);
|
|
17242
|
+
const results = this.quadtree.queryLineSegment(normalLine).filter((result) => result.line !== line && result.line !== dock.dockLine);
|
|
17000
17243
|
return results.length === 0;
|
|
17001
17244
|
}).sort((a2, b4) => {
|
|
17002
17245
|
return getWeight(b4, dock, length) - getWeight(a2, dock, length);
|
|
@@ -17010,6 +17253,10 @@ class DoorFind {
|
|
|
17010
17253
|
}
|
|
17011
17254
|
return point2;
|
|
17012
17255
|
}
|
|
17256
|
+
return this.extendLink(dock, line);
|
|
17257
|
+
}
|
|
17258
|
+
extendLink(dock, line) {
|
|
17259
|
+
const length = line.length();
|
|
17013
17260
|
const direct = dock.dockPoint.direction(dock.dockLine.getAnotherPoint(dock.dockPoint)), queryLine = new LineSegment(
|
|
17014
17261
|
dock.dockPoint,
|
|
17015
17262
|
dock.dockPoint.clone().add(direct.multiplyScalar(length * 2))
|
|
@@ -17526,6 +17773,139 @@ class CorrectionDxf extends Dxf {
|
|
|
17526
17773
|
return this.rotateCorrCad?.downloadDxf(filename, unit);
|
|
17527
17774
|
}
|
|
17528
17775
|
}
|
|
17776
|
+
function getGroups(lines, updateGroup = true) {
|
|
17777
|
+
if (updateGroup) lines = DoubleWallHelper.buildGroup(lines);
|
|
17778
|
+
const map = lines.reduce((map2, line) => {
|
|
17779
|
+
const groups = LineGroupType.get(line);
|
|
17780
|
+
groups.forEach((group2) => {
|
|
17781
|
+
let id = group2.id ?? "wall";
|
|
17782
|
+
if (group2.type === "wall") id = "wall";
|
|
17783
|
+
map2.append(id, line);
|
|
17784
|
+
});
|
|
17785
|
+
return map2;
|
|
17786
|
+
}, new ArrayMap());
|
|
17787
|
+
return map;
|
|
17788
|
+
}
|
|
17789
|
+
function handleGroup(map) {
|
|
17790
|
+
const group2 = map.group((lines) => {
|
|
17791
|
+
if (LineGroupType.everyType(lines, "bayWindow")) return "wall";
|
|
17792
|
+
if (LineGroupType.everyType(lines, "doubleWall")) return "doubleWall";
|
|
17793
|
+
return "wall";
|
|
17794
|
+
}), walls = group2.get("wall") ?? [], doubleWalls = group2.get("doubleWall") ?? [];
|
|
17795
|
+
let newlines = [], doubleWallsSet = new Set(doubleWalls.flat());
|
|
17796
|
+
walls.forEach((lines) => {
|
|
17797
|
+
lines.forEach((line) => doubleWallsSet.has(line) || newlines.push(line));
|
|
17798
|
+
});
|
|
17799
|
+
doubleWalls.forEach((lines) => {
|
|
17800
|
+
lines = [...new Set(lines)];
|
|
17801
|
+
const groups = clippingDoubleWall(lines);
|
|
17802
|
+
groups.forEach((lines2) => {
|
|
17803
|
+
if (lines2.length < 4) return newlines.push(...lines2);
|
|
17804
|
+
lines2 = lines2.sort((a2, b4) => a2.length() - b4.length());
|
|
17805
|
+
const line1 = lines2[0], line2 = lines2[1];
|
|
17806
|
+
const newLine = new LineSegment(line1.center.clone(), line2.center.clone());
|
|
17807
|
+
mergeLineUserData(newLine, lines2);
|
|
17808
|
+
newLine.userData.wallWidth = line1.length();
|
|
17809
|
+
newlines.push(newLine);
|
|
17810
|
+
mergeWindow(newLine);
|
|
17811
|
+
});
|
|
17812
|
+
});
|
|
17813
|
+
newlines = newlines.map((line) => line.clone());
|
|
17814
|
+
return newlines.filter((line) => !line.userData.isBayWindow);
|
|
17815
|
+
}
|
|
17816
|
+
function toJson(lineSegments, name = "测试", communityName = "") {
|
|
17817
|
+
const scale2 = 1, idMap = /* @__PURE__ */ new Map();
|
|
17818
|
+
let index2 = 0;
|
|
17819
|
+
return {
|
|
17820
|
+
version: "2",
|
|
17821
|
+
name,
|
|
17822
|
+
communityName,
|
|
17823
|
+
city: "",
|
|
17824
|
+
province: "",
|
|
17825
|
+
height: DEFAULT_WALL_HEIGHT * scale2,
|
|
17826
|
+
walls: lineSegments.map((line) => {
|
|
17827
|
+
if (line.userData.isDoor && !line.userData.doorDirectConnection) return;
|
|
17828
|
+
idMap.set(line, index2);
|
|
17829
|
+
return {
|
|
17830
|
+
ID: index2++,
|
|
17831
|
+
start: { x: line.start.x * scale2, y: line.start.y * scale2 },
|
|
17832
|
+
end: { x: line.end.x * scale2, y: line.end.y * scale2 },
|
|
17833
|
+
thickness: (line.userData.wallWidth ? line.userData.wallWidth : 0.12) * scale2,
|
|
17834
|
+
type: "LINE",
|
|
17835
|
+
isDoor: line.userData.isDoor,
|
|
17836
|
+
loadBearingWall: false,
|
|
17837
|
+
height: (line.userData.height ?? DEFAULT_WALL_HEIGHT) * scale2
|
|
17838
|
+
};
|
|
17839
|
+
}).filter((i) => !!i),
|
|
17840
|
+
pillars: [],
|
|
17841
|
+
beams: [],
|
|
17842
|
+
holes: lineSegments.flatMap((line) => {
|
|
17843
|
+
if (line.userData.isDoor && line.userData.doorDirectConnection) {
|
|
17844
|
+
return {
|
|
17845
|
+
id: index2++,
|
|
17846
|
+
type: "DOOR",
|
|
17847
|
+
openSide: "RIGHT",
|
|
17848
|
+
start: {
|
|
17849
|
+
x: line.start.x * scale2,
|
|
17850
|
+
y: line.start.y * scale2
|
|
17851
|
+
},
|
|
17852
|
+
end: {
|
|
17853
|
+
x: line.end.x * scale2,
|
|
17854
|
+
y: line.end.y * scale2
|
|
17855
|
+
},
|
|
17856
|
+
height: (line.userData.drawDoorData?.height ?? DEFAULT_DOOR_HEIGHT) * scale2,
|
|
17857
|
+
qroundClearance: (line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT) * scale2,
|
|
17858
|
+
sillHeight: (line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT) * scale2
|
|
17859
|
+
};
|
|
17860
|
+
} else if (line.userData.isWindow && line.userData.drawWindow) {
|
|
17861
|
+
return line.userData.drawWindow.map((item) => {
|
|
17862
|
+
const center = Point.from(item.p);
|
|
17863
|
+
const start = center.clone().add(
|
|
17864
|
+
line.direction().multiplyScalar(item.width * 0.5)
|
|
17865
|
+
);
|
|
17866
|
+
const end = center.clone().add(
|
|
17867
|
+
line.direction().multiplyScalar(-item.width * 0.5)
|
|
17868
|
+
);
|
|
17869
|
+
return {
|
|
17870
|
+
id: index2++,
|
|
17871
|
+
type: "WINDOW",
|
|
17872
|
+
start: {
|
|
17873
|
+
x: start.x * scale2,
|
|
17874
|
+
y: start.y * scale2
|
|
17875
|
+
},
|
|
17876
|
+
end: {
|
|
17877
|
+
x: end.x * scale2,
|
|
17878
|
+
y: end.y * scale2
|
|
17879
|
+
},
|
|
17880
|
+
height: (item.height ?? DEFAULT_WINDOW_HEIGHT) * scale2,
|
|
17881
|
+
groundClearance: (item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT) * scale2,
|
|
17882
|
+
sillHeight: (item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT) * scale2
|
|
17883
|
+
};
|
|
17884
|
+
});
|
|
17885
|
+
}
|
|
17886
|
+
}).filter((i) => !!i),
|
|
17887
|
+
rooms: []
|
|
17888
|
+
};
|
|
17889
|
+
}
|
|
17890
|
+
function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
|
|
17891
|
+
const group2 = getGroups(lineSegments, updateGroup);
|
|
17892
|
+
let newLines = handleGroup(group2);
|
|
17893
|
+
newLines = LineSegmentUndirectedGraph.rotate(newLines, angle, (line, center, angle2) => {
|
|
17894
|
+
if (line.userData.drawWindow) {
|
|
17895
|
+
line.userData.drawWindow.forEach((windowItem) => {
|
|
17896
|
+
const point2 = Point.from(windowItem.p);
|
|
17897
|
+
point2.rotate(center, angle2);
|
|
17898
|
+
windowItem.p = point2.toJson(windowItem.p.z);
|
|
17899
|
+
});
|
|
17900
|
+
}
|
|
17901
|
+
});
|
|
17902
|
+
return {
|
|
17903
|
+
lines: newLines,
|
|
17904
|
+
toJson(name = "测试", communityName = "") {
|
|
17905
|
+
return toJson(newLines, name, communityName);
|
|
17906
|
+
}
|
|
17907
|
+
};
|
|
17908
|
+
}
|
|
17529
17909
|
class ThreeVJia extends Component {
|
|
17530
17910
|
static name = "ThreeVJia";
|
|
17531
17911
|
lineSegments = [];
|
|
@@ -19743,6 +20123,7 @@ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
19743
20123
|
SelectLocalFile,
|
|
19744
20124
|
SetMap,
|
|
19745
20125
|
Side,
|
|
20126
|
+
ThreeVJiaJson,
|
|
19746
20127
|
UndirectedGraph,
|
|
19747
20128
|
UnionFindSet,
|
|
19748
20129
|
buildBayWindowGroup,
|
|
@@ -19758,7 +20139,7 @@ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
|
|
|
19758
20139
|
findVerticalReference,
|
|
19759
20140
|
gltf,
|
|
19760
20141
|
lineDataToOriginalData,
|
|
19761
|
-
lineDataToThreeVJiaJson,
|
|
20142
|
+
lineDataToThreeVJiaJson: lineDataToThreeVJiaJson$1,
|
|
19762
20143
|
lineSegmentClipping,
|
|
19763
20144
|
mergeLineUserData,
|
|
19764
20145
|
mergeWindow,
|
|
@@ -19931,7 +20312,7 @@ async function buildJson(opt) {
|
|
|
19931
20312
|
} else throw new Error("非node环境不允许使用路径");
|
|
19932
20313
|
}
|
|
19933
20314
|
}
|
|
19934
|
-
doorFind && (dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorFind), dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorSpaceHandle));
|
|
20315
|
+
doorFind && (dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorSpaceHandle), dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorFind), dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorSpaceHandle));
|
|
19935
20316
|
if (opt.axisAlignCorr !== false) dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
|
|
19936
20317
|
if (trajectory) {
|
|
19937
20318
|
if (typeof trajectory === "string") {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Component } from '../../ComponentManager';
|
|
2
2
|
import { LineSegment } from '../../LineSegment';
|
|
3
3
|
import { LineUserData } from '../type';
|
|
4
|
-
import { ThreeVJiaJsonObject } from '../utils/
|
|
4
|
+
import { ThreeVJiaJsonObject } from '../utils/lineDataToThreeVJiaJsonOld';
|
|
5
5
|
/**
|
|
6
6
|
* 转为 三维家 墙体结构
|
|
7
7
|
*/
|
|
@@ -23,6 +23,8 @@ export type WallLineGlobalOption = {
|
|
|
23
23
|
isBayWindow?: boolean;
|
|
24
24
|
/** 是不是飘窗墙壁 */
|
|
25
25
|
isWindowWall?: boolean;
|
|
26
|
+
/** 是不是阳台护栏 */
|
|
27
|
+
isBalconyRailing?: boolean;
|
|
26
28
|
/** 是不是门线 */
|
|
27
29
|
isDoor?: boolean;
|
|
28
30
|
doorAutomaticFind?: boolean;
|
|
@@ -70,6 +72,7 @@ export type WallLineGlobalOption = {
|
|
|
70
72
|
};
|
|
71
73
|
height: number;
|
|
72
74
|
groundClearance: number;
|
|
75
|
+
sillHeight?: number;
|
|
73
76
|
};
|
|
74
77
|
};
|
|
75
78
|
export type LineUserData = {
|
|
@@ -2,7 +2,7 @@ import { LineSegment } from '../../LineSegment';
|
|
|
2
2
|
import { LineUserData } from '../type';
|
|
3
3
|
import { Point } from '../../Point';
|
|
4
4
|
import * as THREE from "three";
|
|
5
|
-
interface IDrawBayWindowData {
|
|
5
|
+
export interface IDrawBayWindowData {
|
|
6
6
|
height1: number;
|
|
7
7
|
height2: number;
|
|
8
8
|
height3: number;
|
|
@@ -34,4 +34,3 @@ export declare class BayWindowHelper {
|
|
|
34
34
|
*/
|
|
35
35
|
static drawDataToModel(drawData: IDrawBayWindowData): THREE.Group<THREE.Object3DEventMap>;
|
|
36
36
|
}
|
|
37
|
-
export {};
|
|
@@ -65,7 +65,7 @@ export declare class CAD {
|
|
|
65
65
|
/** 添加组并执行偏移
|
|
66
66
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
67
67
|
*/
|
|
68
|
-
|
|
68
|
+
addGroupAndOffset(lines: LineSegmentType[], joinType?: JoinType, endType?: EndType, scale?: number): this;
|
|
69
69
|
/**
|
|
70
70
|
* 合并所有组
|
|
71
71
|
*/
|
|
@@ -132,7 +132,7 @@ export declare class CAD {
|
|
|
132
132
|
referenceLine: LineSegment<Record<string, any>>;
|
|
133
133
|
};
|
|
134
134
|
}
|
|
135
|
-
/** dxf
|
|
135
|
+
/** dxf 绘制插件
|
|
136
136
|
*/
|
|
137
137
|
export declare class DxfDrawPlugin implements ICADPlugin {
|
|
138
138
|
/** 获取角度范围
|
|
@@ -144,7 +144,7 @@ export declare class DxfDrawPlugin implements ICADPlugin {
|
|
|
144
144
|
private getArcAngleRange;
|
|
145
145
|
install(cad: CAD): void;
|
|
146
146
|
}
|
|
147
|
-
/** dxf
|
|
147
|
+
/** dxf 数据处理插件
|
|
148
148
|
*/
|
|
149
149
|
export declare class DxfDataPlugin implements ICADPlugin {
|
|
150
150
|
lines: LineSegment<LineUserData>[];
|
|
@@ -12,7 +12,9 @@ interface IDockInfo {
|
|
|
12
12
|
export declare class DoorFind {
|
|
13
13
|
lines: LineSegment[];
|
|
14
14
|
grid: PointVirtualGrid<LineSegment<LineUserData>>;
|
|
15
|
-
quadtree: Quadtree<
|
|
15
|
+
quadtree: Quadtree<{
|
|
16
|
+
index: number;
|
|
17
|
+
}>;
|
|
16
18
|
constructor(lines: LineSegment<LineUserData>[]);
|
|
17
19
|
/**
|
|
18
20
|
* 查找兄弟门(双开门)
|
|
@@ -36,6 +38,7 @@ export declare class DoorFind {
|
|
|
36
38
|
* @returns
|
|
37
39
|
*/
|
|
38
40
|
adsorpt(dock: IDockInfo, line: LineSegment, maxAngle?: number): Point<Record<string, any>> | null;
|
|
41
|
+
extendLink(dock: IDockInfo, line: LineSegment): Point<Record<string, any>> | null;
|
|
39
42
|
getLines(): LineSegment<Record<string, any>>[];
|
|
40
43
|
}
|
|
41
44
|
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LineSegment } from '../../LineSegment';
|
|
2
|
+
import { LineUserData } from '../type';
|
|
3
|
+
export interface IGroup<T = any> {
|
|
4
|
+
type: string;
|
|
5
|
+
lines: LineSegment<LineUserData>[];
|
|
6
|
+
data?: T;
|
|
7
|
+
}
|
|
8
|
+
export declare class WallGroupManager {
|
|
9
|
+
[Symbol.iterator](): ArrayIterator<IGroup<any>>;
|
|
10
|
+
private groups;
|
|
11
|
+
add(group: IGroup): void;
|
|
12
|
+
static fromByLines(lineSegments: LineSegment[]): WallGroupManager;
|
|
13
|
+
forEach(fun: (group: IGroup, index: number) => void): void;
|
|
14
|
+
map<T = any>(fun: (group: IGroup, index: number) => T): T[];
|
|
15
|
+
}
|
|
@@ -1,20 +1,32 @@
|
|
|
1
1
|
import { LineSegment } from '../../LineSegment';
|
|
2
2
|
import { LineUserData } from '../type';
|
|
3
|
-
import {
|
|
3
|
+
import { IDrawBayWindowData } from './BayWindowHelper';
|
|
4
|
+
import { WallGroupManager, IGroup } from './WallGroupManager';
|
|
5
|
+
import { HandlerFlow } from '../../HandlerFlow';
|
|
6
|
+
type Vec2 = {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
4
10
|
type Hole = {
|
|
5
11
|
id: number;
|
|
6
|
-
type: "DOOR" | "WINDOW";
|
|
7
|
-
start:
|
|
8
|
-
end:
|
|
9
|
-
height
|
|
12
|
+
type: "DOOR" | "WINDOW" | "BAY_WINDOW";
|
|
13
|
+
start: Vec2;
|
|
14
|
+
end: Vec2;
|
|
15
|
+
height?: number;
|
|
10
16
|
groundClearance?: number;
|
|
11
|
-
sillHeight
|
|
17
|
+
sillHeight?: number;
|
|
12
18
|
openSide?: "RIGHT" | "LEFT" | "UP" | "DOWN";
|
|
19
|
+
height1?: number;
|
|
20
|
+
height2?: number;
|
|
21
|
+
height3?: number;
|
|
22
|
+
depth?: number;
|
|
23
|
+
windowWidth?: number;
|
|
24
|
+
windowHeight?: number;
|
|
13
25
|
};
|
|
14
26
|
type Wall = {
|
|
15
27
|
ID: number;
|
|
16
|
-
start:
|
|
17
|
-
end:
|
|
28
|
+
start: Vec2;
|
|
29
|
+
end: Vec2;
|
|
18
30
|
thickness: number;
|
|
19
31
|
type: "LINE";
|
|
20
32
|
isDoor: boolean;
|
|
@@ -35,6 +47,40 @@ export type ThreeVJiaJsonObject = {
|
|
|
35
47
|
holes: Hole[];
|
|
36
48
|
rooms: Room[];
|
|
37
49
|
};
|
|
50
|
+
export declare class ThreeVJiaJson extends HandlerFlow<ThreeVJiaJsonObject> {
|
|
51
|
+
manager: WallGroupManager;
|
|
52
|
+
index: number;
|
|
53
|
+
constructor(lines: LineSegment[]);
|
|
54
|
+
/** 双线墙处理
|
|
55
|
+
* @param param0
|
|
56
|
+
* @returns
|
|
57
|
+
*/
|
|
58
|
+
doubleWallHandle({ lines }: IGroup): LineSegment<Record<string, any>>[];
|
|
59
|
+
/**
|
|
60
|
+
* 单线墙处理
|
|
61
|
+
* @param param0
|
|
62
|
+
*/
|
|
63
|
+
wallHandle({ lines }: IGroup): LineSegment<LineUserData>[];
|
|
64
|
+
/**
|
|
65
|
+
* 门线处理
|
|
66
|
+
* @param param0
|
|
67
|
+
*/
|
|
68
|
+
doorHandle({ lines }: IGroup, option?: ThreeVJiaJsonObject): never[];
|
|
69
|
+
/**
|
|
70
|
+
* 窗线处理
|
|
71
|
+
* @param param0
|
|
72
|
+
*/
|
|
73
|
+
windowHandle({ lines }: IGroup, option?: ThreeVJiaJsonObject): LineSegment<LineUserData>[];
|
|
74
|
+
/** 飘窗处理
|
|
75
|
+
* @param data
|
|
76
|
+
* @returns
|
|
77
|
+
*/
|
|
78
|
+
bayWindowHandle({ lines, data }: IGroup<IDrawBayWindowData>, option?: ThreeVJiaJsonObject): never[];
|
|
79
|
+
/** 装换
|
|
80
|
+
* @returns
|
|
81
|
+
*/
|
|
82
|
+
transform(): ThreeVJiaJsonObject;
|
|
83
|
+
}
|
|
38
84
|
/**
|
|
39
85
|
* 转为 三维家 墙体结构
|
|
40
86
|
* @param lineSegments
|
|
@@ -42,8 +88,8 @@ export type ThreeVJiaJsonObject = {
|
|
|
42
88
|
* @param updateGroup
|
|
43
89
|
* @returns
|
|
44
90
|
*/
|
|
45
|
-
export declare function lineDataToThreeVJiaJson(lineSegments: LineSegment[], angle?: number, updateGroup?: boolean): {
|
|
46
|
-
lines:
|
|
91
|
+
export declare function lineDataToThreeVJiaJson(lineSegments: LineSegment<LineUserData>[], angle?: number, updateGroup?: boolean): {
|
|
92
|
+
lines: never[];
|
|
47
93
|
toJson(name?: string, communityName?: string): ThreeVJiaJsonObject;
|
|
48
94
|
};
|
|
49
95
|
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { LineSegment } from '../../LineSegment';
|
|
2
|
+
import { LineUserData } from '../type';
|
|
3
|
+
type Vec2 = {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
};
|
|
7
|
+
type Hole = {
|
|
8
|
+
id: number;
|
|
9
|
+
type: "DOOR" | "WINDOW";
|
|
10
|
+
start: Vec2;
|
|
11
|
+
end: Vec2;
|
|
12
|
+
height: number;
|
|
13
|
+
groundClearance?: number;
|
|
14
|
+
sillHeight: number;
|
|
15
|
+
openSide?: "RIGHT" | "LEFT" | "UP" | "DOWN";
|
|
16
|
+
};
|
|
17
|
+
type Wall = {
|
|
18
|
+
ID: number;
|
|
19
|
+
start: Vec2;
|
|
20
|
+
end: Vec2;
|
|
21
|
+
thickness: number;
|
|
22
|
+
type: "LINE";
|
|
23
|
+
isDoor: boolean;
|
|
24
|
+
loadBearingWall: boolean;
|
|
25
|
+
height: number;
|
|
26
|
+
};
|
|
27
|
+
type Room = {};
|
|
28
|
+
export type ThreeVJiaJsonObject = {
|
|
29
|
+
version: string;
|
|
30
|
+
name: string;
|
|
31
|
+
communityName: string;
|
|
32
|
+
city: string;
|
|
33
|
+
province: string;
|
|
34
|
+
height: number;
|
|
35
|
+
walls: Wall[];
|
|
36
|
+
pillars: any[];
|
|
37
|
+
beams: any[];
|
|
38
|
+
holes: Hole[];
|
|
39
|
+
rooms: Room[];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* 转为 三维家 墙体结构
|
|
43
|
+
* @param lineSegments
|
|
44
|
+
* @param angle 弧度
|
|
45
|
+
* @param updateGroup
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
export declare function lineDataToThreeVJiaJson(lineSegments: LineSegment<LineUserData>[], angle?: number, updateGroup?: boolean): {
|
|
49
|
+
lines: LineSegment<LineUserData>[];
|
|
50
|
+
toJson(name?: string, communityName?: string): ThreeVJiaJsonObject;
|
|
51
|
+
};
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ArrayMap } from './Map';
|
|
2
|
+
export interface IHandler<T = any> {
|
|
3
|
+
type: string;
|
|
4
|
+
handle: (data: any, option?: T) => any;
|
|
5
|
+
}
|
|
6
|
+
export declare class HandlerFlow<T = any> {
|
|
7
|
+
handlerMap: ArrayMap<string, IHandler<T>>;
|
|
8
|
+
addHandler(handler: IHandler<T>): void;
|
|
9
|
+
handle(type: string, data: any, option?: T): any;
|
|
10
|
+
}
|
package/src/utils/Point.d.ts
CHANGED
|
@@ -67,10 +67,7 @@ export declare class PointVirtualGrid<T = Record<string, any>> {
|
|
|
67
67
|
* @param radius 半径
|
|
68
68
|
* @returns 相交的节点数组
|
|
69
69
|
*/
|
|
70
|
-
queryCircle(pos: Point, radius: number, excludeOneself?: boolean):
|
|
71
|
-
point: Point;
|
|
72
|
-
userData?: T;
|
|
73
|
-
}[];
|
|
70
|
+
queryCircle(pos: Point, radius: number, excludeOneself?: boolean): PvgList<T>;
|
|
74
71
|
/**
|
|
75
72
|
* 查询与包围盒相交的点
|
|
76
73
|
* @param box2 包围盒
|