Revisit Previous question
Python: Calculate angle between vertices
The answer: Interior Face Angles
Think of it like walking around a table with left hand on surface. The table's up is face normal, our up (or the corner's up going thru v3 in question) is axis. A certain condition flipped axis, making us upside down, the test and negate fixed this. The main gist is need some reference to get the angle into 2d and hence get a signed value.
The verts are ordered the choice is which side of the line of verts is the table top (or face). We need some reference ie since the projection is onto Y plane would use Y or -Y axis as a proxy for face normal (in front view -Y is coming at us).
In the other question, if edges are made from the verts in x order, if the area below is a "face" with normal pointing at us (front view) then we are going clockwise, if above counter clockwise around the face.
Signed angle of 2D vectors.
Simple example, 2 points (p1, p2)
and an origin point o
If the 2d vectors represent the xy plane, the origin in middle, then this is y axis (12 o'clock) to (1, 1) (half past one). Travelling clockwise it's 45 degrees, counter clockwise 315
import bpy
from mathutils import Vector
from math import degrees, pi
context = bpy.context
o = Vector((0, 0))
p1 = Vector((0, 1))
p2 = Vector((1, 1))
#p1, p2 = p2, p1 # flipped
v1 = p1 - o
v2 = p2 - o
# if in z=0 plane this is axis of rotation
axis = v1.to_3d().cross(v2.to_3d())
a1 = v1.angle_signed(v2)
if a1 <= 0:
a2 = 2 * pi + a1
else:
a2 = a1 - 2 * pi
print(degrees(a1), degrees(a2))
# Results
#45.00000125223908 -314.9999987477609
#-45.00000125223908 314.9999987477609 flipped
So to re-iterate need to know what direction to go in. Assuming clockwise then return positive result above, p1 -> p2 is 45 degs, p2 -> p1 is 315.
but the range values do not work and I can't explain why. uniform(a1,
a2) in a loop produces a complete circle
The angles are how far to rotate from p1 to get to p2 either the short way or the long way. Adding them together (range) is effectively adding questions two ranges together.
The only thing I can think of is that v1, v2, v3 positions, relative
to one another, are variable and can occur in different orders.
Yes. It is clear in face edge angle answer link that the order is known. In this case it is not.
To get to p2 from p1 either rotate relative to p1 range (0, a1) or (0, a2)
3D Vectors
Can calculate the rotation difference between two vectors as a quaternion, ie how much to rotate vector to get to match alignment of other vector.
import bpy
from mathutils import Vector
from math import degrees, pi
context = bpy.context
o = Vector((1, 1, 1))
p1 = Vector((2, 3, 4))
p2 = Vector((5, 1, 5))
v1 = p1 - o
v2 = p2 - o
# to rotate v1 to v2
axis, angle = v1.rotation_difference(v2).to_axis_angle()
print(axis, degrees(angle))
if angle <= 0:
angle2 = 2 * pi + angle
else:
angle2 = angle - 2 * pi
print(degrees(angle2))
output
<Vector (0.5774, 0.5774, -0.5774)> 40.89339099490394
-319.10660900509606
Rotate about a pivot point
Recommend look at answer here https://blender.stackexchange.com/a/194802/15543 re making a matrix to rotate about a pivot point.
The example above gives us the angle and axis required to make the rotation matrix R
R = Matrix.Rotation(angle, 4, axis)
the direction of this rotation is determined by the sign of angle and the way the axis is pointing.