From be584d9155805f50a0ef74b5aae92d0f92080460 Mon Sep 17 00:00:00 2001 From: Dion Moult Date: Tue, 21 Nov 2023 14:19:47 +1100 Subject: [PATCH] New IfcPatch recipe to tessellate elements to account for bugs in other vendors. --- .../ifcpatch/recipes/TessellateElements.py | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/ifcpatch/ifcpatch/recipes/TessellateElements.py diff --git a/src/ifcpatch/ifcpatch/recipes/TessellateElements.py b/src/ifcpatch/ifcpatch/recipes/TessellateElements.py new file mode 100644 index 0000000000..d928306e08 --- /dev/null +++ b/src/ifcpatch/ifcpatch/recipes/TessellateElements.py @@ -0,0 +1,69 @@ +# IfcPatch - IFC patching utiliy +# Copyright (C) 2023 Dion Moult +# +# This file is part of IfcPatch. +# +# IfcPatch is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# IfcPatch is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with IfcPatch. If not, see . + +import ifcopenshell +import ifcopenshell.geom +import ifcopenshell.util.selector +import ifcopenshell.util.representation +import multiprocessing + + +class Patcher: + def __init__(self, src, file, logger, query="IfcBeam"): + """Convert element body representations to tessellations or faceted breps + + Some software have bugs that result in incorrect geometry being + imported for more complex representation types, such as CSGs. This + patch converts elements matching your query into a tessellation (or + faceted brep for IFC2X3) which is generally supported by all + implementations. Note that styles and shape aspects are not preserved. + + See example bug: https://github.com/Autodesk/revit-ifc/issues/707 + + Example: + + .. code:: python + + ifcpatch.execute({"input": model, "recipe": "TessellateElements", "arguments": ["IfcBeam"]}) + """ + self.src = src + self.file = file + self.logger = logger + self.query = query + + def patch(self): + context = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW") + elements = ifcopenshell.util.selector.filter_elements(self.file, self.query) + settings = ifcopenshell.geom.settings() + settings.set_context_ids([context.id()]) + iterator = ifcopenshell.geom.iterator(settings, self.file, multiprocessing.cpu_count(), include=elements) + if iterator.initialize(): + while True: + shape = iterator.get() + element = self.file.by_guid(shape.guid) + v = [[x.tolist() for x in ifcopenshell.util.shape.get_vertices(shape.geometry)]] + f = [ifcopenshell.util.shape.get_faces(shape.geometry)] + mesh = ifcopenshell.api.run( + "geometry.add_mesh_representation", self.file, context=context, vertices=v, faces=f + ) + representations = element.Representation.Representations + representations = [r for r in representations if r.ContextOfItems != context] + representations.append(mesh) + element.Representation.Representations = representations + if not iterator.next(): + break