mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-14 19:34:34 +00:00
Add test for IfcFixedReferenceSweptAreaSolid with simple sweep example
Includes `simple_sweep_1.ifc` test input and geometry validation. Updates dependencies in `pixi.lock`.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
|
||||
FILE_NAME('/dev/null','2025-08-26T16:01:38+02:00',('AdaUser'),('AdaOrg'),'IfcOpenShell 0.8.2','IfcOpenShell 0.8.2','Nobody');
|
||||
FILE_SCHEMA(('IFC4X3_ADD2'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROJECT('1TMwI763XBx9E7h3kqXonB',$,'AdaProject',$,$,$,$,(#11),#6);
|
||||
#2=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
|
||||
#3=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
|
||||
#4=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
|
||||
#5=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
|
||||
#6=IFCUNITASSIGNMENT((#5,#3,#4,#2));
|
||||
#7=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#8=IFCDIRECTION((0.,0.,1.));
|
||||
#9=IFCDIRECTION((1.,0.,0.));
|
||||
#10=IFCAXIS2PLACEMENT3D(#7,#8,#9);
|
||||
#11=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#10,$);
|
||||
#12=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#11,$,.MODEL_VIEW.,$);
|
||||
#13=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Axis','Model',*,*,*,*,#11,$,.GRAPH_VIEW.,$);
|
||||
#14=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Box','Model',*,*,*,*,#11,$,.MODEL_VIEW.,$);
|
||||
#15=IFCACTORROLE(.ENGINEER.,$,$);
|
||||
#16=IFCPERSON('AdaUser',$,$,$,$,$,(#15),$);
|
||||
#17=IFCORGANIZATION('ADA','Assembly For Design and Analysis',$,$,$);
|
||||
#18=IFCPERSONANDORGANIZATION(#16,#17,$);
|
||||
#19=IFCAPPLICATION(#17,'XXX','ADA','ADA');
|
||||
#20=IFCOWNERHISTORY(#18,#19,.READWRITE.,$,$,#18,#19,1756216898);
|
||||
#21=IFCDIRECTION((0.,0.,1.));
|
||||
#22=IFCDIRECTION((1.,0.,0.));
|
||||
#23=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#24=IFCAXIS2PLACEMENT3D(#23,#21,#22);
|
||||
#25=IFCLOCALPLACEMENT($,#24);
|
||||
#26=IFCSITE('301mrn5JHCxRMMvjp9uGM1',#20,'Ada',$,$,#25,$,$,.ELEMENT.,$,$,$,$,$);
|
||||
#27=IFCRELAGGREGATES('0RnSPGnurA1RhM0uNbRZ8k',#20,'Project Container',$,#1,(#26));
|
||||
#28=IFCPROPERTYSINGLEVALUE('project',$,IFCTEXT('AdaProject'),$);
|
||||
#29=IFCPROPERTYSINGLEVALUE('schema',$,IFCTEXT('IFC4X3_add2'),$);
|
||||
#30=IFCPROPERTYSET('1Yj9$v$uH0ZQk9AOoWx4hD',#20,'Properties',$,(#28,#29));
|
||||
#31=IFCRELDEFINESBYPROPERTIES('2zKQjOOuP0VwvxPEpnJusI',#20,'Properties',$,(#26),#30);
|
||||
#32=IFCMATERIAL('S355',$,'Steel');
|
||||
#33=IFCPROPERTYSINGLEVALUE('Grade',$,IFCTEXT('S355'),$);
|
||||
#34=IFCPROPERTYSINGLEVALUE('YieldStress',$,IFCPRESSUREMEASURE(355000000.),$);
|
||||
#35=IFCPROPERTYSINGLEVALUE('YoungModulus',$,IFCMODULUSOFELASTICITYMEASURE(210000000000.),$);
|
||||
#36=IFCPROPERTYSINGLEVALUE('PoissonRatio',$,IFCPOSITIVERATIOMEASURE(0.3),$);
|
||||
#37=IFCPROPERTYSINGLEVALUE('ThermalExpansionCoefficient',$,IFCTHERMALEXPANSIONCOEFFICIENTMEASURE(1.2E-05),$);
|
||||
#38=IFCPROPERTYSINGLEVALUE('SpecificHeatCapacity',$,IFCSPECIFICHEATCAPACITYMEASURE(0.03),$);
|
||||
#39=IFCPROPERTYSINGLEVALUE('MassDensity',$,IFCMASSDENSITYMEASURE(7850.),$);
|
||||
#40=IFCMATERIALPROPERTIES('MaterialMechanical','A Material property description',(#33,#34,#35,#36,#37,#38,#39),#32);
|
||||
#41=IFCRELASSOCIATESMATERIAL('13SLSaNyz4PwOBYuDhXcWi',#20,'S355','Objects related to S355',(#64),#32);
|
||||
#42=IFCDIRECTION((0.,0.,1.));
|
||||
#43=IFCDIRECTION((1.,0.,0.));
|
||||
#44=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#45=IFCAXIS2PLACEMENT3D(#44,#42,#43);
|
||||
#46=IFCLOCALPLACEMENT(#25,#45);
|
||||
#47=IFCCARTESIANPOINTLIST2D(((0.,0.),(0.,0.1),(0.1,0.),(0.1,0.1)),$);
|
||||
#48=IFCINDEXEDPOLYCURVE(#47,(IFCLINEINDEX((3,1)),IFCLINEINDEX((1,2)),IFCLINEINDEX((2,4)),IFCLINEINDEX((4,3))),$);
|
||||
#49=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#48);
|
||||
#50=IFCCARTESIANPOINTLIST3D(((-1.,0.,0.8),(-0.14253,0.,0.542759),(-0.039541321421393,0.,0.470579850861542),(0.,0.,0.),(0.,0.,0.351194)),$);
|
||||
#51=IFCINDEXEDPOLYCURVE(#50,(IFCLINEINDEX((4,5)),IFCARCINDEX((5,3,2)),IFCLINEINDEX((2,1))),$);
|
||||
#52=IFCDIRECTION((-0.,1.,0.));
|
||||
#53=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#54=IFCDIRECTION((1.,0.,0.));
|
||||
#55=IFCDIRECTION((0.,0.,-1.));
|
||||
#56=IFCAXIS2PLACEMENT3D(#53,#54,#55);
|
||||
#57=IFCFIXEDREFERENCESWEPTAREASOLID(#49,#56,#51,$,$,#52);
|
||||
#58=IFCSHAPEREPRESENTATION(#12,'Body','AdvancedSweptSolid',(#57));
|
||||
#59=IFCPRODUCTDEFINITIONSHAPE($,$,(#58));
|
||||
#60=IFCCOLOURRGB('Color1',0.8,0.8,0.8);
|
||||
#61=IFCSURFACESTYLESHADING(#60,0.);
|
||||
#62=IFCSURFACESTYLE('Color1',.BOTH.,(#61));
|
||||
#63=IFCSTYLEDITEM(#57,(#62),'Color1');
|
||||
#64=IFCBUILDINGELEMENTPROXY('1R8AUxDeX02RhatZPFgzSt',#20,'sweep1',$,$,#46,#59,$,$);
|
||||
#65=IFCRELCONTAINEDINSPATIALSTRUCTURE('0HNU_Fs7r0SRBiQ9Xqgv$k',#20,'Physical model',$,(#64),#26);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -0,0 +1,62 @@
|
||||
import pathlib
|
||||
from typing import List, Sequence, Tuple
|
||||
|
||||
import ifcopenshell
|
||||
import pytest
|
||||
|
||||
|
||||
def _bbox_from_vertices(verts: List[Tuple[float, float, float]]):
|
||||
if not verts:
|
||||
return (0, 0, 0), (0, 0, 0)
|
||||
xs = [v[0] for v in verts]
|
||||
ys = [v[1] for v in verts]
|
||||
zs = [v[2] for v in verts]
|
||||
mn = (min(xs), min(ys), min(zs))
|
||||
mx = (max(xs), max(ys), max(zs))
|
||||
return mn, mx
|
||||
|
||||
|
||||
def _size_from_bbox(mn, mx):
|
||||
return (mx[0] - mn[0], mx[1] - mn[1], mx[2] - mn[2])
|
||||
|
||||
|
||||
def _triples(flat: Sequence[float]) -> List[Tuple[float, float, float]]:
|
||||
return [(float(flat[i]), float(flat[i + 1]), float(flat[i + 2])) for i in range(0, len(flat), 3)]
|
||||
|
||||
def load_ifc_mesh_bbox(ifc_path: str):
|
||||
"""Load first product's mesh from IFC using ifcopenshell.geom and return bbox and size."""
|
||||
try:
|
||||
import ifcopenshell.geom as geom
|
||||
except Exception as e:
|
||||
raise RuntimeError("ifcopenshell.geom not available: cannot validate IFC geometry") from e
|
||||
|
||||
settings = geom.settings()
|
||||
settings.set(settings.USE_WORLD_COORDS, True)
|
||||
|
||||
f = ifcopenshell.open(ifc_path)
|
||||
# Prefer the proxy we created, otherwise take any product with representation
|
||||
products = f.by_type("IfcProduct")
|
||||
target = None
|
||||
for p in products:
|
||||
if p.is_a("IfcBuildingElementProxy") and getattr(p, "Representation", None):
|
||||
target = p
|
||||
break
|
||||
if target is None:
|
||||
for p in products:
|
||||
if getattr(p, "Representation", None):
|
||||
target = p
|
||||
break
|
||||
if target is None:
|
||||
raise RuntimeError("No representable product found in IFC for validation")
|
||||
|
||||
shape = geom.create_shape(settings, target)
|
||||
verts = _triples(shape.geometry.verts)
|
||||
mn, mx = _bbox_from_vertices(verts)
|
||||
return mn, mx, _size_from_bbox(mn, mx)
|
||||
|
||||
@pytest.fixture
|
||||
def test_dir():
|
||||
return pathlib.Path(__file__).parent.resolve().absolute()
|
||||
def test_simple_sweep_1(test_dir):
|
||||
ifc_mn, ifc_mx, ifc_sz = load_ifc_mesh_bbox(test_dir / "input_temp/simple_sweep_1.ifc")
|
||||
assert ifc_sz == pytest.approx((1.1, 0.1, 0.89578254))
|
||||
Reference in New Issue
Block a user