Place empty on the midpoint edges (matrix help)

Hello, I’m trying to align an Empty to each edge’s midpoint,
I need help composing the correct world matrix for the empty because, the code I’ve been able to put together so far, correctly place the empty in the midpoint but fails to align the axis along the edge vector. I don’t care about the orientation as long as one edge of the empty is aligned to the vector of the edge.

Here is the code, what I’m doing wrong?


import bpy
from mathutils import Matrix, Vector

obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='OBJECT')
if obj and obj.mode == 'OBJECT':
    for i in obj.data.edges:
        locCo0 = obj.data.vertices[i.vertices[0]].co
        locCo1 = obj.data.vertices[i.vertices[1]].co
        vect0 = obj.matrix_world * locCo0
        vect1 = obj.matrix_world * locCo1
        edge_vect = vect1 - vect0
        midpoint = vect0 + edge_vect/2
        edge_vect.normalize()
        
        mat = Matrix.Identity(4)
        mat.col[0] = edge_vect.to_4d()
        mat.col[3] = midpoint.to_4d()
        
        bpy.ops.object.add(type='EMPTY')
        empty = context.object
        empty.empty_draw_type = 'ARROWS'
        empty.empty_draw_size = 0.2
        empty.matrix_world = mat

http://snag.gy/caDLP.jpg

Hi,

You can do this with pitch roll and yaw by looking at solving the cross product = 0 to get the angles, however blender has a handy little vector method


>>> v2.to_track_quat(
to_track_quat(track, up)
.. method:: to_track_quat(track, up)
Return a quaternion rotation from the vector and the track and up axis.
:arg track: Track axis in ['X', 'Y', 'Z', '-X', '-Y', '-Z'].
:type track: string
:arg up: Up axis in ['X', 'Y', 'Z'].
:type up: string
:return: rotation from the vector and the track and up axis.
:rtype: :class:`Quaternion`

So I just whacked that in, which appears to align the default z up empty’s x axis to the edge.


from bpy import context
from mathutils import Matrix, Vector
import math




obj = context.active_object
bpy.ops.object.mode_set(mode='OBJECT')
if obj and obj.mode == 'OBJECT':
    for i in obj.data.edges:


        locCo0 = obj.data.vertices[i.vertices[0]].co
        locCo1 = obj.data.vertices[i.vertices[1]].co
        vect0 = obj.matrix_world * locCo0
        vect1 = obj.matrix_world * locCo1
        edge_vect = vect1 - vect0
        midpoint = 0.5 * (vect1 + vect0)
        edge_vect.normalize()


        
        # the edge rotation by solving cross prod = 0
        for i, k in enumerate(edge_vect):  # rot x  , y and z
            print("ROT:%c" % "xyz"[i],  math.degrees(math.acos(k)))


        
        q = edge_vect.to_track_quat('X', 'Z')


        bpy.ops.object.add(type='EMPTY')
        empty = context.object
        empty.rotation_mode = 'QUATERNION'
        empty.empty_draw_type = 'ARROWS'
        empty.empty_draw_size = 1
        empty.location = midpoint
        empty.rotation_quaternion = q

or in matrix notation


        #empty.location = midpoint
        #empty.rotation_quaternion = q
        
        empty.matrix_world.translation = midpoint
        empty.matrix_world *= q.to_matrix().to_4x4()

with a bit of fiddling could probably get the “normals” right too.

T H A N K S !!!

what a relief thank you so much!