fix error switching to point cloud representation

Previously it wasn't handled and would always result in errors. It seems the only way to load point cloud representation to BBIM was by loading IFC file and only if this is the only representation of the element.
This commit is contained in:
Andrej730
2024-08-23 14:24:53 +05:00
parent 59717d6e92
commit 638d200a27
3 changed files with 34 additions and 23 deletions
+4 -20
View File
@@ -827,28 +827,12 @@ class IfcImporter:
def create_pointcloud( def create_pointcloud(
self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, None]: ) -> Union[ifcopenshell.entity_instance, None]:
placement_matrix = self.get_element_matrix(product) mesh = tool.Loader.create_point_cloud_mesh(representation)
vertex_list = [] if mesh is None:
for item in representation.Items: return
if item.is_a("IfcCartesianPointList3D"):
vertex_list.extend(
mathutils.Vector(list(coordinates)) * self.unit_scale for coordinates in item.CoordList
)
elif item.is_a("IfcCartesianPointList2D"):
vertex_list.extend(
mathutils.Vector(list(coordinates)).to_3d() * self.unit_scale for coordinates in item.CoordList
)
elif item.is_a("IfcCartesianPoint"):
vertex_list.append(mathutils.Vector(list(item.Coordinates)) * self.unit_scale)
if len(vertex_list) == 0:
return None
mesh_name = tool.Geometry.get_representation_name(representation)
mesh = bpy.data.meshes.new(mesh_name)
mesh.from_pydata(vertex_list, [], [])
tool.Ifc.link(representation, mesh) tool.Ifc.link(representation, mesh)
placement_matrix = self.get_element_matrix(product)
obj = bpy.data.objects.new(tool.Loader.get_name(product), mesh) obj = bpy.data.objects.new(tool.Loader.get_name(product), mesh)
self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, placement_matrix)) self.set_matrix_world(obj, tool.Loader.apply_blender_offset_to_matrix_world(obj, placement_matrix))
self.link_element(product, obj) self.link_element(product, obj)
+10 -3
View File
@@ -585,6 +585,16 @@ class Geometry(bonsai.core.tool.Geometry):
settings.set("keep-bounding-boxes", True) settings.set("keep-bounding-boxes", True)
context = representation.ContextOfItems context = representation.ContextOfItems
ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings)
ifc_importer.file = tool.Ifc.get()
# create_shape doesn't support point cloud representations.
if representation.RepresentationType in ("PointCloud", "Point"):
mesh = tool.Loader.create_point_cloud_mesh(representation)
if mesh is None:
raise Exception(f"Failed to process point cloud representation: {representation}.")
return mesh
if element.is_a("IfcTypeProduct"): if element.is_a("IfcTypeProduct"):
# You may only specify a single representation when creating shapes for types # You may only specify a single representation when creating shapes for types
try: try:
@@ -606,9 +616,6 @@ class Geometry(bonsai.core.tool.Geometry):
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS) settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
shape = ifcopenshell.geom.create_shape(settings, element, representation) shape = ifcopenshell.geom.create_shape(settings, element, representation)
ifc_importer = bonsai.bim.import_ifc.IfcImporter(ifc_import_settings)
ifc_importer.file = tool.Ifc.get()
if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING": if element.is_a("IfcAnnotation") and element.ObjectType == "DRAWING":
mesh = ifc_importer.create_camera(element, shape) mesh = ifc_importer.create_camera(element, shape)
if element.is_a("IfcAnnotation") and ifc_importer.is_curve_annotation(element): if element.is_a("IfcAnnotation") and ifc_importer.is_curve_annotation(element):
+20
View File
@@ -651,6 +651,26 @@ class Loader(bonsai.core.tool.Loader):
except: except:
pass pass
@classmethod
def create_point_cloud_mesh(cls, representation: ifcopenshell.entity_instance) -> Union[bpy.types.Mesh, None]:
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
vertex_list = []
for item in representation.Items:
if item.is_a("IfcCartesianPointList3D"):
vertex_list.extend(Vector(list(coordinates)) * unit_scale for coordinates in item.CoordList)
elif item.is_a("IfcCartesianPointList2D"):
vertex_list.extend(Vector(list(coordinates)).to_3d() * unit_scale for coordinates in item.CoordList)
elif item.is_a("IfcCartesianPoint"):
vertex_list.append(Vector(list(item.Coordinates)) * unit_scale)
if len(vertex_list) == 0:
return None
mesh_name = tool.Geometry.get_representation_name(representation)
mesh = bpy.data.meshes.new(mesh_name)
mesh.from_pydata(vertex_list, [], [])
return mesh
@classmethod @classmethod
def get_offset_point(cls, ifc_file: ifcopenshell.file) -> Union[npt.NDArray[np.float64], None]: def get_offset_point(cls, ifc_file: ifcopenshell.file) -> Union[npt.NDArray[np.float64], None]:
elements_checked = 0 elements_checked = 0