Werden für Projekte und Bestandsdokumentation digitale Methoden angewandt, gibt es zwei Optionen für den Datenaustausch. Der openBIM Ansatz kennzeichnet sich durch einen offenen, softwareunabhängigen Datenaustausch. Der closedBIM Ansatz, auch natives BIM genannt, bezieht sich meist auf die Nutzung von Softwarefamilien bzw. abgestimmten Herstellerformaten.
Da für öffentliche Planungs- und Bauprojekte vorwiegend openBIM Ansätze gewählt werden, möchte ich im Weiteren auf das bekannteste, quelloffene Format in der digitalen Arbeitsweise eingehen. Wie der Titel bereits erwähnt handelt es sich um das Industrial Foundation Format (kurz IFC). Es kann verwendet werden um Bauwerke und deren Bauteile eindeutig zu beschreiben. Dabei werden alle Elemente eines Projektes über deren geometrische Ausprägung und Eigenschaften definiert.
Autorenprogramme können ihre Inhalte in dieses Format exportieren. Aber was macht man, wenn das Programm nicht so arbeitet, wie man es sich wünscht?
Meine Antwort: Einfach einmal selber versuchen einen IFC Exporter zu bauen oder die IFC Dateien im Nachgang eigenständig zu ergänzen.
Was braucht man dazu?
Grundsätzlich ist die Kenntnis einer Programmiersprache (wie z.B. Python) und etwas Geduld sehr hilfreich. Dafür möchte ich nun an einem kurzen Beispiel zeigen, wie so etwas gehen könnte. Den kompletten Quellcode für diesen Blogeintrag kann man sich auf GitHub anschauen (groundworker/IFC-Art: modeling art (github.com)). Für das Beispiel zeige ich lediglich einige Ausschnitte.
Zunächst wird eine leere ASCII-Datei erstellt, in die alle IFC-Befehle im STEP Format geschrieben werden.
file_out = open("IFC_Datei_Erstellen.ifc", "w")
Anschließend können die notwendigen IFC-Befehle erstellt werden. Da das IFC-Format in der Art und Weise, wie die Datei aufgebaut ist nur sehr wenige Hierarchieebenen besitzt, können die Befehle einfach untereinander geschrieben werden. Es entsteht somit eine sehr lange Liste mit Befehlseingaben. Die IFC-Befehle sind durch interne Referenzen miteinander verbunden.
Zunächst fange ich an die Kopfdaten der Datei zu schreiben. Diese befinden sich im „HEADER“ und definieren allgemeine Dinge, wie z.B. das IFC-Format oder die Model-View-Definition.
file_out.write("HEADER;\n")
file_out.write("FILE_DESCRIPTION(('ViewDefinition [CoordinationView_V2.0]'),'2;1');\n")
file_out.write("FILE_NAME('Modellname','"+str(time.strftime("%Y-%m-%dT%H:%M:%S",time.localtime()))+"',('Autor'),(''),'','','');\n")
file_out.write("FILE_SCHEMA(('IFC2X3'));\n")
file_out.write("ENDSEC;\n")
Weiter geht dann mit den eigentlichen Modelldaten. Diese sind im zweiten Teil der Datei, dem „DATA“, zu finden. Zunächst beginne ich die allgemeinen Projektdaten (Modellautor, Organisation und Software) und ersten Ebenen (Projekt, Fläche und Bauwerk) zu erstellen.
file_out.write("DATA;\n")
file_out.write("#100= IFCPROJECT('"+GUID +"',#110,'Projekt',$,$,$,$,(#201),#301);\n")
file_out.write("#110= IFCOWNERHISTORY(#111,#115,$,.NOCHANGE.,$,$,$,$);\n")
file_out.write("#111= IFCPERSONANDORGANIZATION(#112,#113,$);\n")
file_out.write("#112= IFCPERSON($,'Modellierer',$,$,$,$,$,$);\n")
file_out.write("#113= IFCORGANIZATION($,'Art@IFC',$,$,$);\n")
file_out.write("#115= IFCAPPLICATION(#113,'0.3','Skript',$);\n")
file_out.write("#116= IFCSITE('"+GUID+"',$,'IFC-ART',$,$,#118,$,$,.ELEMENT.,(0,0,0,0),(0,0,0,0),0.,$,$);\n")
file_out.write("#117= IFCRELAGGREGATES('"+GUID+"',$,$,$,#100,(#116));\n")
file_out.write("#118= IFCLOCALPLACEMENT($,#120);\n")
file_out.write("#119= IFCCARTESIANPOINT((0.,0.,0.));\n")
file_out.write("#120= IFCAXIS2PLACEMENT3D(#119,$,$);\n")
file_out.write("#201= IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.0E-5,#210,$);\n")
file_out.write("#202= IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#201,$,.MODEL_VIEW.,$);\n")
file_out.write("#210= IFCAXIS2PLACEMENT3D(#901,$,$);\n")
Im nächsten Block werden noch die notwendigen Einheiten für z.B. Längen und Winkel definiert.
file_out.write("#301= IFCUNITASSIGNMENT((#311,#312));\n")
file_out.write("#311= IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);\n")
file_out.write("#312= IFCCONVERSIONBASEDUNIT(#313,.PLANEANGLEUNIT.,'degree',#314);\n")
file_out.write("#313= IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);\n")
file_out.write("#314= IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453293),#315);\n")
file_out.write("#315= IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);\n")
Ein weiterer Block erstellt das Bauwerk sowie zwei Ebenen als Datenobjekt und verknüpft diese miteinander.
file_out.write("#500= IFCBUILDING('"+GUID+"',$,'Modell',$,$,#118,$,$,.ELEMENT.,$,$,$);\n")
file_out.write("#519= IFCRELAGGREGATES('"+GUID+"',$,$,$,#116,(#500));\n")
file_out.write("#520= IFCBUILDINGSTOREY('"+GUID+"',#110,'Ebene 1',$,'Ebene:Ebene',#118,$,'Ebene 1',.ELEMENT.,.0);\n")
file_out.write("#521= IFCBUILDINGSTOREY('"+GUID+"',#110,'Ebene 2',$,'Ebene:Ebene',#118,$,'Ebene 2',.ELEMENT.,.0);\n")
file_out.write("#530= IFCRELAGGREGATES('"+GUID+"',#110,$,$,#500,(#520));\n")
file_out.write("#531= IFCRELAGGREGATES('"+GUID+"',#110,$,$,#500,(#521));\n")
Am Ende des ersten Abschnittes wird noch der Bezugsraum auf Basis von Vektoren definiert. Er gibt an, wie sich die Raumachsen (x,y,z) im Projekt verhalten und wo der Projektbezugspunkt zu finden ist. In meinem IFC-Export verweisen fast alle Bezugssysteme der Elemente auf diese Vektoren.
file_out.write("#901= IFCCARTESIANPOINT((0.,0.,0.));\n")
file_out.write("#902= IFCDIRECTION((1.,0.,0.));\n")
file_out.write("#903= IFCDIRECTION((0.,1.,0.));\n")
file_out.write("#904= IFCDIRECTION((0.,0.,1.));\n")
file_out.write("#905= IFCDIRECTION((-1.,0.,0.));\n")
file_out.write("#906= IFCDIRECTION((0.,-1.,0.));\n")
file_out.write("#907= IFCDIRECTION((0.,0.,-1.));\n")
Im nächsten Abschnitt möchte ich nun die eigentlichen Objekte erzeugen, dazu definiere ich ein IFCELEMENT (hier als IFCBUILDINGELEMENTPROXY) und weise ihm einen Raumbezug sowie eine Geometriedefinition zu.
file_out.write("#1000= IFCBUILDINGELEMENTPROXY('"+GUID+"',4,'"ID"','Cylinder Extrusion',$,#1001,#1010,$,$);\n")
file_out.write("#1001= IFCLOCALPLACEMENT($,#1002);\n")
file_out.write("#1002= IFCAXIS2PLACEMENT3D(#1003,$,$);\n")
file_out.write("#1003= IFCCARTESIANPOINT((0.0,0.0,0.0));\n")
file_out.write("#1010= IFCPRODUCTDEFINITIONSHAPE($,$,(#1030));\n")
file_out.write("#1011= IFCRELCONTAINEDINSPATIALSTRUCTURE('"+GUID+"',$,'Physical model',$,(#1000),#520);\n")
Der nächste Schritt ist die Definition der Geometrie. Diese wird als Extrusion unter Verwendung einer kreisförmigen Grundfläche definiert. Die Beschreibung zu den einzelnen IFC-Befehlen findet sich in der Dokumentation von buildingSMART (Extrusionskörper: IfcExtrudedAreaSolid (buildingsmart.org)).
file_out.write("#1030= IFCSHAPEREPRESENTATION(#202,'Body','SweptSolid',(#1031));\n")
file_out.write("#1031= IFCEXTRUDEDAREASOLID(#1032,#1035,#907,5.0);\n")
file_out.write("#1032= IFCCIRCLEPROFILEDEF(.AREA.,$,$,5.0);\n")
file_out.write("#1034= IFCRELCONTAINEDINSPATIALSTRUCTURE('"+GUID+"',$,'Physical model',$,(#1000),#520);\n")
file_out.write("#1035= IFCAXIS2PLACEMENT3D(#1036,$,$);\n")
file_out.write("#1036= IFCCARTESIANPOINT(("+RW+","+HW+","+Z+"));\n")
Neben der Gemetrie kann auch die Semantik der Elemente noch über die Grundmerkmale hinaus erweitert werden. Dazu werden Eigenschaftssätze („Proberty Sets“) mit Merkmalen (z.B. „Property Singe Value“) verwendet. In diesem Beispiel wird dem einfachen Merkmal „_Nummer“ eine fortlaufende Nummer als Freitext zugeordnet. Das Merkmal wird in den Eigenschaftssatz „Semantik“ zugeordnet.
file_out.write("#1040= IFCPROPERTYSET('"+GUID+"',$,'Semantik',$,(#1041));\n")
file_out.write("#1041= IFCPROPERTYSINGLEVALUE('_Nummer',$,IFCLABEL('"+FortlaufendeNummer+"'),$);\n")
file_out.write("#1050= IFCRELDEFINESBYPROPERTIES('"+GUID+"',$,$,$,(#1000),#1040);\n")
Für ein Layout, z.B. in Form von einer farblichen Oberfläche, können auch Stile mit RGB-Farben vergeben werden.
file_out.write("#1055= IFCCOLOURRGB($,"+R_Wert+","+G_Wert+","+B_Wert+");\n")
file_out.write("#1056= IFCSURFACESTYLERENDERING(#1055,$,$,$,$,$,$,$,.FLAT.);\n")
file_out.write("#1057= IFCSURFACESTYLE($,.BOTH.,(#1056));\n")
file_out.write("#1058= IFCPRESENTATIONSTYLEASSIGNMENT((#1057));\n")
file_out.write("#1059= IFCSTYLEDITEM(#1031,(#1058),$);\n")

Wenn man nicht nur ein Element erzeugt, sondern eine ganze Reihe von Elementen, deren Koordinaten sich entlang einer räumlichen Kurve bewegen, kann man auch eine Form von generischen Modellen erzeugen.

Ein Tipp zum Schluss: Für die Erstellung und Kontrolle von IFC-Dateien mit eigenen Skripten eignet sich „Solibri Anywhere“ aktuell am besten, da bei Problemen geeignete Fehlermeldungen erzeugt werden, die auf die jeweiligen Stellen in der Datei verweisen. Alternativ ist auch der „FZK Viewer“ des Institut für Automation und angewandte Informatik des KIT zu empfehlen.