See #1227. Clip based on active camera for legibility of drawings. Needs polish.

This commit is contained in:
Dion Moult
2025-03-16 00:23:47 +11:00
parent 2270185f8c
commit b2e2f765ca
4 changed files with 26 additions and 23 deletions
@@ -1801,7 +1801,6 @@ class CutDecorator:
)
edges = [g for g in bisect["geom_cut"] if isinstance(g, bmesh.types.BMEdge)]
fill = bmesh.ops.edgenet_fill(bm_fill, edges=edges)
print("test FILL1", fill)
if i != 0:
geom = bm_fill.verts[:] + bm_fill.edges[:] + bm_fill.faces[:]
bisect = bmesh.ops.bisect_plane(
@@ -1809,10 +1808,8 @@ class CutDecorator:
)
edges = [g for g in bisect["geom_cut"] if isinstance(g, bmesh.types.BMEdge)]
fill = bmesh.ops.edgenet_fill(bm_fill, edges=edges)
print("test FILL2", fill)
geom = bm_fill.verts[:] + bm_fill.edges[:] + bm_fill.faces[:]
print("gonna bisect mesh tris", geom)
verts, tris = self.bisect_mesh_tris(obj, bm_fill, geom, context.scene.camera)
DecoratorData.fill_cache[element_id].setdefault(colour, []).append((verts, tris))
@@ -2020,6 +2020,7 @@ class ActivateDrawingBase:
camera_props = camera.data.BIMCameraProperties
if camera_props.update_representation(camera):
bpy.ops.bim.update_representation(obj=camera.name, ifc_representation_class="")
bpy.ops.bim.refresh_clipping_planes("INVOKE_DEFAULT")
return {"FINISHED"}
@@ -2299,6 +2299,7 @@ class RefreshClippingPlanes(bpy.types.Operator):
def __init__(self):
self.total_planes = 0
self.camera = None
def invoke(self, context, event):
context.window_manager.modal_handler_add(self)
@@ -2311,16 +2312,22 @@ class RefreshClippingPlanes(bpy.types.Operator):
self.clean_deleted_planes(context)
for clipping_plane in props.clipping_planes:
if clipping_plane.obj and self.is_moved(clipping_plane.obj):
if clipping_plane.obj and tool.Ifc.is_moved(clipping_plane.obj, ifc_only=False):
should_refresh = True
break
if self.camera != context.scene.camera:
should_refresh = True
elif self.camera and tool.Ifc.is_moved(self.camera, ifc_only=False):
should_refresh = True
total_planes = len(props.clipping_planes)
if should_refresh or total_planes != self.total_planes:
self.refresh_clipping_planes(context)
for clipping_plane in props.clipping_planes:
if clipping_plane.obj:
tool.Geometry.record_object_position(clipping_plane.obj)
self.camera = context.scene.camera
self.total_planes = total_planes
return {"PASS_THROUGH"}
@@ -2340,18 +2347,6 @@ class RefreshClippingPlanes(bpy.types.Operator):
else:
break
def is_moved(self, obj: bpy.types.Object) -> bool:
props = tool.Blender.get_object_bim_props(obj)
if not props.location_checksum:
return True # Let's be conservative
loc_check = np.frombuffer(eval(props.location_checksum))
rot_check = np.frombuffer(eval(props.rotation_checksum))
loc_real = np.array(obj.matrix_world.translation).flatten()
rot_real = np.array(obj.matrix_world.to_3x3()).flatten()
if np.allclose(loc_check, loc_real, atol=1e-4) and np.allclose(rot_check, rot_real, atol=1e-2):
return False
return True
def refresh_clipping_planes(self, context):
import bmesh
from itertools import cycle
@@ -2360,8 +2355,9 @@ class RefreshClippingPlanes(bpy.types.Operator):
region = next(r for r in area.regions if r.type == "WINDOW")
data = region.data
camera = context.scene.camera
props = tool.Project.get_project_props()
if not len(props.clipping_planes):
if not len(props.clipping_planes) and not camera:
data.use_clip_planes = False
else:
with bpy.context.temp_override(area=area, region=region):
@@ -2390,6 +2386,14 @@ class RefreshClippingPlanes(bpy.types.Operator):
clip_planes.append(clip_plane)
bm.free()
if camera:
normal = camera.matrix_world.col[2].to_3d()
normal *= -1
center = camera.matrix_world.translation
distance = -center.dot(normal)
clip_plane = (normal.x, normal.y, normal.z, distance)
clip_planes.append(clip_plane)
clip_planes = cycle(clip_planes)
data.clip_planes = [tuple(next(clip_planes)) for i in range(0, 6)]
data.update()
+7 -6
View File
@@ -83,12 +83,13 @@ class Ifc(bonsai.core.tool.Ifc):
return (not ignore_scale and tool.Geometry.is_scaled(obj)) or obj in IfcStore.edited_objs
@classmethod
def is_moved(cls, obj: bpy.types.Object) -> bool:
element = cls.get_entity(obj)
if not element and not tool.Geometry.is_representation_item(obj):
return False
if element and (element.is_a("IfcTypeProduct") or element.is_a("IfcProject")):
return False
def is_moved(cls, obj: bpy.types.Object, ifc_only: bool = True) -> bool:
if ifc_only:
element = cls.get_entity(obj)
if not element and not tool.Geometry.is_representation_item(obj):
return False
if element and (element.is_a("IfcTypeProduct") or element.is_a("IfcProject")):
return False
oprops = tool.Blender.get_object_bim_props(obj)
if not oprops.location_checksum:
return True # Let's be conservative