From 8b7850b3ff9efd1354da71ec8a23b44b9d6db5e4 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Thu, 11 Jun 2020 15:15:54 +1000 Subject: [PATCH] New IFC Patch recipe to split an IFC by building storey --- src/ifcpatch/ifcpatch.py | 2 +- .../recipes/OffsetObjectPlacements.py | 3 +- .../recipes/OffsetStoreyElevations.py | 3 +- .../recipes/RemoveSiteRepresentation.py | 3 +- .../recipes/ResetAbsoluteCoordinates.py | 3 +- .../recipes/ResetSpatialElementLocations.py | 3 +- src/ifcpatch/recipes/SetRefElevation.py | 3 +- src/ifcpatch/recipes/SplitByBuildingStorey.py | 42 +++++++++++++++++++ 8 files changed, 55 insertions(+), 7 deletions(-) create mode 100644 src/ifcpatch/recipes/SplitByBuildingStorey.py diff --git a/src/ifcpatch/ifcpatch.py b/src/ifcpatch/ifcpatch.py index 8947cd222b..8668e13046 100644 --- a/src/ifcpatch/ifcpatch.py +++ b/src/ifcpatch/ifcpatch.py @@ -12,7 +12,7 @@ def execute(args): ifc_file = ifcopenshell.open(args.input) print('# Loading patch recipe ...') patcher = getattr(__import__(f'recipes.{args.recipe}'), args.recipe).Patcher( - ifc_file, logger, args.arguments) + args.input, ifc_file, logger, args.arguments) print('# Patching ...') patcher.patch() print('# Writing patched file ...') diff --git a/src/ifcpatch/recipes/OffsetObjectPlacements.py b/src/ifcpatch/recipes/OffsetObjectPlacements.py index 697c9d2e4d..d9da46c79a 100644 --- a/src/ifcpatch/recipes/OffsetObjectPlacements.py +++ b/src/ifcpatch/recipes/OffsetObjectPlacements.py @@ -1,7 +1,8 @@ import math class Patcher: - def __init__(self, file, logger, args=None): + def __init__(self, src, file, logger, args=None): + self.src = src self.file = file self.logger = logger self.args = args diff --git a/src/ifcpatch/recipes/OffsetStoreyElevations.py b/src/ifcpatch/recipes/OffsetStoreyElevations.py index 356247942f..c0384693c3 100644 --- a/src/ifcpatch/recipes/OffsetStoreyElevations.py +++ b/src/ifcpatch/recipes/OffsetStoreyElevations.py @@ -1,5 +1,6 @@ class Patcher: - def __init__(self, file, logger, args=None): + def __init__(self, src, file, logger, args=None): + self.src = src self.file = file self.logger = logger self.args = args diff --git a/src/ifcpatch/recipes/RemoveSiteRepresentation.py b/src/ifcpatch/recipes/RemoveSiteRepresentation.py index b8a56dad3b..347cddce17 100644 --- a/src/ifcpatch/recipes/RemoveSiteRepresentation.py +++ b/src/ifcpatch/recipes/RemoveSiteRepresentation.py @@ -1,5 +1,6 @@ class Patcher: - def __init__(self, file, logger, args=None): + def __init__(self, src, file, logger, args=None): + self.src = src self.file = file self.logger = logger self.args = args diff --git a/src/ifcpatch/recipes/ResetAbsoluteCoordinates.py b/src/ifcpatch/recipes/ResetAbsoluteCoordinates.py index 5e1ca7908d..98eebf0b58 100644 --- a/src/ifcpatch/recipes/ResetAbsoluteCoordinates.py +++ b/src/ifcpatch/recipes/ResetAbsoluteCoordinates.py @@ -1,5 +1,6 @@ class Patcher: - def __init__(self, file, logger, args=None): + def __init__(self, src, file, logger, args=None): + self.src = src self.file = file self.logger = logger diff --git a/src/ifcpatch/recipes/ResetSpatialElementLocations.py b/src/ifcpatch/recipes/ResetSpatialElementLocations.py index 80b2689ed5..26812aeefc 100644 --- a/src/ifcpatch/recipes/ResetSpatialElementLocations.py +++ b/src/ifcpatch/recipes/ResetSpatialElementLocations.py @@ -1,5 +1,6 @@ class Patcher: - def __init__(self, file, logger, args=None): + def __init__(self, src, file, logger, args=None): + self.src = src self.file = file self.logger = logger self.args = args diff --git a/src/ifcpatch/recipes/SetRefElevation.py b/src/ifcpatch/recipes/SetRefElevation.py index edd687760a..f06e8e77f6 100644 --- a/src/ifcpatch/recipes/SetRefElevation.py +++ b/src/ifcpatch/recipes/SetRefElevation.py @@ -1,5 +1,6 @@ class Patcher: - def __init__(self, file, logger, args=None): + def __init__(self, src, file, logger, args=None): + self.src = src self.file = file self.logger = logger self.args = args diff --git a/src/ifcpatch/recipes/SplitByBuildingStorey.py b/src/ifcpatch/recipes/SplitByBuildingStorey.py new file mode 100644 index 0000000000..44a112ea5e --- /dev/null +++ b/src/ifcpatch/recipes/SplitByBuildingStorey.py @@ -0,0 +1,42 @@ +class Patcher: + def __init__(self, src, file, logger, args=None): + self.src = src + self.file = file + self.logger = logger + self.args = args + + def patch(self): + import ifcopenshell + from shutil import copyfile + storeys = self.file.by_type('IfcBuildingStorey') + for i, storey in enumerate(storeys): + dest = '{}-{}.ifc'.format(i, storey.Name) + copyfile(self.src, dest) + old_ifc = ifcopenshell.open(dest) + new_ifc = ifcopenshell.file(schema=self.file.schema) + if self.file.schema == 'IFC2X3': + elements = old_ifc.by_type('IfcProject') + old_ifc.by_type('IfcProduct') + else: + elements = old_ifc.by_type('IfcContext') + old_ifc.by_type('IfcProduct') + inverse_elements = [] + for element in elements: + if element.is_a('IfcElement') \ + and not self.is_in_storey(element, storey): + element.Representation = None + continue + if element.is_a('IfcElement'): + styled_rep_items = [i for i in old_ifc.traverse(element) if i.is_a('IfcRepresentationItem') and i.StyledByItem] + [new_ifc.add(i.StyledByItem[0]) for i in styled_rep_items] + new_ifc.add(element) + inverse_elements.extend(old_ifc.get_inverse(element)) + for inverse_element in inverse_elements: + new_ifc.add(inverse_element) + for element in new_ifc.by_type('IfcElement'): + if not self.is_in_storey(element, storey): + new_ifc.remove(element) + new_ifc.write(dest) + + def is_in_storey(self, element, storey): + return element.ContainedInStructure \ + and element.ContainedInStructure[0].RelatingStructure.is_a('IfcBuildingStorey') \ + and element.ContainedInStructure[0].RelatingStructure.GlobalId == storey.GlobalId