# How to compute and visualize a Vector?

I would like to use Blender to visualize what I'm calculating with linear algebra formulas, I need to perform linear functions starting with a 2D or 3D vector and multiply this entity with a custom defined matrix; the result of this is a vector that I would like to visualize in some sort of way on the scene ( an arrow, a cilinder, a 3D shape a 2D shape, something ... possibly with colors so I can visualize multiple vector on the same scene ).

Now I know how to get the x,y,z coordinates for each vertex,

# 1 possible way to get x
bpy.context.object.data.vertices.co.x


I don't know how to get an object of type Vector out of this ( 2D or 3D vector ) and fill a matrix ( tipically a 3x3 matrix ) that I can use to perform the computation.

I'm basically having a little trouble understanding how to get the types that I want for the task that I need to perform.

And in the end I also need to keep the result of this computation, tipically an array of vectors/vertices, on the scene in an easy-to-visualize way.

I'm using Blender 2.68a.

Thanks.

The documents for the Matrix and Vector classes are invaluable reading.

from mathutils import Vector

# zero vector, a default
v1 = Vector()

# quick-hand reference to the class.
print(dir(v1))

# using integers or floats
v2 = Vector((1, 0, 0))
v3 = Vector((1.0, 3.0, 0.0))

x, y, z = v3.to_tuple()

v3.xyz
# Vector((1.0, 3.0, 0.0))

v3.zyx
# Vector((0.0, 3.0, 1.0))

# normalize the vector in place, overwrites the value of original vector
v3.normalize()

# normalized returns a normalized copy but does not modify the original.
v3.normalized()


There are many more methods in the Vector class, all covered in the documentation. Unfortunately there are no ready made tools for blender that will draw the head and tail of vectors in the way that you describe. I can see how they would be useful for teaching about vectors initially.

Math Viz addon, doesn't have much documentation but it is straight forward enough. Enable the addon then use the python console to enter these one by one while observing what happens in the 3d view.

v1 = Vector()
v2 = Vector((1,1,0))
line = [v1, v2]   # brackets are optional


If you want to delete any you can do del v1 or del line

I would suggest to add empty objects, or create a mesh to visualize Matrix/Euler/Vector types.

As a handy alternative to this, Blender comes with the MathVis addon that draws python defined variables in the view-port.

• what is the namespace for this types ? Aug 23 '13 at 7:54
• @user1154, For MathVis - the consoles global namespace is currently used. Aug 23 '13 at 9:42

I realize this is an old question, but I came across it. The other answers point to the MathVis addon, certainly a good tool, though I did not know it before.

My personal use case, coming from the python side, was more on the "visualize" part of the original question: I want to animate rigid body kinematics (which I get from actual measurements) and add visual arrows to represent all kinds of vectors.

Here's what I came up with; I acknowledge it is only sloppily integrated with blender. Maybe it still helps someone. (if you need colors, simply link a material to the shaft/tip)

import bpy
import numpy as np

class PhysVector(object):
# a physics vector visualization (e.g. Forces, Moments, velocities...)

def __init__(self, label, radius = 0.1, tip_width = 1.5, tip_length = 2., collection = 'Collection'):
# prepare the components of the vector: a shaft (cylinder) and a tip (cone)
# the apex of the tip will be at the specified location (see SetPosition)
# input:
#   label -> a label (will be the name of the object)
#   tip_width -> the width of the tip, as multiples of radius
#   tip_length -> the length of the tip, as multiples of radius
#

# a name for the arrow
self.label = label

## (0) the PhysVector group
# preparing a group to store shaft and tip
self.group = bpy.data.objects.new(self.label, None) # empty data object
self.group.name = self.label # correct name display
self.group.rotation_mode = 'QUATERNION' # set rotation mode; I recommend quaternions.

# lock the scaling, because it would affect vector length
self.group.lock_scale = [True]*3

# the tip length will be needed on position update

## (1) the shaft
# always a head_length shorter than one.
, depth=1.-self.tip_length \
, location=(0, 0, 0.5-self.tip_length/2) \
)
self.shaft = bpy.context.selected_objects

# name the shaft
bpy.context.active_object.name = f'{self.label}_shaft'

# set rotation mode (because quaternions are cool)
self.shaft.rotation_mode = 'QUATERNION'

# set the origin to the base of the shaft.
bpy.context.scene.cursor.location = (0., 0., 0.) # (by using the world cursor)
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

# add the shaft to the group
self.shaft.parent = self.group
# moved and rotated with the group
self.shaft.lock_location = [True]*3
self.shaft.lock_rotation_w = True
self.shaft.lock_rotation = [True]*3

## (2) the tip
# as with the shaft, but filling the space to unit length
, depth = self.tip_length \
, location=(0, 0, 1.-(self.tip_length/2)) \
)
self.tip = bpy.context.selected_objects

# naming
bpy.context.active_object.name = f'{self.label}_tip'

# rotation mode (quaternions are for geeks)
self.tip.rotation_mode = 'QUATERNION'

# set the origin of the tip to the apex (via world cursor)
bpy.context.scene.cursor.location = (0., 0., 1.)
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')

# add the tip to the group
self.tip.parent = self.group
# moved and rotated with the group
self.tip.lock_location = [True, True, False]
self.tip.lock_rotation_w = True
self.tip.lock_rotation = [True]*3

# reset cursor position
bpy.context.scene.cursor.location = (0., 0., 0.)

# store position
self.position = [(0.,0.,0.), (0.,0.,1.)] # (to avoid keyframe overwriting)

## initialization done!

def SetPosition(self, p0, p1):
# set the position of the vector, given by a base and tip point
# The arrow will increase/decrease length, but radius and head length are fixed.
# input:
#   p0 -> the base ponit
#   p1 -> the tip (apex) point

# update stored position
self.position = [p0, p1]

# the vector is avtually the difference between tip and base
vec = np.subtract(p1, p0)
# a reference is needed to get the rotation quaternion
ref = np.array([0., 0., 1.])

## (i) position
# move the whole group, by setting its location
self.group.location = p0
# ... and adjust the tip relative position
self.tip.location = (0., 0., np.linalg.norm(vec))

## (ii) scaling
# adjust the tip length; too short vectors are smaller.
tip_length = np.min([self.tip_length, np.linalg.norm(vec)])
self.tip.scale = [tip_length/self.tip_length]*3

# set the shaft length (originally little less than 1.0) by adjusting the scale
# if vector is too short, radius is scaled down (as with tip)
shaft_length = (np.linalg.norm(vec)-self.tip_length)/(1-self.tip_length)
self.shaft.scale = (tip_length/self.tip_length, tip_length/self.tip_length \
, np.max([0., shaft_length]) \
)

## (iii) rotation
# did I mention how awesome quaternions are?
# this is just one of the many unit quaternions which will rotate the ref vector to the desired position.
q_w = np.linalg.norm(ref) * np.linalg.norm(vec) + np.dot(ref, vec)
q_x, q_y, q_z = np.cross(ref, vec)

# with that, the whole vector is rotated.
self.group.rotation_quaternion = (q_w, q_x, q_y, q_z)

def SetKeyframe(self, frame_nr = None):
# insert a keyframe with the current vector orientation

if frame_nr is not None:
# first, go to the specified frame number
bpy.context.scene.frame_set(frame_nr)
# changing frame will reset the configuration; restore it:
self.SetPosition(*self.position)

# the group controls location and rotation
self.group.keyframe_insert(data_path = 'location', index = -1)
self.group.keyframe_insert(data_path = 'rotation_quaternion', index = -1)

# the elements only change in certain aspects
self.shaft.keyframe_insert(data_path = 'scale', index = -1)
self.tip.keyframe_insert(data_path = 'location', index = -1)
self.tip.keyframe_insert(data_path = 'scale', index = -1)

# note: when animation starts/ends at very short vectors (vsv), the scaling
#       of the shaft radius will be visible. To avoid that,
#       (a) insert many intermediate keyframes or
#       (b) fix the x/y scaling in "SetPosition" above (but then the tip will flatten).

if __name__ == "__main__":
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)

vm = PhysVector(label = 'v1', radius = 0.1, tip_width = 1.5, tip_length = 2.)

# animation example
bpy.context.scene.frame_end = 50

vm.SetPosition((0.4, 0., 0.2), (-0.6, 0., 1.2))
vm.SetKeyframe(0)

# next frame
vm.SetPosition(np.array((0.4, 0.2, 0.6)).ravel(), np.array((4.4, -0.2, 0.2)).ravel())
vm.SetKeyframe(24)

# test short vector
vm.SetPosition((0.0, 0., 0.0), (0.05, 0.05, 0.05))
vm.SetKeyframe(50)



If you wanna fill a matrix with a location vector, then it needs to be 4x4 transformation matrix of course (3x3 is used for rotation, CryEngine uses 3x4 for loc+rot, 4x4 is loc+rot+scale).

There's a utility function to create a 4x4 translation matrix from a 3d vector:

Matrix.Translation(bpy.context.object.data.vertices.co)