build-dxf 0.1.56 → 0.1.58
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
package/src/build.js
CHANGED
|
@@ -2223,8 +2223,8 @@ class LineSegment {
|
|
|
2223
2223
|
for (const line of lines) {
|
|
2224
2224
|
const p1 = line.start;
|
|
2225
2225
|
const p2 = line.end;
|
|
2226
|
-
const key1 = `${p1.x.toFixed(
|
|
2227
|
-
const key2 = `${p2.x.toFixed(
|
|
2226
|
+
const key1 = `${p1.x.toFixed(4)}_${p1.y.toFixed(4)}`;
|
|
2227
|
+
const key2 = `${p2.x.toFixed(4)}_${p2.y.toFixed(4)}`;
|
|
2228
2228
|
const key = key1 < key2 ? `${key1}_${key2}` : `${key2}_${key1}`;
|
|
2229
2229
|
if (!seen.has(key)) {
|
|
2230
2230
|
seen.add(key);
|
|
@@ -2660,6 +2660,7 @@ class Point {
|
|
|
2660
2660
|
* @returns
|
|
2661
2661
|
*/
|
|
2662
2662
|
static from(arr) {
|
|
2663
|
+
if (!arr) return new Point();
|
|
2663
2664
|
if (Array.isArray(arr)) {
|
|
2664
2665
|
return new Point(arr[0], arr[1]);
|
|
2665
2666
|
} else if ("x" in arr && "y" in arr) {
|
|
@@ -2667,7 +2668,7 @@ class Point {
|
|
|
2667
2668
|
} else if ("X" in arr && "Y" in arr) {
|
|
2668
2669
|
return new Point(arr.X, arr.Y);
|
|
2669
2670
|
}
|
|
2670
|
-
return
|
|
2671
|
+
return new Point();
|
|
2671
2672
|
}
|
|
2672
2673
|
static fromByList(arr) {
|
|
2673
2674
|
return arr.map((item) => Point.from(item));
|
|
@@ -4883,19 +4884,35 @@ class Polygon extends Array {
|
|
|
4883
4884
|
this.forEach((p2) => p2.multiplyScalar(scale2));
|
|
4884
4885
|
return this;
|
|
4885
4886
|
}
|
|
4887
|
+
round() {
|
|
4888
|
+
this.forEach((p2) => {
|
|
4889
|
+
p2.x = Math.round(p2.x);
|
|
4890
|
+
p2.y = Math.round(p2.y);
|
|
4891
|
+
});
|
|
4892
|
+
return this;
|
|
4893
|
+
}
|
|
4886
4894
|
/**
|
|
4887
4895
|
* @param polygon
|
|
4888
4896
|
*/
|
|
4889
|
-
union(
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
|
|
4897
|
-
|
|
4898
|
-
|
|
4897
|
+
union(polygons, scale2 = 1) {
|
|
4898
|
+
polygons = Polygon.booleanOp(this, polygons, {
|
|
4899
|
+
scale: scale2,
|
|
4900
|
+
type: "Union"
|
|
4901
|
+
});
|
|
4902
|
+
if (polygons.length !== 1) return false;
|
|
4903
|
+
this.set(polygons[0]);
|
|
4904
|
+
return true;
|
|
4905
|
+
}
|
|
4906
|
+
/** 差集
|
|
4907
|
+
* @param polygon
|
|
4908
|
+
*/
|
|
4909
|
+
difference(polygons, scale2 = 1) {
|
|
4910
|
+
polygons = Polygon.booleanOp(this, polygons, {
|
|
4911
|
+
scale: scale2,
|
|
4912
|
+
type: "Difference"
|
|
4913
|
+
});
|
|
4914
|
+
if (polygons.length !== 1) return false;
|
|
4915
|
+
this.set(polygons[0]);
|
|
4899
4916
|
return true;
|
|
4900
4917
|
}
|
|
4901
4918
|
/** 拆分为凸包
|
|
@@ -4936,6 +4953,10 @@ class Polygon extends Array {
|
|
|
4936
4953
|
}
|
|
4937
4954
|
return this;
|
|
4938
4955
|
}
|
|
4956
|
+
clone() {
|
|
4957
|
+
const polygon2 = new Polygon([...this].map((p2) => p2.clone()));
|
|
4958
|
+
return polygon2;
|
|
4959
|
+
}
|
|
4939
4960
|
/** 通过线段创建, 默认路径只有一条
|
|
4940
4961
|
* @param lines
|
|
4941
4962
|
* @returns
|
|
@@ -5023,6 +5044,53 @@ class Polygon extends Array {
|
|
|
5023
5044
|
}
|
|
5024
5045
|
return polygon2;
|
|
5025
5046
|
}
|
|
5047
|
+
/**
|
|
5048
|
+
* @param poly
|
|
5049
|
+
*/
|
|
5050
|
+
static ensureCCW(poly) {
|
|
5051
|
+
if (!ClipperLib.Clipper.Orientation(poly)) poly.reverse();
|
|
5052
|
+
}
|
|
5053
|
+
/** 布尔运算
|
|
5054
|
+
* @param subject
|
|
5055
|
+
* @param polygons
|
|
5056
|
+
* @param scale 数据缩放
|
|
5057
|
+
* @returns
|
|
5058
|
+
*/
|
|
5059
|
+
static booleanOp(subject, clips, opt) {
|
|
5060
|
+
const { type = "Union", subjectFillType = "NonZero", clipFillType = "NonZero", scale: scale2 = 100 } = opt;
|
|
5061
|
+
if (subject instanceof Polygon) subject = [subject];
|
|
5062
|
+
if (clips instanceof Polygon) clips = [clips];
|
|
5063
|
+
subject = subject.map((subject2) => subject2.clone().scale(scale2).round());
|
|
5064
|
+
clips = clips.map((clips2) => clips2.clone().scale(scale2).round());
|
|
5065
|
+
const clipper = new ClipperLib.Clipper();
|
|
5066
|
+
clipper.StrictlySimple = true;
|
|
5067
|
+
clipper.PreserveCollinear = true;
|
|
5068
|
+
subject = subject.map((p2) => {
|
|
5069
|
+
p2 = ClipperLib.Clipper.CleanPolygon(p2, 0.5 * scale2 / 100);
|
|
5070
|
+
Polygon.ensureCCW(p2);
|
|
5071
|
+
return p2;
|
|
5072
|
+
});
|
|
5073
|
+
clips = clips.map((p2) => {
|
|
5074
|
+
p2 = ClipperLib.Clipper.CleanPolygon(p2, 0.5 * scale2 / 100);
|
|
5075
|
+
Polygon.ensureCCW(p2);
|
|
5076
|
+
return p2;
|
|
5077
|
+
});
|
|
5078
|
+
clipper.AddPaths(subject, ClipperLib.PolyType.ptSubject, true);
|
|
5079
|
+
clipper.AddPaths(clips, ClipperLib.PolyType.ptClip, true);
|
|
5080
|
+
let solutions = [];
|
|
5081
|
+
clipper.Execute(
|
|
5082
|
+
ClipperLib.ClipType["ct" + type],
|
|
5083
|
+
solutions,
|
|
5084
|
+
ClipperLib.PolyFillType["pft" + subjectFillType],
|
|
5085
|
+
ClipperLib.PolyFillType["pft" + clipFillType]
|
|
5086
|
+
);
|
|
5087
|
+
const inv = 1 / scale2;
|
|
5088
|
+
const results = solutions.map((solution) => {
|
|
5089
|
+
solution = solution.map((p2) => new Point(p2.X * inv, p2.Y * inv));
|
|
5090
|
+
return new Polygon(solution);
|
|
5091
|
+
}).filter((poly) => Math.abs(poly.area()) > 0.01);
|
|
5092
|
+
return results;
|
|
5093
|
+
}
|
|
5026
5094
|
}
|
|
5027
5095
|
async function include(path, exportDefault = true) {
|
|
5028
5096
|
if (typeof global !== "undefined" && typeof require !== "undefined") {
|
|
@@ -5464,11 +5532,41 @@ function getLineIndexByCenter(targetLines, lines) {
|
|
|
5464
5532
|
});
|
|
5465
5533
|
return indices;
|
|
5466
5534
|
}
|
|
5535
|
+
function lazy(fn2) {
|
|
5536
|
+
let cached = false;
|
|
5537
|
+
let value;
|
|
5538
|
+
let type;
|
|
5539
|
+
return Object.freeze({
|
|
5540
|
+
get isValueCreated() {
|
|
5541
|
+
return cached;
|
|
5542
|
+
},
|
|
5543
|
+
get value() {
|
|
5544
|
+
if (!cached) {
|
|
5545
|
+
value = fn2();
|
|
5546
|
+
cached = true;
|
|
5547
|
+
}
|
|
5548
|
+
return value;
|
|
5549
|
+
},
|
|
5550
|
+
get cachedValue() {
|
|
5551
|
+
return cached ? value : void 0;
|
|
5552
|
+
},
|
|
5553
|
+
get valueType() {
|
|
5554
|
+
if (type === void 0) type = typeof this.value;
|
|
5555
|
+
return type;
|
|
5556
|
+
},
|
|
5557
|
+
reset() {
|
|
5558
|
+
cached = false;
|
|
5559
|
+
type = void 0;
|
|
5560
|
+
value = void 0;
|
|
5561
|
+
}
|
|
5562
|
+
});
|
|
5563
|
+
}
|
|
5467
5564
|
const tools = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
5468
5565
|
__proto__: null,
|
|
5469
5566
|
createPointVirtualGrid,
|
|
5470
5567
|
createQuadtree,
|
|
5471
5568
|
getLineIndexByCenter,
|
|
5569
|
+
lazy,
|
|
5472
5570
|
mToMm,
|
|
5473
5571
|
mmTom
|
|
5474
5572
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
@@ -6981,7 +7079,7 @@ function migration(newLine, oldLine) {
|
|
|
6981
7079
|
});
|
|
6982
7080
|
}
|
|
6983
7081
|
}
|
|
6984
|
-
function lineSegmentClipping(lines, minLen = 0.03) {
|
|
7082
|
+
function lineSegmentClipping(lines, minLen = 0.03, dedup = true) {
|
|
6985
7083
|
const quadtree = new Quadtree(Box2.fromByLineSegment(...lines));
|
|
6986
7084
|
lines.forEach((line) => quadtree.insert({ line, userData: void 0 }));
|
|
6987
7085
|
const result = lines.flatMap((line) => {
|
|
@@ -7014,7 +7112,7 @@ function lineSegmentClipping(lines, minLen = 0.03) {
|
|
|
7014
7112
|
return line;
|
|
7015
7113
|
}).filter((line) => line.length() >= minLen);
|
|
7016
7114
|
quadtree.clear();
|
|
7017
|
-
return LineSegment.deduplication(result);
|
|
7115
|
+
return dedup ? LineSegment.deduplication(result) : result;
|
|
7018
7116
|
}
|
|
7019
7117
|
class DoubleWallHelper {
|
|
7020
7118
|
static errorAngle = 4;
|
|
@@ -16537,23 +16635,41 @@ class SceneAutoGenerat {
|
|
|
16537
16635
|
child.updateWorldMatrix(false, false);
|
|
16538
16636
|
});
|
|
16539
16637
|
}
|
|
16638
|
+
createGeometryByLines(lines) {
|
|
16639
|
+
const shape = new THREE.Shape();
|
|
16640
|
+
Polygon.fromByLinePath(lines, polygon);
|
|
16641
|
+
polygon.forEach((p2, i) => i === 0 ? shape.moveTo(p2.x, p2.y) : shape.lineTo(p2.x, p2.y));
|
|
16642
|
+
shape.closePath();
|
|
16643
|
+
const geometry = new THREE.ShapeGeometry(shape);
|
|
16644
|
+
return geometry;
|
|
16645
|
+
}
|
|
16540
16646
|
buildPlane(lines) {
|
|
16541
16647
|
lines = lineSegmentClipping(lines, 0);
|
|
16542
|
-
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16554
|
-
|
|
16555
|
-
|
|
16556
|
-
|
|
16648
|
+
LineSegment.groupByPath(lines).forEach((lines2, i) => {
|
|
16649
|
+
const removeSet = findDiscretePointLine2(lines2, null, true);
|
|
16650
|
+
lines2 = lines2.filter((line) => !removeSet.has(line) && !line.userData.isBayWindow);
|
|
16651
|
+
const doors = lines2.filter((line) => line.userData.isDoor), maxiCircles2 = new MaxiCircles(), { circles } = maxiCircles2.miniCircle(lines2, { circleEdges: doors, side: Side.IN }), { circles: outCircles } = maxiCircles2.miniCircle(lines2, { circleEdges: doors, side: Side.OUT }), ploys = circles.map(((p2) => Polygon.fromByLinePath(p2)));
|
|
16652
|
+
outCircles.forEach((circle) => {
|
|
16653
|
+
const polygon2 = Polygon.fromByLinePath(circle);
|
|
16654
|
+
const newPolys = Polygon.booleanOp(polygon2, ploys, { scale: 100, type: "Difference" });
|
|
16655
|
+
newPolys.forEach((poly, j) => {
|
|
16656
|
+
const geometry = this.createGeometryByLines(poly.toLines());
|
|
16657
|
+
const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ color: 11184810, side: THREE.DoubleSide }));
|
|
16658
|
+
mesh.position.z = this.z;
|
|
16659
|
+
mesh.name = `平面_out_${i}_${j}`;
|
|
16660
|
+
mesh.userData.category = "plane";
|
|
16661
|
+
this.scene.add(mesh);
|
|
16662
|
+
});
|
|
16663
|
+
});
|
|
16664
|
+
circles.forEach((circle, j) => {
|
|
16665
|
+
const geometry = this.createGeometryByLines(circle);
|
|
16666
|
+
const mesh = new THREE.Mesh(geometry, new THREE.MeshStandardMaterial({ color: 11184810, side: THREE.DoubleSide }));
|
|
16667
|
+
mesh.position.z = this.z;
|
|
16668
|
+
mesh.name = `平面_${i}_${j}`;
|
|
16669
|
+
mesh.userData.category = "plane";
|
|
16670
|
+
mesh.userData.room = true;
|
|
16671
|
+
this.scene.add(mesh);
|
|
16672
|
+
});
|
|
16557
16673
|
});
|
|
16558
16674
|
}
|
|
16559
16675
|
wallGroup = null;
|
|
@@ -19881,7 +19997,7 @@ function hasCircle(lineData, startIndex, direction) {
|
|
|
19881
19997
|
let lines = originalDataToLineData(lineData).lineSegments;
|
|
19882
19998
|
const center = lines[startIndex].center;
|
|
19883
19999
|
let findlines = lineSegmentClipping(lines.map((line2) => line2.clone()), 1e-9);
|
|
19884
|
-
let removeSet = findDiscretePointLine2(findlines, /* @__PURE__ */ new Set(),
|
|
20000
|
+
let removeSet = findDiscretePointLine2(findlines, /* @__PURE__ */ new Set(), false);
|
|
19885
20001
|
findlines = findlines.filter((line2) => !removeSet.has(line2));
|
|
19886
20002
|
const list = findlines.filter((line2) => line2.userData.isBayWindow && line2.isPointOnSegment(center));
|
|
19887
20003
|
if (list.length === 0) return null;
|
|
@@ -19896,16 +20012,14 @@ function hasCircle(lineData, startIndex, direction) {
|
|
|
19896
20012
|
path
|
|
19897
20013
|
});
|
|
19898
20014
|
if (result) {
|
|
19899
|
-
let indices =
|
|
19900
|
-
let originalDataIndices =
|
|
20015
|
+
let indices = lazy(() => getLineIndexByCenter(result, findlines).filter((i) => i > -1));
|
|
20016
|
+
let originalDataIndices = lazy(() => getLineIndexByCenter(result, lines).filter((i) => i > -1));
|
|
19901
20017
|
return {
|
|
19902
20018
|
get originalIndices() {
|
|
19903
|
-
|
|
19904
|
-
return originalDataIndices;
|
|
20019
|
+
return originalDataIndices.value;
|
|
19905
20020
|
},
|
|
19906
20021
|
get indices() {
|
|
19907
|
-
|
|
19908
|
-
return indices;
|
|
20022
|
+
return indices.value;
|
|
19909
20023
|
},
|
|
19910
20024
|
circle: result,
|
|
19911
20025
|
originalLines: lines,
|
|
@@ -11,6 +11,7 @@ export declare class SceneAutoGenerat {
|
|
|
11
11
|
angle: number;
|
|
12
12
|
constructor(lines: LineSegment[], itemList: any[], z: number, trajectory?: any);
|
|
13
13
|
init(): Promise<void>;
|
|
14
|
+
private createGeometryByLines;
|
|
14
15
|
buildPlane(lines: LineSegment<LineUserData>[]): void;
|
|
15
16
|
wallGroup: Group | null;
|
|
16
17
|
/** 构建墙壁
|
|
@@ -5,4 +5,4 @@ import { LineUserData } from '../type';
|
|
|
5
5
|
* @param minLen
|
|
6
6
|
* @returns
|
|
7
7
|
*/
|
|
8
|
-
export declare function lineSegmentClipping(lines: LineSegment<LineUserData>[], minLen?: number): LineSegment<Record<string, any>>[];
|
|
8
|
+
export declare function lineSegmentClipping(lines: LineSegment<LineUserData>[], minLen?: number, dedup?: boolean): LineSegment<Record<string, any>>[] | LineSegment<LineUserData>[];
|
|
@@ -8,3 +8,13 @@ export declare function createQuadtree<T = any>(lines: LineSegment<T>[]): Quadtr
|
|
|
8
8
|
export declare function mToMm(value: number): number;
|
|
9
9
|
export declare function mmTom(value: number): number;
|
|
10
10
|
export declare function getLineIndexByCenter(targetLines: LineSegment[], lines: LineSegment[]): number[];
|
|
11
|
+
type JSValueType = "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
|
|
12
|
+
export interface Lazy<T> {
|
|
13
|
+
readonly value: T;
|
|
14
|
+
readonly cachedValue: T | undefined;
|
|
15
|
+
readonly isValueCreated: boolean;
|
|
16
|
+
readonly valueType: JSValueType;
|
|
17
|
+
reset(): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function lazy<T>(fn: () => T): Lazy<T>;
|
|
20
|
+
export {};
|
package/src/utils/Polygon.d.ts
CHANGED
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { Box2 } from './Box2';
|
|
2
2
|
import { LineSegment } from './LineSegment';
|
|
3
3
|
import { Point } from './Point';
|
|
4
|
+
type BooleanOpType = "Union" | "Intersection" | "Difference" | "Xor";
|
|
5
|
+
type FillType = "EvenOdd" | "NonZero" | "Positive" | "Negative";
|
|
6
|
+
type BooleanOpOption = {
|
|
7
|
+
type: BooleanOpType;
|
|
8
|
+
scale: number;
|
|
9
|
+
subjectFillType?: FillType;
|
|
10
|
+
clipFillType?: FillType;
|
|
11
|
+
};
|
|
4
12
|
export declare class Polygon<T = any> extends Array<Point<T>> {
|
|
5
13
|
[Symbol.iterator](): ArrayIterator<Point<T>>;
|
|
6
14
|
constructor(points?: Point<T>[]);
|
|
@@ -55,10 +63,15 @@ export declare class Polygon<T = any> extends Array<Point<T>> {
|
|
|
55
63
|
* @param scale
|
|
56
64
|
*/
|
|
57
65
|
scale(scale?: number): this;
|
|
66
|
+
round(): this;
|
|
58
67
|
/**
|
|
59
68
|
* @param polygon
|
|
60
69
|
*/
|
|
61
|
-
union(
|
|
70
|
+
union(polygons: Polygon | Polygon[], scale?: number): boolean;
|
|
71
|
+
/** 差集
|
|
72
|
+
* @param polygon
|
|
73
|
+
*/
|
|
74
|
+
difference(polygons: Polygon | Polygon[], scale?: number): boolean;
|
|
62
75
|
/** 拆分为凸包
|
|
63
76
|
* @returns
|
|
64
77
|
*/
|
|
@@ -70,6 +83,7 @@ export declare class Polygon<T = any> extends Array<Point<T>> {
|
|
|
70
83
|
toLines(closed?: boolean): LineSegment<Record<string, any>>[];
|
|
71
84
|
toArrays(): [number, number][];
|
|
72
85
|
close(): this;
|
|
86
|
+
clone(): Polygon<Record<string, any>>;
|
|
73
87
|
/** 通过线段创建, 默认路径只有一条
|
|
74
88
|
* @param lines
|
|
75
89
|
* @returns
|
|
@@ -92,4 +106,16 @@ export declare class Polygon<T = any> extends Array<Point<T>> {
|
|
|
92
106
|
* @returns
|
|
93
107
|
*/
|
|
94
108
|
static fromByLinePath(lines: LineSegment[], polygon?: Polygon<any>): Polygon<any>;
|
|
109
|
+
/**
|
|
110
|
+
* @param poly
|
|
111
|
+
*/
|
|
112
|
+
static ensureCCW(poly: Polygon): void;
|
|
113
|
+
/** 布尔运算
|
|
114
|
+
* @param subject
|
|
115
|
+
* @param polygons
|
|
116
|
+
* @param scale 数据缩放
|
|
117
|
+
* @returns
|
|
118
|
+
*/
|
|
119
|
+
static booleanOp(subject: Polygon | Polygon[], clips: Polygon | Polygon[], opt: BooleanOpOption): Polygon<Record<string, any>>[];
|
|
95
120
|
}
|
|
121
|
+
export {};
|