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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "build-dxf",
3
- "version": "0.1.58",
3
+ "version": "0.1.60",
4
4
  "description": "线段构建双线墙壁的dxf版本",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
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
- addGroupByOffset(lines, joinType = "jtMiter", endType = "etOpenButt", scale2 = 1e5) {
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.addGroupByOffset(wall);
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(lines, { circleEdges: [bayWindowLine] });
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
- circles[0].push(...path);
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 getGroups(lines, updateGroup = true) {
7881
- if (updateGroup) lines = DoubleWallHelper.buildGroup(lines);
7882
- const map = lines.reduce((map2, line) => {
7883
- const groups = LineGroupType.get(line);
7884
- groups.forEach((group2) => {
7885
- let id = group2.id ?? "wall";
7886
- if (group2.type === "wall") id = "wall";
7887
- map2.append(id, line);
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
- return map2;
7890
- }, new ArrayMap());
7891
- return map;
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
- function handleGroup(map) {
7894
- const group2 = map.group((lines) => {
7895
- if (LineGroupType.everyType(lines, "bayWindow")) return "wall";
7896
- if (LineGroupType.everyType(lines, "doubleWall")) return "doubleWall";
7897
- return "wall";
7898
- }), walls = group2.get("wall") ?? [], doubleWalls = group2.get("doubleWall") ?? [];
7899
- let newlines = [], doubleWallsSet = new Set(doubleWalls.flat());
7900
- walls.forEach((lines) => {
7901
- lines.forEach((line) => doubleWallsSet.has(line) || newlines.push(line));
7902
- });
7903
- doubleWalls.forEach((lines) => {
7904
- lines = [...new Set(lines)];
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.forEach((lines2) => {
7907
- if (lines2.length < 4) return newlines.push(...lines2);
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
- newlines = newlines.map((line) => line.clone());
7918
- return newlines.filter((line) => !line.userData.isBayWindow);
7919
- }
7920
- function toJson(lineSegments, name = "测试", communityName = "") {
7921
- const scale2 = 1, idMap = /* @__PURE__ */ new Map();
7922
- let index2 = 0;
7923
- return {
7924
- version: "2",
7925
- name,
7926
- communityName,
7927
- city: "",
7928
- province: "",
7929
- height: DEFAULT_WALL_HEIGHT * scale2,
7930
- walls: lineSegments.map((line) => {
7931
- if (line.userData.isDoor && !line.userData.doorDirectConnection) return;
7932
- idMap.set(line, index2);
7933
- return {
7934
- ID: index2++,
7935
- start: { x: line.start.x * scale2, y: line.start.y * scale2 },
7936
- end: { x: line.end.x * scale2, y: line.end.y * scale2 },
7937
- thickness: (line.userData.wallWidth ? line.userData.wallWidth : 0.12) * scale2,
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: line.userData.isDoor,
8220
+ isDoor: false,
7940
8221
  loadBearingWall: false,
7941
- height: (line.userData.height ?? DEFAULT_WALL_HEIGHT) * scale2
7942
- };
7943
- }).filter((i) => !!i),
7944
- pillars: [],
7945
- beams: [],
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
- const group2 = getGroups(lineSegments, updateGroup);
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: newLines,
8241
+ lines: [],
8008
8242
  toJson(name = "测试", communityName = "") {
8009
- return toJson(newLines, name, communityName);
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 * 75;
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.queryCircle(point22, 0.6, true).filter((item) => {
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 = dock.point.direction(item.point), d2 = line2.getAnotherPoint(item.point).direction(item.point);
16985
- return d1.angleBetween(d2, "angle") > maxAngle;
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 queryLine2 = new LineSegment(item.point.clone(), dock.point.clone());
16988
- queryLine2.startShrink(0.01).endShrink(1e-3);
16989
- return this.quadtree.queryLineSegment(queryLine2).length === 0;
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 normal2 = 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);
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(normal2.clone().multiplyScalar(length2))
17239
+ center.clone().add(normal.clone().multiplyScalar(length2))
16997
17240
  );
16998
- normalLine.directionMove(normal2, -length2 * 0.5);
16999
- const results = this.quadtree.queryLineSegment(normalLine).filter((result2) => result2.line !== line && result2.line !== dock.dockLine);
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/lineDataToThreeVJiaJson';
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
- addGroupByOffset(lines: LineSegmentType[], joinType?: JoinType, endType?: EndType, scale?: number): this;
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<LineSegment<LineUserData>>;
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 { Point } from '../../Point';
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: Point;
8
- end: Point;
9
- height: number;
12
+ type: "DOOR" | "WINDOW" | "BAY_WINDOW";
13
+ start: Vec2;
14
+ end: Vec2;
15
+ height?: number;
10
16
  groundClearance?: number;
11
- sillHeight: number;
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: Point;
17
- end: Point;
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: LineSegment<LineUserData>[];
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
+ }
@@ -160,6 +160,10 @@ export declare class Point<T = Record<string, any>> {
160
160
  y: number;
161
161
  z: number;
162
162
  };
163
+ toJson2D(): {
164
+ x: number;
165
+ y: number;
166
+ };
163
167
  toVector3(z?: number): Vector3;
164
168
  /** 点吸附
165
169
  * @param points
@@ -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 包围盒
@@ -27,6 +27,7 @@ export declare class Polygon<T = any> extends Array<Point<T>> {
27
27
  * @returns
28
28
  */
29
29
  area(): number;
30
+ closedLoop(): boolean;
30
31
  /**
31
32
  * 获取点相对于多边形的位置
32
33
  * @param point