1 # ***** BEGIN GPL LICENSE BLOCK *****
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # ***** END GPL LICENCE BLOCK *****
20 # -----------------------------------------------------------------------
21 # Author: Alan Odom (Clockmender), Rune Morling (ermo) Copyright (c) 2019
22 # -----------------------------------------------------------------------
26 from math
import sqrt
, floor
, asin
, sin
, cos
, pi
27 from mathutils
import Vector
28 from bpy
.types
import Operator
30 from .pdt_functions
import (
38 from .pdt_msg_strings
import (
49 from . import pdt_exception
51 PDT_ObjectModeError
= pdt_exception
.ObjectModeError
52 PDT_SelectionError
= pdt_exception
.SelectionError
55 def get_tangent_intersect_outer(hloc_0
, vloc_0
, hloc_1
, vloc_1
, radius_0
, radius_1
):
56 """Return Location in 2 Dimensions of the Intersect Point for Outer Tangents.
59 hloc_0: Horizontal Coordinate of Centre of First Arc
60 vloc_0: Vertical Coordinate of Centre of First Arc
61 hloc_1: Horizontal Coordinate of Centre of Second Arc
62 vloc_1: Vertical Coordinate of Centre of Second Arc
63 radius_0: Radius of First Arc
64 radius_1: Radius of Second Arc
67 hloc_p: Horizontal Coordinate of Centre of Intersection
68 vloc_p: Vertical Coordinate of Centre of Intersection.
71 hloc_p
= ((hloc_1
* radius_0
) - (hloc_0
* radius_1
)) / (radius_0
- radius_1
)
72 vloc_p
= ((vloc_1
* radius_0
) - (vloc_0
* radius_1
)) / (radius_0
- radius_1
)
77 def get_tangent_intersect_inner(hloc_0
, vloc_0
, hloc_1
, vloc_1
, radius_0
, radius_1
):
78 """Return Location in 2 Dimensions of the Intersect Point for Inner Tangents.
81 hloc_0: Horizontal Coordinate of Centre of First Arc
82 vloc_0: Vertical Coordinate of Centre of First Arc
83 hloc_1: Horizontal Coordinate of Centre of Second Arc
84 vloc_1: Vertical Coordinate of Centre of Second Arc
85 radius_0: Radius of First Arc
86 radius_1: Radius of Second Arc
89 hloc_p: Horizontal Coordinate of Centre of Intersection
90 vloc_p: Vertical Coordinate of Centre of Intersection.
93 hloc_p
= ((hloc_1
* radius_0
) + (hloc_0
* radius_1
)) / (radius_0
+ radius_1
)
94 vloc_p
= ((vloc_1
* radius_0
) + (vloc_0
* radius_1
)) / (radius_0
+ radius_1
)
99 def get_tangent_points(context
, hloc_0
, vloc_0
, radius_0
, hloc_p
, vloc_p
):
100 """Return Location in 2 Dimensions of the Tangent Points.
103 context: Blender bpy.context instance
104 hloc_0: Horizontal Coordinate of Centre of First Arc
105 vloc_0: Vertical Coordinate of Centre of First Arc
106 radius_0: Radius of First Arc
107 hloc_p: Horizontal Coordinate of Intersection
108 vloc_p: Vertical Coordinate of Intersection
111 hloc_t1: Horizontal Location of First Tangent Point
112 hloc_t2: Horizontal Location of Second Tangent Point
113 vloc_t1: Vertical Location of First Tangent Point
114 vloc_t2: Vertical Location of Second Tangent Point
117 # Uses basic Pythagorus' theorem to compute locations
119 numerator
= (radius_0
** 2 * (hloc_p
- hloc_0
)) + (
122 * sqrt((hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2 - radius_0
** 2)
124 denominator
= (hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2
125 hloc_t1
= round((numerator
/ denominator
) + hloc_0
, 5)
127 numerator
= (radius_0
** 2 * (hloc_p
- hloc_0
)) - (
130 * sqrt((hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2 - radius_0
** 2)
132 denominator
= (hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2
133 hloc_t2
= round((numerator
/ denominator
) + hloc_0
, 5)
136 numerator
= (radius_0
** 2 * (vloc_p
- vloc_0
)) - (
139 * sqrt((hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2 - radius_0
** 2)
141 denominator
= (hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2
142 vloc_t1
= round((numerator
/ denominator
) + vloc_0
, 5)
144 numerator
= (radius_0
** 2 * (vloc_p
- vloc_0
)) + (
147 * sqrt((hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2 - radius_0
** 2)
149 denominator
= (hloc_p
- hloc_0
) ** 2 + (vloc_p
- vloc_0
) ** 2
150 vloc_t2
= round((numerator
/ denominator
) + vloc_0
, 5)
152 return hloc_t1
, hloc_t2
, vloc_t1
, vloc_t2
155 def make_vectors(coords
, a1
, a2
, a3
, pg
):
156 """Return Vectors of the Tangent Points.
159 coords: A List of Coordinates in 2D space of the tangent points
160 & a third dimension for the vectors
161 a1: Index of horizontal axis
162 a2: Index of vertical axis
163 a3: Index of depth axis
164 pg: PDT Parameters Group - our variables
167 tangent_vector_o1: Location of First Tangent Point
168 tangent_vector_o2: Location of Second Tangent Point
169 tangent_vector_o3: Location of First Tangent Point
170 tangent_vector_o4: Location of Second Tangent Point
173 tangent_vector_o1
= Vector((0, 0, 0))
174 tangent_vector_o1
[a1
] = coords
[0]
175 tangent_vector_o1
[a2
] = coords
[1]
176 tangent_vector_o1
[a3
] = coords
[8]
177 tangent_vector_o2
= Vector((0, 0, 0))
178 tangent_vector_o2
[a1
] = coords
[2]
179 tangent_vector_o2
[a2
] = coords
[3]
180 tangent_vector_o2
[a3
] = coords
[8]
181 tangent_vector_o3
= Vector((0, 0, 0))
182 tangent_vector_o3
[a1
] = coords
[4]
183 tangent_vector_o3
[a2
] = coords
[5]
184 tangent_vector_o3
[a3
] = coords
[8]
185 tangent_vector_o4
= Vector((0, 0, 0))
186 tangent_vector_o4
[a1
] = coords
[6]
187 tangent_vector_o4
[a2
] = coords
[7]
188 tangent_vector_o4
[a3
] = coords
[8]
191 # Reset coordinates from view local (Horiz, Vert, depth) to World XYZ.
193 tangent_vector_o1
= view_coords(
194 tangent_vector_o1
[a1
], tangent_vector_o1
[a2
], tangent_vector_o1
[a3
]
196 tangent_vector_o2
= view_coords(
197 tangent_vector_o2
[a1
], tangent_vector_o2
[a2
], tangent_vector_o2
[a3
]
199 tangent_vector_o3
= view_coords(
200 tangent_vector_o3
[a1
], tangent_vector_o3
[a2
], tangent_vector_o3
[a3
]
202 tangent_vector_o4
= view_coords(
203 tangent_vector_o4
[a1
], tangent_vector_o4
[a2
], tangent_vector_o4
[a3
]
206 return (tangent_vector_o1
, tangent_vector_o2
, tangent_vector_o3
, tangent_vector_o4
)
209 def tangent_setup(context
, pg
, plane
, obj_data
, centre_0
, centre_1
, centre_2
, radius_0
, radius_1
):
210 """This section sets up all the variables required for the tangent functions.
213 context: Blender bpy.context instance
214 pg: PDT Parameter Group of variables
216 obj_data: All the data of the chosen object
217 centre_0: Centre coordinates of the first arc
218 centre_1: Centre coordinates of the second arc
219 centre_2: Coordinates fo the point
220 radius_0: Radius if the first Arc
221 radius_1: Radius of the second Arc
227 a1
, a2
, a3
= set_mode(plane
)
228 mode
= pg
.tangent_mode
230 # Translate world cordinates into view local (horiz, vert, depth)
232 centre_0
= view_coords_i(centre_0
[a1
], centre_0
[a2
], centre_0
[a3
])
233 centre_1
= view_coords_i(centre_1
[a1
], centre_1
[a2
], centre_1
[a3
])
234 centre_2
= view_coords_i(centre_2
[a1
], centre_2
[a2
], centre_2
[a3
])
235 if pg
.tangent_mode
== "point":
236 vector_difference
= centre_2
- centre_0
237 distance
= sqrt(vector_difference
[a1
] ** 2 + vector_difference
[a2
] ** 2)
239 vector_difference
= centre_1
- centre_0
240 distance
= sqrt(vector_difference
[a1
] ** 2 + vector_difference
[a2
] ** 2)
243 (distance
<= radius_0
and mode
in {"point"}) or
244 (distance
<= (radius_0
+ radius_1
) and mode
in {"inner", "both"}) or
245 (distance
<= radius_0
or distance
<= radius_1
and mode
in {"outer", "both"})
247 # Cannot execute, centres are too close.
249 pg
.error
= f
"{PDT_ERR_BADDISTANCE}"
250 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
253 """This next section will draw Point based Tangents.
255 These are drawn from a point to an Arc
260 (centre_2
[a1
] - centre_0
[a1
]) ** 2 + (centre_2
[a2
] - centre_0
[a2
]) ** 2 - radius_0
** 2
262 hloc_to1
, hloc_to2
, vloc_to1
, vloc_to2
= get_tangent_points(
263 context
, centre_0
[a1
], centre_0
[a2
], radius_0
, centre_2
[a1
], centre_2
[a2
]
266 pg
.error
= PDT_ERR_MATHSERROR
267 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
271 tangent_vector_o1
= Vector((0, 0, 0))
272 tangent_vector_o1
[a1
] = hloc_to1
273 tangent_vector_o1
[a2
] = vloc_to1
274 tangent_vector_o1
[a3
] = centre_2
[a3
]
275 tangent_vector_o2
= Vector((0, 0, 0))
276 tangent_vector_o2
[a1
] = hloc_to2
277 tangent_vector_o2
[a2
] = vloc_to2
278 tangent_vector_o2
[a3
] = centre_2
[a3
]
280 # Translate view local coordinates (horiz, vert, depth) into World XYZ
282 centre_2
= view_coords(centre_2
[a1
], centre_2
[a2
], centre_2
[a3
])
283 tangent_vector_o1
= view_coords(
284 tangent_vector_o1
[a1
], tangent_vector_o1
[a2
], tangent_vector_o1
[a3
]
286 tangent_vector_o2
= view_coords(
287 tangent_vector_o2
[a1
], tangent_vector_o2
[a2
], tangent_vector_o2
[a3
]
289 tangent_vectors
= (centre_2
, tangent_vector_o1
, tangent_vector_o2
)
290 draw_tangents(tangent_vectors
, obj_data
)
294 """This next section will draw Arc based Outer Tangents.
296 These are drawn from an Arc to another Arc
299 if mode
in {"outer", "both"}:
300 # Uses basic trigonometry and Pythagorus' theorem to compute locations
302 if radius_0
== radius_1
:
303 # No intersection point for outer tangents
305 sin_angle
= (centre_1
[a2
] - centre_0
[a2
]) / distance
306 cos_angle
= (centre_1
[a1
] - centre_0
[a1
]) / distance
307 hloc_to1
= centre_0
[a1
] + (radius_0
* sin_angle
)
308 hloc_to2
= centre_0
[a1
] - (radius_0
* sin_angle
)
309 hloc_to3
= centre_1
[a1
] + (radius_0
* sin_angle
)
310 hloc_to4
= centre_1
[a1
] - (radius_0
* sin_angle
)
311 vloc_to1
= centre_0
[a2
] - (radius_0
* cos_angle
)
312 vloc_to2
= centre_0
[a2
] + (radius_0
* cos_angle
)
313 vloc_to3
= centre_1
[a2
] - (radius_0
* cos_angle
)
314 vloc_to4
= centre_1
[a2
] + (radius_0
* cos_angle
)
316 hloc_po
, vloc_po
= get_tangent_intersect_outer(
317 centre_0
[a1
], centre_0
[a2
], centre_1
[a1
], centre_1
[a2
], radius_0
, radius_1
320 if ((hloc_po
- centre_0
[a1
]) ** 2 + (vloc_po
- centre_0
[a2
]) ** 2 - radius_0
** 2) > 0:
321 hloc_to1
, hloc_to2
, vloc_to1
, vloc_to2
= get_tangent_points(
322 context
, centre_0
[a1
], centre_0
[a2
], radius_0
, hloc_po
, vloc_po
325 pg
.error
= PDT_ERR_MATHSERROR
326 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
328 if ((hloc_po
- centre_0
[a1
]) ** 2 + (vloc_po
- centre_0
[a2
]) ** 2 - radius_1
** 2) > 0:
329 hloc_to3
, hloc_to4
, vloc_to3
, vloc_to4
= get_tangent_points(
330 context
, centre_1
[a1
], centre_1
[a2
], radius_1
, hloc_po
, vloc_po
333 pg
.error
= PDT_ERR_MATHSERROR
334 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
337 dloc_p
= centre_0
[a3
]
349 tangent_vectors
= make_vectors(coords_in
, a1
, a2
, a3
, pg
)
350 draw_tangents(tangent_vectors
, obj_data
)
352 """This next section will draw Arc based Inner Tangents.
354 These are drawn from an Arc to another Arc
357 if mode
in {"inner", "both"}:
358 # Uses basic trigonometry and Pythagorus' theorem to compute locations
360 hloc_pi
, vloc_pi
= get_tangent_intersect_inner(
361 centre_0
[a1
], centre_0
[a2
], centre_1
[a1
], centre_1
[a2
], radius_0
, radius_1
363 if ((hloc_pi
- centre_0
[a1
]) ** 2 + (vloc_pi
- centre_0
[a2
]) ** 2 - radius_0
** 2) > 0:
364 hloc_to1
, hloc_to2
, vloc_to1
, vloc_to2
= get_tangent_points(
365 context
, centre_0
[a1
], centre_0
[a2
], radius_0
, hloc_pi
, vloc_pi
368 pg
.error
= PDT_ERR_MATHSERROR
369 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
371 if ((hloc_pi
- centre_0
[a1
]) ** 2 + (vloc_pi
- centre_0
[a2
]) ** 2 - radius_0
** 2) > 0:
372 hloc_to3
, hloc_to4
, vloc_to3
, vloc_to4
= get_tangent_points(
373 context
, centre_1
[a1
], centre_1
[a2
], radius_1
, hloc_pi
, vloc_pi
376 pg
.error
= PDT_ERR_MATHSERROR
377 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
380 dloc_p
= centre_0
[a3
]
392 tangent_vectors
= make_vectors(coords_in
, a1
, a2
, a3
, pg
)
393 draw_tangents(tangent_vectors
, obj_data
)
398 def draw_tangents(tangent_vectors
, obj_data
):
399 """Add Edges Representing the Tangents.
402 The length of the tanget_vectors determins whcih tangents will be
403 drawn, 3 gives Point Tangents, 4 gives Inner/Outer tangents
406 tangent_vectors: A list of vectores representing the tangents
407 obj_data: A list giving Object, Object Location and Object Bmesh
413 obj_loc
= obj_data
[1]
415 if len(tangent_vectors
) == 3:
416 point_vertex_outer
= bm
.verts
.new(tangent_vectors
[0] - obj_loc
)
417 tangent_vertex_o1
= bm
.verts
.new(tangent_vectors
[1] - obj_loc
)
418 tangent_vertex_o2
= bm
.verts
.new(tangent_vectors
[2] - obj_loc
)
419 bm
.edges
.new([tangent_vertex_o1
, point_vertex_outer
])
420 bm
.edges
.new([tangent_vertex_o2
, point_vertex_outer
])
422 tangent_vertex_o1
= bm
.verts
.new(tangent_vectors
[0] - obj_loc
)
423 tangent_vertex_o2
= bm
.verts
.new(tangent_vectors
[2] - obj_loc
)
424 tangent_vertex_o3
= bm
.verts
.new(tangent_vectors
[1] - obj_loc
)
425 tangent_vertex_o4
= bm
.verts
.new(tangent_vectors
[3] - obj_loc
)
426 bm
.edges
.new([tangent_vertex_o1
, tangent_vertex_o2
])
427 bm
.edges
.new([tangent_vertex_o3
, tangent_vertex_o4
])
428 bmesh
.update_edit_mesh(obj
.data
)
431 def analyse_arc(context
, pg
):
432 """Analyses an Arc inferred from Selected Vertices.
435 Will work if more than 3 vertices are selected, taking the
436 first, the nearest to the middle and the last.
439 context: Blender bpy.context instance
440 pg: PDT Parameters Group - our variables
443 vector_delta: Location of Arc Centre
444 radius: Radius of Arc.
446 obj
= context
.view_layer
.objects
.active
448 pg
.error
= PDT_ERR_NO_ACT_OBJ
449 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
450 raise PDT_ObjectModeError
451 if obj
.mode
== "EDIT":
452 obj_loc
= obj
.matrix_world
.decompose()[0]
453 bm
= bmesh
.from_edit_mesh(obj
.data
)
454 verts
= [v
for v
in bm
.verts
if v
.select
]
456 pg
.error
= f
"{PDT_ERR_SEL_3_VERTS} {len(verts)})"
457 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
458 raise PDT_SelectionError
459 vector_a
= verts
[0].co
460 # Get the nearest to middle vertex of the arc
462 vector_b
= verts
[int(floor(len(verts
) / 2))].co
463 vector_c
= verts
[-1].co
464 vector_delta
, radius
= arc_centre(vector_a
, vector_b
, vector_c
)
466 return vector_delta
, radius
469 class PDT_OT_TangentOperate(Operator
):
470 """Calculate Tangents from Inputs."""
472 bl_idname
= "pdt.tangentoperate"
473 bl_label
= "Calculate Tangents"
474 bl_options
= {"REGISTER", "UNDO"}
475 bl_description
= "Calculate Tangents to Arcs from Points or Other Arcs"
478 def poll(cls
, context
):
482 return all([bool(ob
), ob
.type == "MESH", ob
.mode
== "EDIT"])
484 def execute(self
, context
):
485 """Calculate Tangents from Inputs.
488 Uses pg.plane, pg.tangent_point0, pg.tangent_radius0, pg.tangent_point1
489 pg.tangent_radius1, pg.tangent_point2 to place tangents.
491 Analyses distance between arc centres, or arc centre and tangent point
492 to determine which mode is possible (Inner, Outer, or Point). If centres are
493 both contianed within 1 inferred circle, Inner tangents are not possible.
495 Arcs of same radius will have no intersection for outer tangents so these
496 are calculated differently.
499 context: Blender bpy.context instance.
505 scene
= context
.scene
509 obj
= context
.view_layer
.objects
.active
511 if obj
.mode
not in {"EDIT"} or obj
.type != "MESH":
512 pg
.error
= PDT_OBJ_MODE_ERROR
513 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
516 pg
.error
= PDT_ERR_NO_ACT_OBJ
517 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
519 bm
= bmesh
.from_edit_mesh(obj
.data
)
520 obj_loc
= obj
.matrix_world
.decompose()[0]
521 obj_data
= (obj
, obj_loc
, bm
)
523 radius_0
= pg
.tangent_radius0
524 radius_1
= pg
.tangent_radius1
525 centre_0
= pg
.tangent_point0
526 centre_1
= pg
.tangent_point1
527 centre_2
= pg
.tangent_point2
530 context
, pg
, plane
, obj_data
, centre_0
, centre_1
, centre_2
, radius_0
, radius_1
536 class PDT_OT_TangentOperateSel(Operator
):
537 """Calculate Tangents from Selection."""
539 bl_idname
= "pdt.tangentoperatesel"
540 bl_label
= "Calculate Tangents"
541 bl_options
= {"REGISTER", "UNDO"}
542 bl_description
= "Calculate Tangents to Arcs from 2 Selected Vertices, or 1 & Point in Menu"
545 def poll(cls
, context
):
549 return all([bool(ob
), ob
.type == "MESH", ob
.mode
== "EDIT"])
551 def execute(self
, context
):
552 """Calculate Tangents from Selection.
555 Uses pg.plane & 2 or more selected Vertices to place tangents.
556 One vertex must be on each arc.
558 Analyses distance between arc centres, or arc centre and tangent point
559 to determine which mode is possible (Inner, Outer, or Point). If centres are
560 both contianed within 1 inferred circle, Inner tangents are not possible.
562 Arcs of same radius will have no intersection for outer tangents so these
563 are calculated differently.
566 context: Blender bpy.context instance.
572 scene
= context
.scene
576 obj
= context
.view_layer
.objects
.active
578 if obj
.mode
not in {"EDIT"} or obj
.type != "MESH":
579 pg
.error
= PDT_OBJ_MODE_ERROR
580 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
583 pg
.error
= PDT_ERR_NO_ACT_OBJ
584 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
586 bm
= bmesh
.from_edit_mesh(obj
.data
)
587 obj_loc
= obj
.matrix_world
.decompose()[0]
588 obj_data
= (obj
, obj_loc
, bm
)
590 # Get All Values from Selected Vertices
591 verts
= [v
for v
in bm
.verts
if v
.select
]
593 pg
.error
= f
"{PDT_ERR_SEL_1_VERT} 0"
594 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
603 bpy
.ops
.mesh
.select_linked()
604 verts1
= [v
for v
in bm
.verts
if v
.select
].copy()
606 pg
.error
= f
"{PDT_ERR_VERT_MODE} or Less than 3 vertices in your Arc(s)"
607 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
614 bpy
.ops
.mesh
.select_linked()
615 vertsn
= [v
for v
in bm
.verts
if v
.select
].copy()
620 bmesh
.update_edit_mesh(obj
.data
)
621 bm
.select_history
.clear()
622 # Select the nearest to middle vertex in the arc
624 verts1
= [verts1
[0].co
, verts1
[int(floor(len(verts1
) / 2))].co
, verts1
[-1].co
]
625 vertsn
= [vertsn
[0].co
, vertsn
[int(floor(len(vertsn
) / 2))].co
, vertsn
[-1].co
]
626 centre_0
, radius_0
= arc_centre(verts1
[0], verts1
[1], verts1
[2])
627 centre_1
, radius_1
= arc_centre(vertsn
[0], vertsn
[1], vertsn
[2])
628 centre_2
= pg
.tangent_point2
631 context
, pg
, plane
, obj_data
, centre_0
, centre_1
, centre_2
, radius_0
, radius_1
637 class PDT_OT_TangentSet1(Operator
):
638 """Calculates Centres & Radii from 3 Vectors."""
640 bl_idname
= "pdt.tangentset1"
641 bl_label
= "Calculate Centres & Radii"
642 bl_options
= {"REGISTER", "UNDO"}
643 bl_description
= "Calculate Centres & Radii from Selected Vertices"
646 def poll(cls
, context
):
650 return all([bool(ob
), ob
.type == "MESH", ob
.mode
== "EDIT"])
652 def execute(self
, context
):
653 """Sets Input Tangent Point 1 to analysis of Arc.
656 context: Blender bpy.context instance.
661 scene
= context
.scene
663 vector_delta
, radius
= analyse_arc(context
, pg
)
664 pg
.tangent_point0
= vector_delta
665 pg
.tangent_radius0
= radius
669 class PDT_OT_TangentSet2(Operator
):
670 """Calculates Centres & Radii from 3 Vectors."""
672 bl_idname
= "pdt.tangentset2"
673 bl_label
= "Calculate Centres & Radii"
674 bl_options
= {"REGISTER", "UNDO"}
675 bl_description
= "Calculate Centres & Radii from Selected Vertices"
678 def poll(cls
, context
):
682 return all([bool(obj
), obj
.type == "MESH", obj
.mode
== "EDIT"])
684 def execute(self
, context
):
685 """Sets Input Tangent Point 2 to analysis of Arc.
688 context: Blender bpy.context instance.
693 scene
= context
.scene
695 vector_delta
, radius
= analyse_arc(context
, pg
)
696 pg
.tangent_point1
= vector_delta
697 pg
.tangent_radius1
= radius
701 class PDT_OT_TangentSet3(Operator
):
702 """Set Tangent Origin Point from Cursor."""
704 bl_idname
= "pdt.tangentset3"
705 bl_label
= "Set Tangent Origin Point from Cursor"
706 bl_options
= {"REGISTER", "UNDO"}
707 bl_description
= "Set Tangent Origin Point from Cursor"
710 def poll(cls
, context
):
714 return all([bool(obj
), obj
.type == "MESH", obj
.mode
== "EDIT"])
716 def execute(self
, context
):
717 """Sets Input Tangent Point 3 to analysis of Arc.
720 context: Blender bpy.context instance.
725 scene
= context
.scene
727 pg
.tangent_point2
= scene
.cursor
.location
731 class PDT_OT_TangentSet4(Operator
):
732 """Set Tangent Origin Point from Cursor."""
734 bl_idname
= "pdt.tangentset4"
735 bl_label
= "Set Tangent Origin Point from Vertex"
736 bl_options
= {"REGISTER", "UNDO"}
737 bl_description
= "Set Tangent Origin Point from Vertex"
740 def poll(cls
, context
):
744 return all([bool(obj
), obj
.type == "MESH", obj
.mode
== "EDIT"])
746 def execute(self
, context
):
747 """Sets Input Tangent Point 2 to selected Vertex.
750 context: Blender bpy.context instance.
755 scene
= context
.scene
758 bm
= bmesh
.from_edit_mesh(obj
.data
)
759 verts
= [v
for v
in bm
.verts
if v
.select
]
761 pg
.error
= f
"{PDT_ERR_SEL_1_VERT} {len(verts)})"
762 context
.window_manager
.popup_menu(oops
, title
="Error", icon
="ERROR")
763 raise PDT_SelectionError
764 pg
.tangent_point2
= verts
[0].co
768 class PDT_OT_TangentExpandMenu(Operator
):
769 """Expand/Collapse Tangent Menu."""
771 bl_idname
= "pdt.tangentexpandmenu"
772 bl_label
= "Expand/Collapse Tangent Menu"
773 bl_options
= {"REGISTER", "UNDO"}
774 bl_description
= "Expand/Collapse Tangent Menu to Show/Hide Input Options"
776 def execute(self
, context
):
777 """Expand/Collapse Tangent Menu.
780 This is used to add further options to the menu.
783 context: Blender bpy.context instance.
788 scene
= context
.scene
791 pg
.menu_expand
= False
793 pg
.menu_expand
= True