Skip to content

IFC import: plain profile-extruded IfcSlab renders offset with wrong thickness #629

Description

@thebossnow

What happened

Imported a minimal hand-authored IFC4 file (IfcProjectIfcSiteIfcBuildingIfcBuildingStorey, one IfcSlab, four IfcWalls forming its perimeter) through editor.pascal.app/ifc.

  • The 4 walls round-tripped perfectly: reported Length 10.00ft, Height 9.84ft, Thickness 0.656ft — exact matches for the 3.048m / 3m / 0.2m in the source file.
  • The slab (IfcArbitraryClosedProfileDef + IfcExtrudedAreaSolid, no material layer set, PredefinedType = .BASESLAB.) came in as "Footprint 1 slab" but rendered offset to the side of the wall footprint instead of underneath it, and reports Thickness 0.16ft (≈0.049m) instead of the file's 0.15m.

Expected: the slab occupies the same footprint as the walls (same rectangle, verified below) and reports 0.15m / ~0.492ft thickness.

What I ruled out

  • The file is internally consistent: the slab's profile points (#42#46, (1.524,1.524)(4.572,3.9624)) are the exact same absolute coordinates as the wall corner placements (#86, #108, #130, #152). The stored IfcExtrudedAreaSolid depth is 0.14999999999999999 (0.15m), not ~0.049m.
  • Suspected a missing ObjectPlacement on the spatial tree/slab (my exporter originally left it null). Added an explicit identity IfcLocalPlacement on IfcSite/IfcBuilding/IfcBuildingStorey and the slab, re-exported, re-tested. Identical result — same offset, same 0.16ft thickness. So it isn't a null-placement artifact; the attached file already has the explicit placements.

A hypothesis, unconfirmed: the slab's extrusion is authored with the local placement's Z-axis flipped ((0,0,-1)) and a local extrusion direction of (0,0,1), so it extrudes downward in world space with a positive depth value (top surface at the placement origin, base below it) — a valid but slightly unusual IFC authoring pattern. The walls in the same file don't do this (local Z stays (0,0,1), and the wall's placement carries the position instead of baking it into the profile). If your depth/extent-recovery code assumes a non-flipped local frame, that combination might be what's tripping it up specifically for the slab. I haven't looked at packages/ifc-converter's source to confirm this — just flagging it as the one structural difference I can see between the wall (works) and slab (doesn't) authoring in this file.

Repro file (IFC4, ~5.5KB, walls + slab as described above):

pascal_test2.ifc
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('','2026-08-10T14:52:59',(''),(''),'IfcOpenShell 0.8.5-1c5b825','IfcOpenShell 0.8.5-1c5b825','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROJECT('0X2rkhFXDCOAqVNZAthnn4',$,'untitled',$,$,$,$,(#10),#5);
#2=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#3=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#4=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#5=IFCUNITASSIGNMENT((#4,#2,#3));
#6=IFCCARTESIANPOINT((0.,0.,0.));
#7=IFCDIRECTION((0.,0.,1.));
#8=IFCDIRECTION((1.,0.,0.));
#9=IFCAXIS2PLACEMENT3D(#6,#7,#8);
#10=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.0000000000000001E-05,#9,$);
#11=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#10,$,.MODEL_VIEW.,$);
#12=IFCSITE('0q2RAHQ9zFNOG5yVK015mH',$,'Site',$,$,#22,#41,$,$,$,$,$,$,$);
#13=IFCBUILDING('2ivlxUwjjAHAPN_qSWj3OP',$,'Building',$,$,#27,$,$,$,$,$,$);
#14=IFCBUILDINGSTOREY('03qMmw5mX1fhw_uEBhpvQo',$,'Ground Floor',$,$,#32,$,$,$,$);
#15=IFCRELAGGREGATES('1Fex0KvXr9k8qi5ztnhGvk',$,$,$,#1,(#12));
#16=IFCRELAGGREGATES('21lLDdwILDU8sBR_j_qwlQ',$,$,$,#12,(#13));
#17=IFCRELAGGREGATES('3yquw45zzFgwkWPEJr70jf',$,$,$,#13,(#14));
#18=IFCCARTESIANPOINT((0.,0.,0.));
#19=IFCDIRECTION((0.,0.,1.));
#20=IFCDIRECTION((1.,0.,0.));
#21=IFCAXIS2PLACEMENT3D(#18,#19,#20);
#22=IFCLOCALPLACEMENT($,#21);
#23=IFCCARTESIANPOINT((0.,0.,0.));
#24=IFCDIRECTION((0.,0.,1.));
#25=IFCDIRECTION((1.,0.,0.));
#26=IFCAXIS2PLACEMENT3D(#23,#24,#25);
#27=IFCLOCALPLACEMENT(#22,#26);
#28=IFCCARTESIANPOINT((0.,0.,0.));
#29=IFCDIRECTION((0.,0.,1.));
#30=IFCDIRECTION((1.,0.,0.));
#31=IFCAXIS2PLACEMENT3D(#28,#29,#30);
#32=IFCLOCALPLACEMENT(#27,#31);
#33=IFCCARTESIANPOINT((0.,0.));
#34=IFCCARTESIANPOINT((9.1440000000000001,0.));
#35=IFCCARTESIANPOINT((9.1440000000000001,15.24));
#36=IFCCARTESIANPOINT((0.,15.24));
#37=IFCCARTESIANPOINT((0.,0.));
#38=IFCPOLYLINE((#33,#34,#35,#36,#37));
#39=IFCGEOMETRICCURVESET((#38));
#40=IFCSHAPEREPRESENTATION(#11,'Body','GeometricCurveSet',(#39));
#41=IFCPRODUCTDEFINITIONSHAPE($,$,(#40));
#42=IFCCARTESIANPOINT((1.524,1.524));
#43=IFCCARTESIANPOINT((4.5720000000000001,1.524));
#44=IFCCARTESIANPOINT((4.5720000000000001,3.9624000000000001));
#45=IFCCARTESIANPOINT((1.524,3.9624000000000001));
#46=IFCCARTESIANPOINT((1.524,1.524));
#47=IFCPOLYLINE((#42,#43,#44,#45,#46));
#48=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#47);
#49=IFCSLAB('1a_QZryoL4RA$jFb_MWudY',$,'Footprint 1 slab',$,$,#68,#57,$,.BASESLAB.);
#50=IFCCARTESIANPOINT((0.,0.,0.));
#51=IFCDIRECTION((0.,0.,-1.));
#52=IFCDIRECTION((1.,0.,0.));
#53=IFCAXIS2PLACEMENT3D(#50,#51,#52);
#54=IFCDIRECTION((0.,0.,1.));
#55=IFCEXTRUDEDAREASOLID(#48,#53,#54,0.14999999999999999);
#56=IFCSHAPEREPRESENTATION(#11,'Body','SweptSolid',(#55));
#57=IFCPRODUCTDEFINITIONSHAPE($,$,(#56));
#63=IFCRELCONTAINEDINSPATIALSTRUCTURE('2onKV5145BKe963NFyNzps',$,$,$,(#91,#135,#113,#49,#69),#14);
#64=IFCCARTESIANPOINT((0.,0.,0.));
#65=IFCDIRECTION((0.,0.,1.));
#66=IFCDIRECTION((1.,0.,0.));
#67=IFCAXIS2PLACEMENT3D(#64,#65,#66);
#68=IFCLOCALPLACEMENT(#32,#67);
#69=IFCWALL('2LU6EYJkH6yPANWtd$EcwV',$,'Footprint 1 wall 1',$,$,#90,#85,$,$);
#70=IFCCARTESIANPOINTLIST2D(((0.,0.),(0.,0.20000000000000001),(3.048,0.20000000000000001),(3.048,0.),(0.,0.)));
#71=IFCINDEXEDPOLYCURVE(#70,$,.F.);
#72=IFCDIRECTION((0.,0.,1.));
#73=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#71);
#74=IFCCARTESIANPOINT((0.,0.,0.));
#75=IFCDIRECTION((0.,0.,1.));
#76=IFCDIRECTION((1.,0.,0.));
#77=IFCAXIS2PLACEMENT3D(#74,#75,#76);
#78=IFCEXTRUDEDAREASOLID(#73,#77,#72,3.);
#79=IFCSHAPEREPRESENTATION(#11,'Body','SweptSolid',(#78));
#85=IFCPRODUCTDEFINITIONSHAPE($,$,(#79));
#86=IFCCARTESIANPOINT((1.524,1.524,0.));
#87=IFCDIRECTION((0.,0.,1.));
#88=IFCDIRECTION((1.,0.,0.));
#89=IFCAXIS2PLACEMENT3D(#86,#87,#88);
#90=IFCLOCALPLACEMENT(#32,#89);
#91=IFCWALL('1wt2kQo0b6qQ1SsGQnsZiL',$,'Footprint 1 wall 2',$,$,#112,#107,$,$);
#92=IFCCARTESIANPOINTLIST2D(((0.,0.),(0.,0.20000000000000001),(2.4384000000000001,0.20000000000000001),(2.4384000000000001,0.),(0.,0.)));
#93=IFCINDEXEDPOLYCURVE(#92,$,.F.);
#94=IFCDIRECTION((0.,0.,1.));
#95=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#93);
#96=IFCCARTESIANPOINT((0.,0.,0.));
#97=IFCDIRECTION((0.,0.,1.));
#98=IFCDIRECTION((1.,0.,0.));
#99=IFCAXIS2PLACEMENT3D(#96,#97,#98);
#100=IFCEXTRUDEDAREASOLID(#95,#99,#94,3.);
#101=IFCSHAPEREPRESENTATION(#11,'Body','SweptSolid',(#100));
#107=IFCPRODUCTDEFINITIONSHAPE($,$,(#101));
#108=IFCCARTESIANPOINT((4.5720000000000001,1.524,0.));
#109=IFCDIRECTION((0.,0.,1.));
#110=IFCDIRECTION((0.,1.,0.));
#111=IFCAXIS2PLACEMENT3D(#108,#109,#110);
#112=IFCLOCALPLACEMENT(#32,#111);
#113=IFCWALL('09Cl9kPrPEWuLu8h9oLi4e',$,'Footprint 1 wall 3',$,$,#134,#129,$,$);
#114=IFCCARTESIANPOINTLIST2D(((0.,0.),(0.,0.20000000000000001),(3.048,0.20000000000000001),(3.048,0.),(0.,0.)));
#115=IFCINDEXEDPOLYCURVE(#114,$,.F.);
#116=IFCDIRECTION((0.,0.,1.));
#117=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#115);
#118=IFCCARTESIANPOINT((0.,0.,0.));
#119=IFCDIRECTION((0.,0.,1.));
#120=IFCDIRECTION((1.,0.,0.));
#121=IFCAXIS2PLACEMENT3D(#118,#119,#120);
#122=IFCEXTRUDEDAREASOLID(#117,#121,#116,3.);
#123=IFCSHAPEREPRESENTATION(#11,'Body','SweptSolid',(#122));
#129=IFCPRODUCTDEFINITIONSHAPE($,$,(#123));
#130=IFCCARTESIANPOINT((4.5720000000000001,3.9624000000000001,0.));
#131=IFCDIRECTION((0.,0.,1.));
#132=IFCDIRECTION((-1.,0.,0.));
#133=IFCAXIS2PLACEMENT3D(#130,#131,#132);
#134=IFCLOCALPLACEMENT(#32,#133);
#135=IFCWALL('10Q_ZH6RP6MRUKqbM2I9_f',$,'Footprint 1 wall 4',$,$,#156,#151,$,$);
#136=IFCCARTESIANPOINTLIST2D(((0.,0.),(0.,0.20000000000000001),(2.4384000000000001,0.20000000000000001),(2.4384000000000001,0.),(0.,0.)));
#137=IFCINDEXEDPOLYCURVE(#136,$,.F.);
#138=IFCDIRECTION((0.,0.,1.));
#139=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#137);
#140=IFCCARTESIANPOINT((0.,0.,0.));
#141=IFCDIRECTION((0.,0.,1.));
#142=IFCDIRECTION((1.,0.,0.));
#143=IFCAXIS2PLACEMENT3D(#140,#141,#142);
#144=IFCEXTRUDEDAREASOLID(#139,#143,#138,3.);
#145=IFCSHAPEREPRESENTATION(#11,'Body','SweptSolid',(#144));
#151=IFCPRODUCTDEFINITIONSHAPE($,$,(#145));
#152=IFCCARTESIANPOINT((1.524,3.9624000000000001,0.));
#153=IFCDIRECTION((0.,0.,1.));
#154=IFCDIRECTION((0.,-1.,0.));
#155=IFCAXIS2PLACEMENT3D(#152,#153,#154);
#156=IFCLOCALPLACEMENT(#32,#155);
ENDSEC;
END-ISO-10303-21;

Generated by aiblueprint-mcp's new (minimal) IFC exporter while validating it against your importer — noticed this while testing rather than going looking for it. Happy to provide more variants if useful (e.g. a slab with local Z not flipped, to test the hypothesis above).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions