New documentation about creating geometry in IFC

Every so often, we get questions about "how do I create geometry in IFC"? This is a difficult question to answer since you need to 1) know something about matrixes 2) know about geometry like meshes and extrusions 3) know how BIM is special that you can have multiple geometries per object 4) know how parametric BIM is extra special since we have the concept of layers and types and profiles and 5) put it altogether in a thing like IFC and the official IFC docs are spread out.

I've been slowly chipping away at this (4 thousand word behemoth) documentation which goes through in painstaking detail (and lots of code examples) from beginning to end everything you need to know about geometry. I'd invite anybody without any Friday night plans to read through and let me know whether it helps clear any confusion: https://blenderbim.org/docs-python/ifcopenshell-python/geometry_creation.html

This includes non-coders! There is a lot of code examples since it's meant for coders, but I genuinely believe non-coders can understand it too!

theoryshawCoenNigelbrunopostleGorgiousBimloosercarlopavbitacovirAceatomkarincaand 15 others.

Comments

  • Wow, this is so incredibly useful! Thank you very much for all the hard work and effort you put into this.

    theoryshaw
  • When creating a beam with blenderBIM, there are options to extend/change the length.
    This option does not exist when creating a beam using python.

  • @smr02 there actually is a way to do it, but the UI isn't exposed (and right now we've moved it to the Debug panel).

    The difference is that the first is a material profile set, whereas the second is just a regular extruded profile. Right now, the "extend" tool only works for material profile sets.

  • edited August 2023

    thank you, @Moult
    I'm now looking into creating a Material profile sets.
    1. There are two errors in the code. I think it should be like this:

    # First, let's create a material set. This will later be assigned to our beam type element.
    material_set = ifcopenshell.api.run("material.add_material_set", model,
        name="B1", set_type="IfcMaterialProfileSet")
    
    # Create an I-beam profile curve. Notice how we use standardised steel profile names.
    hea100 = model.create_entity(
        "IfcIShapeProfileDef", ProfileName="HEA100", ProfileType="AREA",
        OverallWidth=100, OverallDepth=96, WebThickness=5, FlangeThickness=8, FilletRadius=12,
    )
    
    1. I'm running into a error that i can't solve:
      File "/home/smr/Desktop/blenderIDE/tutorial.py", line 177, in <module>
        representation = ifcopenshell.api.run("geometry.add_profile_representation", model, context=body, profile=hea100, depth=1)
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/__init__.py", line 66, in run
        result = usecase_class(ifc_file, **settings).execute()
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 42, in execute
        self.settings["context"].ContextIdentifier,
    AttributeError: 'NoneType' object has no attribute 'ContextIdentifier'
    

    BlenderBIM version: 0.0.230801

  • The line body = ifcopenshell.util.representation.get_representation(element, "Model", "Body") was overwriting my body variable with None. I've removed this line. Now it's working. Thank you!

  • I've written a script that converts a FEM model to IFC.
    Now I'm looking for a function similar to "extend_profile" in BlenderBIM.
    Alternatively, how can I edit my representation?

        body = ifcopenshell.util.representation.get_context(model, "Model", "Body", "MODEL_VIEW")
        representation = ifcopenshell.api.run(
            "geometry.add_profile_representation", 
            model, 
            context=body, 
            profile=profile, 
            depth=beam_length #length
        )
        ifcopenshell.api.run("geometry.assign_representation", model, product=beam, representation=representation)
    

  • There is no "packaged" code available to extend a profile in pure Blender-agnostic code right now. Extension is a bit of a more advanced deal, for example: when you extend a profile, what if the profile was parametrically connected to something? Should it remove that parametric extension too? Should it then remove all boolean clippings (e.g. mitred clips) too or preserve them?

    So you'll need to decide how you want to handle it: you can remove the representation and create a fresh representation from scratch, or simply traverse the representation tree's extruded area solid element then change the Depth attribute of the extrusion.

  • Here's a screenshot of a minimal example of what i want to do.
    I want to extend the beam and then add voids to model the connections. So for now the only thing I want to preserve are voids because the beam likely has multiple connections.
    I think it's enough to change the depth attribute. However, I need to be able to do this on both ends of the beam.

  • Don't use a opening void, use a half space clipping plane. See https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/src/blenderbim/blenderbim/bim/module/model/profile.py#L382 which is how BBIM does it.

  • Ok, that makes sense.
    How do I create a IfcHalfSpaceSolid? I'm stuck here:

    body = ifcopenshell.util.representation.get_context(model, "Model", "Body", "MODEL_VIEW")
    
    vertices = [[(0.,0.,0.), (0.,2.,0.), (2.,2.,0.), (2.,0.,0.), (1.,1.,1.)]]
    faces = [[(0,1,2,3), (0,4,1), (1,4,2), (2,4,3), (3,4,0)]]
    representation = run("geometry.add_mesh_representation", model, context=body, vertices=vertices, faces=faces)
    
    matrix = np.array(
                (
                    (1, 0, 0, 0),
                    (0, 1, 0, 0),
                    (0, 0, 1, 0),
                    (0, 0, 0, 1),
                )
            )
    
    half_space = ifcopenshell.api.run(
            "geometry.add_boolean", 
            model, 
            representation = representation,
            # # IfcHalfSpaceSolid, Mesh
            type = "IfcHalfSpaceSolid",
            # # The XY plane is the clipping boundary and +Z is removed.
            matrix = matrix,  # A matrix to define a clipping Ifchalfspacesolid.
    
        )
    
      File "/home/smr/Desktop/simple_truss/test.py", line 52, in <module>
        half_space = ifcopenshell.api.run(
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/__init__.py", line 66, in run
        result = usecase_class(ifc_file, **settings).execute()
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_boolean.py", line 44, in execute
        result = self.create_half_space_solid()
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_boolean.py", line 58, in create_half_space_solid
        self.file.createIfcCartesianPoint(
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/file.py", line 337, in create_entity
        e[idx] = arg
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/entity_instance.py", line 262, in __setitem__
        self.method_list[idx](self.wrapped_data, idx, entity_instance.unwrap_value(value))
      File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/ifcopenshell_wrapper.py", line 3814, in setArgumentAsAggregateOfDouble
        return _ifcopenshell_wrapper.entity_instance_setArgumentAsAggregateOfDouble(self, i, v)
    TypeError: Attribute of type AGGREGATE OF REAL needs a python sequence of floats
    
  • Did you try providing floats in the matrix, not integers?

  • Now it's running. It didn't like the numpy matrix

    matrix = [
        [1., 0., 0., 0.],
        [0., 1., 0., 0.],
        [0., 0., 1., 0.],
        [0., 0., 0., 1.],
    ]
    

    Now I have a IfcHalfSpaceSolid. How do i "apply" it to my beam?

  • @Moult awsome text, tanks. Just a question about Mesh representations : in BlenderBIM we just have Tessellations, right? Btw when I export/re-import an IFC, all flat surfaces are transformed into a set of triangles, and I have to Delete>Limited Dissolve. Am I doing something wrong, could I save it differently in the IFC ?

  • @smr02 when you do geometry.add_boolean, it applies the boolean to the representation you specify via representation = representation. That should be the beam's representation.

    @RaphaëlVouilloz meshes in BBIM will become Tessellations in IFC4 and FacetedBReps in IFC2X3. Non-meshes in BBIM will stay as non-meshes (e.g. extruded profiles, etc).

    Conversion into a set of triangles is unfortunately just how IfcOpenShell auto-tessellates everything right now. It's not ideal and something @aothms will be investigating in IfcOpenShell 0.8.

    RaphaëlVouilloz
  • Keep in mind that ifopsh does provide additional information. In addition to the faces sequence of ints you also have edges. This serves two purposes. In case no surfaces / volumes exist, edges may provide line segment (e.g annotation, grid) geometries. But in case of non-empty faces, edges will provide the triangle edges which are also edges in the BRep model. So in principle you can dissolve exactly those edges. With one caveat though, that in the BRep model faces can be curved. So you shouldn't dissolve the edges in between of two triangles with different normal vecs.

    MoultRaphaëlVouillozbrunopostle
  • @Moult thank you.


    matrix = np.eye(4) matrix = ifcopenshell.util.placement.rotation(30, "Y") @ matrix matrix[:,3][0:3] = (0, 0, 1) matrix = matrix.tolist() ifcopenshell.api.run( "geometry.add_boolean", model, representation = beam.Representation.Representations[0], # # IfcHalfSpaceSolid, Mesh type = "IfcHalfSpaceSolid", # # The XY plane is the clipping boundary and +Z is removed. matrix = matrix, # A matrix to define a clipping Ifchalfspacesolid. )

    beam.Representation.Representations[0] is probably not the best way, in case there are multiple representations?

    How do i now extend the beam to the clipping plane?

  • When i try do extend the beam created with my above code into blenderBim, I get the following error:



    Traceback (most recent call last): File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/tool/ifc.py", line 186, in execute IfcStore.execute_ifc_operator(self, context) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/ifc.py", line 334, in execute_ifc_operator result = getattr(operator, "_execute")(context) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/module/model/profile.py", line 842, in _execute joiner.set_depth(obj, self.depth) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/module/model/profile.py", line 304, in set_depth self.recreate_profile(element1, profile1, axis, body) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/module/model/profile.py", line 443, in recreate_profile new_body = ifcopenshell.api.run( File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/__init__.py", line 66, in run result = usecase_class(ifc_file, **settings).execute() File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 44, in execute [self.create_item()], File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 60, in create_item return self.apply_clippings(extrusion) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 66, in apply_clippings if clipping["operand_type"] == "IfcHalfSpaceSolid": File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/entity_instance.py", line 245, in __getitem__ if key < 0 or key >= len(self): TypeError: '<' not supported between instances of 'str' and 'int' Error: Python: Traceback (most recent call last): File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/tool/ifc.py", line 186, in execute IfcStore.execute_ifc_operator(self, context) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/ifc.py", line 334, in execute_ifc_operator result = getattr(operator, "_execute")(context) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/module/model/profile.py", line 842, in _execute joiner.set_depth(obj, self.depth) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/module/model/profile.py", line 304, in set_depth self.recreate_profile(element1, profile1, axis, body) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/bim/module/model/profile.py", line 443, in recreate_profile new_body = ifcopenshell.api.run( File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/__init__.py", line 66, in run result = usecase_class(ifc_file, **settings).execute() File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 44, in execute [self.create_item()], File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 60, in create_item return self.apply_clippings(extrusion) File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/api/geometry/add_profile_representation.py", line 66, in apply_clippings if clipping["operand_type"] == "IfcHalfSpaceSolid": File "/home/smr/.config/blender/3.6/scripts/addons/blenderbim/libs/site/packages/ifcopenshell/entity_instance.py", line 245, in __getitem__ if key < 0 or key >= len(self): TypeError: '<' not supported between instances of 'str' and 'int'
  • @aothms oh wow! I have absolutely no idea that behaviour existed! Since when? Since always? This changes EVERYTHING! https://github.com/IfcOpenShell/IfcOpenShell/commit/1c74147d896f35ab250aa84bdb7fe3e7d7e04d4f

    @smr02 You'll either need to move your clipping plane down or increase the depth of your beam extrusion. You'll need to work out the math for this necessary depth yourself - we don't have any generic utils for calculating this.

    Can you share your IFC? Potentially it's a bug.

    Gorgious
  • Here is my IFC file.
    I can change the depth of the extrusion with representation.Items[0].Depth = 1500 in one direction.
    How do i change it in the opposite direction?

  • edited August 2023

    @smr02 the error you showed is caused by a bug that i've reported here (https://github.com/IfcOpenShell/IfcOpenShell/issues/3547).
    I tried to do also a PR here to resolve it

    smr02
  • @smr02 there is no "opposite direction", there is the start of the profile, then an extrusion depth. So you can change the object placement to change the start (or instead, just move your clipping plane).

  • This is great info. and very digestible for non-coders. Really appreciate the effort pulling it together. We often receive over detailed mesh representations so good to understand how these are handled by ifcopenshell, next step is to work out how to batch simplify these meshes...

Sign In or Register to comment.