0 | module Data.NumIdr.Transform.Orthonormal
 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 |
11 | %default total
12 |
13 |
14 | ||| An orthonormal transform is one that contains an orthonormal matrix,
15 | ||| also known as an improper rotation or rotoreflection.
16 | public export
17 | Orthonormal : Nat -> Type -> Type
18 | Orthonormal = Transform TOrthonormal
19 |
20 |
21 | ||| Determine if a matrix represents an orthonormal transform.
22 | export
23 | isOrthonormal' : Eq a => Num a => Matrix' n a -> Bool
24 | isOrthonormal' {n} mat with (viewShape mat)
25 |   _ | Shape [n,n] = identity == fromFunction [n,n] (\[i,j] => getColumn i mat `dot` getColumn j mat)
26 |
27 | ||| Try to construct an orthonormal transform from a matrix.
28 | export
29 | fromMatrix : Eq a => Num a => Matrix' n a -> Maybe (Orthonormal n a)
30 | fromMatrix mat = if isOrthonormal' mat then Just (unsafeMkTrans (matrixToH mat))
31 |                                        else Nothing
32 |
33 |
34 | ||| Determine if a homogeneous matrix represents a rotation.
35 | export
36 | isOrthonormal : Eq a => Num a => HMatrix' n a -> Bool
37 | isOrthonormal {n} mat with (viewShape mat)
38 |   _ | Shape [S n, S n] = isHMatrix mat && all (==0) (mat !!.. [EndBound last, One last])
39 |                             && isOrthonormal' (getMatrix mat)
40 |
41 | export
42 | fromHMatrix : Eq a => Num a => HMatrix' n a -> Maybe (Orthonormal n a)
43 | fromHMatrix mat = if isOrthonormal mat then Just (unsafeMkTrans mat) else Nothing
44 |
45 |
46 | --------------------------------------------------------------------------------
47 | -- Reflections
48 | --------------------------------------------------------------------------------
49 |
50 |
51 | ||| Construct an orthonormal transform that reflects a particular coordinate.
52 | export
53 | reflect : {n : _} -> Neg a => Fin n -> Orthonormal n a
54 | reflect = unsafeMkTrans . reflectH
55 |
56 | ||| The orthonormal transform that reflects on the x-coordinate (first coordinate).
57 | export
58 | reflectX : {n : _} -> Neg a => Orthonormal (1 + n) a
59 | reflectX = reflect 0
60 |
61 | ||| The orthonormal transform that reflects on the y-coordinate (second coordinate).
62 | export
63 | reflectY : {n : _} -> Neg a => Orthonormal (2 + n) a
64 | reflectY = reflect 1
65 |
66 | ||| The orthonormal transform that reflects on the z-coordinate (third coordinate).
67 | export
68 | reflectZ : {n : _} -> Neg a => Orthonormal (3 + n) a
69 | reflectZ = reflect 2
70 |
71 |
72 | ||| Construct an orthonormal transform that reflects along a hyperplane of the
73 | ||| given normal vector. The input does not have to be a unit vector.
74 | export
75 | reflectNormal : (Neg a, Fractional a) => Vector n a -> Orthonormal n a
76 | reflectNormal {n} v with (viewShape v)
77 |   _ | Shape [n] = unsafeMkTrans $ matrixToH $ identity - (2 / normSq v) *. outer v v
78 |