build-dxf 0.0.12 → 0.0.13
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 +314 -67
- package/src/index2.js +43 -15
- package/src/utils/DxfSystem/components/Dxf.d.ts +19 -0
- package/src/utils/DxfSystem/components/LineAnalysis.d.ts +0 -5
- package/src/utils/DxfSystem/plugin/ModelDataPlugin/components/WhiteModel.d.ts +6 -1
- package/src/utils/DxfSystem/plugin/RenderPlugin/components/Renderer.d.ts +2 -2
- package/src/utils/Quadtree/LineSegment.d.ts +42 -0
- package/src/utils/Quadtree/Point.d.ts +9 -0
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -3,6 +3,7 @@ import { EventDispatcher as EventDispatcher$1 } from "three";
|
|
|
3
3
|
import ClipperLib from "clipper-lib";
|
|
4
4
|
import Drawing from "dxf-writer";
|
|
5
5
|
import { OBJExporter } from "three/examples/jsm/exporters/OBJExporter.js";
|
|
6
|
+
import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter.js";
|
|
6
7
|
function uuid() {
|
|
7
8
|
return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(c) {
|
|
8
9
|
var r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
|
|
@@ -274,6 +275,7 @@ class Point {
|
|
|
274
275
|
}
|
|
275
276
|
/** 计算两个向量夹角
|
|
276
277
|
* @description 公式:a · b = |a| × |b| × cosθ
|
|
278
|
+
* @description 结果为0(0度),两个向量方向一致,结果为3.1415926(180度, PI),两个向量方向相反
|
|
277
279
|
* @param point
|
|
278
280
|
* @returns
|
|
279
281
|
*/
|
|
@@ -311,6 +313,14 @@ class Point {
|
|
|
311
313
|
clone() {
|
|
312
314
|
return new Point(this.x, this.y);
|
|
313
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* 克隆
|
|
318
|
+
* @returns
|
|
319
|
+
*/
|
|
320
|
+
copy(p) {
|
|
321
|
+
this.x = p.x ?? 0;
|
|
322
|
+
this.y = p.y ?? 0;
|
|
323
|
+
}
|
|
314
324
|
static from(arr) {
|
|
315
325
|
if (Array.isArray(arr)) {
|
|
316
326
|
return new Point(arr[0], arr[1]);
|
|
@@ -600,6 +610,13 @@ class LineSegment {
|
|
|
600
610
|
direction() {
|
|
601
611
|
return this.points[1].direction(this.points[0]);
|
|
602
612
|
}
|
|
613
|
+
/**
|
|
614
|
+
* 线段长度
|
|
615
|
+
* @returns
|
|
616
|
+
*/
|
|
617
|
+
length() {
|
|
618
|
+
return this.points[1].distance(this.points[0]);
|
|
619
|
+
}
|
|
603
620
|
/**
|
|
604
621
|
* 计算一条线段在另一条直线上的投影,并裁剪超出目标线段的部分
|
|
605
622
|
* @param line 要投影的线段
|
|
@@ -650,6 +667,89 @@ class LineSegment {
|
|
|
650
667
|
}
|
|
651
668
|
return new LineSegment(projP1, projP2);
|
|
652
669
|
}
|
|
670
|
+
/**
|
|
671
|
+
* 判断线段是与线段相交
|
|
672
|
+
* @param line
|
|
673
|
+
*/
|
|
674
|
+
intersectLineSegment(line) {
|
|
675
|
+
const p1 = this.start;
|
|
676
|
+
const p2 = this.end;
|
|
677
|
+
const p3 = line.start;
|
|
678
|
+
const p4 = line.end;
|
|
679
|
+
function crossProduct(p12, p22, p32) {
|
|
680
|
+
return (p22.x - p12.x) * (p32.y - p12.y) - (p22.y - p12.y) * (p32.x - p12.x);
|
|
681
|
+
}
|
|
682
|
+
const d1 = crossProduct(p1, p2, p3);
|
|
683
|
+
const d2 = crossProduct(p1, p2, p4);
|
|
684
|
+
const d3 = crossProduct(p3, p4, p1);
|
|
685
|
+
const d4 = crossProduct(p3, p4, p2);
|
|
686
|
+
return d1 * d2 < 0 && d3 * d4 < 0;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* 获取交点
|
|
690
|
+
* @param line
|
|
691
|
+
* @returns
|
|
692
|
+
*/
|
|
693
|
+
getIntersection(line) {
|
|
694
|
+
const p1 = this.start;
|
|
695
|
+
const p2 = this.end;
|
|
696
|
+
const p3 = line.start;
|
|
697
|
+
const p4 = line.end;
|
|
698
|
+
const denom = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x);
|
|
699
|
+
if (Math.abs(denom) < 1e-10) {
|
|
700
|
+
return null;
|
|
701
|
+
}
|
|
702
|
+
const t = ((p1.x - p3.x) * (p3.y - p4.y) - (p1.y - p3.y) * (p3.x - p4.x)) / denom;
|
|
703
|
+
const x = p1.x + t * (p2.x - p1.x);
|
|
704
|
+
const y = p1.y + t * (p2.y - p1.y);
|
|
705
|
+
return new Point(x, y);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* 获取两条线段夹角
|
|
709
|
+
* @param line
|
|
710
|
+
*/
|
|
711
|
+
includedAngle(line) {
|
|
712
|
+
const d1 = this.direction(), d2 = line.direction();
|
|
713
|
+
return d1.angleBetween(d2) / (Math.PI / 180);
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* 两条线段方向是否一致
|
|
717
|
+
* @param line
|
|
718
|
+
*/
|
|
719
|
+
directionEqual(line, errAngle = 0.1) {
|
|
720
|
+
return this.includedAngle(line) < errAngle;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* 两条线段方向相反否一致
|
|
724
|
+
* @param line
|
|
725
|
+
*/
|
|
726
|
+
directionOpposite(line, errAngle = 0.1) {
|
|
727
|
+
return 180 - this.includedAngle(line) < errAngle;
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* 判断两条线是否平行
|
|
731
|
+
* @param line
|
|
732
|
+
*/
|
|
733
|
+
isParallel(line, errAngle = 4) {
|
|
734
|
+
const angle = this.includedAngle(line);
|
|
735
|
+
return angle < errAngle || angle > 180 - errAngle;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* 判断两条直线是否重合
|
|
739
|
+
* @param line
|
|
740
|
+
* @returns
|
|
741
|
+
*/
|
|
742
|
+
areLinesCoincident(line) {
|
|
743
|
+
const p1 = this.start, p2 = this.end, p3 = line.start, p4 = line.end;
|
|
744
|
+
const m1 = (p2.y - p1.y) / (p2.x - p1.x);
|
|
745
|
+
const b1 = p1.y - m1 * p1.x;
|
|
746
|
+
const m2 = (p4.y - p3.y) / (p4.x - p3.x);
|
|
747
|
+
const b2 = p3.y - m2 * p3.x;
|
|
748
|
+
if (!isFinite(m1) && !isFinite(m2)) {
|
|
749
|
+
return p1.x === p3.x && p2.x === p3.x;
|
|
750
|
+
}
|
|
751
|
+
return Math.abs(m1 - m2) < 1e-3 && Math.abs(b1 - b2) < 1e-3;
|
|
752
|
+
}
|
|
653
753
|
clone() {
|
|
654
754
|
return new LineSegment(
|
|
655
755
|
this.points[0].clone(),
|
|
@@ -701,8 +801,25 @@ const units = {
|
|
|
701
801
|
Parsecs: 3240779289666404e-32
|
|
702
802
|
// 秒差距,1米 ≈ 0.00000000000000003240779289666404秒差距
|
|
703
803
|
};
|
|
804
|
+
function pathToLines(path) {
|
|
805
|
+
const lineSegments = [];
|
|
806
|
+
for (let i = 0; i < path.length; i++) {
|
|
807
|
+
lineSegments.push(new LineSegment(
|
|
808
|
+
path[i],
|
|
809
|
+
path[(i + 1) % path.length]
|
|
810
|
+
));
|
|
811
|
+
}
|
|
812
|
+
return lineSegments;
|
|
813
|
+
}
|
|
814
|
+
function linesToPath(lineSegments) {
|
|
815
|
+
return lineSegments.flatMap((line, index2) => {
|
|
816
|
+
if (index2 === lineSegments.length - 1) [...line.points, lineSegments[0].points[0]];
|
|
817
|
+
return [line.points[0]];
|
|
818
|
+
});
|
|
819
|
+
}
|
|
704
820
|
class Dxf extends Component {
|
|
705
821
|
static name = "Dxf";
|
|
822
|
+
shortLine = 0.04;
|
|
706
823
|
width = 0.04;
|
|
707
824
|
scale = 1;
|
|
708
825
|
originalData = [];
|
|
@@ -740,6 +857,7 @@ class Dxf extends Component {
|
|
|
740
857
|
super();
|
|
741
858
|
this.width = width;
|
|
742
859
|
this.scale = scale;
|
|
860
|
+
this.shortLine = width * 0.8;
|
|
743
861
|
}
|
|
744
862
|
/**
|
|
745
863
|
* 设置
|
|
@@ -765,6 +883,7 @@ class Dxf extends Component {
|
|
|
765
883
|
this.scale = scale;
|
|
766
884
|
this.width = width;
|
|
767
885
|
this.originalData = data;
|
|
886
|
+
this.lineSegments.length = 0;
|
|
768
887
|
const zList = [];
|
|
769
888
|
this.data = data.map(({ start, end, insetionArr, isDoor = false }, index2) => {
|
|
770
889
|
zList.push(start.z ?? 0, end.z ?? 0);
|
|
@@ -875,55 +994,158 @@ class Dxf extends Component {
|
|
|
875
994
|
/** etOpenRound 去除毛刺
|
|
876
995
|
* @description 检查连续的短线段数量,去除合并后产生的毛刺
|
|
877
996
|
*/
|
|
878
|
-
squareRemoveBurr() {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
i += count;
|
|
903
|
-
} else {
|
|
904
|
-
filterLines.push(curr);
|
|
905
|
-
}
|
|
997
|
+
squareRemoveBurr(path) {
|
|
998
|
+
if (path.length < 3) return path;
|
|
999
|
+
const filterLines = [path[0]];
|
|
1000
|
+
for (let i = 1; i < path.length; i++) {
|
|
1001
|
+
const prev = path[i - 1];
|
|
1002
|
+
const curr = path[i];
|
|
1003
|
+
const len = prev.distance(curr);
|
|
1004
|
+
if (len < this.width * 0.5) {
|
|
1005
|
+
let count = 0;
|
|
1006
|
+
for (let j = i + 1; j < path.length; j++) {
|
|
1007
|
+
const prev2 = path[j - 1];
|
|
1008
|
+
const curr2 = path[j];
|
|
1009
|
+
const len2 = prev2.distance(curr2);
|
|
1010
|
+
if (len2 < this.width * 0.8) count++;
|
|
1011
|
+
else break;
|
|
1012
|
+
}
|
|
1013
|
+
if (count === 0 && i + count === path.length - 1) ;
|
|
1014
|
+
else if (i == 1 && count === 1) ;
|
|
1015
|
+
else if (count === 3) {
|
|
1016
|
+
filterLines.push(path[i + 1]);
|
|
1017
|
+
i += count;
|
|
1018
|
+
} else if (count === 5) {
|
|
1019
|
+
filterLines.push(path[i + 2]);
|
|
1020
|
+
i += count;
|
|
906
1021
|
} else {
|
|
907
1022
|
filterLines.push(curr);
|
|
908
1023
|
}
|
|
1024
|
+
} else {
|
|
1025
|
+
filterLines.push(curr);
|
|
909
1026
|
}
|
|
910
|
-
|
|
911
|
-
|
|
1027
|
+
}
|
|
1028
|
+
return filterLines;
|
|
1029
|
+
}
|
|
1030
|
+
epsilon = 1e-6;
|
|
1031
|
+
// 距离阈值,用于比较点
|
|
1032
|
+
/**
|
|
1033
|
+
* 移除共线点
|
|
1034
|
+
* @param path
|
|
1035
|
+
* @returns
|
|
1036
|
+
*/
|
|
1037
|
+
removeCollinearPoints(path) {
|
|
1038
|
+
for (let i = 0; i < path.length; i++) {
|
|
1039
|
+
const p1 = path[i];
|
|
1040
|
+
const p2 = path[(i + 1) % path.length];
|
|
1041
|
+
if (p1.distance(p2) > this.shortLine) {
|
|
1042
|
+
path.push(...path.slice(0, i));
|
|
1043
|
+
path.splice(0, i);
|
|
1044
|
+
break;
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
if (path.length < 3) return path;
|
|
1048
|
+
const cleanedPath = [];
|
|
1049
|
+
const n = path.length;
|
|
1050
|
+
for (let i = 0; i < n; i++) {
|
|
1051
|
+
const p1 = path[i];
|
|
1052
|
+
const p2 = path[(i + 1) % n];
|
|
1053
|
+
const p3 = path[(i + 2) % n];
|
|
1054
|
+
const cross = (p2.X - p1.X) * (p3.Y - p2.Y) - (p2.Y - p1.Y) * (p3.X - p2.X);
|
|
1055
|
+
if (Math.abs(cross) > this.epsilon) {
|
|
1056
|
+
cleanedPath.push(p1);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
return cleanedPath;
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* 线段矫直, 线段中心突刺
|
|
1063
|
+
* @description 突变长度小于墙体宽度,该线段可能为突起线段,
|
|
1064
|
+
* @description 判断后续第2线段与上一条线段是否方向相同,相同就为突刺
|
|
1065
|
+
*/
|
|
1066
|
+
lineSegmentStraightening(path) {
|
|
1067
|
+
const lines = pathToLines(path), filterLines = [lines[0]];
|
|
1068
|
+
for (let i = 1; i < lines.length; i++) {
|
|
1069
|
+
const line = lines[i];
|
|
1070
|
+
const preLine = lines[(lines.length + i - 1) % lines.length];
|
|
1071
|
+
if (line.length() > this.width * 0.9) {
|
|
1072
|
+
filterLines.push(line);
|
|
1073
|
+
continue;
|
|
1074
|
+
}
|
|
1075
|
+
const line1 = lines[i + 1];
|
|
1076
|
+
if (line1 && line1.length() > this.width * 0.9) {
|
|
1077
|
+
filterLines.push(line);
|
|
1078
|
+
filterLines.push(line1);
|
|
1079
|
+
i = i + 1;
|
|
1080
|
+
continue;
|
|
1081
|
+
}
|
|
1082
|
+
const line2 = lines[i + 2];
|
|
1083
|
+
if (line2 && preLine.includedAngle(line2) < 1) {
|
|
1084
|
+
i = i + 2;
|
|
1085
|
+
filterLines.push(line2);
|
|
1086
|
+
} else filterLines.push(line);
|
|
1087
|
+
}
|
|
1088
|
+
return filterLines.length > 3 ? linesToPath(filterLines) : [];
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* 移除短线段
|
|
1092
|
+
* @param path
|
|
1093
|
+
*/
|
|
1094
|
+
removeShortLine(path, shortLine = this.shortLine) {
|
|
1095
|
+
const lines = pathToLines(path), filterLines = [], PI_1 = Math.PI / 180;
|
|
1096
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1097
|
+
const line = lines[i], len = line.length();
|
|
1098
|
+
if (len > shortLine || filterLines.length === 0) {
|
|
1099
|
+
filterLines.push(line);
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
let nextline = lines[++i];
|
|
1103
|
+
const preLine = filterLines[filterLines.length - 1], d1 = preLine.direction();
|
|
1104
|
+
while (i < lines.length) {
|
|
1105
|
+
const angle = d1.angleBetween(nextline.direction()) / PI_1;
|
|
1106
|
+
if (nextline.length() <= shortLine || angle < 4 || angle > 180 - 4) {
|
|
1107
|
+
nextline = lines[++i];
|
|
1108
|
+
} else break;
|
|
1109
|
+
}
|
|
1110
|
+
if (nextline) {
|
|
1111
|
+
const intersectPoint = preLine.getIntersection(nextline);
|
|
1112
|
+
if (intersectPoint) {
|
|
1113
|
+
const p0 = preLine.points[1].clone(), p1 = nextline.points[0].clone();
|
|
1114
|
+
preLine.points[1].copy(intersectPoint);
|
|
1115
|
+
nextline.points[0].copy(intersectPoint);
|
|
1116
|
+
if (preLine.length() < this.width) {
|
|
1117
|
+
preLine.points[1].copy(p0);
|
|
1118
|
+
nextline.points[0].copy(p0);
|
|
1119
|
+
} else if (nextline.length() < this.width) {
|
|
1120
|
+
preLine.points[1].copy(p1);
|
|
1121
|
+
nextline.points[0].copy(p1);
|
|
1122
|
+
}
|
|
1123
|
+
} else {
|
|
1124
|
+
preLine.points[1].copy(nextline.points[0]);
|
|
1125
|
+
}
|
|
1126
|
+
filterLines.push(nextline);
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
return filterLines.length > 3 ? linesToPath(filterLines) : [];
|
|
912
1130
|
}
|
|
913
1131
|
/** 线偏移
|
|
914
1132
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
915
1133
|
*/
|
|
916
1134
|
lineOffset(endType = Dxf.EndType.etOpenSquare, joinType = Dxf.JoinType.jtMiter, scale = 1e4) {
|
|
917
|
-
|
|
1135
|
+
let solutions = new ClipperLib.Paths();
|
|
918
1136
|
const offset = new ClipperLib.ClipperOffset(20, 0.25);
|
|
919
1137
|
this.pointsGroups.forEach((points) => {
|
|
920
1138
|
const linePaths = this.lineTopology(points).map((linePath) => linePath.map((p) => p.clone().mutiplyScalar(scale)));
|
|
921
1139
|
offset.AddPaths(linePaths, joinType, endType);
|
|
922
1140
|
});
|
|
923
1141
|
offset.Execute(solutions, this.width / 2 * scale);
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1142
|
+
this.wallsGroup = solutions.map((ps) => {
|
|
1143
|
+
let path = ps.map((p) => Point.from(p).divisionScalar(scale));
|
|
1144
|
+
path = this.removeCollinearPoints(path);
|
|
1145
|
+
path = this.lineSegmentStraightening(path);
|
|
1146
|
+
if (endType == Dxf.EndType.etOpenSquare) path = this.squareRemoveBurr(path);
|
|
1147
|
+
return path;
|
|
1148
|
+
});
|
|
927
1149
|
this.dispatchEvent({
|
|
928
1150
|
type: "lineOffset",
|
|
929
1151
|
wallsGroup: this.wallsGroup
|
|
@@ -1550,31 +1772,6 @@ class LineAnalysis extends Component {
|
|
|
1550
1772
|
this.Dxf = parent.findComponentByType(Dxf);
|
|
1551
1773
|
this.Variable = this.parent?.findComponentByType(Variable);
|
|
1552
1774
|
this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this));
|
|
1553
|
-
this.Dxf.addEventListener("lineOffset", this.duplicatePointFiltering.bind(this));
|
|
1554
|
-
}
|
|
1555
|
-
/**
|
|
1556
|
-
* 去除路径上重复的点
|
|
1557
|
-
* @description 判断方向向量,一个连续的方向上,只应该出现两个点
|
|
1558
|
-
*/
|
|
1559
|
-
duplicatePointFiltering() {
|
|
1560
|
-
const dxf = this.Dxf;
|
|
1561
|
-
dxf.wallsGroup = dxf.wallsGroup.map((points) => {
|
|
1562
|
-
const filterPoints = [];
|
|
1563
|
-
points.forEach((point, index2) => {
|
|
1564
|
-
if (index2 < 1 || points.length - 1 === index2) return filterPoints.push(point);
|
|
1565
|
-
const preP = points[index2 - 1], nextP = points[index2 + 1], direct1 = point.direction(preP), direct2 = nextP.direction(point), angle = direct1.angleBetween(direct2) / (Math.PI / 180);
|
|
1566
|
-
if (angle > 0.02 && angle < 180 - 0.02) filterPoints.push(point);
|
|
1567
|
-
});
|
|
1568
|
-
points = [filterPoints[0]];
|
|
1569
|
-
for (let i = 1; i < filterPoints.length; i++) {
|
|
1570
|
-
const point = filterPoints[i];
|
|
1571
|
-
const nextP = filterPoints[i - 1];
|
|
1572
|
-
if (nextP.distance(point) < dxf.width * 0.5) ;
|
|
1573
|
-
points.push(point);
|
|
1574
|
-
}
|
|
1575
|
-
return points;
|
|
1576
|
-
});
|
|
1577
|
-
dxf.wallsGroup = dxf.wallsGroup.filter((i) => i.length >= 4);
|
|
1578
1775
|
}
|
|
1579
1776
|
/**
|
|
1580
1777
|
*
|
|
@@ -1619,6 +1816,9 @@ class LineAnalysis extends Component {
|
|
|
1619
1816
|
createRectangle(result) {
|
|
1620
1817
|
const dxf = this.Dxf;
|
|
1621
1818
|
const project0 = result.project, project1 = result.project2;
|
|
1819
|
+
if (project0.includedAngle(project1) > 135) {
|
|
1820
|
+
project1.points = [project1.points[1], project1.points[0]];
|
|
1821
|
+
}
|
|
1622
1822
|
this.addData(project0.points[0], project1.points[0]);
|
|
1623
1823
|
this.addData(project0.points[1], project1.points[1]);
|
|
1624
1824
|
const leftHeight = project0.points[0].distance(project1.points[0]), rightHeight = project0.points[1].distance(project1.points[1]), count = Math.ceil(Math.max(leftHeight, rightHeight) / dxf.width), leftFragment = leftHeight / count, rightFragment = rightHeight / count, leftDirection = project1.points[0].direction(project0.points[0]), rightDirection = project1.points[1].direction(project0.points[1]), leftP = project0.points[0].clone(), rightP = project0.points[1].clone(), direction = rightP.direction(leftP);
|
|
@@ -1701,10 +1901,7 @@ class LineAnalysis extends Component {
|
|
|
1701
1901
|
const temLineSegment = lineSegmentList[index2], direct = sourceLineSegment.direction(), temDirect = temLineSegment.direction(), angle = direct.angleBetween(temDirect) / (Math.PI / 180);
|
|
1702
1902
|
if (angle < this.errorAngle || angle > 180 - this.errorAngle) {
|
|
1703
1903
|
let data;
|
|
1704
|
-
const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment)
|
|
1705
|
-
if (d1.x > 0 && d2.x < 0 || d1.x < 0 && d2.x > 0 || d1.y > 0 && d2.y < 0 || d1.y < 0 && d2.y > 0) {
|
|
1706
|
-
p1.points = [p1.points[1], p1.points[0]];
|
|
1707
|
-
}
|
|
1904
|
+
const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment);
|
|
1708
1905
|
if (p1.getLength() > p2.getLength()) {
|
|
1709
1906
|
data = {
|
|
1710
1907
|
target: temLineSegment,
|
|
@@ -1760,6 +1957,7 @@ class DxfSystem extends ComponentManager {
|
|
|
1760
1957
|
}
|
|
1761
1958
|
}
|
|
1762
1959
|
const exporter = new OBJExporter();
|
|
1960
|
+
const glbExporter = new GLTFExporter();
|
|
1763
1961
|
function lineSqueezing(p1, p2, width = 0.1) {
|
|
1764
1962
|
const normal = p2.normal(p1);
|
|
1765
1963
|
const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
|
|
@@ -1785,8 +1983,11 @@ class WhiteModel extends Component {
|
|
|
1785
1983
|
Variable = null;
|
|
1786
1984
|
// dxf数据白模
|
|
1787
1985
|
whiteModelGroup = new THREE.Group();
|
|
1986
|
+
// dxf数据白模边缘线
|
|
1987
|
+
whiteModelLineGroup = new THREE.Group();
|
|
1788
1988
|
// 原始数据白模
|
|
1789
1989
|
originalWhiteMode = new THREE.Group();
|
|
1990
|
+
material = new THREE.MeshBasicMaterial({ color: 16777215, transparent: true, opacity: 0.8, side: THREE.DoubleSide });
|
|
1790
1991
|
onAddFromParent(parent) {
|
|
1791
1992
|
this.Dxf = parent.findComponentByName("Dxf");
|
|
1792
1993
|
this.Variable = parent.findComponentByName("Variable");
|
|
@@ -1800,6 +2001,8 @@ class WhiteModel extends Component {
|
|
|
1800
2001
|
const dxf = this.Dxf;
|
|
1801
2002
|
this.originalWhiteMode.clear();
|
|
1802
2003
|
this.whiteModelGroup.clear();
|
|
2004
|
+
this.whiteModelLineGroup.clear();
|
|
2005
|
+
this.whiteModelGroup.add(this.whiteModelLineGroup);
|
|
1803
2006
|
this.whiteModelGroup.position.z = dxf.originalZAverage;
|
|
1804
2007
|
this.originalWhiteMode.position.z = dxf.originalZAverage;
|
|
1805
2008
|
dxf.wallsGroup.forEach((points) => {
|
|
@@ -1810,9 +2013,9 @@ class WhiteModel extends Component {
|
|
|
1810
2013
|
bevelSize: 0
|
|
1811
2014
|
});
|
|
1812
2015
|
const mesh = new THREE.Mesh(geometry);
|
|
1813
|
-
mesh.material =
|
|
2016
|
+
mesh.material = this.material;
|
|
1814
2017
|
this.whiteModelGroup.add(mesh);
|
|
1815
|
-
this.
|
|
2018
|
+
this.whiteModelLineGroup.add(
|
|
1816
2019
|
new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({ color: 6710886 }))
|
|
1817
2020
|
);
|
|
1818
2021
|
});
|
|
@@ -1851,15 +2054,58 @@ class WhiteModel extends Component {
|
|
|
1851
2054
|
resolve(exporter.parse(this.whiteModelGroup));
|
|
1852
2055
|
});
|
|
1853
2056
|
}
|
|
1854
|
-
|
|
2057
|
+
toGlb() {
|
|
2058
|
+
return new Promise((resolve) => {
|
|
2059
|
+
this.material.opacity = 1;
|
|
2060
|
+
this.material.needsUpdate = true;
|
|
2061
|
+
setTimeout(() => {
|
|
2062
|
+
glbExporter.parse(this.whiteModelGroup.children, (gltf) => {
|
|
2063
|
+
resolve(gltf);
|
|
2064
|
+
this.material.opacity = 0.8;
|
|
2065
|
+
this.material.transparent = true;
|
|
2066
|
+
}, () => {
|
|
2067
|
+
resolve(void 0);
|
|
2068
|
+
}, {
|
|
2069
|
+
binary: true
|
|
2070
|
+
});
|
|
2071
|
+
}, 100);
|
|
2072
|
+
});
|
|
2073
|
+
}
|
|
2074
|
+
async toOBJBlob() {
|
|
1855
2075
|
const buffer = await this.toOBJ();
|
|
1856
2076
|
if (buffer) {
|
|
1857
2077
|
return new Blob([buffer], { type: "application/octet-stream" });
|
|
1858
2078
|
}
|
|
1859
2079
|
}
|
|
2080
|
+
async toGlbBlob() {
|
|
2081
|
+
const buffer = await this.toGlb();
|
|
2082
|
+
if (buffer) {
|
|
2083
|
+
return new Blob([buffer], { type: "application/octet-stream" });
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
1860
2086
|
async download(filename) {
|
|
1861
2087
|
if (typeof window !== "undefined") {
|
|
1862
|
-
const blob = await this.
|
|
2088
|
+
const blob = await this.toOBJBlob();
|
|
2089
|
+
if (!blob) return;
|
|
2090
|
+
const a = document.createElement("a");
|
|
2091
|
+
a.href = URL.createObjectURL(blob);
|
|
2092
|
+
a.download = filename;
|
|
2093
|
+
a.click();
|
|
2094
|
+
} else if (typeof global !== "undefined") {
|
|
2095
|
+
const buffer = await this.toOBJ();
|
|
2096
|
+
if (buffer) {
|
|
2097
|
+
const packageName = "fs";
|
|
2098
|
+
const { default: fs } = await import(
|
|
2099
|
+
/* @vite-ignore */
|
|
2100
|
+
packageName
|
|
2101
|
+
);
|
|
2102
|
+
fs.writeFileSync(filename, buffer);
|
|
2103
|
+
}
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
async downloadGlb(filename) {
|
|
2107
|
+
if (typeof window !== "undefined") {
|
|
2108
|
+
const blob = await this.toGlbBlob();
|
|
1863
2109
|
if (!blob) return;
|
|
1864
2110
|
const a = document.createElement("a");
|
|
1865
2111
|
a.href = URL.createObjectURL(blob);
|
|
@@ -2016,6 +2262,7 @@ export {
|
|
|
2016
2262
|
ModelDataPlugin as M,
|
|
2017
2263
|
Point as P,
|
|
2018
2264
|
Variable as V,
|
|
2265
|
+
WhiteModel as W,
|
|
2019
2266
|
DetailsPoint as a,
|
|
2020
2267
|
index as i,
|
|
2021
2268
|
loadRenderPlugin as l
|
package/src/index2.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as Component, P as Point, B as Box2, V as Variable, D as DxfSystem, M as ModelDataPlugin, a as DetailsPoint } from "./build.js";
|
|
1
|
+
import { C as Component, P as Point, B as Box2, V as Variable, D as DxfSystem, M as ModelDataPlugin, a as DetailsPoint, W as WhiteModel } from "./build.js";
|
|
2
2
|
import * as THREE from "three";
|
|
3
|
-
import { BufferAttribute, Vector3, Plane, Line3, Vector2, Triangle, Sphere, Matrix4, Box3, BackSide, DoubleSide, REVISION, FrontSide, Mesh, BatchedMesh, Ray } from "three";
|
|
3
|
+
import { BufferAttribute, Vector3, Plane, Line3, Vector2, Triangle, Sphere, Matrix4, Box3, BackSide, DoubleSide, REVISION, FrontSide, Mesh, BatchedMesh, Ray, Group } from "three";
|
|
4
4
|
import "clipper-lib";
|
|
5
5
|
import "dxf-writer";
|
|
6
6
|
import { CSS3DObject, CSS3DSprite, CSS3DRenderer } from "three/addons/renderers/CSS3DRenderer.js";
|
|
@@ -3490,6 +3490,7 @@ class Renderer extends Component {
|
|
|
3490
3490
|
if (pos instanceof Point) box.position.set(pos.x, pos.y, 0);
|
|
3491
3491
|
else if (pos instanceof THREE.Vector3) box.position.copy(pos);
|
|
3492
3492
|
parent.add(box);
|
|
3493
|
+
return box;
|
|
3493
3494
|
}
|
|
3494
3495
|
/**
|
|
3495
3496
|
* 创建文本
|
|
@@ -3500,11 +3501,12 @@ class Renderer extends Component {
|
|
|
3500
3501
|
createText(text, pos, style, parent = this.container) {
|
|
3501
3502
|
const div = document.createElement("div");
|
|
3502
3503
|
div.innerHTML = text;
|
|
3503
|
-
Object.assign(div.style, { fontSize: "
|
|
3504
|
+
Object.assign(div.style, { fontSize: "10px", color: "#ffffff", ...style });
|
|
3504
3505
|
const css2DObject = new Renderer.CSS2DObject(div);
|
|
3505
3506
|
if (pos instanceof Point) css2DObject.position.set(pos.x, pos.y, 0);
|
|
3506
3507
|
else if (pos instanceof THREE.Vector3) css2DObject.position.copy(pos);
|
|
3507
3508
|
parent.add(css2DObject);
|
|
3509
|
+
return css2DObject;
|
|
3508
3510
|
}
|
|
3509
3511
|
/**
|
|
3510
3512
|
* 创建几何缓冲区
|
|
@@ -7109,12 +7111,27 @@ class ModelDataRender extends Component {
|
|
|
7109
7111
|
const renderer = parent.findComponentByName("Renderer");
|
|
7110
7112
|
const variable = parent.findComponentByName("Variable");
|
|
7111
7113
|
const dxfLineModel = parent.findComponentByName("DxfLineModel");
|
|
7114
|
+
const dxf = parent.findComponentByName("Dxf");
|
|
7112
7115
|
renderer.container.add(dxfLineModel.dxfModelGroup);
|
|
7113
7116
|
variable.addEventListener("dxfVisible", (e) => {
|
|
7114
7117
|
dxfLineModel.dxfModelGroup.visible = e.value;
|
|
7115
7118
|
});
|
|
7119
|
+
let group = new Group();
|
|
7120
|
+
dxfLineModel.dxfModelGroup.add(group);
|
|
7116
7121
|
variable?.addEventListener("currentKeyUp", (e) => {
|
|
7117
7122
|
if (e.value === "w") variable.set("dxfVisible", !variable.dxfVisible);
|
|
7123
|
+
if (e.value === "b") {
|
|
7124
|
+
if (group.visible) group.visible = false;
|
|
7125
|
+
else {
|
|
7126
|
+
group.visible = true;
|
|
7127
|
+
group.clear();
|
|
7128
|
+
dxf.wallsGroup.forEach((path, j) => {
|
|
7129
|
+
path.forEach((p, i) => {
|
|
7130
|
+
renderer.createText(`${i}`, p, { color: "#ff00ff", fontSize: "10px" }, group).position.z = dxf.originalZAverage * 0.99;
|
|
7131
|
+
});
|
|
7132
|
+
});
|
|
7133
|
+
}
|
|
7134
|
+
}
|
|
7118
7135
|
});
|
|
7119
7136
|
}
|
|
7120
7137
|
whiteModel(parent) {
|
|
@@ -7237,7 +7254,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
7237
7254
|
setup(__props) {
|
|
7238
7255
|
THREE.Object3D.DEFAULT_UP = new THREE.Vector3(0, 0, 1);
|
|
7239
7256
|
const props = __props;
|
|
7240
|
-
const elRef = ref(), originalLineVisible = ref(true), dxfVisible = ref(true), whiteModelVisible = ref(true), isLook = ref(false), dxfSystem = new DxfSystem().usePlugin(ModelDataPlugin).usePlugin(RenderPlugin), desPoint = dxfSystem.findComponentByType(DetailsPoint), domContainer = dxfSystem.findComponentByType(DomContainer);
|
|
7257
|
+
const elRef = ref(), originalLineVisible = ref(true), dxfVisible = ref(true), whiteModelVisible = ref(true), isLook = ref(false), dxfSystem = new DxfSystem().usePlugin(ModelDataPlugin).usePlugin(RenderPlugin), desPoint = dxfSystem.findComponentByType(DetailsPoint), domContainer = dxfSystem.findComponentByType(DomContainer), whiteModel = dxfSystem.findComponentByType(WhiteModel);
|
|
7241
7258
|
watch(() => props.lines, () => props.lines && setLines(props.lines));
|
|
7242
7259
|
watch(() => props.detailsPoint, () => props.detailsPoint && desPoint?.set(props.detailsPoint));
|
|
7243
7260
|
function setLines(lines) {
|
|
@@ -7281,59 +7298,70 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
7281
7298
|
type: "primary",
|
|
7282
7299
|
onClick: _cache[0] || (_cache[0] = ($event) => unref(dxfSystem).Dxf.download("test.dxf"))
|
|
7283
7300
|
}, {
|
|
7284
|
-
default: withCtx(() => _cache[
|
|
7301
|
+
default: withCtx(() => _cache[6] || (_cache[6] = [
|
|
7285
7302
|
createTextVNode(" 下载 DXF ", -1)
|
|
7286
7303
|
])),
|
|
7287
7304
|
_: 1,
|
|
7288
|
-
__: [
|
|
7305
|
+
__: [6]
|
|
7306
|
+
}),
|
|
7307
|
+
createVNode(unref(ElButton), {
|
|
7308
|
+
size: "small",
|
|
7309
|
+
type: "primary",
|
|
7310
|
+
onClick: _cache[1] || (_cache[1] = ($event) => unref(whiteModel).downloadGlb("test.glb"))
|
|
7311
|
+
}, {
|
|
7312
|
+
default: withCtx(() => _cache[7] || (_cache[7] = [
|
|
7313
|
+
createTextVNode(" 下载 白模 ", -1)
|
|
7314
|
+
])),
|
|
7315
|
+
_: 1,
|
|
7316
|
+
__: [7]
|
|
7289
7317
|
}),
|
|
7290
7318
|
createVNode(unref(ElButton), {
|
|
7291
7319
|
size: "small",
|
|
7292
7320
|
type: "success",
|
|
7293
7321
|
onClick: selectLocalFile
|
|
7294
7322
|
}, {
|
|
7295
|
-
default: withCtx(() => _cache[
|
|
7323
|
+
default: withCtx(() => _cache[8] || (_cache[8] = [
|
|
7296
7324
|
createTextVNode(" 选择线路文件 ", -1)
|
|
7297
7325
|
])),
|
|
7298
7326
|
_: 1,
|
|
7299
|
-
__: [
|
|
7327
|
+
__: [8]
|
|
7300
7328
|
}),
|
|
7301
7329
|
createVNode(unref(ElButton), {
|
|
7302
7330
|
size: "small",
|
|
7303
7331
|
type: "success",
|
|
7304
7332
|
onClick: selectDetailsPointFile
|
|
7305
7333
|
}, {
|
|
7306
|
-
default: withCtx(() => _cache[
|
|
7334
|
+
default: withCtx(() => _cache[9] || (_cache[9] = [
|
|
7307
7335
|
createTextVNode(" 选择详情点文件 ", -1)
|
|
7308
7336
|
])),
|
|
7309
7337
|
_: 1,
|
|
7310
|
-
__: [
|
|
7338
|
+
__: [9]
|
|
7311
7339
|
})
|
|
7312
7340
|
]),
|
|
7313
7341
|
isLook.value ? (openBlock(), createElementBlock("div", {
|
|
7314
7342
|
key: 0,
|
|
7315
|
-
onClick: _cache[
|
|
7343
|
+
onClick: _cache[2] || (_cache[2] = ($event) => unref(dxfSystem).Variable.set("isLook", false)),
|
|
7316
7344
|
class: "text-[#fff] h-fit text-[14px] rounded-[10px] bg-black p-[5px_20px] select-none cursor-pointer"
|
|
7317
7345
|
}, " 点击这或按 ESC 取消 ")) : createCommentVNode("", true),
|
|
7318
7346
|
createElementVNode("div", null, [
|
|
7319
7347
|
createElementVNode("div", _hoisted_2, [
|
|
7320
7348
|
createVNode(unref(ElCheckbox), {
|
|
7321
7349
|
modelValue: originalLineVisible.value,
|
|
7322
|
-
"onUpdate:modelValue": _cache[
|
|
7350
|
+
"onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => originalLineVisible.value = $event),
|
|
7323
7351
|
label: "线(Q)"
|
|
7324
7352
|
}, null, 8, ["modelValue"]),
|
|
7325
7353
|
createVNode(unref(ElCheckbox), {
|
|
7326
7354
|
modelValue: dxfVisible.value,
|
|
7327
|
-
"onUpdate:modelValue": _cache[
|
|
7355
|
+
"onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => dxfVisible.value = $event),
|
|
7328
7356
|
label: "dxf(W)"
|
|
7329
7357
|
}, null, 8, ["modelValue"]),
|
|
7330
7358
|
createVNode(unref(ElCheckbox), {
|
|
7331
7359
|
modelValue: whiteModelVisible.value,
|
|
7332
|
-
"onUpdate:modelValue": _cache[
|
|
7360
|
+
"onUpdate:modelValue": _cache[5] || (_cache[5] = ($event) => whiteModelVisible.value = $event),
|
|
7333
7361
|
label: "墙体(E)"
|
|
7334
7362
|
}, null, 8, ["modelValue"])
|
|
7335
7363
|
]),
|
|
7336
|
-
_cache[
|
|
7364
|
+
_cache[10] || (_cache[10] = createStaticVNode('<div class="mt-[5px] text-[#c9c9c9] text-[10px]"><p class="text-right">详情点射线辅助线快捷键:R</p><p class="text-right">墙壁合并追加线快捷键:A</p><p class="text-right">线段序号快捷键:T</p><p class="text-right">线段端点标示快捷键:P</p><p class="text-right">线段长度(单位米)快捷键:L</p></div>', 1))
|
|
7337
7365
|
])
|
|
7338
7366
|
])
|
|
7339
7367
|
], 512);
|
|
@@ -51,6 +51,7 @@ export declare class Dxf extends Component<{
|
|
|
51
51
|
};
|
|
52
52
|
}> {
|
|
53
53
|
static name: string;
|
|
54
|
+
shortLine: number;
|
|
54
55
|
width: number;
|
|
55
56
|
scale: number;
|
|
56
57
|
originalData: OriginalDataItem[];
|
|
@@ -112,6 +113,24 @@ export declare class Dxf extends Component<{
|
|
|
112
113
|
* @description 检查连续的短线段数量,去除合并后产生的毛刺
|
|
113
114
|
*/
|
|
114
115
|
private squareRemoveBurr;
|
|
116
|
+
epsilon: number;
|
|
117
|
+
/**
|
|
118
|
+
* 移除共线点
|
|
119
|
+
* @param path
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
removeCollinearPoints(path: Point[]): Point[];
|
|
123
|
+
/**
|
|
124
|
+
* 线段矫直, 线段中心突刺
|
|
125
|
+
* @description 突变长度小于墙体宽度,该线段可能为突起线段,
|
|
126
|
+
* @description 判断后续第2线段与上一条线段是否方向相同,相同就为突刺
|
|
127
|
+
*/
|
|
128
|
+
lineSegmentStraightening(path: Point[]): Point[];
|
|
129
|
+
/**
|
|
130
|
+
* 移除短线段
|
|
131
|
+
* @param path
|
|
132
|
+
*/
|
|
133
|
+
removeShortLine(path: Point[], shortLine?: number): Point[];
|
|
115
134
|
/** 线偏移
|
|
116
135
|
* @description 使用 ClipperLib 对每个点组进行线偏移处理,生成具有指定宽度的墙体路径
|
|
117
136
|
*/
|
|
@@ -27,11 +27,6 @@ export declare class LineAnalysis extends Component {
|
|
|
27
27
|
* @param parent
|
|
28
28
|
*/
|
|
29
29
|
onAddFromParent(parent: ComponentManager): void;
|
|
30
|
-
/**
|
|
31
|
-
* 去除路径上重复的点
|
|
32
|
-
* @description 判断方向向量,一个连续的方向上,只应该出现两个点
|
|
33
|
-
*/
|
|
34
|
-
duplicatePointFiltering(): void;
|
|
35
30
|
/**
|
|
36
31
|
*
|
|
37
32
|
* @param p1
|
|
@@ -12,10 +12,15 @@ export declare class WhiteModel extends Component<{
|
|
|
12
12
|
Dxf: Dxf | null;
|
|
13
13
|
Variable: Variable | null;
|
|
14
14
|
whiteModelGroup: THREE.Group<THREE.Object3DEventMap>;
|
|
15
|
+
whiteModelLineGroup: THREE.Group<THREE.Object3DEventMap>;
|
|
15
16
|
originalWhiteMode: THREE.Group<THREE.Object3DEventMap>;
|
|
17
|
+
material: THREE.MeshBasicMaterial;
|
|
16
18
|
onAddFromParent(parent: ComponentManager): void;
|
|
17
19
|
updateModel(): void;
|
|
18
20
|
toOBJ(): Promise<string>;
|
|
19
|
-
|
|
21
|
+
toGlb(): Promise<ArrayBuffer | undefined>;
|
|
22
|
+
toOBJBlob(): Promise<Blob | undefined>;
|
|
23
|
+
toGlbBlob(): Promise<Blob | undefined>;
|
|
20
24
|
download(filename: string): Promise<void>;
|
|
25
|
+
downloadGlb(filename: string): Promise<void>;
|
|
21
26
|
}
|
|
@@ -64,14 +64,14 @@ export declare class Renderer extends Component {
|
|
|
64
64
|
* 创建点
|
|
65
65
|
* @param pos
|
|
66
66
|
*/
|
|
67
|
-
createPointMesh(pos?: Point | THREE.Vector3, size?: number, parameters?: THREE.MeshBasicMaterialParameters, parent?: THREE.Object3D):
|
|
67
|
+
createPointMesh(pos?: Point | THREE.Vector3, size?: number, parameters?: THREE.MeshBasicMaterialParameters, parent?: THREE.Object3D): THREE.Mesh<THREE.SphereGeometry, THREE.MeshBasicMaterial, THREE.Object3DEventMap>;
|
|
68
68
|
/**
|
|
69
69
|
* 创建文本
|
|
70
70
|
* @param text
|
|
71
71
|
* @param pos
|
|
72
72
|
* @param style
|
|
73
73
|
*/
|
|
74
|
-
createText(text: any, pos?: Point | THREE.Vector3, style?: any, parent?: THREE.Object3D):
|
|
74
|
+
createText(text: any, pos?: Point | THREE.Vector3, style?: any, parent?: THREE.Object3D): CSS2DObject;
|
|
75
75
|
/**
|
|
76
76
|
* 创建几何缓冲区
|
|
77
77
|
* @param map
|
|
@@ -19,11 +19,53 @@ export declare class LineSegment<T = Record<string, any>> {
|
|
|
19
19
|
* @returns
|
|
20
20
|
*/
|
|
21
21
|
direction(): Point;
|
|
22
|
+
/**
|
|
23
|
+
* 线段长度
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
length(): number;
|
|
22
27
|
/**
|
|
23
28
|
* 计算一条线段在另一条直线上的投影,并裁剪超出目标线段的部分
|
|
24
29
|
* @param line 要投影的线段
|
|
25
30
|
* @returns 投影并裁剪后的线段
|
|
26
31
|
*/
|
|
27
32
|
projectLineSegment(line: LineSegment): LineSegment;
|
|
33
|
+
/**
|
|
34
|
+
* 判断线段是与线段相交
|
|
35
|
+
* @param line
|
|
36
|
+
*/
|
|
37
|
+
intersectLineSegment(line: LineSegment): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* 获取交点
|
|
40
|
+
* @param line
|
|
41
|
+
* @returns
|
|
42
|
+
*/
|
|
43
|
+
getIntersection(line: LineSegment): Point | null;
|
|
44
|
+
/**
|
|
45
|
+
* 获取两条线段夹角
|
|
46
|
+
* @param line
|
|
47
|
+
*/
|
|
48
|
+
includedAngle(line: LineSegment): number;
|
|
49
|
+
/**
|
|
50
|
+
* 两条线段方向是否一致
|
|
51
|
+
* @param line
|
|
52
|
+
*/
|
|
53
|
+
directionEqual(line: LineSegment, errAngle?: number): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* 两条线段方向相反否一致
|
|
56
|
+
* @param line
|
|
57
|
+
*/
|
|
58
|
+
directionOpposite(line: LineSegment, errAngle?: number): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* 判断两条线是否平行
|
|
61
|
+
* @param line
|
|
62
|
+
*/
|
|
63
|
+
isParallel(line: LineSegment, errAngle?: number): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 判断两条直线是否重合
|
|
66
|
+
* @param line
|
|
67
|
+
* @returns
|
|
68
|
+
*/
|
|
69
|
+
areLinesCoincident(line: LineSegment): boolean;
|
|
28
70
|
clone(): LineSegment<Record<string, any>>;
|
|
29
71
|
}
|
|
@@ -91,6 +91,7 @@ export declare class Point {
|
|
|
91
91
|
dot(point: Point): number;
|
|
92
92
|
/** 计算两个向量夹角
|
|
93
93
|
* @description 公式:a · b = |a| × |b| × cosθ
|
|
94
|
+
* @description 结果为0(0度),两个向量方向一致,结果为3.1415926(180度, PI),两个向量方向相反
|
|
94
95
|
* @param point
|
|
95
96
|
* @returns
|
|
96
97
|
*/
|
|
@@ -108,6 +109,14 @@ export declare class Point {
|
|
|
108
109
|
* @returns
|
|
109
110
|
*/
|
|
110
111
|
clone(): Point;
|
|
112
|
+
/**
|
|
113
|
+
* 克隆
|
|
114
|
+
* @returns
|
|
115
|
+
*/
|
|
116
|
+
copy(p: {
|
|
117
|
+
x: number;
|
|
118
|
+
y: number;
|
|
119
|
+
}): void;
|
|
111
120
|
static from(arr: any): Point;
|
|
112
121
|
static zero(): Point;
|
|
113
122
|
}
|