build-dxf 0.1.105 → 0.1.107
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 +304 -88
- package/src/index3.js +2 -2
- package/src/utils/algorithms/AlignToParallelSegments.d.ts +4 -1
- package/src/utils/algorithms/LineSegment.d.ts +1 -1
- package/src/utils/algorithms/LineSegmentUtils.d.ts +8 -0
- package/src/utils/algorithms/Point.d.ts +65 -17
- package/src/utils/algorithms/PointUtils.d.ts +5 -1
- package/src/utils/algorithms/Polygon.d.ts +9 -1
- package/src/utils/algorithms/precision.d.ts +3 -0
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -316,12 +316,12 @@ class Rectangle {
|
|
|
316
316
|
for (let i = 0; i < 4; i++) {
|
|
317
317
|
const p1 = this.points[i];
|
|
318
318
|
const p2 = this.points[(i + 1) % 4];
|
|
319
|
-
axes.push(p1.
|
|
319
|
+
axes.push(p1.leftNormal(p2));
|
|
320
320
|
}
|
|
321
321
|
for (let i = 0; i < 4; i++) {
|
|
322
322
|
const p1 = rectangle.points[i];
|
|
323
323
|
const p2 = rectangle.points[(i + 1) % 4];
|
|
324
|
-
axes.push(p1.
|
|
324
|
+
axes.push(p1.leftNormal(p2));
|
|
325
325
|
}
|
|
326
326
|
function projectRectangle(rect, axis) {
|
|
327
327
|
const projections = rect.points.map((point2) => point2.dot(axis));
|
|
@@ -377,7 +377,7 @@ class Rectangle {
|
|
|
377
377
|
* @returns
|
|
378
378
|
*/
|
|
379
379
|
static fromByLineSegment(line, width = 0.1, horizontal = false, hScale = 0.5) {
|
|
380
|
-
const p1 = line.points[0], p2 = line.points[1], normal = p2.
|
|
380
|
+
const p1 = line.points[0], p2 = line.points[1], normal = p2.leftNormal(p1), pDirect = horizontal ? p2.directionFrom(p1).multiplyScalar(width * hScale) : Point.zero(), nDirect = horizontal ? p1.directionFrom(p2).multiplyScalar(width * hScale) : Point.zero();
|
|
381
381
|
const offsetX = normal.x * width * 0.5;
|
|
382
382
|
const offsetY = normal.y * width * 0.5;
|
|
383
383
|
return new Rectangle([
|
|
@@ -451,9 +451,17 @@ class LineSegment {
|
|
|
451
451
|
}
|
|
452
452
|
setLength(len) {
|
|
453
453
|
const direct = this.direction();
|
|
454
|
-
const
|
|
455
|
-
const
|
|
456
|
-
|
|
454
|
+
const half = len * 0.5;
|
|
455
|
+
const dx = direct.x * half;
|
|
456
|
+
const dy = direct.y * half;
|
|
457
|
+
this.start.set(
|
|
458
|
+
this.#center.x - dx,
|
|
459
|
+
this.#center.y - dy
|
|
460
|
+
);
|
|
461
|
+
this.end.set(
|
|
462
|
+
this.#center.x + dx,
|
|
463
|
+
this.#center.y + dy
|
|
464
|
+
);
|
|
457
465
|
return this;
|
|
458
466
|
}
|
|
459
467
|
/** 获取另一个点
|
|
@@ -603,10 +611,10 @@ class LineSegment {
|
|
|
603
611
|
return this.#direction.clone();
|
|
604
612
|
}
|
|
605
613
|
/**
|
|
606
|
-
*
|
|
614
|
+
* 获取发向量-左法线
|
|
607
615
|
*/
|
|
608
616
|
normal() {
|
|
609
|
-
return this.points[1].
|
|
617
|
+
return this.points[1].leftNormal(this.points[0]);
|
|
610
618
|
}
|
|
611
619
|
/**
|
|
612
620
|
* @param line
|
|
@@ -623,9 +631,9 @@ class LineSegment {
|
|
|
623
631
|
*/
|
|
624
632
|
toRectangle(width = 0.1, cap = "square") {
|
|
625
633
|
const p1 = this.start, p2 = this.end;
|
|
626
|
-
const normal = p2.
|
|
627
|
-
const pDirect = cap === "butt" ? Point.zero() : p2.directionFrom(p1).
|
|
628
|
-
const nDirect = cap === "butt" ? Point.zero() : p1.directionFrom(p2).
|
|
634
|
+
const normal = p2.leftNormal(p1);
|
|
635
|
+
const pDirect = cap === "butt" ? Point.zero() : p2.directionFrom(p1).multiplyScalar(width * 0.5);
|
|
636
|
+
const nDirect = cap === "butt" ? Point.zero() : p1.directionFrom(p2).multiplyScalar(width * 0.5);
|
|
629
637
|
const offsetX = normal.x * width * 0.5;
|
|
630
638
|
const offsetY = normal.y * width * 0.5;
|
|
631
639
|
const point2 = [
|
|
@@ -995,7 +1003,17 @@ class LineSegment {
|
|
|
995
1003
|
return point2.currentData[LINE_SYMBOL] ?? null;
|
|
996
1004
|
}
|
|
997
1005
|
}
|
|
998
|
-
const
|
|
1006
|
+
const POW10 = [
|
|
1007
|
+
1,
|
|
1008
|
+
10,
|
|
1009
|
+
100,
|
|
1010
|
+
1e3,
|
|
1011
|
+
1e4,
|
|
1012
|
+
1e5,
|
|
1013
|
+
1e6,
|
|
1014
|
+
1e7,
|
|
1015
|
+
1e8
|
|
1016
|
+
];
|
|
999
1017
|
class Point {
|
|
1000
1018
|
x;
|
|
1001
1019
|
y;
|
|
@@ -1051,22 +1069,34 @@ class Point {
|
|
|
1051
1069
|
this.y = arr[1];
|
|
1052
1070
|
return this;
|
|
1053
1071
|
}
|
|
1054
|
-
/**
|
|
1055
|
-
* multiplyScalar
|
|
1072
|
+
/** 乘法
|
|
1056
1073
|
* @param scalar
|
|
1074
|
+
* @returns
|
|
1057
1075
|
*/
|
|
1058
|
-
|
|
1059
|
-
this.x *=
|
|
1060
|
-
this.y *=
|
|
1076
|
+
multiply(point2) {
|
|
1077
|
+
this.x *= point2.x;
|
|
1078
|
+
this.y *= point2.y;
|
|
1061
1079
|
return this;
|
|
1062
1080
|
}
|
|
1081
|
+
/** 乘以一个标量
|
|
1082
|
+
* @param scalar
|
|
1083
|
+
* @returns
|
|
1084
|
+
*/
|
|
1063
1085
|
multiplyScalar(scalar) {
|
|
1064
1086
|
this.x *= scalar;
|
|
1065
1087
|
this.y *= scalar;
|
|
1066
1088
|
return this;
|
|
1067
1089
|
}
|
|
1068
|
-
/**
|
|
1069
|
-
*
|
|
1090
|
+
/** 除法
|
|
1091
|
+
* @param scalar
|
|
1092
|
+
* @returns
|
|
1093
|
+
*/
|
|
1094
|
+
division(point2) {
|
|
1095
|
+
this.x /= point2.x;
|
|
1096
|
+
this.y /= point2.y;
|
|
1097
|
+
return this;
|
|
1098
|
+
}
|
|
1099
|
+
/** 除一个标量
|
|
1070
1100
|
* @param scalar
|
|
1071
1101
|
* @returns
|
|
1072
1102
|
*/
|
|
@@ -1081,20 +1111,20 @@ class Point {
|
|
|
1081
1111
|
* @param point
|
|
1082
1112
|
* @returns
|
|
1083
1113
|
*/
|
|
1084
|
-
|
|
1114
|
+
subtract(point2) {
|
|
1085
1115
|
this.x -= point2.x;
|
|
1086
1116
|
this.y -= point2.y;
|
|
1087
1117
|
return this;
|
|
1088
1118
|
}
|
|
1089
1119
|
/**
|
|
1090
|
-
*
|
|
1120
|
+
* 减一个标量
|
|
1091
1121
|
* @description 将当前点的坐标减去指定点的坐标
|
|
1092
1122
|
* @param point
|
|
1093
1123
|
* @returns
|
|
1094
1124
|
*/
|
|
1095
|
-
|
|
1096
|
-
this.x -=
|
|
1097
|
-
this.y -=
|
|
1125
|
+
subtractScalar(value) {
|
|
1126
|
+
this.x -= value;
|
|
1127
|
+
this.y -= value;
|
|
1098
1128
|
return this;
|
|
1099
1129
|
}
|
|
1100
1130
|
/**
|
|
@@ -1108,8 +1138,7 @@ class Point {
|
|
|
1108
1138
|
this.y += point2.y;
|
|
1109
1139
|
return this;
|
|
1110
1140
|
}
|
|
1111
|
-
/**
|
|
1112
|
-
* 加法
|
|
1141
|
+
/** 加一个标量
|
|
1113
1142
|
* @description 将当前点的坐标加上指定点的坐标
|
|
1114
1143
|
* @param point
|
|
1115
1144
|
* @returns
|
|
@@ -1118,6 +1147,35 @@ class Point {
|
|
|
1118
1147
|
this.x += value;
|
|
1119
1148
|
this.y += value;
|
|
1120
1149
|
}
|
|
1150
|
+
/**
|
|
1151
|
+
* 加法(不可变)
|
|
1152
|
+
* @description 返回当前点与指定点相加后的新点,不修改当前点
|
|
1153
|
+
* @param point
|
|
1154
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
1155
|
+
* @returns 相加后的点
|
|
1156
|
+
*/
|
|
1157
|
+
added(point2, out = new Point()) {
|
|
1158
|
+
return out.set(
|
|
1159
|
+
this.x + point2.x,
|
|
1160
|
+
this.y + point2.y
|
|
1161
|
+
);
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* 减法(不可变)
|
|
1165
|
+
* @description 返回当前点减去指定点后的新点,不修改当前点
|
|
1166
|
+
* @param point
|
|
1167
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
1168
|
+
* @returns 相减后的点
|
|
1169
|
+
*/
|
|
1170
|
+
subtracted(point2, out = new Point()) {
|
|
1171
|
+
return out.set(
|
|
1172
|
+
this.x - point2.x,
|
|
1173
|
+
this.y - point2.y
|
|
1174
|
+
);
|
|
1175
|
+
}
|
|
1176
|
+
/** 转为整型
|
|
1177
|
+
* @returns
|
|
1178
|
+
*/
|
|
1121
1179
|
parseInt() {
|
|
1122
1180
|
this.x = ~~this.x;
|
|
1123
1181
|
this.y = ~~this.y;
|
|
@@ -1139,21 +1197,40 @@ class Point {
|
|
|
1139
1197
|
this.y = rotatedY + point2.y;
|
|
1140
1198
|
return this;
|
|
1141
1199
|
}
|
|
1200
|
+
/**
|
|
1201
|
+
* 旋转(不可变)
|
|
1202
|
+
* @description 返回当前点绕指定中心旋转后的新点,不修改当前点
|
|
1203
|
+
* @param center 旋转中心
|
|
1204
|
+
* @param angle 旋转角度(弧度)
|
|
1205
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
1206
|
+
* @returns 旋转后的点
|
|
1207
|
+
*/
|
|
1208
|
+
rotated(center, angle, out = new Point()) {
|
|
1209
|
+
const dx = this.x - center.x;
|
|
1210
|
+
const dy = this.y - center.y;
|
|
1211
|
+
const cos = Math.cos(angle);
|
|
1212
|
+
const sin = Math.sin(angle);
|
|
1213
|
+
return out.set(
|
|
1214
|
+
dx * cos - dy * sin + center.x,
|
|
1215
|
+
dx * sin + dy * cos + center.y
|
|
1216
|
+
);
|
|
1217
|
+
}
|
|
1142
1218
|
/**
|
|
1143
1219
|
* 保留小数位数
|
|
1144
1220
|
* @param count
|
|
1145
1221
|
*/
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
this.
|
|
1222
|
+
precision(count) {
|
|
1223
|
+
const factor = POW10[count] ?? 10 ** count;
|
|
1224
|
+
this.x = Math.round(this.x * factor) / factor;
|
|
1225
|
+
this.y = Math.round(this.y * factor) / factor;
|
|
1149
1226
|
return this;
|
|
1150
1227
|
}
|
|
1151
|
-
/**
|
|
1228
|
+
/** 保留四位小数
|
|
1152
1229
|
* @returns
|
|
1153
1230
|
*/
|
|
1154
|
-
|
|
1155
|
-
this.x = Math.round(this.x
|
|
1156
|
-
this.y = Math.round(this.y
|
|
1231
|
+
precision4() {
|
|
1232
|
+
this.x = Math.round(this.x * 1e4) / 1e4;
|
|
1233
|
+
this.y = Math.round(this.y * 1e4) / 1e4;
|
|
1157
1234
|
return this;
|
|
1158
1235
|
}
|
|
1159
1236
|
/**
|
|
@@ -1169,12 +1246,28 @@ class Point {
|
|
|
1169
1246
|
return this;
|
|
1170
1247
|
}
|
|
1171
1248
|
/**
|
|
1172
|
-
|
|
1249
|
+
* 归一化(不可变)
|
|
1250
|
+
* @description 返回当前向量归一化后的新点,不修改当前点
|
|
1251
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
1252
|
+
* @returns 单位向量
|
|
1253
|
+
*/
|
|
1254
|
+
normalized(out = new Point()) {
|
|
1255
|
+
const length = Math.hypot(this.x, this.y);
|
|
1256
|
+
if (length === 0) {
|
|
1257
|
+
return out.set(0, 0);
|
|
1258
|
+
}
|
|
1259
|
+
return out.set(
|
|
1260
|
+
this.x / length,
|
|
1261
|
+
this.y / length
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* 获取单位左法向量
|
|
1173
1266
|
* @description 计算当前点到指定点的方向向量,并返回逆时针旋转90度后的单位法向量
|
|
1174
1267
|
* @param point
|
|
1175
1268
|
* @returns
|
|
1176
1269
|
*/
|
|
1177
|
-
|
|
1270
|
+
leftNormal(point2) {
|
|
1178
1271
|
const dx = this.x - point2.x;
|
|
1179
1272
|
const dy = this.y - point2.y;
|
|
1180
1273
|
const length = Math.sqrt(dx * dx + dy * dy);
|
|
@@ -1329,12 +1422,15 @@ class Point {
|
|
|
1329
1422
|
this.y = p2.y ?? 0;
|
|
1330
1423
|
return this;
|
|
1331
1424
|
}
|
|
1332
|
-
/**
|
|
1333
|
-
*
|
|
1425
|
+
/** 转为数组
|
|
1334
1426
|
*/
|
|
1335
1427
|
toArray() {
|
|
1336
1428
|
return [this.x, this.y];
|
|
1337
1429
|
}
|
|
1430
|
+
/** 转为json
|
|
1431
|
+
* @param z
|
|
1432
|
+
* @returns
|
|
1433
|
+
*/
|
|
1338
1434
|
toJson(z = 0) {
|
|
1339
1435
|
return {
|
|
1340
1436
|
x: this.x,
|
|
@@ -2952,10 +3048,18 @@ class PointUtils {
|
|
|
2952
3048
|
/**保留小数位数
|
|
2953
3049
|
* @param points
|
|
2954
3050
|
*/
|
|
2955
|
-
static
|
|
3051
|
+
static precision(points, count) {
|
|
3052
|
+
for (const p2 of points) {
|
|
3053
|
+
p2.precision(count);
|
|
3054
|
+
}
|
|
3055
|
+
return points;
|
|
3056
|
+
}
|
|
3057
|
+
/**保留四位小数位数
|
|
3058
|
+
* @param points
|
|
3059
|
+
*/
|
|
3060
|
+
static precision4(points) {
|
|
2956
3061
|
for (const p2 of points) {
|
|
2957
|
-
p2.
|
|
2958
|
-
p2.y = Math.round(p2.y * scale2) / scale2;
|
|
3062
|
+
p2.precision4();
|
|
2959
3063
|
}
|
|
2960
3064
|
return points;
|
|
2961
3065
|
}
|
|
@@ -3034,9 +3138,30 @@ class UnionFindSet {
|
|
|
3034
3138
|
}
|
|
3035
3139
|
}
|
|
3036
3140
|
class LineSegmentUtils {
|
|
3141
|
+
// 克隆
|
|
3037
3142
|
clone(lines) {
|
|
3038
3143
|
return lines.map((line) => line.clone());
|
|
3039
3144
|
}
|
|
3145
|
+
/**保留小数位数
|
|
3146
|
+
* @param points
|
|
3147
|
+
*/
|
|
3148
|
+
static precision(lines, count) {
|
|
3149
|
+
for (const l of lines) {
|
|
3150
|
+
l.start.precision(count);
|
|
3151
|
+
l.end.precision(count);
|
|
3152
|
+
}
|
|
3153
|
+
return lines;
|
|
3154
|
+
}
|
|
3155
|
+
/**保留四位小数位数
|
|
3156
|
+
* @param points
|
|
3157
|
+
*/
|
|
3158
|
+
static precision4(lines) {
|
|
3159
|
+
for (const l of lines) {
|
|
3160
|
+
l.start.precision4();
|
|
3161
|
+
l.end.precision4();
|
|
3162
|
+
}
|
|
3163
|
+
return lines;
|
|
3164
|
+
}
|
|
3040
3165
|
/** 获取最长线段索引
|
|
3041
3166
|
* @param lines
|
|
3042
3167
|
*/
|
|
@@ -5362,13 +5487,49 @@ class Polygon extends Array {
|
|
|
5362
5487
|
this.length = 0;
|
|
5363
5488
|
this.push(...points);
|
|
5364
5489
|
}
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5371
|
-
|
|
5490
|
+
/**
|
|
5491
|
+
* 获取多边形几何中心(面积质心)
|
|
5492
|
+
* @description 使用多边形面积质心公式计算
|
|
5493
|
+
* @description 适用于闭合简单多边形(顺时针或逆时针均可)
|
|
5494
|
+
* @description 如果面积为 0,则退化为顶点平均中心
|
|
5495
|
+
* @param out 输出对象,用于减少 GC
|
|
5496
|
+
* @returns
|
|
5497
|
+
*/
|
|
5498
|
+
getCenter(out = new Point()) {
|
|
5499
|
+
const len = this.length;
|
|
5500
|
+
if (len === 0) {
|
|
5501
|
+
return out.set(0, 0);
|
|
5502
|
+
}
|
|
5503
|
+
let area2 = 0;
|
|
5504
|
+
let centerX = 0;
|
|
5505
|
+
let centerY = 0;
|
|
5506
|
+
for (let i = 0; i < len; i++) {
|
|
5507
|
+
const p1 = this[i];
|
|
5508
|
+
const p2 = this[(i + 1) % len];
|
|
5509
|
+
const cross = p1.x * p2.y - p2.x * p1.y;
|
|
5510
|
+
area2 += cross;
|
|
5511
|
+
centerX += (p1.x + p2.x) * cross;
|
|
5512
|
+
centerY += (p1.y + p2.y) * cross;
|
|
5513
|
+
}
|
|
5514
|
+
area2 *= 0.5;
|
|
5515
|
+
if (Math.abs(area2) < 1e-9) {
|
|
5516
|
+
let sumX = 0;
|
|
5517
|
+
let sumY = 0;
|
|
5518
|
+
for (let i = 0; i < len; i++) {
|
|
5519
|
+
sumX += this[i].x;
|
|
5520
|
+
sumY += this[i].y;
|
|
5521
|
+
}
|
|
5522
|
+
const inv = 1 / len;
|
|
5523
|
+
return out.set(
|
|
5524
|
+
sumX * inv,
|
|
5525
|
+
sumY * inv
|
|
5526
|
+
);
|
|
5527
|
+
}
|
|
5528
|
+
const factor = 1 / (6 * area2);
|
|
5529
|
+
return out.set(
|
|
5530
|
+
centerX * factor,
|
|
5531
|
+
centerY * factor
|
|
5532
|
+
);
|
|
5372
5533
|
}
|
|
5373
5534
|
/** 计算二维包围盒
|
|
5374
5535
|
* @returns
|
|
@@ -6428,6 +6589,7 @@ function segmentationPath(lines, clipLine) {
|
|
|
6428
6589
|
function clippingDoubleWall(lines) {
|
|
6429
6590
|
lines = lines.map((line) => line.clone());
|
|
6430
6591
|
lines = mergeChains(lines);
|
|
6592
|
+
if (lines.length === 4) return [lines];
|
|
6431
6593
|
const queue = [lines], groups = [], maxCount2 = 2e4;
|
|
6432
6594
|
let pendingLines, count = 0;
|
|
6433
6595
|
while ((pendingLines = queue.pop()) !== void 0) {
|
|
@@ -6457,6 +6619,7 @@ function clippingDoubleWall(lines) {
|
|
|
6457
6619
|
}
|
|
6458
6620
|
const miniCircles = new MiniCircles();
|
|
6459
6621
|
function clippingInsertObjectDoubleWall(lines) {
|
|
6622
|
+
if (lines.length === 4) return [lines];
|
|
6460
6623
|
const hasInsertObject = lines.some((line) => WallInsertObject.isInsertObject(line));
|
|
6461
6624
|
if (!hasInsertObject) return clippingDoubleWall(lines);
|
|
6462
6625
|
const quadtree = createQuadtree(lines), poly = Polygon.fromByLines2(lines), far = 10;
|
|
@@ -9396,6 +9559,12 @@ class BuildGroup {
|
|
|
9396
9559
|
return buildDoubleWallGroup;
|
|
9397
9560
|
}
|
|
9398
9561
|
}
|
|
9562
|
+
function precision4(value) {
|
|
9563
|
+
return Math.round(value * 1e4) * 1e-4;
|
|
9564
|
+
}
|
|
9565
|
+
function precision4Nullable(value) {
|
|
9566
|
+
return value == null ? void 0 : precision4(value);
|
|
9567
|
+
}
|
|
9399
9568
|
const holeTypeMap = {
|
|
9400
9569
|
door: "DOOR",
|
|
9401
9570
|
RAILING: "RAILING",
|
|
@@ -9433,11 +9602,21 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9433
9602
|
const { door, window: windowLines, passageEntrance, untreatedDoubleWallGroup } = WallInsertObjectDrawData.handleHoleDrawData(groups, []);
|
|
9434
9603
|
const walls = untreatedDoubleWallGroup.flatMap((lines2) => {
|
|
9435
9604
|
if (lines2.length < 4) return lines2;
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
const
|
|
9605
|
+
let newLine = null;
|
|
9606
|
+
let wallWidth = 0;
|
|
9607
|
+
const poly = Polygon.fromByLinePath(lines2).getMinimumBoundingRectangle();
|
|
9608
|
+
if (poly) {
|
|
9609
|
+
const len1 = poly[0].distance(poly[1]), len2 = poly[1].distance(poly[2]), direct = len1 > len2 ? poly[0].directionFrom(poly[1]) : poly[1].directionFrom(poly[2]), center = poly.getCenter(), len = Math.max(len1, len2);
|
|
9610
|
+
newLine = center.expandAsLine(direct, len).translate(-len * 0.5, direct);
|
|
9611
|
+
wallWidth = Math.min(len1, len2);
|
|
9612
|
+
} else {
|
|
9613
|
+
lines2 = [...lines2].sort((a2, b4) => a2.length() - b4.length());
|
|
9614
|
+
const line1 = lines2[0], line2 = lines2[1];
|
|
9615
|
+
newLine = new LineSegment(line1.center.clone(), line2.center.clone());
|
|
9616
|
+
wallWidth = line1.length();
|
|
9617
|
+
}
|
|
9439
9618
|
mergeLineUserData(newLine, lines2);
|
|
9440
|
-
newLine.userData.wallWidth =
|
|
9619
|
+
newLine.userData.wallWidth = wallWidth;
|
|
9441
9620
|
return [newLine];
|
|
9442
9621
|
});
|
|
9443
9622
|
this.manager.add({ type: "wallHole", lines: windowLines });
|
|
@@ -9534,12 +9713,12 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9534
9713
|
const hole = {
|
|
9535
9714
|
id: this.index++,
|
|
9536
9715
|
type,
|
|
9537
|
-
start: line.start.toJson2D(),
|
|
9538
|
-
end: line.end.toJson2D(),
|
|
9539
|
-
depth: line.userData.depth,
|
|
9540
|
-
height: line.userData?.height ?? DEFAULT_DOOR_HEIGHT,
|
|
9541
|
-
sillHeight: line.userData?.groundClearance ?? DOOR_GROUND_CLEARANCE_HEIGHT,
|
|
9542
|
-
groundClearance: line.userData?.groundClearance ?? DOOR_GROUND_CLEARANCE_HEIGHT
|
|
9716
|
+
start: line.start.precision4().toJson2D(),
|
|
9717
|
+
end: line.end.precision4().toJson2D(),
|
|
9718
|
+
depth: precision4Nullable(line.userData.depth),
|
|
9719
|
+
height: precision4Nullable(line.userData?.height ?? DEFAULT_DOOR_HEIGHT),
|
|
9720
|
+
sillHeight: precision4Nullable(line.userData?.groundClearance ?? DOOR_GROUND_CLEARANCE_HEIGHT),
|
|
9721
|
+
groundClearance: precision4Nullable(line.userData?.groundClearance ?? DOOR_GROUND_CLEARANCE_HEIGHT)
|
|
9543
9722
|
// ?非三维家需要数据
|
|
9544
9723
|
};
|
|
9545
9724
|
if (type === "DOOR") Object.assign(hole, { openSide: "RIGHT" });
|
|
@@ -9575,16 +9754,16 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9575
9754
|
};
|
|
9576
9755
|
this.manager.forEach((group) => this.run(group.type, { lines: group.lines, json: option }, cache));
|
|
9577
9756
|
cache.wallLines.forEach((line) => {
|
|
9757
|
+
line.setLength(line.len + 4e-3);
|
|
9578
9758
|
option.walls.push({
|
|
9579
9759
|
ID: this.index++,
|
|
9580
|
-
start: line.start.toJson2D(),
|
|
9581
|
-
end: line.end.toJson2D(),
|
|
9582
|
-
thickness: Math.max(line.userData.wallWidth ? line.userData.wallWidth : 0.12, 0.12),
|
|
9760
|
+
start: line.start.precision4().toJson2D(),
|
|
9761
|
+
end: line.end.precision4().toJson2D(),
|
|
9762
|
+
thickness: precision4(Math.max(line.userData.wallWidth ? line.userData.wallWidth : 0.12, 0.12)),
|
|
9583
9763
|
type: "LINE",
|
|
9584
9764
|
isDoor: false,
|
|
9585
9765
|
loadBearingWall: false,
|
|
9586
|
-
|
|
9587
|
-
height: line.currentData[WALL_HEIGHT_KEY] ?? this.maxHeight
|
|
9766
|
+
height: precision4(line.currentData[WALL_HEIGHT_KEY] ?? this.maxHeight)
|
|
9588
9767
|
});
|
|
9589
9768
|
});
|
|
9590
9769
|
return option;
|
|
@@ -9616,6 +9795,7 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9616
9795
|
const rooms = json.rooms, roomPloys = rooms.map((room) => new Polygon(room.polygon.map((p2) => Point.from(p2))));
|
|
9617
9796
|
if (roomPloys.length === 0) return json;
|
|
9618
9797
|
publicInfo.itemInfo.forEach((item, i) => {
|
|
9798
|
+
if (item.category !== "switch" && item.category !== "socket") return;
|
|
9619
9799
|
const itemPoly = new Polygon(item.contour.map((p2) => Point.from(p2).rotate(json.center, json.angle))), center = itemPoly.getCenter(), index2 = roomPloys.findIndex((poly) => poly.pointWithin(center));
|
|
9620
9800
|
if (index2 < 0) return;
|
|
9621
9801
|
json.placeHolders.push({
|
|
@@ -9661,7 +9841,7 @@ class ThreeVJiaPipeline extends Pipeline {
|
|
|
9661
9841
|
});
|
|
9662
9842
|
});
|
|
9663
9843
|
if (heights.length === 0) heights.push(DEFAULT_WALL_HEIGHT);
|
|
9664
|
-
const maxHeight = Math.max(...heights);
|
|
9844
|
+
const maxHeight = precision4(Math.max(...heights));
|
|
9665
9845
|
if (updateGroup) lineSegments = BuildGroup.doubleWall(lineSegments);
|
|
9666
9846
|
const threeVJiaJson = new ThreeVJiaPipeline(lineSegments, maxHeight);
|
|
9667
9847
|
const json = threeVJiaJson.transform();
|
|
@@ -9968,8 +10148,8 @@ class CAD {
|
|
|
9968
10148
|
resetOrigin() {
|
|
9969
10149
|
const lines = this.groups.flatMap((group) => group.lines), box = Box2.fromByLineSegment(...lines), center = box.center;
|
|
9970
10150
|
this.groups.forEach((group) => group.lines.forEach((line) => {
|
|
9971
|
-
line.start.
|
|
9972
|
-
line.end.
|
|
10151
|
+
line.start.subtract(center);
|
|
10152
|
+
line.end.subtract(center);
|
|
9973
10153
|
}));
|
|
9974
10154
|
this.needUpdate = true;
|
|
9975
10155
|
}
|
|
@@ -9981,8 +10161,8 @@ class CAD {
|
|
|
9981
10161
|
const lines = this.groups.flatMap((group) => group.lines), box = Box2.fromByLineSegment(...lines), center = box.center;
|
|
9982
10162
|
this.groups.forEach((group) => group.lines.forEach((line) => {
|
|
9983
10163
|
line.rotate(angle, center);
|
|
9984
|
-
line.start.
|
|
9985
|
-
line.end.
|
|
10164
|
+
line.start.subtract(center);
|
|
10165
|
+
line.end.subtract(center);
|
|
9986
10166
|
}));
|
|
9987
10167
|
this.needUpdate = true;
|
|
9988
10168
|
}
|
|
@@ -10534,13 +10714,19 @@ class DoubleWallHelper {
|
|
|
10534
10714
|
const newLine1 = new LineSegment(project0.start.clone(), project1.start.clone());
|
|
10535
10715
|
const newLine2 = new LineSegment(project0.end.clone(), project1.end.clone());
|
|
10536
10716
|
newLine1.userData.height = line0.userData.height;
|
|
10717
|
+
newLine1.userData.rooftopPz = line0.userData.rooftopPz;
|
|
10537
10718
|
newLine2.userData.height = line1.userData.height;
|
|
10719
|
+
newLine2.userData.rooftopPz = line1.userData.rooftopPz;
|
|
10538
10720
|
appendLines.push(newLine1, newLine2);
|
|
10539
10721
|
addClipingMap(line0, project0);
|
|
10540
10722
|
addClipingMap(line1, project1);
|
|
10541
10723
|
});
|
|
10542
10724
|
clipingMap.forEach((list, line) => {
|
|
10543
10725
|
const newLines = LineSegmentUtils.clippingByPoints(line, list);
|
|
10726
|
+
newLines.forEach((newLine) => {
|
|
10727
|
+
newLine.userData.height = line.userData.height;
|
|
10728
|
+
newLine.userData.rooftopPz = line.userData.rooftopPz;
|
|
10729
|
+
});
|
|
10544
10730
|
lines.push(...newLines);
|
|
10545
10731
|
});
|
|
10546
10732
|
lines = lines.filter((line) => !removeLines.has(line));
|
|
@@ -10551,9 +10737,11 @@ class DoubleWallHelper {
|
|
|
10551
10737
|
const queryLines = quadtree.queryRect(line.toRectangle(1e-3, "butt")).filter((item) => item.line.isParallelTo(line)).map((item) => item.line);
|
|
10552
10738
|
if (queryLines.length) {
|
|
10553
10739
|
const newLines = LineSegmentUtils.clippingByLines(line, queryLines);
|
|
10554
|
-
if (newLines) return newLines.forEach((
|
|
10555
|
-
|
|
10556
|
-
|
|
10740
|
+
if (newLines) return newLines.forEach((newLine) => {
|
|
10741
|
+
newLine.userData.height = line.userData.height;
|
|
10742
|
+
newLine.userData.rooftopPz = line.userData.rooftopPz;
|
|
10743
|
+
quadtree.insert(newLine);
|
|
10744
|
+
lines.push(newLine);
|
|
10557
10745
|
});
|
|
10558
10746
|
}
|
|
10559
10747
|
quadtree.insert(line);
|
|
@@ -10581,9 +10769,6 @@ class DoubleWallHelper {
|
|
|
10581
10769
|
lineSegments = this.complementSide(lineSegments, otherLines);
|
|
10582
10770
|
WIO.recomputed(lineSegments);
|
|
10583
10771
|
lineSegments = BuildGroup.doubleWall(lineSegments, true);
|
|
10584
|
-
PointUtils.round(
|
|
10585
|
-
PointUtils.quantize(LineSegmentUtils.flatPoints(lineSegments), 1e-4)
|
|
10586
|
-
);
|
|
10587
10772
|
return [...lineSegments, ...otherLines];
|
|
10588
10773
|
}
|
|
10589
10774
|
}
|
|
@@ -10889,7 +11074,7 @@ class AlignToParallelSegments {
|
|
|
10889
11074
|
* @param esp 垂直投影值分组距离
|
|
10890
11075
|
* @param gap 平行轴投影区间间隙
|
|
10891
11076
|
*/
|
|
10892
|
-
static group(lines, parallelAxis, verticalAxis, esp = 0.05, gap = 0.01) {
|
|
11077
|
+
static group(lines, parallelAxis, verticalAxis, esp = 0.05, gap = 0.01, onGroup) {
|
|
10893
11078
|
esp = esp / verticalAxis.len;
|
|
10894
11079
|
gap = gap / parallelAxis.len;
|
|
10895
11080
|
const vls = lines.map((line) => [
|
|
@@ -10897,16 +11082,29 @@ class AlignToParallelSegments {
|
|
|
10897
11082
|
line,
|
|
10898
11083
|
[parallelAxis.projectPointValue(line.start), parallelAxis.projectPointValue(line.end)].sort((a2, b4) => a2 - b4)
|
|
10899
11084
|
]).sort((a2, b4) => a2[0] - b4[0]), unionFindSet = new UnionFindSet(vls.length);
|
|
10900
|
-
for (let
|
|
10901
|
-
const [ipv, _iline, [istart, iend]] = vls[
|
|
10902
|
-
for (let j =
|
|
11085
|
+
for (let i2 = 0; i2 < vls.length; i2++) {
|
|
11086
|
+
const [ipv, _iline, [istart, iend]] = vls[i2];
|
|
11087
|
+
for (let j = i2 + 1; j < vls.length; j++) {
|
|
10903
11088
|
const [jpv, _jline, [jstart, jend]] = vls[j];
|
|
10904
11089
|
if (jpv - ipv > esp) break;
|
|
10905
11090
|
const overlap = Math.min(iend, jend) - Math.max(istart, jstart);
|
|
10906
|
-
if (overlap > -gap) unionFindSet.union(
|
|
10907
|
-
}
|
|
10908
|
-
}
|
|
10909
|
-
const
|
|
11091
|
+
if (overlap > -gap) unionFindSet.union(i2, j);
|
|
11092
|
+
}
|
|
11093
|
+
}
|
|
11094
|
+
const map = unionFindSet.getAllSets();
|
|
11095
|
+
const groups = new Array(map.size);
|
|
11096
|
+
let i = 0;
|
|
11097
|
+
map.forEach((list) => {
|
|
11098
|
+
const group = new Array(list.length);
|
|
11099
|
+
const pvList = new Array(list.length);
|
|
11100
|
+
groups[i++] = group;
|
|
11101
|
+
for (let i2 = 0; i2 < list.length; i2++) {
|
|
11102
|
+
const [pv, line] = vls[list[i2]];
|
|
11103
|
+
group[i2] = line;
|
|
11104
|
+
pvList[i2] = pv;
|
|
11105
|
+
}
|
|
11106
|
+
onGroup?.(group, pvList, verticalAxis);
|
|
11107
|
+
});
|
|
10910
11108
|
return groups;
|
|
10911
11109
|
}
|
|
10912
11110
|
/** 拟合并对齐线段
|
|
@@ -10946,13 +11144,13 @@ class AlignToParallelSegments {
|
|
|
10946
11144
|
* @returns
|
|
10947
11145
|
*/
|
|
10948
11146
|
static align(lines, opt = {}) {
|
|
10949
|
-
const { esp = 0.
|
|
11147
|
+
const { esp = 0.08, gap = 0.05 } = opt;
|
|
10950
11148
|
const axisLine = lines[LineSegmentUtils.maxLengthLineIndex(lines)].clone().setLength(100), axisLineV = axisLine.clone().rotate(Math.PI * 0.5, axisLine.center);
|
|
10951
11149
|
let [pllLines, verticalLines] = LineSegmentUtils.groupByParallelToAxis(lines, axisLine);
|
|
10952
|
-
const groups = this.group(pllLines, axisLine, axisLineV, esp, gap);
|
|
11150
|
+
const groups = this.group(pllLines, axisLine, axisLineV, esp, gap, opt.onGroup);
|
|
10953
11151
|
pllLines = this.fittingAlignment(groups, verticalLines, opt);
|
|
10954
11152
|
verticalLines = verticalLines.filter((line) => line.length() > 1e-6);
|
|
10955
|
-
const groups2 = this.group(verticalLines, axisLineV, axisLine, esp, gap);
|
|
11153
|
+
const groups2 = this.group(verticalLines, axisLineV, axisLine, esp, gap, opt.onGroup);
|
|
10956
11154
|
verticalLines = this.fittingAlignment(groups2, pllLines, opt);
|
|
10957
11155
|
pllLines = pllLines.filter((line) => line.length() > 1e-6);
|
|
10958
11156
|
return [
|
|
@@ -11088,7 +11286,17 @@ function correction(lines, targettLine, option) {
|
|
|
11088
11286
|
lines = AxisAlignCorr.start(lines, targettLine);
|
|
11089
11287
|
lines = lineSegmentClipping(lines, 1e-9);
|
|
11090
11288
|
lines = AlignToParallelSegments.align(lines, {
|
|
11091
|
-
onMergeLine: mergeLineUserData
|
|
11289
|
+
onMergeLine: mergeLineUserData,
|
|
11290
|
+
onGroup(group, projValues, axis) {
|
|
11291
|
+
if (group.length <= 1) return;
|
|
11292
|
+
const max = Math.max(...projValues);
|
|
11293
|
+
const min = Math.min(...projValues);
|
|
11294
|
+
const dist = precision4((max - min) * axis.len);
|
|
11295
|
+
if (dist < DEFAULT_WALL_WIDTH) return;
|
|
11296
|
+
group.forEach((line) => {
|
|
11297
|
+
line.userData.wallWidth = dist;
|
|
11298
|
+
});
|
|
11299
|
+
}
|
|
11092
11300
|
// esp: 0.4
|
|
11093
11301
|
});
|
|
11094
11302
|
lines = adsorption(lines, option);
|
|
@@ -11314,7 +11522,7 @@ class DoorFind {
|
|
|
11314
11522
|
}).filter((item) => {
|
|
11315
11523
|
return item.point.distance(dock.point) / length > 0.5;
|
|
11316
11524
|
}).filter((item) => {
|
|
11317
|
-
const normal = item.point.
|
|
11525
|
+
const normal = item.point.leftNormal(dock.point), center = new Point((item.point.x + dock.point.x) / 2, (item.point.y + dock.point.y) / 2), length2 = item.point.distance(dock.point);
|
|
11318
11526
|
const normalLine = new LineSegment(
|
|
11319
11527
|
center,
|
|
11320
11528
|
center.clone().add(normal.clone().multiplyScalar(length2))
|
|
@@ -11601,7 +11809,7 @@ class HeightQuery {
|
|
|
11601
11809
|
if (contoursData.length) return contoursData;
|
|
11602
11810
|
points.filter((p2) => {
|
|
11603
11811
|
point.set(p2[0], p2[1]);
|
|
11604
|
-
new Array(...new Set(quadtree?.queryCircle(point, 0.
|
|
11812
|
+
new Array(...new Set(quadtree?.queryCircle(point, 0.6).map((item) => item.line.currentData.contourIndex))).forEach((index2) => {
|
|
11605
11813
|
if (index2 === maxContourIndex) return;
|
|
11606
11814
|
contoursData.push({ i: index2, averagePz: contours[index2].averagePz });
|
|
11607
11815
|
});
|
|
@@ -11625,9 +11833,17 @@ function wallHeightHandle(lineSegments, option) {
|
|
|
11625
11833
|
Object.defineProperty(option.publicInfo.rootTopContourInfo, "quadtree", { value: quadtree });
|
|
11626
11834
|
}
|
|
11627
11835
|
}
|
|
11836
|
+
const psh = PointSpatialHash.fromByLines(lineSegments);
|
|
11628
11837
|
lineSegments.forEach((line) => {
|
|
11629
11838
|
if (!("height" in line.userData)) {
|
|
11630
|
-
if (!line.userData.rooftopPz && option?.publicInfo?.rootTopContourInfo)
|
|
11839
|
+
if (!line.userData.rooftopPz && option?.publicInfo?.rootTopContourInfo) {
|
|
11840
|
+
const list = psh.queryPoints(line.points, true).map((item) => item.userData?.userData.rooftopPz ?? 0);
|
|
11841
|
+
if (list.length) {
|
|
11842
|
+
line.userData.rooftopPz = Math.max(...list);
|
|
11843
|
+
} else {
|
|
11844
|
+
line.userData.rooftopPz = HeightQuery.query(line, option.publicInfo.rootTopContourInfo);
|
|
11845
|
+
}
|
|
11846
|
+
}
|
|
11631
11847
|
if ("rooftopPz" in line.userData) line.userData.height = Math.abs(line.userData.rooftopPz - (option.originalZ ?? 0));
|
|
11632
11848
|
}
|
|
11633
11849
|
});
|
package/src/index3.js
CHANGED
|
@@ -16415,7 +16415,7 @@ class VerticalCorrContinue extends CommandFlowComponent {
|
|
|
16415
16415
|
}
|
|
16416
16416
|
}
|
|
16417
16417
|
function buildDashedHelperLine$1(start, end, offset = 0.5) {
|
|
16418
|
-
const offsetDistance = end.
|
|
16418
|
+
const offsetDistance = end.leftNormal(start).multiplyScalar(offset);
|
|
16419
16419
|
const startOffPoint = start.clone().add(offsetDistance);
|
|
16420
16420
|
const endOffPoint = end.clone().add(offsetDistance);
|
|
16421
16421
|
return [
|
|
@@ -16494,7 +16494,7 @@ class RayDistance extends CommandFlowComponent {
|
|
|
16494
16494
|
}
|
|
16495
16495
|
}
|
|
16496
16496
|
function buildDashedHelperLine(start, end, offset = 0.5) {
|
|
16497
|
-
const offsetDistance = end.
|
|
16497
|
+
const offsetDistance = end.leftNormal(start).multiplyScalar(offset);
|
|
16498
16498
|
const startOffPoint = start.clone().add(offsetDistance);
|
|
16499
16499
|
const endOffPoint = end.clone().add(offsetDistance);
|
|
16500
16500
|
return [
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { LineSegment } from './LineSegment';
|
|
2
|
+
type OnGroupFun = (group: LineSegment[], projValues: number[], axis: LineSegment) => void;
|
|
2
3
|
export interface AlignDescriptor {
|
|
3
4
|
esp?: number;
|
|
4
5
|
gap?: number;
|
|
5
6
|
onMergeLine?: (target: LineSegment, source: LineSegment) => void;
|
|
7
|
+
onGroup?: OnGroupFun;
|
|
6
8
|
}
|
|
7
9
|
/** 通过平行轴和垂直轴分组对齐线段,搭配垂直纠正使用
|
|
8
10
|
*/
|
|
@@ -14,7 +16,7 @@ export declare class AlignToParallelSegments {
|
|
|
14
16
|
* @param esp 垂直投影值分组距离
|
|
15
17
|
* @param gap 平行轴投影区间间隙
|
|
16
18
|
*/
|
|
17
|
-
static group(lines: LineSegment[], parallelAxis: LineSegment, verticalAxis: LineSegment, esp?: number, gap?: number): LineSegment<Record<string, any>>[][];
|
|
19
|
+
static group(lines: LineSegment[], parallelAxis: LineSegment, verticalAxis: LineSegment, esp?: number, gap?: number, onGroup?: OnGroupFun): LineSegment<Record<string, any>>[][];
|
|
18
20
|
/** 拟合并对齐线段
|
|
19
21
|
* @param groups
|
|
20
22
|
* @param verticalLines
|
|
@@ -26,3 +28,4 @@ export declare class AlignToParallelSegments {
|
|
|
26
28
|
*/
|
|
27
29
|
static align(lines: LineSegment[], opt?: AlignDescriptor): LineSegment<Record<string, any>>[];
|
|
28
30
|
}
|
|
31
|
+
export {};
|
|
@@ -2,6 +2,14 @@ import { LineSegment } from './LineSegment';
|
|
|
2
2
|
import { Point } from './Point';
|
|
3
3
|
export declare class LineSegmentUtils {
|
|
4
4
|
clone(lines: LineSegment[]): LineSegment<Record<string, any>>[];
|
|
5
|
+
/**保留小数位数
|
|
6
|
+
* @param points
|
|
7
|
+
*/
|
|
8
|
+
static precision(lines: LineSegment[], count: number): LineSegment<Record<string, any>>[];
|
|
9
|
+
/**保留四位小数位数
|
|
10
|
+
* @param points
|
|
11
|
+
*/
|
|
12
|
+
static precision4(lines: LineSegment[]): LineSegment<Record<string, any>>[];
|
|
5
13
|
/** 获取最长线段索引
|
|
6
14
|
* @param lines
|
|
7
15
|
*/
|
|
@@ -28,14 +28,22 @@ export declare class Point<T = Record<string, any>> {
|
|
|
28
28
|
* @param arr
|
|
29
29
|
*/
|
|
30
30
|
setByArray(arr: number[]): this;
|
|
31
|
-
/**
|
|
32
|
-
* multiplyScalar
|
|
31
|
+
/** 乘法
|
|
33
32
|
* @param scalar
|
|
33
|
+
* @returns
|
|
34
|
+
*/
|
|
35
|
+
multiply(point: Point): this;
|
|
36
|
+
/** 乘以一个标量
|
|
37
|
+
* @param scalar
|
|
38
|
+
* @returns
|
|
34
39
|
*/
|
|
35
|
-
mutiplyScalar(scalar: number): this;
|
|
36
40
|
multiplyScalar(scalar: number): this;
|
|
37
|
-
/**
|
|
38
|
-
*
|
|
41
|
+
/** 除法
|
|
42
|
+
* @param scalar
|
|
43
|
+
* @returns
|
|
44
|
+
*/
|
|
45
|
+
division(point: Point): this;
|
|
46
|
+
/** 除一个标量
|
|
39
47
|
* @param scalar
|
|
40
48
|
* @returns
|
|
41
49
|
*/
|
|
@@ -46,14 +54,14 @@ export declare class Point<T = Record<string, any>> {
|
|
|
46
54
|
* @param point
|
|
47
55
|
* @returns
|
|
48
56
|
*/
|
|
49
|
-
|
|
57
|
+
subtract(point: Point): this;
|
|
50
58
|
/**
|
|
51
|
-
*
|
|
59
|
+
* 减一个标量
|
|
52
60
|
* @description 将当前点的坐标减去指定点的坐标
|
|
53
61
|
* @param point
|
|
54
62
|
* @returns
|
|
55
63
|
*/
|
|
56
|
-
|
|
64
|
+
subtractScalar(value: number): this;
|
|
57
65
|
/**
|
|
58
66
|
* 加法
|
|
59
67
|
* @description 将当前点的坐标加上指定点的坐标
|
|
@@ -61,13 +69,31 @@ export declare class Point<T = Record<string, any>> {
|
|
|
61
69
|
* @returns
|
|
62
70
|
*/
|
|
63
71
|
add(point: Point): this;
|
|
64
|
-
/**
|
|
65
|
-
* 加法
|
|
72
|
+
/** 加一个标量
|
|
66
73
|
* @description 将当前点的坐标加上指定点的坐标
|
|
67
74
|
* @param point
|
|
68
75
|
* @returns
|
|
69
76
|
*/
|
|
70
77
|
addScalar(value: number): void;
|
|
78
|
+
/**
|
|
79
|
+
* 加法(不可变)
|
|
80
|
+
* @description 返回当前点与指定点相加后的新点,不修改当前点
|
|
81
|
+
* @param point
|
|
82
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
83
|
+
* @returns 相加后的点
|
|
84
|
+
*/
|
|
85
|
+
added(point: Point, out?: Point<Record<string, any>>): Point<Record<string, any>>;
|
|
86
|
+
/**
|
|
87
|
+
* 减法(不可变)
|
|
88
|
+
* @description 返回当前点减去指定点后的新点,不修改当前点
|
|
89
|
+
* @param point
|
|
90
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
91
|
+
* @returns 相减后的点
|
|
92
|
+
*/
|
|
93
|
+
subtracted(point: Point, out?: Point<Record<string, any>>): Point<Record<string, any>>;
|
|
94
|
+
/** 转为整型
|
|
95
|
+
* @returns
|
|
96
|
+
*/
|
|
71
97
|
parseInt(): this;
|
|
72
98
|
/**
|
|
73
99
|
* 绕point旋转angle
|
|
@@ -78,15 +104,27 @@ export declare class Point<T = Record<string, any>> {
|
|
|
78
104
|
x: number;
|
|
79
105
|
y: number;
|
|
80
106
|
}, angle: number): this;
|
|
107
|
+
/**
|
|
108
|
+
* 旋转(不可变)
|
|
109
|
+
* @description 返回当前点绕指定中心旋转后的新点,不修改当前点
|
|
110
|
+
* @param center 旋转中心
|
|
111
|
+
* @param angle 旋转角度(弧度)
|
|
112
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
113
|
+
* @returns 旋转后的点
|
|
114
|
+
*/
|
|
115
|
+
rotated(center: {
|
|
116
|
+
x: number;
|
|
117
|
+
y: number;
|
|
118
|
+
}, angle: number, out?: Point<Record<string, any>>): Point<Record<string, any>>;
|
|
81
119
|
/**
|
|
82
120
|
* 保留小数位数
|
|
83
121
|
* @param count
|
|
84
122
|
*/
|
|
85
|
-
|
|
86
|
-
/**
|
|
123
|
+
precision(count: number): this;
|
|
124
|
+
/** 保留四位小数
|
|
87
125
|
* @returns
|
|
88
126
|
*/
|
|
89
|
-
|
|
127
|
+
precision4(): this;
|
|
90
128
|
/**
|
|
91
129
|
* 归一化
|
|
92
130
|
* @description 将当前点的坐标归一化为单位向量
|
|
@@ -94,12 +132,19 @@ export declare class Point<T = Record<string, any>> {
|
|
|
94
132
|
*/
|
|
95
133
|
normalize(): this;
|
|
96
134
|
/**
|
|
97
|
-
|
|
135
|
+
* 归一化(不可变)
|
|
136
|
+
* @description 返回当前向量归一化后的新点,不修改当前点
|
|
137
|
+
* @param out 输出对象,用于复用对象减少 GC
|
|
138
|
+
* @returns 单位向量
|
|
139
|
+
*/
|
|
140
|
+
normalized(out?: Point<Record<string, any>>): Point<Record<string, any>>;
|
|
141
|
+
/**
|
|
142
|
+
* 获取单位左法向量
|
|
98
143
|
* @description 计算当前点到指定点的方向向量,并返回逆时针旋转90度后的单位法向量
|
|
99
144
|
* @param point
|
|
100
145
|
* @returns
|
|
101
146
|
*/
|
|
102
|
-
|
|
147
|
+
leftNormal(point: Point): Point<Record<string, any>>;
|
|
103
148
|
/**
|
|
104
149
|
* 获取由传入的点到该点的单位方向向量
|
|
105
150
|
* @description 计算当前点到指定点的方向向量,并返回单位方向
|
|
@@ -176,10 +221,13 @@ export declare class Point<T = Record<string, any>> {
|
|
|
176
221
|
x: number;
|
|
177
222
|
y: number;
|
|
178
223
|
}): this;
|
|
179
|
-
/**
|
|
180
|
-
*
|
|
224
|
+
/** 转为数组
|
|
181
225
|
*/
|
|
182
226
|
toArray(): [number, number];
|
|
227
|
+
/** 转为json
|
|
228
|
+
* @param z
|
|
229
|
+
* @returns
|
|
230
|
+
*/
|
|
183
231
|
toJson(z?: number): {
|
|
184
232
|
x: number;
|
|
185
233
|
y: number;
|
|
@@ -8,7 +8,11 @@ export declare class PointUtils {
|
|
|
8
8
|
/**保留小数位数
|
|
9
9
|
* @param points
|
|
10
10
|
*/
|
|
11
|
-
static
|
|
11
|
+
static precision(points: Point[], count: number): Point<Record<string, any>>[];
|
|
12
|
+
/**保留四位小数位数
|
|
13
|
+
* @param points
|
|
14
|
+
*/
|
|
15
|
+
static precision4(points: Point[]): Point<Record<string, any>>[];
|
|
12
16
|
/** 点吸附
|
|
13
17
|
* @param points
|
|
14
18
|
* @param tolerance
|
|
@@ -13,7 +13,15 @@ export declare class Polygon<T = any> extends Array<Point<T>> {
|
|
|
13
13
|
[Symbol.iterator](): ArrayIterator<Point<T>>;
|
|
14
14
|
constructor(points?: Point<T>[]);
|
|
15
15
|
set(points?: Point<T>[]): void;
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* 获取多边形几何中心(面积质心)
|
|
18
|
+
* @description 使用多边形面积质心公式计算
|
|
19
|
+
* @description 适用于闭合简单多边形(顺时针或逆时针均可)
|
|
20
|
+
* @description 如果面积为 0,则退化为顶点平均中心
|
|
21
|
+
* @param out 输出对象,用于减少 GC
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
getCenter(out?: Point<Record<string, any>>): Point<Record<string, any>>;
|
|
17
25
|
/** 计算二维包围盒
|
|
18
26
|
* @returns
|
|
19
27
|
*/
|