Newer
Older
# ***** 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 LICENCE BLOCK *****
#
# -----------------------------------------------------------------------
# Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
# -----------------------------------------------------------------------
#
import bpy
import bmesh
from math import sqrt, floor, asin, sin, cos, pi
from mathutils import Vector
from bpy.types import Operator
from .pdt_functions import (
oops,
arc_centre,
set_mode,
view_coords,
view_coords_i,
)
from .pdt_msg_strings import (
PDT_OBJ_MODE_ERROR,
PDT_ERR_NO_ACT_OBJ,
PDT_ERR_SEL_3_VERTS,
PDT_ERR_SEL_1_VERT,
PDT_ERR_BADDISTANCE,
PDT_ERR_MATHSERROR,
PDT_ERR_SAMERADII,
PDT_ERR_VERT_MODE,
)
from . import pdt_exception
PDT_ObjectModeError = pdt_exception.ObjectModeError
PDT_SelectionError = pdt_exception.SelectionError
def get_tangent_intersect_outer(hloc_0, vloc_0, hloc_1, vloc_1, radius_0, radius_1):
"""Return Location in 2 Dimensions of the Intersect Point for Outer Tangents.
Args:
hloc_0: Horizontal Coordinate of Centre of First Arc
vloc_0: Vertical Coordinate of Centre of First Arc
hloc_1: Horizontal Coordinate of Centre of Second Arc
vloc_1: Vertical Coordinate of Centre of Second Arc
radius_0: Radius of First Arc
radius_1: Radius of Second Arc
Returns:
hloc_p: Horizontal Coordinate of Centre of Intersection
vloc_p: Vertical Coordinate of Centre of Intersection.
"""
hloc_p = ((hloc_1 * radius_0) - (hloc_0 * radius_1)) / (radius_0 - radius_1)
vloc_p = ((vloc_1 * radius_0) - (vloc_0 * radius_1)) / (radius_0 - radius_1)
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
def get_tangent_intersect_inner(hloc_0, vloc_0, hloc_1, vloc_1, radius_0, radius_1):
"""Return Location in 2 Dimensions of the Intersect Point for Inner Tangents.
Args:
hloc_0: Horizontal Coordinate of Centre of First Arc
vloc_0: Vertical Coordinate of Centre of First Arc
hloc_1: Horizontal Coordinate of Centre of Second Arc
vloc_1: Vertical Coordinate of Centre of Second Arc
radius_0: Radius of First Arc
radius_1: Radius of Second Arc
Returns:
hloc_p: Horizontal Coordinate of Centre of Intersection
vloc_p: Vertical Coordinate of Centre of Intersection.
"""
hloc_p = ((hloc_1 * radius_0) + (hloc_0 * radius_1)) / (radius_0 + radius_1)
vloc_p = ((vloc_1 * radius_0) + (vloc_0 * radius_1)) / (radius_0 + radius_1)
return hloc_p, vloc_p
def get_tangent_points(context, hloc_0, vloc_0, radius_0, hloc_p, vloc_p):
"""Return Location in 2 Dimensions of the Tangent Points.
Args:
context: Blender bpy.context instance
hloc_0: Horizontal Coordinate of Centre of First Arc
vloc_0: Vertical Coordinate of Centre of First Arc
radius_0: Radius of First Arc
hloc_p: Horizontal Coordinate of Intersection
vloc_p: Vertical Coordinate of Intersection
Returns:
hloc_t1: Horizontal Location of First Tangent Point
hloc_t2: Horizontal Location of Second Tangent Point
vloc_t1: Vertical Location of First Tangent Point
vloc_t2: Vertical Location of Second Tangent Point
"""
numerator = (radius_0 ** 2 * (hloc_p - hloc_0)) + (
* (vloc_p - vloc_0)
* sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
hloc_t1 = round((numerator / denominator) + hloc_0, 5)
numerator = (radius_0 ** 2 * (hloc_p - hloc_0)) - (
* (vloc_p - vloc_0)
* sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
hloc_t2 = round((numerator / denominator) + hloc_0, 5)
numerator = (radius_0 ** 2 * (vloc_p - vloc_0)) - (
* (hloc_p - hloc_0)
* sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
vloc_t1 = round((numerator / denominator) + vloc_0, 5)
numerator = (radius_0 ** 2 * (vloc_p - vloc_0)) + (
* (hloc_p - hloc_0)
* sqrt((hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2 - radius_0 ** 2)
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
179
180
181
182
183
184
185
186
187
188
denominator = (hloc_p - hloc_0) ** 2 + (vloc_p - vloc_0) ** 2
vloc_t2 = round((numerator / denominator) + vloc_0, 5)
return hloc_t1, hloc_t2, vloc_t1, vloc_t2
def make_vectors(coords, a1, a2, a3, pg):
"""Return Vectors of the Tangent Points.
Args:
coords: A List of Coordinates in 2D space of the tangent points
& a third dimension for the vectors
a1: Index of horizontal axis
a2: Index of vertical axis
a3: Index of depth axis
pg: PDT Parameters Group - our variables
Returns:
tangent_vector_o1: Location of First Tangent Point
tangent_vector_o2: Location of Second Tangent Point
tangent_vector_o3: Location of First Tangent Point
tangent_vector_o4: Location of Second Tangent Point
"""
tangent_vector_o1 = Vector((0, 0, 0))
tangent_vector_o1[a1] = coords[0]
tangent_vector_o1[a2] = coords[1]
tangent_vector_o1[a3] = coords[8]
tangent_vector_o2 = Vector((0, 0, 0))
tangent_vector_o2[a1] = coords[2]
tangent_vector_o2[a2] = coords[3]
tangent_vector_o2[a3] = coords[8]
tangent_vector_o3 = Vector((0, 0, 0))
tangent_vector_o3[a1] = coords[4]
tangent_vector_o3[a2] = coords[5]
tangent_vector_o3[a3] = coords[8]
tangent_vector_o4 = Vector((0, 0, 0))
tangent_vector_o4[a1] = coords[6]
tangent_vector_o4[a2] = coords[7]
tangent_vector_o4[a3] = coords[8]
if pg.plane == "LO":
tangent_vector_o1 = view_coords(
tangent_vector_o1[a1], tangent_vector_o1[a2], tangent_vector_o1[a3]
)
tangent_vector_o2 = view_coords(
tangent_vector_o2[a1], tangent_vector_o2[a2], tangent_vector_o2[a3]
)
tangent_vector_o3 = view_coords(
tangent_vector_o3[a1], tangent_vector_o3[a2], tangent_vector_o3[a3]
)
tangent_vector_o4 = view_coords(
tangent_vector_o4[a1], tangent_vector_o4[a2], tangent_vector_o4[a3]
)
return (tangent_vector_o1, tangent_vector_o2, tangent_vector_o3, tangent_vector_o4)
def tangent_setup(context, pg, plane, obj_data, centre_0, centre_1, centre_2, radius_0, radius_1):
"""This section sets up all the variables required for the tangent functions.
Args:
context: Blender bpy.context instance
pg: PDT Parameter Group of variables
plane: Working plane
obj_data: All the data of the chosen object
centre_0: Centre coordinates of the first arc
centre_1: Centre coordinates of the second arc
centre_2: Coordinates fo the point
radius_0: Radius if the first Arc
radius_1: Radius of the second Arc
Returns:
Status Set.
"""
if plane == "LO":
centre_0 = view_coords_i(centre_0[a1], centre_0[a2], centre_0[a3])
centre_1 = view_coords_i(centre_1[a1], centre_1[a2], centre_1[a3])
centre_2 = view_coords_i(centre_2[a1], centre_2[a2], centre_2[a3])
vector_difference = centre_2 - centre_0
distance = sqrt(vector_difference[a1] ** 2 + vector_difference[a2] ** 2)
else:
vector_difference = centre_1 - centre_0
distance = sqrt(vector_difference[a1] ** 2 + vector_difference[a2] ** 2)
if (
(distance <= radius_0 and mode in {"point"}) or
(distance <= (radius_0 + radius_1) and mode in {"inner", "both"}) or
(distance <= radius_0 or distance <= radius_1 and mode in {"outer", "both"})
):
# Cannot execute, centres are too close.
pg.error = f"{PDT_ERR_BADDISTANCE}"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
"""This next section will draw Point based Tangents.
These are drawn from a point to an Arc
"""
(centre_2[a1] - centre_0[a1]) ** 2 + (centre_2[a2] - centre_0[a2]) ** 2 - radius_0 ** 2
) > 0:
hloc_to1, hloc_to2, vloc_to1, vloc_to2 = get_tangent_points(
context, centre_0[a1], centre_0[a2], radius_0, centre_2[a1], centre_2[a2]
)
else:
pg.error = PDT_ERR_MATHSERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
# Point Tangents
tangent_vector_o1 = Vector((0, 0, 0))
tangent_vector_o1[a1] = hloc_to1
tangent_vector_o1[a2] = vloc_to1
tangent_vector_o1[a3] = centre_2[a3]
tangent_vector_o2 = Vector((0, 0, 0))
tangent_vector_o2[a1] = hloc_to2
tangent_vector_o2[a2] = vloc_to2
tangent_vector_o2[a3] = centre_2[a3]
if pg.plane == "LO":
centre_2 = view_coords(centre_2[a1], centre_2[a2], centre_2[a3])
tangent_vector_o1 = view_coords(
tangent_vector_o1[a1], tangent_vector_o1[a2], tangent_vector_o1[a3]
)
tangent_vector_o2 = view_coords(
tangent_vector_o2[a1], tangent_vector_o2[a2], tangent_vector_o2[a3]
)
tangent_vectors = (centre_2, tangent_vector_o1, tangent_vector_o2)
draw_tangents(tangent_vectors, obj_data)
return {"FINISHED"}
"""This next section will draw Arc based Outer Tangents.
These are drawn from an Arc to another Arc
"""
if radius_0 == radius_1:
# No intersection point for outer tangents
sin_angle = (centre_1[a2] - centre_0[a2]) / distance
cos_angle = (centre_1[a1] - centre_0[a1]) / distance
hloc_to1 = centre_0[a1] + (radius_0 * sin_angle)
hloc_to2 = centre_0[a1] - (radius_0 * sin_angle)
hloc_to3 = centre_1[a1] + (radius_0 * sin_angle)
hloc_to4 = centre_1[a1] - (radius_0 * sin_angle)
vloc_to1 = centre_0[a2] - (radius_0 * cos_angle)
vloc_to2 = centre_0[a2] + (radius_0 * cos_angle)
vloc_to3 = centre_1[a2] - (radius_0 * cos_angle)
vloc_to4 = centre_1[a2] + (radius_0 * cos_angle)
else:
hloc_po, vloc_po = get_tangent_intersect_outer(
centre_0[a1], centre_0[a2], centre_1[a1], centre_1[a2], radius_0, radius_1
)
if ((hloc_po - centre_0[a1]) ** 2 + (vloc_po - centre_0[a2]) ** 2 - radius_0 ** 2) > 0:
hloc_to1, hloc_to2, vloc_to1, vloc_to2 = get_tangent_points(
context, centre_0[a1], centre_0[a2], radius_0, hloc_po, vloc_po
)
else:
pg.error = PDT_ERR_MATHSERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
if ((hloc_po - centre_0[a1]) ** 2 + (vloc_po - centre_0[a2]) ** 2 - radius_1 ** 2) > 0:
hloc_to3, hloc_to4, vloc_to3, vloc_to4 = get_tangent_points(
context, centre_1[a1], centre_1[a2], radius_1, hloc_po, vloc_po
)
else:
pg.error = PDT_ERR_MATHSERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
dloc_p = centre_0[a3]
coords_in = (
hloc_to1,
vloc_to1,
hloc_to2,
vloc_to2,
hloc_to3,
vloc_to3,
hloc_to4,
vloc_to4,
dloc_p,
)
tangent_vectors = make_vectors(coords_in, a1, a2, a3, pg)
draw_tangents(tangent_vectors, obj_data)
"""This next section will draw Arc based Inner Tangents.
These are drawn from an Arc to another Arc
"""
hloc_pi, vloc_pi = get_tangent_intersect_inner(
centre_0[a1], centre_0[a2], centre_1[a1], centre_1[a2], radius_0, radius_1
)
if ((hloc_pi - centre_0[a1]) ** 2 + (vloc_pi - centre_0[a2]) ** 2 - radius_0 ** 2) > 0:
hloc_to1, hloc_to2, vloc_to1, vloc_to2 = get_tangent_points(
context, centre_0[a1], centre_0[a2], radius_0, hloc_pi, vloc_pi
)
else:
pg.error = PDT_ERR_MATHSERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
if ((hloc_pi - centre_0[a1]) ** 2 + (vloc_pi - centre_0[a2]) ** 2 - radius_0 ** 2) > 0:
hloc_to3, hloc_to4, vloc_to3, vloc_to4 = get_tangent_points(
context, centre_1[a1], centre_1[a2], radius_1, hloc_pi, vloc_pi
)
else:
pg.error = PDT_ERR_MATHSERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
dloc_p = centre_0[a3]
coords_in = (
hloc_to1,
vloc_to1,
hloc_to2,
vloc_to2,
hloc_to3,
vloc_to3,
hloc_to4,
vloc_to4,
dloc_p,
)
tangent_vectors = make_vectors(coords_in, a1, a2, a3, pg)
draw_tangents(tangent_vectors, obj_data)
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
def draw_tangents(tangent_vectors, obj_data):
"""Add Edges Representing the Tangents.
Note:
The length of the tanget_vectors determins whcih tangents will be
drawn, 3 gives Point Tangents, 4 gives Inner/Outer tangents
Args:
tangent_vectors: A list of vectores representing the tangents
obj_data: A list giving Object, Object Location and Object Bmesh
Returns:
Nothing.
"""
obj = obj_data[0]
obj_loc = obj_data[1]
bm = obj_data[2]
if len(tangent_vectors) == 3:
point_vertex_outer = bm.verts.new(tangent_vectors[0] - obj_loc)
tangent_vertex_o1 = bm.verts.new(tangent_vectors[1] - obj_loc)
tangent_vertex_o2 = bm.verts.new(tangent_vectors[2] - obj_loc)
bm.edges.new([tangent_vertex_o1, point_vertex_outer])
bm.edges.new([tangent_vertex_o2, point_vertex_outer])
else:
tangent_vertex_o1 = bm.verts.new(tangent_vectors[0] - obj_loc)
tangent_vertex_o2 = bm.verts.new(tangent_vectors[2] - obj_loc)
tangent_vertex_o3 = bm.verts.new(tangent_vectors[1] - obj_loc)
tangent_vertex_o4 = bm.verts.new(tangent_vectors[3] - obj_loc)
bm.edges.new([tangent_vertex_o1, tangent_vertex_o2])
bm.edges.new([tangent_vertex_o3, tangent_vertex_o4])
bmesh.update_edit_mesh(obj.data)
def analyse_arc(context, pg):
"""Analyses an Arc inferred from Selected Vertices.
Note:
Will work if more than 3 vertices are selected, taking the
first, the nearest to the middle and the last.
Args:
context: Blender bpy.context instance
pg: PDT Parameters Group - our variables
Returns:
vector_delta: Location of Arc Centre
radius: Radius of Arc.
"""
obj = context.view_layer.objects.active
if obj is None:
pg.error = PDT_ERR_NO_ACT_OBJ
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
raise PDT_ObjectModeError
if obj.mode == "EDIT":
obj_loc = obj.matrix_world.decompose()[0]
bm = bmesh.from_edit_mesh(obj.data)
verts = [v for v in bm.verts if v.select]
pg.error = f"{PDT_ERR_SEL_3_VERTS} {len(verts)})"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
raise PDT_SelectionError
vector_a = verts[0].co
vector_b = verts[int(floor(len(verts) / 2))].co
vector_delta, radius = arc_centre(vector_a, vector_b, vector_c)
return vector_delta, radius
class PDT_OT_TangentOperate(Operator):
bl_idname = "pdt.tangentoperate"
bl_label = "Calculate Tangents"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Calculate Tangents to Arcs from Points or Other Arcs"
@classmethod
def poll(cls, context):
ob = context.object
if ob is None:
return False
return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
def execute(self, context):
Note:
Uses pg.plane, pg.tangent_point0, pg.tangent_radius0, pg.tangent_point1
pg.tangent_radius1, pg.tangent_point2 to place tangents.
Analyses distance between arc centres, or arc centre and tangent point
to determine which mode is possible (Inner, Outer, or Point). If centres are
both contianed within 1 inferred circle, Inner tangents are not possible.
Arcs of same radius will have no intersection for outer tangents so these
are calculated differently.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
plane = pg.plane
# Get Object
obj = context.view_layer.objects.active
if obj is not None:
if obj.mode not in {"EDIT"} or obj.type != "MESH":
pg.error = PDT_OBJ_MODE_ERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
else:
pg.error = PDT_ERR_NO_ACT_OBJ
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
bm = bmesh.from_edit_mesh(obj.data)
obj_loc = obj.matrix_world.decompose()[0]
radius_0 = pg.tangent_radius0
radius_1 = pg.tangent_radius1
centre_0 = pg.tangent_point0
centre_1 = pg.tangent_point1
centre_2 = pg.tangent_point2
tangent_setup(
context, pg, plane, obj_data, centre_0, centre_1, centre_2, radius_0, radius_1
)
return {"FINISHED"}
class PDT_OT_TangentOperateSel(Operator):
bl_idname = "pdt.tangentoperatesel"
bl_label = "Calculate Tangents"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Calculate Tangents to Arcs from 2 Selected Vertices, or 1 & Point"
@classmethod
def poll(cls, context):
ob = context.object
if ob is None:
return False
return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
def execute(self, context):
Note:
Uses pg.plane & 2 or more selected Vertices to place tangents.
One vertex must be on each arc.
Analyses distance between arc centres, or arc centre and tangent point
to determine which mode is possible (Inner, Outer, or Point). If centres are
both contianed within 1 inferred circle, Inner tangents are not possible.
Arcs of same radius will have no intersection for outer tangents so these
are calculated differently.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
plane = pg.plane
# Get Object
obj = context.view_layer.objects.active
if obj is not None:
if obj.mode not in {"EDIT"} or obj.type != "MESH":
pg.error = PDT_OBJ_MODE_ERROR
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
else:
pg.error = PDT_ERR_NO_ACT_OBJ
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
bm = bmesh.from_edit_mesh(obj.data)
obj_loc = obj.matrix_world.decompose()[0]
# Get All Values from Selected Vertices
verts = [v for v in bm.verts if v.select]
if len(verts) <= 0:
pg.error = f"{PDT_ERR_SEL_1_VERT} 0"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
return {"FINISHED"}
v1 = verts[0]
vn = verts[-1]
for v in bm.verts:
v.select_set(False)
for e in bm.edges:
e.select_set(False)
v1.select_set(True)
bpy.ops.mesh.select_linked()
verts1 = [v for v in bm.verts if v.select].copy()
if len(verts1) < 3:
pg.error = f"{PDT_ERR_VERT_MODE} or Less than 3 vertices in your Arc(s)"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
for v in bm.verts:
v.select_set(False)
for e in bm.edges:
e.select_set(False)
vn.select_set(True)
bpy.ops.mesh.select_linked()
vertsn = [v for v in bm.verts if v.select].copy()
for v in bm.verts:
v.select_set(False)
for e in bm.edges:
e.select_set(False)
bmesh.update_edit_mesh(obj.data)
bm.select_history.clear()
verts1 = [verts1[0].co, verts1[int(floor(len(verts1) / 2))].co, verts1[-1].co]
vertsn = [vertsn[0].co, vertsn[int(floor(len(vertsn) / 2))].co, vertsn[-1].co]
centre_0, radius_0 = arc_centre(verts1[0], verts1[1], verts1[2])
centre_1, radius_1 = arc_centre(vertsn[0], vertsn[1], vertsn[2])
centre_2 = pg.tangent_point2
tangent_setup(
context, pg, plane, obj_data, centre_0, centre_1, centre_2, radius_0, radius_1
)
return {"FINISHED"}
class PDT_OT_TangentSet1(Operator):
"""Calculates Centres & Radii from 3 Vectors."""
bl_idname = "pdt.tangentset1"
bl_label = "Calculate Centres & Radii"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Calculate Centres & Radii from Selected Vertices"
@classmethod
def poll(cls, context):
ob = context.object
if ob is None:
return False
return all([bool(ob), ob.type == "MESH", ob.mode == "EDIT"])
def execute(self, context):
"""Sets Input Tangent Point 1 to analysis of Arc.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
vector_delta, radius = analyse_arc(context, pg)
pg.tangent_point0 = vector_delta
pg.tangent_radius0 = radius
return {"FINISHED"}
class PDT_OT_TangentSet2(Operator):
"""Calculates Centres & Radii from 3 Vectors."""
bl_idname = "pdt.tangentset2"
bl_label = "Calculate Centres & Radii"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Calculate Centres & Radii from Selected Vertices"
@classmethod
def poll(cls, context):
obj = context.object
if obj is None:
return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
def execute(self, context):
"""Sets Input Tangent Point 2 to analysis of Arc.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
vector_delta, radius = analyse_arc(context, pg)
pg.tangent_point1 = vector_delta
pg.tangent_radius1 = radius
return {"FINISHED"}
class PDT_OT_TangentSet3(Operator):
"""Set Tangent Origin Point from Cursor."""
bl_idname = "pdt.tangentset3"
bl_label = "Set Tangent Origin Point from Cursor"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Set Tangent Origin Point from Cursor"
@classmethod
def poll(cls, context):
obj = context.object
if obj is None:
return False
return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
def execute(self, context):
"""Sets Input Tangent Point 3 to analysis of Arc.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
pg.tangent_point2 = scene.cursor.location
return {"FINISHED"}
class PDT_OT_TangentSet4(Operator):
"""Set Tangent Origin Point from Cursor."""
bl_idname = "pdt.tangentset4"
bl_label = "Set Tangent Origin Point from Vertex"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Set Tangent Origin Point from Vertex"
@classmethod
def poll(cls, context):
obj = context.object
if obj is None:
return False
return all([bool(obj), obj.type == "MESH", obj.mode == "EDIT"])
def execute(self, context):
"""Sets Input Tangent Point 2 to selected Vertex.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
obj = context.object
bm = bmesh.from_edit_mesh(obj.data)
verts = [v for v in bm.verts if v.select]
if len(verts) != 1:
pg.error = f"{PDT_ERR_SEL_1_VERT} {len(verts)})"
context.window_manager.popup_menu(oops, title="Error", icon="ERROR")
raise PDT_SelectionError
pg.tangent_point2 = verts[0].co
return {"FINISHED"}
class PDT_OT_TangentExpandMenu(Operator):
"""Expand/Collapse Tangent Menu."""
bl_idname = "pdt.tangentexpandmenu"
bl_label = "Expand/Collapse Tangent Menu"
bl_options = {"REGISTER", "UNDO"}
bl_description = "Expand/Collapse Tangent Menu to Show/Hide Input Options"
def execute(self, context):
"""Expand/Collapse Tangent Menu.
Args:
context: Blender bpy.context instance.
Returns:
Nothing.
"""
scene = context.scene
pg = scene.pdt_pg
if pg.menu_expand:
pg.menu_expand = False
else:
pg.menu_expand = True
return {"FINISHED"}