build-dxf 0.1.82 → 0.1.83

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.82",
3
+ "version": "0.1.83",
4
4
  "description": "线段构建双线墙壁的dxf版本",
5
5
  "main": "./src/index.js",
6
6
  "types": "./src/index.d.ts",
package/src/build.js CHANGED
@@ -1454,6 +1454,14 @@ class LineSegment {
1454
1454
  normal() {
1455
1455
  return this.points[1].normal(this.points[0]);
1456
1456
  }
1457
+ /**
1458
+ * @param line
1459
+ * @param t
1460
+ * @returns
1461
+ */
1462
+ pointAt(t2) {
1463
+ return new Point(this.start.x + (this.end.x - this.start.x) * t2, this.start.y + (this.end.y - this.start.y) * t2);
1464
+ }
1457
1465
  /** 膨胀为矩形
1458
1466
  *
1459
1467
  * @param width
@@ -2172,14 +2180,14 @@ class LineSegment {
2172
2180
  * @param clippingLine
2173
2181
  */
2174
2182
  static clippingByLine(target, clippingLine, callBack) {
2175
- const start = target.projectPoint(clippingLine.start), end = target.projectPoint(clippingLine.end);
2176
- const lines = this.clipping(target, [start, end].filter((i) => !!i), callBack);
2177
- return lines.filter((line) => {
2178
- const line0 = clippingLine.projectLineSegment(line);
2179
- if (line0.length() / clippingLine.length() > 0.8) return false;
2180
- return true;
2181
- });
2183
+ return this.clippingByLines(target, [clippingLine], callBack);
2182
2184
  }
2185
+ /** 通过线段组裁剪线段
2186
+ * @param target
2187
+ * @param clippingLines
2188
+ * @param callBack
2189
+ * @returns
2190
+ */
2183
2191
  static clippingByLines(target, clippingLines, callBack) {
2184
2192
  const eps = 1e-6;
2185
2193
  const intervals = clippingLines.map((line) => {
@@ -2192,15 +2200,38 @@ class LineSegment {
2192
2200
  callBack?.(target.clone(), target);
2193
2201
  return;
2194
2202
  }
2203
+ const merged = [];
2195
2204
  let cur = intervals[0];
2196
2205
  for (let i = 1; i < intervals.length; i++) {
2197
2206
  const next = intervals[i];
2198
2207
  if (next[0] <= cur[1] + eps) {
2199
2208
  cur[1] = Math.max(cur[1], next[1]);
2200
2209
  } else {
2210
+ merged.push(cur);
2201
2211
  cur = next;
2202
2212
  }
2203
2213
  }
2214
+ merged.push(cur);
2215
+ const newLines = [];
2216
+ let prev = 0;
2217
+ for (const [s, e] of merged) {
2218
+ if (s > prev + eps) {
2219
+ const newLine = new LineSegment(target.pointAt(prev), target.pointAt(s));
2220
+ if (newLine.length() > 1e-4) {
2221
+ newLines.push(newLine);
2222
+ callBack?.(newLine, target);
2223
+ }
2224
+ }
2225
+ prev = Math.max(prev, e);
2226
+ }
2227
+ if (prev < 1 - eps) {
2228
+ const newLine = new LineSegment(target.pointAt(prev), target.pointAt(1));
2229
+ if (newLine.length() > 1e-4) {
2230
+ newLines.push(newLine);
2231
+ callBack?.(newLine, target);
2232
+ }
2233
+ }
2234
+ return newLines;
2204
2235
  }
2205
2236
  static constrainLine(line, base) {
2206
2237
  const center = line.center, width = line.length();
@@ -3048,7 +3079,7 @@ class WallInsertObject {
3048
3079
  if (key === "passageEntrance") {
3049
3080
  if (type === "door") return 0.3;
3050
3081
  }
3051
- return 0;
3082
+ return 0.05;
3052
3083
  }
3053
3084
  getMinWidth(key, type) {
3054
3085
  return WallInsertObject.getMinWidth(key, type);
@@ -6724,8 +6755,6 @@ class DoubleWallHelper {
6724
6755
  quadtree
6725
6756
  };
6726
6757
  }
6727
- static appendLine() {
6728
- }
6729
6758
  /** 补双线墙壁
6730
6759
  * @param lines
6731
6760
  * @param wallWidth
@@ -6740,7 +6769,7 @@ class DoubleWallHelper {
6740
6769
  }
6741
6770
  return true;
6742
6771
  });
6743
- let { resultList, quadtree } = this.findDoubleLine(lines, wallWidth), otherQuadtree = createQuadtree(otherLines), removeLines = /* @__PURE__ */ new Set(), clipingMap = /* @__PURE__ */ new Map(), appendLines = [];
6772
+ let { resultList, quadtree } = this.findDoubleLine(lines, wallWidth), removeLines = /* @__PURE__ */ new Set(), clipingMap = /* @__PURE__ */ new Map(), appendLines = [];
6744
6773
  function addClipingMap(line, line1) {
6745
6774
  if (!clipingMap.has(line)) clipingMap.set(line, []);
6746
6775
  const startProj = line.projectPoint(line1.start);
@@ -6758,6 +6787,8 @@ class DoubleWallHelper {
6758
6787
  }
6759
6788
  const newLine1 = new LineSegment(project0.start.clone(), project1.start.clone());
6760
6789
  const newLine2 = new LineSegment(project0.end.clone(), project1.end.clone());
6790
+ newLine1.userData.height = line0.userData.height;
6791
+ newLine2.userData.height = line1.userData.height;
6761
6792
  appendLines.push(newLine1, newLine2);
6762
6793
  addClipingMap(line0, project0);
6763
6794
  addClipingMap(line1, project1);
@@ -6770,33 +6801,22 @@ class DoubleWallHelper {
6770
6801
  quadtree.clear();
6771
6802
  quadtree = new Quadtree(Box2.fromByLineSegment(...lines));
6772
6803
  lines.forEach((line) => line.userData.isDoor || quadtree.insert(line));
6773
- appendLines = LineSegment.mergeCollinearSegments(appendLines, mergeLineUserData);
6774
- appendLines = appendLines.filter((line) => line.length() !== 0).filter((line) => otherQuadtree.queryPoint(line.center).length === 0).map((line) => {
6775
- const list = quadtree.queryLineSegment(line).filter((item) => {
6776
- if (!item.line.isParallelTo(line)) return false;
6777
- if (item.line.projectLineSegment(line).length() === 0) return false;
6778
- return true;
6779
- }).map((item) => item.line);
6780
- if (list.length === 0) {
6781
- quadtree.insert(line);
6782
- return line;
6783
- }
6784
- const newLine = LineSegment.mergeLines(...list, line);
6785
- list.forEach((line2) => {
6786
- mergeLineUserData(newLine, line2);
6787
- quadtree.remove(line2);
6788
- removeLines.add(line2);
6789
- });
6790
- quadtree.insert(newLine);
6791
- return newLine;
6804
+ appendLines = lineSegmentClipping(appendLines, 1e-9);
6805
+ appendLines.flatMap((line) => {
6806
+ const queryLines = quadtree.queryLineSegment(line).filter((item) => item.line.isParallelTo(line)).map((item) => item.line);
6807
+ if (queryLines.length) {
6808
+ const newLines = LineSegment.clippingByLines(line, queryLines);
6809
+ if (newLines) return newLines.forEach((line2) => {
6810
+ quadtree.insert(line2);
6811
+ lines.push(line2);
6812
+ });
6813
+ }
6814
+ quadtree.insert(line);
6815
+ lines.push(line);
6792
6816
  });
6793
- appendLines = appendLines.filter((line) => !removeLines.has(line));
6794
- lines = lines.filter((line) => !removeLines.has(line));
6795
- lines.push(...appendLines);
6796
6817
  lines = lineSegmentClipping(lines, 1e-9);
6797
6818
  quadtree.clear();
6798
6819
  lines.push(...otherLines);
6799
- Point.adsorb(lines.flatMap((line) => line.points), 1e-4);
6800
6820
  return lines.filter((line) => line.length() > 1e-9);
6801
6821
  }
6802
6822
  /**
@@ -8277,67 +8297,6 @@ class DxfDataPlugin extends Pipeline {
8277
8297
  DxfDataPlugin.initData(cad, this.lines);
8278
8298
  }
8279
8299
  }
8280
- class LineQueryer {
8281
- pointVirtualGrid;
8282
- quadtree;
8283
- constructor(lines) {
8284
- this.pointVirtualGrid = createPointVirtualGrid(lines);
8285
- this.quadtree = createQuadtree(lines);
8286
- }
8287
- update(lines) {
8288
- this.clear();
8289
- this.pointVirtualGrid = createPointVirtualGrid(lines);
8290
- this.quadtree = createQuadtree(lines);
8291
- }
8292
- clear() {
8293
- this.pointVirtualGrid.clear();
8294
- this.quadtree.clear();
8295
- }
8296
- /**
8297
- * @param point
8298
- * @param radius
8299
- * @param opt
8300
- * @returns
8301
- */
8302
- queryNearestPoint(point2, opt) {
8303
- if (!point2) throw new Error("请传入查询点");
8304
- const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
8305
- const results = this.pointVirtualGrid.queryCircle(point2, radius).filter((item) => item.point !== point2).filter((item) => condition ? condition(item) : true);
8306
- results.sort((a2, b4) => a2.point.distance(point2, true) - b4.point.distance(point2, true));
8307
- if (results.length > resultIndex) return {
8308
- point: results[resultIndex].point,
8309
- line: results[resultIndex].userData
8310
- };
8311
- return null;
8312
- }
8313
- /**
8314
- * @param point
8315
- * @param radius
8316
- * @param opt
8317
- * @returns
8318
- */
8319
- queryNearestLine(point2, opt) {
8320
- if (!point2) throw new Error("请传入查询点");
8321
- const { resultIndex = 0, radius = 0.4, condition } = opt ?? {};
8322
- const results = this.quadtree.queryCircle(point2, radius).map((item) => {
8323
- const projPoint = item.line.projectPoint(point2, false);
8324
- if (projPoint && (!condition || condition(item, projPoint))) {
8325
- if (projPoint) return {
8326
- ...item,
8327
- distance: projPoint.distance(point2) ?? Infinity,
8328
- projPoint
8329
- };
8330
- }
8331
- return null;
8332
- }).filter((i) => !!i);
8333
- results.sort((a2, b4) => a2.distance - b4.distance);
8334
- if (results.length > resultIndex) return {
8335
- point: results[resultIndex].projPoint,
8336
- line: results[resultIndex].line
8337
- };
8338
- return null;
8339
- }
8340
- }
8341
8300
  function parallel(line, baseline) {
8342
8301
  const currentAngle = Math.atan2(line.end.y - line.start.y, line.end.x - line.start.x);
8343
8302
  const targetAngle = Math.atan2(baseline.end.y - baseline.start.y, baseline.end.x - baseline.start.x);
@@ -8508,66 +8467,6 @@ function preprocessing(lines) {
8508
8467
  quadtree.clear();
8509
8468
  return lines;
8510
8469
  }
8511
- function adsorption(lines, option) {
8512
- const { snapThreshold: threshold = 0.2 } = option ?? {}, lineQueryer = new LineQueryer(lines), modifyManager = LineSegment.createModifyManager();
8513
- function adsorptLine(point2, line) {
8514
- const otherPoint = line.getAnotherPoint(point2);
8515
- const direct = otherPoint.directionFrom(point2);
8516
- const len = line.length();
8517
- const result = lineQueryer.queryNearestLine(point2, {
8518
- radius: threshold,
8519
- condition: (node, projPoint) => {
8520
- if (line !== node.line && node.line.isPerpendicularTo(line, 35)) {
8521
- if (projPoint.distance(point2) < len) return true;
8522
- const direct2 = projPoint.directionFrom(point2);
8523
- return direct2.angleBetween(direct) > Math.PI * 0.5;
8524
- }
8525
- return false;
8526
- }
8527
- });
8528
- if (result) return modifyManager.setPoint(line, point2, result.point.clone());
8529
- }
8530
- function adsorptPoint(point2, line) {
8531
- const result = lineQueryer.queryNearestPoint(point2, {
8532
- radius: threshold,
8533
- condition(node) {
8534
- const line2 = node.userData;
8535
- return line2.isPerpendicularTo(line, 15);
8536
- }
8537
- });
8538
- if (result) {
8539
- const propPoint = result.line.projectPoint(point2, false);
8540
- if (propPoint) {
8541
- modifyManager.setPoint(line, point2, propPoint);
8542
- modifyManager.setPoint(result.line, result.point, propPoint);
8543
- }
8544
- }
8545
- }
8546
- for (let i = 0; i < lines.length; i++) {
8547
- const line = lines[i];
8548
- line.points.map((point2) => {
8549
- let results = lineQueryer.pointVirtualGrid.queryPoint(point2, true);
8550
- if (results.length === 0 && lineQueryer.quadtree.queryCircle(point2, 1e-4).length < 2) adsorptLine(point2, line);
8551
- });
8552
- }
8553
- modifyManager.modify();
8554
- lines = lines.filter((line) => line.length() > 1e-9);
8555
- const dpls = [...findDiscretePointLine2(lines)];
8556
- lineQueryer.update(lines);
8557
- for (let i = 0; i < dpls.length; i++) {
8558
- const line = dpls[i];
8559
- line.points.map((point2) => {
8560
- let results = lineQueryer.pointVirtualGrid.queryPoint(point2, true);
8561
- if (results.length === 0 && lineQueryer.quadtree.queryCircle(point2, 1e-4).length < 2) {
8562
- adsorptPoint(point2, line);
8563
- }
8564
- });
8565
- }
8566
- modifyManager.modify();
8567
- lineQueryer.clear();
8568
- Point.adsorb(lines.flatMap((line) => line.points), 1e-4, "first");
8569
- return lines;
8570
- }
8571
8470
  function removeShortLine(lines, len = 0.01) {
8572
8471
  let defaultLines = [], doorLines = [];
8573
8472
  for (let i = 0; i < lines.length; i++) {
@@ -8606,9 +8505,9 @@ function breakpointMerging(lines) {
8606
8505
  function axisAlignCorr$1(lines, targettLine, option) {
8607
8506
  lines = lines.map((line) => line.clone());
8608
8507
  lines = breakpointMerging(lines);
8508
+ lines = lineSegmentClipping(lines, 1e-9);
8609
8509
  lines = preprocessing(lines);
8610
8510
  lines = AxisAlignCorr.start(lines, targettLine);
8611
- lines = adsorption(lines, option);
8612
8511
  lines = lineSegmentClipping(lines, 1e-9);
8613
8512
  lines = removeShortLine(lines, 0.15);
8614
8513
  let newLines = lines.filter((line) => !line.userData.isDoor);
@@ -8625,6 +8524,7 @@ function axisAlignCorr$1(lines, targettLine, option) {
8625
8524
  newLines.push(...doorLines);
8626
8525
  Point.adsorb(newLines.flatMap((line) => line.points), 1e-4);
8627
8526
  lines = removeShortLine(lines, 0.05);
8527
+ lines = breakpointMerging(lines);
8628
8528
  return newLines;
8629
8529
  }
8630
8530
  class BoundExt {
@@ -18678,10 +18578,11 @@ class SceneAutoGenerat {
18678
18578
  return geometry;
18679
18579
  }
18680
18580
  getDoorAll(lines) {
18681
- return lines.filter((line) => line.userData.isDoor || WallInsertObject.isDoor(line));
18581
+ return lines.filter((line) => line.userData.isDoor || line.userData.isPassageEntrance);
18682
18582
  }
18683
18583
  buildPlane(lines) {
18684
- lines = lineSegmentClipping(lines, 0);
18584
+ lines = lineSegmentClipping(lines.map((line) => line.clone()), 0);
18585
+ Point.adsorb(lines.flatMap((line) => line.points), 1e-4);
18685
18586
  LineSegment.groupByPath(lines).forEach((group, i) => {
18686
18587
  const removeSet = findDiscretePointLine2(group, null, true);
18687
18588
  let lines2 = group.filter((line) => !removeSet.has(line) && !line.userData.isBayWindow);
@@ -19144,9 +19045,7 @@ function doubleWallAlignment(lines) {
19144
19045
  lines = [singleWall, newDoubleWalls].flat(10);
19145
19046
  lines = LineSegmentUndirectedGraph.breakpointMerging(lines, mergeLineUserData);
19146
19047
  lines = lineSegmentClipping(lines, 1e-9);
19147
- TEST = true;
19148
19048
  lines = buildDoubleWallGroup(lines);
19149
- TEST = false;
19150
19049
  lines.push(...doorLines);
19151
19050
  WallInsertObject.recomputed(lines);
19152
19051
  return lines;
@@ -12,7 +12,7 @@ export declare class SceneAutoGenerat {
12
12
  constructor(lines: LineSegment[], itemList: any[], z: number, trajectory?: any);
13
13
  init(): Promise<void>;
14
14
  private createGeometryByLines;
15
- getDoorAll(lines: LineSegment[]): LineSegment<Record<string, any>>[];
15
+ getDoorAll(lines: LineSegment<LineUserData>[]): LineSegment<LineUserData>[];
16
16
  buildPlane(lines: LineSegment<LineUserData>[]): void;
17
17
  wallGroup: Group | null;
18
18
  /** 构建墙壁
@@ -29,7 +29,6 @@ export declare class DoubleWallHelper {
29
29
  walls: LineSegment<LineUserData>[];
30
30
  quadtree: Quadtree<number>;
31
31
  };
32
- private static appendLine;
33
32
  /** 补双线墙壁
34
33
  * @param lines
35
34
  * @param wallWidth
@@ -41,8 +41,8 @@ export declare class WallInsertObject {
41
41
  * @param line
42
42
  * @returns
43
43
  */
44
- static getMinWidth(key: InsertObjectKey, type?: 'door'): 0 | 0.3;
45
- getMinWidth(key: InsertObjectKey, type?: 'door'): 0 | 0.3;
44
+ static getMinWidth(key: InsertObjectKey, type?: 'door'): 0.3 | 0.05;
45
+ getMinWidth(key: InsertObjectKey, type?: 'door'): 0.3 | 0.05;
46
46
  static clear(target: LineSegment, key: InsertObjectKey): void;
47
47
  /**
48
48
  * 重新计算
@@ -103,6 +103,12 @@ export declare class LineSegment<T = Record<string, any>> {
103
103
  * 获取发向量
104
104
  */
105
105
  normal(): Point<Record<string, any>>;
106
+ /**
107
+ * @param line
108
+ * @param t
109
+ * @returns
110
+ */
111
+ pointAt(t: number): Point<Record<string, any>>;
106
112
  /** 膨胀为矩形
107
113
  *
108
114
  * @param width
@@ -295,8 +301,14 @@ export declare class LineSegment<T = Record<string, any>> {
295
301
  * @param target
296
302
  * @param clippingLine
297
303
  */
298
- static clippingByLine(target: LineSegment, clippingLine: LineSegment, callBack?: (newLine: LineSegment, line: LineSegment) => void): LineSegment<Record<string, any>>[];
299
- static clippingByLines(target: LineSegment, clippingLines: LineSegment[], callBack?: (newLine: LineSegment, line: LineSegment) => void): void;
304
+ static clippingByLine(target: LineSegment, clippingLine: LineSegment, callBack?: (newLine: LineSegment, line: LineSegment) => void): LineSegment<Record<string, any>>[] | undefined;
305
+ /** 通过线段组裁剪线段
306
+ * @param target
307
+ * @param clippingLines
308
+ * @param callBack
309
+ * @returns
310
+ */
311
+ static clippingByLines(target: LineSegment, clippingLines: LineSegment[], callBack?: (newLine: LineSegment, line: LineSegment) => void): LineSegment<Record<string, any>>[] | undefined;
300
312
  static constrainLine(line: LineSegment, base: LineSegment): LineSegment<Record<string, any>>;
301
313
  /** 创建线段修改管理器
302
314
  * @returns
@@ -1,93 +0,0 @@
1
- import { DxfSystem } from './utils/DxfSystem';
2
- import { LineUserData, OriginalDataItem, SetDataOption } from './utils/DxfSystem/type';
3
- import { WhiteModel } from './utils/DxfSystem/plugin/ModelDataPlugin/components/WhiteModel';
4
- import { LineSegment } from './utils';
5
- import * as THREE from "three";
6
- export { Dxf } from './utils/DxfSystem/components/Dxf';
7
- export * from './utils/DxfSystem/DxfSystem';
8
- export * as ModelDataPlugin from './utils/DxfSystem/plugin/ModelDataPlugin';
9
- export * as utils from './utils';
10
- /** 快捷创建编辑器
11
- * @param dom
12
- * @param camera
13
- * @returns
14
- */
15
- export declare function createEditor(dom: HTMLDivElement, camera?: THREE.Camera, orbitControls?: boolean, viewPermission?: 'admin'): Promise<{
16
- dxfSystem: DxfSystem;
17
- getFileAll: () => Promise<{
18
- dxf: File;
19
- obj: File;
20
- glb: File;
21
- gltf: File;
22
- json: File;
23
- jpg: File;
24
- correctionDxf: File;
25
- }>;
26
- }>;
27
- /**
28
- * @param originData
29
- * @param trajectory
30
- * @deprecated 已废弃,请勿使用
31
- */
32
- export declare function getModels(originData: OriginalDataItem[], trajectory: any, itemList: any): Promise<{
33
- glb: File;
34
- gltf: File;
35
- }>;
36
- type HandleJsonOption = {
37
- /** json数据或路径 */
38
- json: string | OriginalDataItem[];
39
- trajectory?: string | Record<string, any>;
40
- itemInfo?: string | Record<string, any>;
41
- axisAlignCorr?: boolean;
42
- axisAlignCorrOption?: SetDataOption;
43
- doorFind?: boolean;
44
- download?: {
45
- json?: string;
46
- dxf?: string;
47
- image?: string;
48
- correctionJson?: string;
49
- correctionDxf?: string;
50
- correctionImage?: string;
51
- gltf?: string;
52
- glb?: string;
53
- obj?: string;
54
- };
55
- };
56
- /** 快捷构建需要的json文件
57
- * @param opt
58
- * @returns
59
- */
60
- export declare function buildJson(opt: HandleJsonOption): Promise<{
61
- dxfSystem: DxfSystem;
62
- threeVJia: import('./utils').Component<{}> | null;
63
- whiteModel: WhiteModel | null;
64
- }>;
65
- /** 获取所有文件数据
66
- * @param dxfSystem
67
- */
68
- export declare function getFileAll(dxfSystem?: DxfSystem): Promise<{
69
- dxf: File;
70
- obj: File;
71
- glb: File;
72
- gltf: File;
73
- json: File;
74
- jpg: File;
75
- correctionDxf: File;
76
- }>;
77
- /** 获取全局DxfSystem
78
- * @returns
79
- */
80
- export declare function getGlobalDxfSystem(): DxfSystem | null;
81
- /** 检测原始数据线段一侧是否属于环
82
- * @param lineData
83
- * @param startIndex
84
- * @param direction
85
- * @returns
86
- */
87
- export declare function hasCircle(lineData: OriginalDataItem[], startIndex: number, direction: any): {
88
- readonly originalIndices: number[];
89
- readonly indices: number[];
90
- circle: LineSegment<Record<string, any>>[];
91
- originalLines: LineSegment<LineUserData>[];
92
- lines: LineSegment<Record<string, any>>[];
93
- } | null;