@@ -21,22 +21,18 @@ such that
21
21
"""
22
22
abstract AbstractAffineTransformation <: Transformation
23
23
24
- matrix (:: AbstractAffineTransform ) = error (" AbstractAffineTransformation's must implement matrix()" )
25
- translation (:: AbstractAffineTransform ) = error (" AbstractAffineTransformation's must implement translation()" )
24
+ matrix (:: AbstractAffineTransformation ) = error (" AbstractAffineTransformation's must implement matrix()" )
25
+ translation (:: AbstractAffineTransformation ) = error (" AbstractAffineTransformation's must implement translation()" )
26
26
translation_reverse (:: AbstractAffineTransformation ) = matrix (trans) \ translation (trans)
27
27
28
28
# Default implementations
29
29
@compat function (trans:: AbstractAffineTransformation )(x)
30
30
matrix (trans) * x + translation (trans)
31
31
end
32
32
33
- transform_deriv (trans:: AbstractAffineTransformation ) = matrix (trans)
34
-
35
33
# Could try do similar for transform_deriv_params()?
36
34
37
- @compat function (trans:: AbstractAffineTransformation )(x)
38
- matrix (trans) * x + translation (x)
39
- end
35
+ transform_deriv (trans:: AbstractAffineTransformation , x) = matrix (trans)
40
36
41
37
function Base. inv (trans:: AbstractAffineTransformation )
42
38
Minv = inv (matrix (trans))
@@ -47,6 +43,10 @@ function compose(t1::AbstractAffineTransformation, t2::AbstractAffineTransformat
47
43
AffineTransformation (matrix (t1) * matrix (t2), translation (t1) + matrix (t1) * translation (t2))
48
44
end
49
45
46
+ function Base. isapprox (t1:: AbstractAffineTransformation , t2:: AbstractAffineTransformation , kwargs... )
47
+ isapprox (matrix (t1), matrix (t2); kwargs... ) &&
48
+ isapprox (translation (t1), translation (t2); kwargs... )
49
+ end
50
50
51
51
"""
52
52
abstract AbstractLinearTransformation <: AbstractAffineTransformation
@@ -68,20 +68,57 @@ for optimization purposes.
68
68
abstract AbstractLinearTransformation <: AbstractAffineTransformation
69
69
70
70
matrix (:: AbstractLinearTransformation ) = error (" AbstractLinearTransformation's must implement matrix()" )
71
- @inline translation (:: AbstractLinearTransformation ) = 0 # Does this make sense?
72
- @inline translation_reverse (:: AbstractLinearTransformation ) = 0
71
+ function translation (trans:: AbstractLinearTransformation )
72
+ m = matrix (trans)
73
+ s = size (m, 1 )
74
+ T = eltype (m)
75
+ return zeros (T, s)
76
+ end
77
+ function translation_reverse (trans:: AbstractLinearTransformation )
78
+ m = matrix (trans)
79
+ s = size (m, 2 )
80
+ T = eltype (m)
81
+ return zeros (T, s)
82
+ end
73
83
74
84
# Default implementations
75
85
@compat function (trans:: AbstractLinearTransformation )(x)
76
86
matrix (trans) * x
77
87
end
78
88
79
- # transform_deriv() provided by AbstractAffineTransformation
89
+ # transform_deriv() identical to that provided by AbstractAffineTransformation
80
90
81
- Base. inv (trans:: AbstractLinearTransformation ) = LinearTransformation (inv (matrix (trans))
91
+ Base. inv (trans:: AbstractLinearTransformation ) = LinearTransformation (inv (matrix (trans)))
82
92
83
93
compose (t1:: AbstractLinearTransformation , t2:: AbstractLinearTransformation ) = LinearTransformation (matrix (t1) * matrix (t2))
84
94
95
+ function Base. isapprox (t1:: AbstractLinearTransformation , t2:: AbstractLinearTransformation , kwargs... )
96
+ isapprox (matrix (t1), matrix (t2); kwargs... )
97
+ end
98
+
99
+
100
+
101
+ # These functions are remove any reference to unnecessary calls to
102
+ # translation(::LinearTransformation) from the AbstractAffineTransformations
103
+ # interface:
104
+
105
+ function compose (t1:: AbstractAffineTransformation , t2:: AbstractLinearTransformation )
106
+ AffineTransformation (matrix (t1) * matrix (t2), translation (t1))
107
+ end
108
+
109
+ function compose (t1:: AbstractLinearTransformation , t2:: AbstractAffineTransformation )
110
+ AffineTransformation (matrix (t1) * matrix (t2), matrix (t1) * translation (t2))
111
+ end
112
+
113
+ function Base. isapprox (t1:: AbstractAffineTransformation , t2:: AbstractLinearTransformation , kwargs... )
114
+ isapprox (matrix (t1), matrix (t2); kwargs... ) &&
115
+ isapprox (norm (translation (t1)), 0 ; kwargs... )
116
+ end
117
+
118
+ function Base. isapprox (t1:: AbstractLinearTransformation , t2:: AbstractAffineTransformation , kwargs... )
119
+ isapprox (matrix (t1), matrix (t2); kwargs... ) &&
120
+ isapprox (norm (translation (t2)), 0 ; kwargs... )
121
+ end
85
122
86
123
"""
87
124
LinearTransformation <: AbstractLinearTransformation
@@ -120,14 +157,24 @@ immutable AffineTransformation{MatrixT, VectorT} <: AbstractAffineTransformation
120
157
v:: VectorT
121
158
end
122
159
160
+ matrix (trans:: AffineTransformation ) = trans. M
161
+ translation (trans:: AffineTransformation ) = trans. v
162
+
123
163
function AffineTransformation (trans:: AbstractAffineTransformation )
124
164
AffineTransformation (matrix (trans), translation (trans))
125
165
end
126
166
127
167
# We can create an Affine transformation corresponding to the differential
128
168
# transformation of x + dx
129
- function AffineTransformation (trans:: AbstractTransformation , x)
130
- AffineTransformation (transform_deriv (trans, x), trans (x))
169
+ #
170
+ # Note: the expression `Tx - dT*Tx` will have large cancellation error for
171
+ # large Tx! However, changing the order of applying the matrix and
172
+ # translation won't fix things, because then we'd have `Tx*(x-x0)` which
173
+ # also can incur large cancellation error in `x-x0`.
174
+ function AffineTransformation (trans:: Transformation , x0)
175
+ dT = transform_deriv (trans, x0)
176
+ Tx = trans (x0)
177
+ AffineTransformation (dT, Tx - dT* x0)
131
178
end
132
179
133
180
Base. show (io:: IO , trans:: AffineTransformation ) = print (io, " AffineTransformation($(trans. M) , $(trans. v) )" ) # TODO make this output more petite
221
268
Polar (x. r, x. θ + trans. angle)
222
269
end
223
270
271
+ function matrix (trans:: Rotation2D )
272
+ @fsa [ trans. cos - trans. sin;
273
+ trans. sin trans. cos ]
274
+ end
275
+
224
276
function transform_deriv (trans:: Rotation2D , x)
225
277
@fsa [ trans. cos - trans. sin;
226
278
trans. sin trans. cos ]
311
363
@compat (trans:: Rotation )(x:: Tuple ) = Tuple (trans (Vec (x)))
312
364
313
365
transform_deriv (trans:: Rotation , x) = trans. matrix # It's a linear transformation, so this is easy!
366
+ @inline matrix (trans:: Rotation2D ) = trans. matrix
367
+
314
368
315
369
function transform_deriv_params {T} (trans:: Rotation{Void,T} , x)
316
370
# This derivative isn't projected into the orthogonal/Hermition tangent
@@ -511,20 +565,43 @@ function transform_deriv(trans::RotationXY, x)
511
565
trans. sin trans. cos Z;
512
566
Z Z I]
513
567
end
568
+ function matrix (trans:: RotationXY )
569
+ Z = zero (trans. cos)
570
+ I = one (trans. cos)
571
+ @fsa [ trans. cos - trans. sin Z;
572
+ trans. sin trans. cos Z;
573
+ Z Z I]
574
+ end
575
+
514
576
function transform_deriv (trans:: RotationYZ , x)
515
577
Z = zero (trans. cos)
516
578
I = one (trans. cos)
517
579
@fsa [ I Z Z;
518
580
Z trans. cos - trans. sin;
519
581
Z trans. sin trans. cos ]
520
582
end
583
+ function matrix (trans:: RotationYZ )
584
+ Z = zero (trans. cos)
585
+ I = one (trans. cos)
586
+ @fsa [ I Z Z;
587
+ Z trans. cos - trans. sin;
588
+ Z trans. sin trans. cos ]
589
+ end
590
+
521
591
function transform_deriv (trans:: RotationZX , x)
522
592
Z = zero (trans. cos)
523
593
I = one (trans. cos)
524
594
@fsa [ trans. cos Z trans. sin;
525
595
Z I Z ;
526
596
- trans. sin Z trans. cos ]
527
597
end
598
+ function matrix (trans:: RotationZX )
599
+ Z = zero (trans. cos)
600
+ I = one (trans. cos)
601
+ @fsa [ trans. cos Z trans. sin;
602
+ Z I Z ;
603
+ - trans. sin Z trans. cos ]
604
+ end
528
605
529
606
function transform_deriv_params (trans:: RotationXY , x)
530
607
# 3x1 transformation matrix
0 commit comments