@ifc-lite/drawing-2d 1.4.0
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/LICENSE +373 -0
- package/dist/drawing-generator.d.ts +80 -0
- package/dist/drawing-generator.d.ts.map +1 -0
- package/dist/drawing-generator.js +281 -0
- package/dist/drawing-generator.js.map +1 -0
- package/dist/edge-extractor.d.ts +47 -0
- package/dist/edge-extractor.d.ts.map +1 -0
- package/dist/edge-extractor.js +204 -0
- package/dist/edge-extractor.js.map +1 -0
- package/dist/gpu-section-cutter.d.ts +42 -0
- package/dist/gpu-section-cutter.d.ts.map +1 -0
- package/dist/gpu-section-cutter.js +405 -0
- package/dist/gpu-section-cutter.js.map +1 -0
- package/dist/graphic-overrides/index.d.ts +10 -0
- package/dist/graphic-overrides/index.d.ts.map +1 -0
- package/dist/graphic-overrides/index.js +8 -0
- package/dist/graphic-overrides/index.js.map +1 -0
- package/dist/graphic-overrides/presets.d.ts +22 -0
- package/dist/graphic-overrides/presets.d.ts.map +1 -0
- package/dist/graphic-overrides/presets.js +283 -0
- package/dist/graphic-overrides/presets.js.map +1 -0
- package/dist/graphic-overrides/rule-engine.d.ts +64 -0
- package/dist/graphic-overrides/rule-engine.d.ts.map +1 -0
- package/dist/graphic-overrides/rule-engine.js +438 -0
- package/dist/graphic-overrides/rule-engine.js.map +1 -0
- package/dist/graphic-overrides/types.d.ts +200 -0
- package/dist/graphic-overrides/types.d.ts.map +1 -0
- package/dist/graphic-overrides/types.js +5 -0
- package/dist/graphic-overrides/types.js.map +1 -0
- package/dist/hatch-generator.d.ts +76 -0
- package/dist/hatch-generator.d.ts.map +1 -0
- package/dist/hatch-generator.js +282 -0
- package/dist/hatch-generator.js.map +1 -0
- package/dist/hidden-line.d.ts +64 -0
- package/dist/hidden-line.d.ts.map +1 -0
- package/dist/hidden-line.js +318 -0
- package/dist/hidden-line.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/line-merger.d.ts +35 -0
- package/dist/line-merger.d.ts.map +1 -0
- package/dist/line-merger.js +265 -0
- package/dist/line-merger.js.map +1 -0
- package/dist/math.d.ts +90 -0
- package/dist/math.d.ts.map +1 -0
- package/dist/math.js +284 -0
- package/dist/math.js.map +1 -0
- package/dist/openings/index.d.ts +7 -0
- package/dist/openings/index.d.ts.map +1 -0
- package/dist/openings/index.js +10 -0
- package/dist/openings/index.js.map +1 -0
- package/dist/openings/opening-filter.d.ts +61 -0
- package/dist/openings/opening-filter.d.ts.map +1 -0
- package/dist/openings/opening-filter.js +244 -0
- package/dist/openings/opening-filter.js.map +1 -0
- package/dist/openings/opening-relationship-builder.d.ts +35 -0
- package/dist/openings/opening-relationship-builder.d.ts.map +1 -0
- package/dist/openings/opening-relationship-builder.js +121 -0
- package/dist/openings/opening-relationship-builder.js.map +1 -0
- package/dist/openings/opening-utils.d.ts +55 -0
- package/dist/openings/opening-utils.d.ts.map +1 -0
- package/dist/openings/opening-utils.js +128 -0
- package/dist/openings/opening-utils.js.map +1 -0
- package/dist/polygon-builder.d.ts +62 -0
- package/dist/polygon-builder.d.ts.map +1 -0
- package/dist/polygon-builder.js +261 -0
- package/dist/polygon-builder.js.map +1 -0
- package/dist/section-cutter.d.ts +49 -0
- package/dist/section-cutter.d.ts.map +1 -0
- package/dist/section-cutter.js +220 -0
- package/dist/section-cutter.js.map +1 -0
- package/dist/sheet/frame-renderer.d.ts +28 -0
- package/dist/sheet/frame-renderer.d.ts.map +1 -0
- package/dist/sheet/frame-renderer.js +199 -0
- package/dist/sheet/frame-renderer.js.map +1 -0
- package/dist/sheet/frame-types.d.ts +57 -0
- package/dist/sheet/frame-types.d.ts.map +1 -0
- package/dist/sheet/frame-types.js +88 -0
- package/dist/sheet/frame-types.js.map +1 -0
- package/dist/sheet/index.d.ts +26 -0
- package/dist/sheet/index.d.ts.map +1 -0
- package/dist/sheet/index.js +12 -0
- package/dist/sheet/index.js.map +1 -0
- package/dist/sheet/paper-sizes.d.ts +36 -0
- package/dist/sheet/paper-sizes.d.ts.map +1 -0
- package/dist/sheet/paper-sizes.js +252 -0
- package/dist/sheet/paper-sizes.js.map +1 -0
- package/dist/sheet/scale-bar-renderer.d.ts +29 -0
- package/dist/sheet/scale-bar-renderer.d.ts.map +1 -0
- package/dist/sheet/scale-bar-renderer.js +287 -0
- package/dist/sheet/scale-bar-renderer.js.map +1 -0
- package/dist/sheet/scale-bar-types.d.ts +82 -0
- package/dist/sheet/scale-bar-types.d.ts.map +1 -0
- package/dist/sheet/scale-bar-types.js +66 -0
- package/dist/sheet/scale-bar-types.js.map +1 -0
- package/dist/sheet/sheet-types.d.ts +84 -0
- package/dist/sheet/sheet-types.d.ts.map +1 -0
- package/dist/sheet/sheet-types.js +77 -0
- package/dist/sheet/sheet-types.js.map +1 -0
- package/dist/sheet/title-block-renderer.d.ts +44 -0
- package/dist/sheet/title-block-renderer.d.ts.map +1 -0
- package/dist/sheet/title-block-renderer.js +335 -0
- package/dist/sheet/title-block-renderer.js.map +1 -0
- package/dist/sheet/title-block-types.d.ts +100 -0
- package/dist/sheet/title-block-types.d.ts.map +1 -0
- package/dist/sheet/title-block-types.js +174 -0
- package/dist/sheet/title-block-types.js.map +1 -0
- package/dist/styles.d.ts +77 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +347 -0
- package/dist/styles.js.map +1 -0
- package/dist/styling/index.d.ts +7 -0
- package/dist/styling/index.d.ts.map +1 -0
- package/dist/styling/index.js +10 -0
- package/dist/styling/index.js.map +1 -0
- package/dist/styling/layer-mapping.d.ts +57 -0
- package/dist/styling/layer-mapping.d.ts.map +1 -0
- package/dist/styling/layer-mapping.js +303 -0
- package/dist/styling/layer-mapping.js.map +1 -0
- package/dist/styling/line-styles.d.ts +49 -0
- package/dist/styling/line-styles.d.ts.map +1 -0
- package/dist/styling/line-styles.js +123 -0
- package/dist/styling/line-styles.js.map +1 -0
- package/dist/styling/line-weights.d.ts +61 -0
- package/dist/styling/line-weights.d.ts.map +1 -0
- package/dist/styling/line-weights.js +183 -0
- package/dist/styling/line-weights.js.map +1 -0
- package/dist/svg-exporter.d.ts +63 -0
- package/dist/svg-exporter.d.ts.map +1 -0
- package/dist/svg-exporter.js +278 -0
- package/dist/svg-exporter.js.map +1 -0
- package/dist/symbols/door-symbol.d.ts +82 -0
- package/dist/symbols/door-symbol.d.ts.map +1 -0
- package/dist/symbols/door-symbol.js +390 -0
- package/dist/symbols/door-symbol.js.map +1 -0
- package/dist/symbols/index.d.ts +8 -0
- package/dist/symbols/index.d.ts.map +1 -0
- package/dist/symbols/index.js +11 -0
- package/dist/symbols/index.js.map +1 -0
- package/dist/symbols/symbol-renderer.d.ts +29 -0
- package/dist/symbols/symbol-renderer.d.ts.map +1 -0
- package/dist/symbols/symbol-renderer.js +173 -0
- package/dist/symbols/symbol-renderer.js.map +1 -0
- package/dist/symbols/symbol-utils.d.ts +48 -0
- package/dist/symbols/symbol-utils.d.ts.map +1 -0
- package/dist/symbols/symbol-utils.js +129 -0
- package/dist/symbols/symbol-utils.js.map +1 -0
- package/dist/symbols/window-symbol.d.ts +57 -0
- package/dist/symbols/window-symbol.d.ts.map +1 -0
- package/dist/symbols/window-symbol.js +209 -0
- package/dist/symbols/window-symbol.js.map +1 -0
- package/dist/types.d.ts +443 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +31 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { OpeningRelationshipBuilder } from './opening-relationship-builder';
|
|
5
|
+
/**
|
|
6
|
+
* Build opening relationships from void and fill relationship arrays
|
|
7
|
+
*/
|
|
8
|
+
export function buildOpeningRelationships(voids, fills, entityMetadata, modelIndex = 0) {
|
|
9
|
+
return new OpeningRelationshipBuilder(entityMetadata)
|
|
10
|
+
.addVoidRelationships(voids)
|
|
11
|
+
.addFillRelationships(fills)
|
|
12
|
+
.build(modelIndex);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get all opening IDs for a host element (wall, slab, etc.)
|
|
16
|
+
*/
|
|
17
|
+
export function getOpeningsForHost(relationships, hostId) {
|
|
18
|
+
return relationships.voidedBy.get(hostId) ?? [];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get the filling element (door/window) for an opening
|
|
22
|
+
*/
|
|
23
|
+
export function getFillingElement(relationships, openingId) {
|
|
24
|
+
return relationships.filledBy.get(openingId);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Get opening info by entity ID (works for both opening and filling elements)
|
|
28
|
+
*/
|
|
29
|
+
export function getOpeningInfo(relationships, entityId) {
|
|
30
|
+
return relationships.openingInfo.get(entityId);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Check if an IFC type represents an opening element
|
|
34
|
+
*/
|
|
35
|
+
export function isOpeningElement(ifcType) {
|
|
36
|
+
const upper = ifcType.toUpperCase();
|
|
37
|
+
return (upper === 'IFCOPENINGELEMENT' ||
|
|
38
|
+
upper === 'IFCOPENINGSTANDARDCASE' ||
|
|
39
|
+
upper === 'IFCVOIDINGELEMENT');
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if an IFC type represents a door or window
|
|
43
|
+
*/
|
|
44
|
+
export function isDoorOrWindow(ifcType) {
|
|
45
|
+
const upper = ifcType.toUpperCase();
|
|
46
|
+
return (upper.includes('DOOR') ||
|
|
47
|
+
upper.includes('WINDOW'));
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Check if an IFC type is a host element that can have openings
|
|
51
|
+
*/
|
|
52
|
+
export function isHostElement(ifcType) {
|
|
53
|
+
const upper = ifcType.toUpperCase();
|
|
54
|
+
return (upper.includes('WALL') ||
|
|
55
|
+
upper.includes('SLAB') ||
|
|
56
|
+
upper.includes('ROOF') ||
|
|
57
|
+
upper.includes('FLOOR'));
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get all host element IDs that have openings
|
|
61
|
+
*/
|
|
62
|
+
export function getHostsWithOpenings(relationships) {
|
|
63
|
+
return Array.from(relationships.voidedBy.keys());
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get all door opening infos
|
|
67
|
+
*/
|
|
68
|
+
export function getDoorOpenings(relationships) {
|
|
69
|
+
const result = [];
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
for (const [, info] of relationships.openingInfo) {
|
|
72
|
+
if (info.type === 'door' && !seen.has(info.openingId)) {
|
|
73
|
+
result.push(info);
|
|
74
|
+
seen.add(info.openingId);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get all window opening infos
|
|
81
|
+
*/
|
|
82
|
+
export function getWindowOpenings(relationships) {
|
|
83
|
+
const result = [];
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
for (const [, info] of relationships.openingInfo) {
|
|
86
|
+
if (info.type === 'window' && !seen.has(info.openingId)) {
|
|
87
|
+
result.push(info);
|
|
88
|
+
seen.add(info.openingId);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Filter entity IDs to exclude opening elements
|
|
95
|
+
* Useful for filtering meshes before section cutting
|
|
96
|
+
*/
|
|
97
|
+
export function filterOutOpeningElements(entityIds, relationships) {
|
|
98
|
+
const openingIds = new Set();
|
|
99
|
+
// Collect all opening and filling element IDs
|
|
100
|
+
for (const openingIdList of relationships.voidedBy.values()) {
|
|
101
|
+
for (const id of openingIdList) {
|
|
102
|
+
openingIds.add(id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
for (const fillingId of relationships.filledBy.values()) {
|
|
106
|
+
openingIds.add(fillingId);
|
|
107
|
+
}
|
|
108
|
+
return entityIds.filter((id) => !openingIds.has(id));
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get the entity IDs that should be included in cut lines (hosts only)
|
|
112
|
+
* Excludes opening elements and their filling elements
|
|
113
|
+
*/
|
|
114
|
+
export function getHostEntityIds(allEntityIds, relationships, ifcTypes) {
|
|
115
|
+
const result = [];
|
|
116
|
+
for (const id of allEntityIds) {
|
|
117
|
+
const ifcType = ifcTypes.get(id);
|
|
118
|
+
if (!ifcType)
|
|
119
|
+
continue;
|
|
120
|
+
// Skip opening elements and doors/windows
|
|
121
|
+
if (isOpeningElement(ifcType) || isDoorOrWindow(ifcType)) {
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
result.push(id);
|
|
125
|
+
}
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=opening-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opening-utils.js","sourceRoot":"","sources":["../../src/openings/opening-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polygon Builder - Reconstructs closed polygons from cut line segments
|
|
3
|
+
*
|
|
4
|
+
* Takes the line segments from section cutting and connects them into
|
|
5
|
+
* closed polygon rings, handling:
|
|
6
|
+
* - Multiple disconnected polygons per entity
|
|
7
|
+
* - Holes (inner boundaries)
|
|
8
|
+
* - Floating point tolerance for vertex matching
|
|
9
|
+
*/
|
|
10
|
+
import type { Point2D, CutSegment, DrawingPolygon } from './types';
|
|
11
|
+
export declare class PolygonBuilder {
|
|
12
|
+
/** Tolerance for vertex matching */
|
|
13
|
+
private tolerance;
|
|
14
|
+
constructor(tolerance?: number);
|
|
15
|
+
/**
|
|
16
|
+
* Build polygons from cut segments
|
|
17
|
+
* Groups segments by entity and reconstructs closed loops
|
|
18
|
+
*/
|
|
19
|
+
buildPolygons(segments: CutSegment[]): DrawingPolygon[];
|
|
20
|
+
/**
|
|
21
|
+
* Build polygons for a single entity
|
|
22
|
+
*/
|
|
23
|
+
private buildEntityPolygons;
|
|
24
|
+
/**
|
|
25
|
+
* Build closed loops from segments using a greedy chain-building algorithm
|
|
26
|
+
*/
|
|
27
|
+
private buildLoops;
|
|
28
|
+
/**
|
|
29
|
+
* Build a single closed loop starting from a segment
|
|
30
|
+
*/
|
|
31
|
+
private buildSingleLoop;
|
|
32
|
+
/**
|
|
33
|
+
* Find an unused segment that connects to the given point
|
|
34
|
+
*/
|
|
35
|
+
private findConnectingSegment;
|
|
36
|
+
/**
|
|
37
|
+
* Classify loops as outer boundaries or holes
|
|
38
|
+
* Uses containment testing and area sign
|
|
39
|
+
*/
|
|
40
|
+
private classifyLoops;
|
|
41
|
+
/**
|
|
42
|
+
* Check if a loop is contained within another loop
|
|
43
|
+
* Uses point-in-polygon test on the first point
|
|
44
|
+
*/
|
|
45
|
+
private isLoopContainedIn;
|
|
46
|
+
/**
|
|
47
|
+
* Ray casting point-in-polygon test
|
|
48
|
+
*/
|
|
49
|
+
private pointInPolygon;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Simplify polygon by removing collinear points
|
|
53
|
+
*/
|
|
54
|
+
export declare function simplifyPolygon(points: Point2D[], tolerance?: number): Point2D[];
|
|
55
|
+
/**
|
|
56
|
+
* Compute polygon bounds
|
|
57
|
+
*/
|
|
58
|
+
export declare function polygonBounds(points: Point2D[]): {
|
|
59
|
+
min: Point2D;
|
|
60
|
+
max: Point2D;
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=polygon-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polygon-builder.d.ts","sourceRoot":"","sources":["../src/polygon-builder.ts"],"names":[],"mappings":"AAIA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAa,UAAU,EAAE,cAAc,EAAa,MAAM,SAAS,CAAC;AA8BzF,qBAAa,cAAc;IACzB,oCAAoC;IACpC,OAAO,CAAC,SAAS,CAAS;gBAEd,SAAS,GAAE,MAAe;IAItC;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,cAAc,EAAE;IAuBvD;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAkC3B;;OAEG;IACH,OAAO,CAAC,UAAU;IAmBlB;;OAEG;IACH,OAAO,CAAC,eAAe;IA8CvB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA2B7B;;;OAGG;IACH,OAAO,CAAC,aAAa;IAwCrB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,cAAc;CAkBvB;AAMD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,SAAS,GAAE,MAAc,GAAG,OAAO,EAAE,CAiBvF;AAWD;;GAEG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,OAAO,EAAE,GAChB;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAA;CAAE,CAiBhC"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { makeEntityKey } from './types';
|
|
5
|
+
import { point2DDistance, polygonSignedArea, ensureCCW, ensureCW, } from './math';
|
|
6
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
7
|
+
// POLYGON BUILDER CLASS
|
|
8
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
9
|
+
export class PolygonBuilder {
|
|
10
|
+
/** Tolerance for vertex matching */
|
|
11
|
+
tolerance;
|
|
12
|
+
constructor(tolerance = 0.0001) {
|
|
13
|
+
this.tolerance = tolerance;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build polygons from cut segments
|
|
17
|
+
* Groups segments by entity and reconstructs closed loops
|
|
18
|
+
*/
|
|
19
|
+
buildPolygons(segments) {
|
|
20
|
+
// Group segments by entity
|
|
21
|
+
const byEntity = new Map();
|
|
22
|
+
for (const seg of segments) {
|
|
23
|
+
const key = makeEntityKey(seg.modelIndex, seg.entityId);
|
|
24
|
+
if (!byEntity.has(key)) {
|
|
25
|
+
byEntity.set(key, []);
|
|
26
|
+
}
|
|
27
|
+
byEntity.get(key).push(seg);
|
|
28
|
+
}
|
|
29
|
+
// Build polygons for each entity - collect arrays for efficient flattening
|
|
30
|
+
const polygonArrays = [];
|
|
31
|
+
for (const [key, entitySegments] of byEntity) {
|
|
32
|
+
const entityPolygons = this.buildEntityPolygons(entitySegments);
|
|
33
|
+
polygonArrays.push(entityPolygons);
|
|
34
|
+
}
|
|
35
|
+
return polygonArrays.flat();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build polygons for a single entity
|
|
39
|
+
*/
|
|
40
|
+
buildEntityPolygons(segments) {
|
|
41
|
+
if (segments.length === 0)
|
|
42
|
+
return [];
|
|
43
|
+
const first = segments[0];
|
|
44
|
+
const { entityId, ifcType, modelIndex } = first;
|
|
45
|
+
// Convert to 2D segments
|
|
46
|
+
const segments2D = segments.map((seg) => ({
|
|
47
|
+
start: seg.p0_2d,
|
|
48
|
+
end: seg.p1_2d,
|
|
49
|
+
used: false,
|
|
50
|
+
}));
|
|
51
|
+
// Build closed loops
|
|
52
|
+
const loops = this.buildLoops(segments2D);
|
|
53
|
+
if (loops.length === 0)
|
|
54
|
+
return [];
|
|
55
|
+
// Classify loops as outer boundaries or holes
|
|
56
|
+
const classified = this.classifyLoops(loops);
|
|
57
|
+
// Build final polygons
|
|
58
|
+
return classified.map((c) => ({
|
|
59
|
+
polygon: {
|
|
60
|
+
outer: c.outer,
|
|
61
|
+
holes: c.holes,
|
|
62
|
+
},
|
|
63
|
+
entityId,
|
|
64
|
+
ifcType,
|
|
65
|
+
modelIndex,
|
|
66
|
+
isCut: true,
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Build closed loops from segments using a greedy chain-building algorithm
|
|
71
|
+
*/
|
|
72
|
+
buildLoops(segments) {
|
|
73
|
+
const loops = [];
|
|
74
|
+
// Keep building loops until no more unused segments
|
|
75
|
+
while (true) {
|
|
76
|
+
// Find first unused segment
|
|
77
|
+
const startIdx = segments.findIndex((s) => !s.used);
|
|
78
|
+
if (startIdx === -1)
|
|
79
|
+
break;
|
|
80
|
+
const loop = this.buildSingleLoop(segments, startIdx);
|
|
81
|
+
if (loop && loop.length >= 3) {
|
|
82
|
+
const area = polygonSignedArea(loop);
|
|
83
|
+
loops.push({ points: loop, area });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return loops;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Build a single closed loop starting from a segment
|
|
90
|
+
*/
|
|
91
|
+
buildSingleLoop(segments, startIdx) {
|
|
92
|
+
const points = [];
|
|
93
|
+
const startSeg = segments[startIdx];
|
|
94
|
+
startSeg.used = true;
|
|
95
|
+
points.push(startSeg.start);
|
|
96
|
+
let currentEnd = startSeg.end;
|
|
97
|
+
const loopStart = startSeg.start;
|
|
98
|
+
const maxIterations = segments.length;
|
|
99
|
+
let iterations = 0;
|
|
100
|
+
while (iterations < maxIterations) {
|
|
101
|
+
iterations++;
|
|
102
|
+
// Check if we've closed the loop
|
|
103
|
+
if (point2DDistance(currentEnd, loopStart) < this.tolerance) {
|
|
104
|
+
return points;
|
|
105
|
+
}
|
|
106
|
+
// Find next connecting segment
|
|
107
|
+
const nextIdx = this.findConnectingSegment(segments, currentEnd);
|
|
108
|
+
if (nextIdx === -1) {
|
|
109
|
+
// Can't close loop - mark remaining as unused and return partial
|
|
110
|
+
// This can happen with open geometry or numerical issues
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
const nextSeg = segments[nextIdx];
|
|
114
|
+
nextSeg.used = true;
|
|
115
|
+
// Determine which end connects
|
|
116
|
+
if (point2DDistance(nextSeg.start, currentEnd) < this.tolerance) {
|
|
117
|
+
points.push(nextSeg.start);
|
|
118
|
+
currentEnd = nextSeg.end;
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
points.push(nextSeg.end);
|
|
122
|
+
currentEnd = nextSeg.start;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Loop didn't close - return points anyway for potential use
|
|
126
|
+
// Some entities may have open cross-sections
|
|
127
|
+
return points.length >= 3 ? points : null;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Find an unused segment that connects to the given point
|
|
131
|
+
*/
|
|
132
|
+
findConnectingSegment(segments, point) {
|
|
133
|
+
let bestIdx = -1;
|
|
134
|
+
let bestDist = this.tolerance;
|
|
135
|
+
for (let i = 0; i < segments.length; i++) {
|
|
136
|
+
if (segments[i].used)
|
|
137
|
+
continue;
|
|
138
|
+
const seg = segments[i];
|
|
139
|
+
// Check start point
|
|
140
|
+
const distStart = point2DDistance(seg.start, point);
|
|
141
|
+
if (distStart < bestDist) {
|
|
142
|
+
bestDist = distStart;
|
|
143
|
+
bestIdx = i;
|
|
144
|
+
}
|
|
145
|
+
// Check end point
|
|
146
|
+
const distEnd = point2DDistance(seg.end, point);
|
|
147
|
+
if (distEnd < bestDist) {
|
|
148
|
+
bestDist = distEnd;
|
|
149
|
+
bestIdx = i;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return bestIdx;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Classify loops as outer boundaries or holes
|
|
156
|
+
* Uses containment testing and area sign
|
|
157
|
+
*/
|
|
158
|
+
classifyLoops(loops) {
|
|
159
|
+
if (loops.length === 0)
|
|
160
|
+
return [];
|
|
161
|
+
// Sort by absolute area (largest first)
|
|
162
|
+
const sorted = [...loops].sort((a, b) => Math.abs(b.area) - Math.abs(a.area));
|
|
163
|
+
const result = [];
|
|
164
|
+
const assigned = new Set();
|
|
165
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
166
|
+
if (assigned.has(i))
|
|
167
|
+
continue;
|
|
168
|
+
const outer = sorted[i];
|
|
169
|
+
// Ensure outer boundary is CCW
|
|
170
|
+
const outerPoints = ensureCCW(outer.points);
|
|
171
|
+
// Find holes (smaller loops contained within this one)
|
|
172
|
+
const holes = [];
|
|
173
|
+
for (let j = i + 1; j < sorted.length; j++) {
|
|
174
|
+
if (assigned.has(j))
|
|
175
|
+
continue;
|
|
176
|
+
const inner = sorted[j];
|
|
177
|
+
// Check if inner is contained in outer
|
|
178
|
+
if (this.isLoopContainedIn(inner.points, outerPoints)) {
|
|
179
|
+
// Ensure hole is CW (opposite winding)
|
|
180
|
+
holes.push(ensureCW(inner.points));
|
|
181
|
+
assigned.add(j);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
assigned.add(i);
|
|
185
|
+
result.push({ outer: outerPoints, holes });
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Check if a loop is contained within another loop
|
|
191
|
+
* Uses point-in-polygon test on the first point
|
|
192
|
+
*/
|
|
193
|
+
isLoopContainedIn(inner, outer) {
|
|
194
|
+
// Test the first point of inner against outer
|
|
195
|
+
const testPoint = inner[0];
|
|
196
|
+
return this.pointInPolygon(testPoint, outer);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Ray casting point-in-polygon test
|
|
200
|
+
*/
|
|
201
|
+
pointInPolygon(point, polygon) {
|
|
202
|
+
let inside = false;
|
|
203
|
+
const n = polygon.length;
|
|
204
|
+
for (let i = 0, j = n - 1; i < n; j = i++) {
|
|
205
|
+
const pi = polygon[i];
|
|
206
|
+
const pj = polygon[j];
|
|
207
|
+
if (pi.y > point.y !== pj.y > point.y &&
|
|
208
|
+
point.x < ((pj.x - pi.x) * (point.y - pi.y)) / (pj.y - pi.y) + pi.x) {
|
|
209
|
+
inside = !inside;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
return inside;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
216
|
+
// HELPER FUNCTIONS
|
|
217
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
218
|
+
/**
|
|
219
|
+
* Simplify polygon by removing collinear points
|
|
220
|
+
*/
|
|
221
|
+
export function simplifyPolygon(points, tolerance = 0.001) {
|
|
222
|
+
if (points.length < 3)
|
|
223
|
+
return points;
|
|
224
|
+
const result = [];
|
|
225
|
+
for (let i = 0; i < points.length; i++) {
|
|
226
|
+
const prev = points[(i - 1 + points.length) % points.length];
|
|
227
|
+
const curr = points[i];
|
|
228
|
+
const next = points[(i + 1) % points.length];
|
|
229
|
+
// Check if current point is on the line between prev and next
|
|
230
|
+
if (!isCollinear(prev, curr, next, tolerance)) {
|
|
231
|
+
result.push(curr);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return result.length >= 3 ? result : points;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Check if three points are collinear
|
|
238
|
+
*/
|
|
239
|
+
function isCollinear(a, b, c, tolerance) {
|
|
240
|
+
// Area of triangle formed by the three points
|
|
241
|
+
const area = Math.abs((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y));
|
|
242
|
+
return area < tolerance;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Compute polygon bounds
|
|
246
|
+
*/
|
|
247
|
+
export function polygonBounds(points) {
|
|
248
|
+
let minX = Infinity, minY = Infinity;
|
|
249
|
+
let maxX = -Infinity, maxY = -Infinity;
|
|
250
|
+
for (const p of points) {
|
|
251
|
+
minX = Math.min(minX, p.x);
|
|
252
|
+
minY = Math.min(minY, p.y);
|
|
253
|
+
maxX = Math.max(maxX, p.x);
|
|
254
|
+
maxY = Math.max(maxY, p.y);
|
|
255
|
+
}
|
|
256
|
+
return {
|
|
257
|
+
min: { x: minX, y: minY },
|
|
258
|
+
max: { x: maxX, y: maxY },
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=polygon-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"polygon-builder.js","sourceRoot":"","sources":["../src/polygon-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section Cutter - Core algorithm for cutting 3D triangle meshes with a plane
|
|
3
|
+
*
|
|
4
|
+
* Generates 2D line segments and reconstructed polygons for architectural drawings.
|
|
5
|
+
*/
|
|
6
|
+
import type { MeshData } from '@ifc-lite/geometry';
|
|
7
|
+
import type { SectionPlaneConfig, CutSegment, MeshCutResult, SectionCutResult } from './types';
|
|
8
|
+
export declare class SectionCutter {
|
|
9
|
+
private planeNormal;
|
|
10
|
+
private planeDistance;
|
|
11
|
+
private axis;
|
|
12
|
+
private flipped;
|
|
13
|
+
constructor(config: SectionPlaneConfig);
|
|
14
|
+
/**
|
|
15
|
+
* Cut all meshes with the section plane
|
|
16
|
+
*/
|
|
17
|
+
cutMeshes(meshes: MeshData[]): SectionCutResult;
|
|
18
|
+
/**
|
|
19
|
+
* Cut a single mesh with the section plane
|
|
20
|
+
*/
|
|
21
|
+
cutSingleMesh(mesh: MeshData): MeshCutResult;
|
|
22
|
+
/**
|
|
23
|
+
* Get vertex from positions array
|
|
24
|
+
*/
|
|
25
|
+
private getVertex;
|
|
26
|
+
/**
|
|
27
|
+
* Intersect a triangle with the section plane
|
|
28
|
+
* Returns the two intersection points, or null if no intersection
|
|
29
|
+
*/
|
|
30
|
+
private intersectTrianglePlane;
|
|
31
|
+
/**
|
|
32
|
+
* Find intersection point of an edge with the plane
|
|
33
|
+
*/
|
|
34
|
+
private edgePlaneIntersection;
|
|
35
|
+
}
|
|
36
|
+
export interface StreamingSectionCutterOptions {
|
|
37
|
+
/** Callback when a batch of segments is ready */
|
|
38
|
+
onSegments?: (segments: CutSegment[], progress: number) => void;
|
|
39
|
+
/** Batch size for streaming (number of meshes per batch) */
|
|
40
|
+
batchSize?: number;
|
|
41
|
+
/** Yield to event loop every N milliseconds */
|
|
42
|
+
yieldIntervalMs?: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Streaming section cutter for large models
|
|
46
|
+
* Processes meshes in batches to avoid blocking the main thread
|
|
47
|
+
*/
|
|
48
|
+
export declare function cutMeshesStreaming(meshes: MeshData[], config: SectionPlaneConfig, options?: StreamingSectionCutterOptions): Promise<SectionCutResult>;
|
|
49
|
+
//# sourceMappingURL=section-cutter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"section-cutter.d.ts","sourceRoot":"","sources":["../src/section-cutter.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAGV,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,gBAAgB,EAGjB,MAAM,SAAS,CAAC;AAgBjB,qBAAa,aAAa;IACxB,OAAO,CAAC,WAAW,CAAO;IAC1B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,IAAI,CAAkB;IAC9B,OAAO,CAAC,OAAO,CAAU;gBAEb,MAAM,EAAE,kBAAkB;IAOtC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB;IAqC/C;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,aAAa;IA0D5C;;OAEG;IACH,OAAO,CAAC,SAAS;IAKjB;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IA6C9B;;OAEG;IACH,OAAO,CAAC,qBAAqB;CAwB9B;AAMD,MAAM,WAAW,6BAA6B;IAC5C,iDAAiD;IACjD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAChE,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,QAAQ,EAAE,EAClB,MAAM,EAAE,kBAAkB,EAC1B,OAAO,GAAE,6BAAkC,GAC1C,OAAO,CAAC,gBAAgB,CAAC,CA0D3B"}
|