build-dxf 0.0.8 → 0.0.10
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/README.md +21 -3
- package/package.json +24 -6
- package/src/{plugins/ModelDataPlugin/index.js → build.js} +850 -13
- package/src/index.css +1 -0
- package/src/index.d.ts +85 -0
- package/src/index.js +4 -1750
- package/src/index2.js +7361 -0
- package/src/plugins/ModelDataPlugin/index.d.ts +0 -588
- package/src/plugins/RenderPlugin/index.d.ts +0 -588
- package/src/plugins/RenderPlugin/index.js +0 -1184
|
@@ -2,6 +2,7 @@ import * as THREE from "three";
|
|
|
2
2
|
import { EventDispatcher as EventDispatcher$1 } from "three";
|
|
3
3
|
import ClipperLib from "clipper-lib";
|
|
4
4
|
import Drawing from "dxf-writer";
|
|
5
|
+
import { OBJExporter } from "three/examples/jsm/exporters/OBJExporter.js";
|
|
5
6
|
function uuid() {
|
|
6
7
|
return "xxxx-xxxx-4xxx-yxxx-xxxx".replace(/[xy]/g, function(c) {
|
|
7
8
|
var r = Math.random() * 16 | 0, v = c == "x" ? r : r & 3 | 8;
|
|
@@ -31,6 +32,83 @@ class Component extends EventDispatcher {
|
|
|
31
32
|
destroy() {
|
|
32
33
|
}
|
|
33
34
|
}
|
|
35
|
+
class ComponentManager extends EventDispatcher {
|
|
36
|
+
static EventType = {
|
|
37
|
+
ADD_COMPONENT: "addComponent"
|
|
38
|
+
};
|
|
39
|
+
components = [];
|
|
40
|
+
/**
|
|
41
|
+
* 添加组件
|
|
42
|
+
* @param component
|
|
43
|
+
*/
|
|
44
|
+
addComponent(component) {
|
|
45
|
+
if (component) {
|
|
46
|
+
this.components.push(component);
|
|
47
|
+
this.dispatchEvent({
|
|
48
|
+
type: "addComponent",
|
|
49
|
+
component
|
|
50
|
+
});
|
|
51
|
+
component.dispatchEvent({
|
|
52
|
+
type: "addFromParent",
|
|
53
|
+
parent: this
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 移除组件
|
|
60
|
+
* @param component
|
|
61
|
+
*/
|
|
62
|
+
removeComponent(component) {
|
|
63
|
+
if (component instanceof Component) {
|
|
64
|
+
const index2 = this.components.indexOf(component);
|
|
65
|
+
if (index2 > -1) {
|
|
66
|
+
this.components.splice(index2, 1);
|
|
67
|
+
this.dispatchEvent({
|
|
68
|
+
type: "removeComponent",
|
|
69
|
+
component
|
|
70
|
+
});
|
|
71
|
+
component.dispatchEvent({
|
|
72
|
+
type: "removeFromParent",
|
|
73
|
+
parent: this
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* 查找符合条件的第一个组件
|
|
80
|
+
* @param callBack
|
|
81
|
+
*/
|
|
82
|
+
findComponent(predicate) {
|
|
83
|
+
for (let i = 0; i < this.components.length; i++) {
|
|
84
|
+
const component = this.components[i];
|
|
85
|
+
if (predicate(component, i)) return component;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 查找所有符合条件的组件
|
|
90
|
+
* @param callBack
|
|
91
|
+
*/
|
|
92
|
+
findComponents(predicate) {
|
|
93
|
+
return this.components.find(predicate);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
*
|
|
97
|
+
* @param type
|
|
98
|
+
*/
|
|
99
|
+
findComponentByType(type) {
|
|
100
|
+
const component = this.findComponent((c) => c instanceof type);
|
|
101
|
+
return component ? component : null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
*
|
|
105
|
+
* @param type
|
|
106
|
+
*/
|
|
107
|
+
findComponentByName(name) {
|
|
108
|
+
const component = this.findComponent((c) => c.constructor.name === name);
|
|
109
|
+
return component ? component : null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
34
112
|
class Point {
|
|
35
113
|
x;
|
|
36
114
|
y;
|
|
@@ -981,6 +1059,704 @@ class Variable extends Component {
|
|
|
981
1059
|
if (key in this) return this[key];
|
|
982
1060
|
}
|
|
983
1061
|
}
|
|
1062
|
+
class Rectangle {
|
|
1063
|
+
points;
|
|
1064
|
+
get path() {
|
|
1065
|
+
return this.points.flatMap((p, i) => {
|
|
1066
|
+
const np = this.points[(i + 1) % this.points.length];
|
|
1067
|
+
return [p.x, p.y, 0, np.x, np.y, 0];
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
constructor(points) {
|
|
1071
|
+
if (points.length !== 4) {
|
|
1072
|
+
throw new Error("Rectangle must be defined by exactly 4 points");
|
|
1073
|
+
}
|
|
1074
|
+
this.points = points;
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* 判断线段是否与矩形相交
|
|
1078
|
+
* @param line 线段
|
|
1079
|
+
* @returns 是否与矩形相交
|
|
1080
|
+
*/
|
|
1081
|
+
intersectLineSegment(line) {
|
|
1082
|
+
if (line.points.length !== 2) {
|
|
1083
|
+
throw new Error("LineSegment must have exactly 2 points");
|
|
1084
|
+
}
|
|
1085
|
+
const [p1, p2] = line.points;
|
|
1086
|
+
const doIntersect = (l1p1, l1p2, l2p1, l2p2) => {
|
|
1087
|
+
const orientation = (p, q, r) => {
|
|
1088
|
+
const val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
|
|
1089
|
+
if (val === 0) return 0;
|
|
1090
|
+
return val > 0 ? 1 : 2;
|
|
1091
|
+
};
|
|
1092
|
+
const onSegment = (p, q, r) => {
|
|
1093
|
+
return Math.min(p.x, r.x) <= q.x && q.x <= Math.max(p.x, r.x) && Math.min(p.y, r.y) <= q.y && q.y <= Math.max(p.y, r.y);
|
|
1094
|
+
};
|
|
1095
|
+
const o1 = orientation(l1p1, l1p2, l2p1);
|
|
1096
|
+
const o2 = orientation(l1p1, l1p2, l2p2);
|
|
1097
|
+
const o3 = orientation(l2p1, l2p2, l1p1);
|
|
1098
|
+
const o4 = orientation(l2p1, l2p2, l1p2);
|
|
1099
|
+
if (o1 !== o2 && o3 !== o4) return true;
|
|
1100
|
+
if (o1 === 0 && onSegment(l1p1, l2p1, l1p2)) return true;
|
|
1101
|
+
if (o2 === 0 && onSegment(l1p1, l2p2, l1p2)) return true;
|
|
1102
|
+
if (o3 === 0 && onSegment(l2p1, l1p1, l2p2)) return true;
|
|
1103
|
+
if (o4 === 0 && onSegment(l2p1, l1p2, l2p2)) return true;
|
|
1104
|
+
return false;
|
|
1105
|
+
};
|
|
1106
|
+
for (let i = 0; i < 4; i++) {
|
|
1107
|
+
const rectP1 = this.points[i];
|
|
1108
|
+
const rectP2 = this.points[(i + 1) % 4];
|
|
1109
|
+
if (doIntersect(p1, p2, rectP1, rectP2)) {
|
|
1110
|
+
return true;
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
if (this.containsLineSegment(line)) {
|
|
1114
|
+
return true;
|
|
1115
|
+
}
|
|
1116
|
+
return false;
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* 判断线段是否完全位于矩形内部
|
|
1120
|
+
* @param line 线段
|
|
1121
|
+
* @returns 是否完全在矩形内部
|
|
1122
|
+
*/
|
|
1123
|
+
containsLineSegment(line) {
|
|
1124
|
+
if (line.points.length !== 2) {
|
|
1125
|
+
throw new Error("LineSegment must have exactly 2 points");
|
|
1126
|
+
}
|
|
1127
|
+
const isPointInRectangle = (point) => {
|
|
1128
|
+
let sign = 0;
|
|
1129
|
+
for (let i = 0; i < 4; i++) {
|
|
1130
|
+
const p1 = this.points[i];
|
|
1131
|
+
const p2 = this.points[(i + 1) % 4];
|
|
1132
|
+
const edge = { x: p2.x - p1.x, y: p2.y - p1.y };
|
|
1133
|
+
const toPoint = { x: point.x - p1.x, y: point.y - p1.y };
|
|
1134
|
+
const cross = edge.x * toPoint.y - edge.y * toPoint.x;
|
|
1135
|
+
if (cross === 0) {
|
|
1136
|
+
const t = edge.x !== 0 ? (point.x - p1.x) / edge.x : (point.y - p1.y) / edge.y;
|
|
1137
|
+
if (t >= 0 && t <= 1) return true;
|
|
1138
|
+
} else {
|
|
1139
|
+
const currentSign = cross > 0 ? 1 : -1;
|
|
1140
|
+
if (sign === 0) sign = currentSign;
|
|
1141
|
+
if (sign !== currentSign) return false;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
return true;
|
|
1145
|
+
};
|
|
1146
|
+
return isPointInRectangle(line.points[0]) && isPointInRectangle(line.points[1]);
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* 判断点是否完全位于矩形内部
|
|
1150
|
+
* @param point
|
|
1151
|
+
*/
|
|
1152
|
+
containsPoint(point) {
|
|
1153
|
+
let positiveCount = 0;
|
|
1154
|
+
let negativeCount = 0;
|
|
1155
|
+
for (let i = 0; i < 4; i++) {
|
|
1156
|
+
const p1 = this.points[i];
|
|
1157
|
+
const p2 = this.points[(i + 1) % 4];
|
|
1158
|
+
const cross = (p2.x - p1.x) * (point.y - p1.y) - (p2.y - p1.y) * (point.x - p1.x);
|
|
1159
|
+
if (cross > 0) positiveCount++;
|
|
1160
|
+
else if (cross < 0) negativeCount++;
|
|
1161
|
+
else return false;
|
|
1162
|
+
}
|
|
1163
|
+
return positiveCount === 4 || negativeCount === 4;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
*
|
|
1167
|
+
* @returns
|
|
1168
|
+
*/
|
|
1169
|
+
toBox() {
|
|
1170
|
+
let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
|
|
1171
|
+
this.points.forEach((p) => {
|
|
1172
|
+
maxX = Math.max(p.x, maxX);
|
|
1173
|
+
minX = Math.min(p.x, minX);
|
|
1174
|
+
maxY = Math.max(p.x, maxY);
|
|
1175
|
+
minY = Math.min(p.x, minY);
|
|
1176
|
+
});
|
|
1177
|
+
return new Box2(minX, maxX, minY, maxY);
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
*
|
|
1181
|
+
* @param line
|
|
1182
|
+
* @param width
|
|
1183
|
+
* @returns
|
|
1184
|
+
*/
|
|
1185
|
+
static fromByLineSegment(line, width = 0.1, horizontal = false, hScale = 0.5) {
|
|
1186
|
+
const p1 = line.points[0], p2 = line.points[1], normal = p2.normal(p1), pDirect = horizontal ? p2.direction(p1).mutiplyScalar(width * hScale) : Point.zero(), nDirect = horizontal ? p1.direction(p2).mutiplyScalar(width * hScale) : Point.zero();
|
|
1187
|
+
const offsetX = normal.x * width * 0.5;
|
|
1188
|
+
const offsetY = normal.y * width * 0.5;
|
|
1189
|
+
return new Rectangle([
|
|
1190
|
+
new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
|
|
1191
|
+
new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
|
|
1192
|
+
new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect),
|
|
1193
|
+
new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect)
|
|
1194
|
+
]);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
class Quadtree {
|
|
1198
|
+
bounds;
|
|
1199
|
+
// 包围盒
|
|
1200
|
+
capacity;
|
|
1201
|
+
// 节点容量
|
|
1202
|
+
maxDepth;
|
|
1203
|
+
// 最大深度
|
|
1204
|
+
depth;
|
|
1205
|
+
// 当前深度
|
|
1206
|
+
isLeaf = true;
|
|
1207
|
+
// 是否为叶子节点
|
|
1208
|
+
children = null;
|
|
1209
|
+
// 子节点数组
|
|
1210
|
+
nodes = [];
|
|
1211
|
+
// 存储的节点
|
|
1212
|
+
color = [Math.random(), Math.random(), Math.random()];
|
|
1213
|
+
// 颜色
|
|
1214
|
+
constructor(bounds, capacity = 8, maxDepth = 10, depth = 1) {
|
|
1215
|
+
this.bounds = bounds;
|
|
1216
|
+
this.capacity = capacity;
|
|
1217
|
+
this.depth = depth;
|
|
1218
|
+
this.maxDepth = maxDepth;
|
|
1219
|
+
}
|
|
1220
|
+
/**
|
|
1221
|
+
* 插入线段节点
|
|
1222
|
+
* @param node 线段节点
|
|
1223
|
+
*/
|
|
1224
|
+
insert(node) {
|
|
1225
|
+
if (!this.isLeaf) {
|
|
1226
|
+
const quadrant = this.getQuadrant(node.line);
|
|
1227
|
+
if (quadrant !== -1) {
|
|
1228
|
+
this.children[quadrant].insert(node);
|
|
1229
|
+
return;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
this.nodes.push(node);
|
|
1233
|
+
if (this.isLeaf && this.nodes.length > this.capacity && this.depth < this.maxDepth) {
|
|
1234
|
+
this.subdivide();
|
|
1235
|
+
const nodes = this.nodes;
|
|
1236
|
+
this.nodes = [];
|
|
1237
|
+
for (const n of nodes) {
|
|
1238
|
+
const quadrant = this.getQuadrant(n.line);
|
|
1239
|
+
if (quadrant !== -1) {
|
|
1240
|
+
this.children[quadrant].insert(n);
|
|
1241
|
+
} else {
|
|
1242
|
+
this.nodes.push(n);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* 获取线段所属的象限
|
|
1249
|
+
* @param line 线段
|
|
1250
|
+
* @returns 象限索引(0:西北,1:东北,2:西南,3:东南)或-1(跨多个象限)
|
|
1251
|
+
*/
|
|
1252
|
+
getQuadrant(line) {
|
|
1253
|
+
const intersectsNW = this.children[0].bounds.intersectLineSegment(line);
|
|
1254
|
+
const intersectsNE = this.children[1].bounds.intersectLineSegment(line);
|
|
1255
|
+
const intersectsSW = this.children[2].bounds.intersectLineSegment(line);
|
|
1256
|
+
const intersectsSE = this.children[3].bounds.intersectLineSegment(line);
|
|
1257
|
+
let count = 0;
|
|
1258
|
+
let quadrant = -1;
|
|
1259
|
+
if (intersectsNW) {
|
|
1260
|
+
count++;
|
|
1261
|
+
quadrant = 0;
|
|
1262
|
+
}
|
|
1263
|
+
if (intersectsNE) {
|
|
1264
|
+
count++;
|
|
1265
|
+
quadrant = 1;
|
|
1266
|
+
}
|
|
1267
|
+
if (intersectsSW) {
|
|
1268
|
+
count++;
|
|
1269
|
+
quadrant = 2;
|
|
1270
|
+
}
|
|
1271
|
+
if (intersectsSE) {
|
|
1272
|
+
count++;
|
|
1273
|
+
quadrant = 3;
|
|
1274
|
+
}
|
|
1275
|
+
if (count === 1) return quadrant;
|
|
1276
|
+
return -1;
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* 细分当前节点为四个子节点
|
|
1280
|
+
*/
|
|
1281
|
+
subdivide() {
|
|
1282
|
+
if (!this.isLeaf) return;
|
|
1283
|
+
this.isLeaf = false;
|
|
1284
|
+
this.children = [];
|
|
1285
|
+
const midX = (this.bounds.minX + this.bounds.maxX) / 2;
|
|
1286
|
+
const midY = (this.bounds.minY + this.bounds.maxY) / 2;
|
|
1287
|
+
this.children[0] = new Quadtree(
|
|
1288
|
+
new Box2(this.bounds.minX, midX, this.bounds.minY, midY),
|
|
1289
|
+
this.capacity,
|
|
1290
|
+
this.maxDepth,
|
|
1291
|
+
this.depth + 1
|
|
1292
|
+
);
|
|
1293
|
+
this.children[1] = new Quadtree(
|
|
1294
|
+
new Box2(midX, this.bounds.maxX, this.bounds.minY, midY),
|
|
1295
|
+
this.capacity,
|
|
1296
|
+
this.maxDepth,
|
|
1297
|
+
this.depth + 1
|
|
1298
|
+
);
|
|
1299
|
+
this.children[2] = new Quadtree(
|
|
1300
|
+
new Box2(this.bounds.minX, midX, midY, this.bounds.maxY),
|
|
1301
|
+
this.capacity,
|
|
1302
|
+
this.maxDepth,
|
|
1303
|
+
this.depth + 1
|
|
1304
|
+
);
|
|
1305
|
+
this.children[3] = new Quadtree(
|
|
1306
|
+
new Box2(midX, this.bounds.maxX, midY, this.bounds.maxY),
|
|
1307
|
+
this.capacity,
|
|
1308
|
+
this.maxDepth,
|
|
1309
|
+
this.depth + 1
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* 查询与包围盒相交的线段节点
|
|
1314
|
+
* @param box2 包围盒
|
|
1315
|
+
* @returns 相交的节点数组
|
|
1316
|
+
*/
|
|
1317
|
+
queryBox(box2) {
|
|
1318
|
+
const result = [];
|
|
1319
|
+
if (!this.bounds.intersectBox(box2)) {
|
|
1320
|
+
return result;
|
|
1321
|
+
}
|
|
1322
|
+
for (const node of this.nodes) {
|
|
1323
|
+
if (box2.intersectLineSegment(node.line)) {
|
|
1324
|
+
result.push(node);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
if (!this.isLeaf) {
|
|
1328
|
+
for (const child of this.children) {
|
|
1329
|
+
result.push(...child.queryBox(box2));
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1332
|
+
return result;
|
|
1333
|
+
}
|
|
1334
|
+
/**
|
|
1335
|
+
* 查询与圆形区域相交的线段节点
|
|
1336
|
+
* @param pos 圆心
|
|
1337
|
+
* @param radius 半径
|
|
1338
|
+
* @returns 相交的节点数组
|
|
1339
|
+
*/
|
|
1340
|
+
queryCircle(pos, radius) {
|
|
1341
|
+
const result = [];
|
|
1342
|
+
const circleBox = new Box2(
|
|
1343
|
+
pos.x - radius,
|
|
1344
|
+
pos.x + radius,
|
|
1345
|
+
pos.y - radius,
|
|
1346
|
+
pos.y + radius
|
|
1347
|
+
);
|
|
1348
|
+
if (!this.bounds.intersectBox(circleBox)) {
|
|
1349
|
+
return result;
|
|
1350
|
+
}
|
|
1351
|
+
for (const node of this.nodes) {
|
|
1352
|
+
const [p1, p2] = node.line.points;
|
|
1353
|
+
const dx = p2.x - p1.x;
|
|
1354
|
+
const dy = p2.y - p1.y;
|
|
1355
|
+
const l2 = dx * dx + dy * dy;
|
|
1356
|
+
let t = ((pos.x - p1.x) * dx + (pos.y - p1.y) * dy) / l2;
|
|
1357
|
+
t = Math.max(0, Math.min(1, t));
|
|
1358
|
+
const closestX = p1.x + t * dx;
|
|
1359
|
+
const closestY = p1.y + t * dy;
|
|
1360
|
+
const distance = pos.distance(new Point(closestX, closestY));
|
|
1361
|
+
if (distance <= radius) {
|
|
1362
|
+
result.push(node);
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
if (!this.isLeaf) {
|
|
1366
|
+
for (const child of this.children) {
|
|
1367
|
+
result.push(...child.queryCircle(pos, radius));
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
return result;
|
|
1371
|
+
}
|
|
1372
|
+
/**
|
|
1373
|
+
* 查询与矩形相交的线段节点
|
|
1374
|
+
* @param rectangle 矩形
|
|
1375
|
+
* @returns 相交的节点数组
|
|
1376
|
+
*/
|
|
1377
|
+
queryRect(rectangle) {
|
|
1378
|
+
const result = [];
|
|
1379
|
+
if (!this.bounds.intersectRectangle(rectangle)) {
|
|
1380
|
+
return result;
|
|
1381
|
+
}
|
|
1382
|
+
for (const node of this.nodes) {
|
|
1383
|
+
if (rectangle.intersectLineSegment(node.line)) {
|
|
1384
|
+
result.push(node);
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
if (!this.isLeaf) {
|
|
1388
|
+
for (const child of this.children) {
|
|
1389
|
+
result.push(...child.queryRect(rectangle));
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return result;
|
|
1393
|
+
}
|
|
1394
|
+
/**
|
|
1395
|
+
* 包围盒转换为数组
|
|
1396
|
+
* @param array
|
|
1397
|
+
* @param colors
|
|
1398
|
+
* @returns
|
|
1399
|
+
*/
|
|
1400
|
+
boundsToArray(array = [], colors, recursion = true) {
|
|
1401
|
+
if (!this.isLeaf && recursion) {
|
|
1402
|
+
this.children?.forEach((child) => child.boundsToArray(array, colors));
|
|
1403
|
+
}
|
|
1404
|
+
array.push(...this.bounds.points.flatMap((p, i, array2) => {
|
|
1405
|
+
const np = array2[(i + 1) % array2.length];
|
|
1406
|
+
colors?.push(...this.color);
|
|
1407
|
+
colors?.push(...this.color);
|
|
1408
|
+
return [p.x, p.y, 0, np.x, np.y, 0];
|
|
1409
|
+
}));
|
|
1410
|
+
return array;
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
class PointVirtualGrid {
|
|
1414
|
+
map = /* @__PURE__ */ new Map();
|
|
1415
|
+
gridSize;
|
|
1416
|
+
constructor(gridSize = 2) {
|
|
1417
|
+
this.gridSize = gridSize;
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* 插入
|
|
1421
|
+
* @param point
|
|
1422
|
+
* @param userData
|
|
1423
|
+
*/
|
|
1424
|
+
insert(point, userData) {
|
|
1425
|
+
if (!point || isNaN(point.x) || isNaN(point.y)) {
|
|
1426
|
+
throw new Error("无效的点坐标");
|
|
1427
|
+
}
|
|
1428
|
+
const id = this.getGridId(point);
|
|
1429
|
+
if (!this.map.has(id)) this.map.set(id, /* @__PURE__ */ new Set());
|
|
1430
|
+
const set = this.map.get(id);
|
|
1431
|
+
set?.add({ point, userData });
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* 批量加入
|
|
1435
|
+
* @param points
|
|
1436
|
+
*/
|
|
1437
|
+
insertBatch(points) {
|
|
1438
|
+
for (const { point, userData } of points) {
|
|
1439
|
+
this.insert(point, userData);
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
/**
|
|
1443
|
+
* 获取通过坐标,获取唯一网格索引
|
|
1444
|
+
* @param point
|
|
1445
|
+
* @returns
|
|
1446
|
+
*/
|
|
1447
|
+
getGridId(point) {
|
|
1448
|
+
const i = Math.ceil(point.x / this.gridSize), j = Math.ceil(point.y / this.gridSize);
|
|
1449
|
+
return `${i}.${j}`;
|
|
1450
|
+
}
|
|
1451
|
+
/**
|
|
1452
|
+
*
|
|
1453
|
+
* @param gridId
|
|
1454
|
+
* @returns
|
|
1455
|
+
*/
|
|
1456
|
+
decodeGridId(gridId) {
|
|
1457
|
+
const [i, j] = gridId.split(".").map(Number);
|
|
1458
|
+
return new Point(i, j);
|
|
1459
|
+
}
|
|
1460
|
+
/**
|
|
1461
|
+
* 查询与矩形相交的点
|
|
1462
|
+
* @param rectangle 矩形
|
|
1463
|
+
* @returns 相交的节点数组
|
|
1464
|
+
*/
|
|
1465
|
+
queryRect(rectangle) {
|
|
1466
|
+
const box2 = rectangle.toBox();
|
|
1467
|
+
const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize);
|
|
1468
|
+
for (let i = minI; i <= maxI; i++) {
|
|
1469
|
+
for (let j = minJ; j <= maxJ; j++) {
|
|
1470
|
+
const id = `${i}.${j}`;
|
|
1471
|
+
if (!this.map.has(id)) continue;
|
|
1472
|
+
const set = this.map.get(id);
|
|
1473
|
+
set?.forEach((item) => {
|
|
1474
|
+
if (rectangle.containsPoint(item.point)) ;
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
/**
|
|
1480
|
+
* 查询与圆形区域相交的点
|
|
1481
|
+
* @param pos 圆心
|
|
1482
|
+
* @param radius 半径
|
|
1483
|
+
* @returns 相交的节点数组
|
|
1484
|
+
*/
|
|
1485
|
+
queryCircle(pos, radius) {
|
|
1486
|
+
const box2 = new Box2(pos.x - radius, pos.x + radius, pos.y - radius, pos.y + radius);
|
|
1487
|
+
const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize), list = [];
|
|
1488
|
+
for (let i = minI; i <= maxI; i++) {
|
|
1489
|
+
for (let j = minJ; j <= maxJ; j++) {
|
|
1490
|
+
const id = `${i}.${j}`;
|
|
1491
|
+
if (!this.map.has(id)) continue;
|
|
1492
|
+
const set = this.map.get(id);
|
|
1493
|
+
set?.forEach((item) => {
|
|
1494
|
+
if (pos.distance(item.point) <= radius) list.push(item);
|
|
1495
|
+
});
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
return list;
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* 查询与包围盒相交的点
|
|
1502
|
+
* @param box2 包围盒
|
|
1503
|
+
* @returns 相交的节点数组
|
|
1504
|
+
*/
|
|
1505
|
+
queryBox(box2) {
|
|
1506
|
+
const minI = Math.ceil(box2.minX / this.gridSize), maxI = Math.ceil(box2.maxX / this.gridSize), minJ = Math.ceil(box2.minY / this.gridSize), maxJ = Math.ceil(box2.maxY / this.gridSize), list = [];
|
|
1507
|
+
for (let i = minI; i <= maxI; i++) {
|
|
1508
|
+
for (let j = minJ; j <= maxJ; j++) {
|
|
1509
|
+
const id = `${i}.${j}`;
|
|
1510
|
+
if (!this.map.has(id)) continue;
|
|
1511
|
+
const set = this.map.get(id);
|
|
1512
|
+
set?.forEach((item) => {
|
|
1513
|
+
if (box2.containsPoint(item.point)) list.push(item);
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
return list;
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* 查找相同点
|
|
1521
|
+
* @param point
|
|
1522
|
+
*/
|
|
1523
|
+
queryPoint(point) {
|
|
1524
|
+
const id = this.getGridId(point), list = [];
|
|
1525
|
+
if (this.map.has(id)) {
|
|
1526
|
+
const set = this.map.get(id);
|
|
1527
|
+
set?.forEach((item) => {
|
|
1528
|
+
if (point.equal(item.point)) list.push(item);
|
|
1529
|
+
});
|
|
1530
|
+
}
|
|
1531
|
+
return list;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
class LineAnalysis extends Component {
|
|
1535
|
+
Dxf = null;
|
|
1536
|
+
Variable = null;
|
|
1537
|
+
lineSegmentList = [];
|
|
1538
|
+
container = new THREE.Group();
|
|
1539
|
+
// 误差角度
|
|
1540
|
+
errorAngle = 4;
|
|
1541
|
+
width = 0.4;
|
|
1542
|
+
/**
|
|
1543
|
+
*
|
|
1544
|
+
* @param parent
|
|
1545
|
+
*/
|
|
1546
|
+
onAddFromParent(parent) {
|
|
1547
|
+
this.Dxf = parent.findComponentByName("Dxf");
|
|
1548
|
+
this.Variable = this.parent?.findComponentByName("Variable");
|
|
1549
|
+
this.Dxf.addEventListener("setDta", this.lineAnalysis.bind(this));
|
|
1550
|
+
this.Dxf.addEventListener("lineOffset", this.duplicatePointFiltering.bind(this));
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* 去除路径上重复的点
|
|
1554
|
+
* @description 判断方向向量,一个连续的方向上,只应该出现两个点
|
|
1555
|
+
*/
|
|
1556
|
+
duplicatePointFiltering() {
|
|
1557
|
+
const dxf = this.Dxf;
|
|
1558
|
+
dxf.wallsGroup = dxf.wallsGroup.map((points) => {
|
|
1559
|
+
const filterPoints = [];
|
|
1560
|
+
points.forEach((point, index2) => {
|
|
1561
|
+
if (index2 < 1 || points.length - 1 === index2) return filterPoints.push(point);
|
|
1562
|
+
const preP = points[index2 - 1], nextP = points[index2 + 1], direct1 = point.direction(preP), direct2 = nextP.direction(point), angle = direct1.angleBetween(direct2) / (Math.PI / 180);
|
|
1563
|
+
if (angle > 0.02 && angle < 180 - 0.02) filterPoints.push(point);
|
|
1564
|
+
});
|
|
1565
|
+
points = [filterPoints[0]];
|
|
1566
|
+
for (let i = 1; i < filterPoints.length; i++) {
|
|
1567
|
+
const point = filterPoints[i];
|
|
1568
|
+
const nextP = filterPoints[i - 1];
|
|
1569
|
+
if (nextP.distance(point) < dxf.width * 0.5) ;
|
|
1570
|
+
points.push(point);
|
|
1571
|
+
}
|
|
1572
|
+
return points;
|
|
1573
|
+
});
|
|
1574
|
+
dxf.wallsGroup = dxf.wallsGroup.filter((i) => i.length >= 4);
|
|
1575
|
+
}
|
|
1576
|
+
/**
|
|
1577
|
+
*
|
|
1578
|
+
* @param p1
|
|
1579
|
+
* @param p2
|
|
1580
|
+
* @param width
|
|
1581
|
+
* @returns
|
|
1582
|
+
*/
|
|
1583
|
+
expandLineSegment(p1, p2, width = 0.1) {
|
|
1584
|
+
const normal = p2.normal(p1);
|
|
1585
|
+
const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
|
|
1586
|
+
const nDirect = p1.direction(p2).mutiplyScalar(width * 0.5);
|
|
1587
|
+
const offsetX = normal.x * width * 0.5;
|
|
1588
|
+
const offsetY = normal.y * width * 0.5;
|
|
1589
|
+
return {
|
|
1590
|
+
points: [
|
|
1591
|
+
// 第一条线
|
|
1592
|
+
new Point(p1.x + offsetX, p1.y + offsetY).add(nDirect),
|
|
1593
|
+
new Point(p2.x + offsetX, p2.y + offsetY).add(pDirect),
|
|
1594
|
+
// 第二条线
|
|
1595
|
+
new Point(p1.x - offsetX, p1.y - offsetY).add(nDirect),
|
|
1596
|
+
new Point(p2.x - offsetX, p2.y - offsetY).add(pDirect)
|
|
1597
|
+
],
|
|
1598
|
+
indices: [0, 1, 1, 3, 3, 2, 2, 0],
|
|
1599
|
+
rectIndices: [0, 1, 3, 2, 0]
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
appendLineSegmentList = [];
|
|
1603
|
+
/**
|
|
1604
|
+
* 追加数据
|
|
1605
|
+
* @param p1
|
|
1606
|
+
* @param p2
|
|
1607
|
+
*/
|
|
1608
|
+
addData(p1, p2) {
|
|
1609
|
+
const dxf = this.Dxf;
|
|
1610
|
+
dxf.data.push([p1.clone(), p2.clone(), [], false, dxf.data.length]);
|
|
1611
|
+
this.appendLineSegmentList.push(new LineSegment(p1.clone(), p2.clone()));
|
|
1612
|
+
}
|
|
1613
|
+
/** 结果分析创建矩形
|
|
1614
|
+
* @param result
|
|
1615
|
+
*/
|
|
1616
|
+
createRectangle(result) {
|
|
1617
|
+
const dxf = this.Dxf;
|
|
1618
|
+
const project0 = result.project, project1 = result.project2;
|
|
1619
|
+
this.addData(project0.points[0], project1.points[0]);
|
|
1620
|
+
this.addData(project0.points[1], project1.points[1]);
|
|
1621
|
+
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);
|
|
1622
|
+
direction.multiplyScalar(dxf.width * 0.5);
|
|
1623
|
+
const _leftP = leftP.clone().add(direction), _rightP = rightP.clone().add(direction.multiplyScalar(-1)), d1 = leftP.direction(rightP), d2 = _leftP.direction(_rightP);
|
|
1624
|
+
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) return;
|
|
1625
|
+
leftP.set(_leftP.x, _leftP.y);
|
|
1626
|
+
rightP.set(_rightP.x, _rightP.y);
|
|
1627
|
+
for (let i = 1; i < count; i++) {
|
|
1628
|
+
const left = leftDirection.clone().multiplyScalar(leftFragment * i), right = rightDirection.clone().multiplyScalar(rightFragment * i), p1 = leftP.clone().add(left), p2 = rightP.clone().add(right);
|
|
1629
|
+
this.addData(p1, p2);
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
pointVirtualGrid = new PointVirtualGrid();
|
|
1633
|
+
/**
|
|
1634
|
+
* 构建点的虚拟网格索引
|
|
1635
|
+
*/
|
|
1636
|
+
buildVirtualGrid() {
|
|
1637
|
+
const dxf = this.Dxf;
|
|
1638
|
+
const pointVirtualGrid = new PointVirtualGrid();
|
|
1639
|
+
dxf.originalData.forEach((d, index2) => {
|
|
1640
|
+
const [p1, p2] = [Point.from(d.start), Point.from(d.end)];
|
|
1641
|
+
pointVirtualGrid.insert(p1, { index: index2, type: "start" });
|
|
1642
|
+
pointVirtualGrid.insert(p2, { index: index2, type: "end" });
|
|
1643
|
+
});
|
|
1644
|
+
this.pointVirtualGrid = pointVirtualGrid;
|
|
1645
|
+
}
|
|
1646
|
+
quadtree;
|
|
1647
|
+
/**
|
|
1648
|
+
* 构建线段四叉树,快速查找,
|
|
1649
|
+
*/
|
|
1650
|
+
buildQuadtree() {
|
|
1651
|
+
const dxf = this.Dxf;
|
|
1652
|
+
const lineSegmentList = [];
|
|
1653
|
+
this.quadtree = new Quadtree(dxf.originalBox, 2);
|
|
1654
|
+
dxf.lineSegments.forEach((lineSegment) => {
|
|
1655
|
+
if (lineSegment.userData?.isDoor) return;
|
|
1656
|
+
this.quadtree?.insert({
|
|
1657
|
+
line: lineSegment,
|
|
1658
|
+
userData: lineSegmentList.length
|
|
1659
|
+
});
|
|
1660
|
+
lineSegmentList.push(lineSegment);
|
|
1661
|
+
});
|
|
1662
|
+
this.lineSegmentList = lineSegmentList;
|
|
1663
|
+
}
|
|
1664
|
+
resultList = [];
|
|
1665
|
+
/** 线段分析
|
|
1666
|
+
* @description 判断两条线段距离是否较短且趋近平行,然后查找两条线段的重合部分的投影线,以此判断两根线是否需要合并
|
|
1667
|
+
* @param data
|
|
1668
|
+
*/
|
|
1669
|
+
lineAnalysis() {
|
|
1670
|
+
this.buildQuadtree();
|
|
1671
|
+
this.buildVirtualGrid();
|
|
1672
|
+
const quadtree = this.quadtree;
|
|
1673
|
+
const lineSegmentList = this.lineSegmentList;
|
|
1674
|
+
const visited = /* @__PURE__ */ new Set(), resultList = [];
|
|
1675
|
+
lineSegmentList.forEach((_0, i) => {
|
|
1676
|
+
const sourceLineSegment = lineSegmentList[i], rectangle = Rectangle.fromByLineSegment(sourceLineSegment, this.width * 2, false, -0.01), ids = quadtree.queryRect(rectangle).map((i2) => i2.userData).filter((index2) => index2 !== i);
|
|
1677
|
+
ids.forEach((id) => {
|
|
1678
|
+
try {
|
|
1679
|
+
if (visited.has(`${i}-${id}`) || visited.has(`${id}-${i}`)) return;
|
|
1680
|
+
const res = this.projectionAnalysis(id, i, sourceLineSegment, lineSegmentList);
|
|
1681
|
+
if (res) resultList.push(res);
|
|
1682
|
+
visited.add(`${i}-${id}`);
|
|
1683
|
+
} catch (error) {
|
|
1684
|
+
}
|
|
1685
|
+
});
|
|
1686
|
+
});
|
|
1687
|
+
this.appendLineSegmentList.length = 0;
|
|
1688
|
+
resultList.forEach(this.createRectangle.bind(this));
|
|
1689
|
+
this.resultList = [];
|
|
1690
|
+
}
|
|
1691
|
+
/** 线段投影分析
|
|
1692
|
+
* @param index
|
|
1693
|
+
* @param sourceLineSegment
|
|
1694
|
+
* @param lineSegmentList
|
|
1695
|
+
* @returns
|
|
1696
|
+
*/
|
|
1697
|
+
projectionAnalysis(index2, sourceIndex, sourceLineSegment, lineSegmentList) {
|
|
1698
|
+
const temLineSegment = lineSegmentList[index2], direct = sourceLineSegment.direction(), temDirect = temLineSegment.direction(), angle = direct.angleBetween(temDirect) / (Math.PI / 180);
|
|
1699
|
+
if (angle < this.errorAngle || angle > 180 - this.errorAngle) {
|
|
1700
|
+
let data;
|
|
1701
|
+
const p1 = temLineSegment.projectLineSegment(sourceLineSegment), p2 = sourceLineSegment.projectLineSegment(temLineSegment), d1 = p1.direction(), d2 = p2.direction();
|
|
1702
|
+
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) {
|
|
1703
|
+
p1.points = [p1.points[1], p1.points[0]];
|
|
1704
|
+
}
|
|
1705
|
+
if (p1.getLength() > p2.getLength()) {
|
|
1706
|
+
data = {
|
|
1707
|
+
target: temLineSegment,
|
|
1708
|
+
targetIndex: index2,
|
|
1709
|
+
source: sourceLineSegment,
|
|
1710
|
+
sourceIndex,
|
|
1711
|
+
project: p1,
|
|
1712
|
+
project2: p2
|
|
1713
|
+
};
|
|
1714
|
+
} else {
|
|
1715
|
+
data = {
|
|
1716
|
+
target: sourceLineSegment,
|
|
1717
|
+
targetIndex: sourceIndex,
|
|
1718
|
+
source: temLineSegment,
|
|
1719
|
+
sourceIndex: index2,
|
|
1720
|
+
project: p2,
|
|
1721
|
+
project2: p1
|
|
1722
|
+
};
|
|
1723
|
+
}
|
|
1724
|
+
if (!data || data.project.getLength() < 0.01) return;
|
|
1725
|
+
return data;
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
class DxfSystem extends ComponentManager {
|
|
1730
|
+
Dxf;
|
|
1731
|
+
Variable;
|
|
1732
|
+
wallWidth;
|
|
1733
|
+
environment;
|
|
1734
|
+
/** 构造函数
|
|
1735
|
+
* @param wallWidth 输出墙壁厚度,该墙壁厚度不受缩放影响
|
|
1736
|
+
* @param scale 原始数据缩放比例
|
|
1737
|
+
*/
|
|
1738
|
+
constructor(wallWidth = 0.1, scale = 1) {
|
|
1739
|
+
super();
|
|
1740
|
+
this.environment = typeof window !== "undefined" ? "browser" : typeof global !== "undefined" ? "node" : "unknown";
|
|
1741
|
+
this.wallWidth = wallWidth;
|
|
1742
|
+
this.Dxf = new Dxf(this.wallWidth, scale);
|
|
1743
|
+
this.Variable = new Variable();
|
|
1744
|
+
this.addComponent(this.Variable);
|
|
1745
|
+
this.addComponent(this.Dxf);
|
|
1746
|
+
this.addComponent(new LineAnalysis());
|
|
1747
|
+
}
|
|
1748
|
+
usePlugin(plugin) {
|
|
1749
|
+
if (typeof plugin === "function") plugin.call(this, this);
|
|
1750
|
+
return this;
|
|
1751
|
+
}
|
|
1752
|
+
destroy() {
|
|
1753
|
+
this.components.forEach((com) => {
|
|
1754
|
+
this.removeComponent(com);
|
|
1755
|
+
com.destroy();
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
const exporter = new OBJExporter();
|
|
984
1760
|
function lineSqueezing(p1, p2, width = 0.1) {
|
|
985
1761
|
const normal = p2.normal(p1);
|
|
986
1762
|
const pDirect = p2.direction(p1).mutiplyScalar(width * 0.5);
|
|
@@ -1008,8 +1784,8 @@ class WhiteModel extends Component {
|
|
|
1008
1784
|
// 原始数据白模
|
|
1009
1785
|
originalWhiteMode = new THREE.Group();
|
|
1010
1786
|
onAddFromParent(parent) {
|
|
1011
|
-
this.Dxf = parent.
|
|
1012
|
-
this.Variable = parent.
|
|
1787
|
+
this.Dxf = parent.findComponentByName("Dxf");
|
|
1788
|
+
this.Variable = parent.findComponentByName("Variable");
|
|
1013
1789
|
this.originalWhiteMode.visible = false;
|
|
1014
1790
|
this.Dxf?.addEventListener("lineOffset", () => {
|
|
1015
1791
|
this.updateModel();
|
|
@@ -1030,7 +1806,7 @@ class WhiteModel extends Component {
|
|
|
1030
1806
|
bevelSize: 0
|
|
1031
1807
|
});
|
|
1032
1808
|
const mesh = new THREE.Mesh(geometry);
|
|
1033
|
-
mesh.material = new THREE.
|
|
1809
|
+
mesh.material = new THREE.MeshStandardMaterial({ color: 16777215, transparent: true, opacity: 0.8 });
|
|
1034
1810
|
this.whiteModelGroup.add(mesh);
|
|
1035
1811
|
this.whiteModelGroup.add(
|
|
1036
1812
|
new THREE.LineSegments(new THREE.EdgesGeometry(geometry), new THREE.LineBasicMaterial({ color: 6710886 }))
|
|
@@ -1066,6 +1842,37 @@ class WhiteModel extends Component {
|
|
|
1066
1842
|
whiteModelGroup: this.whiteModelGroup
|
|
1067
1843
|
});
|
|
1068
1844
|
}
|
|
1845
|
+
toOBJ() {
|
|
1846
|
+
return new Promise((resolve) => {
|
|
1847
|
+
resolve(exporter.parse(this.whiteModelGroup));
|
|
1848
|
+
});
|
|
1849
|
+
}
|
|
1850
|
+
async toBlob() {
|
|
1851
|
+
const buffer = await this.toOBJ();
|
|
1852
|
+
if (buffer) {
|
|
1853
|
+
return new Blob([buffer], { type: "application/octet-stream" });
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
async download(filename) {
|
|
1857
|
+
if (typeof window !== "undefined") {
|
|
1858
|
+
const blob = await this.toBlob();
|
|
1859
|
+
if (!blob) return;
|
|
1860
|
+
const a = document.createElement("a");
|
|
1861
|
+
a.href = URL.createObjectURL(blob);
|
|
1862
|
+
a.download = filename;
|
|
1863
|
+
a.click();
|
|
1864
|
+
} else if (typeof global !== "undefined") {
|
|
1865
|
+
const buffer = await this.toOBJ();
|
|
1866
|
+
if (buffer) {
|
|
1867
|
+
const packageName = "fs";
|
|
1868
|
+
const { default: fs } = await import(
|
|
1869
|
+
/* @vite-ignore */
|
|
1870
|
+
packageName
|
|
1871
|
+
);
|
|
1872
|
+
fs.writeFileSync(filename, buffer);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1069
1876
|
}
|
|
1070
1877
|
class DetailsPoint extends Component {
|
|
1071
1878
|
Dxf = null;
|
|
@@ -1075,8 +1882,8 @@ class DetailsPoint extends Component {
|
|
|
1075
1882
|
raylines = [];
|
|
1076
1883
|
data = [];
|
|
1077
1884
|
onAddFromParent(parent) {
|
|
1078
|
-
this.Dxf = parent.
|
|
1079
|
-
this.Variable = parent.
|
|
1885
|
+
this.Dxf = parent.findComponentByName("Dxf");
|
|
1886
|
+
this.Variable = parent.findComponentByName("Variable");
|
|
1080
1887
|
this.Dxf?.addEventListener("setDta", () => {
|
|
1081
1888
|
this.updateModel();
|
|
1082
1889
|
});
|
|
@@ -1085,7 +1892,22 @@ class DetailsPoint extends Component {
|
|
|
1085
1892
|
* 设置值
|
|
1086
1893
|
* @param data
|
|
1087
1894
|
*/
|
|
1088
|
-
set(data) {
|
|
1895
|
+
async set(data) {
|
|
1896
|
+
if (typeof data === "string") {
|
|
1897
|
+
if (typeof global !== "undefined") {
|
|
1898
|
+
const packageName = "fs";
|
|
1899
|
+
const { default: fs } = await import(
|
|
1900
|
+
/* @vite-ignore */
|
|
1901
|
+
packageName
|
|
1902
|
+
);
|
|
1903
|
+
const buffer = fs.readFileSync(data);
|
|
1904
|
+
const json = JSON.parse(buffer.toString("utf-8"));
|
|
1905
|
+
this.set(json);
|
|
1906
|
+
return;
|
|
1907
|
+
} else {
|
|
1908
|
+
throw new Error("非node环境不允许使用路径");
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1089
1911
|
this.data = data;
|
|
1090
1912
|
this.updateModel();
|
|
1091
1913
|
}
|
|
@@ -1111,7 +1933,7 @@ class DetailsPoint extends Component {
|
|
|
1111
1933
|
if (this._timer) clearTimeout(this._timer);
|
|
1112
1934
|
this._timer = setTimeout(() => {
|
|
1113
1935
|
this._timer = null;
|
|
1114
|
-
const whiteModel = this.parent?.
|
|
1936
|
+
const whiteModel = this.parent?.findComponentByName("WhiteModel");
|
|
1115
1937
|
this.raylines.length = 0;
|
|
1116
1938
|
this.desPoints.length = 0;
|
|
1117
1939
|
this.data.forEach((item) => {
|
|
@@ -1151,14 +1973,14 @@ class DxfLineModel extends Component {
|
|
|
1151
1973
|
dxfDoorsLineModel = new THREE.LineSegments();
|
|
1152
1974
|
dxfModelGroup = new THREE.Group();
|
|
1153
1975
|
onAddFromParent(parent) {
|
|
1154
|
-
const dxf = parent.
|
|
1976
|
+
const dxf = parent.findComponentByName("Dxf");
|
|
1155
1977
|
this.dxfModelGroup.add(this.dxfLineModel);
|
|
1156
1978
|
this.dxfModelGroup.add(this.dxfDoorsLineModel);
|
|
1157
1979
|
this.dxfDoorsLineModel.material = new THREE.LineBasicMaterial({ color: 16776960, vertexColors: true });
|
|
1158
1980
|
dxf?.addEventListener("lineOffset", () => this.updateMode());
|
|
1159
1981
|
}
|
|
1160
1982
|
updateMode() {
|
|
1161
|
-
const dxf = this.parent?.
|
|
1983
|
+
const dxf = this.parent?.findComponentByName("Dxf");
|
|
1162
1984
|
this.dxfLineModel.clear();
|
|
1163
1985
|
const dxfArray = dxf.to3DArray(1 / dxf.scale);
|
|
1164
1986
|
this.dxfLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(dxfArray, 3, true));
|
|
@@ -1167,18 +1989,33 @@ class DxfLineModel extends Component {
|
|
|
1167
1989
|
this.dxfDoorsLineModel.geometry = new THREE.BufferGeometry().setAttribute("position", new THREE.BufferAttribute(doorsArray, 3, true)).setAttribute("color", new THREE.BufferAttribute(doorsColorArray, 3));
|
|
1168
1990
|
}
|
|
1169
1991
|
}
|
|
1170
|
-
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1992
|
+
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1171
1993
|
__proto__: null,
|
|
1172
1994
|
DetailsPoint,
|
|
1173
1995
|
DxfLineModel,
|
|
1174
1996
|
WhiteModel
|
|
1175
1997
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
1176
|
-
function
|
|
1998
|
+
function ModelDataPlugin(dxfSystem) {
|
|
1177
1999
|
dxfSystem.addComponent(new DxfLineModel());
|
|
1178
2000
|
dxfSystem.addComponent(new WhiteModel());
|
|
1179
2001
|
dxfSystem.addComponent(new DetailsPoint());
|
|
1180
2002
|
}
|
|
2003
|
+
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
2004
|
+
__proto__: null,
|
|
2005
|
+
ModelDataPlugin,
|
|
2006
|
+
components: index$1
|
|
2007
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
2008
|
+
function loadRenderPlugin() {
|
|
2009
|
+
return import("./index2.js");
|
|
2010
|
+
}
|
|
1181
2011
|
export {
|
|
1182
|
-
|
|
1183
|
-
|
|
2012
|
+
Box2 as B,
|
|
2013
|
+
Component as C,
|
|
2014
|
+
DxfSystem as D,
|
|
2015
|
+
ModelDataPlugin as M,
|
|
2016
|
+
Point as P,
|
|
2017
|
+
Variable as V,
|
|
2018
|
+
DetailsPoint as a,
|
|
2019
|
+
index as i,
|
|
2020
|
+
loadRenderPlugin as l
|
|
1184
2021
|
};
|