Fix #3355. Reimplement graphical clash snapshots in BCF from IfcClash in the BlenderBIM Add-on.

This commit is contained in:
Dion Moult
2023-07-03 16:49:04 +10:00
parent 6758d878d8
commit 99e2598c00
3 changed files with 33 additions and 7 deletions
+2
View File
@@ -275,6 +275,7 @@ class TopicHandler:
"""
new_viewpoint = VisualizationInfoHandler.create_new(element, self._xml_handler)
self.add_visinfo_handler(new_viewpoint)
return new_viewpoint
def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
"""Add a viewpoint pointing at an XYZ point in space
@@ -287,6 +288,7 @@ class TopicHandler:
position, *guids, xml_handler=self._xml_handler
)
self.add_visinfo_handler(vi_handler)
return vi_handler
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
self.viewpoints[new_viewpoint.guid + ".bcfv"] = new_viewpoint
@@ -23,7 +23,7 @@ import bmesh
import logging
import numpy as np
import ifcopenshell
from mathutils import Matrix
from mathutils import Matrix, Vector
from math import radians
from blenderbim.bim.ifc import IfcStore
@@ -222,6 +222,7 @@ class ExecuteIfcClash(bpy.types.Operator):
_, extension = os.path.splitext(self.filepath)
if extension != ".json":
self.filepath = bpy.path.ensure_ext(self.filepath, ".bcf")
settings = ifcclash.ClashSettings()
settings.output = self.filepath
settings.logger = logging.getLogger("Clash")
@@ -230,12 +231,28 @@ class ExecuteIfcClash(bpy.types.Operator):
if context.scene.BIMClashProperties.should_create_clash_snapshots:
def get_viewpoint_snapshot(viewpoint, mat):
def get_viewpoint_snapshot(viewpoint):
camera = bpy.data.objects.get("IFC Clash Camera")
if not camera:
camera = bpy.data.objects.new("IFC Clash Camera", bpy.data.cameras.new("IFC Clash Camera"))
context.scene.collection.objects.link(camera)
camera.matrix_world = Matrix(mat)
bcf_camera = viewpoint.visualization_info.perspective_camera
p = bcf_camera.camera_view_point
z = bcf_camera.camera_direction
z = Vector([z.x, z.y, z.z]) * -1
y = bcf_camera.camera_up_vector
y = Vector([y.x, y.y, y.z])
x = y.cross(z)
mat = Matrix([
[x[0], y[0], z[0], p.x],
[x[1], y[1], z[1], p.y],
[x[2], y[2], z[2], p.z],
[0, 0, 0, 0],
])
camera.matrix_world = mat
context.scene.camera = camera
camera.data.angle = radians(60)
area = next(area for area in context.screen.areas if area.type == "VIEW_3D")
@@ -246,7 +263,8 @@ class ExecuteIfcClash(bpy.types.Operator):
context.scene.render.image_settings.file_format = "PNG"
context.scene.render.filepath = os.path.join(context.scene.BIMProperties.data_dir, "snapshot.png")
bpy.ops.render.opengl(write_still=True)
return context.scene.render.filepath
with open(context.scene.render.filepath, "rb") as f:
return ("snapshot.png", f.read())
clasher.get_viewpoint_snapshot = get_viewpoint_snapshot
+9 -3
View File
@@ -122,14 +122,20 @@ class Clasher:
for clash in clash_set["clashes"].values():
title = f'{clash["a_ifc_class"]}/{clash["a_name"]} and {clash["b_ifc_class"]}/{clash["b_name"]}'
topic = bcfxml.add_topic(title, title, "IfcClash")
topic.add_viewpoint_from_point_and_guids(
viewpoint = topic.add_viewpoint_from_point_and_guids(
np.array(clash["position"]), clash["a_global_id"], clash["b_global_id"],
)
snapshot = self.get_viewpoint_snapshot(viewpoint)
if snapshot:
topic.markup.viewpoints[0].snapshot = snapshot[0]
viewpoint.snapshot = snapshot[1]
suffix = f".{i}" if i else ""
bcfxml.save_project(f"{self.settings.output}{suffix}")
def get_viewpoint_snapshot(self, viewpoint, mat):
return None # Possible to overload this function in a GUI application if used as a library
def get_viewpoint_snapshot(self, viewpoint):
# Possible to overload this function in a GUI application if used as a library.
# Should return a tuple of (filename, bytes).
return None
def export_json(self):
clash_sets = self.clash_sets.copy()