@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.
Files changed (157) hide show
  1. package/dist/BuildInfo.js +3 -3
  2. package/dist/index.d.ts +1 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +3 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/layout/analyzeTemplate.d.ts +4 -4
  7. package/dist/layout/analyzeTemplate.d.ts.map +1 -1
  8. package/dist/layout/analyzeTemplate.js +18 -16
  9. package/dist/layout/analyzeTemplate.js.map +1 -1
  10. package/dist/layout/classClosure.d.ts +41 -0
  11. package/dist/layout/classClosure.d.ts.map +1 -0
  12. package/dist/layout/classClosure.js +143 -0
  13. package/dist/layout/classClosure.js.map +1 -0
  14. package/dist/layout/clipUtils.d.ts +11 -0
  15. package/dist/layout/clipUtils.d.ts.map +1 -1
  16. package/dist/layout/clipUtils.js +67 -6
  17. package/dist/layout/clipUtils.js.map +1 -1
  18. package/dist/layout/filters.d.ts +14 -8
  19. package/dist/layout/filters.d.ts.map +1 -1
  20. package/dist/layout/filters.js +28 -3
  21. package/dist/layout/filters.js.map +1 -1
  22. package/dist/layout/index.d.ts +24 -57
  23. package/dist/layout/index.d.ts.map +1 -1
  24. package/dist/layout/index.js +20 -337
  25. package/dist/layout/index.js.map +1 -1
  26. package/dist/layout/itemBuilders.d.ts +11 -0
  27. package/dist/layout/itemBuilders.d.ts.map +1 -1
  28. package/dist/layout/itemBuilders.js +17 -3
  29. package/dist/layout/itemBuilders.js.map +1 -1
  30. package/dist/layout/labelsRender.d.ts.map +1 -1
  31. package/dist/layout/labelsRender.js +15 -27
  32. package/dist/layout/labelsRender.js.map +1 -1
  33. package/dist/layout/legendRender.d.ts +18 -6
  34. package/dist/layout/legendRender.d.ts.map +1 -1
  35. package/dist/layout/legendRender.js +49 -79
  36. package/dist/layout/legendRender.js.map +1 -1
  37. package/dist/layout/metadata.d.ts.map +1 -1
  38. package/dist/layout/metadata.js +26 -5
  39. package/dist/layout/metadata.js.map +1 -1
  40. package/dist/layout/model.d.ts +4 -3
  41. package/dist/layout/model.d.ts.map +1 -1
  42. package/dist/layout/model.js +17 -57
  43. package/dist/layout/model.js.map +1 -1
  44. package/dist/layout/options.d.ts +1 -2
  45. package/dist/layout/options.d.ts.map +1 -1
  46. package/dist/layout/options.js.map +1 -1
  47. package/dist/layout/preflight.d.ts +32 -0
  48. package/dist/layout/preflight.d.ts.map +1 -0
  49. package/dist/layout/preflight.js +69 -0
  50. package/dist/layout/preflight.js.map +1 -0
  51. package/dist/layout/qrRender.d.ts.map +1 -1
  52. package/dist/layout/qrRender.js +11 -10
  53. package/dist/layout/qrRender.js.map +1 -1
  54. package/dist/layout/renderDrawing.d.ts +28 -17
  55. package/dist/layout/renderDrawing.d.ts.map +1 -1
  56. package/dist/layout/renderDrawing.js +107 -88
  57. package/dist/layout/renderDrawing.js.map +1 -1
  58. package/dist/layout/renderLayout.d.ts +25 -0
  59. package/dist/layout/renderLayout.d.ts.map +1 -0
  60. package/dist/layout/renderLayout.js +315 -0
  61. package/dist/layout/renderLayout.js.map +1 -0
  62. package/dist/layout/renderTemplateSheet.d.ts +99 -0
  63. package/dist/layout/renderTemplateSheet.d.ts.map +1 -0
  64. package/dist/layout/renderTemplateSheet.js +296 -0
  65. package/dist/layout/renderTemplateSheet.js.map +1 -0
  66. package/dist/layout/renderUtils.d.ts +19 -0
  67. package/dist/layout/renderUtils.d.ts.map +1 -1
  68. package/dist/layout/renderUtils.js +47 -4
  69. package/dist/layout/renderUtils.js.map +1 -1
  70. package/dist/layout/sectionDefs.d.ts +65 -0
  71. package/dist/layout/sectionDefs.d.ts.map +1 -0
  72. package/dist/layout/sectionDefs.js +88 -0
  73. package/dist/layout/sectionDefs.js.map +1 -0
  74. package/dist/layout/slabModelView.d.ts +34 -0
  75. package/dist/layout/slabModelView.d.ts.map +1 -0
  76. package/dist/layout/slabModelView.js +175 -0
  77. package/dist/layout/slabModelView.js.map +1 -0
  78. package/dist/layout/templateVariables.d.ts +1 -1
  79. package/dist/layout/templateVariables.d.ts.map +1 -1
  80. package/dist/layout/templateVariables.js +21 -9
  81. package/dist/layout/templateVariables.js.map +1 -1
  82. package/dist/layout/types.d.ts +164 -83
  83. package/dist/layout/types.d.ts.map +1 -1
  84. package/dist/layout/types.js.map +1 -1
  85. package/dist/layout/validation.d.ts.map +1 -1
  86. package/dist/layout/validation.js +78 -33
  87. package/dist/layout/validation.js.map +1 -1
  88. package/dist/layout/viewportPrep.d.ts +8 -6
  89. package/dist/layout/viewportPrep.d.ts.map +1 -1
  90. package/dist/layout/viewportPrep.js +35 -23
  91. package/dist/layout/viewportPrep.js.map +1 -1
  92. package/dist/layout/viewportRender.d.ts +9 -7
  93. package/dist/layout/viewportRender.d.ts.map +1 -1
  94. package/dist/layout/viewportRender.js +93 -126
  95. package/dist/layout/viewportRender.js.map +1 -1
  96. package/dist/layout/viewportUtils.d.ts +20 -0
  97. package/dist/layout/viewportUtils.d.ts.map +1 -1
  98. package/dist/layout/viewportUtils.js +107 -4
  99. package/dist/layout/viewportUtils.js.map +1 -1
  100. package/dist/printToPdf.d.ts +7 -1
  101. package/dist/printToPdf.d.ts.map +1 -1
  102. package/dist/printToPdf.js +81 -14
  103. package/dist/printToPdf.js.map +1 -1
  104. package/dist/printToSvg.d.ts.map +1 -1
  105. package/dist/printToSvg.js +7 -3
  106. package/dist/printToSvg.js.map +1 -1
  107. package/dist/schemaUtils.d.ts +9 -0
  108. package/dist/schemaUtils.d.ts.map +1 -0
  109. package/dist/schemaUtils.js +14 -0
  110. package/dist/schemaUtils.js.map +1 -0
  111. package/dist/templates/default-template.json +30 -8
  112. package/dist/types.d.ts +2 -1
  113. package/dist/types.d.ts.map +1 -1
  114. package/dist/types.js +10 -1
  115. package/dist/types.js.map +1 -1
  116. package/package.json +8 -3
  117. package/src/index.ts +4 -0
  118. package/src/layout/analyzeTemplate.ts +21 -19
  119. package/src/layout/classClosure.ts +142 -0
  120. package/src/layout/clipUtils.ts +65 -6
  121. package/src/layout/filters.ts +31 -3
  122. package/src/layout/index.ts +61 -571
  123. package/src/layout/itemBuilders.ts +20 -5
  124. package/src/layout/labelsRender.ts +23 -40
  125. package/src/layout/legendRender.ts +64 -84
  126. package/src/layout/metadata.ts +26 -5
  127. package/src/layout/model.ts +21 -66
  128. package/src/layout/options.ts +1 -2
  129. package/src/layout/preflight.ts +96 -0
  130. package/src/layout/qrRender.ts +11 -10
  131. package/src/layout/renderDrawing.ts +132 -110
  132. package/src/layout/renderLayout.ts +483 -0
  133. package/src/layout/renderTemplateSheet.ts +435 -0
  134. package/src/layout/renderUtils.ts +53 -4
  135. package/src/layout/sectionDefs.ts +131 -0
  136. package/src/layout/slabModelView.ts +196 -0
  137. package/src/layout/templateVariables.ts +25 -9
  138. package/src/layout/types.ts +160 -70
  139. package/src/layout/validation.ts +98 -32
  140. package/src/layout/viewportPrep.ts +47 -29
  141. package/src/layout/viewportRender.ts +114 -141
  142. package/src/layout/viewportUtils.ts +118 -5
  143. package/src/printToPdf.ts +84 -15
  144. package/src/printToSvg.ts +7 -3
  145. package/src/schemaUtils.ts +13 -0
  146. package/src/templates/default-template.json +30 -8
  147. package/src/types.ts +12 -2
  148. package/templates/default-a0-landscape.json +171 -66
  149. package/templates/default-a0-portrait.json +159 -60
  150. package/templates/default-a1-landscape.json +135 -48
  151. package/templates/default-a1-portrait.json +123 -42
  152. package/templates/default-a3-landscape.json +87 -24
  153. package/templates/default-a3-portrait.json +99 -30
  154. package/templates/default-a4-landscape.json +75 -18
  155. package/templates/default-a4-portrait.json +75 -18
  156. package/templates/llm-authoring-guide.md +247 -0
  157. package/templates/template-schema.json +295 -120
@@ -2,8 +2,8 @@ import { filterModelForViewport } from './model';
2
2
  import { pushWarning } from './warnings';
3
3
  import { pickScale } from './viewportUtils';
4
4
  import { getPathValue } from './renderUtils';
5
- import { pointInPolygon, offsetPolygons } from './clipUtils';
6
- import { matchesV2Filter, normalizeClass } from './filters';
5
+ import { pointInPolygon, offsetPolygons, unionPolygons } from './clipUtils';
6
+ import { matchesFilter, normalizeClass } from './filters';
7
7
  import { EPSILON_MIN_DIMENSION } from './geometryConstants';
8
8
  import { isRecord, getProp } from './typeGuards';
9
9
  export const prepareViewports = (viewports, models, data, preferredScales, presets, options) => {
@@ -26,7 +26,7 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
26
26
  if (hlCfg && hlCfg.where) {
27
27
  const sourceItems = getPathValue(data, `viewports.${vp.id}.items`);
28
28
  if (Array.isArray(sourceItems) && sourceItems.length) {
29
- const matching = sourceItems.filter((it) => matchesV2Filter(it, hlCfg.class, hlCfg.where));
29
+ const matching = sourceItems.filter((it) => matchesFilter(it, hlCfg.class, hlCfg.where));
30
30
  if (matching.length) {
31
31
  highlightGids = new Set(matching
32
32
  .map((it) => getProp(it, 'gid') ?? getProp(it, 'id') ?? null)
@@ -71,7 +71,7 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
71
71
  viewportClipWhere[vp.id] = clipCfg.where;
72
72
  const sourceItems = getPathValue(data, `viewports.${vp.id}.items`);
73
73
  if (Array.isArray(sourceItems) && sourceItems.length) {
74
- const matchingItems = sourceItems.filter((it) => matchesV2Filter(it, clipCfg.class, clipCfg.where));
74
+ const matchingItems = sourceItems.filter((it) => matchesFilter(it, clipCfg.class, clipCfg.where));
75
75
  if (!matchingItems.length) {
76
76
  pushWarning(options.warnings, `Viewport '${vp.id}' clip filter matched 0 of ${sourceItems.length} items.`);
77
77
  }
@@ -107,12 +107,16 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
107
107
  if (mapped.length >= 3)
108
108
  projectedLocal.push(mapped);
109
109
  }
110
- const expandByM = typeof clipCfg.expandByM === 'number' &&
111
- Number.isFinite(clipCfg.expandByM) &&
112
- clipCfg.expandByM > 0
113
- ? clipCfg.expandByM
110
+ const expandBy = typeof clipCfg.expandBy === 'number' &&
111
+ Number.isFinite(clipCfg.expandBy) &&
112
+ clipCfg.expandBy > 0
113
+ ? clipCfg.expandBy
114
114
  : 0;
115
- const buffered = expandByM > 0 ? offsetPolygons(projectedLocal, expandByM) : projectedLocal;
115
+ const expanded = expandBy > 0 ? offsetPolygons(projectedLocal, expandBy) : projectedLocal;
116
+ // Merge overlapping polygons into single outlines (the
117
+ // result rings can include holes — everything downstream
118
+ // renders them with even-odd rules).
119
+ const buffered = unionPolygons(expanded);
116
120
  if (buffered.length) {
117
121
  // Calculate bounds from EXPANDED polygon for viewport sizing (so everything fits)
118
122
  // Fill filtering (clipAllowedGids) uses ORIGINAL polygon from worldPolygons (line 239)
@@ -135,9 +139,10 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
135
139
  viewportClipPolygonsLocal[vp.id] = buffered;
136
140
  viewportClipLabels[vp.id] = !!clipCfg.clipLabels;
137
141
  viewportClipStyles[vp.id] = {
138
- stroke: clipCfg.stroke ?? '#000000',
139
- strokeWidthMm: clipCfg.strokeWidthMm ?? 0.5,
140
- strokeOpacity: clipCfg.strokeOpacity ?? 1,
142
+ color: clipCfg.color ?? '#000000',
143
+ widthMm: clipCfg.widthMm ?? 0.5,
144
+ opacity: clipCfg.opacity ?? 1,
145
+ dash: clipCfg.dash,
141
146
  fill: clipCfg.fill ?? 'none',
142
147
  fillOpacity: clipCfg.fillOpacity ?? 0
143
148
  };
@@ -157,6 +162,8 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
157
162
  if (worldPolygons.length) {
158
163
  viewportClipPolygonsWorld[vp.id] = worldPolygons;
159
164
  clipAllowedGids = new Set();
165
+ // pointInPolygon expects y — map polys ONCE, not per item.
166
+ const worldPolygons2D = worldPolygons.map((poly) => poly.map((p) => ({ x: p.x, y: p.z })));
160
167
  for (const item of sourceItems) {
161
168
  // Use item's direct x/z properties (same approach as labels)
162
169
  const ix = getProp(item, 'x');
@@ -164,11 +171,7 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
164
171
  if (!Number.isFinite(ix) || !Number.isFinite(iz)) {
165
172
  continue;
166
173
  }
167
- // Convert polygon {x,z} to {x,y} for pointInPolygon (same as labels do)
168
- const inside = worldPolygons.some((poly) => {
169
- const polyWith2D = poly.map((p) => ({ x: p.x, y: p.z }));
170
- return pointInPolygon(polyWith2D, ix, iz);
171
- });
174
+ const inside = worldPolygons2D.some((poly) => pointInPolygon(poly, ix, iz));
172
175
  if (inside) {
173
176
  const gid = getProp(item, 'gid') ?? getProp(item, 'id');
174
177
  if (gid !== null && gid !== undefined) {
@@ -202,16 +205,18 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
202
205
  }
203
206
  const hlStyles = hlCfg
204
207
  ? {
205
- stroke: typeof hlCfg.stroke === 'string' ? hlCfg.stroke : '#ff0000',
206
- strokeWidthMm: typeof hlCfg.strokeWidthMm === 'number' ? hlCfg.strokeWidthMm : 0.5,
207
- strokeOpacity: typeof hlCfg.strokeOpacity === 'number' ? hlCfg.strokeOpacity : 1,
208
+ color: typeof hlCfg.color === 'string' ? hlCfg.color : '#ff0000',
209
+ widthMm: typeof hlCfg.widthMm === 'number' ? hlCfg.widthMm : 0.5,
210
+ opacity: typeof hlCfg.opacity === 'number' ? hlCfg.opacity : 1,
211
+ dash: typeof hlCfg.dash === 'string' ? hlCfg.dash : undefined,
208
212
  fill: typeof hlCfg.fill === 'string' ? hlCfg.fill : '#ffff00',
209
213
  fillOpacity: typeof hlCfg.fillOpacity === 'number' ? hlCfg.fillOpacity : 0.5
210
214
  }
211
215
  : {
212
- stroke: undefined,
213
- strokeWidthMm: undefined,
214
- strokeOpacity: undefined,
216
+ color: undefined,
217
+ widthMm: undefined,
218
+ opacity: undefined,
219
+ dash: undefined,
215
220
  fill: undefined,
216
221
  fillOpacity: undefined
217
222
  };
@@ -229,6 +234,13 @@ export const prepareViewports = (viewports, models, data, preferredScales, prese
229
234
  };
230
235
  addFilterClasses(hlCfg?.class);
231
236
  addFilterClasses(clipCfg?.class);
237
+ // gid-based features (highlight, clip include/exclude, includeClasses)
238
+ // require rawPaths with per-product meta — filterModelForViewport
239
+ // returns the model UNTOUCHED without them, so warn instead of
240
+ // silently rendering as if the config didn't exist.
241
+ if (baseModel && !baseModel.rawPaths?.length && (vp.highlight || vp.clip || vp.includeClasses)) {
242
+ pushWarning(options.warnings, `Viewport '${vp.id}' declares highlight/clip/includeClasses but its model has no rawPaths with per-product metadata — these settings will have no effect.`);
243
+ }
232
244
  const model = baseModel
233
245
  ? filterModelForViewport(baseModel, vp, options?.metadataById, presets.includeClasses, effectiveAllowed, {
234
246
  gids: highlightGids,
@@ -1 +1 @@
1
- {"version":3,"file":"viewportPrep.js","sourceRoot":"/","sources":["layout/viewportPrep.ts"],"names":[],"mappings":"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","sourcesContent":["import { filterModelForViewport } from './model';\nimport { ModelMetadata } from './metadata';\nimport { ViewportElement, SvgModelView, ComputedViewportScale } from './types';\nimport { pushWarning } from './warnings';\nimport { pickScale } from './viewportUtils';\nimport type { ResolvedPresets } from './presets';\nimport { getPathValue } from './renderUtils';\nimport { pointInPolygon, offsetPolygons, Polygon } from './clipUtils';\nimport { matchesV2Filter, normalizeClass } from './filters';\nimport { EPSILON_MIN_DIMENSION } from './geometryConstants';\n\nexport interface ViewportPrepResult {\n viewportScales: Record<string, ComputedViewportScale>;\n viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>>;\n viewportClipPolygonsWorld: Record<string, Array<Array<{ x: number; z: number }>>>;\n viewportClipBounds: Record<\n string,\n { minX: number; maxX: number; minY: number; maxY: number; width: number; height: number }\n >;\n viewportClipLabels: Record<string, boolean>;\n viewportClipStyles: Record<\n string,\n { stroke?: string; strokeWidthMm?: number; strokeOpacity?: number; fill?: string; fillOpacity?: number }\n >;\n viewportClipWhere: Record<string, WhereCondition | undefined>;\n viewportHighlight: Record<\n string,\n {\n gids: Set<string> | null;\n styles: {\n stroke?: string;\n strokeWidthMm?: number;\n strokeOpacity?: number;\n fill?: string;\n fillOpacity?: number;\n };\n }\n >;\n filteredModelsByViewport: Record<string, SvgModelView>;\n}\n\nimport { isRecord, getProp } from './typeGuards';\nimport type { WhereCondition } from './types';\n\nexport const prepareViewports = (\n viewports: ViewportElement[],\n models: Record<string, SvgModelView | undefined>,\n data: unknown,\n preferredScales: number[],\n presets: ResolvedPresets,\n options: { metadataById?: unknown; warnings: string[] }\n): ViewportPrepResult => {\n const viewportScales: Record<string, ComputedViewportScale> = {};\n const viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>> = {};\n const viewportClipPolygonsWorld: Record<string, Array<Array<{ x: number; z: number }>>> = {};\n const viewportClipBounds: Record<\n string,\n { minX: number; maxX: number; minY: number; maxY: number; width: number; height: number }\n > = {};\n const viewportClipLabels: Record<string, boolean> = {};\n const viewportClipStyles: Record<\n string,\n { stroke?: string; strokeWidthMm?: number; strokeOpacity?: number; fill?: string; fillOpacity?: number }\n > = {};\n const viewportClipWhere: Record<string, WhereCondition | undefined> = {};\n const viewportHighlight: ViewportPrepResult['viewportHighlight'] = {};\n const filteredModelsByViewport: Record<string, SvgModelView> = {};\n const scales = presets.scales;\n\n viewports.forEach((vp) => {\n const baseModel = models[vp.id];\n let clipAllowedGids: Set<string> | null = null;\n\n // Highlight: optional class+where filter on normalized items\n let highlightGids: Set<string> | null = null;\n const hlCfg = vp.highlight;\n if (hlCfg && hlCfg.where) {\n const sourceItems = getPathValue(data, `viewports.${vp.id}.items`);\n if (Array.isArray(sourceItems) && sourceItems.length) {\n const matching = sourceItems.filter((it) => matchesV2Filter(it, hlCfg.class, hlCfg.where));\n if (matching.length) {\n highlightGids = new Set(\n matching\n .map((it: unknown) => getProp(it, 'gid') ?? getProp(it, 'id') ?? null)\n .filter((v: unknown) => v !== null && v !== undefined)\n .map((v: unknown) => String(v))\n );\n\n // Intersect with referenced viewport if specified\n if (hlCfg.intersectsViewport) {\n const refItems = getPathValue(data, `viewports.${hlCfg.intersectsViewport}.items`);\n if (Array.isArray(refItems) && refItems.length) {\n const refGids = new Set(\n refItems\n .map((it: unknown) => getProp(it, 'gid') ?? getProp(it, 'id') ?? null)\n .filter((v: unknown) => v !== null && v !== undefined)\n .map((v: unknown) => String(v))\n );\n // Keep only items that appear in both viewports\n const intersection = new Set<string>();\n highlightGids.forEach((gid) => {\n if (refGids.has(gid)) intersection.add(gid);\n });\n highlightGids = intersection;\n } else {\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' highlight intersectsViewport=\"${hlCfg.intersectsViewport}\": referenced viewport has no items.`\n );\n highlightGids = new Set(); // No items in referenced viewport = no highlights\n }\n }\n } else {\n highlightGids = new Set(); // explicit no matches\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' highlight filter matched 0 of ${sourceItems.length} items.`\n );\n }\n } else if (Array.isArray(sourceItems) && !sourceItems.length) {\n pushWarning(options.warnings, `Viewport '${vp.id}' highlight: no items available to filter.`);\n }\n }\n\n // Clip: class+where filter — find matching items, extract their polylines as clip polygons\n let clipEffectiveWidthModel: number | undefined;\n let clipEffectiveHeightModel: number | undefined;\n const clipCfg = vp.clip;\n if (clipCfg && clipCfg.where && baseModel?.transform) {\n viewportClipWhere[vp.id] = clipCfg.where;\n const sourceItems = getPathValue(data, `viewports.${vp.id}.items`);\n if (Array.isArray(sourceItems) && sourceItems.length) {\n const matchingItems = sourceItems.filter((it) => matchesV2Filter(it, clipCfg.class, clipCfg.where));\n if (!matchingItems.length) {\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' clip filter matched 0 of ${sourceItems.length} items.`\n );\n }\n\n // Extract polylines from matched items\n const allPolylines: Array<{ points?: Array<{ x: number; z: number }> }> = [];\n for (const item of matchingItems) {\n const polylines = getProp(item, 'polylines');\n if (Array.isArray(polylines)) {\n for (const pl of polylines) {\n if (isRecord(pl)) allPolylines.push(pl as { points?: Array<{ x: number; z: number }> });\n }\n }\n }\n\n if (allPolylines.length) {\n // Project polyline points from world (x/z) to model view space\n const projectedLocal: Polygon[] = [];\n for (const poly of allPolylines) {\n const pts = poly.points;\n if (!Array.isArray(pts) || pts.length < 3) continue;\n const mapped: Polygon = [];\n for (const pt of pts) {\n const px = pt?.x;\n const pz = pt?.z;\n if (!Number.isFinite(px) || !Number.isFinite(pz)) continue;\n mapped.push({\n x: px - baseModel.transform!.viewMinX,\n y: baseModel.transform!.viewMaxZ - pz\n });\n }\n if (mapped.length >= 3) projectedLocal.push(mapped);\n }\n const expandByM =\n typeof clipCfg.expandByM === 'number' &&\n Number.isFinite(clipCfg.expandByM) &&\n clipCfg.expandByM > 0\n ? clipCfg.expandByM\n : 0;\n const buffered = expandByM > 0 ? offsetPolygons(projectedLocal, expandByM) : projectedLocal;\n\n if (buffered.length) {\n // Calculate bounds from EXPANDED polygon for viewport sizing (so everything fits)\n // Fill filtering (clipAllowedGids) uses ORIGINAL polygon from worldPolygons (line 239)\n const boundsSource = buffered; // Use EXPANDED for viewport sizing\n const flat = boundsSource.flat();\n let minX = Infinity,\n maxX = -Infinity,\n minY = Infinity,\n maxY = -Infinity;\n for (let i = 0; i < flat.length; i++) {\n const p = flat[i];\n if (p.x < minX) minX = p.x;\n if (p.x > maxX) maxX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.y > maxY) maxY = p.y;\n }\n clipEffectiveWidthModel = Math.max(EPSILON_MIN_DIMENSION, maxX - minX);\n clipEffectiveHeightModel = Math.max(EPSILON_MIN_DIMENSION, maxY - minY);\n viewportClipPolygonsLocal[vp.id] = buffered;\n viewportClipLabels[vp.id] = !!clipCfg.clipLabels;\n viewportClipStyles[vp.id] = {\n stroke: clipCfg.stroke ?? '#000000',\n strokeWidthMm: clipCfg.strokeWidthMm ?? 0.5,\n strokeOpacity: clipCfg.strokeOpacity ?? 1,\n fill: clipCfg.fill ?? 'none',\n fillOpacity: clipCfg.fillOpacity ?? 0\n };\n viewportClipBounds[vp.id] = {\n minX,\n maxX,\n minY,\n maxY,\n width: clipEffectiveWidthModel,\n height: clipEffectiveHeightModel\n };\n\n // Build clipAllowedGids: include items whose center falls inside the clip polygons\n // Polygon is in XZ coordinates (horizontal plane), Y is vertical (plane height)\n const worldPolygons = allPolylines\n .filter((pl) => Array.isArray(pl.points) && pl.points.length >= 3)\n .map((pl) => pl.points!.map((p) => ({ x: p.x, z: p.z })));\n if (worldPolygons.length) {\n viewportClipPolygonsWorld[vp.id] = worldPolygons;\n clipAllowedGids = new Set<string>();\n for (const item of sourceItems) {\n // Use item's direct x/z properties (same approach as labels)\n const ix = getProp(item, 'x');\n const iz = getProp(item, 'z');\n\n if (!Number.isFinite(ix) || !Number.isFinite(iz)) {\n continue;\n }\n // Convert polygon {x,z} to {x,y} for pointInPolygon (same as labels do)\n const inside = worldPolygons.some((poly) => {\n const polyWith2D = poly.map((p) => ({ x: p.x, y: p.z }));\n return pointInPolygon(polyWith2D, ix as number, iz as number);\n });\n if (inside) {\n const gid = getProp(item, 'gid') ?? getProp(item, 'id');\n if (gid !== null && gid !== undefined) {\n clipAllowedGids.add(String(gid));\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Effective allowed set: if highlight defined, use highlight set; else clipAllowed; if both exist, intersect.\n // IMPORTANT: Store empty Set (not null) when clip filtering is active but finds no matches\n let effectiveAllowed: Set<string> | null = null;\n if (highlightGids && highlightGids.size > 0 && clipAllowedGids) {\n // Both highlight and clip active - intersect them (even if clipAllowedGids is empty)\n const intersection = new Set<string>();\n highlightGids.forEach((gid) => {\n if (clipAllowedGids!.has(gid)) intersection.add(gid);\n });\n effectiveAllowed = intersection;\n } else if (highlightGids && highlightGids.size > 0) {\n effectiveAllowed = highlightGids;\n } else if (clipAllowedGids !== null) {\n // Clip filtering is active - use clipAllowedGids even if empty (means zero items allowed)\n effectiveAllowed = clipAllowedGids;\n }\n\n const hlStyles = hlCfg\n ? {\n stroke: typeof hlCfg.stroke === 'string' ? hlCfg.stroke : '#ff0000',\n strokeWidthMm: typeof hlCfg.strokeWidthMm === 'number' ? hlCfg.strokeWidthMm : 0.5,\n strokeOpacity: typeof hlCfg.strokeOpacity === 'number' ? hlCfg.strokeOpacity : 1,\n fill: typeof hlCfg.fill === 'string' ? hlCfg.fill : '#ffff00',\n fillOpacity: typeof hlCfg.fillOpacity === 'number' ? hlCfg.fillOpacity : 0.5\n }\n : {\n stroke: undefined,\n strokeWidthMm: undefined,\n strokeOpacity: undefined,\n fill: undefined,\n fillOpacity: undefined\n };\n\n // Build the set of classes subject to GID-based filtering from highlight/clip configs\n const filterClasses = new Set<string>();\n const addFilterClasses = (cls: string | string[] | undefined): void => {\n if (!cls) return;\n const classes = Array.isArray(cls) ? cls : [cls];\n for (const c of classes) {\n const normalized = normalizeClass(c);\n if (normalized) filterClasses.add(normalized);\n }\n };\n addFilterClasses(hlCfg?.class);\n addFilterClasses(clipCfg?.class);\n\n const model = baseModel\n ? filterModelForViewport(\n baseModel,\n vp,\n options?.metadataById as ModelMetadata | undefined,\n presets.includeClasses,\n effectiveAllowed,\n {\n gids: highlightGids,\n styles: hlStyles\n },\n filterClasses.size > 0 ? filterClasses : null\n )\n : null;\n viewportHighlight[vp.id] = {\n gids: effectiveAllowed, // Use effectiveAllowed (includes both clip and highlight GIDs)\n styles: hlStyles\n };\n if (!model) {\n pushWarning(options.warnings, `Missing model for viewport '${vp.id}'.`);\n return;\n }\n filteredModelsByViewport[vp.id] = model;\n const effectiveWidthModel = clipEffectiveWidthModel ?? model.widthModel;\n const effectiveHeightModel = clipEffectiveHeightModel ?? model.heightModel;\n\n const scale = pickScale(\n vp,\n { ...model, widthModel: effectiveWidthModel, heightModel: effectiveHeightModel },\n preferredScales,\n scales\n );\n viewportScales[vp.id] = scale;\n viewportClipBounds[vp.id] = viewportClipBounds[vp.id] ?? {\n minX: model.transform?.viewMinX ?? 0,\n maxX: model.transform ? model.transform.viewMinX + effectiveWidthModel : effectiveWidthModel,\n minY: model.transform?.viewMinZ ?? 0,\n maxY: model.transform ? model.transform.viewMinZ + effectiveHeightModel : effectiveHeightModel,\n width: effectiveWidthModel,\n height: effectiveHeightModel\n };\n if (!viewportClipPolygonsLocal[vp.id]) {\n viewportClipPolygonsLocal[vp.id] = [];\n }\n });\n\n return {\n viewportScales,\n viewportClipPolygonsLocal,\n viewportClipPolygonsWorld,\n viewportClipBounds,\n viewportClipLabels,\n viewportClipStyles,\n viewportClipWhere,\n viewportHighlight,\n filteredModelsByViewport\n };\n};\n"]}
1
+ {"version":3,"file":"viewportPrep.js","sourceRoot":"/","sources":["layout/viewportPrep.ts"],"names":[],"mappings":"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","sourcesContent":["import { filterModelForViewport } from './model';\nimport { ModelMetadata } from './metadata';\nimport { ViewportElement, SvgModelView, ComputedViewportScale } from './types';\nimport { pushWarning } from './warnings';\nimport { pickScale } from './viewportUtils';\nimport type { ResolvedPresets } from './presets';\nimport { getPathValue } from './renderUtils';\nimport { pointInPolygon, offsetPolygons, unionPolygons, Polygon } from './clipUtils';\nimport { matchesFilter, normalizeClass } from './filters';\nimport { EPSILON_MIN_DIMENSION } from './geometryConstants';\n\nexport interface ViewportPrepResult {\n viewportScales: Record<string, ComputedViewportScale>;\n viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>>;\n viewportClipPolygonsWorld: Record<string, Array<Array<{ x: number; z: number }>>>;\n viewportClipBounds: Record<\n string,\n { minX: number; maxX: number; minY: number; maxY: number; width: number; height: number }\n >;\n viewportClipLabels: Record<string, boolean>;\n viewportClipStyles: Record<\n string,\n { color?: string; widthMm?: number; opacity?: number; dash?: string; fill?: string; fillOpacity?: number }\n >;\n viewportClipWhere: Record<string, WhereCondition | undefined>;\n viewportHighlight: Record<\n string,\n {\n gids: Set<string> | null;\n styles: {\n color?: string;\n widthMm?: number;\n opacity?: number;\n dash?: string;\n fill?: string;\n fillOpacity?: number;\n };\n }\n >;\n filteredModelsByViewport: Record<string, SvgModelView>;\n}\n\nimport { isRecord, getProp } from './typeGuards';\nimport type { WhereCondition } from './types';\n\nexport const prepareViewports = (\n viewports: ViewportElement[],\n models: Record<string, SvgModelView | undefined>,\n data: unknown,\n preferredScales: number[],\n presets: ResolvedPresets,\n options: { metadataById?: unknown; warnings: string[] }\n): ViewportPrepResult => {\n const viewportScales: Record<string, ComputedViewportScale> = {};\n const viewportClipPolygonsLocal: Record<string, Array<Array<{ x: number; y: number }>>> = {};\n const viewportClipPolygonsWorld: Record<string, Array<Array<{ x: number; z: number }>>> = {};\n const viewportClipBounds: Record<\n string,\n { minX: number; maxX: number; minY: number; maxY: number; width: number; height: number }\n > = {};\n const viewportClipLabels: Record<string, boolean> = {};\n const viewportClipStyles: Record<\n string,\n { color?: string; widthMm?: number; opacity?: number; dash?: string; fill?: string; fillOpacity?: number }\n > = {};\n const viewportClipWhere: Record<string, WhereCondition | undefined> = {};\n const viewportHighlight: ViewportPrepResult['viewportHighlight'] = {};\n const filteredModelsByViewport: Record<string, SvgModelView> = {};\n const scales = presets.scales;\n\n viewports.forEach((vp) => {\n const baseModel = models[vp.id];\n let clipAllowedGids: Set<string> | null = null;\n\n // Highlight: optional class+where filter on normalized items\n let highlightGids: Set<string> | null = null;\n const hlCfg = vp.highlight;\n if (hlCfg && hlCfg.where) {\n const sourceItems = getPathValue(data, `viewports.${vp.id}.items`);\n if (Array.isArray(sourceItems) && sourceItems.length) {\n const matching = sourceItems.filter((it) => matchesFilter(it, hlCfg.class, hlCfg.where));\n if (matching.length) {\n highlightGids = new Set(\n matching\n .map((it: unknown) => getProp(it, 'gid') ?? getProp(it, 'id') ?? null)\n .filter((v: unknown) => v !== null && v !== undefined)\n .map((v: unknown) => String(v))\n );\n\n // Intersect with referenced viewport if specified\n if (hlCfg.intersectsViewport) {\n const refItems = getPathValue(data, `viewports.${hlCfg.intersectsViewport}.items`);\n if (Array.isArray(refItems) && refItems.length) {\n const refGids = new Set(\n refItems\n .map((it: unknown) => getProp(it, 'gid') ?? getProp(it, 'id') ?? null)\n .filter((v: unknown) => v !== null && v !== undefined)\n .map((v: unknown) => String(v))\n );\n // Keep only items that appear in both viewports\n const intersection = new Set<string>();\n highlightGids.forEach((gid) => {\n if (refGids.has(gid)) intersection.add(gid);\n });\n highlightGids = intersection;\n } else {\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' highlight intersectsViewport=\"${hlCfg.intersectsViewport}\": referenced viewport has no items.`\n );\n highlightGids = new Set(); // No items in referenced viewport = no highlights\n }\n }\n } else {\n highlightGids = new Set(); // explicit no matches\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' highlight filter matched 0 of ${sourceItems.length} items.`\n );\n }\n } else if (Array.isArray(sourceItems) && !sourceItems.length) {\n pushWarning(options.warnings, `Viewport '${vp.id}' highlight: no items available to filter.`);\n }\n }\n\n // Clip: class+where filter — find matching items, extract their polylines as clip polygons\n let clipEffectiveWidthModel: number | undefined;\n let clipEffectiveHeightModel: number | undefined;\n const clipCfg = vp.clip;\n if (clipCfg && clipCfg.where && baseModel?.transform) {\n viewportClipWhere[vp.id] = clipCfg.where;\n const sourceItems = getPathValue(data, `viewports.${vp.id}.items`);\n if (Array.isArray(sourceItems) && sourceItems.length) {\n const matchingItems = sourceItems.filter((it) => matchesFilter(it, clipCfg.class, clipCfg.where));\n if (!matchingItems.length) {\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' clip filter matched 0 of ${sourceItems.length} items.`\n );\n }\n\n // Extract polylines from matched items\n const allPolylines: Array<{ points?: Array<{ x: number; z: number }> }> = [];\n for (const item of matchingItems) {\n const polylines = getProp(item, 'polylines');\n if (Array.isArray(polylines)) {\n for (const pl of polylines) {\n if (isRecord(pl)) allPolylines.push(pl as { points?: Array<{ x: number; z: number }> });\n }\n }\n }\n\n if (allPolylines.length) {\n // Project polyline points from world (x/z) to model view space\n const projectedLocal: Polygon[] = [];\n for (const poly of allPolylines) {\n const pts = poly.points;\n if (!Array.isArray(pts) || pts.length < 3) continue;\n const mapped: Polygon = [];\n for (const pt of pts) {\n const px = pt?.x;\n const pz = pt?.z;\n if (!Number.isFinite(px) || !Number.isFinite(pz)) continue;\n mapped.push({\n x: px - baseModel.transform!.viewMinX,\n y: baseModel.transform!.viewMaxZ - pz\n });\n }\n if (mapped.length >= 3) projectedLocal.push(mapped);\n }\n const expandBy =\n typeof clipCfg.expandBy === 'number' &&\n Number.isFinite(clipCfg.expandBy) &&\n clipCfg.expandBy > 0\n ? clipCfg.expandBy\n : 0;\n const expanded = expandBy > 0 ? offsetPolygons(projectedLocal, expandBy) : projectedLocal;\n // Merge overlapping polygons into single outlines (the\n // result rings can include holes — everything downstream\n // renders them with even-odd rules).\n const buffered = unionPolygons(expanded);\n\n if (buffered.length) {\n // Calculate bounds from EXPANDED polygon for viewport sizing (so everything fits)\n // Fill filtering (clipAllowedGids) uses ORIGINAL polygon from worldPolygons (line 239)\n const boundsSource = buffered; // Use EXPANDED for viewport sizing\n const flat = boundsSource.flat();\n let minX = Infinity,\n maxX = -Infinity,\n minY = Infinity,\n maxY = -Infinity;\n for (let i = 0; i < flat.length; i++) {\n const p = flat[i];\n if (p.x < minX) minX = p.x;\n if (p.x > maxX) maxX = p.x;\n if (p.y < minY) minY = p.y;\n if (p.y > maxY) maxY = p.y;\n }\n clipEffectiveWidthModel = Math.max(EPSILON_MIN_DIMENSION, maxX - minX);\n clipEffectiveHeightModel = Math.max(EPSILON_MIN_DIMENSION, maxY - minY);\n viewportClipPolygonsLocal[vp.id] = buffered;\n viewportClipLabels[vp.id] = !!clipCfg.clipLabels;\n viewportClipStyles[vp.id] = {\n color: clipCfg.color ?? '#000000',\n widthMm: clipCfg.widthMm ?? 0.5,\n opacity: clipCfg.opacity ?? 1,\n dash: clipCfg.dash,\n fill: clipCfg.fill ?? 'none',\n fillOpacity: clipCfg.fillOpacity ?? 0\n };\n viewportClipBounds[vp.id] = {\n minX,\n maxX,\n minY,\n maxY,\n width: clipEffectiveWidthModel,\n height: clipEffectiveHeightModel\n };\n\n // Build clipAllowedGids: include items whose center falls inside the clip polygons\n // Polygon is in XZ coordinates (horizontal plane), Y is vertical (plane height)\n const worldPolygons = allPolylines\n .filter((pl) => Array.isArray(pl.points) && pl.points.length >= 3)\n .map((pl) => pl.points!.map((p) => ({ x: p.x, z: p.z })));\n if (worldPolygons.length) {\n viewportClipPolygonsWorld[vp.id] = worldPolygons;\n clipAllowedGids = new Set<string>();\n // pointInPolygon expects y — map polys ONCE, not per item.\n const worldPolygons2D = worldPolygons.map((poly) => poly.map((p) => ({ x: p.x, y: p.z })));\n for (const item of sourceItems) {\n // Use item's direct x/z properties (same approach as labels)\n const ix = getProp(item, 'x');\n const iz = getProp(item, 'z');\n\n if (!Number.isFinite(ix) || !Number.isFinite(iz)) {\n continue;\n }\n const inside = worldPolygons2D.some((poly) =>\n pointInPolygon(poly, ix as number, iz as number)\n );\n if (inside) {\n const gid = getProp(item, 'gid') ?? getProp(item, 'id');\n if (gid !== null && gid !== undefined) {\n clipAllowedGids.add(String(gid));\n }\n }\n }\n }\n }\n }\n }\n }\n\n // Effective allowed set: if highlight defined, use highlight set; else clipAllowed; if both exist, intersect.\n // IMPORTANT: Store empty Set (not null) when clip filtering is active but finds no matches\n let effectiveAllowed: Set<string> | null = null;\n if (highlightGids && highlightGids.size > 0 && clipAllowedGids) {\n // Both highlight and clip active - intersect them (even if clipAllowedGids is empty)\n const intersection = new Set<string>();\n highlightGids.forEach((gid) => {\n if (clipAllowedGids!.has(gid)) intersection.add(gid);\n });\n effectiveAllowed = intersection;\n } else if (highlightGids && highlightGids.size > 0) {\n effectiveAllowed = highlightGids;\n } else if (clipAllowedGids !== null) {\n // Clip filtering is active - use clipAllowedGids even if empty (means zero items allowed)\n effectiveAllowed = clipAllowedGids;\n }\n\n const hlStyles = hlCfg\n ? {\n color: typeof hlCfg.color === 'string' ? hlCfg.color : '#ff0000',\n widthMm: typeof hlCfg.widthMm === 'number' ? hlCfg.widthMm : 0.5,\n opacity: typeof hlCfg.opacity === 'number' ? hlCfg.opacity : 1,\n dash: typeof hlCfg.dash === 'string' ? hlCfg.dash : undefined,\n fill: typeof hlCfg.fill === 'string' ? hlCfg.fill : '#ffff00',\n fillOpacity: typeof hlCfg.fillOpacity === 'number' ? hlCfg.fillOpacity : 0.5\n }\n : {\n color: undefined,\n widthMm: undefined,\n opacity: undefined,\n dash: undefined,\n fill: undefined,\n fillOpacity: undefined\n };\n\n // Build the set of classes subject to GID-based filtering from highlight/clip configs\n const filterClasses = new Set<string>();\n const addFilterClasses = (cls: string | string[] | undefined): void => {\n if (!cls) return;\n const classes = Array.isArray(cls) ? cls : [cls];\n for (const c of classes) {\n const normalized = normalizeClass(c);\n if (normalized) filterClasses.add(normalized);\n }\n };\n addFilterClasses(hlCfg?.class);\n addFilterClasses(clipCfg?.class);\n\n // gid-based features (highlight, clip include/exclude, includeClasses)\n // require rawPaths with per-product meta — filterModelForViewport\n // returns the model UNTOUCHED without them, so warn instead of\n // silently rendering as if the config didn't exist.\n if (baseModel && !baseModel.rawPaths?.length && (vp.highlight || vp.clip || vp.includeClasses)) {\n pushWarning(\n options.warnings,\n `Viewport '${vp.id}' declares highlight/clip/includeClasses but its model has no rawPaths with per-product metadata — these settings will have no effect.`\n );\n }\n const model = baseModel\n ? filterModelForViewport(\n baseModel,\n vp,\n options?.metadataById as ModelMetadata | undefined,\n presets.includeClasses,\n effectiveAllowed,\n {\n gids: highlightGids,\n styles: hlStyles\n },\n filterClasses.size > 0 ? filterClasses : null\n )\n : null;\n viewportHighlight[vp.id] = {\n gids: effectiveAllowed, // Use effectiveAllowed (includes both clip and highlight GIDs)\n styles: hlStyles\n };\n if (!model) {\n pushWarning(options.warnings, `Missing model for viewport '${vp.id}'.`);\n return;\n }\n filteredModelsByViewport[vp.id] = model;\n const effectiveWidthModel = clipEffectiveWidthModel ?? model.widthModel;\n const effectiveHeightModel = clipEffectiveHeightModel ?? model.heightModel;\n\n const scale = pickScale(\n vp,\n { ...model, widthModel: effectiveWidthModel, heightModel: effectiveHeightModel },\n preferredScales,\n scales\n );\n viewportScales[vp.id] = scale;\n viewportClipBounds[vp.id] = viewportClipBounds[vp.id] ?? {\n minX: model.transform?.viewMinX ?? 0,\n maxX: model.transform ? model.transform.viewMinX + effectiveWidthModel : effectiveWidthModel,\n minY: model.transform?.viewMinZ ?? 0,\n maxY: model.transform ? model.transform.viewMinZ + effectiveHeightModel : effectiveHeightModel,\n width: effectiveWidthModel,\n height: effectiveHeightModel\n };\n if (!viewportClipPolygonsLocal[vp.id]) {\n viewportClipPolygonsLocal[vp.id] = [];\n }\n });\n\n return {\n viewportScales,\n viewportClipPolygonsLocal,\n viewportClipPolygonsWorld,\n viewportClipBounds,\n viewportClipLabels,\n viewportClipStyles,\n viewportClipWhere,\n viewportHighlight,\n filteredModelsByViewport\n };\n};\n"]}
@@ -1,12 +1,13 @@
1
1
  import { ViewportRenderInfo } from './labelsRender';
2
- import { ComputedViewportScale, SvgModelView, ViewportElement, AssetSpec } from './types';
2
+ import { ComputedViewportScale, SvgModelView, ViewportElement, ResourceSpec, ResolvedIncludeFilter } from './types';
3
+ import type { LegendColorAssignment } from './legendRender';
3
4
  type PolyPoint = {
4
5
  x: number;
5
6
  y: number;
6
7
  };
7
8
  export declare const renderViewportElement: (vp: ViewportElement, baseModel: SvgModelView | null, dataWithViewport: any, preferredScales: number[], scales: Record<string, {
8
9
  preferredScales?: number[];
9
- }>, assetMap: Map<string, AssetSpec>, viewportScales: Record<string, ComputedViewportScale>, viewportClipPolygonsLocal: Record<string, Array<Array<PolyPoint>>>, viewportClipBounds: Record<string, {
10
+ }>, resourceMap: Map<string, ResourceSpec>, viewportScales: Record<string, ComputedViewportScale>, viewportClipPolygonsLocal: Record<string, Array<Array<PolyPoint>>>, viewportClipBounds: Record<string, {
10
11
  minX: number;
11
12
  maxX: number;
12
13
  minY: number;
@@ -14,15 +15,16 @@ export declare const renderViewportElement: (vp: ViewportElement, baseModel: Svg
14
15
  width: number;
15
16
  height: number;
16
17
  }>, viewportClipLabels: Record<string, boolean>, viewportClipStyles: Record<string, {
17
- stroke?: string;
18
- strokeWidthMm?: number;
19
- strokeOpacity?: number;
18
+ color?: string;
19
+ widthMm?: number;
20
+ opacity?: number;
21
+ dash?: string;
20
22
  fill?: string;
21
23
  fillOpacity?: number;
22
24
  }>, viewportHighlight: Record<string, {
23
25
  gids: Set<string> | null;
24
26
  styles: any;
25
- }>, viewportRenderInfo: Record<string, ViewportRenderInfo>, warnings: string[], legendColorMaps?: Map<string, Map<string, string>>, precomputed?: {
27
+ }>, viewportRenderInfo: Record<string, ViewportRenderInfo>, warnings: string[], legendColorMaps?: Map<string, LegendColorAssignment>, precomputed?: {
26
28
  effectiveWidthModel?: number;
27
29
  effectiveHeightModel?: number;
28
30
  clipPolygonsMm?: Array<Array<PolyPoint>>;
@@ -37,6 +39,6 @@ export declare const renderViewportElement: (vp: ViewportElement, baseModel: Svg
37
39
  };
38
40
  renderCenterModelX?: number;
39
41
  renderCenterModelY?: number;
40
- }) => string[];
42
+ }, includeFilters?: ResolvedIncludeFilter[] | null) => string[];
41
43
  export {};
42
44
  //# sourceMappingURL=viewportRender.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"viewportRender.d.ts","sourceRoot":"/","sources":["layout/viewportRender.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAG1F,KAAK,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA8B1C,eAAO,MAAM,qBAAqB,GAC9B,IAAI,eAAe,EACnB,WAAW,YAAY,GAAG,IAAI,EAC9B,kBAAkB,GAAG,EACrB,iBAAiB,MAAM,EAAE,EACzB,QAAQ,MAAM,CAAC,MAAM,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EACtD,UAAU,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,EAChC,gBAAgB,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,EACrD,2BAA2B,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAClE,oBAAoB,MAAM,CACtB,MAAM,EACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAC5F,EACD,oBAAoB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3C,oBAAoB,MAAM,CACtB,MAAM,EACN;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAC3G,EACD,mBAAmB,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EAC5E,oBAAoB,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACtD,UAAU,MAAM,EAAE,EAClB,kBAAkB,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAClD,cAAc;IACV,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B,KACF,MAAM,EAqPR,CAAC"}
1
+ {"version":3,"file":"viewportRender.d.ts","sourceRoot":"/","sources":["layout/viewportRender.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEpH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,KAAK,SAAS,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA8B1C,eAAO,MAAM,qBAAqB,GAC9B,IAAI,eAAe,EACnB,WAAW,YAAY,GAAG,IAAI,EAC9B,kBAAkB,GAAG,EACrB,iBAAiB,MAAM,EAAE,EACzB,QAAQ,MAAM,CAAC,MAAM,EAAE;IAAE,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,EACtD,aAAa,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACtC,gBAAgB,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,EACrD,2BAA2B,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAClE,oBAAoB,MAAM,CACtB,MAAM,EACN;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAC5F,EACD,oBAAoB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3C,oBAAoB,MAAM,CACtB,MAAM,EACN;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAC7G,EACD,mBAAmB,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EAC5E,oBAAoB,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACtD,UAAU,MAAM,EAAE,EAClB,kBAAkB,GAAG,CAAC,MAAM,EAAE,qBAAqB,CAAC,EACpD,cAAc;IACV,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,cAAc,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,iBAAiB,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAC5C,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC/B,EACD,iBAAiB,qBAAqB,EAAE,GAAG,IAAI,KAChD,MAAM,EAuNR,CAAC"}