Templates -- Meow  1.1.2
不能,也不應該先編譯成obj-file的templates
LinearTransformations.h
Go to the documentation of this file.
1 #ifndef math_LinearTransformations_H__
2 #define math_LinearTransformations_H__
3 
4 #include "LinearTransformation.h"
5 #include "Matrix.h"
6 #include "utility.h"
7 #include "../Self.h"
8 #include "../geo/Vectors.h"
9 
10 #include <cstdlib>
11 
12 namespace meow {
13 
19 template<class Scalar>
20 class Rotation3D: public LinearTransformation<Scalar> {
21 private:
22  struct Myself {
23  Vector3D<Scalar> theta_;
24  bool need_;
25 
26  Myself() {
27  }
28  ~Myself() {
29  }
30  Myself& copyFrom(Myself const& b) {
31  theta_ = b.theta_;
32  need_ = b.need_;
33  return *this;
34  }
35  };
36 
37  Self<Myself> const& self;
38 
39  void calcMatrix() const {
40  if (self->need_) {
41  Vector3D<double> axis (self->theta_.normalize());
42  double angle(self->theta_.length());
43  double cs(cos(angle / 2.0));
44  double sn(sin(angle / 2.0));
45 
46  Matrix<Scalar> tmp(3, 3, Scalar(0.0));
47  tmp.entry(0, 0, 2*(squ(axis.x())-1.0)*squ(sn) + 1);
48  tmp.entry(1, 1, 2*(squ(axis.y())-1.0)*squ(sn) + 1);
49  tmp.entry(2, 2, 2*(squ(axis.z())-1.0)*squ(sn) + 1);
50  tmp.entry(0, 1, 2*axis.x()*axis.y()*squ(sn) - 2*axis.z()*cs*sn);
51  tmp.entry(1, 0, 2*axis.y()*axis.x()*squ(sn) + 2*axis.z()*cs*sn);
52  tmp.entry(0, 2, 2*axis.x()*axis.z()*squ(sn) + 2*axis.y()*cs*sn);
53  tmp.entry(2, 0, 2*axis.z()*axis.x()*squ(sn) - 2*axis.y()*cs*sn);
54  tmp.entry(1, 2, 2*axis.y()*axis.z()*squ(sn) - 2*axis.x()*cs*sn);
55  tmp.entry(2, 1, 2*axis.z()*axis.y()*squ(sn) + 2*axis.x()*cs*sn);
56  ((Rotation3D*)this)->matrix(tmp);
57  self()->need_ = false;
58  }
59  }
60 
61 public:
65  Rotation3D(): LinearTransformation<Scalar>(3u, 3u, 3u),
66  self(true) {
67  self()->theta_.x(Scalar(0));
68  self()->theta_.y(Scalar(0));
69  self()->theta_.z(Scalar(0));
70  self()->need_ = true;
71  calcMatrix();
72  }
73 
78  self(false) {
79  copyFrom(b);
80  }
81 
86  }
87 
96  self().copyFrom(b.self);
97  return *this;
98  }
99 
108  self().referenceFrom(b.self);
109  return *this;
110  }
111 
115  Scalar parameter(size_t i) const {
116  return theta(i);
117  }
118 
122  Scalar parameter(size_t i, Scalar const& s) {
123  return theta(i, s);
124  }
125 
134  Scalar const& theta(size_t i) const {
135  return self->theta_(i);
136  }
137 
147  Scalar const& theta(size_t i, Scalar const& s) {
148  if (theta(i) != s) {
149  if (i == 0) self()->theta_.x(s);
150  else if (i == 1) self()->theta_.y(s);
151  else if (i == 2) self()->theta_.z(s);
152  self()->need_ = true;
153  }
154  return theta(i);
155  }
156 
163  void axisAngle(Vector<Scalar> const& axis, Scalar const& angle) {
164  Vector<Scalar> n(axis.normalize());
165  for (size_t i = 0; i < 3; i++) {
166  theta(i, n(i) * angle);
167  }
168  }
169 
174  Rotation3D& add(Rotation3D const& r) {
175  for (size_t i = 0; i < 3; i++) {
176  theta(i, r.theta(i));
177  }
178  return *this;
179  }
180 
217  if (self->need_) calcMatrix();
219  }
220 
247  if (self->need_) calcMatrix();
249  }
250 
323  Matrix<Scalar> jacobian(Matrix<Scalar> const& x, size_t i) const {
324  if (self->need_) calcMatrix();
325  Matrix<Scalar> mid(3u, 3u, Scalar(0.0));
326  if (i == 0) {
327  mid.entry(1, 2, Scalar(-1.0));
328  mid.entry(2, 1, Scalar( 1.0));
329  }
330  else if(i == 1) {
331  mid.entry(0, 2, Scalar( 1.0));
332  mid.entry(2, 0, Scalar(-1.0));
333  }
334  else {
335  mid.entry(0, 1, Scalar(-1.0));
336  mid.entry(1, 0, Scalar( 1.0));
337  }
338  return mid * LinearTransformation<Scalar>::matrix() * x;
339  }
340 
348  if (self->need_) calcMatrix();
350  }
351 
359  if (self->need_) calcMatrix();
361  }
362 
370  Matrix<Scalar> jacobianInv(Matrix<Scalar> const& x, size_t i) const {
371  if (self->need_) calcMatrix();
372  Matrix<Scalar> mid(3u, 3u, Scalar(0.0));
373  if (i == 0) {
374  mid.entry(1, 2, Scalar(-1.0));
375  mid.entry(2, 1, Scalar( 1.0));
376  }
377  else if(i == 1) {
378  mid.entry(0, 2, Scalar( 1.0));
379  mid.entry(2, 0, Scalar(-1.0));
380  }
381  else {
382  mid.entry(0, 1, Scalar(-1.0));
383  mid.entry(1, 0, Scalar( 1.0));
384  }
385  return mid.transpose() * matrixInv() * x;
386  }
387 
396  if (self->need_) calcMatrix();
398  }
399 
402  return copyFrom(b);
403  }
404 };
405 
406 }
407 
408 #endif // math_LinearTransformations_H__