Storey placement / elevation using ifcopenshell.api

Dear all,

I am very new to ifcopenshell, it is an amazing project!
I want to create an ifc file from scratch but I don't understand how to set the elevation of the building storeys in the root.create_entity function.

for index, story in enumerate(stories):
        elevation = story['data']['elevation']
        storey = ifcopenshell.api.run("root.create_entity", ifcfile, ifc_class="IfcBuildingStorey", name= str(index + 1).zfill(2) + " " + "Storey")
        ifcopenshell.api.run("aggregate.assign_object", ifcfile, relating_object=building, product=storey)

Could someone help me out?
Best!

Comments

  • Cool thank you! Looks like a great reference to look at also for other things
    Do you know if setting the story elevation is also possible using the API , so with the root.create_entity function.

  • The elevation is derived from the Z ordinate of the storey's placement. This means you should use the geometry.edit_object_placement API function and feed it a matrix.

    storey = run("root.create_entity", model, ifc_class="IfcBuildingStorey")
    m = np.eye(4)
    m[:,3][0:3] = (0,0,elevation) # Set XYZ coordinates
    run("geometry.edit_object_placement", model, product=storey, matrix=m, is_si=True)
    
    jemanik
  • Awesome. Thank you @Moult !
    When adding slabs tot the storey, do I have to repeat the process of geometry.edit_object_placement ?
    I was thinking setting the slab position to (0.0, 0.0, 0.0) and assigning the slab object to the storey should do it as well

    slab = ifcopenshell.api.run("root.create_entity", ifcfile, ifc_class="IfcSlab", name="Slab")
    extruded_solid = sb.extrude(profile, magnitude=slab_thickness, position=mathutils.Vector((0.0, 0.0, 0.0)), extrusion_vector=mathutils.Vector((0.0, 0.0, -1.0)))
    representation = sb.get_representation(body, extruded_solid)
    ifcopenshell.api.run("geometry.assign_representation", ifcfile, product=slab, representation=representation)
    ifcopenshell.api.run("spatial.assign_container", ifcfile, relating_structure=storey, product=slab)
    ifcopenshell.api.run("aggregate.assign_object", ifcfile, relating_object=storey, product=slab)
    

    But i does not for the slabs

  • All slabs need to have their own origin too. You can leave them as 0,0,0 if you want:

    run("geometry.edit_object_placement", model, product=storey) # No matrix means 0,0,0 / identity matrix
    

    One option to "model relatively" is to first model all the slabs with all the levels at 0,0,0, then move the levels to their elevation, which will move all the slabs with it if you set should_transform_children=True:

    # Add slabs to storey... then:
    run("geometry.edit_object_placement", model, product=storey, matrix=m, is_si=True, should_transform_children=True)
    
  • Thank you @Moult !
    Following this approach I still don't get the right global placement

    for index, story in enumerate(stories):
        elevation = story['data']['elevation']
        storey = ifcopenshell.api.run("root.create_entity", ifcfile, ifc_class="IfcBuildingStorey", name= str(index + 1).zfill(2) + " " + "Storey")
        ifcopenshell.api.run("aggregate.assign_object", ifcfile, relating_object=building, product=storey)
        for space in story['data']['children']:
            points = space['data']['pts']
            make_slab(ifcfile, sb, body, storey, points, slab_thickness=0.2)
        m = np.eye(4)
        m[:,3][0:3] = (0,0,elevation) # Set XYZ coordinates
        ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=storey, matrix=m, is_si=True, should_transform_children=True)
    
    def make_slab(ifcfile, sb, body, storey, points, slab_thickness=0.2):
        pts = convert_points(points)
        profile = sb.polyline(pts)
        slab = ifcopenshell.api.run("root.create_entity", ifcfile, ifc_class="IfcSlab", name="Slab")
        extruded_solid = sb.extrude(profile, magnitude=slab_thickness, position=mathutils.Vector((0.0, 0.0, 0.0)), extrusion_vector=mathutils.Vector((0.0, 0.0, -1.0)))
        representation = sb.get_representation(body, extruded_solid)
        ifcopenshell.api.run("geometry.assign_representation", ifcfile, product=slab, representation=representation)
        ifcopenshell.api.run("spatial.assign_container", ifcfile, relating_structure=storey, product=slab)
        ifcopenshell.api.run("aggregate.assign_object", ifcfile, relating_object=storey, product=slab)
        ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=slab)
        create_style(ifcfile, representation, ColorRGB(.89, .89, .89))
    

  • Have you tried first setting your slab's origin to 0,0,0 and only afterwards shifting it up?

    ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=storey) # set to 0,0,0
    # ... add slabs
    ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=storey, matrix=m, is_si=True, should_transform_children=True)
    

    BTW containment is mutually exclusive to aggregation. Remove this:

    ifcopenshell.api.run("aggregate.assign_object", ifcfile, relating_object=storey, product=slab)
    

    ... slabs should be contained in storeys, not aggregated in storeys (because a slab is not a part of a storey).

    By the way there are also API functions to help with this:

    create_style(ifcfile, representation, ColorRGB(.89, .89, .89))
    
    jemanik
  • This does the job
    Thank you so much for your advice and patience!!

    for index, story in enumerate(stories):
            elevation = story['data']['elevation']
            storey = ifcopenshell.api.run("root.create_entity", ifcfile, ifc_class="IfcBuildingStorey", name= str(index + 1).zfill(2) + " " + "Storey")
            ifcopenshell.api.run("aggregate.assign_object", ifcfile, relating_object=building, product=storey)
            ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=storey) # set to 0,0,0
            for space in story['data']['children']:
                points = space['data']['pts']
                pts = convert_points(points)
                profile = sb.polyline(pts)
                slab = ifcopenshell.api.run("root.create_entity", ifcfile, ifc_class="IfcSlab", name="Slab")
                extruded_solid = sb.extrude(profile, magnitude=0.2, position=mathutils.Vector((0.0, 0.0, 0.0)), extrusion_vector=mathutils.Vector((0.0, 0.0, -1.0)))
                representation = sb.get_representation(body, extruded_solid)
                ifcopenshell.api.run("geometry.assign_representation", ifcfile, product=slab, representation=representation)
                ifcopenshell.api.run("spatial.assign_container", ifcfile, relating_structure=storey, product=slab)
                ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=slab)
            m = np.eye(4)
            m[:,3][0:3] = (0,0,elevation) # Set XYZ coordinates
            ifcopenshell.api.run("geometry.edit_object_placement", ifcfile, product=storey, matrix=m, is_si=True, should_transform_children=True)
    
  • Cheers! Indeed you need to set the storey to 0,0,0 first so that it knows that children are relative to that 0,0,0, so that when you move it later, the children move with it.

    You should also make sure your building / site / etc are set to 0,0,0 so that you have a proper tree of relative coordinates.

Sign In or Register to comment.