Added option for oblique style for viewport dimension annotations

It's available after adding "oblique" to EPset_Annotation classes of the annotaiton.

Examples with and without it:
- https://i.imgur.com/JtgSeUK.png
- https://i.imgur.com/H7TPnfo.png
This commit is contained in:
Andrej730
2023-03-29 16:35:53 +05:00
parent 86883770b8
commit 59b8347082
2 changed files with 109 additions and 41 deletions
@@ -115,6 +115,7 @@ class DecoratorData:
# stores 1 type of data per object
data = {}
# used by Ifc Annotations with ObjectType = "BATTING"
@classmethod
def get_batting_thickness(cls, obj):
result = cls.data.get(obj.name, None)
@@ -128,6 +129,7 @@ class DecoratorData:
cls.data[obj.name] = thickness
return thickness
# used by Ifc Annotations with ObjectType = "SECTION"
@classmethod
def get_section_markers_display_data(cls, obj):
result = cls.data.get(obj.name, None)
@@ -169,6 +171,7 @@ class DecoratorData:
cls.data[obj.name] = display_data
return display_data
# used by Ifc Annotations with ObjectType = "TEXT"
@classmethod
def get_ifc_text_data(cls, obj):
"""returns font size in mm for current ifc text object"""
@@ -214,3 +217,22 @@ class DecoratorData:
text_data = {"Literals": literals_data, "FontSize": font_size}
cls.data[obj.name] = text_data
return text_data
# used by Ifc Annotations with ObjectType = "DIMENSION"
@classmethod
def get_dimension_style(cls, obj):
result = cls.data.get(obj.name, None)
if result is not None:
return result
element = tool.Ifc.get_entity(obj)
if not element or not element.is_a("IfcAnnotation") or element.ObjectType != "DIMENSION":
return None
dimension_style = "arrow"
classes = ifcopenshell.util.element.get_pset(element, "EPset_Annotation", "Classes")
if classes and "oblique" in classes.lower().split():
dimension_style = "oblique"
cls.data[obj.name] = dimension_style
return dimension_style
@@ -442,7 +442,7 @@ class BaseDecorator:
box_alignment_offset += Vector((0, h))
else:
# middle / center
box_alignment_offset += Vector((0, h / 2))
box_alignment_offset += Vector((0, h / 2))
if "left" in box_alignment:
pass
@@ -451,7 +451,7 @@ class BaseDecorator:
else:
# middle / center
box_alignment_offset += Vector((w / 2, 0))
pos -= rotation_matrix.transposed() @ box_alignment_offset
else:
if center:
@@ -506,6 +506,10 @@ class DimensionDecorator(BaseDecorator):
DEF_GLSL = (
BaseDecorator.DEF_GLSL
+ """
#define OBLIQUE_SYMBOL_ANGLE PI / 4.0
#define OLBIQUE_SYMBOL_SIZE 10.0
#define OBLIQUE_HEAD_VERTS 7
#define ARROW_ANGLE PI / 12.0
#define ARROW_SIZE 16.0
"""
@@ -514,10 +518,23 @@ class DimensionDecorator(BaseDecorator):
GEOM_GLSL = """
uniform vec2 winsize;
uniform float viewportDrawingScale;
uniform float use_oblique_style;
layout(lines) in;
layout(line_strip, max_vertices=MAX_POINTS) out;
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);
head[0] = -dir * size*0.66;
head[1] = vec4(0);
head[2] = ortho * size;
head[3] = -ortho * size;
head[4] = vec4(0);
head[5] = vec4((mat2(c, +s, -s, c) * dir.xy) * size * 0.47, 0, 0);
head[6] = -head[5];
}
void main() {
vec4 clip2win = matCLIP2WIN();
vec4 win2clip = matWIN2CLIP();
@@ -529,49 +546,78 @@ class DimensionDecorator(BaseDecorator):
vec4 p;
vec4 head[3];
arrow_head(dir, viewportDrawingScale * ARROW_SIZE, ARROW_ANGLE, head);
if (use_oblique_style > 0) {
vec4 head[OBLIQUE_HEAD_VERTS];
oblique_dimension_head(dir, viewportDrawingScale * OLBIQUE_SYMBOL_SIZE, OBLIQUE_SYMBOL_ANGLE, head);
// start edge arrow
gl_Position = p0;
EmitVertex();
p = p0w + head[1];
gl_Position = WIN2CLIP(p);
EmitVertex();
p = p0w + head[2];
gl_Position = WIN2CLIP(p);
EmitVertex();
gl_Position = p0;
EmitVertex();
EndPrimitive();
// start edge arrow
for (int i = 0; i < OBLIQUE_HEAD_VERTS; i++) {
gl_Position = WIN2CLIP((p0w + head[i]));
EmitVertex();
}
EndPrimitive();
// end edge arrow
gl_Position = p1;
EmitVertex();
p = p1w - head[1];
gl_Position = WIN2CLIP(p);
EmitVertex();
p = p1w - head[2];
gl_Position = WIN2CLIP(p);
EmitVertex();
gl_Position = p1;
EmitVertex();
EndPrimitive();
// end edge arrow
for (int i = 0; i < OBLIQUE_HEAD_VERTS; i++) {
gl_Position = WIN2CLIP((p1w - head[i]));
EmitVertex();
}
EndPrimitive();
// stem, with gaps for arrows
p = p0w + head[0];
gl_Position = WIN2CLIP(p);
EmitVertex();
p = p1w - head[0];
gl_Position = WIN2CLIP(p);
EmitVertex();
EndPrimitive();
// stem
gl_Position = p0;
EmitVertex();
gl_Position = p1;
EmitVertex();
EndPrimitive();
} else {
vec4 head[3];
arrow_head(dir, viewportDrawingScale * ARROW_SIZE, ARROW_ANGLE, head);
// start edge arrow
gl_Position = p0;
EmitVertex();
p = p0w + head[1];
gl_Position = WIN2CLIP(p);
EmitVertex();
p = p0w + head[2];
gl_Position = WIN2CLIP(p);
EmitVertex();
gl_Position = p0;
EmitVertex();
EndPrimitive();
// end edge arrow
gl_Position = p1;
EmitVertex();
p = p1w - head[1];
gl_Position = WIN2CLIP(p);
EmitVertex();
p = p1w - head[2];
gl_Position = WIN2CLIP(p);
EmitVertex();
gl_Position = p1;
EmitVertex();
EndPrimitive();
// stem, with gaps for arrows
p = p0w + head[0];
gl_Position = WIN2CLIP(p);
EmitVertex();
p = p1w - head[0];
gl_Position = WIN2CLIP(p);
EmitVertex();
EndPrimitive();
}
}
"""
def decorate(self, context, obj):
verts, idxs, _ = self.get_path_geom(obj, topo=False)
self.draw_lines(context, obj, verts, idxs)
dimension_style = DecoratorData.get_dimension_style(obj)
self.draw_lines(
context, obj, verts, idxs, extra_float_kwargs={"use_oblique_style": float(dimension_style == "oblique")}
)
self.draw_labels(context, obj, verts, idxs)
def draw_labels(self, context, obj, vertices, indices):
@@ -806,7 +852,7 @@ class LeaderDecorator(BaseDecorator):
props = obj.BIMTextProperties
text_data = props.get_text_edited_data() if props.is_editing else DecoratorData.get_ifc_text_data(obj)
text = text_data["Literals"][0]['CurrentValue']
text = text_data["Literals"][0]["CurrentValue"]
self.draw_label(context, text, pos, dir, gap=0, center=False, vcenter=False)
@@ -1336,11 +1382,11 @@ class PlanLevelDecorator(LevelDecorator):
dir = p1 - p0
if dir.length < 1:
continue
if dir.x > 0:
box_alignment = "bottom-left"
else:
box_alignment = 'bottom-right'
box_alignment = "bottom-right"
dir *= -1
z = verts[-1].z / unit_scale
@@ -2098,7 +2144,7 @@ class TextDecorator(BaseDecorator):
def matrix_only_rotation(m):
return m.to_3x3().normalized().to_4x4()
text_dir = Vector((1,0))
text_dir = Vector((1, 0))
text_dir_world = matrix_only_rotation(region3d.perspective_matrix.inverted()) @ text_dir.to_3d()
text_dir_world_rotated = matrix_only_rotation(obj.matrix_world) @ text_dir_world
text_dir = (matrix_only_rotation(region3d.perspective_matrix) @ text_dir_world_rotated).to_2d().normalized()