black ifcopenshell-python

This commit is contained in:
htlcnn
2020-11-01 20:08:27 +07:00
committed by Dion Moult
parent 2c9d6a47f4
commit 286c77e3b0
27 changed files with 1502 additions and 979 deletions
@@ -3,65 +3,67 @@ import ifcopenshell.util.element
import lark
cobie_type_assets = [
'IfcDoorStyle',
'IfcBuildingElementProxyType',
'IfcChimneyType',
'IfcCoveringType',
'IfcDoorType',
'IfcFootingType',
'IfcPileType',
'IfcRoofType',
'IfcShadingDeviceType',
'IfcWindowType',
'IfcDistributionControlElementType',
'IfcDistributionChamberElementType',
'IfcEnergyConversionDeviceType',
'IfcFlowControllerType',
'IfcFlowMovingDeviceType',
'IfcFlowStorageDeviceType',
'IfcFlowTerminalType',
'IfcFlowTreatmentDeviceType',
'IfcElementAssemblyType',
'IfcBuildingElementPartType',
'IfcDiscreteAccessoryType',
'IfcMechanicalFastenerType',
'IfcReinforcingElementType',
'IfcVibrationIsolatorType',
'IfcFurnishingElementType',
'IfcGeographicElementType',
'IfcTransportElementType',
'IfcSpatialZoneType',
'IfcWindowStyle',
"IfcDoorStyle",
"IfcBuildingElementProxyType",
"IfcChimneyType",
"IfcCoveringType",
"IfcDoorType",
"IfcFootingType",
"IfcPileType",
"IfcRoofType",
"IfcShadingDeviceType",
"IfcWindowType",
"IfcDistributionControlElementType",
"IfcDistributionChamberElementType",
"IfcEnergyConversionDeviceType",
"IfcFlowControllerType",
"IfcFlowMovingDeviceType",
"IfcFlowStorageDeviceType",
"IfcFlowTerminalType",
"IfcFlowTreatmentDeviceType",
"IfcElementAssemblyType",
"IfcBuildingElementPartType",
"IfcDiscreteAccessoryType",
"IfcMechanicalFastenerType",
"IfcReinforcingElementType",
"IfcVibrationIsolatorType",
"IfcFurnishingElementType",
"IfcGeographicElementType",
"IfcTransportElementType",
"IfcSpatialZoneType",
"IfcWindowStyle",
]
cobie_component_assets = [
'IfcBuildingElementProxy',
'IfcChimney',
'IfcCovering',
'IfcDoor',
'IfcShadingDevice',
'IfcWindow',
'IfcDistributionControlElement',
'IfcDistributionChamberElement',
'IfcEnergyConversionDevice',
'IfcFlowController',
'IfcFlowMovingDevice',
'IfcFlowStorageDevice',
'IfcFlowTerminal',
'IfcFlowTreatmentDevice',
'IfcDiscreteAccessory',
'IfcTendon',
'IfcTendonAnchor',
'IfcVibrationIsolator',
'IfcFurnishingElement',
'IfcGeographicElement',
'IfcTransportElement',
"IfcBuildingElementProxy",
"IfcChimney",
"IfcCovering",
"IfcDoor",
"IfcShadingDevice",
"IfcWindow",
"IfcDistributionControlElement",
"IfcDistributionChamberElement",
"IfcEnergyConversionDevice",
"IfcFlowController",
"IfcFlowMovingDevice",
"IfcFlowStorageDevice",
"IfcFlowTerminal",
"IfcFlowTreatmentDevice",
"IfcDiscreteAccessory",
"IfcTendon",
"IfcTendonAnchor",
"IfcVibrationIsolator",
"IfcFurnishingElement",
"IfcGeographicElement",
"IfcTransportElement",
]
class Selector():
class Selector:
def parse(self, ifc_file, query):
self.file = ifc_file
l = lark.Lark('''start: query (lfunction query)*
l = lark.Lark(
"""start: query (lfunction query)*
query: selector | group
group: "(" query (lfunction query)* ")"
selector: (inverse_relationship)? guid_selector | (inverse_relationship)? class_selector
@@ -111,7 +113,8 @@ class Selector():
NEWLINE: (CR? LF)+
%ignore WS // Disregard spaces in text
''')
"""
)
start = l.parse(query)
return self.get_group(start)
@@ -119,24 +122,24 @@ class Selector():
def get_group(self, group):
lfunction = None
for child in group.children:
if child.data == 'query':
if child.data == "query":
new_results = self.get_query(child)
if not lfunction:
results = new_results
elif lfunction == 'or':
elif lfunction == "or":
results.extend(new_results)
elif lfunction == 'and':
elif lfunction == "and":
results = list(set(results).intersection(new_results))
results = list(set(results))
elif child.data == 'lfunction':
elif child.data == "lfunction":
lfunction = child.children[0].data
return results
def get_query(self, query):
for child in query.children:
if child.data == 'selector':
if child.data == "selector":
return self.get_selector(child)
elif child.data == 'group':
elif child.data == "group":
return self.get_group(child)
def get_selector(self, selector):
@@ -147,9 +150,9 @@ class Selector():
inverse_relationship = selector.children[0]
class_or_guid_selector = selector.children[1]
if class_or_guid_selector.data == 'class_selector':
if class_or_guid_selector.data == "class_selector":
results = self.get_class_selector(class_or_guid_selector)
elif class_or_guid_selector.data == 'guid_selector':
elif class_or_guid_selector.data == "guid_selector":
results = self.get_guid_selector(class_or_guid_selector)
if not inverse_relationship:
@@ -159,26 +162,25 @@ class Selector():
def parse_inverse_relationship(self, elements, inverse_relationship):
results = []
for element in elements:
if inverse_relationship == 'types':
if hasattr(element, 'Types') and element.Types:
if inverse_relationship == "types":
if hasattr(element, "Types") and element.Types:
results.extend(element.Types[0].RelatedObjects)
elif hasattr(element, 'ObjectTypeOf') and element.ObjectTypeOf:
elif hasattr(element, "ObjectTypeOf") and element.ObjectTypeOf:
results.extend(element.ObjectTypeOf[0].RelatedObjects)
elif inverse_relationship == 'contains_elements' \
and hasattr(element, 'ContainsElements'):
elif inverse_relationship == "contains_elements" and hasattr(element, "ContainsElements"):
for relationship in element.ContainsElements:
results.extend(relationship.RelatedElements)
return results
def get_class_selector(self, class_selector):
if class_selector.children[0] == 'COBie':
if class_selector.children[0] == "COBie":
elements = []
for ifc_class in cobie_component_assets:
try:
elements += self.file.by_type(ifc_class)
except:
pass
elif class_selector.children[0] == 'COBieType':
elif class_selector.children[0] == "COBieType":
elements = []
for ifc_class in cobie_type_assets:
try:
@@ -187,8 +189,7 @@ class Selector():
pass
else:
elements = self.file.by_type(class_selector.children[0])
if len(class_selector.children) > 1 \
and class_selector.children[1].data == 'filter':
if len(class_selector.children) > 1 and class_selector.children[1].data == "filter":
return self.filter_elements(elements, class_selector.children[1])
return elements
@@ -196,7 +197,7 @@ class Selector():
results = []
key = filter_rule.children[0].children[0]
if not isinstance(key, str):
key = key.children[0] + '.' + key.children[1]
key = key.children[0] + "." + key.children[1]
comparison = value = None
if len(filter_rule.children) > 1:
comparison = filter_rule.children[1].children[0].data
@@ -205,42 +206,40 @@ class Selector():
element_value = self.get_element_value(element, key)
if not element_value:
continue
if not comparison \
or self.filter_element(element, element_value, comparison, value):
if not comparison or self.filter_element(element, element_value, comparison, value):
results.append(element)
return results
def get_element_value(self, element, key):
if '.' in key \
and key.split('.')[0] == 'type':
if "." in key and key.split(".")[0] == "type":
try:
element = ifcopenshell.util.element.get_type(element)
if not element:
return None
except:
return
key = '.'.join(key.split('.')[1:])
key = ".".join(key.split(".")[1:])
info = element.get_info()
if key in info:
return info[key]
elif '.' in key:
pset_name, prop = key.split('.')
elif "." in key:
pset_name, prop = key.split(".")
psets = ifcopenshell.util.element.get_psets(element)
if pset_name in psets and prop in psets[pset_name]:
return psets[pset_name][prop]
def filter_element(self, element, element_value, comparison, value):
if comparison == 'equal':
if comparison == "equal":
return str(element_value) == value
elif comparison == 'contains':
elif comparison == "contains":
return value in str(element_value)
elif comparison == 'morethan':
elif comparison == "morethan":
return element_value > float(value)
elif comparison == 'lessthan':
elif comparison == "lessthan":
return element_value < float(value)
elif comparison == 'morethanequalto':
elif comparison == "morethanequalto":
return element_value >= float(value)
elif comparison == 'lessthanequalto':
elif comparison == "lessthanequalto":
return element_value <= float(value)
return False