transformation_2d.inl
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_TRANSFORMATION_2D_INL
00044 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_TRANSFORMATION_2D_INL
00045
00046 #include "transformation_2d.h"
00047
00048 namespace lass
00049 {
00050
00051 namespace prim
00052 {
00053
00054
00055
00056
00057
00058
00059 template <typename T>
00060 Transformation2D<T>::Transformation2D():
00061 matrix_(impl::allocateArray<T>(matrixSize_)),
00062 inverseMatrix_(0)
00063 {
00064 matrix_[ 0] = TNumTraits::one;
00065 matrix_[ 1] = TNumTraits::zero;
00066 matrix_[ 2] = TNumTraits::zero;
00067 matrix_[ 3] = TNumTraits::one;
00068 matrix_[ 4] = TNumTraits::zero;
00069 matrix_[ 5] = TNumTraits::zero;
00070 matrix_[ 6] = TNumTraits::one;
00071 matrix_[ 7] = TNumTraits::zero;
00072 matrix_[ 8] = TNumTraits::zero;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 template <typename T>
00082 template <typename InputIterator>
00083 Transformation2D<T>::Transformation2D(InputIterator first, InputIterator last):
00084 matrix_(impl::allocateArray<T>(matrixSize_)),
00085 inverseMatrix_(0)
00086 {
00087 LASS_ENFORCE(std::distance(first, last) == matrixSize_);
00088 std::copy(first, last, matrix_.get());
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 template <typename T>
00100 const Transformation2D<T>
00101 Transformation2D<T>::inverse() const
00102 {
00103 if (inverseMatrix_.isEmpty())
00104 {
00105 TMatrix inverseMatrix(impl::allocateArray<T>(matrixSize_));
00106 const TValue* const mat = matrix_.get();
00107 TValue* const inv = inverseMatrix.get();
00108
00109 inv[0] = mat[4] * mat[8] - mat[5] * mat[7];
00110 inv[1] = mat[7] * mat[2] - mat[8] * mat[1];
00111 inv[2] = mat[1] * mat[5] - mat[2] * mat[4];
00112
00113 inv[3] = mat[6] * mat[5] - mat[8] * mat[3];
00114 inv[4] = mat[0] * mat[8] - mat[2] * mat[6];
00115 inv[5] = mat[3] * mat[2] - mat[5] * mat[0];
00116
00117 inv[6] = mat[3] * mat[7] - mat[4] * mat[6];
00118 inv[7] = mat[6] * mat[1] - mat[7] * mat[0];
00119 inv[8] = mat[0] * mat[4] - mat[1] * mat[3];
00120
00121 const TValue det = mat[0] * inv[0] + mat[1] * inv[3] + mat[2] * inv[6];
00122 if (det == TNumTraits::zero)
00123 {
00124 inverseMatrix.reset();
00125 LASS_THROW_EX(SingularityError, "transformation not invertible");
00126 }
00127 const TValue invDet = num::inv(det);
00128 for (int i = 0; i < 9; ++i)
00129 {
00130 inv[i] *= invDet;
00131 }
00132
00133 sync_.lock();
00134 inverseMatrix_.swap(inverseMatrix);
00135 sync_.unlock();
00136 }
00137
00138 LASS_ASSERT(inverseMatrix_ && matrix_);
00139 return TSelf(inverseMatrix_, matrix_, false);
00140 }
00141
00142
00143
00144
00145
00146
00147 template <typename T> inline
00148 const typename Transformation2D<T>::TValue*
00149 Transformation2D<T>::matrix() const
00150 {
00151 return matrix_.get();
00152 }
00153
00154
00155
00156 template <typename T>
00157 void Transformation2D<T>::swap(TSelf& other)
00158 {
00159 matrix_.swap(other.matrix_);
00160 inverseMatrix_.swap(other.inverseMatrix_);
00161 }
00162
00163
00164
00165
00166
00167 template <typename T>
00168 const Transformation2D<T> Transformation2D<T>::identity()
00169 {
00170 return TSelf();
00171 }
00172
00173
00174
00175
00176
00177 template <typename T>
00178 const Transformation2D<T> Transformation2D<T>::translation(const Vector2D<T>& offset)
00179 {
00180 Transformation2D<T> result;
00181 result.matrix_[2] = offset.x;
00182 result.matrix_[5] = offset.y;
00183 result.matrix_[8] = offset.z;
00184 return result;
00185 }
00186
00187
00188
00189
00190
00191 template <typename T>
00192 const Transformation2D<T> Transformation2D<T>::scaler(const T& scale)
00193 {
00194 Transformation2D<T> result;
00195 result.matrix_[0] = scale;
00196 result.matrix_[4] = scale;
00197 return result;
00198 }
00199
00200
00201
00202
00203
00204 template <typename T>
00205 const Transformation2D<T> Transformation2D<T>::scaler(const Vector2D<T>& scale)
00206 {
00207 Transformation2D<T> result;
00208 result.matrix_[0] = scale.x;
00209 result.matrix_[4] = scale.y;
00210 return result;
00211 }
00212
00213
00214
00215
00216
00217 template <typename T>
00218 const Transformation2D<T> Transformation2D<T>::rotation(TParam radians)
00219 {
00220 const T c = num::cos(radians);
00221 const T s = num::sin(radians);
00222
00223 Transformation2D<T> result;
00224 result.matrix_[0] = c;
00225 result.matrix_[4] = c;
00226 result.matrix_[1] = -s;
00227 result.matrix_[3] = s;
00228 return result;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 template <typename T> inline
00240 Transformation2D<T>::Transformation2D(const TMatrix& matrix, const TMatrix& inverseMatrix, bool):
00241 matrix_(matrix),
00242 inverseMatrix_(inverseMatrix)
00243 {
00244 }
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 template <typename T>
00262 Transformation2D<T> concatenate(const Transformation2D<T>& first, const Transformation2D<T>& second)
00263 {
00264
00265 const T* const a = second.matrix();
00266 const T* const b = first.matrix();
00267 T result[9];
00268 for (size_t i = 0; i < 9; i += 3)
00269 {
00270 for (size_t j = 0; j < 3; ++j)
00271 {
00272 result[i + j] =
00273 a[i ] * b[ j] +
00274 a[i + 1] * b[3 + j] +
00275 a[i + 2] * b[6 + j];
00276 }
00277 }
00278 return Transformation2D<T>(result, result + 9);
00279 }
00280
00281
00282
00283
00284
00285
00286 template <typename T>
00287 Vector2D<T> transform(const Vector2D<T>& subject, const Transformation2D<T>& transformation)
00288 {
00289 const T* const mat = transformation.matrix();
00290 return Vector2D<T>(
00291 mat[0] * subject.x + mat[1] * subject.y,
00292 mat[3] * subject.x + mat[4] * subject.y);
00293 }
00294
00295
00296
00297
00298
00299
00300 template <typename T>
00301 Point2D<T> transform(const Point2D<T>& subject, const Transformation2D<T>& transformation)
00302 {
00303 const T* const mat = transformation.matrix();
00304 const T weight = num::inv(mat[6] * subject.x + mat[7] * subject.y + mat[8]);
00305 return Point2D<T>(
00306 weight * (mat[0] * subject.x + mat[1] * subject.y + mat[2]),
00307 weight * (mat[3] * subject.x + mat[4] * subject.y + mat[5]));
00308
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318 template <typename T>
00319 Vector2D<T> normalTransform(const Vector2D<T>& subject, const Transformation2D<T>& transformation)
00320 {
00321 const T* const invMat = transformation.inverse().matrix();
00322 return Vector2D<T>(
00323 invMat[0] * subject.x + invMat[3] * subject.y,
00324 invMat[1] * subject.x + invMat[4] * subject.y);
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 template <typename T>
00343 std::pair<Vector2D<T>, T> normalTransform(const std::pair<Vector2D<T>, T>& subject,
00344 const Transformation2D<T>& transformation)
00345 {
00346 const T* const invMat = transformation.inverse().matrix();
00347 const Vector2D<T>& n = subject.first;
00348 const T c = subject.second;
00349 return std::make_pair(
00350 Vector2D<T>(
00351 invMat[0] * n.x + invMat[3] * n.y + invMat[6] * c,
00352 invMat[1] * n.x + invMat[4] * n.y + invMat[7] * c),
00353 invMat[2] * n.x + invMat[5] * n.y + invMat[8] * c);
00354 }
00355
00356
00357
00358
00359
00360 template<typename T, typename Char, typename Traits>
00361 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& stream,
00362 const Transformation2D<T>& transformation)
00363 {
00364 const T* const mat = transformation.matrix();
00365 LASS_ENFORCE_STREAM(stream) << "(("
00366 << mat[0] << ", " << mat[1] << ", " << mat[2] << "), ("
00367 << mat[3] << ", " << mat[4] << ", " << mat[5] << "), ("
00368 << mat[6] << ", " << mat[7] << ", " << mat[9] << "))";
00369 return stream;
00370 }
00371
00372
00373
00374
00375
00376 template<typename T>
00377 io::XmlOStream& operator<<(io::XmlOStream& stream, const Transformation2D<T>& transformation)
00378 {
00379 const T* const mat = transformation.matrix();
00380 LASS_ENFORCE_STREAM(stream) << "<Transformation2D>"
00381 << mat[0] << " " << mat[1] << " " << mat[2] << " "
00382 << mat[3] << " " << mat[4] << " " << mat[5] << " "
00383 << mat[6] << " " << mat[7] << " " << mat[9]
00384 << "</Transformation2D>\n";
00385 return stream;
00386 }
00387
00388
00389
00390 }
00391
00392 }
00393
00394 #endif