Newer
Older
# SPDX-License-Identifier: GPL-2.0-or-later
# ----------------------------------------------------------
# support routines for OpenGL
# Author: Antonio Vazquez (antonioya)
#
# ----------------------------------------------------------
# noinspection PyUnresolvedReferences
import bpy
# noinspection PyUnresolvedReferences
import blf
from math import fabs, degrees, radians, sqrt, cos, sin, pi
from mathutils import Vector, Matrix
from bmesh import from_edit_mesh
from bpy_extras import view3d_utils, mesh_utils
import bpy_extras.object_utils as object_utils
# GPU
import gpu
from gpu_extras.batch import batch_for_shader
shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR') if not bpy.app.background else None
shader_line = gpu.shader.from_builtin('3D_POLYLINE_UNIFORM_COLOR') if not bpy.app.background else None
imm_line_width = 1.0
imm_viewport = (0, 0)
def imm_set_line_width(width):
global imm_line_width, imm_viewport
region = bpy.context.region
imm_viewport = (region.width, region.height)
imm_line_width = width
# -------------------------------------------------------------
# Draw segments
#
# -------------------------------------------------------------
# noinspection PyUnresolvedReferences,PyUnboundLocalVariable
def draw_segments(context, myobj, op, region, rv3d):
if op.measureit_num > 0:
a_code = "\u00b0" # degree
scale = bpy.context.scene.unit_settings.scale_length
scene = bpy.context.scene
pr = scene.measureit_gl_precision
fmt = "%1." + str(pr) + "f"
ovr = scene.measureit_ovr
ovrcolor = scene.measureit_ovr_color
ovrfsize = scene.measureit_ovr_font
ovrfang = get_angle_in_rad(scene.measureit_ovr_font_rotation)
ovrfaln = scene.measureit_ovr_font_align
ovrline = scene.measureit_ovr_width
units = scene.measureit_units
fang = get_angle_in_rad(scene.measureit_font_rotation)
# --------------------
# Scene Scale
# --------------------
if scene.measureit_scale is True:
prs = scene.measureit_scale_precision
fmts = "%1." + str(prs) + "f"
pos_2d = get_scale_txt_location(context)
tx_dsp = fmts % scene.measureit_scale_factor
tx_scale = scene.measureit_gl_scaletxt + " 1:" + tx_dsp
tx_scale, scene.measureit_scale_color, scene.measureit_scale_font,
text_rot=fang)
# --------------------
# Loop
# --------------------
ms = op.measureit_segments[idx]
if ovr is False:
fsize = ms.glfont_size
fang = get_angle_in_rad(ms.glfont_rotat)
faln = ms.glfont_align
else:
fsize = ovrfsize
fang = ovrfang
faln = ovrfaln
# ------------------------------
# only active and visible
# ------------------------------
if ms.glview is True and ms.glfree is False:
# Arrow data
a_size = ms.glarrow_s
a_type = ms.glarrow_a
b_type = ms.glarrow_b
# noinspection PyBroadException
try:
if ovr is False:
# ----------------------
# Segment or Label
# ----------------------
if ms.gltype == 1 or ms.gltype == 2:
obverts = get_mesh_vertices(myobj)
if ms.glpointa <= len(obverts) and ms.glpointb <= len(obverts):
a_p1 = get_point(obverts[ms.glpointa].co, myobj)
b_p1 = get_point(obverts[ms.glpointb].co, myobj)
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# ----------------------
# Segment or Label
# ----------------------
if ms.gltype == 12 or ms.gltype == 13 or ms.gltype == 14:
obverts = get_mesh_vertices(myobj)
if ms.glpointa <= len(obverts):
a_p1 = get_point(obverts[ms.glpointa].co, myobj)
if ms.gltype == 12: # X
b_p1 = get_point((0.0,
obverts[ms.glpointa].co[1],
obverts[ms.glpointa].co[2]), myobj)
elif ms.gltype == 13: # Y
b_p1 = get_point((obverts[ms.glpointa].co[0],
0.0,
obverts[ms.glpointa].co[2]), myobj)
else: # Z
b_p1 = get_point((obverts[ms.glpointa].co[0],
obverts[ms.glpointa].co[1],
0.0), myobj)
# ----------------------
# Vertex to Vertex (link)
# ----------------------
if ms.gltype == 3:
obverts = get_mesh_vertices(myobj)
linkverts = bpy.data.objects[ms.gllink].data.vertices
a_p1 = get_point(obverts[ms.glpointa].co, myobj)
b_p1 = get_point(linkverts[ms.glpointb].co, bpy.data.objects[ms.gllink])
# ----------------------
# Vertex to Object (link)
# ----------------------
if ms.gltype == 4:
obverts = get_mesh_vertices(myobj)
a_p1 = get_point(obverts[ms.glpointa].co, myobj)
b_p1 = get_location(bpy.data.objects[ms.gllink])
# ----------------------
# Object to Vertex (link)
# ----------------------
if ms.gltype == 5:
linkverts = bpy.data.objects[ms.gllink].data.vertices
a_p1 = get_location(myobj)
b_p1 = get_point(linkverts[ms.glpointb].co, bpy.data.objects[ms.gllink])
# ----------------------
# Object to Object (link)
# ----------------------
if ms.gltype == 8:
a_p1 = get_location(myobj)
b_p1 = get_location(bpy.data.objects[ms.gllink])
# ----------------------
# Vertex to origin
# ----------------------
if ms.gltype == 6:
obverts = get_mesh_vertices(myobj)
a_p1 = (0, 0, 0)
b_p1 = get_point(obverts[ms.glpointa].co, myobj)
# ----------------------
# Object to origin
# ----------------------
if ms.gltype == 7:
a_p1 = (0, 0, 0)
b_p1 = get_location(myobj)
# ----------------------
# Angle
# ----------------------
if ms.gltype == 9:
obverts = get_mesh_vertices(myobj)
if ms.glpointa <= len(obverts) and ms.glpointb <= len(obverts) and ms.glpointc <= len(obverts):
an_p1 = get_point(obverts[ms.glpointa].co, myobj)
an_p2 = get_point(obverts[ms.glpointb].co, myobj)
an_p3 = get_point(obverts[ms.glpointc].co, myobj)
ang_1 = Vector((an_p1[0] - an_p2[0], an_p1[1] - an_p2[1], an_p1[2] - an_p2[2]))
ang_2 = Vector((an_p3[0] - an_p2[0], an_p3[1] - an_p2[1], an_p3[2] - an_p2[2]))
ang_3 = ang_1 + ang_2 # Result vector
a_p1 = (an_p2[0], an_p2[1], an_p2[2])
b_p1 = (0, 0, 0)
# ----------------------
# Annotation
# ----------------------
if ms.gltype == 10:
a_p1 = get_location(myobj)
b_p1 = get_location(myobj)
# ----------------------
# Arc
# ----------------------
if ms.gltype == 11:
obverts = get_mesh_vertices(myobj)
if ms.glpointa <= len(obverts) and ms.glpointb <= len(obverts) and ms.glpointc <= len(obverts):
an_p1 = get_point(obverts[ms.glpointa].co, myobj)
an_p2 = get_point(obverts[ms.glpointb].co, myobj)
an_p3 = get_point(obverts[ms.glpointc].co, myobj)
# reference for maths: http://en.wikipedia.org/wiki/Circumscribed_circle
an_p12 = Vector((an_p1[0] - an_p2[0], an_p1[1] - an_p2[1], an_p1[2] - an_p2[2]))
an_p13 = Vector((an_p1[0] - an_p3[0], an_p1[1] - an_p3[1], an_p1[2] - an_p3[2]))
an_p21 = Vector((an_p2[0] - an_p1[0], an_p2[1] - an_p1[1], an_p2[2] - an_p1[2]))
an_p23 = Vector((an_p2[0] - an_p3[0], an_p2[1] - an_p3[1], an_p2[2] - an_p3[2]))
an_p31 = Vector((an_p3[0] - an_p1[0], an_p3[1] - an_p1[1], an_p3[2] - an_p1[2]))
an_p32 = Vector((an_p3[0] - an_p2[0], an_p3[1] - an_p2[1], an_p3[2] - an_p2[2]))
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
an_p12xp23 = an_p12.copy().cross(an_p23)
# radius = an_p12.length * an_p23.length * an_p31.length / (2 * an_p12xp23.length)
alpha = pow(an_p23.length, 2) * an_p12.dot(an_p13) / (2 * pow(an_p12xp23.length, 2))
beta = pow(an_p13.length, 2) * an_p21.dot(an_p23) / (2 * pow(an_p12xp23.length, 2))
gamma = pow(an_p12.length, 2) * an_p31.dot(an_p32) / (2 * pow(an_p12xp23.length, 2))
a_p1 = (alpha * an_p1[0] + beta * an_p2[0] + gamma * an_p3[0],
alpha * an_p1[1] + beta * an_p2[1] + gamma * an_p3[1],
alpha * an_p1[2] + beta * an_p2[2] + gamma * an_p3[2])
b_p1 = (an_p2[0], an_p2[1], an_p2[2])
a_n = an_p12.cross(an_p23)
a_n.normalize() # normal vector
arc_angle, arc_length = get_arc_data(an_p1, a_p1, an_p2, an_p3)
# Apply scale to arc_length
arc_length *= scene.measureit_scale_factor
# ----------------------
# Area
# ----------------------
if ms.gltype == 20:
a_p1 = get_location(myobj) # Not used
b_p1 = get_location(myobj) # Not used
# Calculate distance
dist, distloc = distance(a_p1, b_p1, ms.glocx, ms.glocy, ms.glocz)
# ------------------------------------
# get normal vector
# ------------------------------------
if ms.gldefault is True:
if ms.gltype == 9:
vn = ang_3 # if angle, vector is angle position
elif ms.gltype == 11:
vn = a_n # if arc, vector is perpendicular to surface of the three vertices
else:
loc = get_location(myobj)
midpoint3d = interpolate3d(a_p1, b_p1, fabs(dist / 2))
vn = Vector((midpoint3d[0] - loc[0],
midpoint3d[1] - loc[1],
midpoint3d[2] - loc[2]))
vn = Vector((ms.glnormalx, ms.glnormaly, ms.glnormalz))
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
vn.normalize()
# ------------------------------------
# position vector
# ------------------------------------
vi = vn * ms.glspace
s = (14 / 200)
if s > ms.glspace:
s = ms.glspace / 5
vi2 = vn * (ms.glspace + s)
# ------------------------------------
# apply vector
# ------------------------------------
v1 = [a_p1[0] + vi[0], a_p1[1] + vi[1], a_p1[2] + vi[2]]
v2 = [b_p1[0] + vi[0], b_p1[1] + vi[1], b_p1[2] + vi[2]]
# Segment extreme
v11 = [a_p1[0] + vi2[0], a_p1[1] + vi2[1], a_p1[2] + vi2[2]]
v22 = [b_p1[0] + vi2[0], b_p1[1] + vi2[1], b_p1[2] + vi2[2]]
# Labeling
v11a = (a_p1[0] + vi2[0], a_p1[1] + vi2[1], a_p1[2] + vi2[2] + s / 30)
v11b = (a_p1[0] + vi2[0], a_p1[1] + vi2[1], a_p1[2] + vi2[2] - s / 40)
# Annotation
vn1 = (a_p1[0], a_p1[1], a_p1[2])
# -------------------------------------------
# Orthogonal
# -------------------------------------------
if ms.gltype == 1 and ms.glorto != "99":
if ms.glorto == "0": # A
if ms.glorto_x is True:
v1[0] = v2[0]
v11[0] = v22[0]
if ms.glorto_y is True:
v1[1] = v2[1]
v11[1] = v22[1]
if ms.glorto_z is True:
v1[2] = v2[2]
v11[2] = v22[2]
if ms.glorto == "1": # B
if ms.glorto_x is True:
v2[0] = v1[0]
v22[0] = v11[0]
if ms.glorto_y is True:
v2[1] = v1[1]
v22[1] = v11[1]
if ms.glorto_z is True:
v2[2] = v1[2]
v22[2] = v11[2]
# ------------------------------------
# converting to screen coordinates
# ------------------------------------
screen_point_ap1 = get_2d_point(region, rv3d, a_p1)
screen_point_bp1 = get_2d_point(region, rv3d, b_p1)
screen_point_v1 = get_2d_point(region, rv3d, v1)
screen_point_v2 = get_2d_point(region, rv3d, v2)
screen_point_v11 = get_2d_point(region, rv3d, v11)
screen_point_v22 = get_2d_point(region, rv3d, v22)
screen_point_v11a = get_2d_point(region, rv3d, v11a)
screen_point_v11b = get_2d_point(region, rv3d, v11b)
# ------------------------------------
# colour + line setup
# ------------------------------------
if ovr is False:
imm_set_line_width(ms.glwidth)
imm_set_line_width(ovrline)
# ------------------------------------
# Text (distance)
# ------------------------------------
# noinspection PyBroadException
if ms.gltype != 2 and ms.gltype != 9 and ms.gltype != 10 and ms.gltype != 11 and ms.gltype != 20:
# noinspection PyBroadException
try:
midpoint3d = interpolate3d(v1, v2, fabs(dist / 2))
gap3d = (midpoint3d[0], midpoint3d[1], midpoint3d[2] + s / 2)
tmp_point = get_2d_point(region, rv3d, gap3d)
if tmp_point is None:
pass
txtpoint2d = tmp_point[0] + ms.glfontx, tmp_point[1] + ms.glfonty
# Scale
if scene.measureit_scale is True:
dist = dist * scene.measureit_scale_factor
distloc = distloc * scene.measureit_scale_factor
# decide dist to use
if dist == distloc:
locflag = False
usedist = dist
else:
usedist = distloc
locflag = True
# Apply scene scale
usedist *= scale
tx_dist = str(format_distance(fmt, units, usedist))
# -----------------------------------
# Draw text
# -----------------------------------
if scene.measureit_gl_show_d is True and ms.gldist is True:
msg = tx_dist + " "
else:
msg = " "
if scene.measureit_gl_show_n is True and ms.glnames is True:
msg += ms.gltxt
if scene.measureit_gl_show_d is True or scene.measureit_gl_show_n is True:
draw_text(myobj, txtpoint2d, msg, rgba, fsize, faln, fang)
# ------------------------------
# if axis loc, show a indicator
# ------------------------------
if locflag is True and ms.glocwarning is True:
txtpoint2d = get_2d_point(region, rv3d, (v2[0], v2[1], v2[2]))
txt = "["
if ms.glocx is True:
txt += "X"
if ms.glocy is True:
txt += "Y"
if ms.glocz is True:
txt += "Z"
txt += "]"
draw_text(myobj, txtpoint2d, txt, rgba, fsize - 1, text_rot=fang)
except:
pass
# ------------------------------------
# Text (label) and Angles
# ------------------------------------
# noinspection PyBroadException
if ms.gltype == 2 or ms.gltype == 9 or ms.gltype == 11:
tx_dist = ""
# noinspection PyBroadException
try:
if ms.gltype == 2:
tx_dist = ms.gltxt
if ms.gltype == 9: # Angles
ang = ang_1.angle(ang_2)
if bpy.context.scene.unit_settings.system_rotation == "DEGREES":
tx_dist = " " + fmt % ang
# Add degree symbol
if bpy.context.scene.unit_settings.system_rotation == "DEGREES":
tx_dist += a_code
if scene.measureit_gl_show_n is True:
tx_dist += " " + ms.gltxt
if ms.gltype == 11: # arc
# print length or arc and angle
if ms.glarc_len is True:
tx_dist = ms.glarc_txlen + format_distance(fmt, units, arc_length * scale)
else:
tx_dist = " "
if bpy.context.scene.unit_settings.system_rotation == "DEGREES":
else:
arc_d = arc_angle
if ms.glarc_ang is True:
tx_dist += " " + ms.glarc_txang + format_distance(fmt, 9, arc_d)
# Add degree symbol
if bpy.context.scene.unit_settings.system_rotation == "DEGREES":
tx_dist += a_code
if scene.measureit_gl_show_d is True and ms.gldist is True:
msg = tx_dist + " "
else:
msg = " "
if scene.measureit_gl_show_n is True and ms.glnames is True:
msg += ms.gltxt
if scene.measureit_gl_show_d is True or scene.measureit_gl_show_n is True:
# Normal vector
vna = Vector((b_p1[0] - a_p1[0],
b_p1[1] - a_p1[1],
b_p1[2] - a_p1[2]))
vna.normalize()
via = vna * ms.glspace
gap3d = (b_p1[0] + via[0], b_p1[1] + via[1], b_p1[2] + via[2])
tmp_point = get_2d_point(region, rv3d, gap3d)
if tmp_point is not None:
txtpoint2d = tmp_point[0] + ms.glfontx, tmp_point[1] + ms.glfonty
draw_text(myobj, txtpoint2d, msg, rgba, fsize, faln, fang)
# Radius
if scene.measureit_gl_show_d is True and ms.gldist is True and \
ms.glarc_rad is True:
tx_dist = ms.glarc_txradio + format_distance(fmt, units,
dist * scene.measureit_scale_factor * scale)
else:
tx_dist = " "
if ms.gltype == 2:
gap3d = (v11a[0], v11a[1], v11a[2])
else:
gap3d = (a_p1[0], a_p1[1], a_p1[2])
tmp_point = get_2d_point(region, rv3d, gap3d)
if tmp_point is not None:
txtpoint2d = tmp_point[0] + ms.glfontx, tmp_point[1] + ms.glfonty
draw_text(myobj, txtpoint2d, tx_dist, rgba, fsize, faln, fang)
except:
pass
# ------------------------------------
# Annotation
# ------------------------------------
# noinspection PyBroadException
if ms.gltype == 10:
# noinspection PyBroadException
tx_dist = ms.gltxt
gap3d = (vn1[0], vn1[1], vn1[2])
tmp_point = get_2d_point(region, rv3d, gap3d)
if tmp_point is not None:
txtpoint2d = tmp_point[0] + ms.glfontx, tmp_point[1] + ms.glfonty
draw_text(myobj, txtpoint2d, tx_dist, rgba, fsize, faln, fang)
# ------------------------------------
# Draw lines
# ------------------------------------
gpu.state.blend_set('ALPHA')
if ms.gltype == 1: # Segment
draw_line(screen_point_ap1, screen_point_v11, rgba)
draw_line(screen_point_bp1, screen_point_v22, rgba)
draw_arrow(screen_point_v1, screen_point_v2, rgba, a_size, a_type, b_type)
if ms.gltype == 12 or ms.gltype == 13 or ms.gltype == 14: # Segment to origin
draw_line(screen_point_ap1, screen_point_v11, rgba)
draw_line(screen_point_bp1, screen_point_v22, rgba)
draw_arrow(screen_point_v1, screen_point_v2, rgba, a_size, a_type, b_type)
if ms.gltype == 2: # Label
draw_line(screen_point_v11a, screen_point_v11b, rgba)
draw_arrow(screen_point_ap1, screen_point_v11, rgba, a_size, a_type, b_type)
if ms.gltype == 3 or ms.gltype == 4 or ms.gltype == 5 or ms.gltype == 8 \
or ms.gltype == 6 or ms.gltype == 7: # Origin and Links
draw_arrow(screen_point_ap1, screen_point_bp1, rgba, a_size, a_type, b_type)
if ms.gltype == 9: # Angle
dist, distloc = distance(an_p1, an_p2)
mp1 = interpolate3d(an_p1, an_p2, fabs(dist / 1.1))
dist, distloc = distance(an_p3, an_p2)
mp2 = interpolate3d(an_p3, an_p2, fabs(dist / 1.1))
screen_point_an_p1 = get_2d_point(region, rv3d, mp1)
screen_point_an_p2 = get_2d_point(region, rv3d, an_p2)
screen_point_an_p3 = get_2d_point(region, rv3d, mp2)
draw_line(screen_point_an_p1, screen_point_an_p2, rgba)
draw_line(screen_point_an_p2, screen_point_an_p3, rgba)
draw_line(screen_point_an_p1, screen_point_an_p3, rgba)
if ms.gltype == 11: # arc
# draw line from center of arc second point
if ms.glarc_rad is True:
if ms.glarc_extrad is False:
draw_arrow(screen_point_ap1, screen_point_bp1, rgba, a_size, a_type, b_type)
vne = Vector((b_p1[0] - a_p1[0],
b_p1[1] - a_p1[1],
b_p1[2] - a_p1[2]))
vne.normalize()
vie = vne * ms.glspace
pe = (b_p1[0] + vie[0], b_p1[1] + vie[1], b_p1[2] + vie[2])
screen_point_pe = get_2d_point(region, rv3d, pe)
draw_arrow(screen_point_ap1, screen_point_pe, rgba, a_size, a_type, b_type)
# create arc around the centerpoint
# rotation matrix around normal vector at center point
mat_trans1 = Matrix.Translation(-c)
# get step
n_step = 36.0
if ms.glarc_full is False:
step = arc_angle / n_step
else:
mat_rot1 = Matrix.Rotation(step, 4, vn)
mat_trans2 = Matrix.Translation(c)
p1 = Vector(an_p1) # first point of arc
# Normal vector
p1[1] - a_p1[1],
p1[2] - a_p1[2]))
vn.normalize()
vi = vn * ms.glspace
p_01a = None
p_01b = None
p_02a = None
p_02b = None
# draw the arc
p2 = mat_trans2 @ mat_rot1 @ mat_trans1 @ p1
p1_ = (p1[0] + vi[0], p1[1] + vi[1], p1[2] + vi[2])
# First Point
if i == 0:
p_01a = (p1_[0], p1_[1], p1_[2])
p_01b = (p1[0], p1[1], p1[2])
# Normal vector
p2[1] - a_p1[1],
p2[2] - a_p1[2]))
vn.normalize()
vi = vn * ms.glspace
p2_ = (p2[0] + vi[0], p2[1] + vi[1], p2[2] + vi[2])
# convert to screen coordinates
screen_point_p1 = get_2d_point(region, rv3d, p1_)
screen_point_p2 = get_2d_point(region, rv3d, p2_)
if i == 0:
draw_arrow(screen_point_p1, screen_point_p2, rgba, ms.glarc_s, ms.glarc_a, "99")
elif i == int(n_step) - 1:
draw_arrow(screen_point_p1, screen_point_p2, rgba, ms.glarc_s, "99", ms.glarc_b)
draw_line(screen_point_p1, screen_point_p2, rgba)
p1 = p2.copy()
# Last Point
if i == int(n_step) - 1:
p_02a = (p2_[0], p2_[1], p2_[2])
p_02b = (p2[0], p2[1], p2[2])
# Draw close lines
if ms.glarc_full is False:
screen_point_p1a = get_2d_point(region, rv3d, p_01a)
screen_point_p1b = get_2d_point(region, rv3d, p_01b)
screen_point_p2a = get_2d_point(region, rv3d, p_02a)
screen_point_p2b = get_2d_point(region, rv3d, p_02b)
draw_line(screen_point_p1a, screen_point_p1b, rgba)
draw_line(screen_point_p2a, screen_point_p2b, rgba)
if ms.gltype == 20: # Area
obverts = get_mesh_vertices(myobj)
tot = 0
if scene.measureit_scale is True:
ms_scale = scene.measureit_scale_factor
else:
ms_scale = 1.0
for face in ms.measureit_faces:
myvertices = []
for v in face.measureit_index:
area = get_area_and_paint(myvertices, myobj, obverts, region, rv3d, rgba, ms_scale)
tot += area
# Draw Area number over first face
if len(ms.measureit_faces) > 0:
face = ms.measureit_faces[0]
a = face.measureit_index[0].glidx
b = face.measureit_index[2].glidx
p1 = get_point(obverts[a].co, myobj)
p2 = get_point(obverts[b].co, myobj)
d1, dn = distance(p1, p2)
midpoint3d = interpolate3d(p1, p2, fabs(d1 / 2))
# mult by world scale
tot *= scale
tx_dist = str(format_distance(fmt, units, tot, 2))
# -----------------------------------
# Draw text
# -----------------------------------
if scene.measureit_gl_show_d is True and ms.gldist is True:
msg = tx_dist + " "
else:
msg = " "
if scene.measureit_gl_show_n is True and ms.glnames is True:
msg += ms.gltxt
if scene.measureit_gl_show_d is True or scene.measureit_gl_show_n is True:
tmp_point = get_2d_point(region, rv3d, midpoint3d)
if tmp_point is not None:
txtpoint2d = tmp_point[0] + ms.glfontx, tmp_point[1] + ms.glfonty
# todo: swap ms.glcolorarea with ms.glcolor ?
draw_text(myobj, txtpoint2d, msg, ms.glcolorarea, fsize, faln, fang)
except IndexError:
ms.glfree = True
except:
print("Unexpected error:" + str(exc_info()))
pass
return
# ------------------------------------------
# Get polygon area and paint area
#
# ------------------------------------------
def get_area_and_paint(myvertices, myobj, obverts, region, rv3d, rgba, ms_scale):
mymesh = myobj.data
totarea = 0
if len(myvertices) > 3:
# Tessellate the polygon
if myobj.mode != 'EDIT':
tris = mesh_utils.ngon_tessellate(mymesh, myvertices)
else:
myv = []
for v in bm.verts:
tris = mesh_utils.ngon_tessellate(myv, myvertices)
for t in tris:
v1, v2, v3 = t
p1 = get_point(obverts[myvertices[v1]].co, myobj)
p2 = get_point(obverts[myvertices[v2]].co, myobj)
p3 = get_point(obverts[myvertices[v3]].co, myobj)
screen_point_p1 = get_2d_point(region, rv3d, p1)
screen_point_p2 = get_2d_point(region, rv3d, p2)
screen_point_p3 = get_2d_point(region, rv3d, p3)
draw_triangle(screen_point_p1, screen_point_p2, screen_point_p3, rgba)
# Area
area = get_triangle_area(p1, p2, p3, ms_scale)
totarea += area
elif len(myvertices) == 3:
v1, v2, v3 = myvertices
p1 = get_point(obverts[v1].co, myobj)
p2 = get_point(obverts[v2].co, myobj)
p3 = get_point(obverts[v3].co, myobj)
screen_point_p1 = get_2d_point(region, rv3d, p1)
screen_point_p2 = get_2d_point(region, rv3d, p2)
screen_point_p3 = get_2d_point(region, rv3d, p3)
draw_triangle(screen_point_p1, screen_point_p2, screen_point_p3, rgba)
# Area
area = get_triangle_area(p1, p2, p3, ms_scale)
totarea += area
else:
return 0.0
# Apply world scale
totarea *= bpy.context.scene.unit_settings.scale_length
return totarea
# ------------------------------------------
# Get area using Heron formula
#
# ------------------------------------------
def get_triangle_area(p1, p2, p3, scale=1.0):
d1, dn = distance(p1, p2)
d2, dn = distance(p2, p3)
d3, dn = distance(p1, p3)
d1 *= scale
d2 *= scale
d3 *= scale
per = (d1 + d2 + d3) / 2.0
area = sqrt(per * (per - d1) * (per - d2) * (per - d3))
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
return area
# ------------------------------------------
# Get point in 2d space
#
# ------------------------------------------
def get_2d_point(region, rv3d, point3d):
if rv3d is not None and region is not None:
return view3d_utils.location_3d_to_region_2d(region, rv3d, point3d)
else:
return get_render_location(point3d)
# -------------------------------------------------------------
# Get sum of a group
#
# myobj: Current object
# Tag: group
# -------------------------------------------------------------
def get_group_sum(myobj, tag):
# noinspection PyBroadException
try:
tx = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
"T", "U", "V", "W", "X", "Y", "Z"]
g = tag[2:3]
mp = myobj.MeasureGenerator[0]
flag = False
# -----------------
# Sum loop segments
# -----------------
scale = bpy.context.scene.unit_settings.scale_length
tot = 0.0
obverts = get_mesh_vertices(myobj)
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
ms = mp.measureit_segments[idx]
if (ms.gltype == 1 or ms.gltype == 12 or
ms.gltype == 13 or ms.gltype == 14) and ms.gltot != '99' \
and ms.glfree is False and g == tx[int(ms.gltot)]: # only segments
if ms.glpointa <= len(obverts) and ms.glpointb <= len(obverts):
p1 = get_point(obverts[ms.glpointa].co, myobj)
if ms.gltype == 1:
p2 = get_point(obverts[ms.glpointb].co, myobj)
elif ms.gltype == 12:
p2 = get_point((0.0,
obverts[ms.glpointa].co[1],
obverts[ms.glpointa].co[2]), myobj)
elif ms.gltype == 13:
p2 = get_point((obverts[ms.glpointa].co[0],
0.0,
obverts[ms.glpointa].co[2]), myobj)
else:
p2 = get_point((obverts[ms.glpointa].co[0],
obverts[ms.glpointa].co[1],
0.0), myobj)
dist, distloc = distance(p1, p2, ms.glocx, ms.glocy, ms.glocz)
if dist == distloc:
usedist = dist
else:
usedist = distloc
usedist *= scale
tot += usedist
flag = True
if flag is True:
# Return value
pr = bpy.context.scene.measureit_gl_precision
fmt = "%1." + str(pr) + "f"
units = bpy.context.scene.measureit_units
return format_distance(fmt, units, tot)
else:
return " "
except:
return " "
# -------------------------------------------------------------
# Create OpenGL text
#
# -------------------------------------------------------------
def draw_text(myobj, pos2d, display_text, rgba, fsize, align='L', text_rot=0.0):
if pos2d is None:
return
# dpi = bpy.context.preferences.system.dpi
gap = 12
font_id = 0
ui_scale = bpy.context.preferences.system.ui_scale
blf.size(font_id, round(fsize * ui_scale), 72)
# blf.size(font_id, fsize, dpi)
# height of one line
mwidth, mheight = blf.dimensions(font_id, "Tp") # uses high/low letters
# Calculate sum groups
m = 0
while "<#" in display_text:
m += 1
if m > 10: # limit loop
break
i = display_text.index("<#")
tag = display_text[i:i + 4]
display_text = display_text.replace(tag, get_group_sum(myobj, tag.upper()))
# split lines
mylines = display_text.split("|")
idx = len(mylines) - 1
maxwidth = 0
maxheight = len(mylines) * mheight
# -------------------
# Draw all lines
# -------------------
for line in mylines:
text_width, text_height = blf.dimensions(font_id, line)
newx = x_pos - text_width / 2
newx = x_pos - text_width - gap
else:
newx = x_pos
blf.enable(font_id, ROTATION)
blf.rotation(font_id, text_rot)
# calculate new Y position
new_y = y_pos + (mheight * idx)
# Draw
blf.position(font_id, newx, new_y, 0)
blf.color(font_id, rgba[0], rgba[1], rgba[2], rgba[3])
blf.draw(font_id, " " + line)
# sub line
idx -= 1
# saves max width
if maxwidth < text_width:
maxwidth = text_width
blf.disable(font_id, ROTATION)
return maxwidth, maxheight
# -------------------------------------------------------------
# Draw an OpenGL line
#
# -------------------------------------------------------------
coords = [(v1[0], v1[1], 0), (v2[0], v2[1], 0)]
batch = batch_for_shader(shader_line, 'LINES', {"pos": coords})
# noinspection PyBroadException
try:
if v1 is not None and v2 is not None:
shader_line.bind()
shader_line.uniform_float("color", rgba)
shader_line.uniform_float("lineWidth", imm_line_width)
shader_line.uniform_float("viewportSize", imm_viewport)
batch.draw(shader_line)
except:
pass
# -------------------------------------------------------------
# Draw an OpenGL triangle
#
# -------------------------------------------------------------
def draw_triangle(v1, v2, v3, rgba):
coords = [(v1[0], v1[1]), (v2[0], v2[1]), (v3[0], v3[1])]
batch = batch_for_shader(shader, 'TRIS', {"pos": coords})
# noinspection PyBroadException
try:
if v1 is not None and v2 is not None and v3 is not None:
shader.bind()
shader.uniform_float("color", rgba)
batch.draw(shader)
except:
pass
# -------------------------------------------------------------
# Draw an Arrow
#
# -------------------------------------------------------------
def draw_arrow(v1, v2, rgba, size=20, a_typ="1", b_typ="1"):
if v1 is None or v2 is None:
return
rad45 = radians(45)
rad315 = radians(315)
rad90 = radians(90)
rad270 = radians(270)
v = interpolate3d((v1[0], v1[1], 0.0), (v2[0], v2[1], 0.0), size)
v1i = (v[0] - v1[0], v[1] - v1[1])
v = interpolate3d((v2[0], v2[1], 0.0), (v1[0], v1[1], 0.0), size)
v2i = (v[0] - v2[0], v[1] - v2[1])
# Point A
if a_typ == "3":
rad_a = rad90
rad_b = rad270
else:
rad_a = rad45
rad_b = rad315
v1a = (int(v1i[0] * cos(rad_a) - v1i[1] * sin(rad_a) + v1[0]),
int(v1i[1] * cos(rad_a) + v1i[0] * sin(rad_a)) + v1[1])
v1b = (int(v1i[0] * cos(rad_b) - v1i[1] * sin(rad_b) + v1[0]),
int(v1i[1] * cos(rad_b) + v1i[0] * sin(rad_b) + v1[1]))
# Point B
if b_typ == "3":
rad_a = rad90
rad_b = rad270
else:
rad_a = rad45
rad_b = rad315
v2a = (int(v2i[0] * cos(rad_a) - v2i[1] * sin(rad_a) + v2[0]),
int(v2i[1] * cos(rad_a) + v2i[0] * sin(rad_a)) + v2[1])
v2b = (int(v2i[0] * cos(rad_b) - v2i[1] * sin(rad_b) + v2[0]),
int(v2i[1] * cos(rad_b) + v2i[0] * sin(rad_b) + v2[1]))
# Triangle o Lines
if a_typ == "1" or a_typ == "3":
draw_line(v1, v1a, rgba)
draw_line(v1, v1b, rgba)
if b_typ == "1" or b_typ == "3":
draw_line(v2, v2a, rgba)
draw_line(v2, v2b, rgba)
if a_typ == "2":
draw_triangle(v1, v1a, v1b, rgba)
if b_typ == "2":
draw_triangle(v2, v2a, v2b, rgba)
# -------------------------------------------------------------
# Draw an OpenGL Rectangle
#
# v1, v2 are corners (bottom left / top right)
# -------------------------------------------------------------
def draw_rectangle(v1, v2, rgba):
# noinspection PyBroadException
try:
if v1 is not None and v2 is not None:
v1b = (v2[0], v1[1])
v2b = (v1[0], v2[1])
draw_line(v1, v1b, rgba)
draw_line(v1b, v2, rgba)
draw_line(v2, v2b, rgba)
draw_line(v2b, v1, rgba)
except:
pass
# -------------------------------------------------------------
# format a point as (x, y, z) for display
#
# -------------------------------------------------------------
def format_point(mypoint, pr):
pf = "%1." + str(pr) + "f"
fmt = " ("
fmt += pf % mypoint[0]
fmt += ", "
fmt += pf % mypoint[1]
fmt += ", "
fmt += pf % mypoint[2]
fmt += ")"