build-dxf 0.1.95 → 0.1.96

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.95",
3
+ "version": "0.1.96",
4
4
  "description": "线段构建双线墙壁的dxf版本",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
package/src/build.js CHANGED
@@ -1926,6 +1926,15 @@ class PointSpatialHash {
1926
1926
  if (list.size === 1) return [...list][0];
1927
1927
  }
1928
1928
  }
1929
+ /** 通过点快速创建
1930
+ * @param lines
1931
+ * @returns
1932
+ */
1933
+ static from(points) {
1934
+ const psh = new PointSpatialHash();
1935
+ points.forEach((p2, index2) => psh.insert(p2, index2));
1936
+ return psh;
1937
+ }
1929
1938
  /** 通过线段快速创建
1930
1939
  * @param lines
1931
1940
  * @returns
@@ -2989,6 +2998,9 @@ class UnionFindSet {
2989
2998
  }
2990
2999
  }
2991
3000
  class LineSegmentUtils {
3001
+ clone(lines) {
3002
+ return lines.map((line) => line.clone());
3003
+ }
2992
3004
  /** 获取最长线段索引
2993
3005
  * @param lines
2994
3006
  */
@@ -19178,15 +19190,27 @@ function removeDangline(lines, len = 0.01, consecutive = false) {
19178
19190
  return [...defaultLines, ...doorLines];
19179
19191
  }
19180
19192
  const DELETE_SYMBOL = /* @__PURE__ */ Symbol("DELETE_SYMBOL");
19181
- const INTERSECT_COUNT = /* @__PURE__ */ Symbol("INTERSECT_COUNT");
19182
19193
  function fitting(lines) {
19183
19194
  const index2 = LineSegmentUtils.maxLengthLineIndex(lines);
19184
19195
  if (index2 === -1) throw Error("未找到最长线段");
19185
19196
  const maxLine = lines[index2], center = LineSegmentUtils.getLinesCenter(lines), direct = maxLine.direction(), start = center.clone().add(direct.clone().multiplyScalar(-1)), end = center.clone().add(direct.clone().multiplyScalar(1));
19186
19197
  return new LineSegment(start, end);
19187
19198
  }
19188
- function layoutDesign(lines, axis) {
19189
- const blocks = lines.map((line, index2) => {
19199
+ function sortByAxis(lines, axis) {
19200
+ lines.sort((a2, b4) => {
19201
+ const sa2 = axis.projectPointValue(a2.start);
19202
+ const sb = axis.projectPointValue(b4.start);
19203
+ if (Math.abs(sa2 - sb) < 1e-6) {
19204
+ const aLen = axis.projectPointValue(a2.end) - sa2;
19205
+ const bLen = axis.projectPointValue(b4.end) - sb;
19206
+ return bLen - aLen;
19207
+ }
19208
+ return sa2 - sb;
19209
+ });
19210
+ return lines;
19211
+ }
19212
+ function layoutDesign(lines, axis, intersectPoints) {
19213
+ let blocks = lines.map((line, index2) => {
19190
19214
  const sv = axis.projectPointValue(line.start), ev = axis.projectPointValue(line.end), range = sv < ev ? [sv, ev] : [ev, sv];
19191
19215
  return { range, index: index2, rangeSize: range[1] - range[0] };
19192
19216
  });
@@ -19199,10 +19223,10 @@ function layoutDesign(lines, axis) {
19199
19223
  const block = blocks[i], line = lines[block.index], ranges = [];
19200
19224
  let start = block.range[0];
19201
19225
  for (let j = i + 1; j < blocks.length; j++) {
19202
- const nextBlock = blocks[j], nextLine = lines[nextBlock.index];
19226
+ const nextBlock = blocks[j];
19203
19227
  const overlap = Math.min(block.range[1], nextBlock.range[1]) - Math.max(block.range[0], nextBlock.range[0]);
19204
19228
  if (overlap < 0) break;
19205
- else if (!(overlap >= nextBlock.rangeSize && nextLine?.currentData[INTERSECT_COUNT] === 0) && nextBlock.range[0] > start) {
19229
+ if (nextBlock.range[0] > start) {
19206
19230
  ranges.push([start, nextBlock.range[0]]);
19207
19231
  }
19208
19232
  start = Math.max(start, nextBlock.range[1]);
@@ -19210,8 +19234,10 @@ function layoutDesign(lines, axis) {
19210
19234
  if (start < block.range[1]) ranges.push([start, block.range[1]]);
19211
19235
  for (let j = 0; j < ranges.length; j++) {
19212
19236
  const range = ranges[j], start2 = axis.pointAt(range[0]), end = axis.pointAt(range[1]);
19213
- if (j === 0) line.set(start2, end);
19214
- else {
19237
+ if (j === 0) {
19238
+ line.set(start2, end);
19239
+ newLines.push(line);
19240
+ } else {
19215
19241
  let newLine = line.clone();
19216
19242
  newLine.set(start2, end);
19217
19243
  newLines.push(newLine);
@@ -19219,6 +19245,17 @@ function layoutDesign(lines, axis) {
19219
19245
  }
19220
19246
  if (ranges.length === 0) line.currentData[DELETE_SYMBOL] = true;
19221
19247
  }
19248
+ sortByAxis(newLines, axis);
19249
+ const psh = PointSpatialHash.from(intersectPoints);
19250
+ for (let i = 0; i < newLines.length - 1; i++) {
19251
+ const line = newLines[i];
19252
+ if (psh.queryPoint(line.end).length !== 0) continue;
19253
+ const nextLine = newLines[i + 1];
19254
+ nextLine.start.copy(line.start);
19255
+ line.currentData[DELETE_SYMBOL] = true;
19256
+ mergeLineUserData(nextLine, line);
19257
+ }
19258
+ lines.length = 0;
19222
19259
  lines.push(...newLines);
19223
19260
  return lines;
19224
19261
  }
@@ -19258,21 +19295,20 @@ class AlignToParallelSegments {
19258
19295
  const group = groups[i];
19259
19296
  if (group.length <= 1) continue;
19260
19297
  const axisLine = fitting(group);
19298
+ const points = [];
19261
19299
  for (let j = 0; j < group.length; j++) {
19262
19300
  const line = group[j];
19263
- let intersectCount = 0;
19264
19301
  line.points.forEach((p2) => {
19265
19302
  const intersectPoints = grid.queryCircle(p2, 1e-4).map((result) => result.point);
19266
- axisLine.pointAt(axisLine.projectPointValue(p2), p2);
19303
+ const pv = axisLine.projectPointValue(p2);
19304
+ axisLine.pointAt(pv, p2);
19267
19305
  intersectPoints.forEach((point2) => point2.copy(p2));
19268
- intersectCount += intersectPoints.length;
19306
+ points.push(...intersectPoints);
19269
19307
  });
19270
- line.currentData[INTERSECT_COUNT] = intersectCount;
19271
19308
  }
19272
- layoutDesign(group, axisLine);
19309
+ layoutDesign(group, axisLine, points);
19273
19310
  }
19274
19311
  return groups.flat().filter((line) => {
19275
- delete line.currentData[INTERSECT_COUNT];
19276
19312
  if (line.length() < 1e-9) return false;
19277
19313
  if (line.currentData[DELETE_SYMBOL]) {
19278
19314
  delete line.currentData[DELETE_SYMBOL];
@@ -19285,152 +19321,23 @@ class AlignToParallelSegments {
19285
19321
  * @param lines
19286
19322
  * @returns
19287
19323
  */
19288
- static align(lines, esp = 0.05, gap = 0.01) {
19324
+ static align(lines, esp = 0.05, gap = 0.05) {
19289
19325
  const axisLine = lines[0], axisLineV = axisLine.clone().rotate(Math.PI * 0.5, axisLine.center);
19290
19326
  let [pllLines, verticalLines] = LineSegmentUtils.groupByParallelToAxis(lines, axisLine);
19291
19327
  const groups = this.group(pllLines, axisLine, axisLineV, esp, gap);
19292
19328
  pllLines = this.fittingAlignment(groups, verticalLines);
19293
- verticalLines = verticalLines.filter((line) => line.length() > 1e-9);
19329
+ verticalLines = verticalLines.filter((line) => line.length() > 1e-6);
19330
+ TEST = true;
19294
19331
  const groups2 = this.group(verticalLines, axisLineV, axisLine, esp, gap);
19295
19332
  verticalLines = this.fittingAlignment(groups2, pllLines);
19333
+ TEST = false;
19334
+ pllLines = pllLines.filter((line) => line.length() > 1e-6);
19296
19335
  return [
19297
19336
  ...pllLines,
19298
19337
  ...verticalLines
19299
19338
  ];
19300
19339
  }
19301
19340
  }
19302
- function getNextPoint(point2, line, next, width) {
19303
- if (next.length === 0) {
19304
- const direct = point2.directionFrom(line.getAnotherPoint(point2));
19305
- return point2.clone().add(direct.multiplyScalar(width));
19306
- }
19307
- const p2 = next[0].userData.projectPoint(point2, false);
19308
- if (!p2) return false;
19309
- return p2;
19310
- }
19311
- function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
19312
- const grid = createPointSpatialHash(lineSegments);
19313
- function getIntersInfo(line, point2) {
19314
- const intersList = grid.queryCircle(point2, 1e-4).filter((item) => item.point !== point2);
19315
- if (intersList.length == 0) return;
19316
- let firstLine = null, firstPoint = null;
19317
- let count = 0;
19318
- let parallel2 = new PvgList();
19319
- for (let i = 0; i < intersList.length; i++) {
19320
- const res = intersList[i];
19321
- if (line.isPerpendicularTo(res.userData, 10)) {
19322
- count++;
19323
- firstLine = res.userData;
19324
- firstPoint = res.point;
19325
- } else {
19326
- parallel2.push(res);
19327
- }
19328
- }
19329
- if (count !== 1) return;
19330
- if (!firstLine || !firstPoint) return;
19331
- const firstOtherPoint = firstLine.getAnotherPoint(firstPoint);
19332
- const nextResult = grid.queryCircle(firstOtherPoint, 1e-4).filter((item) => item.point !== firstOtherPoint);
19333
- return {
19334
- length: firstLine.length(),
19335
- firstLine,
19336
- firstPoint,
19337
- firstOtherPoint,
19338
- direction: firstOtherPoint.directionFrom(firstPoint),
19339
- nextOnlyVertical: nextResult.every((d2) => d2.userData.isPerpendicularTo(firstLine)),
19340
- next: nextResult,
19341
- parallel: parallel2
19342
- };
19343
- }
19344
- const removeLinesSet = /* @__PURE__ */ new Set();
19345
- for (let i = 0; i < lineSegments.length; i++) {
19346
- const line = lineSegments[i];
19347
- if (removeLinesSet.has(line)) continue;
19348
- const len = line.length();
19349
- if (len > findMinWidth) continue;
19350
- const startInfo = getIntersInfo(line, line.start);
19351
- if (!startInfo) continue;
19352
- const endInfo = getIntersInfo(line, line.end);
19353
- if (!endInfo) continue;
19354
- const angle = startInfo.direction.angle(endInfo.direction, { unit: "degree", range: "180" });
19355
- if (angle < 170) continue;
19356
- if (!startInfo.nextOnlyVertical && !endInfo.nextOnlyVertical) continue;
19357
- let mainInfo = startInfo, secondaryInfo = endInfo;
19358
- if (startInfo.nextOnlyVertical && endInfo.nextOnlyVertical) {
19359
- if (startInfo.length < endInfo.length) {
19360
- mainInfo = endInfo;
19361
- secondaryInfo = startInfo;
19362
- }
19363
- } else if (startInfo.nextOnlyVertical) {
19364
- mainInfo = endInfo;
19365
- secondaryInfo = startInfo;
19366
- }
19367
- const parallel2 = startInfo.parallel.concat(endInfo.parallel);
19368
- const newPoint = getNextPoint(mainInfo.firstPoint, mainInfo.firstLine, secondaryInfo.next, secondaryInfo.length);
19369
- if (!newPoint) continue;
19370
- removeLinesSet.add(line);
19371
- line.points.forEach((p2) => grid.remove(p2));
19372
- if (parallel2.length === 0) {
19373
- const oldLine = mainInfo.firstLine.clone();
19374
- mainInfo.firstPoint.copy(newPoint);
19375
- secondaryInfo.next.forEach((d2) => d2.point.copy(newPoint));
19376
- removeLinesSet.add(secondaryInfo.firstLine);
19377
- secondaryInfo.firstLine.points.forEach((p2) => grid.remove(p2));
19378
- mainInfo.firstLine.points.forEach((p2) => grid.update(p2));
19379
- if (typeof onMerge === "function") onMerge(mainInfo.firstLine, line, secondaryInfo.firstLine, oldLine);
19380
- } else {
19381
- secondaryInfo.firstPoint.copy(mainInfo.firstPoint);
19382
- secondaryInfo.firstOtherPoint.copy(newPoint);
19383
- secondaryInfo.next.forEach((d2) => d2.point.copy(newPoint));
19384
- startInfo.parallel.concat(endInfo.parallel).forEach((item) => item.point.copy(mainInfo.firstPoint));
19385
- secondaryInfo.firstLine.points.forEach((p2) => grid.update(p2));
19386
- secondaryInfo.next.forEach((d2) => grid.update(d2.point));
19387
- startInfo.parallel.concat(endInfo.parallel).forEach((item) => grid.update(item.point));
19388
- }
19389
- }
19390
- lineSegments = lineSegments.filter((line) => !removeLinesSet.has(line));
19391
- return lineSegments;
19392
- }
19393
- function repetitiveTask(count, callfun) {
19394
- for (let i = 0; i < count; i++) {
19395
- callfun(i);
19396
- }
19397
- }
19398
- function stepEliminationMerge(target, _, source, oldLine) {
19399
- if (source.userData.isDoor) WallInsertObject.addInsertObject(target, {
19400
- p: source.center.toJson(),
19401
- width: source.length(),
19402
- full: false,
19403
- type: "door",
19404
- height: source.userData.drawDoorData.height,
19405
- groundClearance: source.userData.drawDoorData.groundClearance
19406
- });
19407
- if (target.userData.isDoor) {
19408
- delete target.userData.isDoor;
19409
- WallInsertObject.addInsertObject(target, {
19410
- p: oldLine.center.toJson(),
19411
- width: oldLine.length(),
19412
- full: false,
19413
- type: "door",
19414
- height: target.userData.drawDoorData?.height,
19415
- groundClearance: target.userData.drawDoorData?.groundClearance ?? 0
19416
- });
19417
- }
19418
- WallInsertObject.copyInsertObject(target, source);
19419
- WallInsertObject.recomputed([target]);
19420
- }
19421
- function linesSmoothing(lines, _) {
19422
- const other = [];
19423
- lines = lines.filter((line) => {
19424
- if (line.userData.isBayWindow) {
19425
- other.push(line);
19426
- return false;
19427
- }
19428
- return true;
19429
- });
19430
- repetitiveTask(2, () => lines = stepElimination(lines, 0.1, stepEliminationMerge));
19431
- WallInsertObject.recomputed(lines);
19432
- return [...lines, ...other];
19433
- }
19434
19341
  function shortDistanceLink(lines, radius = 0.1) {
19435
19342
  const dpSet = findDiscretePoint(lines.filter((line) => !line.userData.isDoor)), pointVirtualGrid = createPointSpatialHash(dpSet.map((v2) => v2)), appendLines = [], visited = /* @__PURE__ */ new Set();
19436
19343
  const getWeight2 = (target, point2, line) => {
@@ -19564,7 +19471,6 @@ function correction(lines, targettLine, option) {
19564
19471
  }
19565
19472
  new WallInsertObject(newLines).recomputed().merge();
19566
19473
  newLines = removeDangline(newLines, 0.15, true);
19567
- newLines = linesSmoothing(newLines);
19568
19474
  newLines.push(...otherLines);
19569
19475
  return newLines.filter((line) => line.length() > 1e-9);
19570
19476
  }
@@ -22522,7 +22428,6 @@ async function buildJson(opt) {
22522
22428
  if (opt.axisAlignCorr !== false) {
22523
22429
  dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
22524
22430
  dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.RemoveShortDoubleWall);
22525
- dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoubleWallAlignment);
22526
22431
  }
22527
22432
  if (trajectory2) {
22528
22433
  if (typeof trajectory2 === "string") {
@@ -1,6 +1,7 @@
1
1
  import { LineSegment } from './LineSegment';
2
2
  import { Point } from './Point';
3
3
  export declare class LineSegmentUtils {
4
+ clone(lines: LineSegment[]): LineSegment<Record<string, any>>[];
4
5
  /** 获取最长线段索引
5
6
  * @param lines
6
7
  */
@@ -108,6 +108,11 @@ export declare class PointSpatialHash<T = Record<string, any>> {
108
108
  /** 查找第一个游离的点
109
109
  */
110
110
  getFreePointFirst(): Target<T> | undefined;
111
+ /** 通过点快速创建
112
+ * @param lines
113
+ * @returns
114
+ */
115
+ static from(points: Point[]): PointSpatialHash<number>;
111
116
  /** 通过线段快速创建
112
117
  * @param lines
113
118
  * @returns