diff --git a/src/blenderbim/blenderbim/bim/module/drawing/data.py b/src/blenderbim/blenderbim/bim/module/drawing/data.py index c16c8e52be..d9b70cf9a4 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/data.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/data.py @@ -30,6 +30,7 @@ def refresh(): SchedulesData.is_loaded = False DrawingsData.is_loaded = False DecoratorData.data = {} + DecoratorData.cut_cache = {} class ProductAssignmentsData: @@ -152,6 +153,7 @@ FONT_SIZES = { class DecoratorData: # stores 1 type of data per object data = {} + cut_cache = {} # used by Ifc Annotations with ObjectType = "BATTING" @classmethod diff --git a/src/blenderbim/blenderbim/bim/module/drawing/decoration.py b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py index 073ac5edaf..b91494a42c 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/decoration.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py @@ -30,6 +30,7 @@ from bpy.types import SpaceView3D from mathutils import Vector, Matrix from bpy_extras.view3d_utils import location_3d_to_region_2d from gpu.types import GPUShader, GPUBatch, GPUIndexBuf, GPUVertBuf, GPUVertFormat +from gpu_extras.batch import batch_for_shader from blenderbim.bim.module.drawing.data import DecoratorData from blenderbim.bim.module.drawing.shaders import BASE_LIB_GLSL, BASE_DEF_GLSL @@ -242,7 +243,7 @@ class BaseDecorator: vertices = [obj.matrix_world @ v.co for v in bm.verts] return vertices, indices - def decorate(self, context, object): + def decorate(self, context, obj): """perform actual drawing stuff""" raise NotImplementedError() @@ -450,7 +451,7 @@ class DimensionDecorator(BaseDecorator): layout(lines) in; layout(triangle_strip, max_vertices=MAX_POINTS) out; - void oblique_dimension_head(in vec4 dir, in float size, + void oblique_dimension_head(in vec4 dir, in float size, in float angle, out vec4 head[OBLIQUE_HEAD_VERTS]) { float c = cos(angle), s = sin(angle); vec4 ortho = vec4(-dir.y, dir.x, 0, 0); @@ -495,22 +496,22 @@ class DimensionDecorator(BaseDecorator): // stem do_edge_verts(p0, p1); - EndPrimitive(); + EndPrimitive(); } else { vec4 head[3]; arrow_head(dir, viewportDrawingScale * ARROW_SIZE, ARROW_ANGLE, head); // start edge arrow - do_edge_verts( p0, WIN2CLIP( (p0w + head[1]) ) ); - do_edge_verts_win( p0w + head[1], p0w + head[2] ); - do_edge_verts( WIN2CLIP( p0w + head[2] ), p0 ); + do_edge_verts( p0, WIN2CLIP( (p0w + head[1]) ) ); + do_edge_verts_win( p0w + head[1], p0w + head[2] ); + do_edge_verts( WIN2CLIP( p0w + head[2] ), p0 ); EndPrimitive(); // end edge arrow - do_edge_verts( p1, WIN2CLIP( p1w - head[1] ) ); - do_edge_verts_win( p1w - head[1], p1w - head[2] ); - do_edge_verts( WIN2CLIP( p1w - head[2] ), p1 ); + do_edge_verts( p1, WIN2CLIP( p1w - head[1] ) ); + do_edge_verts_win( p1w - head[1], p1w - head[2] ); + do_edge_verts( WIN2CLIP( p1w - head[2] ), p1 ); EndPrimitive(); // stem, with gaps for arrows @@ -569,7 +570,7 @@ class AngleDecorator(BaseDecorator): layout(triangle_strip, max_vertices=MAX_POINTS) out; in uint type[]; in vec4 v_next_vert[]; - + // per edge shader void main() { // default setup for macro to work @@ -981,7 +982,7 @@ class StairDecorator(BaseDecorator): if (t0 == 1u) { vec4 head[CIRCLE_SEGS]; circle_head(viewportDrawingScale * CIRCLE_SIZE, head); - + for(int i=0; i 0 for d in bounding_box_signed_distances) + neg_exists_bb = any(d < 0 for d in bounding_box_signed_distances) + + if not (pos_exists_bb and neg_exists_bb): + return False + + bm = bmesh.new() + bm.from_mesh(obj.data) + + # Transform the vertices to world space + mesh_mat = obj.matrix_world + bm.transform(mesh_mat) + + # Calculate the signed distances of all vertices from the plane + signed_distances = [plane_no.dot(v.co - plane_co) for v in bm.verts] + + bm.free() + + # Check for intersection + pos_exists = any(d > 0 for d in signed_distances) + neg_exists = any(d < 0 for d in signed_distances) + + return pos_exists and neg_exists + + def bisect_mesh(self, obj, camera): + camera_matrix = obj.matrix_world.inverted() @ camera.matrix_world + plane_co = camera_matrix.translation + plane_no = camera_matrix.col[2].xyz + + global_offset = camera.matrix_world.col[2].xyz * -camera.data.clip_start + + bm = bmesh.new() + bm.from_mesh(obj.data) + + # Run the bisect operation + geom = bm.verts[:] + bm.edges[:] + bm.faces[:] + results = bmesh.ops.bisect_plane(bm, geom=geom, dist=0.0001, plane_co=plane_co, plane_no=plane_no) + + vert_map = {} + verts = [] + edges = [] + i = 0 + for geom in results["geom_cut"]: + if isinstance(geom, bmesh.types.BMVert): + verts.append(tuple((obj.matrix_world @ geom.co) + global_offset)) + vert_map[geom.index] = i + i += 1 + else: + # It seems as though edges always appear after verts + edges.append([vert_map[v.index] for v in geom.verts]) + + bm.free() + + return verts, edges + + class DecorationsHandler: decorators_classes = [ DimensionDecorator, diff --git a/src/blenderbim/blenderbim/bim/module/drawing/handler.py b/src/blenderbim/blenderbim/bim/module/drawing/handler.py index e30ac87b13..1553e2cc98 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/handler.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/handler.py @@ -23,8 +23,7 @@ from bpy.app.handlers import persistent @persistent def toggleDecorationsOnLoad(*args): - toggle = bpy.context.scene.DocProperties.should_draw_decorations - if toggle: + if bpy.context.scene.DocProperties.should_draw_decorations: decoration.DecorationsHandler.install(bpy.context) else: decoration.DecorationsHandler.uninstall() diff --git a/src/blenderbim/blenderbim/bim/module/drawing/operator.py b/src/blenderbim/blenderbim/bim/module/drawing/operator.py index a0d60eb7d9..e78273d72f 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/operator.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/operator.py @@ -39,6 +39,7 @@ import blenderbim.bim.module.drawing.annotation as annotation import blenderbim.bim.module.drawing.sheeter as sheeter import blenderbim.bim.module.drawing.scheduler as scheduler import blenderbim.bim.module.drawing.helper as helper +from blenderbim.bim.module.drawing.decoration import CutDecorator from blenderbim.bim.module.drawing.data import DecoratorData import blenderbim.bim.export_ifc from lxml import etree @@ -989,11 +990,13 @@ class ActivateView(bpy.types.Operator): drawing: bpy.props.IntProperty() def execute(self, context): - core.activate_drawing_view(tool.Ifc, tool.Drawing, drawing=tool.Ifc.get().by_id(self.drawing)) + drawing = tool.Ifc.get().by_id(self.drawing) + core.activate_drawing_view(tool.Ifc, tool.Drawing, drawing=drawing) bpy.context.scene.DocProperties.active_drawing_id = self.drawing if ifcopenshell.util.element.get_pset(drawing, "EPset_Drawing", "HasUnderlay"): bpy.ops.bim.activate_drawing_style() core.sync_references(tool.Ifc, tool.Collector, tool.Drawing, drawing=tool.Ifc.get().by_id(self.drawing)) + CutDecorator.install(context) return {"FINISHED"} diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py index 29b9584870..7308cb424d 100644 --- a/src/blenderbim/blenderbim/tool/drawing.py +++ b/src/blenderbim/blenderbim/tool/drawing.py @@ -117,6 +117,7 @@ class Drawing(blenderbim.core.tool.Drawing): camera.location = (0, 0, 1.5) # The view shall be 1.5m above the origin camera.data.type = "ORTHO" camera.data.ortho_scale = 50 # The default of 6m is too small + camera.data.clip_start = 0.002 # 2mm is close to zero but allows any GPU-drawn lines to be visible. camera.data.clip_end = 10 # A slightly more reasonable default if bpy.context.scene.unit_settings.system == "IMPERIAL": camera.data.BIMCameraProperties.diagram_scale = '1/8"=1\'-0"|1/96' @@ -495,6 +496,7 @@ class Drawing(blenderbim.core.tool.Drawing): camera = bpy.data.cameras.new(tool.Loader.get_mesh_name(geometry)) camera.type = "ORTHO" camera.ortho_scale = width if width > height else height + camera.clip_start = 0.002 camera.clip_end = depth if width > height: