0
$\begingroup$

enter image description here

I want to calculate the angle between 3 points, the two ends of the selected bone and the centre of the thigh bone using a python script.

I have tried multiple methods but I am not able to figure out how to find the coordinate of the 3 points mentioned and then the angle between them using python script. Please help.

$\endgroup$
2
$\begingroup$

The angle between two vectors.

For example sake the triangle ABC is the three points in space A, B and C. where B and C are the head and tail of the active pose bone (context.active_pose_bone).

The point B is the mid point of head and tail of bone named "Bone". (Edit to match your bones name)

Will use mathutils.Vector.angle(vector) to calculate the angle.

import bpy
from math import degrees
context = bpy.context
ob = context.object
# middle of thigh
tb = ob.pose.bones.get("Bone")
B = (tb.head + tb.tail) / 2

# the active pose bone
pb = context.active_pose_bone

A = pb.head
C = pb.tail

# angle AB BC
alpha = (A - B).angle(C - B)
print(degrees(alpha))
$\endgroup$
  • $\begingroup$ hah, didn't see that the Vector class has an angle function. Nice! $\endgroup$ – aliasguru Aug 17 '18 at 13:19
0
$\begingroup$

It is important to understand that in Blender bones have two conditions: Their Edit Mode and their Pose Mode. So the solution to the question, as long as you don't specify it better, varies by the intent. It matters because accessing those bones, and retrieving their coordinates, works quite differently, as the Pose is stored on the Object, but the Edit Bone on the Object Data of the Armature.

The proposed solution here is based on the assumption that your screenshot shows what you're trying to do. That screenshot was taken in Pose Mode, so here we go:

import bpy
import math  # we need this to get the anglein degrees
import numpy  # we need this for the Vector Math
cob = bpy.data.objects.get('Armature')

# remember, we are working on the Pose Bones in this example!
bones = cob.pose.bones

# get the bones
bone1 = bones['FirstBone']
bone2 = bones['LastBone']


# get the bone locations as Vectors in World Space
pointA = bone1.head
pointB = bone1.tail
pointC = bone2.tail


# find the two Vectors
# you retrieve the Vector by subtracting the intended Vector Root coordinate from the Tip coordinate
vecA = pointA - pointB
vecB = pointC - pointB


print(vecA, vecB)

# calculate the angle, formula taken from https://stackoverflow.com/questions/39497496/angle-between-two-vectors-3d-python
angle=numpy.arccos(numpy.dot(vecA,vecB)/(numpy.linalg.norm(vecA)*numpy.linalg.norm(vecB)))

# remember the angle is in RADIANS!
print(math.degrees(angle))

Important bits for you are: You need Vectors to be able to calculate the angle inbetween. Those Vectors can be derived by a subtraction of head and tail of the bone you're looking for. A screenshot of the file I was testing this in:

angle

The formula to calculate the angle between two Vectors was taken - as stated in the comment - from a StackOverflow question. It involves using numpy, which offers the needed Vector math classes for this.

I have created a .blend file to test this quickly here:

Open the file, press run script in the Text Editor, and the angle should be assigned to the Text field. Repose the bones to test again.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.