TesselateElement ifcpatch recipe to support product types

Previously it would just fail if you provide some IfcTypeProduct in the patch query
This commit is contained in:
Andrej730
2024-06-21 17:40:36 +05:00
parent 4385bf0bcc
commit 746051815d
@@ -24,6 +24,7 @@ import ifcopenshell.util.shape
import ifcopenshell.util.representation import ifcopenshell.util.representation
import multiprocessing import multiprocessing
from logging import Logger from logging import Logger
from typing import Union
class Patcher: class Patcher:
@@ -65,6 +66,9 @@ class Patcher:
def patch(self): def patch(self):
context = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW") context = ifcopenshell.util.representation.get_context(self.file, "Model", "Body", "MODEL_VIEW")
if not context:
return
elements = ifcopenshell.util.selector.filter_elements(self.file, self.query) elements = ifcopenshell.util.selector.filter_elements(self.file, self.query)
if not elements: if not elements:
@@ -72,17 +76,38 @@ class Patcher:
settings = ifcopenshell.geom.settings() settings = ifcopenshell.geom.settings()
settings.set("context-ids", [context.id()]) settings.set("context-ids", [context.id()])
iterator = ifcopenshell.geom.iterator(settings, self.file, multiprocessing.cpu_count(), include=elements)
# Iterator can handle only products, so we filter out everything else (IfcTypeProducts).
products = []
non_products = []
for element in elements:
if element.is_a("IfcProduct"):
products.append(element)
else:
non_products.append(element)
def store_geometry(
element: ifcopenshell.entity_instance,
shape: Union[ifcopenshell.geom.ShapeType, ifcopenshell.geom.ShapeElementType],
) -> None:
geometry = getattr(shape, "geometry", shape)
v = [[x.tolist() for x in ifcopenshell.util.shape.get_vertices(geometry)]]
f = [ifcopenshell.util.shape.get_faces(geometry)]
replacements[element] = (v, f)
iterator = ifcopenshell.geom.iterator(settings, self.file, multiprocessing.cpu_count(), include=products)
replacements = {} replacements = {}
if iterator.initialize(): if iterator.initialize():
while True: for shape in iterator:
shape = iterator.get()
element = self.file.by_guid(shape.guid) element = self.file.by_guid(shape.guid)
v = [[x.tolist() for x in ifcopenshell.util.shape.get_vertices(shape.geometry)]] store_geometry(element, shape)
f = [ifcopenshell.util.shape.get_faces(shape.geometry)]
replacements[element] = (v, f) for element in non_products:
if not iterator.next(): representation = ifcopenshell.util.representation.get_representation(element, context)
break if not representation:
continue
shape = ifcopenshell.geom.create_shape(settings, representation)
store_geometry(element, shape)
# Do the replacements outside the iterator to prevent messing up iterator state. # Do the replacements outside the iterator to prevent messing up iterator state.
for element, geometry in replacements.items(): for element, geometry in replacements.items():
@@ -95,7 +120,14 @@ class Patcher:
faces=f, faces=f,
force_faceted_brep=self.force_faceted_brep, force_faceted_brep=self.force_faceted_brep,
) )
representations = element.Representation.Representations if element.is_a("IfcProduct"):
representations = [r for r in representations if r.ContextOfItems != context] representations = element.Representation.Representations
representations.append(mesh) representations = [r for r in representations if r.ContextOfItems != context]
element.Representation.Representations = representations representations.append(mesh)
element.Representation.Representations = representations
else: # IfcTypeProduct.
rep_maps = element.RepresentationMaps
for rep_map in rep_maps:
mapped_rep = rep_map.MappedRepresentation
if mapped_rep.ContextOfItems == context:
rep_map.MappedRepresentation = mesh