IfcOpenShell code examples
Before getting started, you may be interested in Using the Python console with BlenderBIM Add-on, to quickly install all the software and development environment you need for writing and running code, without any administrator privileges required.
Crash course
To load a file, you'll need to import IfcOpenShell and store the IFC file in a variable. We'll use the variable ifc
. The ifc
will be then used throughout.
import ifcopenshell
ifc = ifcopenshell.open('/path/to/your/file.ifc')
Let's see what IFC schema we are using:
print(ifc.schema) # May return IFC2X3 or IFC4
Let's get the first piece of data in our IFC file:
print(ifc.by_id(1))
But getting data from beginning to end isn't too meaningful to humans. What if we knew a GlobalId
value instead?
print(ifc.by_guid('0EI0MSHbX9gg8Fxwar7lL8'))
If we're not looking specifically for a single element, perhaps let's see how many walls are in our file, and count them:
walls = ifc.by_type('IfcWall')
print(len(walls))
Once we have an element, we can see what IFC class it is:
wall = ifc.by_type('IfcWall')[0]
print(wall.is_a()) # Returns 'IfcWall'
You can also test if it is a certain class, as well as check for parent classes too:
print(wall.is_a('IfcWall')) # Returns True
print(wall.is_a('IfcElement')) # Returns True
print(wall.is_a('IfcWindow')) # Returns False
Let's quickly check the STEP ID of our element:
print(wall.id())
Let's get some attributes of an element. IFC attributes have a particular order. We can access it just like a list, so let's get the first and third attribute:
print(wall[0]) # The first attribute is the GlobalId
print(wall[2]) # The third attribute is the Name
Knowing the order of attributes is boring and technical. We can access them by name too:
print(wall.GlobalId)
print(wall.Name)
Getting attributes one by one is tedious. Let's grab them all:
print(wall.get_info()) # Gives us a dictionary of attributes, such as {'id': 8, 'type': 'IfcWall', 'GlobalId': '2_qMTAIHrEYu0vYcqK8cBX', ... }
Let's see all the properties and quantities associated with this wall:
print(ifcopenshell.util.get_psets(wall))
Some attributes are special, called "inverse attributes". They happen when another element is referencing our element. They can reference it for many reasons, like to define a relationship, such as if they create a void in our wall, join our wall, or define a quantity take-off value for our wall, among others. Just treat them like regular attributes:
print(wall.IsDefinedBy)
Perhaps we want to see all elements which are referencing our wall?
print(ifc.get_inverse(wall))
Let's do the opposite, let's see all the elements which our wall references instead:
print(ifc.traverse(wall))
print(ifc.traverse(wall, max_levels=1)) # Or, let's just go down one level deep
If you want to modify data, just assign it to the relevant attribute:
wall.Name = 'My new wall name'
You can also generate new GlobalId
s:
wall.GlobalId = ifcopenshell.guid.new()
After modifying some IFC data, you can save it to a new IFC-SPF file:
ifc.write('/path/to/a/new.ifc')
You can generate a new IFC from scratch too, instead of reading an existing one:
ifc = ifcopenshell.file()
# Or if you want a particular schema:
ifc = ifcopenshell.file(schema='IFC4')
You can create new IFC elements, and add it either to an existing or newly created IFC file object:
new_wall = ifc.createIfcWall() # Will return #1=IfcWall($,$,$,$,$,$,$,$,$) - notice all of the attributes are blank!
print(ifc.by_type('IfcWall')) # Will return a list with our wall in it: [#1=IfcWall($,$,$,$,$,$,$,$,$)]
Alternatively, you can also use this way to create new elements:
ifc.create_entity('IfcWall')
Specifying more arguments lets you fill in attributes while creating the element instead of assigning them separately. You specify them in the order of the attributes.
ifc.create_entity('IfcWall', ifcopenshell.guid.new()) # Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,$,$,$,$,$,$,$)
Again, knowing the order of attributes is difficult, so you can use keyword arguments instead:
ifc.create_entity('IfcWall', GlobalId=ifcopenshell.guid.new(), Name='Wall Name') # Gives us #1=IfcWall('0EI0MSHbX9gg8Fxwar7lL8',$,'Wall Name',$,$,$,$,$,$)
Sometimes, it's easier to expand a dictionary:
data = {
'GlobalId': ifcopenshell.guid.new(),
'Name': 'Wall Name'
}
ifc.create_entity('IfcWall', **data)
Some attributes of an element aren't just text, they may be a reference to another element. Easy:
wall = ifc.createIfcWall()
wall.OwnerHistory = ifc.createIfcOwnerHistory()
What if we already have an element from one IFC file and want to add it to another?
wall = ifc.by_type('IfcWall')[0]
new_ifc = ifcopenshell.file()
new_ifc.add(wall)
Fed up with an object? Let's delete it:
ifc.remove(wall)
Geometry processing
The usage of IfcOpenShell for geometry processing is currently considered to be moderate to advanced. There are two approaches to processing geometry. One approach is to traverse the Representation
attribute of the IFC element, and parse it yourself. This requires an in-depth understanding of IFC geometric representations, as well as its many caveats with units and transformations, but can be very simple to extract specific types of geometry. The second approach is to use IfcOpenShell's shape processing features, which will convert almost all IFC representations into a triangulated mesh. Regardless of the source format, once it is in a mesh representation, you may use standard mesh geometry processing algorithms to analyse the geometry. This makes it easier to write generic code for any representation, but may be harder to extract certain geometric features.
Note: this article is a work in progress.
TODO: talk about naming in ids.
Samples from web
Subject | Language | Version | Additional infos |
---|---|---|---|
Understanding placements in IFC using IfcOpenShell and FreeCAD | python | 0.6.0a1 | FreeCAD 0.18 git |
Using IfcOpenShell to parse IFC files with Python | python | ||
Read geometry as Boundary Representation in FreeCAD | python | 0.6.0a1 | FreeCAD 0.18 git |
Read IFC geometry as triangle meshes in FreeCAD | python | 0.6.0a1 | FreeCAD 0.18 git |
Using IfcOpenShell and C++ to generate Alignments through the IFC 4×1 schema | python/C++ | ||
Creating a simple wall with property set and quantity information | python | ||
Using IfcOpenshell and pythonOCC to generate cross sections directly from an IFC file | python | <= 0.6 ? | pythonOCC 0.16.0 ? |
Using the parsing functionality of IfcOpenShell interactively | python | ||
Using IfcOpenShell and pythonOCC to construct new geometry | python | <= 0.6 | pythonOCC 0.16.0 |
Various ifc creation examples (little house, geometry etc…) | C++ |