From c9f93b2316d42d35c54dfe41cdd7c54766b28e51 Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Fri, 10 Mar 2023 12:37:30 +0500 Subject: [PATCH] Section annotation option not to draw full line between the markers Here's the example - https://i.imgur.com/db09OVF.png To make it work need to add BBIM_Section property set to the annotation and set "HasConnectedSectionLine" to False (by default it's True). Also added preview for this feature in viewport. --- .../bim/data/pset/Psets_BBIM_Annotation.ifc | 8 +- .../blenderbim/bim/module/drawing/data.py | 24 +++++- .../bim/module/drawing/decoration.py | 51 ++++++++---- .../bim/module/drawing/svgwriter.py | 82 +++++++++++++------ 4 files changed, 121 insertions(+), 44 deletions(-) diff --git a/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc b/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc index 85fda525db..5eb67995a3 100644 --- a/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc +++ b/src/blenderbim/blenderbim/bim/data/pset/Psets_BBIM_Annotation.ifc @@ -1,7 +1,7 @@ ISO-10303-21; HEADER; FILE_DESCRIPTION((),'2;1'); -FILE_NAME('EPset_Annotation.ifc','2020-01-01T00:00:00',(),(),'EPset_Annotation','EPset_Annotation',$); +FILE_NAME('Psets_BBIM_Annotation.ifc','2020-01-01T00:00:00',(),(),'Psets_BBIM_Annotation','Psets_BBIM_Annotation',$); FILE_SCHEMA(('IFC4')); ENDSEC; DATA; @@ -12,5 +12,11 @@ DATA; #5=IFCPROPERTYSETTEMPLATE('0iKwujnQL9IevVQato8f7Z',$,'BBIM_Batting','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#6,#7)); #6=IFCSIMPLEPROPERTYTEMPLATE('0t2LEesGT1QRQtrIZUAR8L',$,'Thickness','Batting thickness',.P_SINGLEVALUE.,'IfcPositiveLengthMeasure',$,$,$,$,$,.READWRITE.); #7=IFCSIMPLEPROPERTYTEMPLATE('082PndS6v2kBOiJoSboMnh',$,'Reverse pattern direction','Reverse batting pattern (swap starting and ending points)',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#8=IFCPROPERTYSETTEMPLATE('1Dx2EiZnP67xotInXpwz90',$,'BBIM_Section','',.PSET_OCCURRENCEDRIVEN.,'IfcAnnotation',(#9,#10,#11,#12,#13)); +#9=IFCSIMPLEPROPERTYTEMPLATE('2a_9s8spHDc9dZHtgg71XL',$,'ShowStartArrow','Display start arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#10=IFCSIMPLEPROPERTYTEMPLATE('3i6SH_GbT7zhKea$wVE56A',$,'StartArrowSymbol','Custom symbol for the start of the section marker arrow.',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#11=IFCSIMPLEPROPERTYTEMPLATE('1DtsPn5a9FG8$zXHDDMavY',$,'ShowEndArrow','Display end arrow.',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); +#12=IFCSIMPLEPROPERTYTEMPLATE('2$6U0mLI9AiPRWeBabdY3u',$,'EndArrowSymbol','Custom symbol for the end of the section marker arrow',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); +#13=IFCSIMPLEPROPERTYTEMPLATE('1naFqntIL7igCY7hCaE7kq',$,'HasConnectedSectionLine','Connect or disconnect section markers with line (by default = True).',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); ENDSEC; END-ISO-10303-21; diff --git a/src/blenderbim/blenderbim/bim/module/drawing/data.py b/src/blenderbim/blenderbim/bim/module/drawing/data.py index dcb7126449..1effddfb78 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/data.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/data.py @@ -136,8 +136,28 @@ class DecoratorData: element = tool.Ifc.get_entity(obj) if element: unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get()) - thickness = ifcopenshell.util.element.get_pset(element, "BBIM_Batting", "Thickness") + thickness = ifcopenshell.util.element.get_pset(element, "BBIM_Batting", "Thickness") thickness = thickness * unit_scale if thickness else 1.5 cls.data[obj.name] = thickness return thickness - return 1.5 + + @classmethod + def get_section_pset_data(cls, obj): + result = cls.data.get(obj.name, None) + if result is not None: + return result + element = tool.Ifc.get_entity(obj) + if element: + # default values + pset_data = { + "HasConnectedSectionLine": True, + "ShowStartArrow": True, + "StartArrowSymbol": "", + "ShowEndArrow": True, + "EndArrowSymbol": "", + } + obj_pset_data = ifcopenshell.util.element.get_pset(element, "BBIM_Section") or {} + pset_data.update(obj_pset_data) + + cls.data[obj.name] = pset_data + return pset_data diff --git a/src/blenderbim/blenderbim/bim/module/drawing/decoration.py b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py index 066df06674..cbc3da09b3 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/decoration.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py @@ -309,6 +309,7 @@ class BaseDecorator: indices = [] idx = 0 + # TODO: are we adding same verts twice? for edge in mesh.edges: vertices.extend(edge.verts) indices.append((idx, idx + 1)) @@ -1818,6 +1819,7 @@ class SectionDecorator(LevelDecorator): GEOM_GLSL = """ uniform vec2 winsize; uniform float viewportDrawingScale; + uniform float connect_markers; layout(lines) in; layout(line_strip, max_vertices=MAX_POINTS) out; @@ -1879,14 +1881,7 @@ class SectionDecorator(LevelDecorator): EmitVertex(); EndPrimitive(); - // start reference divider - p = p0w + normalize(vec4(-1, 0, 0, 0)) * viewportDrawingScale * CIRCLE_SIZE; - gl_Position = WIN2CLIP(p); - EmitVertex(); - p = p0w + normalize(vec4(1, 0, 0, 0)) * viewportDrawingScale * CIRCLE_SIZE; - gl_Position = WIN2CLIP(p); - EmitVertex(); - EndPrimitive(); + // end edge circle for(int i=0; i 0) { + divider_line_size = CIRCLE_SIZE; + } else { + divider_line_size = CIRCLE_SIZE * 3; + } + + // start reference divider + p = p0w + normalize(vec4(-1, 0, 0, 0)) * viewportDrawingScale * divider_line_size; + gl_Position = WIN2CLIP(p); + EmitVertex(); + p = p0w + normalize(vec4(1, 0, 0, 0)) * viewportDrawingScale * CIRCLE_SIZE; + gl_Position = WIN2CLIP(p); + EmitVertex(); + EndPrimitive(); + // end reference divider p = p1w + normalize(vec4(-1, 0, 0, 0)) * viewportDrawingScale * CIRCLE_SIZE; gl_Position = WIN2CLIP(p); EmitVertex(); - p = p1w + normalize(vec4(1, 0, 0, 0)) * viewportDrawingScale * CIRCLE_SIZE; + p = p1w + normalize(vec4(1, 0, 0, 0)) * viewportDrawingScale * divider_line_size; gl_Position = WIN2CLIP(p); EmitVertex(); EndPrimitive(); // stem - p = p0w + gap; - gl_Position = WIN2CLIP(p); - EmitVertex(); - p = p1w - gap; - gl_Position = WIN2CLIP(p); - EmitVertex(); - EndPrimitive(); + if (connect_markers > 0) { + p = p0w + gap; + gl_Position = WIN2CLIP(p); + EmitVertex(); + p = p1w - gap; + gl_Position = WIN2CLIP(p); + EmitVertex(); + EndPrimitive(); + } } """ @@ -1945,7 +1958,11 @@ class SectionDecorator(LevelDecorator): verts, idxs = self.get_mesh_geom(obj) vert_map = {v.freeze(): (obj.matrix_world.inverted() @ v).x for v in verts} verts = sorted(verts, key=lambda v: vert_map[v], reverse=True) - self.draw_lines(context, obj, verts, idxs) + # TODO: add dashed line to shader + # mind the vertices limit + section_pset_data = DecoratorData.get_section_pset_data(obj) + connect_markers = section_pset_data["HasConnectedSectionLine"] + self.draw_lines(context, obj, verts, idxs, extra_float_kwargs={"connect_markers": float(connect_markers)}) class TextDecorator(BaseDecorator): diff --git a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py index 469b030f51..dc88c8ec53 100644 --- a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py +++ b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py @@ -31,10 +31,12 @@ import ifcopenshell.util.representation import blenderbim.tool as tool import blenderbim.bim.module.drawing.helper as helper import blenderbim.bim.module.drawing.annotation as annotation -from math import pi, ceil, atan, degrees -from mathutils import Vector -from mathutils import geometry + +from blenderbim.bim.module.drawing.data import DecoratorData from blenderbim.bim.ifc import IfcStore + +from math import pi, ceil, atan, degrees +from mathutils import geometry, Vector from bpy_extras import view3d_utils @@ -367,13 +369,25 @@ class SvgWriter: self.draw_edge_annotation(obj, classes) def draw_edge_annotation(self, obj, classes): - predefined_type = classes[2] + predefined_type = classes[2].split("-", 1)[1] - if predefined_type.endswith("-BATTING"): - x_offset = self.raw_width / 2 - y_offset = self.raw_height / 2 - matrix_world = obj.matrix_world + x_offset = self.raw_width / 2 + y_offset = self.raw_height / 2 + matrix_world = obj.matrix_world + def draw_simple_edge_annotation(v0, v1): + v0_global = matrix_world @ obj.data.vertices[v0].co.xyz + v1_global = matrix_world @ obj.data.vertices[v1].co.xyz + v0 = self.project_point_onto_camera(v0_global) + v1 = self.project_point_onto_camera(v1_global) + start = Vector(((x_offset + v0.x), (y_offset - v0.y))) + end = Vector(((x_offset + v1.x), (y_offset - v1.y))) + line = self.svg.add( + self.svg.line(start=start * self.svg_scale, end=end * self.svg_scale, class_=" ".join(classes)) + ) + + # BATTING ANNOTATIONS + if predefined_type == "BATTING": v0_global = matrix_world @ obj.data.vertices[0].co.xyz v1_global = matrix_world @ obj.data.vertices[1].co.xyz v0 = self.project_point_onto_camera(v0_global) @@ -439,23 +453,43 @@ class SvgWriter: ) self.svg.add(self.svg.polyline(points=points, class_=" ".join(classes), style=polyline_style)) - else: - x_offset = self.raw_width / 2 - y_offset = self.raw_height / 2 - matrix_world = obj.matrix_world - for edge in obj.data.edges: - v0_global = matrix_world @ obj.data.vertices[edge.vertices[0]].co.xyz - v1_global = matrix_world @ obj.data.vertices[edge.vertices[1]].co.xyz - v0 = self.project_point_onto_camera(v0_global) - v1 = self.project_point_onto_camera(v1_global) - start = Vector(((x_offset + v0.x), (y_offset - v0.y))) - end = Vector(((x_offset + v1.x), (y_offset - v1.y))) - vector = end - start - line = self.svg.add( - self.svg.line( - start=tuple(start * self.svg_scale), end=tuple(end * self.svg_scale), class_=" ".join(classes) + elif predefined_type == "SECTION": + section_pset_data = DecoratorData.get_section_pset_data(obj) + connect_markers = section_pset_data["HasConnectedSectionLine"] + if connect_markers: + for edge in obj.data.edges: + draw_simple_edge_annotation(*edge.vertices[:]) + else: + for edge in obj.data.edges: + v0_global = matrix_world @ obj.data.vertices[edge.vertices[0]].co.xyz + v1_global = matrix_world @ obj.data.vertices[edge.vertices[1]].co.xyz + v0 = self.project_point_onto_camera(v0_global) + v1 = self.project_point_onto_camera(v1_global) + start = Vector(((x_offset + v0.x), (y_offset - v0.y))) + end = Vector(((x_offset + v1.x), (y_offset - v1.y))) + + edge_dir = (end - start).normalized() + circle_radius = 5 + segment_size = circle_radius * 3 + + self.svg.add( + self.svg.line( + start=start * self.svg_scale, + end=start * self.svg_scale + edge_dir * segment_size, + class_=" ".join(classes), + ) ) - ) + self.svg.add( + self.svg.line( + start=end * self.svg_scale, + end=end * self.svg_scale - edge_dir * segment_size, + class_=" ".join(classes), + ) + ) + + else: + for edge in obj.data.edges: + draw_simple_edge_annotation(*edge.vertices[:]) def draw_leader_annotation(self, obj): self.draw_line_annotation(obj)