@Moult following is a test of this new ifcopenshell api. Let me know if I'm on the right track.
I'm not using any blender specific code yet, I'm hoping that there is some magic to conjure up blender geometry from this ifc data (or maybe it is the other way around, I'm clueless!). IfcOwnerHistory doesn't seem to work for me, though I haven't really dug into this. I think I can work with numpy matrices for transforms, is this recommended? There doesn't seem to be an api for assembling geometry, so I'm constructing a SweptSolid the old fashioned way, is this ok?
#!/usr/bin/python3
import numpy
import ifcopenshell.api
# save some typing
run = ifcopenshell.api.run
ifc = run("project.create_file")
# try and set up ownerhistory
myperson = run("owner.add_person", ifc)
myorganisation = run("owner.add_organisation", ifc)
ownerhistory = run(
"owner.create_owner_history",
ifc,
person=myperson,
organisation=myorganisation,
) # doesn't seem to do anything
# create a "project > site > building > storey" hierarchy
project = run(
"root.create_entity",
ifc,
ifc_class="IfcProject",
name="My Project",
)
run("unit.assign_unit", ifc, length={"is_metric": True, "raw": "METERS"})
mycontext = run("context.add_context", ifc)
subcontext = run(
"context.add_context",
ifc,
context="Model",
subcontext="Body",
target_view="MODEL_VIEW",
)
site = run("root.create_entity", ifc, ifc_class="IfcSite", name="My Site")
building = run(
"root.create_entity", ifc, ifc_class="IfcBuilding", name="My Building"
)
storey = run(
"root.create_entity", ifc, ifc_class="IfcBuildingStorey", name="My Storey"
)
run("aggregate.assign_object", ifc, product=site, relating_object=project)
run("aggregate.assign_object", ifc, product=building, relating_object=site)
run("aggregate.assign_object", ifc, product=storey, relating_object=building)
# create a sweptsolid:
# start with a 2D profile in the XY plane
profile = ifc.createIfcArbitraryClosedProfileDef(
"AREA",
None,
ifc.createIfcPolyline(
[
ifc.createIfcCartesianPoint((1.0, 0.1)),
ifc.createIfcCartesianPoint((4.0, 0.2)),
ifc.createIfcCartesianPoint((4.0, 3.1)),
ifc.createIfcCartesianPoint((1.0, 3.1)),
ifc.createIfcCartesianPoint((1.0, 0.1)), # last point is same as first, oh my
]
),
)
# this is just a default coordinate system
axis = ifc.createIfcAxis2Placement3D(
ifc.createIfcCartesianPoint((0.0, 0.0, 0.0)), None, None
)
# Z positive up direction
direction = ifc.createIfcDirection([0.0, 0.0, 1.0])
# extrude the profile 0.5m
solid = ifc.createIfcExtrudedAreaSolid(profile, axis, direction, 0.5)
# solid needs to be put in a shape
shape = ifc.createIfcShapeRepresentation(
subcontext, "Body", "SweptSolid", [solid]
)
# how do we use this as a placement relative to the storey origin?
shift = ifc.createIfcAxis2Placement3D(
ifc.createIfcCartesianPoint((0.0, 0.0, 3.0)), None, None
)
localplacement = ifc.createIfcLocalPlacement(axis, shift)
# create an ifcslab without a representation
slab = run("root.create_entity", ifc, ifc_class="IfcSlab", name="My Slab")
# assign the shape created earlier as the ifcslab representation
run("geometry.assign_representation", ifc, product=slab, representation=shape)
# place the ifcslab, but an identity matrix doesn't do anything
run("geometry.edit_object_placement", ifc, product=slab, matrix=numpy.eye(4))
# put the slab in the storey
run("spatial.assign_container", ifc, product=slab, relating_structure=storey)
ifc.write("test.ifc")