Monday, 30 June 2014

Metasequoia Script – Using Quaternions to Rotate Points

You can use a Python script in Metasequoia to demonstrate the quaternion sandwich product rotating a point.

I have set up a Metasequoia document as shown below.

Demonstate quatenion sandwich product in Metasequoia 4

The document shows a point object located on the X axis which will be rotated about the Y axis. The axis of rotation is shown by an orange coloured line object.

A counter-clockwise rotation about an axis when the rotation is viewed from the positive of end of the axis towards the zero end of that axis is a positive rotation.

To visualise this I have placed a clock face at the origin of the Y axis.

If you copy this example, the object name for the point object must be “point” and the object name for the axis object must be “axis”. The axis object must be a line with one or both points at (0, 0, 0).

The script is shown below and uses information contained in my post on quaternions [link].

# clear the script editor output window each run
MQSystem.clearLog()

# can add path where Python looks for modules
# with sys.path
import sys
sys.path.append("./Script")

# need pi, sin and cos from math module
import math

def pr(message):
 '''
 Save some typing
 '''
 MQSystem.println(str(message))
 return
 
def quat(axis, angle):
 '''
 Create a quaternion from an axis and an angle.
 The axis must be an MQPoint
 The axis will be normalized in this function
 The angle must be in degrees
 A quaternion is returned as a Python tuple
 '''
 theta = math.pi * angle / 180.0
 halftheta = theta / 2.0
 v = axis.getNormal()
 c = math.cos(halftheta)
 s = math.sin(halftheta)
 return (s*v.x, s*v.y, s*v.z, c)
 
def q_inv(q):
 '''
 Returns the inverse of a unit quaternion q
 A quaternion is returned as a Python tuple
 '''
 return (-q[0],-q[1],-q[2],q[3])
  
def pxq(p,q):
 '''
 Returns the multiplication of two quaternions
 A quaternion is returned as a Python tuple
 '''
 p1,p2,p3,p4 = p[0],p[1],p[2],p[3]
 q1,q2,q3,q4 = q[0],q[1],q[2],q[3]
 
 i = p4*q1-p3*q2+p2*q3+p1*q4
 j = p3*q1+p4*q2-p1*q3+p2*q4
 k = -p2*q1+p1*q2+p4*q3+p3*q4
 w = -p1*q1-p2*q2-p3*q3+p4*q4
 
 return (i,j,k,w)

# input the axis of the rotation here
axis = MQSystem.newPoint(0,1,0)

# input the angle here
angle = 45.0 # degrees

# the quaternion
q = quat(axis, angle)
pr("q is %s"%str(q))

# the inverse quaternion
qi = q_inv(q)
pr("qi is %s"%str(qi))

doc = MQSystem.getDocument()

if doc.numObject>0:
 obj = None
 for ob in doc.object:
  if ob:
   if ob.name.lower()=="point":
    obj = ob
    break
 line = None
 for ob in doc.object:
  if ob:
   if ob.name.lower()=="axis":
    line = ob
    break
    
 if obj:
  if line:
   if line.numVertex == 2:
   # creates a line showing the axis of rotation
    sc = 100
    pt = MQSystem.newPoint(axis.x*sc,axis.y*sc,axis.z*sc)
    line.vertex[1].setPos(pt)
  for v in obj.vertex:
   ax = v.getPos()
   p = (ax.x,ax.y,ax.z,0)
   qxp = pxq(q,p)
   # r is the result of q x p x qi
   # i.e. the sandwich product
   r = pxq(qxp,qi)
   pp = MQSystem.newPoint(r[0],r[1],r[2])   
   v.setPos(pp)
   
  
pr("Script finished")



Repeatedly running the script rotates the point counter-clockwise about the Y axis in steps of 45 degrees.

You can change the axis of rotation and angle of rotation by changing the values in the script.


quatscript

This post [link] has some basic information about using Metasequoia’s script editor.

No comments:

Post a Comment