build-dxf 0.1.109 → 0.1.111
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 +1 -1
- package/src/build.js +329 -297
- package/src/dxfSystem/components/Dxf.d.ts +1 -14
- package/src/dxfSystem/plugins/editor/components/CommandFlow/CFComponent.d.ts +6 -6
- package/src/dxfSystem/type.d.ts +5 -13
- package/src/dxfSystem/utils/CAD/drawData.d.ts +43 -0
- package/src/dxfSystem/utils/CAD/drawDxfImage.d.ts +2 -0
- package/src/dxfSystem/utils/CAD/drawDxfString.d.ts +3 -0
- package/src/dxfSystem/utils/{CAD.d.ts → CAD/index.d.ts} +12 -10
- package/src/dxfSystem/utils/lineSegmentClipping.d.ts +1 -1
- package/src/utils/algorithms/LineSegment.d.ts +7 -5
- package/src/utils/algorithms/LineSegmentUtils.d.ts +1 -0
- package/src/utils/algorithms/Point.d.ts +1 -1
- package/src/utils/algorithms/Quadtree.d.ts +1 -0
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -399,9 +399,9 @@ class LineSegment {
|
|
|
399
399
|
currentData = {};
|
|
400
400
|
// line: any
|
|
401
401
|
uuid = uuid();
|
|
402
|
-
|
|
402
|
+
_length = 0;
|
|
403
403
|
get len() {
|
|
404
|
-
return this
|
|
404
|
+
return this._length;
|
|
405
405
|
}
|
|
406
406
|
get start() {
|
|
407
407
|
return this.points[0];
|
|
@@ -409,11 +409,11 @@ class LineSegment {
|
|
|
409
409
|
get end() {
|
|
410
410
|
return this.points[1];
|
|
411
411
|
}
|
|
412
|
-
|
|
412
|
+
_center = Point.zero();
|
|
413
413
|
get center() {
|
|
414
|
-
return this
|
|
414
|
+
return this._center.clone();
|
|
415
415
|
}
|
|
416
|
-
|
|
416
|
+
_direction = Point.zero();
|
|
417
417
|
constructor(p1, p2) {
|
|
418
418
|
this.set(p1 ?? this.start, p2 ?? this.end);
|
|
419
419
|
this.start.currentData[LineSegment.LINE_SYMBOL] = this;
|
|
@@ -422,12 +422,12 @@ class LineSegment {
|
|
|
422
422
|
}
|
|
423
423
|
_initLenListener() {
|
|
424
424
|
const distanceUpdate = () => {
|
|
425
|
-
this
|
|
426
|
-
this
|
|
425
|
+
this._length = this.points[0].distance(this.points[1]);
|
|
426
|
+
this._center.set(
|
|
427
427
|
this.points[0].x + (this.points[1].x - this.points[0].x) * 0.5,
|
|
428
428
|
this.points[0].y + (this.points[1].y - this.points[0].y) * 0.5
|
|
429
429
|
);
|
|
430
|
-
this
|
|
430
|
+
this._direction = this.points[1].directionFrom(this.points[0]);
|
|
431
431
|
};
|
|
432
432
|
this.points.forEach((p2) => fields.forEach((k) => {
|
|
433
433
|
let value = p2[k];
|
|
@@ -455,12 +455,12 @@ class LineSegment {
|
|
|
455
455
|
const dx = direct.x * half;
|
|
456
456
|
const dy = direct.y * half;
|
|
457
457
|
this.start.set(
|
|
458
|
-
this
|
|
459
|
-
this
|
|
458
|
+
this._center.x - dx,
|
|
459
|
+
this._center.y - dy
|
|
460
460
|
);
|
|
461
461
|
this.end.set(
|
|
462
|
-
this
|
|
463
|
-
this
|
|
462
|
+
this._center.x + dx,
|
|
463
|
+
this._center.y + dy
|
|
464
464
|
);
|
|
465
465
|
return this;
|
|
466
466
|
}
|
|
@@ -477,7 +477,7 @@ class LineSegment {
|
|
|
477
477
|
* @returns
|
|
478
478
|
*/
|
|
479
479
|
length(_ = false) {
|
|
480
|
-
return this
|
|
480
|
+
return this._length;
|
|
481
481
|
}
|
|
482
482
|
/** 开始点向线段内收缩 width
|
|
483
483
|
* @param width
|
|
@@ -500,35 +500,35 @@ class LineSegment {
|
|
|
500
500
|
* @param line
|
|
501
501
|
* @returns
|
|
502
502
|
*/
|
|
503
|
-
isSameEndpoint(line) {
|
|
504
|
-
return this.start.equal(line.start) || this.start.equal(line.end) || this.end.equal(line.start) || this.end.equal(line.end);
|
|
503
|
+
isSameEndpoint(line, eps = 1e-9) {
|
|
504
|
+
return this.start.equal(line.start, eps) || this.start.equal(line.end, eps) || this.end.equal(line.start, eps) || this.end.equal(line.end, eps);
|
|
505
505
|
}
|
|
506
506
|
/**
|
|
507
507
|
* 相同端点是否为开始
|
|
508
508
|
* @param line
|
|
509
509
|
* @returns
|
|
510
510
|
*/
|
|
511
|
-
isSameEndpointAsStart(line) {
|
|
512
|
-
return this.start.equal(line.start) || this.start.equal(line.end);
|
|
511
|
+
isSameEndpointAsStart(line, eps = 1e-9) {
|
|
512
|
+
return this.start.equal(line.start, eps) || this.start.equal(line.end, eps);
|
|
513
513
|
}
|
|
514
514
|
/**
|
|
515
515
|
* 相同端点是否为结束
|
|
516
516
|
* @param line
|
|
517
517
|
* @returns
|
|
518
518
|
*/
|
|
519
|
-
isSameEndpointAsEnd(line) {
|
|
520
|
-
return this.end.equal(line.start) || this.end.equal(line.end);
|
|
519
|
+
isSameEndpointAsEnd(line, eps = 1e-9) {
|
|
520
|
+
return this.end.equal(line.start, eps) || this.end.equal(line.end, eps);
|
|
521
521
|
}
|
|
522
522
|
/**
|
|
523
523
|
* 获取共线点
|
|
524
524
|
* @param line
|
|
525
525
|
* @returns
|
|
526
526
|
*/
|
|
527
|
-
getSameEndpoint(line) {
|
|
528
|
-
if (this.start.equal(line.start)) return [this.start, line.start];
|
|
529
|
-
else if (this.start.equal(line.end)) return [this.start, line.end];
|
|
530
|
-
else if (this.end.equal(line.start)) return [this.end, line.start];
|
|
531
|
-
else if (this.end.equal(line.end)) return [this.end, line.end];
|
|
527
|
+
getSameEndpoint(line, eps = 1e-9) {
|
|
528
|
+
if (this.start.equal(line.start, eps)) return [this.start, line.start];
|
|
529
|
+
else if (this.start.equal(line.end, eps)) return [this.start, line.end];
|
|
530
|
+
else if (this.end.equal(line.start, eps)) return [this.end, line.start];
|
|
531
|
+
else if (this.end.equal(line.end, eps)) return [this.end, line.end];
|
|
532
532
|
return null;
|
|
533
533
|
}
|
|
534
534
|
/**
|
|
@@ -608,7 +608,7 @@ class LineSegment {
|
|
|
608
608
|
* @returns
|
|
609
609
|
*/
|
|
610
610
|
direction() {
|
|
611
|
-
return this
|
|
611
|
+
return this._direction.clone();
|
|
612
612
|
}
|
|
613
613
|
/**
|
|
614
614
|
* 获取发向量-左法线
|
|
@@ -1058,8 +1058,8 @@ class Point {
|
|
|
1058
1058
|
* @param point
|
|
1059
1059
|
* @returns
|
|
1060
1060
|
*/
|
|
1061
|
-
equal(point2) {
|
|
1062
|
-
return Math.abs(point2.x - this.x) <
|
|
1061
|
+
equal(point2, eps = 1e-9) {
|
|
1062
|
+
return Math.abs(point2.x - this.x) < eps && Math.abs(point2.y - this.y) < eps;
|
|
1063
1063
|
}
|
|
1064
1064
|
/**
|
|
1065
1065
|
*
|
|
@@ -2417,6 +2417,11 @@ class Quadtree {
|
|
|
2417
2417
|
}));
|
|
2418
2418
|
return array;
|
|
2419
2419
|
}
|
|
2420
|
+
static from(lines) {
|
|
2421
|
+
const quadtree = new Quadtree(Box2.fromByLineSegment(...lines));
|
|
2422
|
+
lines.forEach((line) => quadtree.insert({ line, userData: void 0 }));
|
|
2423
|
+
return quadtree;
|
|
2424
|
+
}
|
|
2420
2425
|
}
|
|
2421
2426
|
class WallInsertObject {
|
|
2422
2427
|
static mountedObjectType = [];
|
|
@@ -3655,6 +3660,33 @@ class LineSegmentUtils {
|
|
|
3655
3660
|
}
|
|
3656
3661
|
return points;
|
|
3657
3662
|
}
|
|
3663
|
+
static resolveIntersection(lines, onClip) {
|
|
3664
|
+
const quadtree = Quadtree.from(lines), queryLine = new LineSegment(), arrayMap = new ArrayMap();
|
|
3665
|
+
for (let i = 0; i < lines.length; i++) {
|
|
3666
|
+
const line = lines[i];
|
|
3667
|
+
queryLine.copy(line).setLength(line.len + 0.04);
|
|
3668
|
+
quadtree.queryLineSegment(queryLine).forEach((res) => {
|
|
3669
|
+
if (res.line === line) return;
|
|
3670
|
+
if (line.isSameEndpoint(res.line, 1e-4)) return;
|
|
3671
|
+
const point2 = res.line.getIntersection(line);
|
|
3672
|
+
if (!point2) return;
|
|
3673
|
+
arrayMap.append(res.line, point2);
|
|
3674
|
+
});
|
|
3675
|
+
}
|
|
3676
|
+
const newLines = [];
|
|
3677
|
+
const removeSet = /* @__PURE__ */ new Set();
|
|
3678
|
+
arrayMap.forEach((points, line) => {
|
|
3679
|
+
if (points.length) {
|
|
3680
|
+
let lines2 = LineSegmentUtils.clippingByPoints(line, points);
|
|
3681
|
+
onClip?.(line, lines2);
|
|
3682
|
+
newLines.push(...lines2);
|
|
3683
|
+
removeSet.add(line);
|
|
3684
|
+
} else newLines.push(line);
|
|
3685
|
+
});
|
|
3686
|
+
lines = lines.filter((line) => !removeSet.has(line));
|
|
3687
|
+
lines.push(...newLines);
|
|
3688
|
+
return lines;
|
|
3689
|
+
}
|
|
3658
3690
|
/** 对线段组统计,找到主导方向线
|
|
3659
3691
|
* @param lineSegments
|
|
3660
3692
|
* @returns
|
|
@@ -6010,39 +6042,25 @@ function migration(newLine, oldLine) {
|
|
|
6010
6042
|
});
|
|
6011
6043
|
}
|
|
6012
6044
|
function lineSegmentClipping(lines, minLen = 1e-9, dedup = true) {
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
if (!point2 || line.start.equal(point2) || line.end.equal(point2)) return;
|
|
6020
|
-
return point2;
|
|
6021
|
-
}).filter((i) => !!i);
|
|
6022
|
-
if (points.length) {
|
|
6023
|
-
const newLines2 = LineSegmentUtils.clippingByPoints(line, points);
|
|
6024
|
-
newLines2.map((newLine) => migration(newLine, line));
|
|
6025
|
-
if (line.userData.isBayWindow) {
|
|
6026
|
-
newLines2.sort((a2, b4) => b4.length() - a2.length());
|
|
6027
|
-
for (let i = 1; i < newLines2.length; i++) {
|
|
6028
|
-
newLines2[i].userData.isBayWindow = false;
|
|
6029
|
-
}
|
|
6045
|
+
lines = LineSegmentUtils.resolveIntersection(lines, (line, newLines) => {
|
|
6046
|
+
newLines.map((newLine) => migration(newLine, line));
|
|
6047
|
+
if (line.userData.isBayWindow) {
|
|
6048
|
+
newLines.sort((a2, b4) => b4.length() - a2.length());
|
|
6049
|
+
for (let i = 1; i < newLines.length; i++) {
|
|
6050
|
+
newLines[i].userData.isBayWindow = false;
|
|
6030
6051
|
}
|
|
6031
|
-
if (line.userData.isBalconyRailing) {
|
|
6032
|
-
const len = line.length();
|
|
6033
|
-
newLines2.forEach((line2) => {
|
|
6034
|
-
if (line2.length() / len < 0.2) {
|
|
6035
|
-
delete line2.userData.isBalconyRailing;
|
|
6036
|
-
}
|
|
6037
|
-
});
|
|
6038
|
-
}
|
|
6039
|
-
return newLines2;
|
|
6040
6052
|
}
|
|
6041
|
-
|
|
6053
|
+
if (line.userData.isBalconyRailing) {
|
|
6054
|
+
const len = line.length();
|
|
6055
|
+
newLines.forEach((line2) => {
|
|
6056
|
+
if (line2.length() / len < 0.2) {
|
|
6057
|
+
delete line2.userData.isBalconyRailing;
|
|
6058
|
+
}
|
|
6059
|
+
});
|
|
6060
|
+
}
|
|
6042
6061
|
});
|
|
6043
|
-
|
|
6044
|
-
|
|
6045
|
-
return dedup ? LineSegmentUtils.deduplication(newLines) : newLines;
|
|
6062
|
+
lines = lines.filter((line) => line.length() >= minLen);
|
|
6063
|
+
return dedup ? LineSegmentUtils.deduplication(lines) : lines;
|
|
6046
6064
|
}
|
|
6047
6065
|
class LineIndexGenerator {
|
|
6048
6066
|
index = 0;
|
|
@@ -6641,7 +6659,6 @@ function clippingDoubleWall(lines) {
|
|
|
6641
6659
|
}
|
|
6642
6660
|
const miniCircles = new MiniCircles();
|
|
6643
6661
|
function clippingInsertObjectDoubleWall(lines) {
|
|
6644
|
-
if (lines.length === 4) return [lines];
|
|
6645
6662
|
const hasInsertObject = lines.some((line) => WallInsertObject.isInsertObject(line));
|
|
6646
6663
|
if (!hasInsertObject) return clippingDoubleWall(lines);
|
|
6647
6664
|
const quadtree = createQuadtree(lines), poly = Polygon.fromByLines2(lines), far = 10;
|
|
@@ -6653,7 +6670,7 @@ function clippingInsertObjectDoubleWall(lines) {
|
|
|
6653
6670
|
if (!poly.pointWithin(center.add(normal.clone().multiplyScalar(1e-6)))) normal.multiplyScalar(-1);
|
|
6654
6671
|
WallInsertObject.forEachInsertObjectData(line, (data) => data.forEach((d2) => {
|
|
6655
6672
|
const wioLine = wallInsertObjectToLine(line, d2);
|
|
6656
|
-
wioLine.setLength(wioLine.len
|
|
6673
|
+
wioLine.setLength(wioLine.len - 4e-3);
|
|
6657
6674
|
const len = wioLine.length();
|
|
6658
6675
|
let startResults = quadtree.raycaster(wioLine.start, normal, 1e-4, far).filter((item) => item.targetLine.isParallelTo(wioLine));
|
|
6659
6676
|
let endResults = quadtree.raycaster(wioLine.end, normal, 1e-4, far).filter((item) => item.targetLine.isParallelTo(wioLine));
|
|
@@ -9689,6 +9706,7 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9689
9706
|
if (info) {
|
|
9690
9707
|
const { dottedLine, windowLine, depth, side } = info, line = new LineSegment(dottedLine.start.clone(), dottedLine.end.clone()), win = windowLine?.userData.drawWindow && windowLine.userData.drawWindow[0];
|
|
9691
9708
|
if (side === "LEFT") line.swapValue();
|
|
9709
|
+
line.translate(-DEFAULT_WALL_WIDTH * 0.5, line.normal());
|
|
9692
9710
|
line.userData = {
|
|
9693
9711
|
groundClearance: win?.groundClearance ?? 0,
|
|
9694
9712
|
height: win?.height,
|
|
@@ -9815,17 +9833,27 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9815
9833
|
if (roomPloys.length === 0) return json;
|
|
9816
9834
|
publicInfo.itemInfo.forEach((item, i) => {
|
|
9817
9835
|
if (!placeHoldersMap[item.category]) return;
|
|
9818
|
-
const
|
|
9836
|
+
const contour = item.quadContour ?? item.contour;
|
|
9837
|
+
if (contour.length === 0) {
|
|
9838
|
+
console.warn(`第${i}个物品轮廓为空`);
|
|
9839
|
+
return;
|
|
9840
|
+
}
|
|
9841
|
+
const itemPoly = new Polygon(contour.map((p2) => Point.from(p2).rotate(json.center, json.angle))), center = itemPoly.getCenter(), index2 = roomPloys.findIndex((poly) => poly.pointWithin(center));
|
|
9819
9842
|
if (index2 < 0) return;
|
|
9820
|
-
|
|
9821
|
-
|
|
9822
|
-
|
|
9823
|
-
|
|
9824
|
-
|
|
9825
|
-
|
|
9826
|
-
|
|
9827
|
-
|
|
9828
|
-
|
|
9843
|
+
try {
|
|
9844
|
+
const rect = itemPoly.getMinimumBoundingRectangle().map((p2) => p2.toJson2D());
|
|
9845
|
+
json.placeHolders.push({
|
|
9846
|
+
name: placeHoldersMap[item.category],
|
|
9847
|
+
polygon: rect,
|
|
9848
|
+
direction: Point.from(item.direction).rotate(Point.zero(), json.angle),
|
|
9849
|
+
height: item.box.max.z - item.box.min.z,
|
|
9850
|
+
sillHeight: item.box.min.z - z,
|
|
9851
|
+
roomId: rooms[index2].roomTypeId,
|
|
9852
|
+
id: i
|
|
9853
|
+
});
|
|
9854
|
+
} catch (error) {
|
|
9855
|
+
console.warn(`第${i}个物品解析异常`);
|
|
9856
|
+
}
|
|
9829
9857
|
});
|
|
9830
9858
|
return json;
|
|
9831
9859
|
}
|
|
@@ -9977,39 +10005,6 @@ const tools = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
|
|
|
9977
10005
|
toOriginalDataItem,
|
|
9978
10006
|
wallInsertObjectToLine
|
|
9979
10007
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
9980
|
-
class Group {
|
|
9981
|
-
type = "";
|
|
9982
|
-
userData = { color: "#fff" };
|
|
9983
|
-
constructor(lines = [], type = "", userData = {}) {
|
|
9984
|
-
this.type = type;
|
|
9985
|
-
this.addLine(...lines);
|
|
9986
|
-
Object.assign(this.userData, userData);
|
|
9987
|
-
}
|
|
9988
|
-
lines = [];
|
|
9989
|
-
/** 添加线段
|
|
9990
|
-
* @param arg
|
|
9991
|
-
*/
|
|
9992
|
-
addLine(...arg) {
|
|
9993
|
-
this.lines.push(...arg);
|
|
9994
|
-
}
|
|
9995
|
-
removeLine(...lines) {
|
|
9996
|
-
if (lines.length === 0) return;
|
|
9997
|
-
if (lines.length === 1) {
|
|
9998
|
-
const index2 = this.lines.indexOf(lines[0]);
|
|
9999
|
-
this.lines.splice(index2, 1);
|
|
10000
|
-
return;
|
|
10001
|
-
}
|
|
10002
|
-
const set2 = new Set(lines);
|
|
10003
|
-
this.lines = this.lines.filter((line) => !set2.has(line));
|
|
10004
|
-
}
|
|
10005
|
-
clone() {
|
|
10006
|
-
const group = new this.constructor();
|
|
10007
|
-
group.type = this.type;
|
|
10008
|
-
group.lines = this.lines.map((line) => line.clone());
|
|
10009
|
-
Object.assign(group.userData, this.userData);
|
|
10010
|
-
return group;
|
|
10011
|
-
}
|
|
10012
|
-
}
|
|
10013
10008
|
const units = {
|
|
10014
10009
|
Unitless: 1,
|
|
10015
10010
|
// 无单位,1米 = 1(无单位)
|
|
@@ -10054,6 +10049,223 @@ const units = {
|
|
|
10054
10049
|
Parsecs: 3240779289666404e-32
|
|
10055
10050
|
// 秒差距,1米 ≈ 0.00000000000000003240779289666404秒差距
|
|
10056
10051
|
};
|
|
10052
|
+
function toDrawData(unit = "Centimeters") {
|
|
10053
|
+
if (!this.needUpdate && this._cachedDrawDataMap.has(unit)) return this._cachedDrawDataMap.get(unit);
|
|
10054
|
+
this._cachedDrawDataMap.clear();
|
|
10055
|
+
this.needUpdate = false;
|
|
10056
|
+
const lines = this.groups.flatMap((group) => group.lines), s = units[unit], expansionWidth = 2, box = Box2.fromByLineSegment(...lines).expansion(expansionWidth), center = box.center, data = {
|
|
10057
|
+
unit,
|
|
10058
|
+
lines: [],
|
|
10059
|
+
lines2: [],
|
|
10060
|
+
arcs: [],
|
|
10061
|
+
texts: [],
|
|
10062
|
+
center: center.clone().multiplyScalar(s).toJson(),
|
|
10063
|
+
width: box.width * s,
|
|
10064
|
+
height: box.height * s,
|
|
10065
|
+
scale: s
|
|
10066
|
+
};
|
|
10067
|
+
let color = "white";
|
|
10068
|
+
function drawText2(str, p2) {
|
|
10069
|
+
data.texts.push([str, p2.x * s, p2.y * s, color]);
|
|
10070
|
+
}
|
|
10071
|
+
function drawLine(p1, p2) {
|
|
10072
|
+
data.lines.push([p1.x * s, p1.y * s, p2.x * s, p2.y * s, color]);
|
|
10073
|
+
}
|
|
10074
|
+
function drawLine2(p1, p2) {
|
|
10075
|
+
data.lines2.push([p1.x * s, p1.y * s, p2.x * s, p2.y * s, color]);
|
|
10076
|
+
}
|
|
10077
|
+
function drawDottedLine(p1, p2, dash = 0.04, gap = 0.05, mode = "line") {
|
|
10078
|
+
const distance2 = dash + gap;
|
|
10079
|
+
let current = 0;
|
|
10080
|
+
const direction = p2.directionFrom(p1);
|
|
10081
|
+
const length = p1.distance(p2);
|
|
10082
|
+
while (current < length) {
|
|
10083
|
+
const dashEnd = Math.min(current + dash, length);
|
|
10084
|
+
const start = p1.clone().add(direction.clone().multiplyScalar(current));
|
|
10085
|
+
const end = p1.clone().add(direction.clone().multiplyScalar(dashEnd));
|
|
10086
|
+
if (mode === "line") drawLine(start, end);
|
|
10087
|
+
else drawLine2(start, end);
|
|
10088
|
+
current += distance2;
|
|
10089
|
+
}
|
|
10090
|
+
}
|
|
10091
|
+
const line = new LineSegment();
|
|
10092
|
+
function drawRulerLine(p1, p2) {
|
|
10093
|
+
line.set(p1, p2);
|
|
10094
|
+
const length = line.length();
|
|
10095
|
+
const angle = line.direction().angle(new Point(0, 1), { unit: "degree", range: "180" });
|
|
10096
|
+
const p1C = p1.clone();
|
|
10097
|
+
const p2C = p2.clone();
|
|
10098
|
+
const offset = expansionWidth * 0.4;
|
|
10099
|
+
if (Math.min(angle, 180 - angle) < 1) {
|
|
10100
|
+
if (p1.x < center.x) {
|
|
10101
|
+
p1C.x = box.minX + offset;
|
|
10102
|
+
p2C.x = box.minX + offset;
|
|
10103
|
+
} else {
|
|
10104
|
+
p1C.x = box.maxX - offset;
|
|
10105
|
+
p2C.x = box.maxX - offset;
|
|
10106
|
+
}
|
|
10107
|
+
} else {
|
|
10108
|
+
if (p1.y < center.y) {
|
|
10109
|
+
p1C.y = box.minY + offset;
|
|
10110
|
+
p2C.y = box.minY + offset;
|
|
10111
|
+
} else {
|
|
10112
|
+
p1C.y = box.maxY - offset;
|
|
10113
|
+
p2C.y = box.maxY - offset;
|
|
10114
|
+
}
|
|
10115
|
+
}
|
|
10116
|
+
line.set(p1C, p2C);
|
|
10117
|
+
drawDottedLine(p1C, p1, 0.04, 0.05, "line2");
|
|
10118
|
+
drawDottedLine(p2C, p2, 0.04, 0.05, "line2");
|
|
10119
|
+
drawLine2(p1C, p2C);
|
|
10120
|
+
color = "white";
|
|
10121
|
+
drawText2((length * 1e3).toFixed(0) + "mm", line.center);
|
|
10122
|
+
}
|
|
10123
|
+
function drawArc(pos, radius, startAngle, endAngle) {
|
|
10124
|
+
data.arcs.push([
|
|
10125
|
+
pos.x * s,
|
|
10126
|
+
pos.y * s,
|
|
10127
|
+
radius * s,
|
|
10128
|
+
startAngle,
|
|
10129
|
+
endAngle,
|
|
10130
|
+
color
|
|
10131
|
+
]);
|
|
10132
|
+
}
|
|
10133
|
+
this.groups.forEach((group) => {
|
|
10134
|
+
const set2 = this._drawHandlerMap.get(group.type);
|
|
10135
|
+
if (!set2) return;
|
|
10136
|
+
const option = { group, drawArc, drawLine, drawDottedLine, drawText: drawText2, drawRulerLine, setColor(c) {
|
|
10137
|
+
color = c;
|
|
10138
|
+
} };
|
|
10139
|
+
set2.forEach((fun) => fun.handler(option));
|
|
10140
|
+
});
|
|
10141
|
+
this._cachedDrawDataMap.set(unit, data);
|
|
10142
|
+
return data;
|
|
10143
|
+
}
|
|
10144
|
+
async function toDxfImageBlob(data, type = "image/jpeg", background = "#000") {
|
|
10145
|
+
const margin = 0 * data.scale;
|
|
10146
|
+
let canvas;
|
|
10147
|
+
if (typeof window !== "undefined") {
|
|
10148
|
+
canvas = document.createElement("canvas");
|
|
10149
|
+
} else if (typeof global !== "undefined") {
|
|
10150
|
+
const { createCanvas } = await include("canvas");
|
|
10151
|
+
canvas = createCanvas(data.width + margin * 2, data.height + margin * 2);
|
|
10152
|
+
} else {
|
|
10153
|
+
throw new Error("创建画布失败");
|
|
10154
|
+
}
|
|
10155
|
+
const colors = {
|
|
10156
|
+
cyan: "cyan",
|
|
10157
|
+
yellow: "yellow",
|
|
10158
|
+
white: "white"
|
|
10159
|
+
};
|
|
10160
|
+
canvas.width = data.width + margin * 2;
|
|
10161
|
+
canvas.height = data.height + margin * 2;
|
|
10162
|
+
const ctx = canvas.getContext("2d");
|
|
10163
|
+
if (background) {
|
|
10164
|
+
ctx.fillStyle = background;
|
|
10165
|
+
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
10166
|
+
}
|
|
10167
|
+
ctx.translate(-data.center.x + data.width * 0.5 + margin, data.center.y + data.height * 0.5 + margin);
|
|
10168
|
+
ctx.scale(1, -1);
|
|
10169
|
+
data.lines.forEach(([p1x, p1y, p2x, p2y, color]) => {
|
|
10170
|
+
ctx.strokeStyle = colors[color] ?? color;
|
|
10171
|
+
ctx.beginPath();
|
|
10172
|
+
ctx.moveTo(p1x, p1y);
|
|
10173
|
+
ctx.lineTo(p2x, p2y);
|
|
10174
|
+
ctx.closePath();
|
|
10175
|
+
ctx.stroke();
|
|
10176
|
+
});
|
|
10177
|
+
data.lines2.forEach(([p1x, p1y, p2x, p2y, color]) => {
|
|
10178
|
+
ctx.strokeStyle = colors[color] ?? color;
|
|
10179
|
+
ctx.beginPath();
|
|
10180
|
+
ctx.moveTo(p1x, p1y);
|
|
10181
|
+
ctx.lineTo(p2x, p2y);
|
|
10182
|
+
ctx.closePath();
|
|
10183
|
+
ctx.stroke();
|
|
10184
|
+
});
|
|
10185
|
+
data.arcs.forEach(([x, y, radius, startAngle, endAngle, color]) => {
|
|
10186
|
+
ctx.strokeStyle = colors[color];
|
|
10187
|
+
ctx.beginPath();
|
|
10188
|
+
ctx.arc(x, y, radius, startAngle * (Math.PI / 180), endAngle * (Math.PI / 180));
|
|
10189
|
+
ctx.stroke();
|
|
10190
|
+
});
|
|
10191
|
+
data.texts.forEach(([str, x, y, color]) => {
|
|
10192
|
+
ctx.fillStyle = colors[color] ?? color ?? "#fff";
|
|
10193
|
+
ctx.font = `${0.15 * data.scale}px Arial`;
|
|
10194
|
+
ctx.textAlign = "center";
|
|
10195
|
+
ctx.textBaseline = "middle";
|
|
10196
|
+
ctx.save();
|
|
10197
|
+
ctx.translate(x, y);
|
|
10198
|
+
ctx.scale(1, -1);
|
|
10199
|
+
ctx.fillText(str, 0, 0);
|
|
10200
|
+
ctx.restore();
|
|
10201
|
+
});
|
|
10202
|
+
if ("toBlob" in canvas) {
|
|
10203
|
+
return new Promise((resolve) => {
|
|
10204
|
+
canvas.toBlob((b4) => {
|
|
10205
|
+
resolve(b4);
|
|
10206
|
+
}, type, 1);
|
|
10207
|
+
});
|
|
10208
|
+
} else {
|
|
10209
|
+
const buffer = canvas.toBuffer(type, { quality: 1 });
|
|
10210
|
+
return buffer;
|
|
10211
|
+
}
|
|
10212
|
+
}
|
|
10213
|
+
function drawDxfString(data, unit = "Millimeters") {
|
|
10214
|
+
const d2 = new Drawing();
|
|
10215
|
+
d2.setUnits(unit);
|
|
10216
|
+
d2.addLayer("cyan", Drawing.ACI.CYAN, "DOTTED");
|
|
10217
|
+
d2.addLayer("yellow", Drawing.ACI.YELLOW, "DOTTED");
|
|
10218
|
+
d2.addLayer("white", Drawing.ACI.WHITE, "DOTTED");
|
|
10219
|
+
d2.addLayer("blue", Drawing.ACI.BLUE, "DOTTED");
|
|
10220
|
+
d2.addLayer("green", Drawing.ACI.GREEN, "DOTTED");
|
|
10221
|
+
d2.addLayer("layer", Drawing.ACI.LAYER, "DOTTED");
|
|
10222
|
+
d2.addLayer("magenta", Drawing.ACI.MAGENTA, "DOTTED");
|
|
10223
|
+
d2.addLayer("red", Drawing.ACI.RED, "DOTTED");
|
|
10224
|
+
data.lines.forEach((item) => {
|
|
10225
|
+
let [p1x, p1y, p2x, p2y, color] = item;
|
|
10226
|
+
d2.setActiveLayer(color);
|
|
10227
|
+
d2.drawLine(p1x, p1y, p2x, p2y);
|
|
10228
|
+
});
|
|
10229
|
+
data.arcs.forEach((item) => {
|
|
10230
|
+
const [x, y, r2, startAngle, endAngle, color] = item;
|
|
10231
|
+
d2.setActiveLayer(color);
|
|
10232
|
+
d2.drawArc(x, y, r2, startAngle, endAngle);
|
|
10233
|
+
});
|
|
10234
|
+
return d2.toDxfString();
|
|
10235
|
+
}
|
|
10236
|
+
class Group {
|
|
10237
|
+
type = "";
|
|
10238
|
+
userData = { color: "#fff" };
|
|
10239
|
+
constructor(lines = [], type = "", userData = {}) {
|
|
10240
|
+
this.type = type;
|
|
10241
|
+
this.addLine(...lines);
|
|
10242
|
+
Object.assign(this.userData, userData);
|
|
10243
|
+
}
|
|
10244
|
+
lines = [];
|
|
10245
|
+
/** 添加线段
|
|
10246
|
+
* @param arg
|
|
10247
|
+
*/
|
|
10248
|
+
addLine(...arg) {
|
|
10249
|
+
this.lines.push(...arg);
|
|
10250
|
+
}
|
|
10251
|
+
removeLine(...lines) {
|
|
10252
|
+
if (lines.length === 0) return;
|
|
10253
|
+
if (lines.length === 1) {
|
|
10254
|
+
const index2 = this.lines.indexOf(lines[0]);
|
|
10255
|
+
this.lines.splice(index2, 1);
|
|
10256
|
+
return;
|
|
10257
|
+
}
|
|
10258
|
+
const set2 = new Set(lines);
|
|
10259
|
+
this.lines = this.lines.filter((line) => !set2.has(line));
|
|
10260
|
+
}
|
|
10261
|
+
clone() {
|
|
10262
|
+
const group = new this.constructor();
|
|
10263
|
+
group.type = this.type;
|
|
10264
|
+
group.lines = this.lines.map((line) => line.clone());
|
|
10265
|
+
Object.assign(group.userData, this.userData);
|
|
10266
|
+
return group;
|
|
10267
|
+
}
|
|
10268
|
+
}
|
|
10057
10269
|
class CAD {
|
|
10058
10270
|
groups = [];
|
|
10059
10271
|
_drawHandlerMap = new SetMap();
|
|
@@ -10199,169 +10411,14 @@ class CAD {
|
|
|
10199
10411
|
*/
|
|
10200
10412
|
_cachedDrawDataMap = /* @__PURE__ */ new Map();
|
|
10201
10413
|
toDrawData(unit = "Centimeters") {
|
|
10202
|
-
|
|
10203
|
-
this._cachedDrawDataMap.clear();
|
|
10204
|
-
this.needUpdate = false;
|
|
10205
|
-
const lines = this.groups.flatMap((group) => group.lines), s = units[unit], expansionWidth = 2, box = Box2.fromByLineSegment(...lines).expansion(expansionWidth), center = box.center, data = {
|
|
10206
|
-
unit,
|
|
10207
|
-
lines: [],
|
|
10208
|
-
lines2: [],
|
|
10209
|
-
arcs: [],
|
|
10210
|
-
texts: [],
|
|
10211
|
-
center: center.clone().multiplyScalar(s).toJson(),
|
|
10212
|
-
width: box.width * s,
|
|
10213
|
-
height: box.height * s,
|
|
10214
|
-
scale: s
|
|
10215
|
-
};
|
|
10216
|
-
let color = "white";
|
|
10217
|
-
function drawText2(str, p2) {
|
|
10218
|
-
data.texts.push([str, p2.x * s, p2.y * s, color]);
|
|
10219
|
-
}
|
|
10220
|
-
function drawLine(p1, p2) {
|
|
10221
|
-
data.lines.push([p1.x * s, p1.y * s, p2.x * s, p2.y * s, color]);
|
|
10222
|
-
}
|
|
10223
|
-
function drawLine2(p1, p2) {
|
|
10224
|
-
data.lines2.push([p1.x * s, p1.y * s, p2.x * s, p2.y * s, color]);
|
|
10225
|
-
}
|
|
10226
|
-
function drawDottedLine(p1, p2, dash = 0.04, gap = 0.05, mode = "line") {
|
|
10227
|
-
const distance2 = dash + gap;
|
|
10228
|
-
let current = 0;
|
|
10229
|
-
const direction = p2.directionFrom(p1);
|
|
10230
|
-
const length = p1.distance(p2);
|
|
10231
|
-
while (current < length) {
|
|
10232
|
-
const dashEnd = Math.min(current + dash, length);
|
|
10233
|
-
const start = p1.clone().add(direction.clone().multiplyScalar(current));
|
|
10234
|
-
const end = p1.clone().add(direction.clone().multiplyScalar(dashEnd));
|
|
10235
|
-
if (mode === "line") drawLine(start, end);
|
|
10236
|
-
else drawLine2(start, end);
|
|
10237
|
-
current += distance2;
|
|
10238
|
-
}
|
|
10239
|
-
}
|
|
10240
|
-
const line = new LineSegment();
|
|
10241
|
-
function drawRulerLine(p1, p2) {
|
|
10242
|
-
line.set(p1, p2);
|
|
10243
|
-
const length = line.length();
|
|
10244
|
-
const angle = line.direction().angle(new Point(0, 1), { unit: "degree", range: "180" });
|
|
10245
|
-
const p1C = p1.clone();
|
|
10246
|
-
const p2C = p2.clone();
|
|
10247
|
-
const offset = expansionWidth * 0.4;
|
|
10248
|
-
if (Math.min(angle, 180 - angle) < 1) {
|
|
10249
|
-
if (p1.x < center.x) {
|
|
10250
|
-
p1C.x = box.minX + offset;
|
|
10251
|
-
p2C.x = box.minX + offset;
|
|
10252
|
-
} else {
|
|
10253
|
-
p1C.x = box.maxX - offset;
|
|
10254
|
-
p2C.x = box.maxX - offset;
|
|
10255
|
-
}
|
|
10256
|
-
} else {
|
|
10257
|
-
if (p1.y < center.y) {
|
|
10258
|
-
p1C.y = box.minY + offset;
|
|
10259
|
-
p2C.y = box.minY + offset;
|
|
10260
|
-
} else {
|
|
10261
|
-
p1C.y = box.maxY - offset;
|
|
10262
|
-
p2C.y = box.maxY - offset;
|
|
10263
|
-
}
|
|
10264
|
-
}
|
|
10265
|
-
line.set(p1C, p2C);
|
|
10266
|
-
drawDottedLine(p1C, p1, 0.04, 0.05, "line2");
|
|
10267
|
-
drawDottedLine(p2C, p2, 0.04, 0.05, "line2");
|
|
10268
|
-
drawLine2(p1C, p2C);
|
|
10269
|
-
color = "white";
|
|
10270
|
-
drawText2((length * 1e3).toFixed(0) + "mm", line.center);
|
|
10271
|
-
}
|
|
10272
|
-
function drawArc(pos, radius, startAngle, endAngle) {
|
|
10273
|
-
data.arcs.push([
|
|
10274
|
-
pos.x * s,
|
|
10275
|
-
pos.y * s,
|
|
10276
|
-
radius * s,
|
|
10277
|
-
startAngle,
|
|
10278
|
-
endAngle,
|
|
10279
|
-
color
|
|
10280
|
-
]);
|
|
10281
|
-
}
|
|
10282
|
-
this.groups.forEach((group) => {
|
|
10283
|
-
const set2 = this._drawHandlerMap.get(group.type);
|
|
10284
|
-
if (!set2) return;
|
|
10285
|
-
const option = { group, drawArc, drawLine, drawDottedLine, drawRulerLine, setColor(c) {
|
|
10286
|
-
color = c;
|
|
10287
|
-
} };
|
|
10288
|
-
set2.forEach((fun) => fun.handler(option));
|
|
10289
|
-
});
|
|
10290
|
-
this._cachedDrawDataMap.set(unit, data);
|
|
10291
|
-
return data;
|
|
10414
|
+
return toDrawData.call(this, unit);
|
|
10292
10415
|
}
|
|
10293
10416
|
/** 转为图片
|
|
10294
10417
|
* @param type
|
|
10295
10418
|
*/
|
|
10296
10419
|
async toDxfImageBlob(unit = "Centimeters", type = "image/jpeg", background = "#000") {
|
|
10297
10420
|
const data = this.toDrawData(unit);
|
|
10298
|
-
|
|
10299
|
-
let canvas;
|
|
10300
|
-
if (typeof window !== "undefined") {
|
|
10301
|
-
canvas = document.createElement("canvas");
|
|
10302
|
-
} else if (typeof global !== "undefined") {
|
|
10303
|
-
const { createCanvas } = await include("canvas");
|
|
10304
|
-
canvas = createCanvas(data.width + margin * 2, data.height + margin * 2);
|
|
10305
|
-
} else {
|
|
10306
|
-
throw new Error("创建画布失败");
|
|
10307
|
-
}
|
|
10308
|
-
const colors = {
|
|
10309
|
-
cyan: "cyan",
|
|
10310
|
-
yellow: "yellow",
|
|
10311
|
-
white: "white"
|
|
10312
|
-
};
|
|
10313
|
-
canvas.width = data.width + margin * 2;
|
|
10314
|
-
canvas.height = data.height + margin * 2;
|
|
10315
|
-
const ctx = canvas.getContext("2d");
|
|
10316
|
-
if (background) {
|
|
10317
|
-
ctx.fillStyle = background;
|
|
10318
|
-
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
10319
|
-
}
|
|
10320
|
-
ctx.translate(-data.center.x + data.width * 0.5 + margin, data.center.y + data.height * 0.5 + margin);
|
|
10321
|
-
ctx.scale(1, -1);
|
|
10322
|
-
data.lines.forEach(([p1x, p1y, p2x, p2y, color]) => {
|
|
10323
|
-
ctx.strokeStyle = colors[color] ?? color;
|
|
10324
|
-
ctx.beginPath();
|
|
10325
|
-
ctx.moveTo(p1x, p1y);
|
|
10326
|
-
ctx.lineTo(p2x, p2y);
|
|
10327
|
-
ctx.closePath();
|
|
10328
|
-
ctx.stroke();
|
|
10329
|
-
});
|
|
10330
|
-
data.lines2.forEach(([p1x, p1y, p2x, p2y, color]) => {
|
|
10331
|
-
ctx.strokeStyle = colors[color] ?? color;
|
|
10332
|
-
ctx.beginPath();
|
|
10333
|
-
ctx.moveTo(p1x, p1y);
|
|
10334
|
-
ctx.lineTo(p2x, p2y);
|
|
10335
|
-
ctx.closePath();
|
|
10336
|
-
ctx.stroke();
|
|
10337
|
-
});
|
|
10338
|
-
data.arcs.forEach(([x, y, radius, startAngle, endAngle, color]) => {
|
|
10339
|
-
ctx.strokeStyle = colors[color];
|
|
10340
|
-
ctx.beginPath();
|
|
10341
|
-
ctx.arc(x, y, radius, startAngle * (Math.PI / 180), endAngle * (Math.PI / 180));
|
|
10342
|
-
ctx.stroke();
|
|
10343
|
-
});
|
|
10344
|
-
data.texts.forEach(([str, x, y, color]) => {
|
|
10345
|
-
ctx.fillStyle = colors[color] ?? color ?? "#fff";
|
|
10346
|
-
ctx.font = `${0.15 * data.scale}px Arial`;
|
|
10347
|
-
ctx.textAlign = "center";
|
|
10348
|
-
ctx.textBaseline = "middle";
|
|
10349
|
-
ctx.save();
|
|
10350
|
-
ctx.translate(x, y);
|
|
10351
|
-
ctx.scale(1, -1);
|
|
10352
|
-
ctx.fillText(str, 0, 0);
|
|
10353
|
-
ctx.restore();
|
|
10354
|
-
});
|
|
10355
|
-
if ("toBlob" in canvas) {
|
|
10356
|
-
return new Promise((resolve) => {
|
|
10357
|
-
canvas.toBlob((b4) => {
|
|
10358
|
-
resolve(b4);
|
|
10359
|
-
}, type, 1);
|
|
10360
|
-
});
|
|
10361
|
-
} else {
|
|
10362
|
-
const buffer = canvas.toBuffer(type, { quality: 1 });
|
|
10363
|
-
return buffer;
|
|
10364
|
-
}
|
|
10421
|
+
return toDxfImageBlob(data, type, background);
|
|
10365
10422
|
}
|
|
10366
10423
|
/** 下载为图片
|
|
10367
10424
|
* @param filename
|
|
@@ -10389,28 +10446,8 @@ class CAD {
|
|
|
10389
10446
|
* 将点json结构转换为Dxf string
|
|
10390
10447
|
*/
|
|
10391
10448
|
toDxfString(unit = "Millimeters") {
|
|
10392
|
-
const d2 = new Drawing();
|
|
10393
|
-
d2.setUnits(unit);
|
|
10394
|
-
d2.addLayer("cyan", Drawing.ACI.CYAN, "DOTTED");
|
|
10395
|
-
d2.addLayer("yellow", Drawing.ACI.YELLOW, "DOTTED");
|
|
10396
|
-
d2.addLayer("white", Drawing.ACI.WHITE, "DOTTED");
|
|
10397
|
-
d2.addLayer("blue", Drawing.ACI.BLUE, "DOTTED");
|
|
10398
|
-
d2.addLayer("green", Drawing.ACI.GREEN, "DOTTED");
|
|
10399
|
-
d2.addLayer("layer", Drawing.ACI.LAYER, "DOTTED");
|
|
10400
|
-
d2.addLayer("magenta", Drawing.ACI.MAGENTA, "DOTTED");
|
|
10401
|
-
d2.addLayer("red", Drawing.ACI.RED, "DOTTED");
|
|
10402
10449
|
const data = this.toDrawData(unit);
|
|
10403
|
-
data
|
|
10404
|
-
let [p1x, p1y, p2x, p2y, color] = item;
|
|
10405
|
-
d2.setActiveLayer(color);
|
|
10406
|
-
d2.drawLine(p1x, p1y, p2x, p2y);
|
|
10407
|
-
});
|
|
10408
|
-
data.arcs.forEach((item) => {
|
|
10409
|
-
const [x, y, r2, startAngle, endAngle, color] = item;
|
|
10410
|
-
d2.setActiveLayer(color);
|
|
10411
|
-
d2.drawArc(x, y, r2, startAngle, endAngle);
|
|
10412
|
-
});
|
|
10413
|
-
return d2.toDxfString();
|
|
10450
|
+
return drawDxfString(data, unit);
|
|
10414
10451
|
}
|
|
10415
10452
|
/**
|
|
10416
10453
|
* 将点云结构转换为DXF格式
|
|
@@ -10560,15 +10597,6 @@ class DxfDrawPlugin {
|
|
|
10560
10597
|
});
|
|
10561
10598
|
}
|
|
10562
10599
|
});
|
|
10563
|
-
cad.addDrawHandler({
|
|
10564
|
-
type: ["ruler"],
|
|
10565
|
-
handler({ drawRulerLine, setColor, group }) {
|
|
10566
|
-
setColor("cyan");
|
|
10567
|
-
group.lines.forEach((line) => {
|
|
10568
|
-
drawRulerLine(line.start, line.end);
|
|
10569
|
-
});
|
|
10570
|
-
}
|
|
10571
|
-
});
|
|
10572
10600
|
cad.addDrawHandler({
|
|
10573
10601
|
type: ["balconyRailing"],
|
|
10574
10602
|
handler({ group, setColor, drawLine }) {
|
|
@@ -10580,17 +10608,19 @@ class DxfDrawPlugin {
|
|
|
10580
10608
|
});
|
|
10581
10609
|
}
|
|
10582
10610
|
}
|
|
10583
|
-
class DxfDataPlugin
|
|
10611
|
+
class DxfDataPlugin {
|
|
10584
10612
|
manager;
|
|
10585
10613
|
lines = [];
|
|
10614
|
+
pipeline;
|
|
10586
10615
|
constructor(lines) {
|
|
10587
|
-
super();
|
|
10588
10616
|
this.lines = lines;
|
|
10589
10617
|
this.manager = WallGroupManager.fromByLines(lines);
|
|
10590
|
-
this.
|
|
10591
|
-
|
|
10592
|
-
|
|
10593
|
-
|
|
10618
|
+
this.pipeline = new Pipeline();
|
|
10619
|
+
this.manager.forEach((group) => {
|
|
10620
|
+
const option = { lines: group.lines };
|
|
10621
|
+
this.pipeline.run(group.type, option);
|
|
10622
|
+
group.lines = option.lines;
|
|
10623
|
+
});
|
|
10594
10624
|
}
|
|
10595
10625
|
install(cad) {
|
|
10596
10626
|
const wallGroupManager = this.manager, lines = this.lines;
|
|
@@ -10613,6 +10643,7 @@ class DxfDataPlugin extends Pipeline {
|
|
|
10613
10643
|
cad.addGroupAndOffset([...untreatedWall], { type: "wall" });
|
|
10614
10644
|
cad.addGroups(untreatedDoubleWallGroup, "doubleWall");
|
|
10615
10645
|
cad.unionGroupAll("wall");
|
|
10646
|
+
cad.addGroup(cad.getAllLines(), "measurement");
|
|
10616
10647
|
const offsetWidth = 0.05;
|
|
10617
10648
|
cad.addGroupAndOffset(balconyRailingLines, {
|
|
10618
10649
|
offsetHalfWidth: offsetWidth * 0.5,
|
|
@@ -11157,9 +11188,9 @@ class DoubleWallHelper {
|
|
|
11157
11188
|
quadtree.insert(line);
|
|
11158
11189
|
lines.push(line);
|
|
11159
11190
|
});
|
|
11160
|
-
lines = lineSegmentClipping(lines, 1e-9);
|
|
11161
11191
|
quadtree.clear();
|
|
11162
11192
|
lines.push(...otherLines);
|
|
11193
|
+
lines = lineSegmentClipping(lines, 1e-9);
|
|
11163
11194
|
PointUtils.adsorb(lines.flatMap((line) => line.points), 1e-4);
|
|
11164
11195
|
return lines.filter((line) => line.length() > 1e-9);
|
|
11165
11196
|
}
|
|
@@ -11340,7 +11371,8 @@ function correction(lines, targettLine, option) {
|
|
|
11340
11371
|
new WallInsertObject(newLines).recomputed().merge();
|
|
11341
11372
|
newLines.push(...otherLines);
|
|
11342
11373
|
newLines = removeDangline(newLines, 0.15, true);
|
|
11343
|
-
|
|
11374
|
+
newLines = newLines.filter((line) => line.length() > 1e-9);
|
|
11375
|
+
return newLines;
|
|
11344
11376
|
}
|
|
11345
11377
|
function axisAlignCorr(lines, option, verticalReferenceLine) {
|
|
11346
11378
|
verticalReferenceLine = verticalReferenceLine ?? LineSegmentUtils.findDominantDirectionLine(lines.filter((line) => !line.userData.isDoor));
|
|
@@ -71,20 +71,7 @@ export declare class Dxf<TEventMap extends {} = {}> extends Component<{
|
|
|
71
71
|
downloadOriginalData(filename: string): Promise<void>;
|
|
72
72
|
/** 获取绘制数据
|
|
73
73
|
*/
|
|
74
|
-
toDrawData(unit?: Unit):
|
|
75
|
-
unit: Unit;
|
|
76
|
-
lines: [number, number, number, number, string][];
|
|
77
|
-
lines2: [number, number, number, number, string][];
|
|
78
|
-
arcs: [number, number, number, number, number, string][];
|
|
79
|
-
texts: [string, number, number, string][];
|
|
80
|
-
center: {
|
|
81
|
-
x: number;
|
|
82
|
-
y: number;
|
|
83
|
-
};
|
|
84
|
-
width: number;
|
|
85
|
-
height: number;
|
|
86
|
-
scale: number;
|
|
87
|
-
} | undefined;
|
|
74
|
+
toDrawData(unit?: Unit): import('../utils/CAD/drawData').DrawData | undefined;
|
|
88
75
|
/** 获取 dxf 图片 二进制对象
|
|
89
76
|
* @param type
|
|
90
77
|
*/
|
|
@@ -169,12 +169,12 @@ export declare class CommandFlowComponent<TEventMap extends {} = {}> extends Com
|
|
|
169
169
|
}): {
|
|
170
170
|
readonly ended: boolean;
|
|
171
171
|
end: () => void;
|
|
172
|
-
next: (mode_: "all" | "
|
|
172
|
+
next: (mode_: "all" | "line" | "point" | "empty" | "line_point" | "line_empty" | "point_empty" | "null") => Promise<{
|
|
173
173
|
point: Point;
|
|
174
174
|
line?: LineSegment;
|
|
175
175
|
} | null>;
|
|
176
176
|
setBaseLine(line: LineSegment<Record<string, any>> | null, point: Point | null): void;
|
|
177
|
-
points(mode_: "all" | "
|
|
177
|
+
points(mode_: "all" | "line" | "point" | "empty" | "line_point" | "line_empty" | "point_empty" | "null"): {
|
|
178
178
|
next(): Promise<{
|
|
179
179
|
value: {
|
|
180
180
|
point: Point;
|
|
@@ -190,15 +190,15 @@ export declare class CommandFlowComponent<TEventMap extends {} = {}> extends Com
|
|
|
190
190
|
awaitEach(callBack: (result: {
|
|
191
191
|
point: Point<Record<string, any>>;
|
|
192
192
|
line?: LineSegment;
|
|
193
|
-
} | null) => void, mode_?: "all" | "
|
|
193
|
+
} | null) => void, mode_?: "all" | "line" | "point" | "empty" | "line_point" | "line_empty" | "point_empty" | "null"): Promise<{
|
|
194
194
|
readonly ended: boolean;
|
|
195
195
|
end: () => void;
|
|
196
|
-
next: (mode_: "all" | "
|
|
196
|
+
next: (mode_: "all" | "line" | "point" | "empty" | "line_point" | "line_empty" | "point_empty" | "null") => Promise<{
|
|
197
197
|
point: Point;
|
|
198
198
|
line?: LineSegment;
|
|
199
199
|
} | null>;
|
|
200
200
|
setBaseLine(line: LineSegment<Record<string, any>> | null, point: Point | null): void;
|
|
201
|
-
points(mode_: "all" | "
|
|
201
|
+
points(mode_: "all" | "line" | "point" | "empty" | "line_point" | "line_empty" | "point_empty" | "null"): {
|
|
202
202
|
next(): Promise<{
|
|
203
203
|
value: {
|
|
204
204
|
point: Point;
|
|
@@ -214,7 +214,7 @@ export declare class CommandFlowComponent<TEventMap extends {} = {}> extends Com
|
|
|
214
214
|
awaitEach(callBack: (result: {
|
|
215
215
|
point: Point<Record<string, any>>;
|
|
216
216
|
line?: LineSegment;
|
|
217
|
-
} | null) => void, mode_?: "all" | "
|
|
217
|
+
} | null) => void, mode_?: "all" | "line" | "point" | "empty" | "line_point" | "line_empty" | "point_empty" | "null"): Promise</*elided*/ any>;
|
|
218
218
|
}>;
|
|
219
219
|
};
|
|
220
220
|
/**
|
package/src/dxfSystem/type.d.ts
CHANGED
|
@@ -103,19 +103,6 @@ export type OriginalDataItem = {
|
|
|
103
103
|
* [开始点, 结束点, 相交点, 是否是门, 索引]
|
|
104
104
|
*/
|
|
105
105
|
export type DataItem = [Point, Point, number[], boolean, number];
|
|
106
|
-
export type DrawData = {
|
|
107
|
-
unit: Unit;
|
|
108
|
-
line: [number, number, number, number, string][];
|
|
109
|
-
arc: [number, number, number, number, number, string][];
|
|
110
|
-
dimensionLine: number[][];
|
|
111
|
-
center: {
|
|
112
|
-
x: number;
|
|
113
|
-
y: number;
|
|
114
|
-
};
|
|
115
|
-
width: number;
|
|
116
|
-
height: number;
|
|
117
|
-
scale: number;
|
|
118
|
-
};
|
|
119
106
|
export type FittingMethodType = "average" | "max";
|
|
120
107
|
export type SetDataOption = {
|
|
121
108
|
/**
|
|
@@ -190,6 +177,11 @@ export type ItemInfo = {
|
|
|
190
177
|
y: number;
|
|
191
178
|
z: number;
|
|
192
179
|
}[];
|
|
180
|
+
quadContour?: {
|
|
181
|
+
x: number;
|
|
182
|
+
y: number;
|
|
183
|
+
z: number;
|
|
184
|
+
}[];
|
|
193
185
|
direction: {
|
|
194
186
|
x: number;
|
|
195
187
|
y: number;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Unit } from '../../type';
|
|
2
|
+
import { CAD } from '.';
|
|
3
|
+
export type DrawData = {
|
|
4
|
+
unit: Unit;
|
|
5
|
+
lines: [number, number, number, number, string][];
|
|
6
|
+
lines2: [number, number, number, number, string][];
|
|
7
|
+
arcs: [number, number, number, number, number, string][];
|
|
8
|
+
texts: [string, number, number, string][];
|
|
9
|
+
center: {
|
|
10
|
+
x: number;
|
|
11
|
+
y: number;
|
|
12
|
+
};
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
scale: number;
|
|
16
|
+
};
|
|
17
|
+
export declare const units: {
|
|
18
|
+
Unitless: number;
|
|
19
|
+
Inches: number;
|
|
20
|
+
Feet: number;
|
|
21
|
+
Miles: number;
|
|
22
|
+
Millimeters: number;
|
|
23
|
+
Centimeters: number;
|
|
24
|
+
Meters: number;
|
|
25
|
+
Kilometers: number;
|
|
26
|
+
Microinches: number;
|
|
27
|
+
Mils: number;
|
|
28
|
+
Yards: number;
|
|
29
|
+
Angstroms: number;
|
|
30
|
+
Nanometers: number;
|
|
31
|
+
Microns: number;
|
|
32
|
+
Decimeters: number;
|
|
33
|
+
Decameters: number;
|
|
34
|
+
Hectometers: number;
|
|
35
|
+
Gigameters: number;
|
|
36
|
+
"Astronomical units": number;
|
|
37
|
+
"Light years": number;
|
|
38
|
+
Parsecs: number;
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* 转为绘制数据
|
|
42
|
+
*/
|
|
43
|
+
export declare function toDrawData(this: CAD, unit?: Unit): DrawData;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { LineSegment } from '
|
|
2
|
-
import { LineUserData, Unit } from '
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { LineSegment } from '../../../utils/algorithms/LineSegment';
|
|
2
|
+
import { LineUserData, Unit } from '../../type';
|
|
3
|
+
import { SetMap } from '../../../utils/algorithms/Map';
|
|
4
|
+
import { Point } from '../../../utils/algorithms/Point';
|
|
5
|
+
import { WallGroupManager } from '../WallGroupManager';
|
|
6
|
+
import { Pipeline } from '../../../utils/algorithms/Pipeline';
|
|
6
7
|
type LineSegmentType = LineSegment<LineUserData>;
|
|
7
8
|
type JoinType = "jtMiter" | "jtSquare" | "jtRound";
|
|
8
9
|
type EndType = "etOpenSquare" | "etOpenButt" | "etOpenRound";
|
|
@@ -26,6 +27,7 @@ export type CADDrawHandler = {
|
|
|
26
27
|
drawArc(pos: Point, radius: number, startAngle: number, endAngle: number): void;
|
|
27
28
|
drawDottedLine(p1: Point, p2: Point, dash?: number, gap?: number): void;
|
|
28
29
|
drawRulerLine(p1: Point, p2: Point): void;
|
|
30
|
+
drawText(str: string, p: Point): void;
|
|
29
31
|
group: Group;
|
|
30
32
|
setColor: (color: string) => void;
|
|
31
33
|
}) => void;
|
|
@@ -51,7 +53,7 @@ declare class Group {
|
|
|
51
53
|
*/
|
|
52
54
|
export declare class CAD {
|
|
53
55
|
groups: Group[];
|
|
54
|
-
|
|
56
|
+
_drawHandlerMap: SetMap<string, CADDrawHandler>;
|
|
55
57
|
needUpdate: boolean;
|
|
56
58
|
getAllLines(): LineSegmentType[];
|
|
57
59
|
/** 添加组
|
|
@@ -98,8 +100,8 @@ export declare class CAD {
|
|
|
98
100
|
/**
|
|
99
101
|
* 转为绘制数据
|
|
100
102
|
*/
|
|
101
|
-
|
|
102
|
-
toDrawData(unit?: Unit): DrawData;
|
|
103
|
+
_cachedDrawDataMap: Map<string, DrawData>;
|
|
104
|
+
toDrawData(unit?: Unit): import('./drawData').DrawData;
|
|
103
105
|
/** 转为图片
|
|
104
106
|
* @param type
|
|
105
107
|
*/
|
|
@@ -157,11 +159,11 @@ type DataOption = {
|
|
|
157
159
|
};
|
|
158
160
|
/** dxf 数据处理插件
|
|
159
161
|
*/
|
|
160
|
-
export declare class DxfDataPlugin
|
|
162
|
+
export declare class DxfDataPlugin implements ICADPlugin {
|
|
161
163
|
manager: WallGroupManager;
|
|
162
164
|
lines: LineSegment<LineUserData>[];
|
|
165
|
+
pipeline: Pipeline<DataOption>;
|
|
163
166
|
constructor(lines: LineSegment<LineUserData>[]);
|
|
164
|
-
init(): void;
|
|
165
167
|
install(cad: CAD): void;
|
|
166
168
|
}
|
|
167
169
|
export {};
|
|
@@ -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, dedup?: boolean): LineSegment<Record<string, any>>[];
|
|
8
|
+
export declare function lineSegmentClipping(lines: LineSegment<LineUserData>[], minLen?: number, dedup?: boolean): LineSegment<Record<string, any>>[] | LineSegment<LineUserData>[];
|
|
@@ -4,16 +4,18 @@ import { Rectangle } from './Rectangle';
|
|
|
4
4
|
* 非轴对称线段
|
|
5
5
|
*/
|
|
6
6
|
export declare class LineSegment<T = Record<string, any>> {
|
|
7
|
-
#private;
|
|
8
7
|
static get LINE_SYMBOL(): symbol;
|
|
9
8
|
points: Point[];
|
|
10
9
|
userData: T;
|
|
11
10
|
currentData: Record<string | number | symbol, any>;
|
|
12
11
|
uuid: string;
|
|
12
|
+
private _length;
|
|
13
13
|
get len(): number;
|
|
14
14
|
get start(): Point<Record<string, any>>;
|
|
15
15
|
get end(): Point<Record<string, any>>;
|
|
16
|
+
_center: Point<Record<string, any>>;
|
|
16
17
|
get center(): Point<Record<string, any>>;
|
|
18
|
+
_direction: Point<Record<string, any>>;
|
|
17
19
|
constructor(p1?: Point, p2?: Point);
|
|
18
20
|
private _initLenListener;
|
|
19
21
|
set(p1: Point, p2: Point): this;
|
|
@@ -41,25 +43,25 @@ export declare class LineSegment<T = Record<string, any>> {
|
|
|
41
43
|
* @param line
|
|
42
44
|
* @returns
|
|
43
45
|
*/
|
|
44
|
-
isSameEndpoint(line: LineSegment): boolean;
|
|
46
|
+
isSameEndpoint(line: LineSegment, eps?: number): boolean;
|
|
45
47
|
/**
|
|
46
48
|
* 相同端点是否为开始
|
|
47
49
|
* @param line
|
|
48
50
|
* @returns
|
|
49
51
|
*/
|
|
50
|
-
isSameEndpointAsStart(line: LineSegment): boolean;
|
|
52
|
+
isSameEndpointAsStart(line: LineSegment, eps?: number): boolean;
|
|
51
53
|
/**
|
|
52
54
|
* 相同端点是否为结束
|
|
53
55
|
* @param line
|
|
54
56
|
* @returns
|
|
55
57
|
*/
|
|
56
|
-
isSameEndpointAsEnd(line: LineSegment): boolean;
|
|
58
|
+
isSameEndpointAsEnd(line: LineSegment, eps?: number): boolean;
|
|
57
59
|
/**
|
|
58
60
|
* 获取共线点
|
|
59
61
|
* @param line
|
|
60
62
|
* @returns
|
|
61
63
|
*/
|
|
62
|
-
getSameEndpoint(line: LineSegment): Point<Record<string, any>>[] | null;
|
|
64
|
+
getSameEndpoint(line: LineSegment, eps?: number): Point<Record<string, any>>[] | null;
|
|
63
65
|
/**
|
|
64
66
|
* 判断一个点是否在当前线段上(包含端点)
|
|
65
67
|
* @param point 要判断的点
|
|
@@ -113,6 +113,7 @@ export declare class LineSegmentUtils {
|
|
|
113
113
|
* @returns
|
|
114
114
|
*/
|
|
115
115
|
static flatPoints(lines: LineSegment[] | LineSegment): any[];
|
|
116
|
+
static resolveIntersection<T>(lines: LineSegment[], onClip?: (target: LineSegment<T>, newLines: LineSegment<T>[]) => void): LineSegment<T>[];
|
|
116
117
|
/** 对线段组统计,找到主导方向线
|
|
117
118
|
* @param lineSegments
|
|
118
119
|
* @returns
|