88import lark
99import argparse
1010
11- class IfcAttributeExtractor ():
11+
12+ class IfcAttributeExtractor :
1213 @staticmethod
1314 def set_element_key (ifc_file , element , key , value ):
14- if key == ' type' and element .is_a () != value :
15+ if key == " type" and element .is_a () != value :
1516 return IfcAttributeExtractor .change_ifc_class (ifc_file , element , value )
1617 if hasattr (element , key ):
1718 setattr (element , key , value )
1819 return element
19- if '.' not in key :
20+ if "." not in key :
2021 return element
21- if key [0 :3 ] == ' Qto' :
22- qto , prop = key .split ('.' , 1 )
22+ if key [0 :3 ] == " Qto" :
23+ qto , prop = key .split ("." , 1 )
2324 qto = IfcAttributeExtractor .get_element_qto (element , qto_name )
2425 if qto :
2526 IfcAttributeExtractor .set_qto_property (qto , prop , value )
2627 return element
27- pset_name , prop = key .split ('.' , 1 )
28+ pset_name , prop = key .split ("." , 1 )
2829 pset = IfcAttributeExtractor .get_element_pset (element , pset_name )
2930 if pset :
3031 IfcAttributeExtractor .set_pset_property (pset , prop , value )
@@ -51,31 +52,34 @@ def change_ifc_class(ifc_file, element, new_class):
5152 @staticmethod
5253 def get_element_qto (element , name ):
5354 for relationship in element .IsDefinedBy :
54- if relationship .is_a ('IfcRelDefinesByProperties' ) \
55- and relationship .RelatingPropertyDefinition .is_a ('IfcElementQuantity' ) \
56- and relationship .RelatingPropertyDefinition .Name == name :
55+ if (
56+ relationship .is_a ("IfcRelDefinesByProperties" )
57+ and relationship .RelatingPropertyDefinition .is_a ("IfcElementQuantity" )
58+ and relationship .RelatingPropertyDefinition .Name == name
59+ ):
5760 return relationship .RelatingPropertyDefinition
5861
5962 @staticmethod
6063 def set_qto_property (qto , name , value ):
6164 for prop in qto .Quantities :
6265 if prop .Name != name :
6366 continue
64- setattr (prop , prop .is_a ()[len (' IfcQuantity' ) :] + ' Value' , value )
67+ setattr (prop , prop .is_a ()[len (" IfcQuantity" ) :] + " Value" , value )
6568
6669 @staticmethod
6770 def get_element_pset (element , name ):
68- if element .is_a (' IfcTypeObject' ):
71+ if element .is_a (" IfcTypeObject" ):
6972 if element .HasPropertySets :
7073 for pset in element .HasPropertySets :
71- if pset .is_a ('IfcPropertySet' ) \
72- and pset .Name == name :
74+ if pset .is_a ("IfcPropertySet" ) and pset .Name == name :
7375 return pset
7476 else :
7577 for relationship in element .IsDefinedBy :
76- if relationship .is_a ('IfcRelDefinesByProperties' ) \
77- and relationship .RelatingPropertyDefinition .is_a ('IfcPropertySet' ) \
78- and relationship .RelatingPropertyDefinition .Name == name :
78+ if (
79+ relationship .is_a ("IfcRelDefinesByProperties" )
80+ and relationship .RelatingPropertyDefinition .is_a ("IfcPropertySet" )
81+ and relationship .RelatingPropertyDefinition .Name == name
82+ ):
7983 return relationship .RelatingPropertyDefinition
8084
8185 @staticmethod
@@ -93,57 +97,59 @@ def set_pset_property(pset, name, value):
9397 try :
9498 property .NominalValue .wrappedValue = int (value )
9599 except :
96- property .NominalValue .wrappedValue = True if value .lower () in ['1' , 't' , 'true' , 'yes' , 'y' , 'uh-huh' ] else False
100+ property .NominalValue .wrappedValue = (
101+ True if value .lower () in ["1" , "t" , "true" , "yes" , "y" , "uh-huh" ] else False
102+ )
97103
98104
99- class IfcCsv () :
105+ class IfcCsv :
100106 def __init__ (self ):
101107 self .results = []
102108 self .attributes = []
103- self .output = ''
109+ self .output = ""
104110 self .selector = None
105111
106112 def export (self , ifc_file , elements ):
107113 self .ifc_file = ifc_file
108114 for element in elements :
109115 result = []
110- if hasattr (element , ' GlobalId' ):
116+ if hasattr (element , " GlobalId" ):
111117 result .append (element .GlobalId )
112118 else :
113119 result .append (None )
114120
115121 for index , attribute in enumerate (self .attributes ):
116- if '*' in attribute :
122+ if "*" in attribute :
117123 self .attributes .extend (self .get_wildcard_attributes (attribute ))
118- del ( self .attributes [index ])
124+ del self .attributes [index ]
119125
120126 for attribute in self .attributes :
121127 result .append (self .selector .get_element_value (element , attribute ))
122128 self .results .append (result )
123129
124- with open (self .output , 'w' , newline = '' , encoding = ' utf-8' ) as f :
130+ with open (self .output , "w" , newline = "" , encoding = " utf-8" ) as f :
125131 writer = csv .writer (f )
126- header = [' GlobalId' ]
132+ header = [" GlobalId" ]
127133 header .extend (self .attributes )
128134 writer .writerow (header )
129135 for row in self .results :
130136 writer .writerow (row )
131137
132138 def get_wildcard_attributes (self , attribute ):
133139 results = set ()
134- pset_qto_name = attribute .split ('.' , 1 )[0 ]
135- for element in self .ifc_file .by_type (' IfcPropertySet' ) + self .ifc_file .by_type (' IfcElementQuantity' ):
140+ pset_qto_name = attribute .split ("." , 1 )[0 ]
141+ for element in self .ifc_file .by_type (" IfcPropertySet" ) + self .ifc_file .by_type (" IfcElementQuantity" ):
136142 if element .Name != pset_qto_name :
137143 continue
138- if element .is_a (' IfcPropertySet' ):
144+ if element .is_a (" IfcPropertySet" ):
139145 results .update ([p .Name for p in element .HasProperties ])
140146 else :
141147 results .update ([p .Name for p in element .Quantities ])
142- return [' {}.{}' .format (pset_qto_name , n ) for n in results ]
148+ return [" {}.{}" .format (pset_qto_name , n ) for n in results ]
143149
144150 def Import (self , ifc ):
145151 ifc_file = ifcopenshell .open (ifc )
146- with open (self .output , newline = '' , encoding = ' utf-8' ) as f :
152+ with open (self .output , newline = "" , encoding = " utf-8" ) as f :
147153 reader = csv .reader (f )
148154 headers = []
149155 for row in reader :
@@ -155,44 +161,19 @@ def Import(self, ifc):
155161 continue
156162 for i , value in enumerate (row ):
157163 if i == 0 :
158- continue # Skip GlobalId
164+ continue # Skip GlobalId
159165 element = IfcAttributeExtractor .set_element_key (ifc_file , element , headers [i ], value )
160166 ifc_file .write (ifc )
161167
162- if __name__ == '__main__' :
163- parser = argparse .ArgumentParser (
164- description = 'Exports IFC data to and from CSV' )
165- parser .add_argument (
166- '-i' ,
167- '--ifc' ,
168- type = str ,
169- required = True ,
170- help = 'The IFC file' )
171- parser .add_argument (
172- '-c' ,
173- '--csv' ,
174- type = str ,
175- default = 'data.csv' ,
176- help = 'The CSV file to import from or export to' )
177- parser .add_argument (
178- '-q' ,
179- '--query' ,
180- type = str ,
181- default = '' ,
182- help = 'Specify a IFC query selector, such as ".IfcWall"' )
183- parser .add_argument (
184- '-a' ,
185- '--arguments' ,
186- nargs = '+' ,
187- help = 'Specify attributes that are part of the extract' )
188- parser .add_argument (
189- '--export' ,
190- action = 'store_true' ,
191- help = 'Export from IFC to CSV' )
192- parser .add_argument (
193- '--import' ,
194- action = 'store_true' ,
195- help = 'Import from CSV to IFC' )
168+
169+ if __name__ == "__main__" :
170+ parser = argparse .ArgumentParser (description = "Exports IFC data to and from CSV" )
171+ parser .add_argument ("-i" , "--ifc" , type = str , required = True , help = "The IFC file" )
172+ parser .add_argument ("-c" , "--csv" , type = str , default = "data.csv" , help = "The CSV file to import from or export to" )
173+ parser .add_argument ("-q" , "--query" , type = str , default = "" , help = 'Specify a IFC query selector, such as ".IfcWall"' )
174+ parser .add_argument ("-a" , "--arguments" , nargs = "+" , help = "Specify attributes that are part of the extract" )
175+ parser .add_argument ("--export" , action = "store_true" , help = "Export from IFC to CSV" )
176+ parser .add_argument ("--import" , action = "store_true" , help = "Import from CSV to IFC" )
196177 args = parser .parse_args ()
197178
198179 if args .export :
@@ -204,7 +185,7 @@ def Import(self, ifc):
204185 ifc_csv .attributes = args .arguments if args .arguments else []
205186 ifc_csv .selector = selector
206187 ifc_csv .export (ifc_file , results )
207- elif getattr (args , ' import' ):
188+ elif getattr (args , " import" ):
208189 ifc_csv = IfcCsv ()
209190 ifc_csv .output = args .csv
210191 ifc_csv .Import (args .ifc )
0 commit comments