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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "build-dxf",
3
- "version": "0.1.60",
3
+ "version": "0.1.61",
4
4
  "description": "线段构建双线墙壁的dxf版本",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
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 id = LineGroupType.getIdByType(line, type);
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 = 0; i < groups.length; 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, joinType = "jtMiter", endType = "etOpenButt", scale2 = 1e5) {
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, DEFAULT_WALL_WIDTH / 2 * scale2);
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, "groupOffset", { polygon: polygon2 });
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 lineSegments = lines, doubleWall = [], wall = [], doors = [], bayWindows = [];
6732
- for (let i = 0; i < lineSegments.length; i++) {
6733
- const line = lineSegments[i];
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(wall);
6751
- cad.addGroups(doubleWallGroup, "doubleWall");
6977
+ cad.addGroupAndOffset(wallLines);
6978
+ cad.addGroups(doubleWalls, "doubleWall");
6752
6979
  cad.unionGroupAll();
6753
- cad.addGroup(doors, "door");
6754
- cad.addGroup(windows, "window");
6755
- cad.addGroup(bayWindows, "bayWindow");
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
- if (!LineGroupType.replace(line, id, "bayWindow")) LineGroupType.set(line, id, "bayWindow");
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(), angleCorrectionDxf.angle).toJson();
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[], joinType?: JoinType, endType?: EndType, scale?: number): this;
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
  */