@@ -19,33 +19,37 @@ The package provide two main pieces of functionality
19
19
differentiating (` transform_deriv() ` and ` transform_deriv_params() ` ) them.
20
20
21
21
2 . A small set of built-in, composable, primitive transformations for
22
- transforming 2D and 3D points (optionally leveraging the * FixedSizeArrays *
22
+ transforming 2D and 3D points (optionally leveraging the * StaticArrays *
23
23
and * Rotations* packages).
24
24
25
25
### Quick start
26
26
27
- Let's rotate a 2D point:
27
+ Let's translate a 3D point:
28
28
``` julia
29
- x = Point (1.0 , 2.0 ) # Point is provided by FixedSizeArrays
30
- rot = Rotation2D (0.3 ) # a rotation by 0.3 radians anticlockwise about the origin
29
+ using CoordinateTransformations, Rotations, StaticArrays
31
30
32
- y = rot (x)
31
+ x = SVector (1.0 , 2.0 , 3.0 ) # SVector is provided by StaticArrays.jl
32
+ trans = Translation (3.5 , 1.5 , 0.0 )
33
+
34
+ y = trans (x)
33
35
```
34
36
35
- We can either apply transformations in turn,
37
+ We can either apply different transformations in turn,
36
38
``` julia
37
- trans = Translation ( 3.5 , 1.5 )
39
+ rot = LinearMap ( RotX ( 0.3 )) # Rotate 0.3 radians about X-axis, from Rotations.jl
38
40
39
41
z = trans (rot (x))
40
42
```
41
- or build a composed transformation:
43
+ or build a composed transformation using the ` ∘ ` operator (accessible at the
44
+ REPL by typing ` \circ ` then tab):
42
45
``` julia
43
- composed = trans ∘ rot # or compose(trans, rot)
46
+ composed = trans ∘ rot # alternatively, use compose(trans, rot)
44
47
45
48
composed (x) == z
46
49
```
50
+ A composition of a ` Translation ` and a ` LinearMap ` results in an ` AffineMap ` .
47
51
48
- We can invert it :
52
+ We can invert the transformation :
49
53
``` julia
50
54
composed_inv = inv (composed)
51
55
@@ -67,10 +71,9 @@ rotation angle:
67
71
### The interface
68
72
69
73
Transformations are derived from ` Transformation ` . As an example, we have
70
- ` Translation{T} <: Transformation ` . A translation will accept points in a
71
- variety of formats, such as ` Vector ` , ` FixedVector ` , ` Tuple ` , etc, and will try
72
- to return the same type as given (of course, type promotion may occur for the
73
- element type itself).
74
+ ` Translation{T} <: Transformation ` . A ` Translation ` will accept and translate
75
+ points in a variety of formats, such as ` Vector ` or ` SVector ` , but in general
76
+ your custom-defined ` Transformation ` s could transform any Julia object.
74
77
75
78
Transformations can be reversed using ` inv(trans) ` . They can be chained
76
79
together using the ` ∘ ` operator (` trans1 ∘ trans2 ` ) or ` compose ` function (` compose(trans1, trans2) ` ).
@@ -130,30 +133,33 @@ transformations:
130
133
#### Translations
131
134
132
135
Translations can be be applied to Cartesian coordinates in arbitrary dimensions,
133
- by e.g. ` Translation(Δx, Δy) ` or ` Translation(Δx, Δy, Δz) ` in 2D/3D.
134
-
135
- #### Rotations
136
-
137
- Rotations in 2D and 3D are treated slightly differently. The ` Rotation2D(Δθ) ` rotates a
138
- Cartesian point about the origin, while ` RotationPolar(Δθ) ` rotates a ` Polar `
139
- coordinate about the origin.
140
-
141
- ` Rotation ` performs rotations of 3D Cartesian coordinates. Rotations may be
142
- defined simply by their transformation matrix (assumed to be orthogonal),
143
- or via any of the types exported from the * Rotations* package, including
144
- ` Quaternion ` (originating from the * Quaternions* package), ` AngleAxis ` ,
145
- ` EulerAngles ` , ` ProperEulerAngles ` and ` SpQuat ` . In these latter cases, the
146
- "parameters" differentiated by ` transform_deriv_params() ` come directly from the
147
- parameterization of the quaternion, Euler angles, etc. ** Note:** the derivative
148
- is only guaranteed to be correct in the tangent plane of the constrained variable,
149
- such as normalized quaternions, and optimization techniques should take this
150
- into account as necessary.
151
-
152
- Also included are built-in ` RotationXY ` , ` RotationYZ ` and ` RotationZX ` for
153
- rotating about the * z* , * x* and * y* axes, respectively. A helper function for
154
- constructing a composed transformation of Euler angles is
155
- ` euler_rotation(θ₁, θ₂, θ₃, [order = EulerZXY]) ` , where ` order ` can be any of
156
- * Rotations* ' orderings (` EulerXYZ ` , etc). The default ` EulerZXY ` first rotates
157
- around the * y* axis (* z-x* plane) by ` θ₃ ` , then the * x* axis (* y-z* plane) by
158
- ` θ₂ ` , and finally about the * z* axis (* x-y* plane) by ` θ₁ ` , and is therefore
159
- equivalent to ` RotationXY(θ₁) ∘ RotationYZ(θ₂) ∘ RotationZX(θ₃) ` .
136
+ by e.g. ` Translation(Δx, Δy) ` or ` Translation(Δx, Δy, Δz) ` in 2D/3D, or by
137
+ ` Translation(Δv) ` in general (with ` Δv ` an ` AbstractVector ` ). Compositions of
138
+ two ` Translation ` s will intelligently create a new ` Translation ` by adding the
139
+ translation vectors.
140
+
141
+ #### Linear transformations
142
+
143
+ Linear transformations (a.k.a. linear maps), including rotations, can be
144
+ encapsulated in the ` LinearMap ` type, which is a simple wrapper of an
145
+ ` AbstractMatrix ` .
146
+
147
+ You are able to provide any matrix of your choosing, but your choice of type
148
+ will have a large effect on speed. For instance, if you know the dimensionality
149
+ of your points (e.g. 2D or 3D) you might consider a statically sized matrix
150
+ like ` SMatrix ` from * StaticArrays.jl* . We recommend performing 3D rotations
151
+ using those from * Rotations.jl* for their speed and flexibility. Scaling will
152
+ be efficient with Julia's built-in ` UniformScaling ` . Also note that compositions
153
+ of two ` LinearMap ` s will intelligently create a new ` LinearMap ` by multiplying
154
+ the transformation matrices.
155
+
156
+ #### Affine maps
157
+
158
+ An Affine map encapsulates a more general set of transformation which are
159
+ defined by a composition of a translation and a linear transformation. An
160
+ ` AffineMap ` is constructed from an ` AbstractVector ` translation ` v ` and an
161
+ ` AbstractMatrix ` linear transformation ` M ` . It will perform the mapping
162
+ ` x -> M*x + v ` , but the order of addition and multiplication will be more obvious
163
+ (and controllable) if you construct it from a composition of a linear map
164
+ and a translation, e.g. ` Translation(v) ∘ LinearMap(v) ` (or any combination of
165
+ ` LinearMap ` , ` Translation ` and ` AffineMap ` ).
0 commit comments