Hi!
I've been recently needing to level up my skills with the IFC schema, from the coding standpoint, because I feel that lots of useful things can be accomplished from that angle. Along those lines, I found a couple of random posts about an "IfcOpenHouse", and I decided to have a look into it in order to learn more. It turns out that it was an @aothms project from 2012, in which he demonstrated the capabilities of IfcOpenShell to programmatically generate a house. And all of that in C++! Huge feat for a time in which most of the industry didn't even understand the word "BIM" ?.
Link to the tutorial
So some weeks ago, I thought that it would be cool to try to recreate the same model with the high level API as a learning exercise. You can find the result as a step-by-step tutorial under the following link:
https://cvillagrasa.github.io/IfcOpenHouse/generation.html
Appart from IfcOpenShell, I've used nbdev to autogenerate a Quarto website + plain Python scripts, IFC.js for viz, and some custom code to make all of those pieces stick together.
The project consists of a Jupyter Notebook environment with some incorporated assistance to experiment with IFC models. The previous link points to the static website, for ease of access, from which there are further links to the actual notebook and the rest of the repository, if interested.
Questions that have arised
It is worth noting that at the moment, the project is totally experimental and should by no means be considered a correct usage of IFC nor the IfcOpenShell library. In fact, I've even placed some questions with my own doubts into Python comments. @Moult if you have time at some point, search in the link for "#q" and you'll come across those questions in context, although some of them are just mere suggestions. They are also listed as follows:
-
q1: Data-scientish notation as suggested below, context1, context2.
-
q2: Is
project.assign_declaration(file, definition=project, relating_context=project)
necessary? what does it do? I copied it from some snippet I found. -
q3: For clarity, should there be a
context.add_subcontext
call? -
q4: For placements, should there be an option to just give X (RefDirection) and Z (Axis), and don't deal with any matrix?
-
q5: Should there be a
geometry.add_extruded_representation
on a higher level thanshape_builder
? Accepting optional width/depth, or radius, or a profile. -
q6: Shouldn't there be an elegant solution by the API to avoid monkey-patching?
-
q6b: Calls to an add method, followed by another call to an edit method, like when adding psets, could be simplified into one call?
-
q7: How are IfcRelConnectsPathElements with ConnectionGeometry made?
-
q8: Any viewer in which to check advanced BREPs with IfcBSplineSurfaceWithKnots?
-
q9: I removed usages, as they were in the original IfcOpenHouse. The validator was complaining, and it seems that in "modern IFC", usages go together with types. Should I add types? types + usages? leave it as it is?
-
q10: When building doors or windows with
geometry.add_door_representation
andgeometry.add_window_representation
, will it be possible to apply different styles to different "subrepresentations"? As in a wooden lining + glass panel, or a metallic door knob.
Below, there are some specific features which can be found in the notebook and deem some explanation:
Data Science notation
I'd love if the API leveraged the benefits of static signatures in the future. In a notebook environment, that would mean that running an API call followed by one question mark would show the help, and followed by two question marks would directly show the code. For now, in order to avoid calling methods as strings and have a conveniently short alias for the library more identifiable than "run", I created a temporary helper class which is imported as "ios" (short for IfcOpenShell).
Automatic garbage collection of overwritten entities
Envision for instance the following scenario: a cell of the notebook creates a wall entity as follows:
my_entity = ios.root.create_entity(file, ifc_class='IfcWall')
(Yes, I'm using a non-standard ios in a data-scientish way, to avoid strings and shorten commands to a significant alias, but that's another story).
Let's say that we run that cell, so that the variable my_entity now holds the newly created instance for the wall (say step ID #20)... but for some reason we regret, and rerun the cell creating a column instead:
my_entity = ios.root.create_entity(file, ifc_class='IfcColumn')
What now happens is that the variable my_entity points towards the newly created column (say with step ID #21), but the previous wall #20 doesn't get deleted from the file. This is logical from a scripting standpoint, but feels totally counterintuitive when interacting within a notebook environment. In order to be able to experiment without constantly polluting the IfcOpenShell file with unwanted instances, an audit hook provides some level of garbage collection. In the previous example, the wall entity with step ID #20 will be removed from the file when overwriting the Python variable pointing to it. It has also been successfully tested by changing the angle of the roof and rerunning all depending cells, and other similar tasks. Nevertheless, bear in mind that this is a highly experimental code and the door is open to unexpected results, so it shouldn't be used in production under any circumstances.
IFC.js viz
Since Jupyter Notebooks run in the browser, it is possible to use IFC.js to visualize our IFC model in real time, which altogether with the mentioned garbage collection, really allows for a truly interactive session. In the notebook, the file is parsed as a string with IfcOpenShell, and then retrieved from the Python session with JavaScript, allowing for a smooth all-in-memory workflow, not requiring to save and read from disk as an intermediate step.
Some issues I was having is the current version of web-ifc-three not reading IFC4x3 (although it seems that this will change soon), and also web-ifc-three not showing transparency, at least for styles directly assigned to representations. This was worked around by some custom code for traversing the IFC entities in order to check for transparent styles.
Summary
So now, there are some open questions, some obscure sorcery with non-standard library aliases, Python audit hooks... so I guess there is still some room for changes. @aothms I'll be happy to link it to the academy repo when you judge it's ready (beware that as I pointed out, at the moment the code has 10 questions inside the comments).
That was all for now! thank you for reading this authentic IfcSlab ?