Don't hardcode unit definitions

This commit is contained in:
Dion Moult
2019-09-10 17:08:45 +10:00
parent dd1ddfcd8e
commit 2c84a07bdc
2 changed files with 45 additions and 17 deletions
+45 -10
View File
@@ -92,6 +92,7 @@ class IfcParser():
self.product_index = 0 self.product_index = 0
self.units = {}
self.psets = {} self.psets = {}
self.qtos = {} self.qtos = {}
self.aggregates = {} self.aggregates = {}
@@ -110,6 +111,7 @@ class IfcParser():
self.products = [] self.products = []
def parse(self): def parse(self):
self.units = self.get_units()
self.convert_selected_objects_into_products(bpy.context.selected_objects) self.convert_selected_objects_into_products(bpy.context.selected_objects)
self.psets = self.get_psets() self.psets = self.get_psets()
self.representations = self.get_representations() self.representations = self.get_representations()
@@ -128,6 +130,24 @@ class IfcParser():
self.spatial_structure_elements_tree = self.get_spatial_structure_elements_tree( self.spatial_structure_elements_tree = self.get_spatial_structure_elements_tree(
self.project['raw'].children, self.collection_name_filter) self.project['raw'].children, self.collection_name_filter)
def get_units(self):
return {
'length': {
'ifc': None,
'is_metric': bpy.context.scene.unit_settings.system == 'METRIC',
'raw': bpy.context.scene.unit_settings.length_unit
},
'area': {
'ifc': None,
'is_metric': bpy.context.scene.unit_settings.system == 'METRIC',
'raw': bpy.context.scene.unit_settings.length_unit
},
'volume': {
'ifc': None,
'is_metric': bpy.context.scene.unit_settings.system == 'METRIC',
'raw': bpy.context.scene.unit_settings.length_unit
}}
def get_object_attributes(self, object): def get_object_attributes(self, object):
attributes = { 'Name': self.get_ifc_name(object.name) } attributes = { 'Name': self.get_ifc_name(object.name) }
if 'IfcGlobalId' not in object: if 'IfcGlobalId' not in object:
@@ -489,7 +509,7 @@ class SIUnitHelper:
@staticmethod @staticmethod
def get_unit_name(text): def get_unit_name(text):
for name in SIUnitHelper.unit_names: for name in SIUnitHelper.unit_names:
if name in text.upper(): if name in text.upper().replace('METER', 'METRE'):
return name return name
class IfcExporter(): class IfcExporter():
@@ -505,6 +525,7 @@ class IfcExporter():
self.file = ifcopenshell.open(self.template_file) self.file = ifcopenshell.open(self.template_file)
self.set_common_definitions() self.set_common_definitions()
self.ifc_parser.parse() self.ifc_parser.parse()
self.create_units()
self.create_psets() self.create_psets()
self.create_rep_context() self.create_rep_context()
self.create_project() self.create_project()
@@ -526,14 +547,28 @@ class IfcExporter():
self.file.write(self.output_file) self.file.write(self.output_file)
def set_common_definitions(self): def set_common_definitions(self):
self.origin = self.file.by_type('IfcAxis2Placement3D')[0]
# Owner history doesn't actually work like this, but for now, it does :) # Owner history doesn't actually work like this, but for now, it does :)
self.origin = self.file.by_type('IfcAxis2Placement3D')[0]
def create_units(self):
self.owner_history = self.file.by_type('IfcOwnerHistory')[0] self.owner_history = self.file.by_type('IfcOwnerHistory')[0]
# TODO: unhardcode units for type, data in self.ifc_parser.units.items():
units = self.file.by_type('IfcSIUnit') if data['is_metric']:
self.length_unit = units[0] type_prefix = ''
self.area_unit = units[1] if type == 'area':
self.volume_unit = units[2] type_prefix = 'SQUARE_'
elif type == 'volume':
type_prefix = 'CUBIC_'
data['ifc'] = self.file.createIfcSIUnit(None,
'{}UNIT'.format(type.upper()),
SIUnitHelper.get_prefix(data['raw']),
type_prefix + SIUnitHelper.get_unit_name(data['raw']))
else:
self.create_imperial_unit(type, data)
self.file.createIfcUnitAssignment([u['ifc'] for u in self.ifc_parser.units.values()])
def create_imperial_unit(self, type, data):
pass # TODO
def create_psets(self): def create_psets(self):
for pset in self.ifc_parser.psets.values(): for pset in self.ifc_parser.psets.values():
@@ -767,17 +802,17 @@ class IfcExporter():
quantity = float(self.qto_calculator.get_length(object, index)) quantity = float(self.qto_calculator.get_length(object, index))
quantities.append(self.file.createIfcQuantityLength( quantities.append(self.file.createIfcQuantityLength(
vg.name.split('/')[1], None, vg.name.split('/')[1], None,
self.length_unit, quantity)) self.ifc_parser.units['length']['ifc'], quantity))
elif 'area' in vg.name.lower(): elif 'area' in vg.name.lower():
quantity = float(self.qto_calculator.get_area(object, index)) quantity = float(self.qto_calculator.get_area(object, index))
quantities.append(self.file.createIfcQuantityArea( quantities.append(self.file.createIfcQuantityArea(
vg.name.split('/')[1], None, vg.name.split('/')[1], None,
self.area_unit, quantity)) self.ifc_parser.units['area']['ifc'], quantity))
elif 'volume' in vg.name.lower(): elif 'volume' in vg.name.lower():
quantity = float(self.qto_calculator.get_volume(object, index)) quantity = float(self.qto_calculator.get_volume(object, index))
quantities.append(self.file.createIfcQuantityVolume( quantities.append(self.file.createIfcQuantityVolume(
vg.name.split('/')[1], None, vg.name.split('/')[1], None,
self.volume_unit, quantity)) self.ifc_parser.units['volume']['ifc'], quantity))
if not quantity: if not quantity:
print('Warning: the calculated quantity {} for {} is zero.'.format( print('Warning: the calculated quantity {} for {} is zero.'.format(
vg.name, object.name)) vg.name, object.name))
-7
View File
@@ -16,12 +16,5 @@ DATA;
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6); #9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
#10=IFCDIRECTION((0.,1.,0.)); #10=IFCDIRECTION((0.,1.,0.));
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0); #12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
ENDSEC; ENDSEC;
END-ISO-10303-21; END-ISO-10303-21;