build-dxf 0.1.60 → 0.1.61
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 +286 -181
- package/src/utils/DxfSystem/utils/BayWindowHelper.d.ts +13 -0
- package/src/utils/DxfSystem/utils/CAD.d.ts +7 -1
- package/src/utils/DxfSystem/utils/LineGroupType.d.ts +7 -1
- package/src/utils/DxfSystem/utils/WallGroupManager.d.ts +11 -1
- package/src/utils/DxfSystem/utils/lineDataToThreeVJiaJson.d.ts +6 -0
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -5143,8 +5143,8 @@ class LineGroupType {
|
|
|
5143
5143
|
* @param type
|
|
5144
5144
|
* @returns
|
|
5145
5145
|
*/
|
|
5146
|
-
static set(line, id, type) {
|
|
5147
|
-
if (this.hasId(line, id) || this.hasType(line, type)) return;
|
|
5146
|
+
static set(line, id, type, repeat = false) {
|
|
5147
|
+
if (this.hasId(line, id) || !repeat && this.hasType(line, type)) return;
|
|
5148
5148
|
if (typeof line.userData.groupId === "undefined") {
|
|
5149
5149
|
line.userData.groupId = id;
|
|
5150
5150
|
line.userData.groupType = type;
|
|
@@ -5162,14 +5162,27 @@ class LineGroupType {
|
|
|
5162
5162
|
if (line.userData.groupType == type) return line.userData.groupId;
|
|
5163
5163
|
return line.userData?.groups?.find((item) => item.type === type)?.id;
|
|
5164
5164
|
}
|
|
5165
|
+
/** 通过类型获取所有id
|
|
5166
|
+
* @param line
|
|
5167
|
+
* @param type
|
|
5168
|
+
* @returns
|
|
5169
|
+
*/
|
|
5170
|
+
static getIdsByType(line, type) {
|
|
5171
|
+
const ids = [];
|
|
5172
|
+
if (line.userData.groupType == type) ids.push(line.userData.groupId);
|
|
5173
|
+
line.userData?.groups?.forEach((group2) => {
|
|
5174
|
+
group2.type === type && ids.push(group2.id);
|
|
5175
|
+
});
|
|
5176
|
+
return ids;
|
|
5177
|
+
}
|
|
5165
5178
|
/** 通过类型获取所有组
|
|
5166
5179
|
* @param lines
|
|
5167
5180
|
* @param type
|
|
5168
5181
|
*/
|
|
5169
5182
|
static getGroupsByType(lines, type) {
|
|
5170
5183
|
return lines.reduce((map, line) => {
|
|
5171
|
-
const
|
|
5172
|
-
if (id) map.append(id, line);
|
|
5184
|
+
const ids = LineGroupType.getIdsByType(line, type);
|
|
5185
|
+
if (ids) ids.forEach((id) => map.append(id, line));
|
|
5173
5186
|
return map;
|
|
5174
5187
|
}, new ArrayMap()).valueArray;
|
|
5175
5188
|
}
|
|
@@ -5328,7 +5341,7 @@ class LineGroupType {
|
|
|
5328
5341
|
}
|
|
5329
5342
|
const groups = line.userData?.groups;
|
|
5330
5343
|
if (groups) {
|
|
5331
|
-
for (let i =
|
|
5344
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
5332
5345
|
const element = groups[i];
|
|
5333
5346
|
if (element.type === type) {
|
|
5334
5347
|
groups.splice(i, 1);
|
|
@@ -6105,6 +6118,212 @@ function getWinDrawData(doubleWallGroup, wall, lines = []) {
|
|
|
6105
6118
|
});
|
|
6106
6119
|
return windows;
|
|
6107
6120
|
}
|
|
6121
|
+
function createGeometry(points, options) {
|
|
6122
|
+
points = points.map((p2) => p2 instanceof Point ? new THREE.Vector2(p2.x, p2.y) : p2);
|
|
6123
|
+
const shape = new THREE.Shape(points);
|
|
6124
|
+
const extrudeGeometry = new THREE.ExtrudeGeometry(shape, {
|
|
6125
|
+
bevelEnabled: false,
|
|
6126
|
+
...options
|
|
6127
|
+
});
|
|
6128
|
+
return extrudeGeometry;
|
|
6129
|
+
}
|
|
6130
|
+
class ExtrudeMesh extends THREE.Mesh {
|
|
6131
|
+
geometry;
|
|
6132
|
+
options;
|
|
6133
|
+
constructor(points, options, material) {
|
|
6134
|
+
const geometry = createGeometry(points, options);
|
|
6135
|
+
super(geometry, material);
|
|
6136
|
+
this.geometry = geometry;
|
|
6137
|
+
this.options = options;
|
|
6138
|
+
}
|
|
6139
|
+
setPoints(points, options = this.options) {
|
|
6140
|
+
const geometry = createGeometry(points, options);
|
|
6141
|
+
this.geometry = geometry;
|
|
6142
|
+
}
|
|
6143
|
+
}
|
|
6144
|
+
class BayWindowHelper {
|
|
6145
|
+
/** 获取绘制数据
|
|
6146
|
+
* @param lines
|
|
6147
|
+
* @returns
|
|
6148
|
+
*/
|
|
6149
|
+
static getDrawData(lines) {
|
|
6150
|
+
lines = LineSegmentUndirectedGraph.breakpointMerging(lines.map((line) => line.clone()), mergeLineUserData);
|
|
6151
|
+
if (lines.length === 4) {
|
|
6152
|
+
let bayWindowLine = null;
|
|
6153
|
+
let windowLine = null;
|
|
6154
|
+
let deptLine = null;
|
|
6155
|
+
for (let i = 0; i < lines.length; i++) {
|
|
6156
|
+
const line = lines[i];
|
|
6157
|
+
if (line.userData.isBayWindow) bayWindowLine = line;
|
|
6158
|
+
else if (line.userData.isWindow && line.userData.drawWindow) windowLine = line;
|
|
6159
|
+
else deptLine = line;
|
|
6160
|
+
}
|
|
6161
|
+
if (bayWindowLine && windowLine && deptLine) {
|
|
6162
|
+
const { width, height, groundClearance } = windowLine.userData.drawWindow[0];
|
|
6163
|
+
const direction = Point.zero();
|
|
6164
|
+
if (deptLine.sameEndpointAsEnd(bayWindowLine)) {
|
|
6165
|
+
deptLine.start.direction(deptLine.end, direction);
|
|
6166
|
+
} else {
|
|
6167
|
+
deptLine.end.direction(deptLine.start, direction);
|
|
6168
|
+
}
|
|
6169
|
+
return {
|
|
6170
|
+
height1: bayWindowLine.userData.topClearance ?? 0,
|
|
6171
|
+
height2: height,
|
|
6172
|
+
height3: groundClearance,
|
|
6173
|
+
depth: deptLine.length(),
|
|
6174
|
+
windowWidth: width,
|
|
6175
|
+
windowHeight: height,
|
|
6176
|
+
bayWindowLine,
|
|
6177
|
+
windowLine,
|
|
6178
|
+
deptLine,
|
|
6179
|
+
direction
|
|
6180
|
+
};
|
|
6181
|
+
}
|
|
6182
|
+
}
|
|
6183
|
+
return null;
|
|
6184
|
+
}
|
|
6185
|
+
/** 获取绘制数据
|
|
6186
|
+
* @param lines
|
|
6187
|
+
* @returns
|
|
6188
|
+
*/
|
|
6189
|
+
static getDrawData2(lines) {
|
|
6190
|
+
lines = LineSegmentUndirectedGraph.breakpointMerging(lines.map((line) => line.clone()), mergeLineUserData);
|
|
6191
|
+
let bayWindowLine = null;
|
|
6192
|
+
let windowLine = null;
|
|
6193
|
+
for (let i = 0; i < lines.length; i++) {
|
|
6194
|
+
const line = lines[i];
|
|
6195
|
+
if (line.userData.isBayWindow) bayWindowLine = line;
|
|
6196
|
+
else if (line.userData.isWindow && line.userData.drawWindow) windowLine = line;
|
|
6197
|
+
}
|
|
6198
|
+
if (bayWindowLine && windowLine) {
|
|
6199
|
+
const { width, height, groundClearance } = windowLine.userData.drawWindow[0];
|
|
6200
|
+
const direction = Point.zero();
|
|
6201
|
+
return {
|
|
6202
|
+
height1: bayWindowLine.userData.topClearance ?? 0,
|
|
6203
|
+
height2: height,
|
|
6204
|
+
height3: groundClearance,
|
|
6205
|
+
windowWidth: width,
|
|
6206
|
+
windowHeight: height,
|
|
6207
|
+
direction
|
|
6208
|
+
};
|
|
6209
|
+
}
|
|
6210
|
+
return null;
|
|
6211
|
+
}
|
|
6212
|
+
/** 获取所有绘制数据
|
|
6213
|
+
* @param lineSegments
|
|
6214
|
+
* @returns
|
|
6215
|
+
*/
|
|
6216
|
+
static getDrawDataAll(lineSegments) {
|
|
6217
|
+
const groups = LineGroupType.getGroupsByType(lineSegments, "bayWindow");
|
|
6218
|
+
const drawDataList = groups.map(this.getDrawData);
|
|
6219
|
+
return groups.map((group2, indxe) => ({
|
|
6220
|
+
group: group2,
|
|
6221
|
+
drawData: drawDataList[indxe]
|
|
6222
|
+
})).filter((item) => item.drawData);
|
|
6223
|
+
}
|
|
6224
|
+
/** 绘制数据转模型
|
|
6225
|
+
* @param drawData
|
|
6226
|
+
* @returns
|
|
6227
|
+
*/
|
|
6228
|
+
static drawDataToModel(drawData) {
|
|
6229
|
+
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 });
|
|
6230
|
+
winGroup.position.set(pos.x, pos.y, 0);
|
|
6231
|
+
const rectangle = bayWindowLine.expandToRectangle(DEFAULT_WALL_WIDTH), extrudeMesh = new ExtrudeMesh(rectangle.points, { depth: drawData.height3 }, material);
|
|
6232
|
+
winGroup.add(extrudeMesh);
|
|
6233
|
+
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 }));
|
|
6234
|
+
extrudeMesh2.position.z = drawData.height3;
|
|
6235
|
+
winGroup.add(extrudeMesh2);
|
|
6236
|
+
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);
|
|
6237
|
+
extrudeMesh3.position.z = drawData.height3;
|
|
6238
|
+
winGroup.add(extrudeMesh3);
|
|
6239
|
+
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);
|
|
6240
|
+
extrudeMesh4.position.z = drawData.height3;
|
|
6241
|
+
winGroup.add(extrudeMesh4);
|
|
6242
|
+
const extrudeMesh5 = new ExtrudeMesh(rectangle.points, { depth: drawData.height1 }, material);
|
|
6243
|
+
extrudeMesh5.position.z = drawData.height3 + drawData.height2;
|
|
6244
|
+
winGroup.add(extrudeMesh5);
|
|
6245
|
+
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);
|
|
6246
|
+
extrudeMesh6.position.z = drawData.height3;
|
|
6247
|
+
winGroup.add(extrudeMesh6);
|
|
6248
|
+
const extrudeMesh7 = new ExtrudeMesh(rectangle6.points, { depth: 1e-3 }, material);
|
|
6249
|
+
extrudeMesh7.position.z = drawData.height3 + drawData.height2;
|
|
6250
|
+
winGroup.add(extrudeMesh7);
|
|
6251
|
+
return winGroup;
|
|
6252
|
+
}
|
|
6253
|
+
}
|
|
6254
|
+
class WallGroupManager {
|
|
6255
|
+
[Symbol.iterator]() {
|
|
6256
|
+
return this.groups[Symbol.iterator]();
|
|
6257
|
+
}
|
|
6258
|
+
groups = [];
|
|
6259
|
+
add(group2) {
|
|
6260
|
+
this.groups.push(group2);
|
|
6261
|
+
}
|
|
6262
|
+
forEach(fun) {
|
|
6263
|
+
for (let i = 0; i < this.groups.length; i++) {
|
|
6264
|
+
fun(this.groups[i], i);
|
|
6265
|
+
}
|
|
6266
|
+
}
|
|
6267
|
+
map(fun) {
|
|
6268
|
+
const list = [];
|
|
6269
|
+
for (let i = 0; i < this.groups.length; i++) {
|
|
6270
|
+
list.push(fun(this.groups[i], i));
|
|
6271
|
+
}
|
|
6272
|
+
return list;
|
|
6273
|
+
}
|
|
6274
|
+
/** 查找符合条件的组
|
|
6275
|
+
* @param fun
|
|
6276
|
+
* @returns
|
|
6277
|
+
*/
|
|
6278
|
+
findGroup(fun) {
|
|
6279
|
+
for (let i = 0; i < this.groups.length; i++) {
|
|
6280
|
+
const group2 = this.groups[i];
|
|
6281
|
+
if (fun(group2)) return group2;
|
|
6282
|
+
}
|
|
6283
|
+
}
|
|
6284
|
+
/** 查找所有符合条件的组
|
|
6285
|
+
* @param fun
|
|
6286
|
+
* @returns
|
|
6287
|
+
*/
|
|
6288
|
+
findGroups(fun) {
|
|
6289
|
+
const list = [];
|
|
6290
|
+
for (let i = 0; i < this.groups.length; i++) {
|
|
6291
|
+
const group2 = this.groups[i];
|
|
6292
|
+
if (fun(group2)) list.push(group2);
|
|
6293
|
+
}
|
|
6294
|
+
return list;
|
|
6295
|
+
}
|
|
6296
|
+
static fromByLines(lineSegments) {
|
|
6297
|
+
const wallGroupManager = new WallGroupManager();
|
|
6298
|
+
const removeLines = [];
|
|
6299
|
+
BayWindowHelper.getDrawDataAll(lineSegments).forEach(({ group: group2, drawData }) => {
|
|
6300
|
+
wallGroupManager.add({
|
|
6301
|
+
type: "bayWindow",
|
|
6302
|
+
lines: group2,
|
|
6303
|
+
data: drawData
|
|
6304
|
+
});
|
|
6305
|
+
removeLines.push(...group2);
|
|
6306
|
+
});
|
|
6307
|
+
const doors = lineSegments.filter((line) => line.userData.isDoor);
|
|
6308
|
+
wallGroupManager.add({ type: "door", lines: doors });
|
|
6309
|
+
removeLines.push(...doors);
|
|
6310
|
+
const doubleWalls = LineGroupType.getGroupsByType(lineSegments, "doubleWall");
|
|
6311
|
+
doubleWalls.forEach((doubleWall) => {
|
|
6312
|
+
wallGroupManager.add({ type: "doubleWall", lines: doubleWall });
|
|
6313
|
+
removeLines.push(...doubleWall);
|
|
6314
|
+
});
|
|
6315
|
+
const set2 = new Set(removeLines), walls = [], windowLines = [], balconyRailingLines = [];
|
|
6316
|
+
lineSegments.filter((line) => !set2.has(line)).forEach((line) => {
|
|
6317
|
+
if (line.userData.isWindow) windowLines.push(line);
|
|
6318
|
+
else if (line.userData.isBalconyRailing) balconyRailingLines.push(line);
|
|
6319
|
+
else walls.push(line);
|
|
6320
|
+
});
|
|
6321
|
+
walls.length && wallGroupManager.add({ type: "wall", lines: walls });
|
|
6322
|
+
windowLines.length && wallGroupManager.add({ type: "window", lines: windowLines });
|
|
6323
|
+
balconyRailingLines.length && wallGroupManager.add({ type: "balconyRailing", lines: balconyRailingLines });
|
|
6324
|
+
return wallGroupManager;
|
|
6325
|
+
}
|
|
6326
|
+
}
|
|
6108
6327
|
class Group {
|
|
6109
6328
|
type = "";
|
|
6110
6329
|
userData = { color: "#fff" };
|
|
@@ -6210,7 +6429,14 @@ class CAD {
|
|
|
6210
6429
|
/** 添加组并执行偏移
|
|
6211
6430
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
6212
6431
|
*/
|
|
6213
|
-
addGroupAndOffset(lines,
|
|
6432
|
+
addGroupAndOffset(lines, option) {
|
|
6433
|
+
const {
|
|
6434
|
+
offsetHalfWidth = DEFAULT_WALL_WIDTH * 0.5,
|
|
6435
|
+
joinType = "jtMiter",
|
|
6436
|
+
endType = "etOpenButt",
|
|
6437
|
+
groupName = "groupOffset",
|
|
6438
|
+
scale: scale2 = 1e5
|
|
6439
|
+
} = option ?? {};
|
|
6214
6440
|
const groups = LineSegment.groupByPoint(lines);
|
|
6215
6441
|
const polygons = groups.flatMap((group2) => Polygon.multipleFromByLines(group2));
|
|
6216
6442
|
const offset2 = new ClipperLib.ClipperOffset(2, 0.25);
|
|
@@ -6224,13 +6450,13 @@ class CAD {
|
|
|
6224
6450
|
ClipperLib.EndType[endType]
|
|
6225
6451
|
);
|
|
6226
6452
|
}
|
|
6227
|
-
offset2.Execute(solutions,
|
|
6453
|
+
offset2.Execute(solutions, offsetHalfWidth * scale2);
|
|
6228
6454
|
solutions = solutions.map((solution) => solution.map((p2) => Point.from(p2).multiplyScalar(1 / scale2)));
|
|
6229
6455
|
solutions.forEach((solution) => {
|
|
6230
6456
|
const polygon2 = new Polygon(solution);
|
|
6231
6457
|
const lines2 = LineSegment.brokenLineMerging(polygon2.toLines(true), mergeLineUserData);
|
|
6232
6458
|
Point.adsorb(lines2.flatMap((line) => line.points));
|
|
6233
|
-
this.addGroup(lines2,
|
|
6459
|
+
this.addGroup(lines2, groupName, { polygon: polygon2 });
|
|
6234
6460
|
});
|
|
6235
6461
|
this.needUpdate = true;
|
|
6236
6462
|
return this;
|
|
@@ -6717,6 +6943,15 @@ class DxfDrawPlugin {
|
|
|
6717
6943
|
});
|
|
6718
6944
|
}
|
|
6719
6945
|
});
|
|
6946
|
+
cad.addDrawHandler({
|
|
6947
|
+
type: ["balconyRailing"],
|
|
6948
|
+
handler({ group: group2, setColor, drawLine }) {
|
|
6949
|
+
group2.lines.forEach((line) => {
|
|
6950
|
+
setColor("green");
|
|
6951
|
+
drawLine(line.start, line.end);
|
|
6952
|
+
});
|
|
6953
|
+
}
|
|
6954
|
+
});
|
|
6720
6955
|
}
|
|
6721
6956
|
}
|
|
6722
6957
|
class DxfDataPlugin {
|
|
@@ -6728,17 +6963,9 @@ class DxfDataPlugin {
|
|
|
6728
6963
|
* @param cad
|
|
6729
6964
|
*/
|
|
6730
6965
|
static initData(cad, lines) {
|
|
6731
|
-
const
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
if (line.userData.isDoor) doors.push(line);
|
|
6735
|
-
else if (line.userData.isBayWindow) bayWindows.push(line);
|
|
6736
|
-
else if (LineGroupType.hasType(line, "doubleWall")) doubleWall.push(line);
|
|
6737
|
-
else wall.push(line);
|
|
6738
|
-
}
|
|
6739
|
-
const doubleWallGroup = LineGroupType.getGroupsByType(doubleWall, "doubleWall"), windows = getWinDrawData(doubleWallGroup, wall, lineSegments);
|
|
6740
|
-
const quadtree = createQuadtree([...wall, ...doubleWall]);
|
|
6741
|
-
doors.forEach((line) => {
|
|
6966
|
+
const wallGroupManager = WallGroupManager.fromByLines(lines), doubleWallGroups = wallGroupManager.findGroups((group2) => group2.type === "doubleWall"), balconyRailingGroups = wallGroupManager.findGroups((group2) => group2.type === "balconyRailing"), doorGroups = wallGroupManager.findGroups((group2) => group2.type === "door"), jointGroups = wallGroupManager.findGroups((group2) => group2.type === "wall" || group2.type === "bayWindow" || group2.type === "window"), doubleWalls = doubleWallGroups.map((group2) => group2.lines), jointLines = jointGroups.map((group2) => group2.lines).flat(2), { bayWindowLines, wallLines } = jointLines.reduce((opt, line) => (line.userData.isBayWindow ? opt.bayWindowLines.push(line) : opt.wallLines.push(line), opt), { bayWindowLines: [], wallLines: [] }), doorLines = doorGroups.map((group2) => group2.lines).flat(2), balconyRailingLines = balconyRailingGroups.map((group2) => group2.lines).flat(2), windowLines = getWinDrawData(doubleWalls, wallLines, lines);
|
|
6967
|
+
const quadtree = createQuadtree([...wallLines, ...doubleWalls.flat(2)]);
|
|
6968
|
+
[...doorLines, ...balconyRailingLines].forEach((line) => {
|
|
6742
6969
|
const startList = quadtree.queryPoint(line.start).filter((item) => item.line !== line && item.line.vertical(line, 35)), endList = quadtree.queryPoint(line.end).filter((item) => item.line !== line && item.line.vertical(line, 35)), direct = line.direction();
|
|
6743
6970
|
if (startList.length && !startList.some((item) => LineGroupType.hasType(item.line, "doubleWall"))) {
|
|
6744
6971
|
line.start.add(direct.clone().multiplyScalar(DEFAULT_WALL_WIDTH * 0.5));
|
|
@@ -6747,12 +6974,27 @@ class DxfDataPlugin {
|
|
|
6747
6974
|
line.end.add(direct.clone().multiplyScalar(-DEFAULT_WALL_WIDTH * 0.5));
|
|
6748
6975
|
}
|
|
6749
6976
|
});
|
|
6750
|
-
cad.addGroupAndOffset(
|
|
6751
|
-
cad.addGroups(
|
|
6977
|
+
cad.addGroupAndOffset(wallLines);
|
|
6978
|
+
cad.addGroups(doubleWalls, "doubleWall");
|
|
6752
6979
|
cad.unionGroupAll();
|
|
6753
|
-
|
|
6754
|
-
cad.
|
|
6755
|
-
|
|
6980
|
+
const offsetWidth = 0.05;
|
|
6981
|
+
cad.addGroupAndOffset(balconyRailingLines, {
|
|
6982
|
+
offsetHalfWidth: offsetWidth * 0.5,
|
|
6983
|
+
groupName: "balconyRailing"
|
|
6984
|
+
});
|
|
6985
|
+
cad.addGroup(
|
|
6986
|
+
balconyRailingLines.flatMap((line) => {
|
|
6987
|
+
const dirct = line.normal(), removeDirct = line.direction(), length = line.length(), newLine = line.start.expandAsLine(dirct, offsetWidth).directionMove(dirct.multiplyScalar(-1), offsetWidth * 0.5), distance2 = length / 4, count = Math.floor(length / distance2), lines2 = [];
|
|
6988
|
+
for (let i = 1; i <= count; i++) {
|
|
6989
|
+
lines2.push(newLine.clone().directionMove(removeDirct, i * distance2));
|
|
6990
|
+
}
|
|
6991
|
+
return lines2;
|
|
6992
|
+
}),
|
|
6993
|
+
"balconyRailing"
|
|
6994
|
+
);
|
|
6995
|
+
cad.addGroup(doorLines, "door");
|
|
6996
|
+
cad.addGroup(windowLines, "window");
|
|
6997
|
+
cad.addGroup(bayWindowLines, "bayWindow");
|
|
6756
6998
|
}
|
|
6757
6999
|
install(cad) {
|
|
6758
7000
|
DxfDataPlugin.initData(cad, this.lines);
|
|
@@ -7014,11 +7256,12 @@ function buildBayWindowGroup(lines, clear = true) {
|
|
|
7014
7256
|
const bayWindowLines = lines.filter((line) => line.userData.isBayWindow), groupedLineSet = /* @__PURE__ */ new Set();
|
|
7015
7257
|
const removeSet = findDiscretePointLine2(lines, null, true);
|
|
7016
7258
|
const lines_ = lines.filter((line) => !removeSet.has(line));
|
|
7259
|
+
lines.forEach((line) => LineGroupType.removeByType(line, "bayWindow"));
|
|
7017
7260
|
bayWindowLines.forEach((bayWindowLine) => {
|
|
7018
7261
|
let { circles } = maxiCircles.miniCircle(lines_, { circleEdges: [bayWindowLine] });
|
|
7019
7262
|
circles = circles.filter((group2) => group2.some((line) => line.userData.isWindow && LineGroupType.hasType(line, "bayWindow")));
|
|
7020
7263
|
if (circles.length === 0 && bayWindowLine.userData?.outSize) {
|
|
7021
|
-
const direct = Point.from(bayWindowLine.userData.outSize.direction), point2 = bayWindowLine.center.add(direct.multiplyScalar(1e-8));
|
|
7264
|
+
const direct = Point.from(bayWindowLine.userData.outSize.direction), point2 = bayWindowLine.center.add(direct.multiplyScalar(1e-8)), bwCenter = bayWindowLine.center;
|
|
7022
7265
|
circles.push([bayWindowLine]);
|
|
7023
7266
|
const paths = bayWindowLine.points.map((p2) => {
|
|
7024
7267
|
const path = /* @__PURE__ */ new Set();
|
|
@@ -7030,7 +7273,9 @@ function buildBayWindowGroup(lines, clear = true) {
|
|
|
7030
7273
|
exitPoint: p2,
|
|
7031
7274
|
grid: lines
|
|
7032
7275
|
});
|
|
7033
|
-
return [...path]
|
|
7276
|
+
return [...path].filter((line) => {
|
|
7277
|
+
return line.center.direction(bwCenter).dot(direct) > 1e-9;
|
|
7278
|
+
});
|
|
7034
7279
|
}).filter((path) => path.length);
|
|
7035
7280
|
circles[0].push(...paths.flat(2));
|
|
7036
7281
|
if (paths.length === 2) {
|
|
@@ -7063,7 +7308,7 @@ function buildBayWindowGroup(lines, clear = true) {
|
|
|
7063
7308
|
const group2 = circles[0];
|
|
7064
7309
|
group2.forEach((line) => {
|
|
7065
7310
|
clear && LineGroupType.clear(line);
|
|
7066
|
-
|
|
7311
|
+
LineGroupType.set(line, id, "bayWindow", true);
|
|
7067
7312
|
groupedLineSet.add(line);
|
|
7068
7313
|
});
|
|
7069
7314
|
} else clear && LineGroupType.clear(bayWindowLine);
|
|
@@ -7925,158 +8170,6 @@ class BoundExt {
|
|
|
7925
8170
|
};
|
|
7926
8171
|
}
|
|
7927
8172
|
}
|
|
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);
|
|
8052
|
-
});
|
|
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
|
-
}
|
|
8079
|
-
}
|
|
8080
8173
|
class HandlerFlow {
|
|
8081
8174
|
handlerMap = new ArrayMap();
|
|
8082
8175
|
addHandler(handler) {
|
|
@@ -8099,6 +8192,7 @@ class ThreeVJiaJson extends HandlerFlow {
|
|
|
8099
8192
|
this.addHandler({ type: "wall", handle: this.wallHandle.bind(this) });
|
|
8100
8193
|
this.addHandler({ type: "door", handle: this.doorHandle.bind(this) });
|
|
8101
8194
|
this.addHandler({ type: "window", handle: this.windowHandle.bind(this) });
|
|
8195
|
+
this.addHandler({ type: "balconyRailing", handle: this.balconyRailing.bind(this) });
|
|
8102
8196
|
}
|
|
8103
8197
|
/** 双线墙处理
|
|
8104
8198
|
* @param param0
|
|
@@ -8186,12 +8280,23 @@ class ThreeVJiaJson extends HandlerFlow {
|
|
|
8186
8280
|
height3: data?.height3,
|
|
8187
8281
|
depth: data?.depth,
|
|
8188
8282
|
windowWidth: data?.windowWidth,
|
|
8189
|
-
windowHeight: data?.windowHeight
|
|
8283
|
+
windowHeight: data?.windowHeight,
|
|
8190
8284
|
// direction: data?.direction.toJson2D(),
|
|
8285
|
+
pictures: [
|
|
8286
|
+
"https://image.cnyang.cn/pano/PJ1772163638nmb/image/1527725175900.jpg",
|
|
8287
|
+
"https://image.cnyang.cn/pano/PJ1772163638nmb/image/1527725221900.jpg"
|
|
8288
|
+
]
|
|
8191
8289
|
});
|
|
8192
8290
|
}
|
|
8193
8291
|
return [];
|
|
8194
8292
|
}
|
|
8293
|
+
/** 阳台护栏
|
|
8294
|
+
* @param param0
|
|
8295
|
+
* @returns
|
|
8296
|
+
*/
|
|
8297
|
+
balconyRailing({ lines }) {
|
|
8298
|
+
return lines;
|
|
8299
|
+
}
|
|
8195
8300
|
/** 装换
|
|
8196
8301
|
* @returns
|
|
8197
8302
|
*/
|
|
@@ -17924,7 +18029,7 @@ class ThreeVJia extends Component {
|
|
|
17924
18029
|
updateData() {
|
|
17925
18030
|
if (!this.neededUpdate) return;
|
|
17926
18031
|
const angleCorrectionDxf = this.parent?.findComponentByName("CorrectionDxf");
|
|
17927
|
-
this.cacheJson = lineDataToThreeVJiaJson(angleCorrectionDxf.getLineSegments(),
|
|
18032
|
+
this.cacheJson = lineDataToThreeVJiaJson(angleCorrectionDxf.getLineSegments(), 0).toJson();
|
|
17928
18033
|
this.neededUpdate = false;
|
|
17929
18034
|
}
|
|
17930
18035
|
/** 转为json
|
|
@@ -14,12 +14,25 @@ export interface IDrawBayWindowData {
|
|
|
14
14
|
deptLine: LineSegment;
|
|
15
15
|
direction: Point;
|
|
16
16
|
}
|
|
17
|
+
export interface IDrawBayWindowData2 {
|
|
18
|
+
height1: number;
|
|
19
|
+
height2: number;
|
|
20
|
+
height3: number;
|
|
21
|
+
windowWidth: number;
|
|
22
|
+
windowHeight: number;
|
|
23
|
+
direction: Point;
|
|
24
|
+
}
|
|
17
25
|
export declare class BayWindowHelper {
|
|
18
26
|
/** 获取绘制数据
|
|
19
27
|
* @param lines
|
|
20
28
|
* @returns
|
|
21
29
|
*/
|
|
22
30
|
static getDrawData(lines: LineSegment<LineUserData>[]): IDrawBayWindowData | null;
|
|
31
|
+
/** 获取绘制数据
|
|
32
|
+
* @param lines
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
static getDrawData2(lines: LineSegment<LineUserData>[]): IDrawBayWindowData2 | null;
|
|
23
36
|
/** 获取所有绘制数据
|
|
24
37
|
* @param lineSegments
|
|
25
38
|
* @returns
|
|
@@ -65,7 +65,13 @@ export declare class CAD {
|
|
|
65
65
|
/** 添加组并执行偏移
|
|
66
66
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
67
67
|
*/
|
|
68
|
-
addGroupAndOffset(lines: LineSegmentType[],
|
|
68
|
+
addGroupAndOffset(lines: LineSegmentType[], option?: {
|
|
69
|
+
offsetHalfWidth?: number;
|
|
70
|
+
joinType?: JoinType;
|
|
71
|
+
endType?: EndType;
|
|
72
|
+
groupName?: string;
|
|
73
|
+
scale?: number;
|
|
74
|
+
}): this;
|
|
69
75
|
/**
|
|
70
76
|
* 合并所有组
|
|
71
77
|
*/
|
|
@@ -17,13 +17,19 @@ export declare class LineGroupType {
|
|
|
17
17
|
* @param type
|
|
18
18
|
* @returns
|
|
19
19
|
*/
|
|
20
|
-
static set(line: LineSegment<LineUserData>, id: string, type: string): void;
|
|
20
|
+
static set(line: LineSegment<LineUserData>, id: string, type: string, repeat?: boolean): void;
|
|
21
21
|
/** 通过类型获取id
|
|
22
22
|
* @param line
|
|
23
23
|
* @param type
|
|
24
24
|
* @returns
|
|
25
25
|
*/
|
|
26
26
|
static getIdByType(line: LineSegment<LineUserData>, type: string): string | undefined;
|
|
27
|
+
/** 通过类型获取所有id
|
|
28
|
+
* @param line
|
|
29
|
+
* @param type
|
|
30
|
+
* @returns
|
|
31
|
+
*/
|
|
32
|
+
static getIdsByType(line: LineSegment<LineUserData>, type: string): string[];
|
|
27
33
|
/** 通过类型获取所有组
|
|
28
34
|
* @param lines
|
|
29
35
|
* @param type
|
|
@@ -9,7 +9,17 @@ export declare class WallGroupManager {
|
|
|
9
9
|
[Symbol.iterator](): ArrayIterator<IGroup<any>>;
|
|
10
10
|
private groups;
|
|
11
11
|
add(group: IGroup): void;
|
|
12
|
-
static fromByLines(lineSegments: LineSegment[]): WallGroupManager;
|
|
13
12
|
forEach(fun: (group: IGroup, index: number) => void): void;
|
|
14
13
|
map<T = any>(fun: (group: IGroup, index: number) => T): T[];
|
|
14
|
+
/** 查找符合条件的组
|
|
15
|
+
* @param fun
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
findGroup(fun: (group: IGroup) => boolean): IGroup<any> | undefined;
|
|
19
|
+
/** 查找所有符合条件的组
|
|
20
|
+
* @param fun
|
|
21
|
+
* @returns
|
|
22
|
+
*/
|
|
23
|
+
findGroups(fun: (group: IGroup) => boolean): IGroup<any>[];
|
|
24
|
+
static fromByLines(lineSegments: LineSegment[]): WallGroupManager;
|
|
15
25
|
}
|
|
@@ -22,6 +22,7 @@ type Hole = {
|
|
|
22
22
|
depth?: number;
|
|
23
23
|
windowWidth?: number;
|
|
24
24
|
windowHeight?: number;
|
|
25
|
+
pictures?: string[];
|
|
25
26
|
};
|
|
26
27
|
type Wall = {
|
|
27
28
|
ID: number;
|
|
@@ -76,6 +77,11 @@ export declare class ThreeVJiaJson extends HandlerFlow<ThreeVJiaJsonObject> {
|
|
|
76
77
|
* @returns
|
|
77
78
|
*/
|
|
78
79
|
bayWindowHandle({ lines, data }: IGroup<IDrawBayWindowData>, option?: ThreeVJiaJsonObject): never[];
|
|
80
|
+
/** 阳台护栏
|
|
81
|
+
* @param param0
|
|
82
|
+
* @returns
|
|
83
|
+
*/
|
|
84
|
+
balconyRailing({ lines }: IGroup<IDrawBayWindowData>): LineSegment<LineUserData>[];
|
|
79
85
|
/** 装换
|
|
80
86
|
* @returns
|
|
81
87
|
*/
|