1 #ifndef MSP_GEOMETRY_AFFINETRANSFORMATION_H_
2 #define MSP_GEOMETRY_AFFINETRANSFORMATION_H_
4 #include <msp/linal/squarematrix.h>
10 template<typename T, unsigned D>
11 class AffineTransformation;
15 Helper class to provide specialized operations for AffineTransformation.
17 template<typename T, unsigned D>
18 class AffineTransformationOps
21 AffineTransformationOps() { }
25 class AffineTransformationOps<T, 2>
28 AffineTransformationOps() { }
31 static AffineTransformation<T, 2> rotation(const Angle<T> &);
35 class AffineTransformationOps<T, 3>
38 AffineTransformationOps() { }
41 static AffineTransformation<T, 3> rotation(const Angle<T> &, const LinAl::Vector<T, 3> &);
46 An affine transformation in D dimensions. Affine transformations preserve
47 straightness of lines and ratios of distances. Angles and distances themselves
48 may change. Internally this is represented by a square matrix of size D+1.
50 template<typename T, unsigned D>
51 class AffineTransformation: public AffineTransformationOps<T, D>
53 friend class AffineTransformationOps<T, D>;
56 LinAl::SquareMatrix<T, D+1> matrix;
59 AffineTransformation();
61 static AffineTransformation<T, D> translation(const LinAl::Vector<T, D> &);
62 static AffineTransformation<T, D> scaling(const LinAl::Vector<T, D> &);
63 static AffineTransformation<T, D> shear(const LinAl::Vector<T, D> &, const LinAl::Vector<T, D> &);
65 AffineTransformation &operator*=(const AffineTransformation &);
66 AffineTransformation &invert();
68 const LinAl::SquareMatrix<T, D+1> &get_matrix() const { return matrix; }
69 operator const LinAl::SquareMatrix<T, D+1> &() const { return matrix; }
71 LinAl::Vector<T, D> transform(const LinAl::Vector<T, D> &) const;
72 LinAl::Vector<T, D> transform_linear(const LinAl::Vector<T, D> &) const;
75 template<typename T, unsigned D>
76 inline AffineTransformation<T, D>::AffineTransformation()
78 this->matrix = LinAl::SquareMatrix<T, D+1>::identity();
82 template<typename T, unsigned D>
83 AffineTransformation<T, D> AffineTransformation<T, D>::translation(const LinAl::Vector<T, D> &v)
85 AffineTransformation<T, D> r;
86 for(unsigned i=0; i<D; ++i)
87 r.matrix(i, D) = v[i];
91 template<typename T, unsigned D>
92 AffineTransformation<T, D> AffineTransformation<T, D>::scaling(const LinAl::Vector<T, D> &factors)
94 AffineTransformation<T, D> r;
95 for(unsigned i=0; i<D; ++i)
96 r.matrix(i, i) = factors[i];
100 template<typename T, unsigned D>
101 AffineTransformation<T, D> AffineTransformation<T, D>::shear(const LinAl::Vector<T, D> &normal, const LinAl::Vector<T, D> &shift)
103 AffineTransformation<T, D> r;
104 for(unsigned i=0; i<D; ++i)
105 for(unsigned j=0; j<D; ++j)
106 r.matrix(i, j) += normal[j]*shift[i];
111 AffineTransformation<T, 2> AffineTransformationOps<T, 2>::rotation(const Angle<T> &angle)
113 AffineTransformation<T, 2> r;
124 AffineTransformation<T, 3> AffineTransformationOps<T, 3>::rotation(const Angle<T> &angle, const LinAl::Vector<T, 3> &axis)
126 AffineTransformation<T, 3> r;
127 LinAl::Vector<T, 3> axn = normalize(axis);
130 // http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
131 r.matrix(0, 0) = c+axn.x*axn.x*(1-c);
132 r.matrix(0, 1) = axn.x*axn.y*(1-c)-axn.z*s;
133 r.matrix(0, 2) = axn.x*axn.z*(1-c)+axn.y*s;
134 r.matrix(1, 0) = axn.y*axn.x*(1-c)+axn.z*s;
135 r.matrix(1, 1) = c+axn.y*axn.y*(1-c);
136 r.matrix(1, 2) = axn.y*axn.z*(1-c)-axn.x*s;
137 r.matrix(2, 0) = axn.z*axn.x*(1-c)-axn.y*s;
138 r.matrix(2, 1) = axn.z*axn.y*(1-c)+axn.x*s;
139 r.matrix(2, 2) = c+axn.z*axn.z*(1-c);
143 template<typename T, unsigned D>
144 inline AffineTransformation<T, D> &AffineTransformation<T, D>::operator*=(const AffineTransformation<T, D> &other)
146 matrix *= other.get_matrix();
150 template<typename T, unsigned D>
151 inline AffineTransformation<T, D> operator*(const AffineTransformation<T, D> &at1, const AffineTransformation<T, D> &at2)
153 AffineTransformation<T, D> r = at1;
157 template<typename T, unsigned D>
158 inline AffineTransformation<T, D> &AffineTransformation<T, D>::invert()
164 template<typename T, unsigned D>
165 inline AffineTransformation<T, D> invert(const AffineTransformation<T, D> &at)
167 AffineTransformation<T, D> r = at;
171 template<typename T, unsigned D>
172 inline LinAl::Vector<T, D> AffineTransformation<T, D>::transform(const LinAl::Vector<T, D> &v) const
174 return LinAl::Vector<T, D>(matrix*LinAl::Vector<T, D+1>(v, T(1)));
177 template<typename T, unsigned D>
178 inline LinAl::Vector<T, D> AffineTransformation<T, D>::transform_linear(const LinAl::Vector<T, D> &v) const
180 return LinAl::Vector<T, D>(matrix*LinAl::Vector<T, D+1>(v, T(0)));
183 } // namespace Geometry