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(
self, product: ifcopenshell.entity_instance, representation: ifcopenshell.entity_instance
) -> Union[ifcopenshell.entity_instance, None]:
placement_matrix = self.get_element_matrix(product)
vertex_list = []
for item in representation.Items:
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, [], [])
mesh = tool.Loader.create_point_cloud_mesh(representation)
if mesh is None:
return
tool.Ifc.link(representation, mesh)
placement_matrix = self.get_element_matrix(product)
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.link_element(product, obj)
+10 -3
View File
@@ -585,6 +585,16 @@ class Geometry(bonsai.core.tool.Geometry):
settings.set("keep-bounding-boxes", True)
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"):
# You may only specify a single representation when creating shapes for types
try:
@@ -606,9 +616,6 @@ class Geometry(bonsai.core.tool.Geometry):
settings.set("dimensionality", ifcopenshell.ifcopenshell_wrapper.CURVES_SURFACES_AND_SOLIDS)
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":
mesh = ifc_importer.create_camera(element, shape)
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:
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
def get_offset_point(cls, ifc_file: ifcopenshell.file) -> Union[npt.NDArray[np.float64], None]:
elements_checked = 0