Editing IfcOpenShell code examples

From Wiki.OSArch

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
 
{{Template:Start coding}}
 
{{Template:Start coding}}
{{Template:IfcOpenShell}}
+
 
 
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. You may also find it useful watching [https://www.youtube.com/watch?v=WZPNaAM9ZuQ this video] which is complementary.
 
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. You may also find it useful watching [https://www.youtube.com/watch?v=WZPNaAM9ZuQ this video] which is complementary.
  
Line 10: Line 10:
 
import ifcopenshell
 
import ifcopenshell
 
ifc = ifcopenshell.open('/path/to/your/file.ifc')
 
ifc = ifcopenshell.open('/path/to/your/file.ifc')
</syntaxhighlight>
 
 
...or if you already opened the file in BlenderBIM, for example, you could use...
 
 
<syntaxhighlight lang="python">
 
import ifcopenshell
 
from blenderbim.bim.ifc import IfcStore
 
ifc = ifcopenshell.open(IfcStore.path)
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 199: Line 191:
 
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 <code>Representation</code> 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.
 
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 <code>Representation</code> 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.
  
The simplest way to get started is to use the <code>create_shape</code> function to convert an element into vertices, edges, and faces.
+
Note: this article is a work in progress.
 +
 
 +
TODO: talk about [https://github.com/IfcOpenShell/IfcOpenShell/issues/866 naming in ids].
  
 
<syntaxhighlight lang="python">
 
<syntaxhighlight lang="python">
 +
import multiprocessing
 
import ifcopenshell
 
import ifcopenshell
 
import ifcopenshell.geom
 
import ifcopenshell.geom
  
 
ifc_file = ifcopenshell.open('/path/to/your/file.ifc')
 
ifc_file = ifcopenshell.open('/path/to/your/file.ifc')
 
element = ifc_file.by_type('IfcWall')[0]
 
 
 
settings = ifcopenshell.geom.settings()
 
settings = ifcopenshell.geom.settings()
shape = ifcopenshell.geom.create_shape(settings, element)
+
iterator = ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count())
faces = shape.geometry.faces # Indices of vertices per triangle face e.g. [f1v1, f1v2, f1v3, f2v1, f2v2, f2v3, ...]
+
valid_file = iterator.initialize()
verts = shape.geometry.verts # X Y Z of vertices in flattened list e.g. [v1x, v1y, v1z, v2x, v2y, v2z, ...]
+
if valid_file:
materials = shape.geometry.materials # Material names and colour style information that are relevant to this shape
+
    while True:
material_ids = shape.geometry.material_ids # Indices of material applied per triangle face e.g. [f1m, f2m, ...]
+
        shape = iterator.get()
 
+
        element = ifc_file.by_guid(shape.guid)
# Since the lists are flattened, you may prefer to group them per face like so depending on your geometry kernel
+
        if not iterator.next():
grouped_verts = [[verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
+
            break
grouped_faces = [[faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
 
</syntaxhighlight>
 
 
 
Once you have a list of vertices, edges, and faces, you can perform any standard mesh algorithm to do more geometric analysis. There are a series of settings you can apply when creating a shape. These are documented [https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/docs/geom/settings.md here].
 
 
 
All shapes are given an ID to uniquely identify it. These IDs following a [https://github.com/IfcOpenShell/IfcOpenShell/issues/866 naming scheme].
 
 
 
If you have a lot of geometry to process, it is advised to use the geometry iterator. This will process shapes using more than one CPU and is significantly faster.
 
 
 
<syntaxhighlight lang="python">
 
import multiprocessing
 
import ifcopenshell
 
import ifcopenshell.geom
 
 
 
try:
 
    ifc_file = ifcopenshell.open('/path/to/your/file.ifc')
 
except:
 
    print(ifcopenshell.get_log())
 
else:
 
    settings = ifcopenshell.geom.settings()
 
    iterator = ifcopenshell.geom.iterator(settings, ifc_file, multiprocessing.cpu_count())
 
    if iterator.initialize():
 
        while True:
 
            shape = iterator.get()
 
            element = ifc_file.by_guid(shape.guid)
 
            faces = shape.geometry.faces # Indices of vertices per triangle face e.g. [f1v1, f1v2, f1v3, f2v1, f2v2, f2v3, ...]
 
            verts = shape.geometry.verts # X Y Z of vertices in flattened list e.g. [v1x, v1y, v1z, v2x, v2y, v2z, ...]
 
            materials = shape.geometry.materials # Material names and colour style information that are relevant to this shape
 
            material_ids = shape.geometry.material_ids # Indices of material applied per triangle face e.g. [f1m, f2m, ...]
 
 
 
            # Since the lists are flattened, you may prefer to group them per face like so depending on your geometry kernel
 
            grouped_verts = [[verts[i], verts[i + 1], verts[i + 2]] for i in range(0, len(verts), 3)]
 
            grouped_faces = [[faces[i], faces[i + 1], faces[i + 2]] for i in range(0, len(faces), 3)]
 
            if not iterator.next():
 
                break
 
 
</syntaxhighlight>
 
</syntaxhighlight>
 
==Geometry tree (clash detection/ray tracing etc…)==
 
You can use [[https://blenderbim.org/docs-python/ifcopenshell-python/geometry_tree.html geometry tree]] to perform various task like clash detection and ray tracing. Trees are common terms is geometry libraries. IfcOpenShell tree has [[https://en.wikipedia.org/wiki/Bounding_volume_hierarchy BVHTree]] functionalities.
 
  
 
=IFC Query Syntax=
 
=IFC Query Syntax=
Line 319: Line 273:
 
# This gets all walls and slabs in a particular building storey
 
# This gets all walls and slabs in a particular building storey
 
elements = selector.parse(ifc, '@ #0ehnsYoIDA7wC8yu69IDjv & ( .IfcWall | .IfcSlab )')
 
elements = selector.parse(ifc, '@ #0ehnsYoIDA7wC8yu69IDjv & ( .IfcWall | .IfcSlab )')
</syntaxhighlight>
 
 
<syntaxhighlight lang="python">
 
# This gets all walls and slabs in a particular space (if IfcRelSpaceBoundary exist)
 
elements = selector.parse(ifc, '@@ .IfcSpace & ( .IfcWall | .IfcSlab )')
 
</syntaxhighlight>
 
 
 
You can also use query a specific element. It is what you do when using [[BlenderBIM_Add-on/BlenderBIM_IFCCSV | IfcCsv]] for example.
 
 
<syntaxhighlight lang="python">
 
# This gets all walls and slabs in a particular building storey
 
wall = selector.parse(ifc, '.IfcWall')[0]
 
wall_name = selector.get_element_value(wall, "Name")
 
wall_type_name = selector.get_element_value(wall, "type.Name")
 
wall_is_external = selector.get_element_value(wall, "Pset_WallCommon.IsExternal")
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Line 387: Line 325:
 
<entity IfcFlowSegment>
 
<entity IfcFlowSegment>
 
</syntaxhighlight>
 
</syntaxhighlight>
 
Another way to get a list of supertypes :
 
<!-- From discussion here: https://app.element.io/#/room/#OSArch:matrix.org/$LKrDGOp4OT3Qfbpl-Yj8QeUDG5mowS0YXrAKr0OBjts -->
 
<syntaxhighlight lang="python">
 
>>> import ifcopenshell
 
>>> s = ifcopenshell.ifcopenshell_wrapper.schema_by_name('IFC4')
 
>>> e = s.declaration_by_name('IfcWall')
 
>>> inheritance = []
 
>>> while e.supertype():
 
...    inheritance.append(e.supertype())
 
...    e = e.supertype()
 
...
 
>>> inheritance
 
[<entity IfcBuildingElement>, <entity IfcElement>, <entity IfcProduct>, <entity IfcObject>, <entity IfcObjectDefinition>, <entity IfcRoot>]
 
</syntaxhighlight>
 
 
  
 
Get subtypes :
 
Get subtypes :
Line 413: Line 335:
 
  <entity IfcPipeSegment>)
 
  <entity IfcPipeSegment>)
 
</syntaxhighlight>
 
</syntaxhighlight>
 
  
 
=Property and quantity sets (Pset and Qto)=
 
=Property and quantity sets (Pset and Qto)=
Line 467: Line 388:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=File validation=
 
Ifcopenshell allows you to validate a file against its corresponding schema.
 
==From command line==
 
<syntaxhighlight lang="python">
 
python -m ifcopenshell.validate some_file.ifc
 
</syntaxhighlight>
 
On GNU/Linux you can store result in a json file:
 
<syntaxhighlight lang="bash">
 
python -m ifcopenshell.validate --json some_file.ifc >> json_output_path.json
 
</syntaxhighlight>
 
 
==Inside a script==
 
It looks similar to command line way but you need to provide a logger (standard logger or json_logger as below).
 
<syntaxhighlight lang="python">
 
import ifcopenshell
 
import ifcopenshell.validate
 
 
ifc_file = ifcopenshell.open("some_file.ifc")
 
json_logger = ifcopenshell.validate.json_logger()
 
ifcopenshell.validate.validate(ifc_file, json_logger)
 
json_logger.statements
 
</syntaxhighlight>
 
 
=Date and time in IFC=
 
=Date and time in IFC=
 
Date and time conversion can be error prone. Fortunately IFC has chosen wide used definitions so standard python [https://docs.python.org/3/library/datetime.html datetime] and [https://docs.python.org/3/library/time.html time] modules have tools to handle most of them.
 
Date and time conversion can be error prone. Fortunately IFC has chosen wide used definitions so standard python [https://docs.python.org/3/library/datetime.html datetime] and [https://docs.python.org/3/library/time.html time] modules have tools to handle most of them.
Line 500: Line 399:
 
# To convert it to datetime (UTC+1 in this example)
 
# To convert it to datetime (UTC+1 in this example)
 
>>> import datetime
 
>>> import datetime
>>> datetime.date.fromtimestamp(0)
+
>>> datetime.fromtimestamp(0)
datetime.date(1970, 1, 1, 1, 0)
+
datetime.datetime(1970, 1, 1, 1, 0)
>>> datetime.date.fromtimestamp(1610829915)
+
>>> datetime.fromtimestamp(1610829915)
datetime.date(2021, 1, 16, 21, 45, 15)
+
datetime.datetime(2021, 1, 16, 21, 45, 15)
 
</syntaxhighlight>
 
</syntaxhighlight>
 
 
==IfcDateTime==
 
==IfcDateTime==
 
[https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/link/ifcdatetime.htm IfcDateTime] is stored in ISO 8601 format : YYYY-MM-DDThh:mm:ss
 
[https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/link/ifcdatetime.htm IfcDateTime] is stored in ISO 8601 format : YYYY-MM-DDThh:mm:ss
Line 558: Line 456:
 
!Additional infos
 
!Additional infos
 
|-
 
|-
| [https://academy.ifcopenshell.org/posts/ifcopenshell-optimizer-tutorial/ Optimize IFC files]
+
| [http://academy.ifcopenshell.org/optimize-ifc-files/ http://academy.ifcopenshell.org/optimize-ifc-files/]
 
| python
 
| python
 
| 0.6.0-0d93633
 
| 0.6.0-0d93633
 
|-
 
|-
| [https://academy.ifcopenshell.org/posts/calculate-differences-of-ifc-files-with-hashing/ Calculate Differences of IFC files with Hashing]
+
| [http://academy.ifcopenshell.org/calculate-differences-of-ifc-files-with-hashing/ Calculate Differences of IFC files with Hashing]
 
| python
 
| python
 
| 0.6.0-0d93633
 
| 0.6.0-0d93633
Line 584: Line 482:
 
| FreeCAD 0.18 git
 
| FreeCAD 0.18 git
 
|-
 
|-
| [https://academy.ifcopenshell.org/posts/using-ifcopenshell-and-c%2B%2B-to-generate-alignments-through-the-ifc-4x1-schema/ Using IfcOpenShell and C++ to generate Alignments through the IFC 4×1 schema]
+
| [http://academy.ifcopenshell.org/using-ifcopenshell-and-c-to-generate-alignments-through-the-ifc-4x1-schema/ Using IfcOpenShell and C++ to generate Alignments through the IFC 4×1 schema]
 
| python/C++
 
| python/C++
 
|-
 
|-
| [https://academy.ifcopenshell.org/posts/creating-a-simple-wall-with-property-set-and-quantity-information/ Creating a simple wall with property set and quantity information]
+
| [http://academy.ifcopenshell.org/creating-a-simple-wall-with-property-set-and-quantity-information/ Creating a simple wall with property set and quantity information]
 
| python
 
| python
 
|-
 
|-
| [https://academy.ifcopenshell.org/posts/using-ifcopenshell-and-pythonocc-to-generate-cross-sections-directly-from-an-ifc-file/ Using IfcOpenshell and pythonOCC to generate cross sections directly from an IFC file]
+
| [http://academy.ifcopenshell.org/using-ifcopenshell-and-pythonocc-to-generate-cross-sections-directly-from-an-ifc-file/ Using IfcOpenshell and pythonOCC to generate cross sections directly from an IFC file]
 
| python
 
| python
 
| <= 0.6 ?
 
| <= 0.6 ?
 
| pythonOCC 0.16.0 ?
 
| pythonOCC 0.16.0 ?
 
|-
 
|-
|[https://academy.ifcopenshell.org/posts/using-the-parsing-functionality-of-ifcopenshell-interactively/ Using the parsing functionality of IfcOpenShell interactively]
+
|[http://academy.ifcopenshell.org/using-the-parsing-functionality-of-ifcopenshell-interactively/ Using the parsing functionality of IfcOpenShell interactively]
 
| python
 
| python
 
|-
 
|-
|[https://academy.ifcopenshell.org/posts/using-ifcopenshell-and-pythonocc-to-construct-new-geometry/ Using IfcOpenShell and pythonOCC to construct new geometry]
+
|[http://academy.ifcopenshell.org/using-ifcopenshell-and-pythonocc-to-construct-new-geometry/ Using IfcOpenShell and pythonOCC to construct new geometry]
 
| python
 
| python
 
| <= 0.6
 
| <= 0.6

Please note that all contributions to Wiki.OSArch are considered to be released under the Creative Commons Attribution-ShareAlike (see Wiki.OSArch:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel Editing help (opens in new window)