@twinfinity/printing 6.1.0-beta → 6.1.2-ci.30738-beta
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/BuildInfo.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/analyzeTemplate.d.ts +4 -4
- package/dist/layout/analyzeTemplate.d.ts.map +1 -1
- package/dist/layout/analyzeTemplate.js +18 -16
- package/dist/layout/analyzeTemplate.js.map +1 -1
- package/dist/layout/classClosure.d.ts +41 -0
- package/dist/layout/classClosure.d.ts.map +1 -0
- package/dist/layout/classClosure.js +143 -0
- package/dist/layout/classClosure.js.map +1 -0
- package/dist/layout/clipUtils.d.ts +11 -0
- package/dist/layout/clipUtils.d.ts.map +1 -1
- package/dist/layout/clipUtils.js +67 -6
- package/dist/layout/clipUtils.js.map +1 -1
- package/dist/layout/filters.d.ts +14 -8
- package/dist/layout/filters.d.ts.map +1 -1
- package/dist/layout/filters.js +28 -3
- package/dist/layout/filters.js.map +1 -1
- package/dist/layout/index.d.ts +24 -57
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +20 -337
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/itemBuilders.d.ts +11 -0
- package/dist/layout/itemBuilders.d.ts.map +1 -1
- package/dist/layout/itemBuilders.js +17 -3
- package/dist/layout/itemBuilders.js.map +1 -1
- package/dist/layout/labelsRender.d.ts.map +1 -1
- package/dist/layout/labelsRender.js +15 -27
- package/dist/layout/labelsRender.js.map +1 -1
- package/dist/layout/legendRender.d.ts +18 -6
- package/dist/layout/legendRender.d.ts.map +1 -1
- package/dist/layout/legendRender.js +49 -79
- package/dist/layout/legendRender.js.map +1 -1
- package/dist/layout/metadata.d.ts.map +1 -1
- package/dist/layout/metadata.js +26 -5
- package/dist/layout/metadata.js.map +1 -1
- package/dist/layout/model.d.ts +4 -3
- package/dist/layout/model.d.ts.map +1 -1
- package/dist/layout/model.js +17 -57
- package/dist/layout/model.js.map +1 -1
- package/dist/layout/options.d.ts +1 -2
- package/dist/layout/options.d.ts.map +1 -1
- package/dist/layout/options.js.map +1 -1
- package/dist/layout/preflight.d.ts +32 -0
- package/dist/layout/preflight.d.ts.map +1 -0
- package/dist/layout/preflight.js +69 -0
- package/dist/layout/preflight.js.map +1 -0
- package/dist/layout/qrRender.d.ts.map +1 -1
- package/dist/layout/qrRender.js +11 -10
- package/dist/layout/qrRender.js.map +1 -1
- package/dist/layout/renderDrawing.d.ts +28 -17
- package/dist/layout/renderDrawing.d.ts.map +1 -1
- package/dist/layout/renderDrawing.js +107 -88
- package/dist/layout/renderDrawing.js.map +1 -1
- package/dist/layout/renderLayout.d.ts +25 -0
- package/dist/layout/renderLayout.d.ts.map +1 -0
- package/dist/layout/renderLayout.js +315 -0
- package/dist/layout/renderLayout.js.map +1 -0
- package/dist/layout/renderTemplateSheet.d.ts +99 -0
- package/dist/layout/renderTemplateSheet.d.ts.map +1 -0
- package/dist/layout/renderTemplateSheet.js +296 -0
- package/dist/layout/renderTemplateSheet.js.map +1 -0
- package/dist/layout/renderUtils.d.ts +19 -0
- package/dist/layout/renderUtils.d.ts.map +1 -1
- package/dist/layout/renderUtils.js +47 -4
- package/dist/layout/renderUtils.js.map +1 -1
- package/dist/layout/sectionDefs.d.ts +65 -0
- package/dist/layout/sectionDefs.d.ts.map +1 -0
- package/dist/layout/sectionDefs.js +88 -0
- package/dist/layout/sectionDefs.js.map +1 -0
- package/dist/layout/slabModelView.d.ts +34 -0
- package/dist/layout/slabModelView.d.ts.map +1 -0
- package/dist/layout/slabModelView.js +175 -0
- package/dist/layout/slabModelView.js.map +1 -0
- package/dist/layout/templateVariables.d.ts +1 -1
- package/dist/layout/templateVariables.d.ts.map +1 -1
- package/dist/layout/templateVariables.js +21 -9
- package/dist/layout/templateVariables.js.map +1 -1
- package/dist/layout/types.d.ts +164 -83
- package/dist/layout/types.d.ts.map +1 -1
- package/dist/layout/types.js.map +1 -1
- package/dist/layout/validation.d.ts.map +1 -1
- package/dist/layout/validation.js +78 -33
- package/dist/layout/validation.js.map +1 -1
- package/dist/layout/viewportPrep.d.ts +8 -6
- package/dist/layout/viewportPrep.d.ts.map +1 -1
- package/dist/layout/viewportPrep.js +35 -23
- package/dist/layout/viewportPrep.js.map +1 -1
- package/dist/layout/viewportRender.d.ts +9 -7
- package/dist/layout/viewportRender.d.ts.map +1 -1
- package/dist/layout/viewportRender.js +93 -126
- package/dist/layout/viewportRender.js.map +1 -1
- package/dist/layout/viewportUtils.d.ts +20 -0
- package/dist/layout/viewportUtils.d.ts.map +1 -1
- package/dist/layout/viewportUtils.js +107 -4
- package/dist/layout/viewportUtils.js.map +1 -1
- package/dist/printToPdf.d.ts +7 -1
- package/dist/printToPdf.d.ts.map +1 -1
- package/dist/printToPdf.js +81 -14
- package/dist/printToPdf.js.map +1 -1
- package/dist/printToSvg.d.ts.map +1 -1
- package/dist/printToSvg.js +7 -3
- package/dist/printToSvg.js.map +1 -1
- package/dist/schemaUtils.d.ts +9 -0
- package/dist/schemaUtils.d.ts.map +1 -0
- package/dist/schemaUtils.js +14 -0
- package/dist/schemaUtils.js.map +1 -0
- package/dist/templates/default-template.json +30 -8
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +10 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -3
- package/src/index.ts +4 -0
- package/src/layout/analyzeTemplate.ts +21 -19
- package/src/layout/classClosure.ts +142 -0
- package/src/layout/clipUtils.ts +65 -6
- package/src/layout/filters.ts +31 -3
- package/src/layout/index.ts +61 -571
- package/src/layout/itemBuilders.ts +20 -5
- package/src/layout/labelsRender.ts +23 -40
- package/src/layout/legendRender.ts +64 -84
- package/src/layout/metadata.ts +26 -5
- package/src/layout/model.ts +21 -66
- package/src/layout/options.ts +1 -2
- package/src/layout/preflight.ts +96 -0
- package/src/layout/qrRender.ts +11 -10
- package/src/layout/renderDrawing.ts +132 -110
- package/src/layout/renderLayout.ts +483 -0
- package/src/layout/renderTemplateSheet.ts +435 -0
- package/src/layout/renderUtils.ts +53 -4
- package/src/layout/sectionDefs.ts +131 -0
- package/src/layout/slabModelView.ts +196 -0
- package/src/layout/templateVariables.ts +25 -9
- package/src/layout/types.ts +160 -70
- package/src/layout/validation.ts +98 -32
- package/src/layout/viewportPrep.ts +47 -29
- package/src/layout/viewportRender.ts +114 -141
- package/src/layout/viewportUtils.ts +118 -5
- package/src/printToPdf.ts +84 -15
- package/src/printToSvg.ts +7 -3
- package/src/schemaUtils.ts +13 -0
- package/src/templates/default-template.json +30 -8
- package/src/types.ts +12 -2
- package/templates/default-a0-landscape.json +171 -66
- package/templates/default-a0-portrait.json +159 -60
- package/templates/default-a1-landscape.json +135 -48
- package/templates/default-a1-portrait.json +123 -42
- package/templates/default-a3-landscape.json +87 -24
- package/templates/default-a3-portrait.json +99 -30
- package/templates/default-a4-landscape.json +75 -18
- package/templates/default-a4-portrait.json +75 -18
- package/templates/llm-authoring-guide.md +247 -0
- package/templates/template-schema.json +295 -120
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { sectionStateToModelView, computePolylinesCenter } from './itemBuilders';
|
|
1
|
+
import { sectionStateToModelView, computePolylinesCenter, readXZ } from './itemBuilders';
|
|
2
2
|
import { buildMetadataMap, normalizePropertySets, resolveIfcClassName, resolveIfcClassId } from './metadata';
|
|
3
3
|
import { applyLineStyleToPaths } from './utils';
|
|
4
4
|
import { analyzeTemplate } from './analyzeTemplate';
|
|
5
|
-
import {
|
|
5
|
+
import { matchesFilter, matchesProductClass, normalizeValue } from './filters';
|
|
6
6
|
import { getProp } from './typeGuards';
|
|
7
7
|
// These were previously lazy-loaded via require() from @measurement-tools/* packages.
|
|
8
8
|
// Now they are part of @twinfinity/printing (this package) and @twinfinity/geometry.
|
|
@@ -75,30 +75,27 @@ function getGeometry() {
|
|
|
75
75
|
function getSampleColor() {
|
|
76
76
|
return _geometry.sampleProductColorRgba;
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
// renderDrawing is imported by index.ts which defines renderLayout.
|
|
80
|
-
// The binding is set by index.ts after definition via setRenderLayoutBinding().
|
|
81
|
-
let _renderLayout = null;
|
|
82
|
-
/** Called by index.ts to register renderLayout without a circular import. */
|
|
83
|
-
export function setRenderLayoutBinding(fn) {
|
|
84
|
-
_renderLayout = fn;
|
|
85
|
-
}
|
|
86
|
-
function getRenderLayout() {
|
|
87
|
-
if (!_renderLayout) {
|
|
88
|
-
throw new Error('renderLayout not initialized. Ensure @twinfinity/printing index is imported before calling renderDrawing.');
|
|
89
|
-
}
|
|
90
|
-
return _renderLayout;
|
|
91
|
-
}
|
|
78
|
+
import { renderLayout } from './renderLayout';
|
|
92
79
|
// ---------------------------------------------------------------------------
|
|
93
80
|
// Public API
|
|
94
81
|
// ---------------------------------------------------------------------------
|
|
95
82
|
/**
|
|
96
|
-
* High-level entry point that
|
|
97
|
-
*
|
|
83
|
+
* High-level entry point that renders a layout template to a ready-to-print
|
|
84
|
+
* SVG string.
|
|
85
|
+
*
|
|
86
|
+
* The inputs form a 2×2 matrix — geometry × item data, each either raw or
|
|
87
|
+
* pre-built:
|
|
88
|
+
*
|
|
89
|
+
* | input | what it is |
|
|
90
|
+
* |---------------------------|--------------------------------------------------|
|
|
91
|
+
* | `sections` | RAW geometry: plane-section results (one shared or per viewport id). |
|
|
92
|
+
* | `models` | PRE-BUILT geometry: `SvgModelView`s per viewport id (e.g. from `slabSectionToModelView`). Needs `rawPaths` with `meta.gid` for highlight/clip/includeClasses. |
|
|
93
|
+
* | `options.productEntries` | RAW item data: per-product world-x/z polylines (`slabPerProductToEntries`); one flat list shared by all viewports or a per-viewport record. Feeds labels/legend/clip/highlight items. |
|
|
94
|
+
* | `options.viewportItems` | PRE-BUILT item data per viewport id (overrides `productEntries`). |
|
|
98
95
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
96
|
+
* Prerequisite: products must have property sets loaded
|
|
97
|
+
* (`await api.ifc.loadPropertySets()` on core BIM objects) — without them
|
|
98
|
+
* every `where` filter matches nothing.
|
|
102
99
|
*
|
|
103
100
|
* ```ts
|
|
104
101
|
* const section = computePlaneSectionsForProducts(products, plane, { includeInvisible: true });
|
|
@@ -106,9 +103,8 @@ function getRenderLayout() {
|
|
|
106
103
|
* template,
|
|
107
104
|
* sections: { main: section },
|
|
108
105
|
* options: {
|
|
109
|
-
*
|
|
110
|
-
* qrContext: { host, containerName
|
|
111
|
-
* productFields: { idPath: "propertySets.BIP.spacenumber.value", ... },
|
|
106
|
+
* allowRemoteResources: true,
|
|
107
|
+
* qrContext: { host, containerName },
|
|
112
108
|
* roomLabels: { labelPath: "BIP.spacename", classFilter: "space" },
|
|
113
109
|
* },
|
|
114
110
|
* });
|
|
@@ -126,9 +122,8 @@ export async function renderDrawing(input) {
|
|
|
126
122
|
// Add variable resolution warnings to output
|
|
127
123
|
varWarnings.forEach((w) => warnings.push(`[Variables] ${w}`));
|
|
128
124
|
// Apply variables to template (substitute {{vars.*}} references)
|
|
129
|
-
template = applyTemplateVariables(template, values);
|
|
125
|
+
template = applyTemplateVariables(template, values, warnings);
|
|
130
126
|
}
|
|
131
|
-
const renderLayout = getRenderLayout();
|
|
132
127
|
// ---- Collect viewport elements from template ----
|
|
133
128
|
const viewports = template.elements.filter((el) => el.kind === 'viewport');
|
|
134
129
|
if (!viewports.length) {
|
|
@@ -136,19 +131,28 @@ export async function renderDrawing(input) {
|
|
|
136
131
|
}
|
|
137
132
|
// ---- Fast path: pre-built models provided directly ----
|
|
138
133
|
if (input.models) {
|
|
134
|
+
if (options?.roomLabels) {
|
|
135
|
+
warnings.push('options.roomLabels is ignored on the models path — use a template labels element instead.');
|
|
136
|
+
}
|
|
137
|
+
// productEntries: one flat list for all viewports, or per-viewport record.
|
|
138
|
+
const entriesInput = options?.productEntries;
|
|
139
|
+
const entriesFor = (vpId) => Array.isArray(entriesInput) ? entriesInput : (entriesInput?.[vpId] ?? []);
|
|
140
|
+
const allEntries = Array.isArray(entriesInput)
|
|
141
|
+
? entriesInput
|
|
142
|
+
: Object.values(entriesInput ?? {}).flat();
|
|
139
143
|
// Build items: explicit viewportItems take priority, then auto-build from productEntries
|
|
140
144
|
let viewportsData;
|
|
141
145
|
if (options?.viewportItems) {
|
|
142
146
|
const emptyDefaults = Object.fromEntries(viewports.map((vp) => [vp.id, { items: [] }]));
|
|
143
147
|
viewportsData = { ...emptyDefaults, ...options.viewportItems };
|
|
144
148
|
}
|
|
145
|
-
else if (
|
|
149
|
+
else if (allEntries.length) {
|
|
146
150
|
// Auto-build items per viewport from raw product entries
|
|
147
151
|
const sampleColor = getSampleColor();
|
|
148
152
|
viewportsData = {};
|
|
149
153
|
for (const vp of viewports) {
|
|
150
154
|
viewportsData[vp.id] = {
|
|
151
|
-
items: buildItemsFromEntries(
|
|
155
|
+
items: buildItemsFromEntries(entriesFor(vp.id), vp.fills, sampleColor)
|
|
152
156
|
};
|
|
153
157
|
}
|
|
154
158
|
}
|
|
@@ -176,14 +180,22 @@ export async function renderDrawing(input) {
|
|
|
176
180
|
}
|
|
177
181
|
}
|
|
178
182
|
}
|
|
179
|
-
if (reqs.
|
|
180
|
-
|
|
183
|
+
else if (reqs.propertyPaths.length > 0 ||
|
|
184
|
+
template.elements.some((el) => el.kind === 'labels' || el.kind === 'legend')) {
|
|
185
|
+
// Item-driven features with zero items is almost always a missing
|
|
186
|
+
// productEntries/viewportItems input, not an intentionally empty sheet.
|
|
187
|
+
warnings.push('Template uses item data (labels/legend/where-filters) but no items were provided — pass options.productEntries or options.viewportItems.');
|
|
188
|
+
}
|
|
189
|
+
if (reqs.usesRemoteResources && !template.allowRemoteResources && !options?.allowRemoteResources) {
|
|
190
|
+
warnings.push('Template uses remote resources but allowRemoteResources is not enabled.');
|
|
181
191
|
}
|
|
182
192
|
// Build metadata from product entries (same as standard path)
|
|
183
|
-
|
|
184
|
-
|
|
193
|
+
// Caller-supplied metadata first: entries only cover cut-bearing products, but
|
|
194
|
+
// include filtering must classify products whose geometry never crosses the cut
|
|
195
|
+
// (furniture below a plan cut) - renderTemplateSheet supplies the full map.
|
|
196
|
+
const metadataById = { ...(options?.metadataById ?? {}), ...buildMetadataMap(allEntries) };
|
|
185
197
|
const result = await renderLayout(template, layoutData, input.models, {
|
|
186
|
-
|
|
198
|
+
allowRemoteResources: template.allowRemoteResources ?? options?.allowRemoteResources,
|
|
187
199
|
qrContext: options?.qrContext,
|
|
188
200
|
metadataById
|
|
189
201
|
});
|
|
@@ -210,7 +222,6 @@ export async function renderDrawing(input) {
|
|
|
210
222
|
// ---- Build section state + model view per viewport ----
|
|
211
223
|
const models = {};
|
|
212
224
|
const entriesByViewport = {};
|
|
213
|
-
const sectionStateCache = new Map();
|
|
214
225
|
for (const vp of viewports) {
|
|
215
226
|
const sectionResult = sections[vp.id];
|
|
216
227
|
if (!sectionResult?.perProduct?.length) {
|
|
@@ -218,38 +229,38 @@ export async function renderDrawing(input) {
|
|
|
218
229
|
continue;
|
|
219
230
|
}
|
|
220
231
|
entriesByViewport[vp.id] = sectionResult.perProduct;
|
|
221
|
-
// Dedup: skip if already built for this viewport key
|
|
222
|
-
if (sectionStateCache.has(vp.id)) {
|
|
223
|
-
const cached = sectionStateCache.get(vp.id);
|
|
224
|
-
if (cached) {
|
|
225
|
-
models[vp.id] = sectionStateToModelView(cached);
|
|
226
|
-
}
|
|
227
|
-
continue;
|
|
228
|
-
}
|
|
229
232
|
const resolved = resolveLineStyles(vp);
|
|
230
233
|
// Estimate label font size from template style and section bounds
|
|
231
234
|
const labelFontSize = estimateLabelFontSize(template, vp, sectionResult.perProduct);
|
|
232
|
-
// Extract clip polygon from section results if clip config is present
|
|
235
|
+
// Extract clip polygon from section results if clip config is present.
|
|
236
|
+
// Matching semantics MUST mirror matchesFilter (viewportPrep/labels/
|
|
237
|
+
// legend all use it on the same clip config): class optional,
|
|
238
|
+
// Ifc prefix optional, case-insensitive values, arrays mean any-of.
|
|
233
239
|
let clipPolygon;
|
|
234
|
-
if (vp.clip?.where
|
|
235
|
-
const clipClass = Array.isArray(vp.clip.class) ? vp.clip.class : [vp.clip.class];
|
|
240
|
+
if (vp.clip?.where) {
|
|
241
|
+
const clipClass = vp.clip.class ? (Array.isArray(vp.clip.class) ? vp.clip.class : [vp.clip.class]) : null;
|
|
236
242
|
const clipEntries = sectionResult.perProduct.filter((entry) => {
|
|
237
243
|
const product = entry.product;
|
|
238
|
-
|
|
239
|
-
|
|
244
|
+
// Shared helper rather than product.class.is(): that compares with ===, so a clip
|
|
245
|
+
// filter of "SPACE" or "IFCWALL" selected nothing while labels and legend — reading
|
|
246
|
+
// the same clip config through matchesFilter — matched it. The clip silently did
|
|
247
|
+
// not apply, with no warning anywhere.
|
|
248
|
+
if (!matchesProductClass(product, clipClass ?? undefined))
|
|
240
249
|
return false;
|
|
241
|
-
// Match where condition using T8-aware property resolution
|
|
242
250
|
for (const [path, expected] of Object.entries(vp.clip.where)) {
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
251
|
+
const actual = normalizeValue(resolveProductProperty(product, path));
|
|
252
|
+
const matches = Array.isArray(expected)
|
|
253
|
+
? expected.some((v) => normalizeValue(v) === actual)
|
|
254
|
+
: actual === normalizeValue(expected);
|
|
255
|
+
if (!matches)
|
|
247
256
|
return false;
|
|
248
257
|
}
|
|
249
258
|
return true;
|
|
250
259
|
});
|
|
251
260
|
if (clipEntries.length) {
|
|
252
|
-
clipPolygon = clipEntries.flatMap((entry) => (entry.polylines || []).map((pl) => (pl.points || [])
|
|
261
|
+
clipPolygon = clipEntries.flatMap((entry) => (entry.polylines || []).map((pl) => (pl.points || [])
|
|
262
|
+
.map((p) => readXZ(p))
|
|
263
|
+
.filter((p) => p.x !== null && p.z !== null)));
|
|
253
264
|
}
|
|
254
265
|
}
|
|
255
266
|
// Convert planeNormal array to object with x, y, z if present
|
|
@@ -272,7 +283,6 @@ export async function renderDrawing(input) {
|
|
|
272
283
|
clipPolygon,
|
|
273
284
|
planeNormal
|
|
274
285
|
});
|
|
275
|
-
sectionStateCache.set(vp.id, state);
|
|
276
286
|
if (!state) {
|
|
277
287
|
warnings.push(`No geometry for viewport '${vp.id}'.`);
|
|
278
288
|
continue;
|
|
@@ -315,14 +325,17 @@ export async function renderDrawing(input) {
|
|
|
315
325
|
}
|
|
316
326
|
// ---- Build metadata from all section entries ----
|
|
317
327
|
const allEntries = Object.values(entriesByViewport).flat();
|
|
318
|
-
|
|
328
|
+
// Caller-supplied metadata first: entries only cover cut-bearing products, but
|
|
329
|
+
// include filtering must classify products whose geometry never crosses the cut
|
|
330
|
+
// (furniture below a plan cut) - renderTemplateSheet supplies the full map.
|
|
331
|
+
const metadataById = { ...(options?.metadataById ?? {}), ...buildMetadataMap(allEntries) };
|
|
319
332
|
// ---- Assemble layout data ----
|
|
320
333
|
const layoutData = {
|
|
321
334
|
viewports: viewportsData
|
|
322
335
|
};
|
|
323
336
|
// ---- Render ----
|
|
324
337
|
const result = await renderLayout(template, layoutData, models, {
|
|
325
|
-
|
|
338
|
+
allowRemoteResources: template.allowRemoteResources ?? options?.allowRemoteResources,
|
|
326
339
|
qrContext: options?.qrContext,
|
|
327
340
|
metadataById
|
|
328
341
|
});
|
|
@@ -388,9 +401,8 @@ function estimateLabelFontSize(template, vp, perProduct) {
|
|
|
388
401
|
if (!polyline.points)
|
|
389
402
|
continue;
|
|
390
403
|
for (const pt of polyline.points) {
|
|
391
|
-
const px =
|
|
392
|
-
|
|
393
|
-
if (Number.isFinite(px) && Number.isFinite(pz)) {
|
|
404
|
+
const { x: px, z: pz } = readXZ(pt);
|
|
405
|
+
if (px !== null && pz !== null) {
|
|
394
406
|
if (px < minX)
|
|
395
407
|
minX = px;
|
|
396
408
|
if (px > maxX)
|
|
@@ -446,56 +458,63 @@ export const BUILTIN_HIDDEN_DEFAULTS = {
|
|
|
446
458
|
export const CATEGORY_BUILTIN_OVERRIDES = {
|
|
447
459
|
cutLines: { widthMm: 0.02 },
|
|
448
460
|
hiddenLines: BUILTIN_HIDDEN_DEFAULTS,
|
|
461
|
+
// Occluded silhouettes follow the hidden drafting convention out of the box.
|
|
462
|
+
silhouettesHidden: BUILTIN_HIDDEN_DEFAULTS,
|
|
449
463
|
outlineHidden: BUILTIN_HIDDEN_DEFAULTS
|
|
450
464
|
};
|
|
465
|
+
/** Visibility group of each category; keyed to the `defaultVisibleLines`/`defaultHiddenLines` template keys. `stairArrows` is annotation, not geometry, and belongs to neither group. */
|
|
466
|
+
const CATEGORY_VISIBILITY_GROUP = {
|
|
467
|
+
cutLines: 'defaultVisibleLines',
|
|
468
|
+
visibleLines: 'defaultVisibleLines',
|
|
469
|
+
silhouettesVisible: 'defaultVisibleLines',
|
|
470
|
+
silhouettesHidden: 'defaultHiddenLines',
|
|
471
|
+
featureEdges: 'defaultVisibleLines',
|
|
472
|
+
outlineVisible: 'defaultVisibleLines',
|
|
473
|
+
hiddenLines: 'defaultHiddenLines',
|
|
474
|
+
outlineHidden: 'defaultHiddenLines'
|
|
475
|
+
};
|
|
451
476
|
/**
|
|
452
|
-
* Resolve the effective line style for
|
|
477
|
+
* Resolve the effective line style for one category — the single source of
|
|
478
|
+
* truth used by both the slab plan path (slabModelView) and the drawing path.
|
|
453
479
|
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
480
|
+
* Cascade, weakest first: built-in defaults → `default` → built-in category
|
|
481
|
+
* defaults → `defaultVisibleLines`/`defaultHiddenLines` (the category's
|
|
482
|
+
* visibility group) → the category's own key.
|
|
483
|
+
*/
|
|
484
|
+
export function resolveCategoryLineStyle(category, lineStyles) {
|
|
485
|
+
const group = CATEGORY_VISIBILITY_GROUP[category];
|
|
486
|
+
return {
|
|
487
|
+
...BUILTIN_LINE_DEFAULTS,
|
|
488
|
+
...(lineStyles?.default ?? {}),
|
|
489
|
+
...(CATEGORY_BUILTIN_OVERRIDES[category] ?? {}),
|
|
490
|
+
...((group && lineStyles?.[group]) ?? {}),
|
|
491
|
+
...(lineStyles?.[category] ?? {})
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Resolve the effective line style for every category via
|
|
496
|
+
* {@link resolveCategoryLineStyle} (shared with the slab plan path).
|
|
456
497
|
*/
|
|
457
498
|
function resolveLineStyles(vp) {
|
|
458
499
|
const ls = vp.lineStyles;
|
|
459
|
-
// Base default: lineStyles.default → shorthand → built-in
|
|
460
500
|
const base = {
|
|
461
501
|
...BUILTIN_LINE_DEFAULTS,
|
|
462
|
-
...(vp.lineWidthMm !== undefined ? { widthMm: vp.lineWidthMm } : {}),
|
|
463
|
-
...(vp.lineColor !== undefined ? { color: vp.lineColor } : {}),
|
|
464
502
|
...(ls?.default ?? {})
|
|
465
503
|
};
|
|
466
504
|
const categories = [
|
|
467
505
|
'cutLines',
|
|
468
506
|
'visibleLines',
|
|
469
507
|
'hiddenLines',
|
|
470
|
-
'
|
|
508
|
+
'silhouettesVisible',
|
|
509
|
+
'silhouettesHidden',
|
|
471
510
|
'featureEdges',
|
|
472
511
|
'stairArrows',
|
|
473
512
|
'outlineVisible',
|
|
474
513
|
'outlineHidden'
|
|
475
514
|
];
|
|
476
|
-
// Category group mapping: individual categories inherit from their group style
|
|
477
|
-
const categoryGroups = {
|
|
478
|
-
cutLines: 'visibleLines',
|
|
479
|
-
visibleLines: 'visibleLines',
|
|
480
|
-
silhouettes: 'visibleLines',
|
|
481
|
-
featureEdges: 'visibleLines',
|
|
482
|
-
outlineVisible: 'visibleLines',
|
|
483
|
-
hiddenLines: 'hiddenLines',
|
|
484
|
-
outlineHidden: 'hiddenLines',
|
|
485
|
-
stairArrows: 'stairArrows'
|
|
486
|
-
};
|
|
487
515
|
const byCategory = {};
|
|
488
516
|
for (const cat of categories) {
|
|
489
|
-
|
|
490
|
-
const groupName = categoryGroups[cat];
|
|
491
|
-
const groupStyle = ls?.[groupName]; // Group style (visibleLines, hiddenLines, stairArrows)
|
|
492
|
-
const categoryOverride = ls?.[cat]; // Individual category settings (enable/disable)
|
|
493
|
-
byCategory[cat] = {
|
|
494
|
-
...base,
|
|
495
|
-
...(builtinOverride ?? {}),
|
|
496
|
-
...(groupStyle ?? {}), // Apply group style first
|
|
497
|
-
...(categoryOverride ?? {}) // Then individual overrides (enable/disable)
|
|
498
|
-
};
|
|
517
|
+
byCategory[cat] = resolveCategoryLineStyle(cat, ls);
|
|
499
518
|
}
|
|
500
519
|
return { default: base, byCategory };
|
|
501
520
|
}
|
|
@@ -510,7 +529,7 @@ export function resolveFillColor(item, product, fills, sampleColor) {
|
|
|
510
529
|
if (!fills?.length)
|
|
511
530
|
return undefined;
|
|
512
531
|
for (const rule of fills) {
|
|
513
|
-
if (!
|
|
532
|
+
if (!matchesFilter(item, rule.class, rule.where))
|
|
514
533
|
continue;
|
|
515
534
|
if (rule.fill === 'sample') {
|
|
516
535
|
const sampled = sampleColor(product);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderDrawing.js","sourceRoot":"/","sources":["layout/renderDrawing.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SectionRenderState, SectionPath, SectionLabel } from '@twinfinity/geometry';\nimport { sectionStateToModelView, computePolylinesCenter } from './itemBuilders';\nimport { buildMetadataMap, normalizePropertySets, resolveIfcClassName, resolveIfcClassId } from './metadata';\nimport { applyLineStyleToPaths } from './utils';\nimport { analyzeTemplate } from './analyzeTemplate';\nimport { matchesV2Filter } from './filters';\nimport type {\n LayoutTemplate,\n ViewportElement,\n ViewportLineStyle,\n FillRule,\n SvgModelView,\n SectionResult,\n RenderDrawingInput,\n RenderDrawingResult,\n NormalizedProductItem,\n LabelStyle\n} from './types';\nimport { getProp } from './typeGuards';\n\n// ---------------------------------------------------------------------------\n// Local type declarations for optional peer-dependency APIs.\n// Declared inline to avoid pulling @babylonjs/core and @twinfinity/core into\n// print-layout's compile-time dependency graph.\n// ---------------------------------------------------------------------------\n\ninterface SampledColor {\n color: { r: number; g: number; b: number };\n alpha: number;\n}\n\ninterface ExternalSections {\n buildSectionStateForEntries: (\n perProduct: unknown[],\n options: {\n viewport?: { viewMinX: number; viewMaxX: number; viewMinZ: number; viewMaxZ: number };\n strokeWidth?: number;\n labelFontSize?: number;\n fills?: Array<{ class?: string | string[]; fillOpacity?: number; matchClipFilter?: boolean }>;\n includeMeta?: boolean;\n includeLabels?: boolean;\n buildLabels?: (products: unknown[], fontSize: number) => unknown[];\n clipPolygon?: Array<Array<{ x: number; z: number }>>;\n planeNormal?: unknown;\n }\n ) => (SectionRenderState & { rawPaths?: SectionPath[]; rawLabels?: SectionLabel[] }) | null;\n}\n\ninterface ExternalGeometry {\n sampleProductColorRgba: (product: unknown) => SampledColor | undefined;\n buildRoomLabels: (\n entries: unknown[],\n fontSize: number,\n options: { labelPath: string; classFilter?: string }\n ) => SectionLabel[];\n}\n\n// These were previously lazy-loaded via require() from @measurement-tools/* packages.\n// Now they are part of @twinfinity/printing (this package) and @twinfinity/geometry.\nimport { buildSectionStateForEntries, resolveProductProperty } from '../sections';\n\n// Wrap into the ExternalSections shape for backward compat with the rest of this file.\nconst _sections: ExternalSections = {\n buildSectionStateForEntries: (perProduct, options) => {\n type Entries = Parameters<typeof buildSectionStateForEntries>[0];\n type Opts = Parameters<typeof buildSectionStateForEntries>[1];\n return buildSectionStateForEntries(perProduct as Entries, {\n ...options,\n fills: options.fills as Opts['fills'],\n buildLabels: options.buildLabels as Opts['buildLabels'],\n planeNormal: options.planeNormal as Opts['planeNormal']\n });\n }\n};\nfunction getSections(): ExternalSections {\n return _sections;\n}\n\n// sampleProductColorRgba: duck-type access to product mesh style color.\n// buildRoomLabels: requires product-geometry which this package can't depend on.\n// Consumers must provide buildRoomLabels via options if room labels are needed.\nconst _geometry: ExternalGeometry = {\n sampleProductColorRgba: (product: unknown): SampledColor | undefined => {\n /** Duck-typed mesh with optional color-access methods. */\n interface DuckMesh {\n copyColorTo?: (out: Uint8Array, offset: number) => void;\n getColorComponent?: (index: number) => number;\n style?: { surfaceColor?: readonly number[]; color?: readonly number[] };\n }\n const p = product as Record<string, unknown>;\n const meshes = (p?.meshes ?? p?.productMeshes) as DuckMesh[] | undefined;\n if (!meshes?.length) return undefined;\n\n const rgba = new Uint8Array(4);\n for (const mesh of meshes) {\n try {\n if (typeof mesh.copyColorTo === 'function') {\n mesh.copyColorTo(rgba, 0);\n } else if (typeof mesh.getColorComponent === 'function') {\n rgba[0] = mesh.getColorComponent(0);\n rgba[1] = mesh.getColorComponent(1);\n rgba[2] = mesh.getColorComponent(2);\n rgba[3] = mesh.getColorComponent(3);\n } else {\n const style = mesh.style;\n const c = style?.surfaceColor ?? style?.color;\n if (c) {\n // surfaceColor values may be 0–1 or 0–255; normalize to 0–1\n const maxVal = Math.max(c[0], c[1], c[2]);\n const scale = maxVal > 1 ? 1 / 255 : 1;\n return {\n color: { r: c[0] * scale, g: c[1] * scale, b: c[2] * scale },\n alpha: (c[3] ?? (maxVal > 1 ? 255 : 1)) * scale\n };\n }\n continue;\n }\n } catch {\n continue;\n }\n const [r, g, b, a] = rgba;\n if (a === 0 && r === 0 && g === 0 && b === 0) continue;\n return { color: { r: r / 255, g: g / 255, b: b / 255 }, alpha: a / 255 };\n }\n return undefined;\n },\n buildRoomLabels: () => [] // Requires product-geometry — consumer provides via options\n};\nfunction getGeometry(): ExternalGeometry {\n return _geometry;\n}\nfunction getSampleColor(): (product: unknown) => SampledColor | undefined {\n return _geometry.sampleProductColorRgba;\n}\n\n// Late-binding for renderLayout to break circular dependency.\n// renderDrawing is imported by index.ts which defines renderLayout.\n// The binding is set by index.ts after definition via setRenderLayoutBinding().\nlet _renderLayout:\n | ((\n template: LayoutTemplate,\n data: any,\n models: Record<string, SvgModelView>,\n options?: any\n ) => Promise<{ svg: string; viewportScales: any; warnings: string[] }>)\n | null = null;\n\n/** Called by index.ts to register renderLayout without a circular import. */\nexport function setRenderLayoutBinding(fn: NonNullable<typeof _renderLayout>): void {\n _renderLayout = fn;\n}\n\nfunction getRenderLayout(): NonNullable<typeof _renderLayout> {\n if (!_renderLayout) {\n throw new Error(\n 'renderLayout not initialized. Ensure @twinfinity/printing index is imported before calling renderDrawing.'\n );\n }\n return _renderLayout;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * High-level entry point that converts raw plane-section results and a layout\n * template into a ready-to-print SVG string.\n *\n * Internalizes all data wiring (section → SVG, item extraction, color sampling,\n * metadata building, legend/label data) that previously required ~350 lines of\n * app-side boilerplate.\n *\n * ```ts\n * const section = computePlaneSectionsForProducts(products, plane, { includeInvisible: true });\n * const { svg, warnings } = await renderDrawing({\n * template,\n * sections: { main: section },\n * options: {\n * allowRemoteAssets: true,\n * qrContext: { host, containerName, planeHeight },\n * productFields: { idPath: \"propertySets.BIP.spacenumber.value\", ... },\n * roomLabels: { labelPath: \"BIP.spacename\", classFilter: \"space\" },\n * },\n * });\n * ```\n */\nexport async function renderDrawing(input: RenderDrawingInput): Promise<RenderDrawingResult> {\n const { options } = input;\n const warnings: string[] = [];\n\n // ---- Resolve template variables (if present) ----\n // This happens FIRST to ensure all {{vars.*}} references are resolved before validation/rendering\n let template = input.template;\n if (template.variables) {\n const { resolveTemplateValues, applyTemplateVariables } = await import('./templateVariables');\n const { values, warnings: varWarnings } = resolveTemplateValues(template, options?.variables);\n\n // Add variable resolution warnings to output\n varWarnings.forEach((w) => warnings.push(`[Variables] ${w}`));\n\n // Apply variables to template (substitute {{vars.*}} references)\n template = applyTemplateVariables(template, values);\n }\n\n const renderLayout = getRenderLayout();\n\n // ---- Collect viewport elements from template ----\n const viewports = template.elements.filter((el) => el.kind === 'viewport') as ViewportElement[];\n if (!viewports.length) {\n return { svg: '', warnings: ['No viewport elements in template.'] };\n }\n\n // ---- Fast path: pre-built models provided directly ----\n if (input.models) {\n // Build items: explicit viewportItems take priority, then auto-build from productEntries\n let viewportsData: Record<string, { items: NormalizedProductItem[] }>;\n\n if (options?.viewportItems) {\n const emptyDefaults = Object.fromEntries(\n viewports.map((vp) => [vp.id, { items: [] as NormalizedProductItem[] }])\n );\n viewportsData = { ...emptyDefaults, ...options.viewportItems };\n } else if (options?.productEntries?.length) {\n // Auto-build items per viewport from raw product entries\n const sampleColor = getSampleColor();\n viewportsData = {};\n for (const vp of viewports) {\n viewportsData[vp.id] = {\n items: buildItemsFromEntries(options.productEntries, vp.fills, sampleColor)\n };\n }\n } else {\n viewportsData = Object.fromEntries(\n viewports.map((vp) => [vp.id, { items: [] as NormalizedProductItem[] }])\n );\n }\n\n const layoutData = { viewports: viewportsData };\n\n // Early input analysis: warn about mismatches between template and provided data\n const reqs = analyzeTemplate(template);\n\n for (const vpId of reqs.viewportIds) {\n if (!input.models[vpId]) {\n warnings.push(`Template viewport '${vpId}' has no model — it will render empty.`);\n }\n }\n\n const allItems = Object.values(viewportsData).flatMap((v) => v.items);\n if (allItems.length > 0) {\n for (const path of reqs.propertyPaths) {\n const parts = path.split('.');\n if (parts.length < 2) continue;\n const [setName, propName] = parts;\n const hasIt = allItems.some((item) => item.propertySets?.[setName]?.[propName]?.value !== undefined);\n if (!hasIt) {\n warnings.push(`Template references property '${path}' but no items provide it.`);\n }\n }\n }\n\n if (reqs.usesRemoteAssets && !template.allowRemoteAssets && !options?.allowRemoteAssets) {\n warnings.push('Template uses remote assets but allowRemoteAssets is not enabled.');\n }\n\n // Build metadata from product entries (same as standard path)\n const metadataEntries = options?.productEntries ?? [];\n const metadataById = buildMetadataMap(metadataEntries);\n\n const result = await renderLayout(template, layoutData, input.models, {\n allowRemoteAssets: template.allowRemoteAssets ?? options?.allowRemoteAssets,\n qrContext: options?.qrContext,\n metadataById\n });\n\n return {\n svg: result.svg,\n warnings: [...warnings, ...result.warnings]\n };\n }\n\n // ---- Standard path: build models from section results ----\n if (!input.sections) {\n return { svg: '', warnings: ['Either sections or models must be provided.'] };\n }\n\n const { buildSectionStateForEntries } = getSections();\n const { sampleProductColorRgba, buildRoomLabels } = getGeometry();\n\n // Normalize sections: single SectionResult → map to all viewports\n const isSingle = !!(input.sections as SectionResult).perProduct;\n const sections: Record<string, SectionResult> = isSingle\n ? Object.fromEntries(viewports.map((vp) => [vp.id, input.sections as SectionResult]))\n : (input.sections as Record<string, SectionResult>);\n\n // Auto-detect whether the template has its own labels elements.\n // If so, do NOT embed labels in the section SVG (would cause duplicates).\n const hasTemplateLabelElements = template.elements.some((el) => el.kind === 'labels');\n const roomLabelCfg = hasTemplateLabelElements ? undefined : options?.roomLabels;\n\n // ---- Build section state + model view per viewport ----\n const models: Record<string, SvgModelView> = {};\n const entriesByViewport: Record<string, SectionResult['perProduct']> = {};\n const sectionStateCache = new Map<string, SectionRenderState | null>();\n\n for (const vp of viewports) {\n const sectionResult = sections[vp.id];\n if (!sectionResult?.perProduct?.length) {\n warnings.push(`No section data for viewport '${vp.id}'.`);\n continue;\n }\n\n entriesByViewport[vp.id] = sectionResult.perProduct;\n\n // Dedup: skip if already built for this viewport key\n if (sectionStateCache.has(vp.id)) {\n const cached = sectionStateCache.get(vp.id);\n if (cached) {\n models[vp.id] = sectionStateToModelView(cached);\n }\n continue;\n }\n\n const resolved = resolveLineStyles(vp);\n\n // Estimate label font size from template style and section bounds\n const labelFontSize = estimateLabelFontSize(template, vp, sectionResult.perProduct);\n\n // Extract clip polygon from section results if clip config is present\n let clipPolygon: Array<Array<{ x: number; z: number }>> | undefined;\n if (vp.clip?.where && vp.clip.class) {\n const clipClass = Array.isArray(vp.clip.class) ? vp.clip.class : [vp.clip.class];\n const clipEntries = sectionResult.perProduct.filter((entry: any) => {\n const product = entry.product;\n const matchesClass = clipClass.some((c: string) => product.class?.is?.(c));\n if (!matchesClass) return false;\n // Match where condition using T8-aware property resolution\n for (const [path, expected] of Object.entries(vp.clip!.where!)) {\n const actualValue = resolveProductProperty(product, path);\n if (actualValue === undefined) return false;\n if (actualValue !== expected) return false;\n }\n return true;\n });\n if (clipEntries.length) {\n clipPolygon = clipEntries.flatMap((entry: any) =>\n (entry.polylines || []).map((pl: any) => (pl.points || []).map((p: any) => ({ x: p.x, z: p.z })))\n );\n }\n }\n\n // Convert planeNormal array to object with x, y, z if present\n let planeNormal: unknown = undefined;\n if (vp.planeNormal && Array.isArray(vp.planeNormal) && vp.planeNormal.length === 3) {\n planeNormal = { x: vp.planeNormal[0], y: vp.planeNormal[1], z: vp.planeNormal[2] };\n }\n\n type SectionStateWithRaw = SectionRenderState & { rawPaths?: SectionPath[]; rawLabels?: SectionLabel[] };\n const state: SectionStateWithRaw | null = buildSectionStateForEntries(sectionResult.perProduct, {\n strokeWidth: resolved.default.widthMm,\n labelFontSize,\n fills: vp.fills,\n includeMeta: true,\n includeLabels: !!roomLabelCfg,\n buildLabels: roomLabelCfg\n ? (products, fontSize) =>\n buildRoomLabels(products, fontSize, {\n labelPath: roomLabelCfg.labelPath,\n classFilter: roomLabelCfg.classFilter\n })\n : undefined,\n clipPolygon,\n planeNormal\n });\n\n sectionStateCache.set(vp.id, state);\n\n if (!state) {\n warnings.push(`No geometry for viewport '${vp.id}'.`);\n continue;\n }\n\n // Apply line style overrides from viewport config\n let finalState: SectionStateWithRaw = state;\n const defaultStyle = resolved.default;\n if (defaultStyle.color || defaultStyle.widthMm) {\n const style: { stroke?: string; strokeWidth?: number } = {};\n if (defaultStyle.color) style.stroke = defaultStyle.color;\n if (defaultStyle.widthMm) style.strokeWidth = defaultStyle.widthMm;\n finalState = {\n ...state,\n paths: applyLineStyleToPaths(state.paths, style)\n };\n if (state.rawPaths) {\n finalState.rawPaths = applyLineStyleToPaths(state.rawPaths, style);\n }\n }\n\n const labelStyle: LabelStyle | undefined = template.styles?.body\n ? {\n fill: template.styles.body.color ?? BUILTIN_LABEL_DEFAULTS.fill,\n fontFamily: template.styles.body.fontFamily ?? BUILTIN_LABEL_DEFAULTS.fontFamily,\n fontWeight: template.styles.body.fontWeight ?? BUILTIN_LABEL_DEFAULTS.fontWeight\n }\n : undefined;\n\n models[vp.id] = sectionStateToModelView(finalState, labelStyle);\n }\n\n // ---- Build items per viewport ----\n const viewportsData: Record<string, { items: NormalizedProductItem[] }> = {};\n\n for (const vp of viewports) {\n const entries = entriesByViewport[vp.id];\n if (!entries) {\n viewportsData[vp.id] = { items: [] };\n continue;\n }\n\n viewportsData[vp.id] = { items: buildItemsFromEntries(entries, vp.fills, sampleProductColorRgba) };\n }\n\n // ---- Build metadata from all section entries ----\n const allEntries = Object.values(entriesByViewport).flat();\n const metadataById = buildMetadataMap(allEntries);\n\n // ---- Assemble layout data ----\n const layoutData = {\n viewports: viewportsData\n };\n\n // ---- Render ----\n const result = await renderLayout(template, layoutData, models, {\n allowRemoteAssets: template.allowRemoteAssets ?? options?.allowRemoteAssets,\n qrContext: options?.qrContext,\n metadataById\n });\n\n return {\n svg: result.svg,\n warnings: [...warnings, ...result.warnings]\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build NormalizedProductItems from per-product entries.\n *\n * Shared between the standard path (plane sections) and the models path\n * (slab sections / pre-built models with productEntries).\n */\nfunction buildItemsFromEntries(\n entries: Array<{ product: unknown; polylines: unknown }>,\n fills: FillRule[] | undefined,\n sampleColor: ((product: unknown) => SampledColor | undefined) | undefined\n): NormalizedProductItem[] {\n return entries.map((entry) => {\n const product = entry.product;\n const propertySets = normalizePropertySets(product);\n const gid = getProp(product, 'gid') ?? getProp(product, 'id');\n const center = computePolylinesCenter(entry);\n const name = getProp(product, 'name') as string | undefined;\n const displayName = typeof name === 'string' && name.trim().length ? name.trim() : gid ? String(gid) : '-';\n const item: NormalizedProductItem = {\n gid: gid ? String(gid) : undefined,\n ifcClass: resolveIfcClassName(product),\n ifcClassId: resolveIfcClassId(product),\n propertySets,\n productId: gid ? String(gid) : '-',\n productName: displayName,\n area: null,\n x: center.x,\n z: center.z,\n text: displayName,\n polylines: entry.polylines as Array<{ points?: Array<{ x: number; z: number }> }>\n };\n\n if (fills?.length && sampleColor) {\n const color = resolveFillColor(item, product, fills, sampleColor);\n if (color) {\n item.color = color;\n }\n }\n\n return item;\n });\n}\n\n/**\n * Estimate label font size in model units from the template body style and the\n * approximate viewport-to-world scale ratio.\n */\nfunction estimateLabelFontSize(\n template: LayoutTemplate,\n vp: ViewportElement,\n perProduct: SectionResult['perProduct']\n): number {\n const templateFontSizeMm = template.styles?.body?.fontSizeMm ?? 3.5;\n\n // Quick world-bounds scan\n let minX = Infinity;\n let maxX = -Infinity;\n let minZ = Infinity;\n let maxZ = -Infinity;\n for (const entry of perProduct) {\n if (!entry.polylines) continue;\n for (const polyline of entry.polylines) {\n if (!polyline.points) continue;\n for (const pt of polyline.points) {\n const px = getProp(pt, 'x');\n const pz = getProp(pt, 'z');\n if (Number.isFinite(px) && Number.isFinite(pz)) {\n if ((px as number) < minX) minX = px as number;\n if ((px as number) > maxX) maxX = px as number;\n if ((pz as number) < minZ) minZ = pz as number;\n if ((pz as number) > maxZ) maxZ = pz as number;\n }\n }\n }\n }\n\n const worldWidth = maxX - minX;\n const worldHeight = maxZ - minZ;\n if (!Number.isFinite(worldWidth) || worldWidth <= 0 || !Number.isFinite(worldHeight) || worldHeight <= 0) {\n return templateFontSizeMm; // Fallback: 1:1 estimate\n }\n\n // Approximate mm-per-model-unit from the viewport dimensions\n const scaleX = vp.widthMm / worldWidth;\n const scaleY = vp.heightMm / worldHeight;\n const mmPerModelUnit = Math.min(scaleX, scaleY);\n\n if (!Number.isFinite(mmPerModelUnit) || mmPerModelUnit <= 0) {\n return templateFontSizeMm;\n }\n\n return templateFontSizeMm / mmPerModelUnit;\n}\n\n// ---------------------------------------------------------------------------\n// Label style defaults\n// ---------------------------------------------------------------------------\n\n/** Built-in label style defaults when template body styles are partially set. */\nexport const BUILTIN_LABEL_DEFAULTS = {\n fill: '#374151',\n fontFamily: '\"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif',\n fontWeight: '300'\n} as const;\n\n// ---------------------------------------------------------------------------\n// Line style defaults & resolution\n// ---------------------------------------------------------------------------\n\n/** Built-in defaults when neither lineStyles nor lineWidthMm/lineColor are set. */\nexport const BUILTIN_LINE_DEFAULTS: Required<ViewportLineStyle> = {\n widthMm: 0.35, // Reasonable default: 0.35mm line width (was 0.01mm - too thin!)\n color: '#1f2937',\n dash: '',\n enabled: true\n};\n\nexport const BUILTIN_HIDDEN_DEFAULTS: Required<ViewportLineStyle> = {\n widthMm: 0.005,\n color: '#9ca3af',\n dash: '4 2',\n enabled: true\n};\n\ntype LineCategory =\n | 'cutLines'\n | 'visibleLines'\n | 'hiddenLines'\n | 'silhouettes'\n | 'featureEdges'\n | 'stairArrows'\n | 'outlineVisible'\n | 'outlineHidden';\n\n/** Category-specific built-in defaults (merged over the global default). */\nexport const CATEGORY_BUILTIN_OVERRIDES: Partial<Record<LineCategory, Partial<ViewportLineStyle>>> = {\n cutLines: { widthMm: 0.02 },\n hiddenLines: BUILTIN_HIDDEN_DEFAULTS,\n outlineHidden: BUILTIN_HIDDEN_DEFAULTS\n};\n\nexport interface ResolvedLineStyles {\n default: Required<ViewportLineStyle>;\n byCategory: Record<LineCategory, Required<ViewportLineStyle>>;\n}\n\n/**\n * Resolve the effective line style for every category.\n *\n * Priority: category entry in `lineStyles` → `lineStyles.default`\n * → `lineWidthMm`/`lineColor` shorthand → built-in defaults.\n */\nfunction resolveLineStyles(vp: ViewportElement): ResolvedLineStyles {\n const ls = vp.lineStyles;\n\n // Base default: lineStyles.default → shorthand → built-in\n const base: Required<ViewportLineStyle> = {\n ...BUILTIN_LINE_DEFAULTS,\n ...(vp.lineWidthMm !== undefined ? { widthMm: vp.lineWidthMm } : {}),\n ...(vp.lineColor !== undefined ? { color: vp.lineColor } : {}),\n ...(ls?.default ?? {})\n } as Required<ViewportLineStyle>;\n\n const categories: LineCategory[] = [\n 'cutLines',\n 'visibleLines',\n 'hiddenLines',\n 'silhouettes',\n 'featureEdges',\n 'stairArrows',\n 'outlineVisible',\n 'outlineHidden'\n ];\n\n // Category group mapping: individual categories inherit from their group style\n const categoryGroups: Record<LineCategory, LineCategory> = {\n cutLines: 'visibleLines',\n visibleLines: 'visibleLines',\n silhouettes: 'visibleLines',\n featureEdges: 'visibleLines',\n outlineVisible: 'visibleLines',\n hiddenLines: 'hiddenLines',\n outlineHidden: 'hiddenLines',\n stairArrows: 'stairArrows'\n };\n\n const byCategory = {} as Record<LineCategory, Required<ViewportLineStyle>>;\n for (const cat of categories) {\n const builtinOverride = CATEGORY_BUILTIN_OVERRIDES[cat];\n const groupName = categoryGroups[cat];\n const groupStyle = ls?.[groupName]; // Group style (visibleLines, hiddenLines, stairArrows)\n const categoryOverride = ls?.[cat]; // Individual category settings (enable/disable)\n\n byCategory[cat] = {\n ...base,\n ...(builtinOverride ?? {}),\n ...(groupStyle ?? {}), // Apply group style first\n ...(categoryOverride ?? {}) // Then individual overrides (enable/disable)\n } as Required<ViewportLineStyle>;\n }\n\n return { default: base, byCategory };\n}\n\n// ---------------------------------------------------------------------------\n// Fill rule helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve fill color for an item based on viewport fill rules.\n * Returns an RGBA tuple [r, g, b, a] (0–255) or undefined if no rule matches.\n */\nexport function resolveFillColor(\n item: NormalizedProductItem,\n product: unknown,\n fills: FillRule[] | undefined,\n sampleColor: (product: unknown) => SampledColor | undefined\n): [number, number, number, number] | undefined {\n if (!fills?.length) return undefined;\n for (const rule of fills) {\n if (!matchesV2Filter(item, rule.class, rule.where)) continue;\n if (rule.fill === 'sample') {\n const sampled = sampleColor(product);\n if (sampled) {\n return [\n Math.round(sampled.color.r * 255),\n Math.round(sampled.color.g * 255),\n Math.round(sampled.color.b * 255),\n Math.round(sampled.alpha * 255)\n ];\n }\n } else {\n return parseHexToRgba(rule.fill);\n }\n break; // first matching rule wins\n }\n return undefined;\n}\n\n/**\n * Parse a CSS hex color string to an RGBA tuple (0–255).\n */\nfunction parseHexToRgba(hex: string): [number, number, number, number] {\n const h = hex.replace(/^#/, '');\n if (h.length === 3) {\n return [parseInt(h[0] + h[0], 16), parseInt(h[1] + h[1], 16), parseInt(h[2] + h[2], 16), 255];\n }\n if (h.length === 6) {\n return [parseInt(h.substring(0, 2), 16), parseInt(h.substring(2, 4), 16), parseInt(h.substring(4, 6), 16), 255];\n }\n if (h.length === 8) {\n return [\n parseInt(h.substring(0, 2), 16),\n parseInt(h.substring(2, 4), 16),\n parseInt(h.substring(4, 6), 16),\n parseInt(h.substring(6, 8), 16)\n ];\n }\n // Fallback: opaque black\n return [0, 0, 0, 255];\n}\n"]}
|
|
1
|
+
{"version":3,"file":"renderDrawing.js","sourceRoot":"/","sources":["layout/renderDrawing.ts"],"names":[],"mappings":"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","sourcesContent":["import type { SectionRenderState, SectionPath, SectionLabel } from '@twinfinity/geometry';\nimport { sectionStateToModelView, computePolylinesCenter, readXZ } from './itemBuilders';\nimport { buildMetadataMap, normalizePropertySets, resolveIfcClassName, resolveIfcClassId } from './metadata';\nimport { applyLineStyleToPaths } from './utils';\nimport { analyzeTemplate } from './analyzeTemplate';\nimport { matchesFilter, matchesProductClass, normalizeValue } from './filters';\nimport type {\n LayoutTemplate,\n ViewportElement,\n ViewportLineStyle,\n ViewportLineStyles,\n FillRule,\n SvgModelView,\n SectionResult,\n RenderDrawingInput,\n RenderDrawingResult,\n NormalizedProductItem,\n ProductPolylineEntry,\n LabelStyle\n} from './types';\nimport { getProp } from './typeGuards';\n\n// ---------------------------------------------------------------------------\n// Local type declarations for optional peer-dependency APIs.\n// Declared inline to avoid pulling @babylonjs/core and @twinfinity/core into\n// print-layout's compile-time dependency graph.\n// ---------------------------------------------------------------------------\n\ninterface SampledColor {\n color: { r: number; g: number; b: number };\n alpha: number;\n}\n\ninterface ExternalSections {\n buildSectionStateForEntries: (\n perProduct: unknown[],\n options: {\n viewport?: { viewMinX: number; viewMaxX: number; viewMinZ: number; viewMaxZ: number };\n strokeWidth?: number;\n labelFontSize?: number;\n fills?: Array<{ class?: string | string[]; fillOpacity?: number; matchClipFilter?: boolean }>;\n includeMeta?: boolean;\n includeLabels?: boolean;\n buildLabels?: (products: unknown[], fontSize: number) => unknown[];\n clipPolygon?: Array<Array<{ x: number; z: number }>>;\n planeNormal?: unknown;\n }\n ) => (SectionRenderState & { rawPaths?: SectionPath[]; rawLabels?: SectionLabel[] }) | null;\n}\n\ninterface ExternalGeometry {\n sampleProductColorRgba: (product: unknown) => SampledColor | undefined;\n buildRoomLabels: (\n entries: unknown[],\n fontSize: number,\n options: { labelPath: string; classFilter?: string }\n ) => SectionLabel[];\n}\n\n// These were previously lazy-loaded via require() from @measurement-tools/* packages.\n// Now they are part of @twinfinity/printing (this package) and @twinfinity/geometry.\nimport { buildSectionStateForEntries, resolveProductProperty } from '../sections';\n\n// Wrap into the ExternalSections shape for backward compat with the rest of this file.\nconst _sections: ExternalSections = {\n buildSectionStateForEntries: (perProduct, options) => {\n type Entries = Parameters<typeof buildSectionStateForEntries>[0];\n type Opts = Parameters<typeof buildSectionStateForEntries>[1];\n return buildSectionStateForEntries(perProduct as Entries, {\n ...options,\n fills: options.fills as Opts['fills'],\n buildLabels: options.buildLabels as Opts['buildLabels'],\n planeNormal: options.planeNormal as Opts['planeNormal']\n });\n }\n};\nfunction getSections(): ExternalSections {\n return _sections;\n}\n\n// sampleProductColorRgba: duck-type access to product mesh style color.\n// buildRoomLabels: requires product-geometry which this package can't depend on.\n// Consumers must provide buildRoomLabels via options if room labels are needed.\nconst _geometry: ExternalGeometry = {\n sampleProductColorRgba: (product: unknown): SampledColor | undefined => {\n /** Duck-typed mesh with optional color-access methods. */\n interface DuckMesh {\n copyColorTo?: (out: Uint8Array, offset: number) => void;\n getColorComponent?: (index: number) => number;\n style?: { surfaceColor?: readonly number[]; color?: readonly number[] };\n }\n const p = product as Record<string, unknown>;\n const meshes = (p?.meshes ?? p?.productMeshes) as DuckMesh[] | undefined;\n if (!meshes?.length) return undefined;\n\n const rgba = new Uint8Array(4);\n for (const mesh of meshes) {\n try {\n if (typeof mesh.copyColorTo === 'function') {\n mesh.copyColorTo(rgba, 0);\n } else if (typeof mesh.getColorComponent === 'function') {\n rgba[0] = mesh.getColorComponent(0);\n rgba[1] = mesh.getColorComponent(1);\n rgba[2] = mesh.getColorComponent(2);\n rgba[3] = mesh.getColorComponent(3);\n } else {\n const style = mesh.style;\n const c = style?.surfaceColor ?? style?.color;\n if (c) {\n // surfaceColor values may be 0–1 or 0–255; normalize to 0–1\n const maxVal = Math.max(c[0], c[1], c[2]);\n const scale = maxVal > 1 ? 1 / 255 : 1;\n return {\n color: { r: c[0] * scale, g: c[1] * scale, b: c[2] * scale },\n alpha: (c[3] ?? (maxVal > 1 ? 255 : 1)) * scale\n };\n }\n continue;\n }\n } catch {\n continue;\n }\n const [r, g, b, a] = rgba;\n if (a === 0 && r === 0 && g === 0 && b === 0) continue;\n return { color: { r: r / 255, g: g / 255, b: b / 255 }, alpha: a / 255 };\n }\n return undefined;\n },\n buildRoomLabels: () => [] // Requires product-geometry — consumer provides via options\n};\nfunction getGeometry(): ExternalGeometry {\n return _geometry;\n}\nfunction getSampleColor(): (product: unknown) => SampledColor | undefined {\n return _geometry.sampleProductColorRgba;\n}\n\nimport { renderLayout } from './renderLayout';\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * High-level entry point that renders a layout template to a ready-to-print\n * SVG string.\n *\n * The inputs form a 2×2 matrix — geometry × item data, each either raw or\n * pre-built:\n *\n * | input | what it is |\n * |---------------------------|--------------------------------------------------|\n * | `sections` | RAW geometry: plane-section results (one shared or per viewport id). |\n * | `models` | PRE-BUILT geometry: `SvgModelView`s per viewport id (e.g. from `slabSectionToModelView`). Needs `rawPaths` with `meta.gid` for highlight/clip/includeClasses. |\n * | `options.productEntries` | RAW item data: per-product world-x/z polylines (`slabPerProductToEntries`); one flat list shared by all viewports or a per-viewport record. Feeds labels/legend/clip/highlight items. |\n * | `options.viewportItems` | PRE-BUILT item data per viewport id (overrides `productEntries`). |\n *\n * Prerequisite: products must have property sets loaded\n * (`await api.ifc.loadPropertySets()` on core BIM objects) — without them\n * every `where` filter matches nothing.\n *\n * ```ts\n * const section = computePlaneSectionsForProducts(products, plane, { includeInvisible: true });\n * const { svg, warnings } = await renderDrawing({\n * template,\n * sections: { main: section },\n * options: {\n * allowRemoteResources: true,\n * qrContext: { host, containerName },\n * roomLabels: { labelPath: \"BIP.spacename\", classFilter: \"space\" },\n * },\n * });\n * ```\n */\nexport async function renderDrawing(input: RenderDrawingInput): Promise<RenderDrawingResult> {\n const { options } = input;\n const warnings: string[] = [];\n\n // ---- Resolve template variables (if present) ----\n // This happens FIRST to ensure all {{vars.*}} references are resolved before validation/rendering\n let template = input.template;\n if (template.variables) {\n const { resolveTemplateValues, applyTemplateVariables } = await import('./templateVariables');\n const { values, warnings: varWarnings } = resolveTemplateValues(template, options?.variables);\n\n // Add variable resolution warnings to output\n varWarnings.forEach((w) => warnings.push(`[Variables] ${w}`));\n\n // Apply variables to template (substitute {{vars.*}} references)\n template = applyTemplateVariables(template, values, warnings);\n }\n\n // ---- Collect viewport elements from template ----\n const viewports = template.elements.filter((el) => el.kind === 'viewport') as ViewportElement[];\n if (!viewports.length) {\n return { svg: '', warnings: ['No viewport elements in template.'] };\n }\n\n // ---- Fast path: pre-built models provided directly ----\n if (input.models) {\n if (options?.roomLabels) {\n warnings.push('options.roomLabels is ignored on the models path — use a template labels element instead.');\n }\n // productEntries: one flat list for all viewports, or per-viewport record.\n const entriesInput = options?.productEntries;\n const entriesFor = (vpId: string): ProductPolylineEntry[] =>\n Array.isArray(entriesInput) ? entriesInput : (entriesInput?.[vpId] ?? []);\n const allEntries: ProductPolylineEntry[] = Array.isArray(entriesInput)\n ? entriesInput\n : Object.values(entriesInput ?? {}).flat();\n\n // Build items: explicit viewportItems take priority, then auto-build from productEntries\n let viewportsData: Record<string, { items: NormalizedProductItem[] }>;\n\n if (options?.viewportItems) {\n const emptyDefaults = Object.fromEntries(\n viewports.map((vp) => [vp.id, { items: [] as NormalizedProductItem[] }])\n );\n viewportsData = { ...emptyDefaults, ...options.viewportItems };\n } else if (allEntries.length) {\n // Auto-build items per viewport from raw product entries\n const sampleColor = getSampleColor();\n viewportsData = {};\n for (const vp of viewports) {\n viewportsData[vp.id] = {\n items: buildItemsFromEntries(entriesFor(vp.id), vp.fills, sampleColor)\n };\n }\n } else {\n viewportsData = Object.fromEntries(\n viewports.map((vp) => [vp.id, { items: [] as NormalizedProductItem[] }])\n );\n }\n\n const layoutData = { viewports: viewportsData };\n\n // Early input analysis: warn about mismatches between template and provided data\n const reqs = analyzeTemplate(template);\n\n for (const vpId of reqs.viewportIds) {\n if (!input.models[vpId]) {\n warnings.push(`Template viewport '${vpId}' has no model — it will render empty.`);\n }\n }\n\n const allItems = Object.values(viewportsData).flatMap((v) => v.items);\n if (allItems.length > 0) {\n for (const path of reqs.propertyPaths) {\n const parts = path.split('.');\n if (parts.length < 2) continue;\n const [setName, propName] = parts;\n const hasIt = allItems.some((item) => item.propertySets?.[setName]?.[propName]?.value !== undefined);\n if (!hasIt) {\n warnings.push(`Template references property '${path}' but no items provide it.`);\n }\n }\n } else if (\n reqs.propertyPaths.length > 0 ||\n template.elements.some((el) => el.kind === 'labels' || el.kind === 'legend')\n ) {\n // Item-driven features with zero items is almost always a missing\n // productEntries/viewportItems input, not an intentionally empty sheet.\n warnings.push(\n 'Template uses item data (labels/legend/where-filters) but no items were provided — pass options.productEntries or options.viewportItems.'\n );\n }\n\n if (reqs.usesRemoteResources && !template.allowRemoteResources && !options?.allowRemoteResources) {\n warnings.push('Template uses remote resources but allowRemoteResources is not enabled.');\n }\n\n // Build metadata from product entries (same as standard path)\n // Caller-supplied metadata first: entries only cover cut-bearing products, but\n // include filtering must classify products whose geometry never crosses the cut\n // (furniture below a plan cut) - renderTemplateSheet supplies the full map.\n const metadataById = { ...(options?.metadataById ?? {}), ...buildMetadataMap(allEntries) };\n\n const result = await renderLayout(template, layoutData, input.models, {\n allowRemoteResources: template.allowRemoteResources ?? options?.allowRemoteResources,\n qrContext: options?.qrContext,\n metadataById\n });\n\n return {\n svg: result.svg,\n warnings: [...warnings, ...result.warnings]\n };\n }\n\n // ---- Standard path: build models from section results ----\n if (!input.sections) {\n return { svg: '', warnings: ['Either sections or models must be provided.'] };\n }\n\n const { buildSectionStateForEntries } = getSections();\n const { sampleProductColorRgba, buildRoomLabels } = getGeometry();\n\n // Normalize sections: single SectionResult → map to all viewports\n const isSingle = !!(input.sections as SectionResult).perProduct;\n const sections: Record<string, SectionResult> = isSingle\n ? Object.fromEntries(viewports.map((vp) => [vp.id, input.sections as SectionResult]))\n : (input.sections as Record<string, SectionResult>);\n\n // Auto-detect whether the template has its own labels elements.\n // If so, do NOT embed labels in the section SVG (would cause duplicates).\n const hasTemplateLabelElements = template.elements.some((el) => el.kind === 'labels');\n const roomLabelCfg = hasTemplateLabelElements ? undefined : options?.roomLabels;\n\n // ---- Build section state + model view per viewport ----\n const models: Record<string, SvgModelView> = {};\n const entriesByViewport: Record<string, SectionResult['perProduct']> = {};\n\n for (const vp of viewports) {\n const sectionResult = sections[vp.id];\n if (!sectionResult?.perProduct?.length) {\n warnings.push(`No section data for viewport '${vp.id}'.`);\n continue;\n }\n\n entriesByViewport[vp.id] = sectionResult.perProduct;\n\n const resolved = resolveLineStyles(vp);\n\n // Estimate label font size from template style and section bounds\n const labelFontSize = estimateLabelFontSize(template, vp, sectionResult.perProduct);\n\n // Extract clip polygon from section results if clip config is present.\n // Matching semantics MUST mirror matchesFilter (viewportPrep/labels/\n // legend all use it on the same clip config): class optional,\n // Ifc prefix optional, case-insensitive values, arrays mean any-of.\n let clipPolygon: Array<Array<{ x: number; z: number }>> | undefined;\n if (vp.clip?.where) {\n const clipClass = vp.clip.class ? (Array.isArray(vp.clip.class) ? vp.clip.class : [vp.clip.class]) : null;\n const clipEntries = sectionResult.perProduct.filter((entry: any) => {\n const product = entry.product;\n // Shared helper rather than product.class.is(): that compares with ===, so a clip\n // filter of \"SPACE\" or \"IFCWALL\" selected nothing while labels and legend — reading\n // the same clip config through matchesFilter — matched it. The clip silently did\n // not apply, with no warning anywhere.\n if (!matchesProductClass(product, clipClass ?? undefined)) return false;\n for (const [path, expected] of Object.entries(vp.clip!.where!)) {\n const actual = normalizeValue(resolveProductProperty(product, path));\n const matches = Array.isArray(expected)\n ? expected.some((v) => normalizeValue(v) === actual)\n : actual === normalizeValue(expected);\n if (!matches) return false;\n }\n return true;\n });\n if (clipEntries.length) {\n clipPolygon = clipEntries.flatMap((entry: any) =>\n (entry.polylines || []).map((pl: any) =>\n (pl.points || [])\n .map((p: any) => readXZ(p))\n .filter(\n (p: { x: number | null; z: number | null }): p is { x: number; z: number } =>\n p.x !== null && p.z !== null\n )\n )\n );\n }\n }\n\n // Convert planeNormal array to object with x, y, z if present\n let planeNormal: unknown = undefined;\n if (vp.planeNormal && Array.isArray(vp.planeNormal) && vp.planeNormal.length === 3) {\n planeNormal = { x: vp.planeNormal[0], y: vp.planeNormal[1], z: vp.planeNormal[2] };\n }\n\n type SectionStateWithRaw = SectionRenderState & { rawPaths?: SectionPath[]; rawLabels?: SectionLabel[] };\n const state: SectionStateWithRaw | null = buildSectionStateForEntries(sectionResult.perProduct, {\n strokeWidth: resolved.default.widthMm,\n labelFontSize,\n fills: vp.fills,\n includeMeta: true,\n includeLabels: !!roomLabelCfg,\n buildLabels: roomLabelCfg\n ? (products, fontSize) =>\n buildRoomLabels(products, fontSize, {\n labelPath: roomLabelCfg.labelPath,\n classFilter: roomLabelCfg.classFilter\n })\n : undefined,\n clipPolygon,\n planeNormal\n });\n\n if (!state) {\n warnings.push(`No geometry for viewport '${vp.id}'.`);\n continue;\n }\n\n // Apply line style overrides from viewport config\n let finalState: SectionStateWithRaw = state;\n const defaultStyle = resolved.default;\n if (defaultStyle.color || defaultStyle.widthMm) {\n const style: { stroke?: string; strokeWidth?: number } = {};\n if (defaultStyle.color) style.stroke = defaultStyle.color;\n if (defaultStyle.widthMm) style.strokeWidth = defaultStyle.widthMm;\n finalState = {\n ...state,\n paths: applyLineStyleToPaths(state.paths, style)\n };\n if (state.rawPaths) {\n finalState.rawPaths = applyLineStyleToPaths(state.rawPaths, style);\n }\n }\n\n const labelStyle: LabelStyle | undefined = template.styles?.body\n ? {\n fill: template.styles.body.color ?? BUILTIN_LABEL_DEFAULTS.fill,\n fontFamily: template.styles.body.fontFamily ?? BUILTIN_LABEL_DEFAULTS.fontFamily,\n fontWeight: template.styles.body.fontWeight ?? BUILTIN_LABEL_DEFAULTS.fontWeight\n }\n : undefined;\n\n models[vp.id] = sectionStateToModelView(finalState, labelStyle);\n }\n\n // ---- Build items per viewport ----\n const viewportsData: Record<string, { items: NormalizedProductItem[] }> = {};\n\n for (const vp of viewports) {\n const entries = entriesByViewport[vp.id];\n if (!entries) {\n viewportsData[vp.id] = { items: [] };\n continue;\n }\n\n viewportsData[vp.id] = { items: buildItemsFromEntries(entries, vp.fills, sampleProductColorRgba) };\n }\n\n // ---- Build metadata from all section entries ----\n const allEntries = Object.values(entriesByViewport).flat();\n // Caller-supplied metadata first: entries only cover cut-bearing products, but\n // include filtering must classify products whose geometry never crosses the cut\n // (furniture below a plan cut) - renderTemplateSheet supplies the full map.\n const metadataById = { ...(options?.metadataById ?? {}), ...buildMetadataMap(allEntries) };\n\n // ---- Assemble layout data ----\n const layoutData = {\n viewports: viewportsData\n };\n\n // ---- Render ----\n const result = await renderLayout(template, layoutData, models, {\n allowRemoteResources: template.allowRemoteResources ?? options?.allowRemoteResources,\n qrContext: options?.qrContext,\n metadataById\n });\n\n return {\n svg: result.svg,\n warnings: [...warnings, ...result.warnings]\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Build NormalizedProductItems from per-product entries.\n *\n * Shared between the standard path (plane sections) and the models path\n * (slab sections / pre-built models with productEntries).\n */\nfunction buildItemsFromEntries(\n entries: Array<{ product: unknown; polylines: unknown }>,\n fills: FillRule[] | undefined,\n sampleColor: ((product: unknown) => SampledColor | undefined) | undefined\n): NormalizedProductItem[] {\n return entries.map((entry) => {\n const product = entry.product;\n const propertySets = normalizePropertySets(product);\n const gid = getProp(product, 'gid') ?? getProp(product, 'id');\n const center = computePolylinesCenter(entry);\n const name = getProp(product, 'name') as string | undefined;\n const displayName = typeof name === 'string' && name.trim().length ? name.trim() : gid ? String(gid) : '-';\n const item: NormalizedProductItem = {\n gid: gid ? String(gid) : undefined,\n ifcClass: resolveIfcClassName(product),\n ifcClassId: resolveIfcClassId(product),\n propertySets,\n productId: gid ? String(gid) : '-',\n productName: displayName,\n area: null,\n x: center.x,\n z: center.z,\n text: displayName,\n polylines: entry.polylines as Array<{ points?: Array<{ x: number; z: number }> }>\n };\n\n if (fills?.length && sampleColor) {\n const color = resolveFillColor(item, product, fills, sampleColor);\n if (color) {\n item.color = color;\n }\n }\n\n return item;\n });\n}\n\n/**\n * Estimate label font size in model units from the template body style and the\n * approximate viewport-to-world scale ratio.\n */\nfunction estimateLabelFontSize(\n template: LayoutTemplate,\n vp: ViewportElement,\n perProduct: SectionResult['perProduct']\n): number {\n const templateFontSizeMm = template.styles?.body?.fontSizeMm ?? 3.5;\n\n // Quick world-bounds scan\n let minX = Infinity;\n let maxX = -Infinity;\n let minZ = Infinity;\n let maxZ = -Infinity;\n for (const entry of perProduct) {\n if (!entry.polylines) continue;\n for (const polyline of entry.polylines) {\n if (!polyline.points) continue;\n for (const pt of polyline.points) {\n const { x: px, z: pz } = readXZ(pt);\n if (px !== null && pz !== null) {\n if (px < minX) minX = px;\n if (px > maxX) maxX = px;\n if (pz < minZ) minZ = pz;\n if (pz > maxZ) maxZ = pz;\n }\n }\n }\n }\n\n const worldWidth = maxX - minX;\n const worldHeight = maxZ - minZ;\n if (!Number.isFinite(worldWidth) || worldWidth <= 0 || !Number.isFinite(worldHeight) || worldHeight <= 0) {\n return templateFontSizeMm; // Fallback: 1:1 estimate\n }\n\n // Approximate mm-per-model-unit from the viewport dimensions\n const scaleX = vp.widthMm / worldWidth;\n const scaleY = vp.heightMm / worldHeight;\n const mmPerModelUnit = Math.min(scaleX, scaleY);\n\n if (!Number.isFinite(mmPerModelUnit) || mmPerModelUnit <= 0) {\n return templateFontSizeMm;\n }\n\n return templateFontSizeMm / mmPerModelUnit;\n}\n\n// ---------------------------------------------------------------------------\n// Label style defaults\n// ---------------------------------------------------------------------------\n\n/** Built-in label style defaults when template body styles are partially set. */\nexport const BUILTIN_LABEL_DEFAULTS = {\n fill: '#374151',\n fontFamily: '\"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif',\n fontWeight: '300'\n} as const;\n\n// ---------------------------------------------------------------------------\n// Line style defaults & resolution\n// ---------------------------------------------------------------------------\n\n/** Built-in defaults when neither lineStyles nor lineWidthMm/lineColor are set. */\nexport const BUILTIN_LINE_DEFAULTS: Required<ViewportLineStyle> = {\n widthMm: 0.35, // Reasonable default: 0.35mm line width (was 0.01mm - too thin!)\n color: '#1f2937',\n dash: '',\n enabled: true\n};\n\nexport const BUILTIN_HIDDEN_DEFAULTS: Required<ViewportLineStyle> = {\n widthMm: 0.005,\n color: '#9ca3af',\n dash: '4 2',\n enabled: true\n};\n\nexport type LineCategory =\n | 'cutLines'\n | 'visibleLines'\n | 'hiddenLines'\n | 'silhouettesVisible'\n | 'silhouettesHidden'\n | 'featureEdges'\n | 'stairArrows'\n | 'outlineVisible'\n | 'outlineHidden';\n\n/** Category-specific built-in defaults (merged over the global default). */\nexport const CATEGORY_BUILTIN_OVERRIDES: Partial<Record<LineCategory, Partial<ViewportLineStyle>>> = {\n cutLines: { widthMm: 0.02 },\n hiddenLines: BUILTIN_HIDDEN_DEFAULTS,\n // Occluded silhouettes follow the hidden drafting convention out of the box.\n silhouettesHidden: BUILTIN_HIDDEN_DEFAULTS,\n outlineHidden: BUILTIN_HIDDEN_DEFAULTS\n};\n\n/** Visibility group of each category; keyed to the `defaultVisibleLines`/`defaultHiddenLines` template keys. `stairArrows` is annotation, not geometry, and belongs to neither group. */\nconst CATEGORY_VISIBILITY_GROUP: Partial<Record<LineCategory, 'defaultVisibleLines' | 'defaultHiddenLines'>> = {\n cutLines: 'defaultVisibleLines',\n visibleLines: 'defaultVisibleLines',\n silhouettesVisible: 'defaultVisibleLines',\n silhouettesHidden: 'defaultHiddenLines',\n featureEdges: 'defaultVisibleLines',\n outlineVisible: 'defaultVisibleLines',\n hiddenLines: 'defaultHiddenLines',\n outlineHidden: 'defaultHiddenLines'\n};\n\n/**\n * Resolve the effective line style for one category — the single source of\n * truth used by both the slab plan path (slabModelView) and the drawing path.\n *\n * Cascade, weakest first: built-in defaults → `default` → built-in category\n * defaults → `defaultVisibleLines`/`defaultHiddenLines` (the category's\n * visibility group) → the category's own key.\n */\nexport function resolveCategoryLineStyle(\n category: LineCategory,\n lineStyles?: ViewportLineStyles\n): Required<ViewportLineStyle> {\n const group = CATEGORY_VISIBILITY_GROUP[category];\n return {\n ...BUILTIN_LINE_DEFAULTS,\n ...(lineStyles?.default ?? {}),\n ...(CATEGORY_BUILTIN_OVERRIDES[category] ?? {}),\n ...((group && lineStyles?.[group]) ?? {}),\n ...(lineStyles?.[category] ?? {})\n } as Required<ViewportLineStyle>;\n}\n\nexport interface ResolvedLineStyles {\n default: Required<ViewportLineStyle>;\n byCategory: Record<LineCategory, Required<ViewportLineStyle>>;\n}\n\n/**\n * Resolve the effective line style for every category via\n * {@link resolveCategoryLineStyle} (shared with the slab plan path).\n */\nfunction resolveLineStyles(vp: ViewportElement): ResolvedLineStyles {\n const ls = vp.lineStyles;\n\n const base: Required<ViewportLineStyle> = {\n ...BUILTIN_LINE_DEFAULTS,\n ...(ls?.default ?? {})\n } as Required<ViewportLineStyle>;\n\n const categories: LineCategory[] = [\n 'cutLines',\n 'visibleLines',\n 'hiddenLines',\n 'silhouettesVisible',\n 'silhouettesHidden',\n 'featureEdges',\n 'stairArrows',\n 'outlineVisible',\n 'outlineHidden'\n ];\n\n const byCategory = {} as Record<LineCategory, Required<ViewportLineStyle>>;\n for (const cat of categories) {\n byCategory[cat] = resolveCategoryLineStyle(cat, ls);\n }\n\n return { default: base, byCategory };\n}\n\n// ---------------------------------------------------------------------------\n// Fill rule helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve fill color for an item based on viewport fill rules.\n * Returns an RGBA tuple [r, g, b, a] (0–255) or undefined if no rule matches.\n */\nexport function resolveFillColor(\n item: NormalizedProductItem,\n product: unknown,\n fills: FillRule[] | undefined,\n sampleColor: (product: unknown) => SampledColor | undefined\n): [number, number, number, number] | undefined {\n if (!fills?.length) return undefined;\n for (const rule of fills) {\n if (!matchesFilter(item, rule.class, rule.where)) continue;\n if (rule.fill === 'sample') {\n const sampled = sampleColor(product);\n if (sampled) {\n return [\n Math.round(sampled.color.r * 255),\n Math.round(sampled.color.g * 255),\n Math.round(sampled.color.b * 255),\n Math.round(sampled.alpha * 255)\n ];\n }\n } else {\n return parseHexToRgba(rule.fill);\n }\n break; // first matching rule wins\n }\n return undefined;\n}\n\n/**\n * Parse a CSS hex color string to an RGBA tuple (0–255).\n */\nfunction parseHexToRgba(hex: string): [number, number, number, number] {\n const h = hex.replace(/^#/, '');\n if (h.length === 3) {\n return [parseInt(h[0] + h[0], 16), parseInt(h[1] + h[1], 16), parseInt(h[2] + h[2], 16), 255];\n }\n if (h.length === 6) {\n return [parseInt(h.substring(0, 2), 16), parseInt(h.substring(2, 4), 16), parseInt(h.substring(4, 6), 16), 255];\n }\n if (h.length === 8) {\n return [\n parseInt(h.substring(0, 2), 16),\n parseInt(h.substring(2, 4), 16),\n parseInt(h.substring(4, 6), 16),\n parseInt(h.substring(6, 8), 16)\n ];\n }\n // Fallback: opaque black\n return [0, 0, 0, 255];\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RenderLayoutOptions } from './options';
|
|
2
|
+
import { LayoutTemplate, ModelContext, LayoutData, ComputedViewportScale } from './types';
|
|
3
|
+
/** Result of {@link renderLayout}: the final SVG markup, per-viewport scale info, and any warnings. */
|
|
4
|
+
export interface RenderLayoutResult {
|
|
5
|
+
/** Complete SVG markup string ready for embedding or PDF conversion. */
|
|
6
|
+
svg: string;
|
|
7
|
+
/** Per-viewport computed scale information (denominator, mm-per-model-unit, fit status). */
|
|
8
|
+
viewportScales: Record<string, ComputedViewportScale>;
|
|
9
|
+
/** Non-fatal issues encountered during rendering (missing resources, unresolved styles, etc.). */
|
|
10
|
+
warnings: string[];
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Render a layout template to SVG.
|
|
14
|
+
*
|
|
15
|
+
* This is the low-level rendering function. For most use cases, prefer {@link renderDrawing}
|
|
16
|
+
* which handles all data wiring automatically.
|
|
17
|
+
*
|
|
18
|
+
* @param template - Validated layout template (page, elements, styles, presets).
|
|
19
|
+
* @param data - Layout data with viewport items, template variables, and legend rows.
|
|
20
|
+
* @param models - Per-viewport SVG model views (geometry + transforms).
|
|
21
|
+
* @param options - Optional rendering settings (remote resources, scale overrides, metadata).
|
|
22
|
+
* @returns SVG markup string, computed viewport scales, and any warnings.
|
|
23
|
+
*/
|
|
24
|
+
export declare function renderLayout(template: LayoutTemplate, data: LayoutData, models: ModelContext, options?: RenderLayoutOptions): Promise<RenderLayoutResult>;
|
|
25
|
+
//# sourceMappingURL=renderLayout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderLayout.d.ts","sourceRoot":"/","sources":["layout/renderLayout.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAuBhD,OAAO,EAgBH,cAAc,EACd,YAAY,EACZ,UAAU,EAEV,qBAAqB,EACxB,MAAM,SAAS,CAAC;AAIjB,uGAAuG;AACvG,MAAM,WAAW,kBAAkB;IAC/B,wEAAwE;IACxE,GAAG,EAAE,MAAM,CAAC;IACZ,4FAA4F;IAC5F,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IACtD,kGAAkG;IAClG,QAAQ,EAAE,MAAM,EAAE,CAAC;CACtB;AAID;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAC9B,QAAQ,EAAE,cAAc,EACxB,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,YAAY,EACpB,OAAO,CAAC,EAAE,mBAAmB,GAC9B,OAAO,CAAC,kBAAkB,CAAC,CAgZ7B"}
|