# Align an array of vertices to vectors with python

I have an array filled with points that should be aligned to a random coordinate system. The direction vectors of the coordinate system are known, as well as the direction vectors that form the points together.

My approach was to calculate the respective angle, from each point to the appropriate direction vector and then to rotate each point by this angle. The centre of rotation is the origin of all vertices together.

vert_array = [vert_1, vert_2, ..., vert_x]

def dotproduct(v1, v2):
return sum((a*b) for a, b in zip(v1, v2))

def length(v):
return math.sqrt(dotproduct(v, v))

def angle(v1, v2):
return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2)))

angle_x = angle(x_axis_vec_coordinatesys, direction_vec_x_array)

for vert in vert_array:
mat_rot = mathutils.Matrix.Rotation(angle, 4, direction_vec_x_array)

new_point= mat_rot * (vert - origin) + origin

vert_array_new.append(new_point)

#And so on for all axis.....


Unfortunately, that doesn't really work. If I had the vertices in an object, I would know how to adjust the object using DirectionVector.to_track_quat('X', 'Z'). However, it is not possible for me to save the points in an object here. These must remain independent of each other in an array.

I know i have somehow to use the rotation matrix and translation matrix, but i don't know how.

Edit: I've added a blend file for a better understanding. My current code is included there. The emptys in this file should simulate the coordinate axes. I've also added the translation of the new coordinate system, not like before.

My new coordinate system and the incorrectly placed points:

Edit: My desired result

Blenderfile

Advice, suggestions, questions, or assistance are all welcome.

The question is equivalent to say:

• vert_array is a set of coordinates in world space
• a coordinate system is given by its 3 vectors also in world space
• how to convert vert_array so that it has in world space the coordinates it should have in this coordinate system

So, the point is to find how to do that.

To convert from 1 coordinate system A(X, Y, Z) to another B knowing X', Y', Z' of B in A, you can use a matrix like the following composed of 3 columns which are respectively the coordinates of X', Y' and Z'.

Once the matrix defined, as it allows to convert from A to B, we need to get the inverted matrix to have the result.

Here is an example in Python:

import bpy
from mathutils import Vector, Matrix

# Coordinates system: enter your own values there
x = Vector( (0.70711, -0.70711, 0 ) )
y = Vector( (0, 0, -1 ) )
z = Vector( (0.70711, 0.70711, 0 ) )

# The matrix to go from world to the coordinates system
# It is defined by rows
m = Matrix( ((x[0], y[0], z[0], 0 ), (x[1], y[1], z[1], 0 ), (x[2], y[2], z[2], 0 ), (0, 0, 0, 1 )) )
m.normalize() # mainly because values are approximated above

m_inv = m.inverted() # as we need to go from the coo system to world

objects =bpy.context.selected_objects #get some objects (or take your vector array)

for o in objects:
o.location = m_inv * o.location #apply the transformation


• This is exactly my problem. But somehow it doesn't work for me, if i try your example with my own coordinate system. It does not match the desired coordinate system. I've added a blend file, maybe you see my mistake? – P. Sector Apr 23 '18 at 15:09
• I've edited the answer as the translation part was effectively wrong. But from you file (as the center is at 0, 0, 0) I don't see what is going wrong? (also I'm not able to select anything in this file, I don't know why) – lemon Apr 24 '18 at 7:37
• i wanted to try without translation to simplify the scenario. However, even here the points do not fit correctly into the desired coordinate system. If I try the unit matrix like in your gif, it works perfectly. However, as soon as the coordinate system is rotated, the points do not fit. I adjusted the Blendfile again, to show my problem a little more clearly. You can also see in the newly added image how the new coordinate system lies exactly and how faulty the new points are. The elements cannot be selected because I deactivated them in the outliner window (the mouse sursor there). – P. Sector Apr 24 '18 at 15:44
• Sorry, but I'm unable to see what is wrong. "incorrectly placed points", why? Orientation, location? – lemon Apr 24 '18 at 16:16
• The orientation and also the location of the new coordinates are wrong. I've added a picture of of my desired result. – P. Sector Apr 24 '18 at 16:42

Going by the edits to your post, it appears this is what you are trying to achieve.

Console code.

c = D.objects['zero_coordinatesys'].location
x = D.objects['axis_x'].location - c
y = D.objects['axis_y'].location - c
z = D.objects['axis_z'].location - c

m = Matrix((x, y, z))
m.is_orthogonal_axis_vectors
# True
# need to transpose because of order
m = m.transposed().to_4x4()
m.translation = c
# make it the matrix world of your pipe.
D.objects['Pipe'].matrix_world = m


Result.