@ifc-lite/drawing-2d 2.0.0 → 2.1.1
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/dist/color-raster.d.ts +95 -0
- package/dist/color-raster.d.ts.map +1 -0
- package/dist/color-raster.js +225 -0
- package/dist/color-raster.js.map +1 -0
- package/dist/drawing-generator.d.ts +12 -0
- package/dist/drawing-generator.d.ts.map +1 -1
- package/dist/drawing-generator.js +13 -4
- package/dist/drawing-generator.js.map +1 -1
- package/dist/edge-extractor.d.ts +17 -0
- package/dist/edge-extractor.d.ts.map +1 -1
- package/dist/edge-extractor.js +95 -0
- package/dist/edge-extractor.js.map +1 -1
- package/dist/half-space-clip.d.ts +77 -0
- package/dist/half-space-clip.d.ts.map +1 -0
- package/dist/half-space-clip.js +257 -0
- package/dist/half-space-clip.js.map +1 -0
- package/dist/hidden-line-raster.d.ts +11 -2
- package/dist/hidden-line-raster.d.ts.map +1 -1
- package/dist/hidden-line-raster.js +7 -58
- package/dist/hidden-line-raster.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -1
- package/dist/index.js.map +1 -1
- package/dist/pdf-scale.d.ts +17 -0
- package/dist/pdf-scale.d.ts.map +1 -1
- package/dist/pdf-scale.js +38 -0
- package/dist/pdf-scale.js.map +1 -1
- package/dist/raster-core.d.ts +71 -0
- package/dist/raster-core.d.ts.map +1 -0
- package/dist/raster-core.js +89 -0
- package/dist/raster-core.js.map +1 -0
- package/dist/sheet/index.d.ts +2 -0
- package/dist/sheet/index.d.ts.map +1 -1
- package/dist/sheet/index.js +1 -0
- package/dist/sheet/index.js.map +1 -1
- package/dist/sheet/scale-stamp.d.ts +130 -0
- package/dist/sheet/scale-stamp.d.ts.map +1 -0
- package/dist/sheet/scale-stamp.js +277 -0
- package/dist/sheet/scale-stamp.js.map +1 -0
- package/dist/symbols/door-symbol.d.ts.map +1 -1
- package/dist/symbols/door-symbol.js +18 -12
- package/dist/symbols/door-symbol.js.map +1 -1
- package/dist/view-plane.d.ts +99 -0
- package/dist/view-plane.d.ts.map +1 -0
- package/dist/view-plane.js +183 -0
- package/dist/view-plane.js.map +1 -0
- package/dist/world-line-seeds.d.ts +41 -0
- package/dist/world-line-seeds.d.ts.map +1 -0
- package/dist/world-line-seeds.js +43 -0
- package/dist/world-line-seeds.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,183 @@
|
|
|
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 { vec3, vec3Cross, vec3Dot, vec3Length, vec3Normalize, vec3Sub } from './math.js';
|
|
5
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
6
|
+
// WORLD BOUNDS
|
|
7
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
8
|
+
/**
|
|
9
|
+
* World-space AABB of `meshes`, folding each mesh's local frame:
|
|
10
|
+
* `world = origin + positions[3i..3i+3]`.
|
|
11
|
+
*
|
|
12
|
+
* Reading `positions` without adding `origin` is the standing local-frame
|
|
13
|
+
* defect in this codebase (see `MeshData.origin`): it reports a box around
|
|
14
|
+
* the model ORIGIN instead of around the model, which would place the
|
|
15
|
+
* synthetic camera plane in the wrong place entirely.
|
|
16
|
+
*
|
|
17
|
+
* Returns `null` when no mesh contributes a vertex — the caller must decide
|
|
18
|
+
* what an empty view means rather than receive an inverted/infinite box.
|
|
19
|
+
*/
|
|
20
|
+
export function worldBoundsOfMeshes(meshes) {
|
|
21
|
+
let minX = Infinity, minY = Infinity, minZ = Infinity;
|
|
22
|
+
let maxX = -Infinity, maxY = -Infinity, maxZ = -Infinity;
|
|
23
|
+
let any = false;
|
|
24
|
+
for (const mesh of meshes) {
|
|
25
|
+
const { positions, origin } = mesh;
|
|
26
|
+
const ox = origin ? origin[0] : 0;
|
|
27
|
+
const oy = origin ? origin[1] : 0;
|
|
28
|
+
const oz = origin ? origin[2] : 0;
|
|
29
|
+
const vertexCount = Math.floor(positions.length / 3);
|
|
30
|
+
for (let i = 0; i < vertexCount; i++) {
|
|
31
|
+
const x = positions[i * 3] + ox;
|
|
32
|
+
const y = positions[i * 3 + 1] + oy;
|
|
33
|
+
const z = positions[i * 3 + 2] + oz;
|
|
34
|
+
if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z))
|
|
35
|
+
continue;
|
|
36
|
+
if (x < minX)
|
|
37
|
+
minX = x;
|
|
38
|
+
if (y < minY)
|
|
39
|
+
minY = y;
|
|
40
|
+
if (z < minZ)
|
|
41
|
+
minZ = z;
|
|
42
|
+
if (x > maxX)
|
|
43
|
+
maxX = x;
|
|
44
|
+
if (y > maxY)
|
|
45
|
+
maxY = y;
|
|
46
|
+
if (z > maxZ)
|
|
47
|
+
maxZ = z;
|
|
48
|
+
any = true;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!any)
|
|
52
|
+
return null;
|
|
53
|
+
return { min: vec3(minX, minY, minZ), max: vec3(maxX, maxY, maxZ) };
|
|
54
|
+
}
|
|
55
|
+
/** The eight corners of a world AABB, in a fixed order. */
|
|
56
|
+
export function worldBoundsCorners(bounds) {
|
|
57
|
+
const { min, max } = bounds;
|
|
58
|
+
const corners = [];
|
|
59
|
+
for (const x of [min.x, max.x]) {
|
|
60
|
+
for (const y of [min.y, max.y]) {
|
|
61
|
+
for (const z of [min.z, max.z]) {
|
|
62
|
+
corners.push(vec3(x, y, z));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return corners;
|
|
67
|
+
}
|
|
68
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
69
|
+
// CAMERA PLANE
|
|
70
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
71
|
+
/** Smallest cross-product length treated as "up is parallel to the view". */
|
|
72
|
+
const PARALLEL_EPSILON = 1e-6;
|
|
73
|
+
/**
|
|
74
|
+
* A reference up that is guaranteed not to be parallel to `viewDir`: world
|
|
75
|
+
* +Y unless the camera looks (near-)straight up or down, in which case world
|
|
76
|
+
* +Z. Without this, a top-down / bottom-up view — the single most common
|
|
77
|
+
* plan-drawing camera — produces a zero-length right vector and a basis full
|
|
78
|
+
* of NaN, i.e. a blank PDF.
|
|
79
|
+
*/
|
|
80
|
+
function fallbackUp(viewDir) {
|
|
81
|
+
return Math.abs(viewDir.y) < 0.9 ? vec3(0, 1, 0) : vec3(0, 0, 1);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Build the synthetic section plane that represents the current camera view.
|
|
85
|
+
*
|
|
86
|
+
* @param camera World-space eye/target/up.
|
|
87
|
+
* @param worldBounds World AABB of everything that will be drawn (see
|
|
88
|
+
* {@link worldBoundsOfMeshes}).
|
|
89
|
+
*
|
|
90
|
+
* @throws when the camera degenerates (eye == target) or the bounds are
|
|
91
|
+
* non-finite — both would otherwise yield a NaN transform and a
|
|
92
|
+
* blank-but-plausible PDF page.
|
|
93
|
+
*/
|
|
94
|
+
export function buildCameraSectionPlane(camera, worldBounds) {
|
|
95
|
+
const rawView = vec3Sub(camera.target, camera.position);
|
|
96
|
+
if (vec3Length(rawView) < PARALLEL_EPSILON) {
|
|
97
|
+
throw new Error('Cannot build a camera section plane: the camera position and target coincide, ' +
|
|
98
|
+
'so the view direction is undefined.');
|
|
99
|
+
}
|
|
100
|
+
const viewDir = vec3Normalize(rawView);
|
|
101
|
+
for (const v of [worldBounds.min, worldBounds.max]) {
|
|
102
|
+
if (!Number.isFinite(v.x) || !Number.isFinite(v.y) || !Number.isFinite(v.z)) {
|
|
103
|
+
throw new Error('Cannot build a camera section plane: world bounds must be finite.');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ── Orthonormal basis ───────────────────────────────────────────────────
|
|
107
|
+
// tangent = screen right
|
|
108
|
+
// bitangent = screen up, RE-ORTHOGONALISED against the view direction
|
|
109
|
+
// normal = −viewDir (points back at the viewer)
|
|
110
|
+
//
|
|
111
|
+
// `cross(tangent, bitangent) === normal` holds by construction, which is
|
|
112
|
+
// what keeps the page from coming out mirrored (#2119 defect class).
|
|
113
|
+
// NORMALISED before the parallel test below. `|cross(viewDir, up)|` is
|
|
114
|
+
// `|up| * sin(angle)`, so testing it against a fixed epsilon without
|
|
115
|
+
// normalising makes the threshold depend on the LENGTH of `up`: a long up
|
|
116
|
+
// vector that is genuinely almost parallel to the view still clears the
|
|
117
|
+
// epsilon, and the basis is then built from a direction that is numerically
|
|
118
|
+
// noise. Normalising first makes PARALLEL_EPSILON a pure angle tolerance.
|
|
119
|
+
const upHint = vec3Length(camera.up) < PARALLEL_EPSILON ? fallbackUp(viewDir) : vec3Normalize(camera.up);
|
|
120
|
+
let right = vec3Cross(viewDir, upHint);
|
|
121
|
+
if (vec3Length(right) < PARALLEL_EPSILON) {
|
|
122
|
+
right = vec3Cross(viewDir, fallbackUp(viewDir));
|
|
123
|
+
}
|
|
124
|
+
const tangent = vec3Normalize(right);
|
|
125
|
+
const bitangent = vec3Normalize(vec3Cross(tangent, viewDir));
|
|
126
|
+
const normal = vec3(-viewDir.x, -viewDir.y, -viewDir.z);
|
|
127
|
+
// ── Plane placement: strictly in front of every bounds corner ───────────
|
|
128
|
+
// `s = dot(corner, viewDir)` grows AWAY from the viewer, so the nearest
|
|
129
|
+
// corner is at `sMin`. Putting the plane a pad before `sMin` guarantees
|
|
130
|
+
// every corner has a strictly positive view depth.
|
|
131
|
+
const corners = worldBoundsCorners(worldBounds);
|
|
132
|
+
let sMin = Infinity;
|
|
133
|
+
let sMax = -Infinity;
|
|
134
|
+
for (const c of corners) {
|
|
135
|
+
const s = vec3Dot(c, viewDir);
|
|
136
|
+
if (s < sMin)
|
|
137
|
+
sMin = s;
|
|
138
|
+
if (s > sMax)
|
|
139
|
+
sMax = s;
|
|
140
|
+
}
|
|
141
|
+
const span = sMax - sMin;
|
|
142
|
+
// Relative pad so it stays meaningful from a door handle to a city block,
|
|
143
|
+
// with an absolute floor for a degenerate (flat) box.
|
|
144
|
+
const pad = Math.max(span * 1e-3, 1e-4);
|
|
145
|
+
const planeS = sMin - pad;
|
|
146
|
+
// A genuine point ON the plane, used as the 2D basis origin so drawing
|
|
147
|
+
// coordinates stay centred on the model instead of on the world origin.
|
|
148
|
+
const center = vec3((worldBounds.min.x + worldBounds.max.x) / 2, (worldBounds.min.y + worldBounds.max.y) / 2, (worldBounds.min.z + worldBounds.max.z) / 2);
|
|
149
|
+
const shift = planeS - vec3Dot(center, viewDir);
|
|
150
|
+
const origin = vec3(center.x + viewDir.x * shift, center.y + viewDir.y * shift, center.z + viewDir.z * shift);
|
|
151
|
+
// dot(origin, normal) = −dot(origin, viewDir) = −planeS, computed in closed
|
|
152
|
+
// form rather than re-derived from `origin` so the offset carries no extra
|
|
153
|
+
// rounding from the point reconstruction above.
|
|
154
|
+
const distance = -planeS;
|
|
155
|
+
// Legacy cardinal fields. Every plane-aware helper (`signedDepth`,
|
|
156
|
+
// `projectPointForPlane`, `SectionCutter`, the depth raster) checks
|
|
157
|
+
// `customPlane` FIRST, so these only feed code that predates arbitrary
|
|
158
|
+
// planes. They are set to the closest cardinal reading of this plane
|
|
159
|
+
// rather than to a lie like `position: 0`.
|
|
160
|
+
const axis = dominantAxis(normal);
|
|
161
|
+
const position = origin[axis];
|
|
162
|
+
return {
|
|
163
|
+
plane: {
|
|
164
|
+
axis,
|
|
165
|
+
position,
|
|
166
|
+
flipped: false,
|
|
167
|
+
customPlane: { normal, distance, origin, tangent, bitangent },
|
|
168
|
+
},
|
|
169
|
+
viewDepth: span + pad * 2,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/** The cardinal axis the plane normal is most aligned with. */
|
|
173
|
+
function dominantAxis(normal) {
|
|
174
|
+
const ax = Math.abs(normal.x);
|
|
175
|
+
const ay = Math.abs(normal.y);
|
|
176
|
+
const az = Math.abs(normal.z);
|
|
177
|
+
if (ax >= ay && ax >= az)
|
|
178
|
+
return 'x';
|
|
179
|
+
if (ay >= az)
|
|
180
|
+
return 'y';
|
|
181
|
+
return 'z';
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=view-plane.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-plane.js","sourceRoot":"","sources":["../src/view-plane.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project world-space 3D segments (the section rim produced by
|
|
3
|
+
* `half-space-clip.ts`) into classified `DrawingLine`s (issue #2042).
|
|
4
|
+
*
|
|
5
|
+
* # Defect class this module guards against
|
|
6
|
+
* **A line producer that invents its own projection or its own depth
|
|
7
|
+
* convention.** Everything else in this pipeline — the section cutter, the
|
|
8
|
+
* edge extractor, the projection bands, and the hidden-line depth raster —
|
|
9
|
+
* derives 2D coordinates from `projectPointForPlane` and view depths from
|
|
10
|
+
* `−signedDepth`. A producer that re-implements either (a hand-rolled dot
|
|
11
|
+
* product, a forgotten sign, a `depth` measured from the wrong side) emits
|
|
12
|
+
* lines that look right on their own but sit in a *different frame* from the
|
|
13
|
+
* depth buffer they are sampled against — so hidden-line removal silently
|
|
14
|
+
* dashes visible edges, or leaves occluded ones solid, with no error
|
|
15
|
+
* anywhere. This module does nothing but call those two shared helpers.
|
|
16
|
+
*
|
|
17
|
+
* The rim of a section cut is, by definition, geometry lying IN the cut
|
|
18
|
+
* plane, so it is emitted as `category: 'cut'` (heavy line weight). It is
|
|
19
|
+
* still handed to the hidden-line stage rather than drawn unconditionally:
|
|
20
|
+
* on an oblique 3D view the far side of a cut object is genuinely behind
|
|
21
|
+
* other geometry and must print dashed.
|
|
22
|
+
*/
|
|
23
|
+
import type { DrawingLine, SectionPlaneConfig, Vec3 } from './types.js';
|
|
24
|
+
/** A world-space segment to be drawn, with its source element metadata. */
|
|
25
|
+
export interface WorldLineSeed {
|
|
26
|
+
start: Vec3;
|
|
27
|
+
end: Vec3;
|
|
28
|
+
entityId: number;
|
|
29
|
+
ifcType: string;
|
|
30
|
+
modelIndex: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Project `seeds` into drawing lines against `plane`.
|
|
34
|
+
*
|
|
35
|
+
* Segments whose 2D projection collapses to a point (an edge parallel to the
|
|
36
|
+
* view direction) are dropped: they carry no information on the page and
|
|
37
|
+
* would only add zero-length strokes for the line merger and the PDF writer
|
|
38
|
+
* to trip over.
|
|
39
|
+
*/
|
|
40
|
+
export declare function projectWorldLineSeeds(seeds: readonly WorldLineSeed[], plane: SectionPlaneConfig): DrawingLine[];
|
|
41
|
+
//# sourceMappingURL=world-line-seeds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-line-seeds.d.ts","sourceRoot":"","sources":["../src/world-line-seeds.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAW,kBAAkB,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIjF,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,IAAI,CAAC;IACZ,GAAG,EAAE,IAAI,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,SAAS,aAAa,EAAE,EAC/B,KAAK,EAAE,kBAAkB,GACxB,WAAW,EAAE,CA8Bf"}
|
|
@@ -0,0 +1,43 @@
|
|
|
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 { EPSILON, point2DDistance } from './math.js';
|
|
5
|
+
import { projectPointForPlane, signedDepth } from './projection-bands.js';
|
|
6
|
+
/**
|
|
7
|
+
* Project `seeds` into drawing lines against `plane`.
|
|
8
|
+
*
|
|
9
|
+
* Segments whose 2D projection collapses to a point (an edge parallel to the
|
|
10
|
+
* view direction) are dropped: they carry no information on the page and
|
|
11
|
+
* would only add zero-length strokes for the line merger and the PDF writer
|
|
12
|
+
* to trip over.
|
|
13
|
+
*/
|
|
14
|
+
export function projectWorldLineSeeds(seeds, plane) {
|
|
15
|
+
const lines = [];
|
|
16
|
+
for (const seed of seeds) {
|
|
17
|
+
const start = projectPointForPlane(seed.start, plane);
|
|
18
|
+
const end = projectPointForPlane(seed.end, plane);
|
|
19
|
+
if (point2DDistance(start, end) < EPSILON)
|
|
20
|
+
continue;
|
|
21
|
+
// VIEW depth (issue #2639): the negated flip-adjusted signed depth — 0 at
|
|
22
|
+
// the plane, growing into the kept half, smaller means nearer the viewer.
|
|
23
|
+
// Identical quantity to the one `buildDepthRaster` stores per pixel.
|
|
24
|
+
const depth = -signedDepth(seed.start, plane);
|
|
25
|
+
const depthEnd = -signedDepth(seed.end, plane);
|
|
26
|
+
const line = {
|
|
27
|
+
line: { start, end },
|
|
28
|
+
category: 'cut',
|
|
29
|
+
visibility: 'visible',
|
|
30
|
+
entityId: seed.entityId,
|
|
31
|
+
ifcType: seed.ifcType,
|
|
32
|
+
modelIndex: seed.modelIndex,
|
|
33
|
+
depth,
|
|
34
|
+
};
|
|
35
|
+
// "Omitted means constant depth" — only carry `depthEnd` when it differs,
|
|
36
|
+
// matching what every other producer in this package emits.
|
|
37
|
+
if (depthEnd !== depth)
|
|
38
|
+
line.depthEnd = depthEnd;
|
|
39
|
+
lines.push(line);
|
|
40
|
+
}
|
|
41
|
+
return lines;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=world-line-seeds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"world-line-seeds.js","sourceRoot":"","sources":["../src/world-line-seeds.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA0B/D,OAAO,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAW1E;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,KAA+B,EAC/B,KAAyB;IAEzB,MAAM,KAAK,GAAkB,EAAE,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAY,oBAAoB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAY,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3D,IAAI,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC,GAAG,OAAO;YAAE,SAAS;QAEpD,0EAA0E;QAC1E,0EAA0E;QAC1E,qEAAqE;QACrE,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAE/C,MAAM,IAAI,GAAgB;YACxB,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE;YACpB,QAAQ,EAAE,KAAK;YACf,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,KAAK;SACN,CAAC;QACF,0EAA0E;QAC1E,4DAA4D;QAC5D,IAAI,QAAQ,KAAK,KAAK;YAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ifc-lite/drawing-2d",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "2D architectural drawing generation from IFC models - section cuts, floor plans, and elevations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@ifc-lite/geometry": "^3.8.
|
|
16
|
+
"@ifc-lite/geometry": "^3.8.4"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@webgpu/types": "^0.1.71",
|