import math


def axisRotate(p_a, v_a, p, theta):
    """ 
    Rotate p by the angle theta around the line defined by the point p_a and 
    the vector v_a. Does not assume v_a is normalized. 
    """
    #From http://inside.mines.edu/fs_home/gmurray/ArbitraryAxisRotation/
    x,y,z = p
    a,b,c = p_a
    u,v,w = v_a
    t1 = 1-math.cos(theta) #Avoids repeated computations
    t2 = math.cos(theta)   #Avoids repeated computations
    t3 = math.sin(theta)   #Avoids repeated computations
    t4 = -u*x-v*y-w*z      #Avoids repeated computations
    Rx = (a*(v*v+w*w)-u*(b*v+c*w+t4))*t1 + x*t2 + (-c*v+b*w-w*y+v*z)*t3
    Ry = (b*(u*u+w*w)-v*(a*u+c*w+t4))*t1 + y*t2 + ( c*u-a*w+w*x-u*z)*t3
    Rz = (c*(u*u+v*v)-w*(a*u+b*v+t4))*t1 + z*t2 + (-b*u+a*v-v*x+u*y)*t3
    return [Rx,Ry,Rz]