# Rotation: using quaternions in Igor Pro

Quaternions are essentially magic. With just four numbers, they can describe the position and orientation of an object in space. For example, the rotation of an object about one axis. Consecutive rotations can also be described by a quaternion.

There are many explainer articles which help to understand quaternions and their uses (they are used extensively in computer graphics, particularly in gaming). Quaternions are tough to understand but when you do, you can see why Hamilton, the Irish Mathematician who discovered them, engraved his eureka moment on the side of a bridge in Dublin.

In Igor, 3D objects are displayed in a Gizmo window. There are three keywords that allow rotation: setQuaternion, setRotationMatrix and euler. The focus here is on setQuaternion. Note that it is possible to use appendRotation to add successive rotations (specified using a quaternion). Here I am going to show some code to do three distinct rotations in a single quaternion.

First let’s make an object:

The code to make this object is below:

```Function MakeATestObject()
String gizName = "testGiz"
KillWindow/Z \$gizName
NewGizmo/N=\$gizName
AppendToGizmo/N=\$gizName/D pieWedge=pieWedge0
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ calcNormals,1}
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ rMin,0.3}
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ colorType,2}
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ topRGBA,1,0.499947,0.250019,1}
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ sidesRGBA,0.533333,0.533333,0.533333,1}
AppendToGizmo/N=\$gizName/D Axes=BoxAxes,name=axes0
ModifyGizmo/N=\$gizName setOuterBox={-1,1,-1,1,-1,1}
ModifyGizmo/N=\$gizName scalingOption=0
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ zMin,0}
ModifyGizmo/N=\$gizName ModifyObject=pieWedge0,objectType=pieWedge,property={ zMax,-1}
//	AppendToGizmo/N=\$gizName/D freeAxesCue={0,0,0,1},name=freeAxesCue0
ModifyGizmo/N=\$gizName showAxisCue=1
End
```

Now that we have an object we can rotate it using a command like this:

```ModifyGizmo/N=\$gizName setQuaternion={0.5,0.5,0.5,0.5}
```

This is where x,y,z and w terms of the quaternion are 0.5. This will rotate the object such that the Z-axis points up, the Y-axis points right and the X-axis points forward. But how do we specify those terms?

A function to set the four terms is given below. First, a 4 point wave needs to be made and fed to the function specifying the vector of the axis for rotation, and the angle. So for example, MakeQuaternion(1,0,0,pi/2,wave0) will put into wave0, the rotation of 90 degrees CCW about the X-axis.

```Function MakeQuaternion(Ax,Ay,Az,theta,w)
Variable Ax,Ay,Az,theta
Wave w
Variable N = sqrt(Ax^2 + Ay^2 + Az^2)
w = Ax * sin(theta/2)/N
w = Ay * sin(theta/2)/N
w = Az * sin(theta/2)/N
w = cos(theta/2)
End
```

As mentioned above quaternions can be combined in a product quaternion. This code is modified from the Igor Help File.

```Function MultiplyQuaternions(q1,q2,qr)
Wave q1,q2,qr

Variable w2 = q2
Variable w1 = q1
qr = w2 * w1 - (q2 * q1 + q2 * q1 + q2 * q1)
Make/N=4/FREE vcross = 0
vcross = (q1 * q2) - (q1 * q2)
vcross = (q1 * q2) - (q1 * q2)
vcross = (q1 * q2) - (q1 * q2)
MatrixOP/FREE aa = w2 * q1 + w1 * q2 + vcross
qr = aa
qr = aa
qr = aa
Variable NN = norm(qr)
qr /= NN
End
```

In that function, three waves are specified. q1 and q2 contain the first and second rotations as quaternions and the result goes into qr.

What is really neat is that we can combine two quaternions, but then also use the result with a further quaternion to do three rotations. This gives us a single quaternion that specifies the desired position of our object.

```Function TestIt(GizName)
String GizName
Make/O/N=4/FREE p1,p2,pr
MakeQuaternion(1,0,0,pi/2,p1) // 90 CCW about X
MakeQuaternion(0,1,0,0.75 * pi,p2) // 135 CCW about Y
MultiplyQuaternions(p1,p2,pr)
p1[] = pr[p]
MakeQuaternion(1,0,0,1.75 * pi,p2) // 315 CCW about X
MultiplyQuaternions(p1,p2,pr)
ModifyGizmo/N=\$gizName setQuaternion={pr,pr,pr,pr}
End
```

Notice how p1 gets reset as the result of the combination of p1 and p2, then combined with a third rotation (in p2) to give the final result, pr.