# Help the math challenged jamesk

(Jamesk) #1

I’ve got this problem. A bit embarrasing, but here goes: I don’t know any linear algebra! [snicker, what a bonehead]…

I need your help on this.

a) Assume that DV is a directional vector
b) Assume that P1 is a point in space

Now I need to calculate where P1 would end up if I move it, say 1 unit in the direction indicated by DV.

So, I would need a function like

``````
def moveIt(point_of_origin, distance_to_move, direction):
#fill in this blank
return the_new_point

``````

Could someone fill this func with the necessary stuff for me?

(Jamesk) #2

Well, this far along I know that there are at least 10 others that don’t know how to do this either. I’m obviously not alone

(d0pamine) #3

This would be my approach, assuming the arguments are lists in python:

``````
def moveIt(point_of_origin, distance_to_move, direction):
# make sure 'direction' is normalized (length == 1)
point_of_origin[0] += distance_to_move * direction[0]
point_of_origin[1] += distance_to_move * direction[1]
point_of_origin[2] += distance_to_move * direction[2]
return point_of_origin

``````

You can see that if direction = [0,0,1], the point would move in the z direction exactly distance_to_move units.

Cheers,
Tom

(theeth) #4

using this module called vecf.py

``````
"""
VECTOR FUNCTIONS
"""
from math import *
from dynoise import random, randuvec

# Return a new vector initialised to zero
def ZeroVector():
return [0.0, 0.0, 0.0]

#resize a until it is the same lenght as b, while retaining the orientation
def resize(a,b):
return vecmul( vnorm(a), veclen(b) )

return [a[0]+b[0], a[1]+b[1], a[2]+b[2]]

def vecsub(a,b):
return [a[0]-b[0], a[1]-b[1], a[2]-b[2]]

def vecmul(a, s):
return [a[0]*s, a[1]*s, a[2]*s]

def vecdiv(a, s):
if s!=0.0: s = 1.0/s
return vecmul(a, s)

# transform a Cartesian vector into a Geographic oriented vector ANGLES ARE IN DEGREES
def makeGeo(v):
tv = [0.0, 0.0, 0.0]
tv[0] = veclen(v)
tv[1] = atan2(v[0], v[1]) * 180 / pi
tv[2] = asin(vecnorm(v)[2]) * 180 / pi
return tv

# transfrom a geographic vector into a Cartesian vector ANGLES ARE IN DEGREES
def makeCart(v):
v[1] = v[1] / 180 * pi
v[2] = v[2] / 180 * pi
tv = [0.0, 0.0, 0.0]
tv[0] = v[0] * cos(v[2]) * cos(v[1])
tv[1] = v[0] * cos(v[2]) * sin(v[1])
tv[2] = v[0] * sin(v[2])
return tv

# return a copy of a vector, this is to prevent cross referencing
# like vector1 = vector2 which both point to the same object
def vcopy(v):
return [v[0], v[1], v[2]]

# normalize, but don't modify
def vecnorm(v):
# normalize vector
d = vdot(v, v)
if d&gt;0.0: d = 1./sqrt(d)
return vecmul(v, d)

# normalize
def vnorm(v):
# normalize vector
d = vdot(v, v)
if d&gt;0.0:
d = 1./sqrt(d); v[0]*=d; v[1]*=d; v[2]*=d
return v

# normalize and return length
def vnormlen(v):
# normalize vector
d = vdot(v, v)
if d&gt;0.0:
d = sqrt(d)
dv = 1./d; v[0]*=dv; v[1]*=dv; v[2]*=dv
return d

# normalize and return length squared
def vnormlensq(v):
# normalize vector
d = vdot(v, v)
if d&gt;0.0:
dv = 1./sqrt(d); v[0]*=dv; v[1]*=dv; v[2]*=dv
return d

# dotproduct
def vdot(v1, v2):
# dot product
return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]

# vector length
def veclen(v):
return sqrt(vdot(v, v))

# crossproduct
def crossp(v1, v2):
r = ZeroVector()
r[0] = v1[1]*v2[2] - v1[2]*v2[1]
r[1] = v1[2]*v2[0] - v1[0]*v2[2]
r[2] = v1[0]*v2[1] - v1[1]*v2[0]
return r

# scaled random vector
def randvecs(s):
v = randuvec()
v[0]*=s; v[1]*=s; v[2]*=s
return v

##################################
# random emitter shape functions #
##################################

# These are now all in the same format, so the function can be a stored as a 'pointer'
# All return two values, position and velocity

def RandomLine(vs):
return [vs[0] * (2.0 * random()-1.0), 0.0, 0.0], randuvec()

def RandomPlane(vs):
return [vs[0] * (2.0 * random()-1.0), vs[1] * (2.0 * random() - 1.0), 0.0], randuvec()

def RandomDisc(vs):
v = randuvec()
return [vs[0] * v[0], vs[1] * v[1], 0.0], randuvec()

def RandomCylinder(vs):
v = randuvec()
return [vs[0] * v[0], vs[1] * v[1], vs[2] * (2.0*random()-1.0)], randuvec()

def RandomCone(vs):
v = randuvec()
return [vs[0] * v[0], vs[1] * v[1], vs[2] * sqrt(v[0]*v[0]+v[1]*v[1])], randuvec()

def RandomSphere(vs):
v = randvecs(random())
return [vs[0] * v[0], vs[1] * v[1], vs[2] * v[2]], randuvec()

def RandomCube(vs):
v = [2.0 * (random() - 0.5), 2.0 * (random() - 0.5), 2.0 * (random() - 0.5)]
return [vs[0] * v[0], vs[1] * v[1], vs[2] * v[2]], randuvec()

# used for mesh and point emitters
def RandomConeVelocity(angle):
ty = 6.283185307 * random()
tp = 1.570796327 + angle * random()
return [-sin(ty)*cos(tp), cos(tp)*cos(ty), sin(tp)]

# For reasons of consistency it is called RandomPoint, but it always returns [0,0,0]
# vs not used as scale, vs[2] is used to store angle
def RandomPoint(vs):
return ZeroVector(), RandomConeVelocity(vs[2])

#######################

# calculate reflected direction
def reflect(dirc, norm):
ndir = ZeroVector()	# new direction
t = -2.0 * vdot(dirc, norm)
ndir[0] = t * norm[0] + dirc[0]
ndir[1] = t * norm[1] + dirc[1]
ndir[2] = t * norm[2] + dirc[2]
return ndir

#######################

# Curve calculation (cubic hermite interpolation)
# From p1 to p2, p0 & p3 are the points before and after these points to calculate the gradient
# t is the time value
def HCurve(p0, p1, p2, p3, t):
t2 = t * t
t3 = t2 * t
kp0 = (2.0 * t2 - t3 - t) * 0.5
kp1 = 1.5 * t3 - 2.5 * t2 + 1.0
kp2 = (4.0 * t2 - 3.0 * t3 + t) * 0.5
kp3 = (t3 - t2) * 0.5
r = ZeroVector()
r[0] = p0[0] * kp0 + p1[0] * kp1 + p2[0] * kp2 + p3[0] * kp3
r[1] = p0[1] * kp0 + p1[1] * kp1 + p2[1] * kp2 + p3[1] * kp3
r[2] = p0[2] * kp0 + p1[2] * kp1 + p2[2] * kp2 + p3[2] * kp3
return r

# alternate method, cubic interpolation, same arguments as HCurve
def CCurve(p0, p1, p2, p3, t):
t2 = t * t
t3 = t2 * t
d01 = vecsub(p0, p1)
a = vecsub(vecsub(p3, p2), d01)
b = vecsub(d01, a)
c = vecsub(p2, p0)
r = ZeroVector()
r[0] = a[0]*t3 + b[0]*t2 + c[0]*t + p1[0]
r[1] = a[1]*t3 + b[1]*t2 + c[1]*t + p1[1]
r[2] = a[2]*t3 + b[2]*t2 + c[2]*t + p1[2]
return r

#########################
# MATRIX FUNCTIONS
#########################

#returns a list of list of float from a Matrix object (unpickleable)
def convertFL(mtx):
fmtx = []
for row in mtx:
fmtx.append([x for x in row])
return fmtx

# returns 3x3 identity matrix
def MtxIdentity3x3():
return [[ 1.0, 0.0, 0.0],
[ 0.0, 1.0, 0.0],
[ 0.0, 0.0, 1.0]]

# returns 4x4 identity matrix
def MtxIdentity4x4():
return [[ 1.0, 0.0, 0.0, 0.0],
[ 0.0, 1.0, 0.0, 0.0],
[ 0.0, 0.0, 1.0, 0.0],
[ 0.0, 0.0, 0.0, 1.0]]

# multiplies two matrices, d determines 3x3(d=3) or 4x4(d=4)
def mulmat(m1, m2, d):
r = MtxIdentity4x4()	#just for initialisation
for i in range(d):
for j in range(d):
rij = 0.0
for k in range(d): rij += m1[i][k] * m2[k][j]
r[i][j] = rij
return r

# multiply 3X3 matrix (rotation, scaling) with vector
def mulmatvec3x3(m, v):
r = ZeroVector()
r[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]
r[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]
r[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]
return r

# multiply 4X3 matrix (rotation, scaling & translation) with vector
def mulmatvec4x3(m, v):
r = ZeroVector()
r[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0] + m[3][0]
r[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1] + m[3][1]
r[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2] + m[3][2]
return r

# transpose 3X3 matrix, the inverse rotation matrix
def transp3x3(m):
r = MtxIdentity3x3()
for i in range(3):
for j in range(3): r[i][j] = m[j][i]
return r

# creates rotation matrix around X, Y or Z
# axis must be 'X', 'Y' or anything else=='Z'
# angle in radians, all made equivalent to blenders matrices from RotXYZ
def makeRotMtx(axis, angle):
if axis=='X':
rs, rc = sin(angle), cos(angle)
mtx = [	[1.0, 0.0, 0.0],
[0.0,  rc, rs],
[0.0, -rs, rc] ]
elif axis=='Y':
rs, rc = sin(angle), cos(angle)
mtx = [	[ rc, 0.0, -rs],
[0.0, 1.0, 0.0],
[ rs, 0.0,  rc] ]
else:
rs, rc = sin(angle), cos(angle)
mtx = [	[ rc,  rs, 0.0],
[-rs,  rc, 0.0],
[0.0, 0.0, 1.0] ]
return mtx

# creates full 3D rotation matrix
# rx, ry, rz angles in radians
def makeRotMtx3D(rx, ry, rz):
# old slow indirect method
#mtx_x = makeRotMtx('X', rx)
#mtx_y = makeRotMtx('Y', ry)
#mtx_z = makeRotMtx('Z', rz)
#mtx = mulmat(mulmat(mtx_x, mtx_y, 3), mtx_z, 3)
# faster equivalent
# mtx_x =	[1, 0, 0]
#			[0, B, A]
#			[0,-A, B]
# mtx_y =	[D, 0, -C]
#			[0, 1,  0]
#			[C, 0,  D]
# 1.D +  0.0 +  0.C, 1.0 +  0.1 +  0.0, 1.-C +  0.0 +  0.D =  D,  0, -C
# 0.D +  B.0 +  A.C, 0.0 +  B.1 +  A.0, 0.-C +  B.0 +  A.D = AC,  B, AD
# 0.D + -A.0 +  B.C, 0.0 + -A.1 +  B.0, 0.-C + -A.0 +  B.D = BC, -A, BD
# mtx_xy =	[ D, 0,  -C]
#			[BC, -A, BD]
# mtx_z =	[ F, E, 0]
#			[-E, F, 0]
#			[ 0, 0, 1]
# D.F + 0.-E + -C.0 , D.E + 0.F + -C.0 , D.0 + 0.0 + -C.1 = DF, DE, -C
# BC.F + -A.-E + BD.0 , BC.E + -A.F + BD.0 , BC.0 + -A.0 + BD.1 = BCF+AE, BCE-AF, BD
A, B = sin(rx), cos(rx)
C, D = sin(ry), cos(ry)
E, F = sin(rz), cos(rz)
AC, BC = A*C, B*C
return [[D*F, 	   D*E, 	 -C],
[AC*F-B*E, AC*E+B*F, A*D],
[BC*F+A*E, BC*E-A*F, B*D]]

# creates rotation matrix from a normalized direction vector
# z-rotation is ignored!
def makeRotMtx_fromVec(tv):
v = vcopy(tv)
v[1], v[2] = v[2], v[1]
r = v[0]*v[0] + v[1]*v[1]
if r&gt;0.0: r = (acos(v[2]) / sqrt(r)) / pi
u, v = v[0]*r, v[1]*r
theta, phi = atan2(v, u), pi*sqrt(u*u + v*v)
mtx = makeRotMtx3D(phi+0.5*pi, 0.5*pi-theta, 0.0)
return mtx

``````

you can do

``````
DV = [x, y, z]
P1 = [x, y, z]
S = Scalar