Skip to content

Commit 8b87af8

Browse files
authored
Merge pull request #8 from FugroRoames/call
Deprecate transform(), replace with call.
2 parents 9d93999 + 2ba3839 commit 8b87af8

File tree

9 files changed

+169
-175
lines changed

9 files changed

+169
-175
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ networks of coordinate system transformations. Transformations can be easily
77
applied, inverted, composed, and differentiated (both with respect to the
88
input coordinates and with respect to transformation parameters such as rotation
99
angle). Transformations are designed to be light-weight and efficient enough
10-
for, e.g., real-time graphical applications, while support for both explicit
10+
for, e.g., real-time graphical applications, while support for both explicit
1111
and automatic differentiation makes it easy to perform optimization and
1212
therefore ideal for computer vision applications such as SLAM (simultaneous
1313
localization and mapping).
1414

1515
The package provide two main pieces of functionality
1616

1717
1. Primarily, an interface for defining `Transformation`s and applying
18-
(`transform()`), inverting (`inv()`), composing (`` or `compose()`) and
18+
(by calling), inverting (`inv()`), composing (`` or `compose()`) and
1919
differentiating (`transform_deriv()` and `transform_deriv_params()`) them.
2020

2121
2. A small set of built-in, composable, primitive transformations for
@@ -29,27 +29,27 @@ Let's rotate a 2D point:
2929
x = Point(1.0, 2.0) # Point is provided by FixedSizeArrays
3030
rot = Rotation2D(0.3) # a rotation by 0.3 radians anticlockwise about the origin
3131

32-
y = transform(rot, x)
32+
y = rot(x)
3333
```
3434

3535
We can either apply transformations in turn,
3636
```julia
3737
trans = Translation(3.5, 1.5)
3838

39-
z = transform(trans, transform(rot, x))
39+
z = trans(rot(x))
4040
```
4141
or build a composed transformation:
4242
```julia
4343
composed = trans rot # or compose(trans, rot)
4444

45-
transform(composed, x) == z
45+
composed(x) == z
4646
```
4747

4848
We can invert it:
4949
```julia
5050
composed_inv = inv(composed)
5151

52-
transform(composed_inv, z) == x
52+
composed_inv(z) == x
5353
```
5454

5555
Finally, we can construct a matrix describing how the components of `z`

REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
julia 0.4
2+
Compat 0.8
23
FixedSizeArrays 0.2.2
34
Rotations

src/CoordinateTransformations.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
module CoordinateTransformations
22

3+
using Compat
34
using FixedSizeArrays
45
export Point # Use Point{N, T} from FixedSizedArrays for Cartesian frames
56

src/commontransformations.jl

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ Translation(x,y) = Translation(Vec(x,y))
1616
Translation(x,y,z) = Translation(Vec(x,y,z))
1717
Base.show(io::IO, trans::Translation) = print(io, "Translation$((trans.dx...))")
1818

19-
function transform(trans::Translation, x)
19+
@compat function (trans::Translation)(x)
2020
x + trans.dx
2121
end
2222

23-
transform(trans::Translation, x::Tuple) = Tuple(Vec(x) + trans.dx)
23+
@compat (trans::Translation)(x::Tuple) = Tuple(Vec(x) + trans.dx)
2424

2525
Base.inv(trans::Translation) = Translation(-trans.dx)
2626

@@ -60,28 +60,28 @@ function Rotation2D(a)
6060
end
6161

6262
# A variety of specializations for all occassions!
63-
function transform(trans::Rotation2D, x::FixedVector{2})
63+
@compat function (trans::Rotation2D)(x::FixedVector{2})
6464
(sincos, x2) = promote(Vec(trans.sin, trans.cos), x)
6565
(typeof(x2))(x[1]*sincos[2] - x[2]*sincos[1], x[1]*sincos[1] + x[2]*sincos[2])
6666
end
6767

68-
transform(trans::Rotation2D, x::NTuple{2}) = (x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos)
69-
transform{T1,T2}(trans::Rotation2D{T1}, x::Vector{T2}) = [x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos]
68+
@compat (trans::Rotation2D)(x::NTuple{2}) = (x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos)
69+
@compat (trans::Rotation2D{T1}){T1,T2}(x::Vector{T2}) = [x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos]
7070

7171
# E.g. for ArrayFire, this might work better than the below?
72-
function transform{T1,T2}(trans::Rotation2D{T1}, x::AbstractVector{T2})
72+
@compat function (trans::Rotation2D{T1}){T1,T2}(x::AbstractVector{T2})
7373
out = similar(x, promote_type(T1,T2))
7474
out[1] = x[1]*trans.cos - x[2]*trans.sin
7575
out[2] = x[1]*trans.sin + x[2]*trans.cos
7676
return out
7777
end
7878

79-
function transform(trans::Rotation2D, x)
79+
@compat function (trans::Rotation2D)(x)
8080
[ trans.cos -trans.sin;
8181
trans.sin trans.cos ] * x
8282
end
8383

84-
function transform(trans::Rotation2D, x::Polar)
84+
@compat function (trans::Rotation2D)(x::Polar)
8585
Polar(x.r, x.θ + trans.angle)
8686
end
8787

@@ -163,16 +163,16 @@ Base.isapprox(a::Rotation, b::Rotation; kwargs...) = isapprox(a.matrix, b.matrix
163163
Base.isapprox{T}(a::Rotation{T}, b::Rotation{T}; kwargs...) = isapprox(a.matrix, b.matrix; kwargs...) && isapprox(a.rotation, b.rotation; kwargs...)
164164
Base.isapprox(a::Rotation{Void}, b::Rotation{Void}; kwargs...) = isapprox(a.matrix, b.matrix; kwargs...)
165165

166-
function transform(trans::Rotation, x)
166+
@compat function (trans::Rotation)(x)
167167
trans.matrix * x
168168
end
169169

170-
function transform(trans::Rotation, x::FixedVector{3})
170+
@compat function (trans::Rotation)(x::FixedVector{3})
171171
(m, x2) = promote(trans.matrix, x)
172172
(typeof(x2))(m * Vec(x2))
173173
end
174174

175-
transform(trans::Rotation, x::Tuple) = Tuple(transform(trans, Vec(x)))
175+
@compat (trans::Rotation)(x::Tuple) = Tuple(trans(Vec(x)))
176176

177177
transform_deriv(trans::Rotation, x) = trans.matrix # It's a linear transformation, so this is easy!
178178

@@ -323,13 +323,13 @@ Base.show(io::IO, r::RotationYZ) = print(io, "RotationYZ($(r.angle))")
323323
Base.show(io::IO, r::RotationZX) = print(io, "RotationZX($(r.angle))")
324324

325325
# It's a little fiddly to support all possible point container types, but this should do a good majority of them!
326-
transform(trans::RotationXY, x::Vector) = [x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos, x[3]]
327-
transform(trans::RotationXY, x::NTuple{3}) = (x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos, x[3])
328-
function transform(trans::RotationXY, x::FixedVector{3})
326+
@compat (trans::RotationXY)(x::Vector) = [x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos, x[3]]
327+
@compat (trans::RotationXY)(x::NTuple{3}) = (x[1]*trans.cos - x[2]*trans.sin, x[1]*trans.sin + x[2]*trans.cos, x[3])
328+
@compat function (trans::RotationXY)(x::FixedVector{3})
329329
(sincos, x2) = promote(Vec(trans.sin, trans.cos), x)
330330
(typeof(x2))(x[1]*sincos[2] - x[2]*sincos[1], x[1]*sincos[1] + x[2]*sincos[2], x2[3])
331331
end
332-
function transform{T}(trans::RotationXY{T}, x)
332+
@compat function (trans::RotationXY{T}){T}(x)
333333
Z = zero(T)
334334
I = one(T)
335335

@@ -338,13 +338,13 @@ function transform{T}(trans::RotationXY{T}, x)
338338
Z Z I ] * x
339339
end
340340

341-
transform(trans::RotationYZ, x::Vector) = [x[1], x[2]*trans.cos - x[3]*trans.sin, x[2]*trans.sin + x[3]*trans.cos]
342-
transform(trans::RotationYZ, x::NTuple{3}) = (x[1], x[2]*trans.cos - x[3]*trans.sin, x[2]*trans.sin + x[3]*trans.cos)
343-
function transform(trans::RotationYZ, x::FixedVector{3})
341+
@compat (trans::RotationYZ)(x::Vector) = [x[1], x[2]*trans.cos - x[3]*trans.sin, x[2]*trans.sin + x[3]*trans.cos]
342+
@compat (trans::RotationYZ)(x::NTuple{3}) = (x[1], x[2]*trans.cos - x[3]*trans.sin, x[2]*trans.sin + x[3]*trans.cos)
343+
@compat function (trans::RotationYZ)(x::FixedVector{3})
344344
(sincos, x2) = promote(Vec(trans.sin, trans.cos), x)
345345
(typeof(x2))(x2[1], x[2]*sincos[2] - x[3]*sincos[1], x[2]*sincos[1] + x[3]*sincos[2])
346346
end
347-
function transform{T}(trans::RotationYZ{T}, x)
347+
@compat function (trans::RotationYZ{T}){T}(x)
348348
Z = zero(T)
349349
I = one(T)
350350

@@ -353,13 +353,13 @@ function transform{T}(trans::RotationYZ{T}, x)
353353
Z trans.sin trans.cos] * x
354354
end
355355

356-
transform(trans::RotationZX, x::Vector) = [x[3]*trans.sin + x[1]*trans.cos, x[2], x[3]*trans.cos - x[1]*trans.sin]
357-
transform(trans::RotationZX, x::NTuple{3}) = (x[3]*trans.sin + x[1]*trans.cos, x[2], x[3]*trans.cos - x[1]*trans.sin)
358-
function transform(trans::RotationZX, x::FixedVector{3})
356+
@compat (trans::RotationZX)(x::Vector) = [x[3]*trans.sin + x[1]*trans.cos, x[2], x[3]*trans.cos - x[1]*trans.sin]
357+
@compat (trans::RotationZX)(x::NTuple{3}) = (x[3]*trans.sin + x[1]*trans.cos, x[2], x[3]*trans.cos - x[1]*trans.sin)
358+
@compat function (trans::RotationZX)(x::FixedVector{3})
359359
(sincos, x2) = promote(Vec(trans.sin, trans.cos), x)
360360
(typeof(x2))(x[3]*sincos[1] + x[1]*sincos[2], x2[2], x[3]*sincos[2] - x[1]*sincos[1])
361361
end
362-
function transform{T}(trans::RotationZX{T}, x)
362+
@compat function (trans::RotationZX{T}){T}(x)
363363
Z = zero(T)
364364
I = one(T)
365365

src/coordinatesystems.jl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ immutable CartesianFromPolar <: Transformation; end
2121
Base.show(io::IO, trans::PolarFromCartesian) = print(io, "PolarFromCartesian()")
2222
Base.show(io::IO, trans::CartesianFromPolar) = print(io, "CartesianFromPolar()")
2323

24-
function transform(::PolarFromCartesian, x)
24+
@compat function (::PolarFromCartesian)(x)
2525
length(x) == 2 || error("Polar transform takes a 2D coordinate")
2626

2727
Polar(sqrt(x[1]*x[1] + x[2]*x[2]), atan2(x[2], x[1]))
@@ -38,7 +38,7 @@ function transform_deriv(::PolarFromCartesian, x)
3838
end
3939
transform_deriv_params(::PolarFromCartesian, x) = error("PolarFromCartesian has no parameters")
4040

41-
function transform(::CartesianFromPolar, x::Polar)
41+
@compat function (::CartesianFromPolar)(x::Polar)
4242
Point(x.r * cos(x.θ), x.r * sin(x.θ))
4343
end
4444
function transform_deriv(::CartesianFromPolar, x::Polar)
@@ -105,7 +105,7 @@ Base.show(io::IO, trans::CylindricalFromSpherical) = print(io, "CylindricalFromS
105105
Base.show(io::IO, trans::SphericalFromCylindrical) = print(io, "SphericalFromCylindrical()")
106106

107107
# Cartesian <-> Spherical
108-
function transform(::SphericalFromCartesian, x)
108+
@compat function (::SphericalFromCartesian)(x)
109109
length(x) == 3 || error("Spherical transform takes a 3D coordinate")
110110

111111
Spherical(sqrt(x[1]*x[1] + x[2]*x[2] + x[3]*x[3]), atan2(x[2],x[1]), atan(x[3]/sqrt(x[1]*x[1] + x[2]*x[2])))
@@ -126,7 +126,7 @@ function transform_deriv(::SphericalFromCartesian, x)
126126
end
127127
transform_deriv_params(::SphericalFromCartesian, x) = error("SphericalFromCartesian has no parameters")
128128

129-
function transform(::CartesianFromSpherical, x::Spherical)
129+
@compat function (::CartesianFromSpherical)(x::Spherical)
130130
Point(x.r * cos(x.θ) * cos(x.ϕ), x.r * sin(x.θ) * cos(x.ϕ), x.r * sin(x.ϕ))
131131
end
132132
function transform_deriv{T}(::CartesianFromSpherical, x::Spherical{T})
@@ -142,7 +142,7 @@ end
142142
transform_deriv_params(::CartesianFromSpherical, x::Spherical) = error("CartesianFromSpherical has no parameters")
143143

144144
# Cartesian <-> Cylindrical
145-
function transform(::CylindricalFromCartesian, x)
145+
@compat function (::CylindricalFromCartesian)(x)
146146
length(x) == 3 || error("Cylindrical transform takes a 3D coordinate")
147147

148148
Cylindrical(sqrt(x[1]*x[1] + x[2]*x[2]), atan2(x[2],x[1]), x[3])
@@ -161,7 +161,7 @@ function transform_deriv(::CylindricalFromCartesian, x)
161161
end
162162
transform_deriv_params(::CylindricalFromCartesian, x) = error("CylindricalFromCartesian has no parameters")
163163

164-
function transform(::CartesianFromCylindrical, x::Cylindrical)
164+
@compat function (::CartesianFromCylindrical)(x::Cylindrical)
165165
Point(x.r * cos(x.θ), x.r * sin(x.θ), x.z)
166166
end
167167
function transform_deriv{T}(::CartesianFromCylindrical, x::Cylindrical{T})
@@ -174,21 +174,21 @@ end
174174
transform_deriv_params(::CartesianFromPolar, x::Cylindrical) = error("CartesianFromCylindrical has no parameters")
175175

176176
# Spherical <-> Cylindrical (TODO direct would be faster)
177-
function transform(::CylindricalFromSpherical, x::Spherical)
178-
transform(CylindricalFromCartesian() , transform(CartesianFromSpherical(), x))
177+
@compat function (::CylindricalFromSpherical)(x::Spherical)
178+
CylindricalFromCartesian()(CartesianFromSpherical()(x))
179179
end
180180
function transform_deriv(::CylindricalFromSpherical, x::Spherical)
181-
M1 = transform_deriv(CylindricalFromCartesian(), transform(CartesianFromSpherical(), x))
181+
M1 = transform_deriv(CylindricalFromCartesian(), CartesianFromSpherical()(x))
182182
M2 = transform_deriv(CartesianFromSpherical(), x)
183183
return M1*M2
184184
end
185185
transform_deriv_params(::CylindricalFromSpherical, x::Spherical) = error("CylindricalFromSpherical has no parameters")
186186

187-
function transform(::SphericalFromCylindrical, x::Cylindrical)
188-
transform(SphericalFromCartesian() , transform(CartesianFromCylindrical(), x))
187+
@compat function (::SphericalFromCylindrical)(x::Cylindrical)
188+
SphericalFromCartesian()(CartesianFromCylindrical()(x))
189189
end
190190
function transform_deriv(::SphericalFromCylindrical, x::Cylindrical)
191-
M1 = transform_deriv(SphericalFromCartesian(), transform(CartesianFromCylindrical(), x))
191+
M1 = transform_deriv(SphericalFromCartesian(), CartesianFromCylindrical()(x))
192192
M2 = transform_deriv(CartesianFromCylindrical(), x)
193193
return M1*M2
194194
end

src/core.jl

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,30 +8,22 @@
88
"""
99
The `Transformation` supertype defines a simple interface for performing
1010
transformations. Subtypes should be able to apply a coordinate system
11-
transformation on the correct data types by overloading `transform()`, and
11+
transformation on the correct data types by overloading the call method, and
1212
usually would have the corresponding inverse transformation defined by `Base.inv()`.
1313
Efficient compositions can optionally be defined by `compose()` (equivalently `∘`).
1414
"""
1515
abstract Transformation
1616

17+
Base.@deprecate_binding AbstractTransformation Transformation
18+
Base.@deprecate transform(transformation::Transformation, x) transformation(x)
19+
1720
"""
1821
The `IdentityTransformation` is a singleton `Transformation` that returns the
1922
input unchanged, similar to `identity`.
2023
"""
2124
immutable IdentityTransformation <: Transformation; end
2225

23-
"""
24-
transform(trans::Transformation, x)
25-
26-
A transformation `trans` is explicitly applied to data x, returning the
27-
coordinates in the new coordinate system.
28-
"""
29-
function transform(trans::Transformation, x)
30-
error("The transform of datatype $(typeof(x)) is not defined for transformation $trans.")
31-
end
32-
33-
@inline transform(::IdentityTransformation, x) = x
34-
26+
@compat @inline (::IdentityTransformation)(x) = x
3527

3628
"""
3729
A `ComposedTransformation` simply executes two transformations successively, and
@@ -44,8 +36,8 @@ end
4436

4537
Base.show(io::IO, trans::ComposedTransformation) = print(io, "($(trans.t1)$(trans.t2))")
4638

47-
@inline function transform(trans::ComposedTransformation, x)
48-
transform(trans.t1, transform(trans.t2, x))
39+
@compat @inline function (trans::ComposedTransformation)(x)
40+
trans.t1(trans.t2(x))
4941
end
5042

5143
"""
@@ -66,7 +58,7 @@ compose(trans::IdentityTransformation, ::IdentityTransformation) = trans
6658
compose(::IdentityTransformation, trans::Transformation) = trans
6759
compose(trans::Transformation, ::IdentityTransformation) = trans
6860

69-
const = compose
61+
const = compose # TODO watch JuliaLang/julia#17184 and #17155 for v0.5 compatibility
7062

7163

7264
"""
@@ -93,7 +85,7 @@ transform_deriv(::Transformation, x) = error("Differential matrix of transform $
9385
transform_deriv(::IdentityTransformation, x) = I
9486

9587
function transform_deriv(trans::ComposedTransformation, x)
96-
x2 = transform(trans.t2, x)
88+
x2 = trans.t2(x)
9789
m1 = transform_deriv(trans.t1, x2)
9890
m2 = transform_deriv(trans.t2, x)
9991
return m1 * m2
@@ -111,7 +103,7 @@ transform_deriv(::Transformation, x) = error("Differential matrix of parameters
111103
transform_deriv_params(::IdentityTransformation, x) = error("IdentityTransformation has no parameters")
112104

113105
function transform_deriv_params(trans::ComposedTransformation, x)
114-
x2 = transform(trans.t2, x)
106+
x2 = trans.t2(x)
115107
m1 = transform_deriv(trans.t1, x2)
116108
p2 = transform_deriv_params(trans.t2, x)
117109
p1 = transform_deriv_params(trans.t1, x2)

0 commit comments

Comments
 (0)