build-dxf 0.1.72 → 0.1.74

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.72",
3
+ "version": "0.1.74",
4
4
  "description": "线段构建双线墙壁的dxf版本",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
package/src/build.js CHANGED
@@ -4850,6 +4850,76 @@ class Polygon extends Array {
4850
4850
  const last = this[this.length - 1];
4851
4851
  return first.equal(last);
4852
4852
  }
4853
+ /** 闭合路径向路径外膨胀width
4854
+ * @param width
4855
+ */
4856
+ closedExpansion(width, scale2 = 100) {
4857
+ if (this.length < 3) return null;
4858
+ const inv = 1 / scale2;
4859
+ const path = this.clone().scale(scale2).round();
4860
+ const co2 = new ClipperLib.ClipperOffset(
4861
+ 2,
4862
+ // miter limit
4863
+ 0.25 * scale2
4864
+ );
4865
+ co2.AddPath(
4866
+ path,
4867
+ ClipperLib.JoinType.jtMiter,
4868
+ // 角处理方式
4869
+ ClipperLib.EndType.etClosedPolygon
4870
+ );
4871
+ const solution = [];
4872
+ co2.Execute(solution, width * scale2);
4873
+ if (!solution.length) return null;
4874
+ const result = solution[0].map(
4875
+ (p2) => new Point(p2.X * inv, p2.Y * inv)
4876
+ );
4877
+ this.set(result);
4878
+ return this;
4879
+ }
4880
+ clipByLine(line) {
4881
+ if (this.length < 3) return [];
4882
+ const intersections = [];
4883
+ const lines = this.toLines(true);
4884
+ for (let i = 0; i < lines.length; i++) {
4885
+ const l = lines[i];
4886
+ const p2 = l.getIntersection(line);
4887
+ if (p2) {
4888
+ intersections.push({
4889
+ index: i,
4890
+ point: p2
4891
+ });
4892
+ }
4893
+ }
4894
+ if (intersections.length < 2) return [this.clone()];
4895
+ intersections.sort((a22, b22) => a22.index - b22.index);
4896
+ const newPoints = [];
4897
+ for (let i = 0; i < this.length; i++) {
4898
+ const p2 = this[i].clone();
4899
+ newPoints.push(p2);
4900
+ intersections.forEach((inter) => {
4901
+ if (inter.index === i) {
4902
+ newPoints.push(inter.point.clone());
4903
+ }
4904
+ });
4905
+ }
4906
+ const polygon2 = new Polygon(newPoints);
4907
+ const left = [];
4908
+ const right = [];
4909
+ const a2 = line.start;
4910
+ const b4 = line.end;
4911
+ const side = (p2) => {
4912
+ return (b4.x - a2.x) * (p2.y - a2.y) - (b4.y - a2.y) * (p2.x - a2.x);
4913
+ };
4914
+ polygon2.forEach((p2) => {
4915
+ if (side(p2) >= 0) left.push(p2.clone());
4916
+ if (side(p2) <= 0) right.push(p2.clone());
4917
+ });
4918
+ const results = [];
4919
+ if (left.length >= 3) results.push(new Polygon(left));
4920
+ if (right.length >= 3) results.push(new Polygon(right));
4921
+ return results;
4922
+ }
4853
4923
  /**
4854
4924
  * 获取点相对于多边形的位置
4855
4925
  * @param point
@@ -5010,7 +5080,7 @@ class Polygon extends Array {
5010
5080
  const p2 = this[i].clone(), nextP = this[(i + 1) % this.length].clone();
5011
5081
  lines.push(new LineSegment(p2, nextP));
5012
5082
  }
5013
- return lines;
5083
+ return lines.filter((line) => line.length() > 1e-9);
5014
5084
  }
5015
5085
  toArrays() {
5016
5086
  return this.map((p2) => p2.toArray());
@@ -6046,6 +6116,7 @@ function segmentationPath(lines, clipLine) {
6046
6116
  const groups = LineSegment.groupByPosition(lines, queryLine);
6047
6117
  const newGroups = [];
6048
6118
  groups.forEach((group2) => {
6119
+ Point.adsorb(group2.flatMap((line) => line.points), 5e-4);
6049
6120
  const points = [...findDiscretePoint(group2).keys()].sort((a2, b4) => a2.distance(queryLine.start, true) - b4.distance(queryLine.start, true));
6050
6121
  for (let i = 0; i < points.length; i += 2) {
6051
6122
  const p1 = points[i], p2 = points[i + 1];
@@ -8203,7 +8274,7 @@ class BoundExt {
8203
8274
  const walls = lines.filter((line) => !line.userData.isDoor);
8204
8275
  lines = [...LineSegment.brokenLineMerging(walls, mergeLineUserData), ...doors];
8205
8276
  recomputedWindow(...lines);
8206
- lines = lines.filter((line) => line.length() > 0.01);
8277
+ lines = lines.filter((line) => line.length() > 0.01).filter((line) => line.userData.isDoor ? line.length() > 0.25 : true);
8207
8278
  findCallBack && findCallBack([...exteriorLines, ...appendLines], trajectoryPoints);
8208
8279
  return {
8209
8280
  lines,
@@ -8227,8 +8298,13 @@ class HandlerFlow {
8227
8298
  class ThreeVJiaJson extends HandlerFlow {
8228
8299
  manager;
8229
8300
  index = 0;
8230
- constructor(lines) {
8301
+ version = "1.0";
8302
+ maxHeight;
8303
+ lines;
8304
+ constructor(lines, maxHeight) {
8231
8305
  super();
8306
+ this.maxHeight = maxHeight;
8307
+ this.lines = lines;
8232
8308
  this.manager = WallGroupManager.fromByLines(lines);
8233
8309
  this.addHandler({ type: "bayWindow", handle: this.bayWindowHandle.bind(this) });
8234
8310
  this.addHandler({ type: "doubleWall", handle: this.doubleWallHandle.bind(this) });
@@ -8281,7 +8357,7 @@ class ThreeVJiaJson extends HandlerFlow {
8281
8357
  groundClearance: line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT
8282
8358
  });
8283
8359
  });
8284
- return [];
8360
+ return lines;
8285
8361
  }
8286
8362
  /**
8287
8363
  * 窗线处理
@@ -8311,24 +8387,41 @@ class ThreeVJiaJson extends HandlerFlow {
8311
8387
  * @returns
8312
8388
  */
8313
8389
  bayWindowHandle({ lines, data }, option) {
8314
- const bayWindows = lines.filter((line) => line.userData.isBayWindow);
8315
- if (bayWindows.length) {
8316
- option?.holes.push({
8317
- type: "BAY_WINDOW",
8318
- id: this.index++,
8319
- start: bayWindows[0].start,
8320
- end: bayWindows[0].end,
8321
- height1: data?.height1,
8322
- height2: data?.height2,
8323
- height3: data?.height3,
8324
- depth: data?.depth,
8325
- windowWidth: data?.windowWidth,
8326
- windowHeight: data?.windowHeight,
8327
- // direction: data?.direction.toJson2D(),
8328
- pictures: [
8329
- "https://image.cnyang.cn/pano/PJ1772163638nmb/image/1527725175900.jpg",
8330
- "https://image.cnyang.cn/pano/PJ1772163638nmb/image/1527725221900.jpg"
8331
- ]
8390
+ if (this.version === "2.0") {
8391
+ const bayWindows = lines.filter((line) => line.userData.isBayWindow);
8392
+ if (bayWindows.length) {
8393
+ option?.holes.push({
8394
+ type: "BAY_WINDOW",
8395
+ id: this.index++,
8396
+ start: bayWindows[0].start,
8397
+ end: bayWindows[0].end,
8398
+ height1: data?.height1,
8399
+ height2: data?.height2,
8400
+ height3: data?.height3,
8401
+ depth: data?.depth,
8402
+ windowWidth: data?.windowWidth,
8403
+ windowHeight: data?.windowHeight,
8404
+ // direction: data?.direction.toJson2D(),
8405
+ pictures: [
8406
+ "https://image.cnyang.cn/pano/PJ1772163638nmb/image/1527725175900.jpg",
8407
+ "https://image.cnyang.cn/pano/PJ1772163638nmb/image/1527725221900.jpg"
8408
+ ]
8409
+ });
8410
+ }
8411
+ } else {
8412
+ const wallLines = [];
8413
+ const winLines = [];
8414
+ lines.forEach((line) => {
8415
+ if (line.userData.isWindow) winLines.push(line);
8416
+ else if (!line.userData.isBayWindow) wallLines.push(line);
8417
+ });
8418
+ this.manager.add({
8419
+ type: "wall",
8420
+ lines: wallLines
8421
+ });
8422
+ this.manager.add({
8423
+ type: "window",
8424
+ lines: winLines
8332
8425
  });
8333
8426
  }
8334
8427
  return [];
@@ -8340,6 +8433,24 @@ class ThreeVJiaJson extends HandlerFlow {
8340
8433
  balconyRailing({ lines }) {
8341
8434
  return lines;
8342
8435
  }
8436
+ findRooms(lines) {
8437
+ lines = lineSegmentClipping(lines, 0);
8438
+ LineSegment.groupByPath(lines).forEach((group2, i) => {
8439
+ const removeSet = findDiscretePointLine2(group2, null, true);
8440
+ lines = group2.filter((line) => !removeSet.has(line) && !line.userData.isBayWindow);
8441
+ const doors = lines.filter((line) => line.userData.isDoor), maxiCircles2 = new MaxiCircles(), { circles } = maxiCircles2.miniCircle(lines, { circleEdges: doors, side: Side.IN }), ploys = circles.map(((p2) => Polygon.fromByLinePath(p2)));
8442
+ ploys.forEach((ploy) => {
8443
+ const xList = [];
8444
+ const yList = [];
8445
+ ploy.forEach((p2) => {
8446
+ xList.push(p2.x);
8447
+ yList.push(p2.y);
8448
+ });
8449
+ const minX = Math.min(...xList), maxX = Math.max(...xList), minY = Math.min(...yList), maxY = Math.max(...yList), center = new Point((maxX - minX) * 0.5 + minX, (maxY - minY) * 0.5 + minY);
8450
+ drawPoint(center);
8451
+ });
8452
+ });
8453
+ }
8343
8454
  /** 装换
8344
8455
  * @returns
8345
8456
  */
@@ -8350,7 +8461,7 @@ class ThreeVJiaJson extends HandlerFlow {
8350
8461
  communityName: "",
8351
8462
  city: "",
8352
8463
  province: "",
8353
- height: 0,
8464
+ height: this.maxHeight,
8354
8465
  walls: [],
8355
8466
  pillars: [],
8356
8467
  beams: [],
@@ -8367,13 +8478,14 @@ class ThreeVJiaJson extends HandlerFlow {
8367
8478
  type: "LINE",
8368
8479
  isDoor: false,
8369
8480
  loadBearingWall: false,
8370
- height: line.userData.height ?? DEFAULT_WALL_HEIGHT
8481
+ // height: line.userData.height ?? DEFAULT_WALL_HEIGHT
8482
+ height: this.maxHeight
8371
8483
  });
8372
8484
  });
8373
8485
  return option;
8374
8486
  }
8375
8487
  }
8376
- function lineDataToThreeVJiaJson$1(lineSegments, angle = 0, updateGroup = true) {
8488
+ function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
8377
8489
  lineSegments = LineSegmentUndirectedGraph.rotate(lineSegments.map((line) => line.clone()), angle, (line, center, angle2) => {
8378
8490
  if (line.userData.drawWindow) {
8379
8491
  line.userData.drawWindow.forEach((windowItem) => {
@@ -8381,10 +8493,24 @@ function lineDataToThreeVJiaJson$1(lineSegments, angle = 0, updateGroup = true)
8381
8493
  point2.rotate(center, angle2);
8382
8494
  windowItem.p = point2.toJson(windowItem.p.z);
8383
8495
  });
8496
+ } else if (line.userData.isPassageEntrance) {
8497
+ line.userData.passageEntrance?.forEach((item) => {
8498
+ const point2 = Point.from(item.p);
8499
+ point2.rotate(center, angle2);
8500
+ item.p = point2.toJson(item.p.z);
8501
+ });
8502
+ }
8503
+ });
8504
+ const heights = [DEFAULT_WALL_HEIGHT];
8505
+ lineSegments.forEach((line) => {
8506
+ if (line.userData.isDoor) heights.push(line.userData.height ?? 0);
8507
+ else if (line.userData.isWindow) {
8508
+ line.userData.drawWindow?.forEach((item) => heights.push(item.height ?? 0));
8384
8509
  }
8385
8510
  });
8511
+ const maxHeight = Math.max(...heights);
8386
8512
  if (updateGroup) lineSegments = DoubleWallHelper.buildGroup(lineSegments);
8387
- const threeVJiaJson = new ThreeVJiaJson(lineSegments);
8513
+ const threeVJiaJson = new ThreeVJiaJson(lineSegments, maxHeight);
8388
8514
  return {
8389
8515
  lines: [],
8390
8516
  toJson(name = "测试", communityName = "") {
@@ -8499,6 +8625,9 @@ LoadModel.addNameMap("window", "窗户");
8499
8625
  LoadModel.addNameMap("wall", "单线墙");
8500
8626
  LoadModel.addNameMap("doubleWall", "双线墙");
8501
8627
  LoadModel.addNameMap("balcony", "阳台");
8628
+ LoadModel.addNameMap("balconyFilm", "阳台片");
8629
+ LoadModel.addNameMap("balconyFilmFilm", "阳台片片");
8630
+ LoadModel.addNameMap("balconyFilmFilmFilm", "阳台片片片");
8502
8631
  class BayWindow {
8503
8632
  bayWindowExpansion = [];
8504
8633
  dottedLinePoints = [];
@@ -10055,6 +10184,8 @@ class Scenario {
10055
10184
  }
10056
10185
  // 安装阳台
10057
10186
  installBalconys(data, index2) {
10187
+ let balconyGroup = new Group$1();
10188
+ balconyGroup.name = `阳台${index2}`;
10058
10189
  const point1 = new THREE.Vector3(data.start.x, data.start.y, 0);
10059
10190
  const point2 = new THREE.Vector3(data.end.x, data.end.y, 0);
10060
10191
  new THREE.Vector3(data.center.x, data.center.y, 0);
@@ -10066,19 +10197,57 @@ class Scenario {
10066
10197
  const wallWidth = data.userData.wallWidth ? data.userData.wallWidth : 0.18;
10067
10198
  (data.userData.groundClearance ?? this.WindowGroundHeight) + this.height;
10068
10199
  let menModel = this.balconyModely.clone();
10069
- if (data.center && distance2) {
10070
- menModel.position.set(data.center.x, data.center.y, 0);
10071
- const box32 = new THREE.Box3();
10072
- box32.setFromObject(menModel);
10073
- let size2 = new THREE.Vector3();
10074
- box32.getSize(size2);
10075
- menModel.rotation.x = Math.PI / 2;
10076
- menModel.rotation.y = angleRad;
10077
- menModel.scale.set(distance2 / size2.x, height / size2.y, wallWidth / size2.z);
10078
- menModel.position.set(data.center.x, data.center.y, this.height);
10079
- menModel.name = `阳台_${index2}`;
10080
- menModel.userData.category = "balcony";
10081
- this.group.add(menModel);
10200
+ if (distance2 < 1.2) {
10201
+ if (data.center && distance2) {
10202
+ menModel.position.set(data.center.x, data.center.y, 0);
10203
+ const box32 = new THREE.Box3();
10204
+ box32.setFromObject(menModel);
10205
+ let size2 = new THREE.Vector3();
10206
+ box32.getSize(size2);
10207
+ menModel.rotation.x = Math.PI / 2;
10208
+ menModel.rotation.y = angleRad;
10209
+ menModel.scale.set(distance2 / size2.x, height / size2.y, wallWidth / size2.z);
10210
+ menModel.position.set(data.center.x, data.center.y, this.height);
10211
+ menModel.name = `阳台_${index2}`;
10212
+ menModel.userData.category = "balcony";
10213
+ balconyGroup.add(menModel);
10214
+ this.group.add(balconyGroup);
10215
+ }
10216
+ } else {
10217
+ let splitLineInto7Points = function(startPoint, endPoint) {
10218
+ const points2 = [];
10219
+ const startVec = new THREE.Vector3(startPoint.x, startPoint.y, startPoint.z);
10220
+ const endVec = new THREE.Vector3(endPoint.x, endPoint.y, endPoint.z);
10221
+ for (let i = 0; i <= npc; i++) {
10222
+ const fraction = i / npc;
10223
+ const point3 = new THREE.Vector3();
10224
+ point3.lerpVectors(startVec, endVec, fraction);
10225
+ points2.push(point3);
10226
+ }
10227
+ return points2;
10228
+ };
10229
+ let npc = 0;
10230
+ npc = distance2 / 0.8;
10231
+ npc = Math.round(npc);
10232
+ const points = splitLineInto7Points(point1, point2);
10233
+ for (let o = 0; o < points.length - 1; o++) {
10234
+ const spacing = points[o].distanceTo(points[o + 1]);
10235
+ const center = new THREE.Vector3();
10236
+ center.lerpVectors(points[o], points[o + 1], 0.5);
10237
+ let balconyModel = this.balconyModely.clone();
10238
+ const box32 = new THREE.Box3();
10239
+ box32.setFromObject(menModel);
10240
+ let size2 = new THREE.Vector3();
10241
+ box32.getSize(size2);
10242
+ balconyModel.rotation.x = Math.PI / 2;
10243
+ balconyModel.rotation.y = angleRad;
10244
+ balconyModel.scale.set(spacing / size2.x, height / size2.y, wallWidth / size2.z);
10245
+ balconyModel.position.set(center.x, center.y, this.height);
10246
+ balconyModel.name = `阳台_${index2}`;
10247
+ balconyModel.userData.category = "balcony";
10248
+ balconyGroup.add(balconyModel);
10249
+ }
10250
+ this.group.add(balconyGroup);
10082
10251
  }
10083
10252
  }
10084
10253
  // 放置柜子
@@ -10517,7 +10686,7 @@ class Scenario {
10517
10686
  }
10518
10687
  // 获取阳台模型
10519
10688
  async balconyModelLoader() {
10520
- this.balconyModely = await LoadModel.loadGlb("balcony");
10689
+ this.balconyModely = await LoadModel.loadGlb("balconyFilmFilmFilm");
10521
10690
  }
10522
10691
  damian() {
10523
10692
  const planeGeometry = new THREE.BufferGeometry();
@@ -18646,6 +18815,52 @@ const PRE_PROCESSOR = {
18646
18815
  console.log(`外墙外扩总消耗时间: ${(performance.now() - t2).toFixed(2)} ms 处理线段数量:`, lines.length);
18647
18816
  return lines;
18648
18817
  },
18818
+ /** 双线墙对齐单线墙
18819
+ * @param lines
18820
+ * @returns
18821
+ */
18822
+ DoubleWallAlignment(lines) {
18823
+ const singleWall = lines.filter((line) => !LineGroupType.hasType(line, "doubleWall") && !line.userData.isDoor), doorLines = lines.filter((line) => line.userData.isDoor), grid = createPointVirtualGrid(singleWall.filter((line) => !line.userData.isDoor)), quadtree = createQuadtree(singleWall), doubleWalls = LineGroupType.getGroupsByType(lines, "doubleWall"), offset2 = -DEFAULT_WALL_WIDTH * 0.5, tree = createQuadtree(doubleWalls.flat());
18824
+ const newDoubleWalls = doubleWalls.flatMap((doubleWall) => {
18825
+ const poly = Polygon.fromByLines2(doubleWall);
18826
+ Polygon.ensureCCW(poly);
18827
+ doubleWall = poly.toLines();
18828
+ doubleWall.forEach((line) => {
18829
+ const list = tree.queryCircle(line.center, 1e-6);
18830
+ if (list.length) line.userData = list[0].line.userData;
18831
+ });
18832
+ const expLines = doubleWall.filter((line) => {
18833
+ if (line.length() < 1e-3) return false;
18834
+ for (let i = 0; i < line.points.length; i++) {
18835
+ const point2 = line.points[i];
18836
+ let list = grid.queryPoint(point2);
18837
+ if (list.length !== 1) continue;
18838
+ list = grid.queryPoint(point2).filter((item) => item.userData?.parallel(line));
18839
+ if (list.length !== 1) continue;
18840
+ return true;
18841
+ }
18842
+ return false;
18843
+ });
18844
+ const newLines = expLines.flatMap((line) => {
18845
+ const normal = line.normal(), oldLine = line.clone(), id = LineGroupType.getIdByType(line, "doubleWall");
18846
+ line.directionMove(normal, offset2);
18847
+ return [
18848
+ new LineSegment(oldLine.start.clone(), line.start.clone()),
18849
+ new LineSegment(oldLine.end.clone(), line.end.clone())
18850
+ ].filter((l) => {
18851
+ LineGroupType.set(l, id, "doubleWall");
18852
+ return quadtree.queryPoint(l.center).length === 0;
18853
+ });
18854
+ });
18855
+ return [newLines, doubleWall].flat(10);
18856
+ });
18857
+ lines = [singleWall, newDoubleWalls].flat(10);
18858
+ lines = LineSegmentUndirectedGraph.breakpointMerging(lines, mergeLineUserData);
18859
+ lines = lineSegmentClipping(lines, 1e-9);
18860
+ lines = buildDoubleWallGroup(lines, lines.filter((line) => line.userData.isDoor), true, true);
18861
+ lines.push(...doorLines);
18862
+ return lines;
18863
+ },
18649
18864
  /** 图形角度修正
18650
18865
  * @param lines
18651
18866
  * @returns
@@ -18738,12 +18953,55 @@ const PRE_PROCESSOR = {
18738
18953
  lineSegments.push(...appendLines);
18739
18954
  return lineSegments;
18740
18955
  },
18741
- /**
18956
+ /** 门点纠值
18742
18957
  * @param lineSegments
18743
18958
  * @returns
18744
18959
  */
18745
18960
  DoorPointCorr(lineSegments) {
18746
18961
  return lineSegments;
18962
+ },
18963
+ /** 短连接合并
18964
+ * @description 合并链接两条平行线的短线段,且两条平行线的至少有一条线段另一个端点只有一条与之相连的线段且垂直
18965
+ */
18966
+ shortLinkMerging(lineSegments) {
18967
+ const minWidth = 0.05, grid = createPointVirtualGrid(lineSegments), shortLines = lineSegments.filter((line) => line.length() < minWidth);
18968
+ const removeLines = /* @__PURE__ */ new Set();
18969
+ for (let i = 0; i < shortLines.length; i++) {
18970
+ const line = shortLines[i];
18971
+ const intersLines = [];
18972
+ for (let j = 0; j < 2; j++) {
18973
+ const point2 = line.points[j];
18974
+ const list = grid.queryPoint(point2, true);
18975
+ if (list.length != 1) break;
18976
+ const line2 = list[0].userData;
18977
+ if (!line2.vertical(line)) break;
18978
+ intersLines.push([line2, list[0].point]);
18979
+ }
18980
+ if (intersLines.length === 2) {
18981
+ for (let i2 = 0; i2 < 2; i2++) {
18982
+ const [line2, point2] = intersLines[i2], [_, point3] = intersLines[i2 === 0 ? 1 : 0], otherPoint = line2.getAnotherPoint(point2), list = grid.queryPoint(otherPoint, true);
18983
+ if (list.length == 1 && list[0].userData?.vertical(line2)) {
18984
+ const line4 = list[0].userData;
18985
+ const newP = line4.projectPoint(point3);
18986
+ if (newP) {
18987
+ point3.copy(newP);
18988
+ list[0].point.copy(newP);
18989
+ removeLines.add(line);
18990
+ removeLines.add(line2);
18991
+ break;
18992
+ }
18993
+ }
18994
+ }
18995
+ }
18996
+ }
18997
+ return lineSegments.filter((line) => !removeLines.has(line));
18998
+ },
18999
+ /**
19000
+ * 移除与双线墙链接的短线段
19001
+ */
19002
+ removeShortDoubleWall(lineSegments) {
19003
+ const doubleWalls = LineGroupType.getGroupsByType(lineSegments, "doubleWall"), freePointLines = [...findDiscretePointLine2(lineSegments)].filter((line) => line.length() < 0.3), grid = createPointVirtualGrid(doubleWalls.flat(4)), lines = freePointLines.filter((line) => grid.queryPoint(line.start).length > 0 || grid.queryPoint(line.end).length > 0), removeSet = new Set(lines);
19004
+ return lineSegments.filter((line) => !removeSet.has(line));
18747
19005
  }
18748
19006
  };
18749
19007
  class Dxf extends Component {
@@ -18968,6 +19226,7 @@ class CorrectionDxf extends Dxf {
18968
19226
  onAddFromParent(parent) {
18969
19227
  parent.Dxf.addEventListener("cadChange", (e) => {
18970
19228
  e.options.trajectory && this.addPreProcessor(PRE_PROCESSOR.BoundExt);
19229
+ this.addPreProcessor(PRE_PROCESSOR.DoubleWallAlignment);
18971
19230
  const lines = parent.Dxf.getLineSegments(true);
18972
19231
  this.set(lineDataToOriginalData(lines, parent.Dxf.originalZAverage), {
18973
19232
  trajectory: e.options.trajectory,
@@ -19056,139 +19315,6 @@ class CorrectionDxf extends Dxf {
19056
19315
  return this.rotateCorrCad?.downloadDxf(filename, unit);
19057
19316
  }
19058
19317
  }
19059
- function getGroups(lines, updateGroup = true) {
19060
- if (updateGroup) lines = DoubleWallHelper.buildGroup(lines);
19061
- const map = lines.reduce((map2, line) => {
19062
- const groups = LineGroupType.get(line);
19063
- groups.forEach((group2) => {
19064
- let id = group2.id ?? "wall";
19065
- if (group2.type === "wall") id = "wall";
19066
- map2.append(id, line);
19067
- });
19068
- return map2;
19069
- }, new ArrayMap());
19070
- return map;
19071
- }
19072
- function handleGroup(map) {
19073
- const group2 = map.group((lines) => {
19074
- if (LineGroupType.everyType(lines, "bayWindow")) return "wall";
19075
- if (LineGroupType.everyType(lines, "doubleWall")) return "doubleWall";
19076
- return "wall";
19077
- }), walls = group2.get("wall") ?? [], doubleWalls = group2.get("doubleWall") ?? [];
19078
- let newlines = [], doubleWallsSet = new Set(doubleWalls.flat());
19079
- walls.forEach((lines) => {
19080
- lines.forEach((line) => doubleWallsSet.has(line) || newlines.push(line));
19081
- });
19082
- doubleWalls.forEach((lines) => {
19083
- lines = [...new Set(lines)];
19084
- const groups = clippingDoubleWall(lines);
19085
- groups.forEach((lines2) => {
19086
- if (lines2.length < 4) return newlines.push(...lines2);
19087
- lines2 = lines2.sort((a2, b4) => a2.length() - b4.length());
19088
- const line1 = lines2[0], line2 = lines2[1];
19089
- const newLine = new LineSegment(line1.center.clone(), line2.center.clone());
19090
- mergeLineUserData(newLine, lines2);
19091
- newLine.userData.wallWidth = line1.length();
19092
- newlines.push(newLine);
19093
- mergeWindow(newLine);
19094
- });
19095
- });
19096
- newlines = newlines.map((line) => line.clone());
19097
- return newlines.filter((line) => !line.userData.isBayWindow);
19098
- }
19099
- function toJson(lineSegments, name = "测试", communityName = "") {
19100
- const scale2 = 1, idMap = /* @__PURE__ */ new Map();
19101
- let index2 = 0;
19102
- return {
19103
- version: "2",
19104
- name,
19105
- communityName,
19106
- city: "",
19107
- province: "",
19108
- height: DEFAULT_WALL_HEIGHT * scale2,
19109
- walls: lineSegments.map((line) => {
19110
- if (line.userData.isDoor && !line.userData.doorDirectConnection) return;
19111
- idMap.set(line, index2);
19112
- return {
19113
- ID: index2++,
19114
- start: { x: line.start.x * scale2, y: line.start.y * scale2 },
19115
- end: { x: line.end.x * scale2, y: line.end.y * scale2 },
19116
- thickness: (line.userData.wallWidth ? line.userData.wallWidth : 0.12) * scale2,
19117
- type: "LINE",
19118
- isDoor: line.userData.isDoor,
19119
- loadBearingWall: false,
19120
- height: (line.userData.height ?? DEFAULT_WALL_HEIGHT) * scale2
19121
- };
19122
- }).filter((i) => !!i),
19123
- pillars: [],
19124
- beams: [],
19125
- holes: lineSegments.flatMap((line) => {
19126
- if (line.userData.isDoor && line.userData.doorDirectConnection) {
19127
- return {
19128
- id: index2++,
19129
- type: "DOOR",
19130
- openSide: "RIGHT",
19131
- start: {
19132
- x: line.start.x * scale2,
19133
- y: line.start.y * scale2
19134
- },
19135
- end: {
19136
- x: line.end.x * scale2,
19137
- y: line.end.y * scale2
19138
- },
19139
- height: (line.userData.drawDoorData?.height ?? DEFAULT_DOOR_HEIGHT) * scale2,
19140
- qroundClearance: (line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT) * scale2,
19141
- sillHeight: (line.userData.drawDoorData?.sillHeight ?? DOOR_GROUND_CLEARANCE_HEIGHT) * scale2
19142
- };
19143
- } else if (line.userData.isWindow && line.userData.drawWindow) {
19144
- return line.userData.drawWindow.map((item) => {
19145
- const center = Point.from(item.p);
19146
- const start = center.clone().add(
19147
- line.direction().multiplyScalar(item.width * 0.5)
19148
- );
19149
- const end = center.clone().add(
19150
- line.direction().multiplyScalar(-item.width * 0.5)
19151
- );
19152
- return {
19153
- id: index2++,
19154
- type: "WINDOW",
19155
- start: {
19156
- x: start.x * scale2,
19157
- y: start.y * scale2
19158
- },
19159
- end: {
19160
- x: end.x * scale2,
19161
- y: end.y * scale2
19162
- },
19163
- height: (item.height ?? DEFAULT_WINDOW_HEIGHT) * scale2,
19164
- groundClearance: (item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT) * scale2,
19165
- sillHeight: (item?.groundClearance ?? WINDOW_GROUND_CLEARANCE_HEIGHT) * scale2
19166
- };
19167
- });
19168
- }
19169
- }).filter((i) => !!i),
19170
- rooms: []
19171
- };
19172
- }
19173
- function lineDataToThreeVJiaJson(lineSegments, angle = 0, updateGroup = true) {
19174
- const group2 = getGroups(lineSegments, updateGroup);
19175
- let newLines = handleGroup(group2);
19176
- newLines = LineSegmentUndirectedGraph.rotate(newLines, angle, (line, center, angle2) => {
19177
- if (line.userData.drawWindow) {
19178
- line.userData.drawWindow.forEach((windowItem) => {
19179
- const point2 = Point.from(windowItem.p);
19180
- point2.rotate(center, angle2);
19181
- windowItem.p = point2.toJson(windowItem.p.z);
19182
- });
19183
- }
19184
- });
19185
- return {
19186
- lines: newLines,
19187
- toJson(name = "测试", communityName = "") {
19188
- return toJson(newLines, name, communityName);
19189
- }
19190
- };
19191
- }
19192
19318
  class ThreeVJia extends Component {
19193
19319
  static name = "ThreeVJia";
19194
19320
  lineSegments = [];
@@ -19207,7 +19333,7 @@ class ThreeVJia extends Component {
19207
19333
  updateData() {
19208
19334
  if (!this.neededUpdate) return;
19209
19335
  const angleCorrectionDxf = this.parent?.findComponentByName("CorrectionDxf");
19210
- this.cacheJson = lineDataToThreeVJiaJson(angleCorrectionDxf.getLineSegments(), 0).toJson();
19336
+ this.cacheJson = lineDataToThreeVJiaJson(angleCorrectionDxf.getLineSegments(), angleCorrectionDxf.angle).toJson();
19211
19337
  this.neededUpdate = false;
19212
19338
  }
19213
19339
  /** 转为json
@@ -19328,7 +19454,7 @@ function drawLines$1(lines, parameters, offset2 = 1e-3) {
19328
19454
  }
19329
19455
  }
19330
19456
  }
19331
- function drawPoint(point2, parameters, offset2 = 1e-3) {
19457
+ function drawPoint$1(point2, parameters, offset2 = 1e-3) {
19332
19458
  const dxfSystem = DxfSystem.finalInstance;
19333
19459
  if (dxfSystem) {
19334
19460
  const renderer = dxfSystem.findComponentByName("Renderer");
@@ -21416,7 +21542,7 @@ const index$2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePrope
21416
21542
  findVerticalReference,
21417
21543
  gltf,
21418
21544
  lineDataToOriginalData,
21419
- lineDataToThreeVJiaJson: lineDataToThreeVJiaJson$1,
21545
+ lineDataToThreeVJiaJson,
21420
21546
  lineSegmentClipping,
21421
21547
  mergeLineUserData,
21422
21548
  mergeWindow,
@@ -21516,7 +21642,7 @@ class Log {
21516
21642
  }
21517
21643
  if (typeof window !== "undefined") {
21518
21644
  window.drawLines = drawLines$1;
21519
- window.drawPoint = drawPoint;
21645
+ window.drawPoint = drawPoint$1;
21520
21646
  window.drawText = drawText$1;
21521
21647
  window.randomColor = () => Math.floor(Math.random() * 16777215);
21522
21648
  window.Log = Log;
@@ -21590,7 +21716,10 @@ async function buildJson(opt) {
21590
21716
  }
21591
21717
  }
21592
21718
  doorFind && (dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorSpaceHandle), dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorFind), dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoorSpaceHandle));
21593
- if (opt.axisAlignCorr !== false) dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
21719
+ if (opt.axisAlignCorr !== false) {
21720
+ dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
21721
+ dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.shortLinkMerging);
21722
+ }
21594
21723
  if (trajectory) {
21595
21724
  if (typeof trajectory === "string") {
21596
21725
  if (typeof global !== "undefined") {
@@ -7,7 +7,7 @@ import { Dxf } from './Dxf';
7
7
  */
8
8
  export declare class CorrectionDxf<TEventMap extends {} = {}> extends Dxf<{} & TEventMap> {
9
9
  static name: string;
10
- static readonly PRE_PROCESSOR: Record<"DoorFind" | "DoorPointCorr" | "DoorSpaceHandle" | "clipDoubleWall" | "AxisAlignCorr" | "BoundExt" | "AngleCorr" | "ResetGeometricCenter" | "WallHeightHandle" | "Clipping" | "RemoveShortLine", (lines: import('../..').LineSegment[], option: SetDataOption, ...arg: any[]) => import('../..').LineSegment[]>;
10
+ static readonly PRE_PROCESSOR: Record<"DoorFind" | "shortLinkMerging" | "removeShortDoubleWall" | "DoorPointCorr" | "DoorSpaceHandle" | "clipDoubleWall" | "AxisAlignCorr" | "BoundExt" | "DoubleWallAlignment" | "AngleCorr" | "ResetGeometricCenter" | "WallHeightHandle" | "Clipping" | "RemoveShortLine", (lines: import('../..').LineSegment[], option: SetDataOption, ...arg: any[]) => import('../..').LineSegment[]>;
11
11
  rotateCorrCad?: CAD;
12
12
  angle: number;
13
13
  constructor();
@@ -5,7 +5,7 @@ import { Quadtree } from '../../Quadtree';
5
5
  import { SetDataOption, DataItem, LineUserData, OriginalDataItem, Unit } from '../type';
6
6
  import { CAD } from '../utils/CAD';
7
7
  type PreProcessor = (lines: LineSegment[], option: SetDataOption, ...arg: any[]) => LineSegment[];
8
- type PreProcessorType = "DoorFind" | "DoorPointCorr" | "DoorSpaceHandle" | "clipDoubleWall" | "AxisAlignCorr" | "BoundExt" | "AngleCorr" | "ResetGeometricCenter" | "WallHeightHandle" | "Clipping" | "RemoveShortLine";
8
+ type PreProcessorType = "DoorFind" | "shortLinkMerging" | "removeShortDoubleWall" | "DoorPointCorr" | "DoorSpaceHandle" | "clipDoubleWall" | "AxisAlignCorr" | "BoundExt" | "DoubleWallAlignment" | "AngleCorr" | "ResetGeometricCenter" | "WallHeightHandle" | "Clipping" | "RemoveShortLine";
9
9
  /**
10
10
  * 默认提供的预处理函数
11
11
  */
@@ -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/lineDataToThreeVJiaJsonOld';
4
+ import { ThreeVJiaJsonObject } from '../utils/lineDataToThreeVJiaJson';
5
5
  /**
6
6
  * 转为 三维家 墙体结构
7
7
  */
@@ -29,6 +29,7 @@ export type WallLineGlobalOption = {
29
29
  isDoor?: boolean;
30
30
  doorAutomaticFind?: boolean;
31
31
  doorDirectConnection?: boolean;
32
+ isPassageEntrance?: boolean;
32
33
  topClearance?: number;
33
34
  isVerticalReferenceLine?: boolean;
34
35
  insetionArr?: {
@@ -74,6 +75,19 @@ export type WallLineGlobalOption = {
74
75
  groundClearance: number;
75
76
  sillHeight?: number;
76
77
  };
78
+ passageEntrance?: {
79
+ p: {
80
+ x: number;
81
+ y: number;
82
+ z: number;
83
+ };
84
+ width: number;
85
+ full: boolean;
86
+ rooftopPz?: number;
87
+ uuid?: string;
88
+ height?: number;
89
+ groundClearance?: number;
90
+ }[];
77
91
  };
78
92
  export type LineUserData = {
79
93
  quadtreeNode?: QuadtreeNode;
@@ -0,0 +1,18 @@
1
+ import { LineSegment } from '../../LineSegment';
2
+ import { LineUserData } from '../type';
3
+ import { PointVirtualGrid } from '../../PointVirtualGrid';
4
+ /**
5
+ * @param line
6
+ */
7
+ export declare function peDrawLine(line: LineSegment<LineUserData>, grid?: PointVirtualGrid): LineSegment<any>[] | null;
8
+ /** 获取双线窗户线段
9
+ * @param lines
10
+ * @returns
11
+ */
12
+ export declare function doublePEDrawLine(lines: LineSegment<LineUserData>[]): LineSegment<any>[] | null;
13
+ /** 获取窗户线段
14
+ * @param doubleWallGroup
15
+ * @param wall
16
+ * @returns
17
+ */
18
+ export declare function getWinDrawData(doubleWallGroup: LineSegment[][], wall: LineSegment[], lines?: LineSegment<LineUserData>[]): LineSegment<Record<string, any>>[];
@@ -51,7 +51,10 @@ export type ThreeVJiaJsonObject = {
51
51
  export declare class ThreeVJiaJson extends HandlerFlow<ThreeVJiaJsonObject> {
52
52
  manager: WallGroupManager;
53
53
  index: number;
54
- constructor(lines: LineSegment[]);
54
+ version: string;
55
+ maxHeight: number;
56
+ lines: LineSegment[];
57
+ constructor(lines: LineSegment[], maxHeight: number);
55
58
  /** 双线墙处理
56
59
  * @param param0
57
60
  * @returns
@@ -66,7 +69,7 @@ export declare class ThreeVJiaJson extends HandlerFlow<ThreeVJiaJsonObject> {
66
69
  * 门线处理
67
70
  * @param param0
68
71
  */
69
- doorHandle({ lines }: IGroup, option?: ThreeVJiaJsonObject): never[];
72
+ doorHandle({ lines }: IGroup, option?: ThreeVJiaJsonObject): LineSegment<LineUserData>[];
70
73
  /**
71
74
  * 窗线处理
72
75
  * @param param0
@@ -82,6 +85,7 @@ export declare class ThreeVJiaJson extends HandlerFlow<ThreeVJiaJsonObject> {
82
85
  * @returns
83
86
  */
84
87
  balconyRailing({ lines }: IGroup<IDrawBayWindowData>): LineSegment<LineUserData>[];
88
+ findRooms(lines: LineSegment<LineUserData>[]): void;
85
89
  /** 装换
86
90
  * @returns
87
91
  */
@@ -28,6 +28,11 @@ export declare class Polygon<T = any> extends Array<Point<T>> {
28
28
  */
29
29
  area(): number;
30
30
  closedLoop(): boolean;
31
+ /** 闭合路径向路径外膨胀width
32
+ * @param width
33
+ */
34
+ closedExpansion(width: number, scale?: number): this | null;
35
+ clipByLine(line: LineSegment): Polygon<Record<string, any>>[];
31
36
  /**
32
37
  * 获取点相对于多边形的位置
33
38
  * @param point