build-dxf 0.1.95 → 0.1.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
package/src/build.js
CHANGED
|
@@ -1926,6 +1926,15 @@ class PointSpatialHash {
|
|
|
1926
1926
|
if (list.size === 1) return [...list][0];
|
|
1927
1927
|
}
|
|
1928
1928
|
}
|
|
1929
|
+
/** 通过点快速创建
|
|
1930
|
+
* @param lines
|
|
1931
|
+
* @returns
|
|
1932
|
+
*/
|
|
1933
|
+
static from(points) {
|
|
1934
|
+
const psh = new PointSpatialHash();
|
|
1935
|
+
points.forEach((p2, index2) => psh.insert(p2, index2));
|
|
1936
|
+
return psh;
|
|
1937
|
+
}
|
|
1929
1938
|
/** 通过线段快速创建
|
|
1930
1939
|
* @param lines
|
|
1931
1940
|
* @returns
|
|
@@ -2989,6 +2998,9 @@ class UnionFindSet {
|
|
|
2989
2998
|
}
|
|
2990
2999
|
}
|
|
2991
3000
|
class LineSegmentUtils {
|
|
3001
|
+
clone(lines) {
|
|
3002
|
+
return lines.map((line) => line.clone());
|
|
3003
|
+
}
|
|
2992
3004
|
/** 获取最长线段索引
|
|
2993
3005
|
* @param lines
|
|
2994
3006
|
*/
|
|
@@ -19178,15 +19190,27 @@ function removeDangline(lines, len = 0.01, consecutive = false) {
|
|
|
19178
19190
|
return [...defaultLines, ...doorLines];
|
|
19179
19191
|
}
|
|
19180
19192
|
const DELETE_SYMBOL = /* @__PURE__ */ Symbol("DELETE_SYMBOL");
|
|
19181
|
-
const INTERSECT_COUNT = /* @__PURE__ */ Symbol("INTERSECT_COUNT");
|
|
19182
19193
|
function fitting(lines) {
|
|
19183
19194
|
const index2 = LineSegmentUtils.maxLengthLineIndex(lines);
|
|
19184
19195
|
if (index2 === -1) throw Error("未找到最长线段");
|
|
19185
19196
|
const maxLine = lines[index2], center = LineSegmentUtils.getLinesCenter(lines), direct = maxLine.direction(), start = center.clone().add(direct.clone().multiplyScalar(-1)), end = center.clone().add(direct.clone().multiplyScalar(1));
|
|
19186
19197
|
return new LineSegment(start, end);
|
|
19187
19198
|
}
|
|
19188
|
-
function
|
|
19189
|
-
|
|
19199
|
+
function sortByAxis(lines, axis) {
|
|
19200
|
+
lines.sort((a2, b4) => {
|
|
19201
|
+
const sa2 = axis.projectPointValue(a2.start);
|
|
19202
|
+
const sb = axis.projectPointValue(b4.start);
|
|
19203
|
+
if (Math.abs(sa2 - sb) < 1e-6) {
|
|
19204
|
+
const aLen = axis.projectPointValue(a2.end) - sa2;
|
|
19205
|
+
const bLen = axis.projectPointValue(b4.end) - sb;
|
|
19206
|
+
return bLen - aLen;
|
|
19207
|
+
}
|
|
19208
|
+
return sa2 - sb;
|
|
19209
|
+
});
|
|
19210
|
+
return lines;
|
|
19211
|
+
}
|
|
19212
|
+
function layoutDesign(lines, axis, intersectPoints) {
|
|
19213
|
+
let blocks = lines.map((line, index2) => {
|
|
19190
19214
|
const sv = axis.projectPointValue(line.start), ev = axis.projectPointValue(line.end), range = sv < ev ? [sv, ev] : [ev, sv];
|
|
19191
19215
|
return { range, index: index2, rangeSize: range[1] - range[0] };
|
|
19192
19216
|
});
|
|
@@ -19199,10 +19223,10 @@ function layoutDesign(lines, axis) {
|
|
|
19199
19223
|
const block = blocks[i], line = lines[block.index], ranges = [];
|
|
19200
19224
|
let start = block.range[0];
|
|
19201
19225
|
for (let j = i + 1; j < blocks.length; j++) {
|
|
19202
|
-
const nextBlock = blocks[j]
|
|
19226
|
+
const nextBlock = blocks[j];
|
|
19203
19227
|
const overlap = Math.min(block.range[1], nextBlock.range[1]) - Math.max(block.range[0], nextBlock.range[0]);
|
|
19204
19228
|
if (overlap < 0) break;
|
|
19205
|
-
|
|
19229
|
+
if (nextBlock.range[0] > start) {
|
|
19206
19230
|
ranges.push([start, nextBlock.range[0]]);
|
|
19207
19231
|
}
|
|
19208
19232
|
start = Math.max(start, nextBlock.range[1]);
|
|
@@ -19210,8 +19234,10 @@ function layoutDesign(lines, axis) {
|
|
|
19210
19234
|
if (start < block.range[1]) ranges.push([start, block.range[1]]);
|
|
19211
19235
|
for (let j = 0; j < ranges.length; j++) {
|
|
19212
19236
|
const range = ranges[j], start2 = axis.pointAt(range[0]), end = axis.pointAt(range[1]);
|
|
19213
|
-
if (j === 0)
|
|
19214
|
-
|
|
19237
|
+
if (j === 0) {
|
|
19238
|
+
line.set(start2, end);
|
|
19239
|
+
newLines.push(line);
|
|
19240
|
+
} else {
|
|
19215
19241
|
let newLine = line.clone();
|
|
19216
19242
|
newLine.set(start2, end);
|
|
19217
19243
|
newLines.push(newLine);
|
|
@@ -19219,6 +19245,17 @@ function layoutDesign(lines, axis) {
|
|
|
19219
19245
|
}
|
|
19220
19246
|
if (ranges.length === 0) line.currentData[DELETE_SYMBOL] = true;
|
|
19221
19247
|
}
|
|
19248
|
+
sortByAxis(newLines, axis);
|
|
19249
|
+
const psh = PointSpatialHash.from(intersectPoints);
|
|
19250
|
+
for (let i = 0; i < newLines.length - 1; i++) {
|
|
19251
|
+
const line = newLines[i];
|
|
19252
|
+
if (psh.queryPoint(line.end).length !== 0) continue;
|
|
19253
|
+
const nextLine = newLines[i + 1];
|
|
19254
|
+
nextLine.start.copy(line.start);
|
|
19255
|
+
line.currentData[DELETE_SYMBOL] = true;
|
|
19256
|
+
mergeLineUserData(nextLine, line);
|
|
19257
|
+
}
|
|
19258
|
+
lines.length = 0;
|
|
19222
19259
|
lines.push(...newLines);
|
|
19223
19260
|
return lines;
|
|
19224
19261
|
}
|
|
@@ -19258,21 +19295,20 @@ class AlignToParallelSegments {
|
|
|
19258
19295
|
const group = groups[i];
|
|
19259
19296
|
if (group.length <= 1) continue;
|
|
19260
19297
|
const axisLine = fitting(group);
|
|
19298
|
+
const points = [];
|
|
19261
19299
|
for (let j = 0; j < group.length; j++) {
|
|
19262
19300
|
const line = group[j];
|
|
19263
|
-
let intersectCount = 0;
|
|
19264
19301
|
line.points.forEach((p2) => {
|
|
19265
19302
|
const intersectPoints = grid.queryCircle(p2, 1e-4).map((result) => result.point);
|
|
19266
|
-
axisLine.
|
|
19303
|
+
const pv = axisLine.projectPointValue(p2);
|
|
19304
|
+
axisLine.pointAt(pv, p2);
|
|
19267
19305
|
intersectPoints.forEach((point2) => point2.copy(p2));
|
|
19268
|
-
|
|
19306
|
+
points.push(...intersectPoints);
|
|
19269
19307
|
});
|
|
19270
|
-
line.currentData[INTERSECT_COUNT] = intersectCount;
|
|
19271
19308
|
}
|
|
19272
|
-
layoutDesign(group, axisLine);
|
|
19309
|
+
layoutDesign(group, axisLine, points);
|
|
19273
19310
|
}
|
|
19274
19311
|
return groups.flat().filter((line) => {
|
|
19275
|
-
delete line.currentData[INTERSECT_COUNT];
|
|
19276
19312
|
if (line.length() < 1e-9) return false;
|
|
19277
19313
|
if (line.currentData[DELETE_SYMBOL]) {
|
|
19278
19314
|
delete line.currentData[DELETE_SYMBOL];
|
|
@@ -19285,152 +19321,23 @@ class AlignToParallelSegments {
|
|
|
19285
19321
|
* @param lines
|
|
19286
19322
|
* @returns
|
|
19287
19323
|
*/
|
|
19288
|
-
static align(lines, esp = 0.05, gap = 0.
|
|
19324
|
+
static align(lines, esp = 0.05, gap = 0.05) {
|
|
19289
19325
|
const axisLine = lines[0], axisLineV = axisLine.clone().rotate(Math.PI * 0.5, axisLine.center);
|
|
19290
19326
|
let [pllLines, verticalLines] = LineSegmentUtils.groupByParallelToAxis(lines, axisLine);
|
|
19291
19327
|
const groups = this.group(pllLines, axisLine, axisLineV, esp, gap);
|
|
19292
19328
|
pllLines = this.fittingAlignment(groups, verticalLines);
|
|
19293
|
-
verticalLines = verticalLines.filter((line) => line.length() > 1e-
|
|
19329
|
+
verticalLines = verticalLines.filter((line) => line.length() > 1e-6);
|
|
19330
|
+
TEST = true;
|
|
19294
19331
|
const groups2 = this.group(verticalLines, axisLineV, axisLine, esp, gap);
|
|
19295
19332
|
verticalLines = this.fittingAlignment(groups2, pllLines);
|
|
19333
|
+
TEST = false;
|
|
19334
|
+
pllLines = pllLines.filter((line) => line.length() > 1e-6);
|
|
19296
19335
|
return [
|
|
19297
19336
|
...pllLines,
|
|
19298
19337
|
...verticalLines
|
|
19299
19338
|
];
|
|
19300
19339
|
}
|
|
19301
19340
|
}
|
|
19302
|
-
function getNextPoint(point2, line, next, width) {
|
|
19303
|
-
if (next.length === 0) {
|
|
19304
|
-
const direct = point2.directionFrom(line.getAnotherPoint(point2));
|
|
19305
|
-
return point2.clone().add(direct.multiplyScalar(width));
|
|
19306
|
-
}
|
|
19307
|
-
const p2 = next[0].userData.projectPoint(point2, false);
|
|
19308
|
-
if (!p2) return false;
|
|
19309
|
-
return p2;
|
|
19310
|
-
}
|
|
19311
|
-
function stepElimination(lineSegments, findMinWidth = 0.1, onMerge) {
|
|
19312
|
-
const grid = createPointSpatialHash(lineSegments);
|
|
19313
|
-
function getIntersInfo(line, point2) {
|
|
19314
|
-
const intersList = grid.queryCircle(point2, 1e-4).filter((item) => item.point !== point2);
|
|
19315
|
-
if (intersList.length == 0) return;
|
|
19316
|
-
let firstLine = null, firstPoint = null;
|
|
19317
|
-
let count = 0;
|
|
19318
|
-
let parallel2 = new PvgList();
|
|
19319
|
-
for (let i = 0; i < intersList.length; i++) {
|
|
19320
|
-
const res = intersList[i];
|
|
19321
|
-
if (line.isPerpendicularTo(res.userData, 10)) {
|
|
19322
|
-
count++;
|
|
19323
|
-
firstLine = res.userData;
|
|
19324
|
-
firstPoint = res.point;
|
|
19325
|
-
} else {
|
|
19326
|
-
parallel2.push(res);
|
|
19327
|
-
}
|
|
19328
|
-
}
|
|
19329
|
-
if (count !== 1) return;
|
|
19330
|
-
if (!firstLine || !firstPoint) return;
|
|
19331
|
-
const firstOtherPoint = firstLine.getAnotherPoint(firstPoint);
|
|
19332
|
-
const nextResult = grid.queryCircle(firstOtherPoint, 1e-4).filter((item) => item.point !== firstOtherPoint);
|
|
19333
|
-
return {
|
|
19334
|
-
length: firstLine.length(),
|
|
19335
|
-
firstLine,
|
|
19336
|
-
firstPoint,
|
|
19337
|
-
firstOtherPoint,
|
|
19338
|
-
direction: firstOtherPoint.directionFrom(firstPoint),
|
|
19339
|
-
nextOnlyVertical: nextResult.every((d2) => d2.userData.isPerpendicularTo(firstLine)),
|
|
19340
|
-
next: nextResult,
|
|
19341
|
-
parallel: parallel2
|
|
19342
|
-
};
|
|
19343
|
-
}
|
|
19344
|
-
const removeLinesSet = /* @__PURE__ */ new Set();
|
|
19345
|
-
for (let i = 0; i < lineSegments.length; i++) {
|
|
19346
|
-
const line = lineSegments[i];
|
|
19347
|
-
if (removeLinesSet.has(line)) continue;
|
|
19348
|
-
const len = line.length();
|
|
19349
|
-
if (len > findMinWidth) continue;
|
|
19350
|
-
const startInfo = getIntersInfo(line, line.start);
|
|
19351
|
-
if (!startInfo) continue;
|
|
19352
|
-
const endInfo = getIntersInfo(line, line.end);
|
|
19353
|
-
if (!endInfo) continue;
|
|
19354
|
-
const angle = startInfo.direction.angle(endInfo.direction, { unit: "degree", range: "180" });
|
|
19355
|
-
if (angle < 170) continue;
|
|
19356
|
-
if (!startInfo.nextOnlyVertical && !endInfo.nextOnlyVertical) continue;
|
|
19357
|
-
let mainInfo = startInfo, secondaryInfo = endInfo;
|
|
19358
|
-
if (startInfo.nextOnlyVertical && endInfo.nextOnlyVertical) {
|
|
19359
|
-
if (startInfo.length < endInfo.length) {
|
|
19360
|
-
mainInfo = endInfo;
|
|
19361
|
-
secondaryInfo = startInfo;
|
|
19362
|
-
}
|
|
19363
|
-
} else if (startInfo.nextOnlyVertical) {
|
|
19364
|
-
mainInfo = endInfo;
|
|
19365
|
-
secondaryInfo = startInfo;
|
|
19366
|
-
}
|
|
19367
|
-
const parallel2 = startInfo.parallel.concat(endInfo.parallel);
|
|
19368
|
-
const newPoint = getNextPoint(mainInfo.firstPoint, mainInfo.firstLine, secondaryInfo.next, secondaryInfo.length);
|
|
19369
|
-
if (!newPoint) continue;
|
|
19370
|
-
removeLinesSet.add(line);
|
|
19371
|
-
line.points.forEach((p2) => grid.remove(p2));
|
|
19372
|
-
if (parallel2.length === 0) {
|
|
19373
|
-
const oldLine = mainInfo.firstLine.clone();
|
|
19374
|
-
mainInfo.firstPoint.copy(newPoint);
|
|
19375
|
-
secondaryInfo.next.forEach((d2) => d2.point.copy(newPoint));
|
|
19376
|
-
removeLinesSet.add(secondaryInfo.firstLine);
|
|
19377
|
-
secondaryInfo.firstLine.points.forEach((p2) => grid.remove(p2));
|
|
19378
|
-
mainInfo.firstLine.points.forEach((p2) => grid.update(p2));
|
|
19379
|
-
if (typeof onMerge === "function") onMerge(mainInfo.firstLine, line, secondaryInfo.firstLine, oldLine);
|
|
19380
|
-
} else {
|
|
19381
|
-
secondaryInfo.firstPoint.copy(mainInfo.firstPoint);
|
|
19382
|
-
secondaryInfo.firstOtherPoint.copy(newPoint);
|
|
19383
|
-
secondaryInfo.next.forEach((d2) => d2.point.copy(newPoint));
|
|
19384
|
-
startInfo.parallel.concat(endInfo.parallel).forEach((item) => item.point.copy(mainInfo.firstPoint));
|
|
19385
|
-
secondaryInfo.firstLine.points.forEach((p2) => grid.update(p2));
|
|
19386
|
-
secondaryInfo.next.forEach((d2) => grid.update(d2.point));
|
|
19387
|
-
startInfo.parallel.concat(endInfo.parallel).forEach((item) => grid.update(item.point));
|
|
19388
|
-
}
|
|
19389
|
-
}
|
|
19390
|
-
lineSegments = lineSegments.filter((line) => !removeLinesSet.has(line));
|
|
19391
|
-
return lineSegments;
|
|
19392
|
-
}
|
|
19393
|
-
function repetitiveTask(count, callfun) {
|
|
19394
|
-
for (let i = 0; i < count; i++) {
|
|
19395
|
-
callfun(i);
|
|
19396
|
-
}
|
|
19397
|
-
}
|
|
19398
|
-
function stepEliminationMerge(target, _, source, oldLine) {
|
|
19399
|
-
if (source.userData.isDoor) WallInsertObject.addInsertObject(target, {
|
|
19400
|
-
p: source.center.toJson(),
|
|
19401
|
-
width: source.length(),
|
|
19402
|
-
full: false,
|
|
19403
|
-
type: "door",
|
|
19404
|
-
height: source.userData.drawDoorData.height,
|
|
19405
|
-
groundClearance: source.userData.drawDoorData.groundClearance
|
|
19406
|
-
});
|
|
19407
|
-
if (target.userData.isDoor) {
|
|
19408
|
-
delete target.userData.isDoor;
|
|
19409
|
-
WallInsertObject.addInsertObject(target, {
|
|
19410
|
-
p: oldLine.center.toJson(),
|
|
19411
|
-
width: oldLine.length(),
|
|
19412
|
-
full: false,
|
|
19413
|
-
type: "door",
|
|
19414
|
-
height: target.userData.drawDoorData?.height,
|
|
19415
|
-
groundClearance: target.userData.drawDoorData?.groundClearance ?? 0
|
|
19416
|
-
});
|
|
19417
|
-
}
|
|
19418
|
-
WallInsertObject.copyInsertObject(target, source);
|
|
19419
|
-
WallInsertObject.recomputed([target]);
|
|
19420
|
-
}
|
|
19421
|
-
function linesSmoothing(lines, _) {
|
|
19422
|
-
const other = [];
|
|
19423
|
-
lines = lines.filter((line) => {
|
|
19424
|
-
if (line.userData.isBayWindow) {
|
|
19425
|
-
other.push(line);
|
|
19426
|
-
return false;
|
|
19427
|
-
}
|
|
19428
|
-
return true;
|
|
19429
|
-
});
|
|
19430
|
-
repetitiveTask(2, () => lines = stepElimination(lines, 0.1, stepEliminationMerge));
|
|
19431
|
-
WallInsertObject.recomputed(lines);
|
|
19432
|
-
return [...lines, ...other];
|
|
19433
|
-
}
|
|
19434
19341
|
function shortDistanceLink(lines, radius = 0.1) {
|
|
19435
19342
|
const dpSet = findDiscretePoint(lines.filter((line) => !line.userData.isDoor)), pointVirtualGrid = createPointSpatialHash(dpSet.map((v2) => v2)), appendLines = [], visited = /* @__PURE__ */ new Set();
|
|
19436
19343
|
const getWeight2 = (target, point2, line) => {
|
|
@@ -19564,7 +19471,6 @@ function correction(lines, targettLine, option) {
|
|
|
19564
19471
|
}
|
|
19565
19472
|
new WallInsertObject(newLines).recomputed().merge();
|
|
19566
19473
|
newLines = removeDangline(newLines, 0.15, true);
|
|
19567
|
-
newLines = linesSmoothing(newLines);
|
|
19568
19474
|
newLines.push(...otherLines);
|
|
19569
19475
|
return newLines.filter((line) => line.length() > 1e-9);
|
|
19570
19476
|
}
|
|
@@ -22522,7 +22428,6 @@ async function buildJson(opt) {
|
|
|
22522
22428
|
if (opt.axisAlignCorr !== false) {
|
|
22523
22429
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
|
|
22524
22430
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.RemoveShortDoubleWall);
|
|
22525
|
-
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoubleWallAlignment);
|
|
22526
22431
|
}
|
|
22527
22432
|
if (trajectory2) {
|
|
22528
22433
|
if (typeof trajectory2 === "string") {
|
|
@@ -108,6 +108,11 @@ export declare class PointSpatialHash<T = Record<string, any>> {
|
|
|
108
108
|
/** 查找第一个游离的点
|
|
109
109
|
*/
|
|
110
110
|
getFreePointFirst(): Target<T> | undefined;
|
|
111
|
+
/** 通过点快速创建
|
|
112
|
+
* @param lines
|
|
113
|
+
* @returns
|
|
114
|
+
*/
|
|
115
|
+
static from(points: Point[]): PointSpatialHash<number>;
|
|
111
116
|
/** 通过线段快速创建
|
|
112
117
|
* @param lines
|
|
113
118
|
* @returns
|