Repository navigation
[Bugs] ifc-converter, editor: export wall assembly layers to IFC; unpainted PDF shapes no longer filled - #1104
Conversation
…illed IFC: walls with an assembly were written as one "Core" IfcMaterialLayer of the total thickness, so receiving tools (Revit, Archicad) never saw the stucco / sheathing / framing / drywall stack. Each assembly layer is now an IfcMaterialLayer with its material, thickness, role and IFC4 category (LoadBearing for the core, Insulation, Finish), ordered from the front face so an exterior-faced stack stays outward on both wall directions. The layer set takes the preset label. Walls without an assembly keep the single Core layer. PDF: paintStyledGeometry built a path for geometry with neither fill nor stroke (zone outlines) and never ended it, so the next fill (the walls) painted it too and rooms printed as solid wall-coloured blocks in floorplan and sheet exports. The unpainted path is now ended with 'n'. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129pCwGotaTiKv5JgBv8vaC
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 52f7233. Configure here.
Aymericr
left a comment
There was a problem hiding this comment.
Thanks for this! The PDF fix (ending the unpainted path with n) looks right.
One thing to fix on the IFC side: the layer reversal checks resolveWallExteriorSide(wall) === -1, but core's wall-layer-bands.ts treats an unknown side as ?? -1. So on walls whose exterior side isn't known, IFC puts the stucco on the opposite face from what the 3D view shows. Could you switch it to (resolveWallExteriorSide(wall) ?? -1) === -1 and add a test for an unknown-side wall?
Minor: walls with identical layers but different preset labels end up sharing one layer set, so the second wall shows the first one's name. Worth including the label in the cache key.
| if (Math.abs(sum - thickness) > 1e-4) return null | ||
| // Layers run from the front face unless the stack starts at the exterior | ||
| // and the exterior is the back face. | ||
| const startsAtBack = assembly.face === 'exterior' && resolveWallExteriorSide(wall) === -1 |
There was a problem hiding this comment.
Core treats an unknown side as -1 here (?? -1 in wall-layer-bands.ts), so this should be (resolveWallExteriorSide(wall) ?? -1) === -1 to keep IFC matching the 3D view.
|
Hey @muratdbc, quick nudge on this one, no new push since the review yet. Two things left:
Once those are in, I'll kick off CI and take another look. Thanks! |
…ed as IfcLogical An exterior-faced assembly on a wall whose exterior side is undetermined now starts at the back face, matching core's `?? -1` fallback in wall-layer-bands, so IFC layers sit on the same faces as the 3D view. IfcMaterialLayer.IsVentilated is an IfcLogical in IFC4; air layers now emit IFCLOGICAL(.T.) instead of IFCBOOLEAN(.T.). Co-authored-by: Murat Gocmen <8277046+muratdbc@users.noreply.github.com>
|
Thanks @muratdbc for this contribution! We pushed the two small review fixes on top of your commit (3cdaf32) so this can land sooner: walls with an unknown exterior side now use the |

What does this PR do?
Fixes #1103. Related: #981 (IFC4 export).
IFC — wall assembly layers (
packages/ifc-converter/src/export/scene-to-ifc.ts)assemblynow exports oneIfcMaterialLayerper layer: anIfcMaterialnamed after the layer's material (falling back to its role), the layer thickness, the layer id as Name, the role as Description, and the IFC4 category (LoadBearingfor the core,Insulation,Finish).airlayers are marked ventilated.AXIS2/POSITIVEusage at-faces.astarts. A stack withface: 'exterior'whose exterior is the back face is reversed, so the exterior finish stays outward whichever way the wall was drawn.Exterior 2x6 — stucco).Corelayer. Usages are still shared per thickness/offset/stack.PDF — unpainted shapes (
packages/editor/src/lib/floorplan/floorplan-pdfkit-renderer.ts)paintStyledGeometrybuilt a path for geometry with neither fill nor stroke (zone outlines) and never ended it, so the next fill (the walls) painted it as well and every room printed as a dark block. The path is now ended withn.How to test
bun test packages/ifc-converter/tests/export-wall-assembly.test.ts: 3 new tests (layer stack and set name, one wall reversed so both orientations are covered, no-assembly fallback). Two of them fail onmain.bun test packages/editor/src/lib/floorplan/floorplan-pdfkit-renderer.test.ts: the new test fails onmain.ifc-convertersuite passes (95 tests). I also opened the exported IFC (two-bedroom template with theexterior-2x6-stuccoandinterior-2x4-drywallpresets) in IfcOpenShell 0.9: 0 schema issues, 4 and 3 layers per wall, and a geometric check that the stucco is on the outside of every exterior wall, with one wall reversed as well.Screenshots / screen recording
Not a UI change. Before the PDF fix, a floorplan sheet of the two-bedroom template printed every room as a solid #374151 block; after it, rooms are blank with walls, dimensions and marks drawn as usual.
Checklist
bun dev(tested headless through the packages and tests instead)bun checkto verify)mainbranch🤖 Generated with Claude Code
https://claude.ai/code/session_0129pCwGotaTiKv5JgBv8vaC
Note
Medium Risk
IFC wall material export behavior changes for assembled walls (more entities and sharing keys); PDF fix is localized to unpainted geometry rendering.
Overview
Fixes floorplan PDF export where zone outlines with no fill/stroke left an open path, so the next wall fill painted every room as a solid block. Unpainted geometry now ends the path with PDF operator
n(end path without painting), with a regression test on grouped zone + wall polygons.IFC export now maps Pascal wall assemblies to multi-layer
IfcMaterialLayerSetstacks when layer thicknesses match the wall body. Each layer gets its own material, thickness, role metadata, IFC4 category (e.g. LoadBearing for core), and ventilatedIfcLogicalfor air gaps; layer order follows the front face and reverses when an exterior-facing assembly’s exterior is on the back. Preset labels name the layer set; walls without a valid assembly still get a single core layer. Newexport-wall-assembly.test.tscovers stack order, reversed walls, unknown exterior side, air layers, and the no-assembly fallback.Reviewed by Cursor Bugbot for commit 3cdaf32. Bugbot is set up for automated code reviews on this repo. Configure here.