0 | module Data.NumIdr.Transform.Rotation
 1 |
 2 | import Data.Vect
 3 | import Data.NumIdr.Interfaces
 4 | import Data.NumIdr.Array
 5 | import Data.NumIdr.Vector
 6 | import Data.NumIdr.Matrix
 7 | import Data.NumIdr.Homogeneous
 8 | import Data.NumIdr.Transform.Point
 9 | import Data.NumIdr.Transform.Transform
10 | import Data.NumIdr.Transform.Orthonormal
11 |
12 | %default total
13 |
14 |
15 | ||| A transform that contains a rotation.
16 | public export
17 | Rotation : Nat -> Type -> Type
18 | Rotation = Transform TRotation
19 |
20 |
21 | ||| Determine if a matrix represents a rotation.
22 | export
23 | isRotation' : FieldCmp a => Matrix' n a -> Bool
24 | isRotation' mat = isOrthonormal' mat && det mat == 1
25 |
26 | ||| Try to constuct a rotation from a matrix.
27 | export
28 | fromMatrix : FieldCmp a => Matrix' n a -> Maybe (Rotation n a)
29 | fromMatrix mat = if isRotation' mat then Just (unsafeMkTrans $ matrixToH mat)
30 |                                     else Nothing
31 |
32 | ||| Determine if a homogeneous matrix represents a rotation.
33 | export
34 | isRotation : FieldCmp a => HMatrix' n a -> Bool
35 | isRotation {n} mat with (viewShape mat)
36 |   _ | Shape [S n, S n] = isHMatrix mat && all (==0) (mat !!.. [EndBound last, One last])
37 |                             && isRotation' (getMatrix mat)
38 |
39 | export
40 | fromHMatrix : FieldCmp a => HMatrix' n a -> Maybe (Rotation n a)
41 | fromHMatrix mat = if isRotation mat then Just (unsafeMkTrans mat)
42 |                                     else Nothing
43 |
44 | ||| Construct a 2D rotation that rotates by the given angle (in radians).
45 | export
46 | rotate2D : Num a => Double -> Rotation 2 Double
47 | rotate2D = unsafeMkTrans . rotate2DH
48 |
49 |
50 | --------------------------------------------------------------------------------
51 | -- 3D rotations
52 | --------------------------------------------------------------------------------
53 |
54 |
55 | ||| Construct a 3D rotation around the x-axis.
56 | export
57 | rotate3DX : Double -> Rotation 3 Double
58 | rotate3DX = unsafeMkTrans . rotate3DXH
59 |
60 | ||| Construct a 3D rotation around the y-axis.
61 | export
62 | rotate3DY : Double -> Rotation 3 Double
63 | rotate3DY = unsafeMkTrans . rotate3DYH
64 |
65 | ||| Construct a 3D rotation around the z-axis.
66 | export
67 | rotate3DZ : Double -> Rotation 3 Double
68 | rotate3DZ = unsafeMkTrans . rotate3DZH
69 |
70 |
71 | ||| Construct a rotation representing an observer facing towards `dir`.
72 | |||
73 | ||| @ dir The facing direction, aligned with the z-axis.
74 | ||| @ up The vertical direction, the direction that the y-axis faces.
75 | export
76 | faceTowards : (dir, up : Vector 3 Double) -> Rotation 3 Double
77 | faceTowards dir up = let z = normalize dir
78 |                          x = normalize (up `cross` z)
79 |                          y = normalize (z `cross` x)
80 |                      in  unsafeMkTrans $ matrixToH $ hstack [x,y,z]
81 |