build-dxf 0.1.95 → 0.1.97
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,21 @@ class AlignToParallelSegments {
|
|
|
19285
19321
|
* @param lines
|
|
19286
19322
|
* @returns
|
|
19287
19323
|
*/
|
|
19288
|
-
static align(lines, esp = 0.05, gap = 0.
|
|
19289
|
-
const axisLine = lines
|
|
19324
|
+
static align(lines, esp = 0.05, gap = 0.05) {
|
|
19325
|
+
const axisLine = lines.find((line) => line.length() > 0.1), 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);
|
|
19294
19330
|
const groups2 = this.group(verticalLines, axisLineV, axisLine, esp, gap);
|
|
19295
19331
|
verticalLines = this.fittingAlignment(groups2, pllLines);
|
|
19332
|
+
pllLines = pllLines.filter((line) => line.length() > 1e-6);
|
|
19296
19333
|
return [
|
|
19297
19334
|
...pllLines,
|
|
19298
19335
|
...verticalLines
|
|
19299
19336
|
];
|
|
19300
19337
|
}
|
|
19301
19338
|
}
|
|
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
19339
|
function shortDistanceLink(lines, radius = 0.1) {
|
|
19435
19340
|
const dpSet = findDiscretePoint(lines.filter((line) => !line.userData.isDoor)), pointVirtualGrid = createPointSpatialHash(dpSet.map((v2) => v2)), appendLines = [], visited = /* @__PURE__ */ new Set();
|
|
19436
19341
|
const getWeight2 = (target, point2, line) => {
|
|
@@ -19564,7 +19469,6 @@ function correction(lines, targettLine, option) {
|
|
|
19564
19469
|
}
|
|
19565
19470
|
new WallInsertObject(newLines).recomputed().merge();
|
|
19566
19471
|
newLines = removeDangline(newLines, 0.15, true);
|
|
19567
|
-
newLines = linesSmoothing(newLines);
|
|
19568
19472
|
newLines.push(...otherLines);
|
|
19569
19473
|
return newLines.filter((line) => line.length() > 1e-9);
|
|
19570
19474
|
}
|
|
@@ -22522,7 +22426,6 @@ async function buildJson(opt) {
|
|
|
22522
22426
|
if (opt.axisAlignCorr !== false) {
|
|
22523
22427
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.AxisAlignCorr);
|
|
22524
22428
|
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.RemoveShortDoubleWall);
|
|
22525
|
-
dxfSystem.Dxf.addPreProcessor(PRE_PROCESSOR.DoubleWallAlignment);
|
|
22526
22429
|
}
|
|
22527
22430
|
if (trajectory2) {
|
|
22528
22431
|
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
|