If you're reading this, we've just migrated servers! If anything looks broken please email dion@thinkmoult.com :)

IfcOpenshell: How to: an IfcBeamTypeInstance using an IfcProfile with IfcParametrizedProfileDef?

My attempt has been as following:
1. Tried to create an IfcProfile using ifcopenshell.api.
Looked here:
https://sourcegraph.com/search?q=context:global+profile+repo:^github\.com/IfcOpenShell/IfcOpenShell$+file:src/ifcopenshell-python&patternType=standard
Read the BS documentation:
https://standards.buildingsmart.org/IFC/DEV/IFC4_3/RC2/HTML/schema/ifcmaterialresource/lexical/ifcmaterialprofile.htm
2) Tried to create a IfcBeamType instance with IfcMaterial:

import ifcopenshell.api

element_name='my_beam'

ifc_file = ifcopenshell.api.run("project.create_file")
project = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcProject", name="BlenderBIM Demo")

ifcopenshell.api.run( "project.assign_declaration", ifc_file, definition=project, relating_context=project)
ifcopenshell.api.run("unit.assign_unit", ifc_file, length={"is_metric": True, "raw": "METERS"})

material = ifcopenshell.api.run("material.add_material", ifc_file, name='beam_material')

element = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class='IfcBeamType', name=element_name)

profile_1 = ifcopenshell.api.run("material.assign_material", ifc_file, product=element, type="IfcMaterialProfileSetUsage")
profile_set = profile_1.RelatingMaterial

profile_2 = ifc_file.create_entity("IfcMaterialProfile")

ifcopenshell.api.run("project.assign_declaration", ifc_file, definition=element, relating_context=project)

ifc_file.write("D:\\02_ifc\\ifc_bibliotheek\\" + str(element_name) + ".ifc")   

Quite clueless on how to tie it all together, this script just outputs this:

ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
FILE_NAME('/dev/null','2022-11-06T11:31:03+01:00',(),(),'IfcOpenShell v0.7.0-cdde5366','IfcOpenShell v0.7.0-cdde5366','Nobody');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPROJECT('3NWCe2Fg16oO7d$m1LJcmY',$,'BlenderBIM Demo',$,$,$,$,$,#6);
#2=IFCRELDECLARES('0WOKmCVaz6$QsPWDCFj_FP',$,$,$,#1,(#8,#1));
#3=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#4=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#5=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#6=IFCUNITASSIGNMENT((#4,#5,#3));
#7=IFCMATERIAL('beam_material',$,$);
#8=IFCBEAMTYPE('2CPnfvwOT6O9ZQyImvzlxU',$,'my_beam',$,$,$,$,$,$,.NOTDEFINED.);
#9=IFCMATERIALPROFILESET($,$,$,$);
#10=IFCMATERIALPROFILESETUSAGE(#9,$,$);
#11=IFCRELASSOCIATESMATERIAL('0LU7BOA5v1h9_90260WfJ0',$,$,$,(#8),#10);
#12=IFCMATERIALPROFILE($,$,$,$,$,$);
ENDSEC;
END-ISO-10303-21;

Somehow I need to define the IfcParametrizedProfileDef somewhere, hardcoded the X and Y dimensions, say to the IfcBeamType instance, you are now using an IfcProfile..
Is there a very simple example script somewhere?

Comments

  • @theoryshaw
    Thanks! I was looking for that, finally I understand it,

    import ifcopenshell.api
    
    
    element_name='my_beam'
    ifc_file = ifcopenshell.api.run("project.create_file")
    project = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcProject", name="BlenderBIM Demo")
    
    ifcopenshell.api.run( "project.assign_declaration", ifc_file, definition=project, relating_context=project)
    ifcopenshell.api.run("unit.assign_unit", ifc_file, length={"is_metric": True, "raw": "METERS"})
    
    model = ifcopenshell.api.run("context.add_context", ifc_file, context_type="Model")
    plan = ifcopenshell.api.run("context.add_context", ifc_file, context_type="Plan")
    representations = {
        "body": ifcopenshell.api.run(
            "context.add_context",
            ifc_file,
            context_type="Model",
            context_identifier="Body",
            target_view="MODEL_VIEW",
            parent=model,
        ),
        "annotation": ifcopenshell.api.run(
            "context.add_context",
            ifc_file,
            context_type="Plan",
            context_identifier="Annotation",
            target_view="PLAN_VIEW",
            parent=plan,
        ),
    }
    
    
    material = ifcopenshell.api.run("material.add_material", ifc_file, name='beam_material')
    profile = ifc_file.create_entity("IfcRectangleProfileDef", ProfileType="AREA", XDim=0.5, YDim=0.6)
    
    element = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class='IfcBeamType', name=element_name)
    rel = ifcopenshell.api.run("material.assign_material", ifc_file, product=element, type="IfcMaterialProfileSet")
    profile_set = rel.RelatingMaterial
    material_profile = ifcopenshell.api.run( "material.add_profile", ifc_file, profile_set=profile_set, material=material)
    ifcopenshell.api.run("material.assign_profile", ifc_file, material_profile=material_profile, profile=profile)
    ifcopenshell.api.run("project.assign_declaration", ifc_file, definition=element, relating_context=project)
    
    ifc_file.write("D:\\02_ifc\\ifc_bibliotheek\\" + str(element_name) + ".ifc") 
    

    outputs:

    ISO-10303-21;
    HEADER;
    FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
    FILE_NAME('/dev/null','2022-11-06T18:14:10+01:00',(),(),'IfcOpenShell v0.7.0-cdde5366','IfcOpenShell v0.7.0-cdde5366','Nobody');
    FILE_SCHEMA(('IFC4'));
    ENDSEC;
    DATA;
    #1=IFCPROJECT('2prh7Q8cv0gQP0cEVv3X5i',$,'BlenderBIM Demo',$,$,$,$,(#11,#15),#6);
    #2=IFCRELDECLARES('2$qNb5ZJrAkwtlKF2_xIcw',$,$,$,#1,(#1,#20));
    #3=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
    #4=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
    #5=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
    #6=IFCUNITASSIGNMENT((#5,#3,#4));
    #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=IFCCARTESIANPOINT((0.,0.,0.));
    #13=IFCDIRECTION((1.,0.,0.));
    #14=IFCAXIS2PLACEMENT2D(#12,#13);
    #15=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Plan',2,1.E-05,#14,$);
    #16=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#11,$,.MODEL_VIEW.,$);
    #17=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Annotation','Plan',*,*,*,*,#15,$,.PLAN_VIEW.,$);
    #18=IFCMATERIAL('beam_material',$,$);
    #19=IFCRECTANGLEPROFILEDEF(.AREA.,$,$,0.5,0.6);
    #20=IFCBEAMTYPE('3NjduEPSD8rO4_gUk3YfbZ',$,'my_beam',$,$,$,$,$,$,.NOTDEFINED.);
    #21=IFCMATERIALPROFILESET($,$,(#23),$);
    #22=IFCRELASSOCIATESMATERIAL('1$CC$$22r6Cgn9FedD7wRG',$,$,$,(#20),#21);
    #23=IFCMATERIALPROFILE($,$,#18,#19,$,$);
    ENDSEC;
    END-ISO-10303-21;
    

    In BlenderBIM:

    How to add an IfcType instance with python?

  • You're almost there, you're just missing at the end:

    # Add occurrence based on type
    occurrence = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcBeam", name=element_name)
    ifcopenshell.api.run("type.assign_type", ifc_file, related_object=occurrence, relating_type=element)
    representation = ifcopenshell.api.run("geometry.add_profile_representation", ifc_file, context=contexts["body"], profile=profile, depth=3)
    ifcopenshell.api.run("geometry.assign_representation", ifc_file, product=occurrence, representation=representation)
    

    Also you can do this which is simpler:

    material_profile = ifcopenshell.api.run("material.add_profile", ifc_file, profile_set=profile_set, material=material, profile=profile)
    

    Don't use project.assign_declaration it is not necessary, you can delete every line that uses that. That's only used for asset library declarations.

    theoryshawCoen
  • @Moult
    Thanks! how would I place the IfcElementType instance using XYZ coordinates?

  • Use geometry.edit_object_placement.

  • edited November 2022

    @Moult
    Thank you. :-)

    What does depth=3 do in ifcopenshell.api.run("geometry.add_profile_representation", ifc_file, context=contexts["body"], profile=profile, depth=3)?

    And where is contexts defined in representation = ifcopenshell.api.run("geometry.add_profile_representation", ifc_file, context=contexts["body"], profile=profile, depth=3)

  • I changed this line
    ifcopenshell.api.run("geometry.add_profile_representation", ifc_file, context=contexts["body"], profile=profile, depth=3)
    to
    representation = ifcopenshell.api.run("geometry.add_profile_representation", ifc_file, context=representations["body"], profile=profile, depth=3)
    I have not defined an IfcBuildingStorey to place the beam in, but for some strange reason, when loading the created IFC in BlenderBIM my beam appears vertical:

  • edited November 2022

    How do I add an IfcBuilding, IfcSite and IfcBuildingStorey using the ifcopenshell.api?
    I know i can do it with IfcOpenShell like following:

    site_placement = create_ifclocalplacement(ifcfile)
    site = ifcfile.createIfcSite(create_guid(), owner_history, "site", None, None, site_placement, None, None, "ELEMENT", None, None, None, None, None)
    
    building_placement = create_ifclocalplacement(ifcfile, relative_to=site_placement)
    building = ifcfile.createIfcBuilding(create_guid(), owner_history, 'osarch_building', None, None, building_placement, None, None, "ELEMENT", None, None, None)
    
    storey_placement = create_ifclocalplacement(ifcfile, relative_to=building_placement)
    building_storey = ifcfile.createIfcBuildingStorey(  create_guid(),
                                                                owner_history,
                                                                '0' + str(i) + '_building_storey',
                                                                None,
                                                                None, 
                                                                storey_placement,
                                                                None,
                                                                None,
                                                                "ELEMENT",
                                                                0)
            container_storey = ifcfile.createIfcRelAggregates(create_guid(), owner_history, "Building Container", None, building, [building_storey])
    
    

    Not really clear to me how to translate this to the ifcopenshell.api

    EDIT:
    found it here in @Martin156131 thread:
    https://community.osarch.org/discussion/1221/ifcopenshell-python-how-using-the-objectplacement-in-ifcwall#latest

    site = run("root.create_entity", model, ifc_class="IfcSite", name="My Site")
    building = run("root.create_entity", model, ifc_class="IfcBuilding", name="Building A")
    storey = run("root.create_entity", model, ifc_class="IfcBuildingStorey", name="Ground Floor")
    
  • I have a working script, still need to figure out how to place the IfcElement correctly

    Script to be found here:
    https://github.com/C-Claus/BlenderScripts/blob/master/BlenderBIM_create_objects/create_beam.py

  • The beam is vertical because all extrusions in IFC have the convention of extruding in the local Z axis. This is an awesome convention and makes a huge difference in the reliability of geometric analysis. So if you want the beam to be flat, just edit its ObjectPlacement matrix.

  • matrix = numpy.array(
                (
                    (1.0, 0.0, 0.0, 2.0),
                    (0.0, 1.0, 0.0, 1.0),
                    (0.0, 0.0, 1.0, 1.0),
                    (0.0, 0.0, 0.0, 1.0),
                )
            )
    
    ifcopenshell.api.run("geometry.edit_object_placement",ifc_file, product=occurrence, matrix=matrix) 
    

    @Moult, thanks, never worked with numpy arrays, need to figure it out first.

  • edited November 2022

    Where is the length of the IfcBeamType instance defined in the ifcopenshell.api? Can't find it in the example scripts or documentation.

  • The length is called depth=3 in the add_profile_representation call.

    The matrix is a 4x4 matrix described here https://blenderbim.org/docs-python/ifcopenshell-python/geometry_processing.html#individual-processing

    Coentheoryshaw

  • Yes, horizontal beam! @Moult Thanks for patiently answering all my ignorant questions.

  • Getting the hang of it now

    for i in range(0, 10, 1): 
    
    
        matrix_1 = numpy.array(
                    (
                        (0.0, 0.0, 1.0, 0.0),
                        (0.0, 1.0, 0.0, i),
                        (1.0, 0.0, 0.0, 0.0),
                        (0.0, 0.0, 0.0, 1.0),
                    )
                )
    
        matrix_1 = numpy.array(matrix_1)
    
        occurrence = ifcopenshell.api.run("root.create_entity", ifc_file, ifc_class="IfcBeam", name=element_name, )
        ifcopenshell.api.run("type.assign_type", ifc_file, related_object=occurrence, relating_type=element)
        representation = ifcopenshell.api.run("geometry.add_profile_representation", ifc_file, context=representations["body"], profile=profile, depth=5)
    
    

    theoryshawAcebrunopostle
  • Okay, this is a lot of fun, paramatric foundation beam system.. code is a mess now, but it works.

  • edited November 2022


    Next step, slab and walls.
    EDIT:
    https://github.com/C-Claus/BlenderScripts/blob/master/BlenderBIM_create_objects/create_beam_array.py
    Also the beams should align neatly now within their constraint when changing the profile.
    It all should work with only 5 config variables,:

    beam_length_x = 1
    beam_profile_y = 0.4
    beam_profile_x = 0.5
    beam_total_length_n_y = 10
    beam_inbetween_distance = 3 #=beam_length_y = 3
    
    theoryshawNigel
  • If you can get the code working with an arbitrary polygonal profile (i.e. not only rectangular), then that would be super cool and we could reuse your code for a feature for exactly that.

  • @Moult said:
    If you can get the code working with an arbitrary polygonal profile (i.e. not only rectangular), then that would be super cool and we could reuse your code for a feature for exactly that.

    I will attempt

    cvillagrasa
  • It seems we are set on a very similar journey currently @Coen. I've been reading your different endeavours with great interest, and I'd like to thank you for documenting it so thorougly. I've still got lots to learn, and it's great fun to see others taking baby steps around me :)

    The example demo is great but I think we can do more, there are in fact a lot of hidden snippets in the codebase, it would be nice to document them a bit more in depth. I'll do what I can to help :)

    cvillagrasatheoryshawCoenArv
  • edited November 2022

    @Gorgious
    Thanks for the kind words. There's a lot of knowledge on this forum. Many people here know how to point you in the right direction, so I don't drown in reading boring documentation. I'd like to document it together somewhere in a coherent way with fun little practical code snippets. Just curious where there's a demand. Because most of the stuff I document I do it for myself.

  • Is it possible to miter two beams with IfcOpenShell?

  • @Coen I think all that stuff is in the blenderbim Cad module, I would very much like to see it moved into the IfcOpenShell API.

    Coentheoryshaw
  • @Moult said:
    If you can get the code working with an arbitrary polygonal profile (i.e. not only rectangular), then that would be super cool and we could reuse your code for a feature for exactly that.

    First attempt with an I profile,

    I think I need to use the predefined profiles from the EU demo library exactly for this purpose.
    I was having fun and also decided to add columns

    Just curious now how one would no would miter all these beams with python.
    Where is the described what the feature should do exactly?

    theoryshawAce
Sign In or Register to comment.