Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormeta-androcto <meta.androcto1@gmail.com>2016-08-03 03:47:46 +0300
committermeta-androcto <meta.androcto1@gmail.com>2016-08-03 03:47:46 +0300
commitcf4ac00ea0aabfbc1c84b085c53991862003f5ae (patch)
tree6f145d6cb875e314ee2f2672d213b36087641927 /measureit/measureit_geometry.py
parent5cd9040c995effc4c6bf233e820f741cbaf083ca (diff)
add mesureit to release "warning temporary status" pending T48704
Diffstat (limited to 'measureit/measureit_geometry.py')
-rw-r--r--measureit/measureit_geometry.py1350
1 files changed, 1350 insertions, 0 deletions
diff --git a/measureit/measureit_geometry.py b/measureit/measureit_geometry.py
new file mode 100644
index 00000000..c8c6170d
--- /dev/null
+++ b/measureit/measureit_geometry.py
@@ -0,0 +1,1350 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# <pep8 compliant>
+
+# ----------------------------------------------------------
+# support routines for OpenGL
+# Author: Antonio Vazquez (antonioya)
+#
+# ----------------------------------------------------------
+# noinspection PyUnresolvedReferences
+import bpy
+# noinspection PyUnresolvedReferences
+import bgl
+# noinspection PyUnresolvedReferences
+import blf
+import math
+# noinspection PyUnresolvedReferences
+import mathutils
+# noinspection PyUnresolvedReferences
+import bmesh
+# noinspection PyUnresolvedReferences
+from bpy_extras import view3d_utils, mesh_utils
+# noinspection PyUnresolvedReferences
+import bpy_extras.object_utils as object_utils
+import sys
+
+
+# -------------------------------------------------------------
+# Draw segments
+#
+# rgb: Color
+# fsize: Font size
+# -------------------------------------------------------------
+# 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
+ ovrline = scene.measureit_ovr_width
+ units = scene.measureit_units
+ # --------------------
+ # Scene Scale
+ # --------------------
+ if scene.measureit_scale is True:
+ prs = scene.measureit_scale_precision
+ fmts = "%1." + str(prs) + "f"
+ pos_x, pos_y = get_scale_txt_location(context)
+ tx_dsp = fmts % scene.measureit_scale_factor
+ tx_scale = scene.measureit_gl_scaletxt + " 1:" + tx_dsp
+ draw_text(myobj, pos_x, pos_y,
+ tx_scale, scene.measureit_scale_color, scene.measureit_scale_font)
+ # --------------------
+ # Loop
+ # --------------------
+ for idx in range(0, op.measureit_num):
+ ms = op.measureit_segments[idx]
+ if ovr is False:
+ fsize = ms.glfont_size
+ else:
+ fsize = ovrfsize
+ # ------------------------------
+ # 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:
+ rgb = ms.glcolor
+ else:
+ rgb = ovrcolor
+ # ----------------------
+ # 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)
+ # ----------------------
+ # 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 = mathutils.Vector((an_p1[0] - an_p2[0], an_p1[1] - an_p2[1], an_p1[2] - an_p2[2]))
+ ang_2 = mathutils.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 = mathutils.Vector((an_p1[0] - an_p2[0], an_p1[1] - an_p2[1], an_p1[2] - an_p2[2]))
+ an_p13 = mathutils.Vector((an_p1[0] - an_p3[0], an_p1[1] - an_p3[1], an_p1[2] - an_p3[2]))
+ an_p21 = mathutils.Vector((an_p2[0] - an_p1[0], an_p2[1] - an_p1[1], an_p2[2] - an_p1[2]))
+ an_p23 = mathutils.Vector((an_p2[0] - an_p3[0], an_p2[1] - an_p3[1], an_p2[2] - an_p3[2]))
+ an_p31 = mathutils.Vector((an_p3[0] - an_p1[0], an_p3[1] - an_p1[1], an_p3[2] - an_p1[2]))
+ an_p32 = mathutils.Vector((an_p3[0] - an_p2[0], an_p3[1] - an_p2[1], an_p3[2] - an_p2[2]))
+ 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, math.fabs(dist / 2))
+ vn = mathutils.Vector((midpoint3d[0] - loc[0],
+ midpoint3d[1] - loc[1],
+ midpoint3d[2] - loc[2]))
+ else:
+ vn = mathutils.Vector((ms.glnormalx, ms.glnormaly, ms.glnormalz))
+
+ 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:
+ bgl.glLineWidth(ms.glwidth)
+ else:
+ bgl.glLineWidth(ovrline)
+
+ bgl.glColor4f(rgb[0], rgb[1], rgb[2], rgb[3])
+
+ # ------------------------------------
+ # 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, math.fabs(dist / 2))
+ gap3d = (midpoint3d[0], midpoint3d[1], midpoint3d[2] + s / 2)
+ txtpoint2d = get_2d_point(region, rv3d, gap3d)
+ # 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[0] + ms.glfontx, txtpoint2d[1] + ms.glfonty,
+ msg, rgb, fsize)
+
+ # ------------------------------
+ # 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[0], txtpoint2d[1], txt, rgb, fsize - 1)
+
+ except:
+ pass
+ # ------------------------------------
+ # Text (label) and Angles
+ # ------------------------------------
+ # noinspection PyBroadException
+ if ms.gltype == 2 or ms.gltype == 9 or ms.gltype == 11:
+ right = False
+ tx_dist = ""
+ # noinspection PyBroadException
+ try:
+ if ms.gltype == 2:
+ tx_dist = ms.gltxt
+ right = False
+ if ms.gltype == 9: # Angles
+ ang = ang_1.angle(ang_2)
+ right = True
+ if bpy.context.scene.unit_settings.system_rotation == "DEGREES":
+ ang = math.degrees(ang)
+
+ 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
+ right = True
+ # print length or arc and angle
+ if ms.glarc_len is True:
+ tx_dist = ms.glarc_txlen + format_distance(fmt, units, arc_length)
+ else:
+ tx_dist = " "
+
+ if bpy.context.scene.unit_settings.system_rotation == "DEGREES":
+ arc_d = math.degrees(arc_angle)
+ 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 = mathutils.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])
+ txtpoint2d = get_2d_point(region, rv3d, gap3d)
+ draw_text(myobj, txtpoint2d[0] + ms.glfontx, txtpoint2d[1] + ms.glfonty, msg, rgb,
+ fsize, right)
+ # 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)
+ 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])
+
+ txtpoint2d = get_2d_point(region, rv3d, gap3d)
+ draw_text(myobj, txtpoint2d[0] + ms.glfontx, txtpoint2d[1] + ms.glfonty, tx_dist, rgb,
+ fsize, right)
+ except:
+ pass
+ # ------------------------------------
+ # Annotation
+ # ------------------------------------
+ # noinspection PyBroadException
+ if ms.gltype == 10:
+ # noinspection PyBroadException
+ try:
+ tx_dist = ms.gltxt
+ gap3d = (vn1[0], vn1[1], vn1[2])
+ txtpoint2d = get_2d_point(region, rv3d, gap3d)
+ draw_text(myobj, txtpoint2d[0] + ms.glfontx, txtpoint2d[1] + ms.glfonty,
+ tx_dist, rgb, fsize)
+ except:
+ pass
+ # ------------------------------------
+ # Draw lines
+ # ------------------------------------
+ bgl.glEnable(bgl.GL_BLEND)
+ bgl.glColor4f(rgb[0], rgb[1], rgb[2], rgb[3])
+
+ if ms.gltype == 1: # Segment
+ draw_line(screen_point_ap1, screen_point_v11)
+ draw_line(screen_point_bp1, screen_point_v22)
+ draw_arrow(screen_point_v1, screen_point_v2, 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)
+ draw_line(screen_point_bp1, screen_point_v22)
+ draw_arrow(screen_point_v1, screen_point_v2, a_size, a_type, b_type)
+
+ if ms.gltype == 2: # Label
+ draw_line(screen_point_v11a, screen_point_v11b)
+ draw_arrow(screen_point_ap1, screen_point_v11, 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, a_size, a_type, b_type)
+
+ if ms.gltype == 9: # Angle
+ dist, distloc = distance(an_p1, an_p2)
+ mp1 = interpolate3d(an_p1, an_p2, math.fabs(dist / 1.1))
+
+ dist, distloc = distance(an_p3, an_p2)
+ mp2 = interpolate3d(an_p3, an_p2, math.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)
+ draw_line(screen_point_an_p2, screen_point_an_p3)
+ draw_line(screen_point_an_p1, screen_point_an_p3)
+
+ if ms.gltype == 11: # arc
+ # draw line from center of arc second point
+ c = mathutils.Vector(a_p1)
+ if ms.glarc_rad is True:
+ if ms.glarc_extrad is False:
+ draw_arrow(screen_point_ap1, screen_point_bp1, a_size, a_type, b_type)
+ else:
+ vne = mathutils.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, a_size, a_type, b_type)
+
+ # create arc around the centerpoint
+ # rotation matrix around normal vector at center point
+ mat_trans1 = mathutils.Matrix.Translation(-c)
+ # get step
+ n_step = 36.0
+ if ms.glarc_full is False:
+ step = arc_angle / n_step
+ else:
+ step = math.radians(360.0) / n_step
+ #
+ mat_rot1 = mathutils.Matrix.Rotation(step, 4, vn)
+ mat_trans2 = mathutils.Matrix.Translation(c)
+ p1 = mathutils.Vector(an_p1) # first point of arc
+ # Normal vector
+ vn = mathutils.Vector((p1[0] - a_p1[0],
+ 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
+ for i in range(0, int(n_step)):
+ 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
+ vn = mathutils.Vector((p2[0] - a_p1[0],
+ 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, ms.glarc_s, ms.glarc_a, "99")
+ elif i == int(n_step) - 1:
+ draw_arrow(screen_point_p1, screen_point_p2, ms.glarc_s, "99", ms.glarc_b)
+ else:
+ draw_line(screen_point_p1, screen_point_p2)
+
+ 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)
+ draw_line(screen_point_p2a, screen_point_p2b)
+
+ if ms.gltype == 20: # Area
+ obverts = get_mesh_vertices(myobj)
+ tot = 0
+ for face in ms.measureit_faces:
+ myvertices = []
+ for v in face.measureit_index:
+ myvertices.extend([v.glidx])
+
+ area = get_area_and_paint(myvertices, myobj, obverts, region, rv3d)
+ 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, math.fabs(d1 / 2))
+ txtpoint2d = get_2d_point(region, rv3d, midpoint3d)
+ # Scale
+ if scene.measureit_scale is True:
+ tot = tot * scene.measureit_scale_factor
+
+ # 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:
+ draw_text(myobj, txtpoint2d[0] + ms.glfontx, txtpoint2d[1] + ms.glfonty,
+ msg, ms.glcolorarea,
+ fsize)
+
+ except IndexError:
+ ms.glfree = True
+ except:
+ # print("Unexpected error:" + str(sys.exc_info()))
+ # if error, disable segment
+ pass
+
+ return
+
+
+# ------------------------------------------
+# Get polygon area and paint area
+#
+# ------------------------------------------
+def get_area_and_paint(myvertices, myobj, obverts, region, rv3d):
+ mymesh = myobj.data
+ totarea = 0
+ if len(myvertices) > 3:
+ # Tessellate the polygon
+ if myobj.mode != 'EDIT':
+ tris = mesh_utils.ngon_tessellate(mymesh, myvertices)
+ else:
+ bm = bmesh.from_edit_mesh(myobj.data)
+ myv = []
+ for v in bm.verts:
+ myv.extend([v.co])
+ 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)
+
+ # Area
+ area = get_triangle_area(p1, p2, p3)
+
+ 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)
+
+ # Area
+ area = get_triangle_area(p1, p2, p3)
+ totarea += area
+ else:
+ return 0.0
+
+ return totarea
+
+
+# ------------------------------------------
+# Get area using Heron formula
+#
+# ------------------------------------------
+def get_triangle_area(p1, p2, p3):
+ d1, dn = distance(p1, p2)
+ d2, dn = distance(p2, p3)
+ d3, dn = distance(p1, p3)
+ per = (d1 + d2 + d3) / 2.0
+ area = math.sqrt(per * (per - d1) * (per - d2) * (per - d3))
+ 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)
+ for idx in range(0, mp.measureit_num):
+ 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
+#
+# right: Align to right
+# -------------------------------------------------------------
+def draw_text(myobj, x_pos, y_pos, display_text, rgb, fsize, right=False):
+ gap = 12
+ font_id = 0
+ blf.size(font_id, fsize, 72)
+ # 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)
+ if right is True:
+ newx = x_pos - text_width - gap
+ else:
+ newx = x_pos
+ # calculate new Y position
+ new_y = y_pos + (mheight * idx)
+ # Draw
+ blf.position(font_id, newx, new_y, 0)
+ bgl.glColor4f(rgb[0], rgb[1], rgb[2], rgb[3])
+ blf.draw(font_id, " " + line)
+ # sub line
+ idx -= 1
+ # saves max width
+ if maxwidth < text_width:
+ maxwidth = text_width
+
+ return maxwidth, maxheight
+
+
+# -------------------------------------------------------------
+# Draw an OpenGL line
+#
+# -------------------------------------------------------------
+def draw_line(v1, v2):
+ # noinspection PyBroadException
+ try:
+ if v1 is not None and v2 is not None:
+ bgl.glBegin(bgl.GL_LINES)
+ bgl.glVertex2f(*v1)
+ bgl.glVertex2f(*v2)
+ bgl.glEnd()
+ except:
+ pass
+
+
+# -------------------------------------------------------------
+# Draw an OpenGL triangle
+#
+# -------------------------------------------------------------
+def draw_triangle(v1, v2, v3):
+ # noinspection PyBroadException
+ try:
+ if v1 is not None and v2 is not None and v3 is not None:
+ bgl.glBegin(bgl.GL_TRIANGLES)
+ bgl.glVertex2f(*v1)
+ bgl.glVertex2f(*v2)
+ bgl.glVertex2f(*v3)
+ bgl.glEnd()
+ except:
+ pass
+
+
+# -------------------------------------------------------------
+# Draw an Arrow
+#
+# -------------------------------------------------------------
+def draw_arrow(v1, v2, size=20, a_typ="1", b_typ="1"):
+
+ rad45 = math.radians(45)
+ rad315 = math.radians(315)
+ rad90 = math.radians(90)
+ rad270 = math.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] * math.cos(rad_a) - v1i[1] * math.sin(rad_a) + v1[0]),
+ int(v1i[1] * math.cos(rad_a) + v1i[0] * math.sin(rad_a)) + v1[1])
+ v1b = (int(v1i[0] * math.cos(rad_b) - v1i[1] * math.sin(rad_b) + v1[0]),
+ int(v1i[1] * math.cos(rad_b) + v1i[0] * math.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] * math.cos(rad_a) - v2i[1] * math.sin(rad_a) + v2[0]),
+ int(v2i[1] * math.cos(rad_a) + v2i[0] * math.sin(rad_a)) + v2[1])
+ v2b = (int(v2i[0] * math.cos(rad_b) - v2i[1] * math.sin(rad_b) + v2[0]),
+ int(v2i[1] * math.cos(rad_b) + v2i[0] * math.sin(rad_b) + v2[1]))
+
+ # Triangle o Lines
+ if a_typ == "1" or a_typ == "3":
+ draw_line(v1, v1a)
+ draw_line(v1, v1b)
+
+ if b_typ == "1" or b_typ == "3":
+ draw_line(v2, v2a)
+ draw_line(v2, v2b)
+
+ if a_typ == "2":
+ draw_triangle(v1, v1a, v1b)
+ if b_typ == "2":
+ draw_triangle(v2, v2a, v2b)
+
+ draw_line(v1, v2)
+
+
+# -------------------------------------------------------------
+# Draw an OpenGL Rectangle
+#
+# v1, v2 are corners (bottom left / top right)
+# -------------------------------------------------------------
+def draw_rectangle(v1, v2):
+ # 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)
+ draw_line(v1b, v2)
+ draw_line(v2, v2b)
+ draw_line(v2b, v1)
+ 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 += ")"
+
+ return fmt
+
+
+# -------------------------------------------------------------
+# Draw vertex num for debug
+#
+# -------------------------------------------------------------
+# noinspection PyUnresolvedReferences,PyUnboundLocalVariable,PyUnusedLocal
+def draw_vertices(context, myobj, region, rv3d):
+ # Only meshes
+ if myobj.type != "MESH":
+ return
+
+ scene = bpy.context.scene
+ rgb = scene.measureit_debug_color
+ fsize = scene.measureit_debug_font
+ precision = scene.measureit_debug_precision
+ # --------------------
+ # vertex Loop
+ # --------------------
+ if myobj.mode == 'EDIT':
+ bm = bmesh.from_edit_mesh(myobj.data)
+ obverts = bm.verts
+ else:
+ obverts = myobj.data.vertices
+
+ for v in obverts:
+ # Display only selected
+ if scene.measureit_debug_select is True:
+ if v.select is False:
+ continue
+ # noinspection PyBroadException
+ try:
+ a_p1 = get_point(v.co, myobj)
+ # colour
+ bgl.glColor4f(rgb[0], rgb[1], rgb[2], rgb[3])
+ # converting to screen coordinates
+ txtpoint2d = get_2d_point(region, rv3d, a_p1)
+ # Text
+ txt = str(v.index)
+ if scene.measureit_debug_location is True:
+ txt += format_point(v.co, precision)
+ draw_text(myobj, txtpoint2d[0], txtpoint2d[1], txt, rgb, fsize)
+ except:
+ print("Unexpected error:" + str(sys.exc_info()))
+ pass
+
+ return
+
+
+# -------------------------------------------------------------
+# Draw face num for debug
+#
+# -------------------------------------------------------------
+# noinspection PyUnresolvedReferences,PyUnboundLocalVariable,PyUnusedLocal
+def draw_faces(context, myobj, region, rv3d):
+ # Only meshes
+ if myobj.type != "MESH":
+ return
+
+ scene = bpy.context.scene
+ rgb = scene.measureit_debug_color2
+ rgb2 = scene.measureit_debug_color3
+ fsize = scene.measureit_debug_font
+ ln = scene.measureit_debug_normal_size
+ th = scene.measureit_debug_width
+ precision = scene.measureit_debug_precision
+
+ # --------------------
+ # face Loop
+ # --------------------
+ if myobj.mode == 'EDIT':
+ bm = bmesh.from_edit_mesh(myobj.data)
+ obverts = bm.verts
+ myfaces = bm.faces
+ else:
+ obverts = myobj.data.vertices
+ myfaces = myobj.data.polygons
+
+ for f in myfaces:
+ normal = f.normal
+ # Display only selected
+ if scene.measureit_debug_select is True:
+ if f.select is False:
+ continue
+ # noinspection PyBroadException
+ try:
+ if myobj.mode == 'EDIT':
+ a_p1 = get_point(f.calc_center_median(), myobj)
+ else:
+ a_p1 = get_point(f.center, myobj)
+
+ a_p2 = (a_p1[0] + normal[0] * ln, a_p1[1] + normal[1] * ln, a_p1[2] + normal[2] * ln)
+ # colour + line setup
+ bgl.glEnable(bgl.GL_BLEND)
+ bgl.glLineWidth(th)
+ bgl.glColor4f(rgb[0], rgb[1], rgb[2], rgb[3])
+ # converting to screen coordinates
+ txtpoint2d = get_2d_point(region, rv3d, a_p1)
+ point2 = get_2d_point(region, rv3d, a_p2)
+ # Text
+ if scene.measureit_debug_faces is True:
+ draw_text(myobj, txtpoint2d[0], txtpoint2d[1], str(f.index), rgb, fsize)
+ # Draw Normal
+ if scene.measureit_debug_normals is True:
+ bgl.glEnable(bgl.GL_BLEND)
+ bgl.glColor4f(rgb2[0], rgb2[1], rgb2[2], rgb2[3])
+ draw_arrow(txtpoint2d, point2, 10, "99", "1")
+
+ if len(obverts) > 2 and scene.measureit_debug_normal_details is True:
+ if myobj.mode == 'EDIT':
+ i1 = f.verts[0].index
+ i2 = f.verts[1].index
+ i3 = f.verts[2].index
+ else:
+ i1 = f.vertices[0]
+ i2 = f.vertices[1]
+ i3 = f.vertices[2]
+
+ a_p1 = get_point(obverts[i1].co, myobj)
+ a_p2 = get_point(obverts[i2].co, myobj)
+ a_p3 = get_point(obverts[i3].co, myobj)
+ # converting to screen coordinates
+ a2d = get_2d_point(region, rv3d, a_p1)
+ b2d = get_2d_point(region, rv3d, a_p2)
+ c2d = get_2d_point(region, rv3d, a_p3)
+ # draw vectors
+ draw_arrow(a2d, b2d, 10, "99", "1")
+ draw_arrow(b2d, c2d, 10, "99", "1")
+ # Normal vector data
+ txt = format_point(normal, precision)
+ draw_text(myobj, point2[0], point2[1], txt, rgb2, fsize)
+
+ except:
+ print("Unexpected error:" + str(sys.exc_info()))
+ pass
+
+ return
+
+
+# --------------------------------------------------------------------
+# Distance between 2 points in 3D space
+# v1: first point
+# v2: second point
+# locx/y/z: Use this axis
+# return: distance
+# --------------------------------------------------------------------
+def distance(v1, v2, locx=True, locy=True, locz=True):
+ x = math.sqrt((v2[0] - v1[0]) ** 2 + (v2[1] - v1[1]) ** 2 + (v2[2] - v1[2]) ** 2)
+
+ # If axis is not used, make equal both (no distance)
+ v1b = [v1[0], v1[1], v1[2]]
+ v2b = [v2[0], v2[1], v2[2]]
+ if locx is False:
+ v2b[0] = v1b[0]
+ if locy is False:
+ v2b[1] = v1b[1]
+ if locz is False:
+ v2b[2] = v1b[2]
+
+ xloc = math.sqrt((v2b[0] - v1b[0]) ** 2 + (v2b[1] - v1b[1]) ** 2 + (v2b[2] - v1b[2]) ** 2)
+
+ return x, xloc
+
+
+# --------------------------------------------------------------------
+# Interpolate 2 points in 3D space
+# v1: first point
+# v2: second point
+# d1: distance
+# return: interpolate point
+# --------------------------------------------------------------------
+def interpolate3d(v1, v2, d1):
+ # calculate vector
+ v = (v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2])
+ # calculate distance between points
+ d0, dloc = distance(v1, v2)
+
+ # calculate interpolate factor (distance from origin / distance total)
+ # if d1 > d0, the point is projected in 3D space
+ if d0 > 0:
+ x = d1 / d0
+ else:
+ x = d1
+
+ final = (v1[0] + (v[0] * x), v1[1] + (v[1] * x), v1[2] + (v[2] * x))
+ return final
+
+
+# --------------------------------------------------------------------
+# Get point rotated and relative to parent
+# v1: point
+# mainobject
+# --------------------------------------------------------------------
+def get_point(v1, mainobject):
+ # Using World Matrix
+ vt = mathutils.Vector((v1[0], v1[1], v1[2], 1))
+ m4 = mainobject.matrix_world
+ vt2 = m4 * vt
+ v2 = [vt2[0], vt2[1], vt2[2]]
+
+ return v2
+
+
+# --------------------------------------------------------------------
+# Get location in world space
+# v1: point
+# mainobject
+# --------------------------------------------------------------------
+def get_location(mainobject):
+ # Using World Matrix
+ m4 = mainobject.matrix_world
+
+ return [m4[0][3], m4[1][3], m4[2][3]]
+
+
+# --------------------------------------------------------------------
+# Get vertex data
+# mainobject
+# --------------------------------------------------------------------
+def get_mesh_vertices(myobj):
+ try:
+ if myobj.mode == 'EDIT':
+ bm = bmesh.from_edit_mesh(myobj.data)
+ obverts = bm.verts
+ else:
+ obverts = myobj.data.vertices
+
+ return obverts
+ except AttributeError:
+ return None
+
+
+# --------------------------------------------------------------------
+# Get position for scale text
+#
+# --------------------------------------------------------------------
+def get_scale_txt_location(context):
+ scene = context.scene
+ pos_x = int(context.region.width * scene.measureit_scale_pos_x / 100)
+ pos_y = int(context.region.height * scene.measureit_scale_pos_y / 100)
+
+ return pos_x, pos_y
+
+
+# --------------------------------------------------------------------
+# Get position in final render image
+# (Z < 0 out of camera)
+# return 2d position
+# --------------------------------------------------------------------
+def get_render_location(mypoint):
+
+ v1 = mathutils.Vector(mypoint)
+ scene = bpy.context.scene
+ co_2d = object_utils.world_to_camera_view(scene, scene.camera, v1)
+ # Get pixel coords
+ render_scale = scene.render.resolution_percentage / 100
+ render_size = (int(scene.render.resolution_x * render_scale),
+ int(scene.render.resolution_y * render_scale))
+
+ return [round(co_2d.x * render_size[0]), round(co_2d.y * render_size[1])]
+
+
+# ---------------------------------------------------------
+# Get center of circle base on 3 points
+#
+# Point a: (x,y,z) arc start
+# Point b: (x,y,z) center
+# Point c: (x,y,z) midle point in the arc
+# Point d: (x,y,z) arc end
+# Return:
+# ang: angle (radians)
+# len: len of arc
+#
+# ---------------------------------------------------------
+def get_arc_data(pointa, pointb, pointc, pointd):
+ v1 = mathutils.Vector((pointa[0] - pointb[0], pointa[1] - pointb[1], pointa[2] - pointb[2]))
+ v2 = mathutils.Vector((pointc[0] - pointb[0], pointc[1] - pointb[1], pointc[2] - pointb[2]))
+ v3 = mathutils.Vector((pointd[0] - pointb[0], pointd[1] - pointb[1], pointd[2] - pointb[2]))
+
+ angle = v1.angle(v2) + v2.angle(v3)
+
+ rclength = math.pi * 2 * v2.length * (angle / (math.pi * 2))
+
+ return angle, rclength
+
+
+# -------------------------------------------------------------
+# Format a number to the right unit
+#
+# -------------------------------------------------------------
+def format_distance(fmt, units, value, factor=1):
+ s_code = "\u00b2" # Superscript two
+ # ------------------------
+ # Units automatic
+ # ------------------------
+ if units == "1":
+ # Units
+ if bpy.context.scene.unit_settings.system == "IMPERIAL":
+ feet = value * (3.2808399 ** factor)
+ if round(feet, 2) >= 1.0:
+ fmt += " ft"
+ if factor == 2:
+ fmt += s_code
+ tx_dist = fmt % feet
+ else:
+ inches = value * (39.3700787 ** factor)
+ fmt += " in"
+ if factor == 2:
+ fmt += s_code
+ tx_dist = fmt % inches
+ elif bpy.context.scene.unit_settings.system == "METRIC":
+ if round(value, 2) >= 1.0:
+ fmt += " m"
+ if factor == 2:
+ fmt += s_code
+ tx_dist = fmt % value
+ else:
+ if round(value, 2) >= 0.01:
+ fmt += " cm"
+ if factor == 2:
+ fmt += s_code
+ d_cm = value * (100 ** factor)
+ tx_dist = fmt % d_cm
+ else:
+ fmt += " mm"
+ if factor == 2:
+ fmt += s_code
+ d_mm = value * (1000 ** factor)
+ tx_dist = fmt % d_mm
+ else:
+ tx_dist = fmt % value
+ # ------------------------
+ # Units meters
+ # ------------------------
+ elif units == "2":
+ fmt += " m"
+ if factor == 2:
+ fmt += s_code
+ tx_dist = fmt % value
+ # ------------------------
+ # Units centimeters
+ # ------------------------
+ elif units == "3":
+ fmt += " cm"
+ if factor == 2:
+ fmt += s_code
+ d_cm = value * (100 ** factor)
+ tx_dist = fmt % d_cm
+ # ------------------------
+ # Units milimiters
+ # ------------------------
+ elif units == "4":
+ fmt += " mm"
+ if factor == 2:
+ fmt += s_code
+ d_mm = value * (1000 ** factor)
+ tx_dist = fmt % d_mm
+ # ------------------------
+ # Units feet
+ # ------------------------
+ elif units == "5":
+ fmt += " ft"
+ if factor == 2:
+ fmt += s_code
+ feet = value * (3.2808399 ** factor)
+ tx_dist = fmt % feet
+ # ------------------------
+ # Units inches
+ # ------------------------
+ elif units == "6":
+ fmt += " in"
+ if factor == 2:
+ fmt += s_code
+ inches = value * (39.3700787 ** factor)
+ tx_dist = fmt % inches
+ # ------------------------
+ # Default
+ # ------------------------
+ else:
+ tx_dist = fmt % value
+
+ return tx_dist