﻿ Vector, the Journal of the British APL Association

## Volumes

British APL Association

Archive articles posted online on request: ask the archivist.

Volume 26, No.1

• online
• 1.0

# by Norman Thomson

A general objective of J-ottings over the years has been to draw attention to the considerable number of mathematical or mathematical type routines which are built into J primitives thereby leading to significant reductions of programming effort. One such feature is the versatility of j which although primarily a complex number constructor is adaptable to other circumstances in which objects are defined by pairs of numbers, for example betting odds (see J-ottings 54).

A further example concerns transformations of a 2-dimensional plane by means of matrices of the form where a and are b real numbers. A transformation such as is called a similitude, that is a transformation which results in the combination of an anti-clockwise rotation about the origin and an enlargement of the objects described by the coordinates. (For a clockwise rotation exchange b and –b ). Given `det=.-/ .*` standing for determinant, det M is a² + b² and its square root is the enlargement E. The rotation component is represented by M divided by E, resulting in a matrix of the form where t is the anti-clockwise angle of rotation.

Now although a similtude could be applied to a triangle whose points are, say, (0,0), (2,1) and (0,1) by

```   ]M=.2 2\$2 _3 3 2		NB. similitude matrix
2 _3
3  2
]tri=.2 3\$0 2 0 0 1 1
0 2 0
0 1 1
M +/ .*tri
0 1 _3
0 8  2
```

to give the transformed triangle (0,0), (1,8), (-3,2), clearly M is defined by the number pair (a,b) and so can be represented compactly as a `j` pair, in which case enlargement E and rotation t are given by :

```   10 o. 2j3
3.60555                     NB. enlargement=sqrt of 2^2 + 3^2
(%10&o.)2j3
0.5547j0.83205              NB. (cos x)j(sin x) where tan x=3%2
```

Instead of using a matrix inner product to transform points, simple multiplication is all that is required, so that the previous triangle transformation is given by

```   each=.&>
2j3*each 0j0 2j1 0j1     NB. triangle transformation
0 1j8 _3j2
```

Also since multiplication is commutative, a product such as `2j3*2j1` has two geometric interpretations, viz. the similtude `2j3` transforms the point (2,1) to the point (1,8) and the similtude `2j1` transforms the point (2,3) to (1,8).

For rotation without enlargement the transformed coordinates of the point (x, y) in the new frame of reference are which can be confirmed by elementary trigonometry: The components of displacement from {x, y} are thus or which can be written .

The object of this rearrangement will become apparent shortly.

## Rotations in three dimensions

Here the geometry is more complicated and j no longer helps. Take those rotations in which any line through the origin may be chosen as axis. Define such a rotation by any point on it other than the origin, and normalise this so that the defining point lies on the unit sphere. The results of this normalisation are the direction cosines of the axis of rotation, that is the cosines of the angles which this axis makes separately with each of the coordinate axes :

```   dircos=.% %:@(+/@:*:)       NB. direction cosines
dircos 3 4 5
0.424264 0.565685 0.707107 ```

A necessary preliminary is to obtain the cross-product of the rotation vector and a point to be rotated. To my knowledge there is no primitive which delivers cross-products directly, however it is a reasonably straightforward to write a verb xp. First stitch 3 4 5 (defining the axis) to 1 2 3, a point to rotated, and use the ‘all but one’ technique described in J-ottings 52 to obtain the submatrices obtained by progressively eliminating one row at a time. The determinant of each of these 2x2 matrices is required with a suitable adjustment for alternating signs leading to :

```xp=.4 : '1 _1 1*det each<"(2) 1+\.(dircos x),.y'
```

One other requirement is an identity matrix of appropriate length :

```   id=.=@i.@#               NB. identity matrix
```

Now suppose the anti-clockwise angle of rotation looking outwards from the origin is t. By a pleasing analogy with the two dimensional case the displacement components are

```- (1 - cos t) times <a vector>  -  sin t times <a cross-product>
```

Where ‘a vector’ is the result of the matrix multiplication in which the λs are the direction cosines of the axis of rotation. The parameters defining a rotation are thus an axis (three coordinates) joined to the angle t, and it seems natural to take this 4-element vector as the left argument of a rotation verb. Also many people are more comfortable with degrees rather than radians, so define :

```dtor=.180%~o.               NB. degrees to radians
```

rm defines the rotation matrix above and rmdata multiplies it with the coordinates of the data point being rotated :

```rm =.(id - */~)@dircos      NB. rotation matrix
rm 3 4 5
0.82 _0.24 _0.3
_0.24  0.68 _0.4
_0.3  _0.4  0.5
rmdata=.rm@dircos@(}:@[) +/ .* ]
(3 4 5,dtor 60) rmdata 1 2 3
_0.56 _0.08 0.4
```

(As an aside, taking the z axis as axis of rotation (0 0 1) so that λ3 = 1 and λ 1 = λ2 = 0 gives

```    rm 0 0 1
1 0 0
0 1 0
0 0 0
```

which multiplies to give , while the cross-product of is so that this reduces to the formula given earlier for the two-dimensional case. )

Next define m1 and m2, bearing in mind that t has to be extracted as the 4th element of the rotation vector:

```    m1=.-.@(2&o.@({:@[))	NB. (1-cos t)
m2=.1&o.@({:@[)	        NB. sin t
```

Finally reflect the formula for the displacement components in

```    rotate=.] - (m1 * rmdata) + m2 * }:@[ xp ]
(1 0 0,dtor 90)rotate 1 2 3
1 3 _2
```

A couple of further checks helps confirm understanding :

(a) Rotate the point (1,2,3) through a clockwise angle of 90o about the x-axis:

```   (1 0 0,dtor _90)rotate 1 2 3
1 _3 2
```

(b) Undo a clockwise rotation of (1,2,3) with an anti-clockwise one :

```    axis=.?3\$10	NB. choose an axis at random
(axis,dtor 60)rotate (axis,dtor _60)rotate 1 2 3
1 2 3
```

Multiple data points are dealt with by, for example

```   (<3 4 5,dtor 60)rotate each 1 2 3;2 3 1;3 1 2
1.03505  2.5299 2.55505
3.03722 1.56268 1.52753
1.82258 0.31773 3.25227
```

For practical uses consider that every minute of every day we all perform rotations on a merry-go-round called Earth which itself rotates continuously within an even larger solar system which itself gyrates around another even larger system and so on. Alternatively, from an earth-bound view, units of this larger system are in a perpetual state of 3-D rotation about what appears to us as a fixed axis. Perhaps there’s an idea here for next time …

```script began 1:04:58
caching off
debug mode off
cache time 3600 sec