7 #ifndef NUKLEI_LINEAR_ALGEBRA_H
8 #define NUKLEI_LINEAR_ALGEBRA_H
22 Quaternion quaternionCopy(
const Matrix3& m)
25 q.FromRotationMatrix(m);
31 Matrix3 matrixCopy(
const Quaternion &q)
34 q.ToRotationMatrix(m);
41 Quaternion quaternionCopy(
const Quaternion& q)
47 Matrix3 matrixCopy(
const Matrix3 &m)
54 void copyRotation(Quaternion& q,
const Matrix3& m)
56 q = quaternionCopy(m);
60 void copyRotation(Matrix3& m,
const Quaternion& q)
66 void copyRotation(Quaternion& q,
const Quaternion& q2)
72 void copyRotation(Matrix3& m,
const Matrix3& m2)
78 GVector gVectorCopy(
const GVector& v)
84 GVector gVectorCopy(
const Vector3& v)
90 Vector3 vector3Copy(
const Vector3& v)
96 Vector3 vector3Copy(
const GVector& v)
99 return Vector3(v[0], v[1], v[2]);
104 std::istream& operator>>(std::istream &in, Vector3 &l)
112 std::istream& operator>>(std::istream &in, Quaternion &q)
119 std::ostream& operator<<(std::ostream &out,
const Quaternion &q)
121 NUKLEI_ASSERT(out << q.W() <<
' ' << q.X() <<
' ' << q.Y() <<
' ' << q.Z());
126 std::ostream& operator<<(std::ostream &out,
const Matrix3 &m)
133 std::istream& operator>>(std::istream &in, Matrix3 &m)
137 m = la::matrixCopy(q);
141 std::ostream& operator<<(std::ostream &out,
const GMatrix &m);
142 std::istream& operator>>(std::istream &in, GMatrix &m);
153 Vector3 normalized(
const Vector3 &v)
161 Quaternion normalized(
const Quaternion &q)
169 Matrix3 normalized(
const Matrix3 &m)
177 void makeZero(Vector3 &v)
183 void makeIdentity(Matrix3 &m)
185 m = Matrix3::IDENTITY;
189 void makeIdentity(Quaternion &q)
191 q = Quaternion::IDENTITY;
196 Vector3 min(
const Vector3 &v1,
const Vector3 &v2)
199 for (
int i = 0; i < 3; ++i)
200 minv[i] = std::min(v1[i], v2[i]);
206 Vector3 max(
const Vector3 &v1,
const Vector3 &v2)
209 for (
int i = 0; i < 3; ++i)
210 maxv[i] = std::max(v1[i], v2[i]);
215 Vector3 mean(
const Vector3 &v1,
const Vector3 &v2)
218 for (
int i = 0; i < 3; ++i)
219 mean[i] = ( v1[i] + v2[i] ) / 2.0;
226 Vector3 xAxis(
const Quaternion &q)
230 Real fTy = ((Real)2.0)*q[2];
231 Real fTz = ((Real)2.0)*q[3];
232 Real fTwy = fTy*q[0];
233 Real fTwz = fTz*q[0];
234 Real fTxy = fTy*q[1];
235 Real fTxz = fTz*q[1];
236 Real fTyy = fTy*q[2];
237 Real fTzz = fTz*q[3];
239 Vector3 x((Real)1.0-(fTyy+fTzz),
243 return normalized(x);
247 Vector3 xAxis(
const Matrix3 &m)
249 return m.GetColumn(0);
254 coord_t numDrift(
const Quaternion &q)
256 return std::fabs(q.Length()-1);
260 coord_t numDrift(
const Matrix3 &m)
263 for (
int i = 0; i < 3; ++i)
264 sum += std::fabs(Vector3(m.GetColumn(i)).Dot(m.GetColumn((i+1)%3))) + std::fabs(Vector3(m.GetColumn(i)).Length() - 1);
270 void check(
const Quaternion &q,
const char* msg)
273 if (!(nd < FLOATTOL))
275 std::cout << msg <<
": \n" <<
NUKLEI_NVP(q) <<
"\n" <<
282 void check(
const Matrix3 &m,
const char* msg)
285 if (!(nd < FLOATTOL))
287 std::cout << msg <<
": \n" <<
NUKLEI_NVP(m) <<
"\n" <<
294 Quaternion inverseRotation(
const Quaternion &q)
296 return q.Conjugate();
300 Matrix3 inverseRotation(
const Matrix3 &m)
302 return m.Transpose();
307 Quaternion slerp(
double c,
308 const Quaternion &q1,
309 const Quaternion &q2)
326 Matrix3 slerp(
double c,
330 return matrixCopy(slerp(c, quaternionCopy(m1), quaternionCopy(m2)));
335 Quaternion mean(
const Quaternion &q1,
336 const Quaternion &q2)
338 return slerp(.5, q1, q2);
342 Matrix3 mean(
const Matrix3 &m1,
345 return matrixCopy(mean(quaternionCopy(m1), quaternionCopy(m2)));
350 Quaternion so3FromS2(
const Vector3 &w)
353 Vector3::GenerateComplementBasis(u, v, w);
357 Vector3 up = std::cos(angle)*u + std::sin(angle)*v;
358 Vector3 vp = -std::sin(angle)*u + std::cos(angle)*v;
364 return la::quaternionCopy(m);
367 void eigenDecomposition(Matrix3 &eVectors, Vector3& eValues,
const Matrix3& sym);
369 double determinant(
const GMatrix &m);
370 GMatrix inverse(
const GMatrix &m);
394 return X.Rotate(y) + x;
399 const Vector3& x,
const Matrix3& X,
400 const Vector3& y,
const Matrix3& Y)
408 const Vector3& x,
const Quaternion& X,
409 const Vector3& y,
const Quaternion& Y)
417 const Vector3& x,
const Matrix3& X,
418 const Vector3& y,
const Vector3& Y)
426 const Vector3& x,
const Quaternion& X,
427 const Vector3& y,
const Vector3& Y)
438 return X.Transpose() * (z-x);
446 return X.Conjugate().Rotate(z-x);
451 const Vector3& x,
const Matrix3& X,
452 const Vector3& z,
const Matrix3& Z)
455 Y = X.TransposeTimes(Z);
459 inline void project(Vector3& y, Quaternion& Y,
460 const Vector3& x,
const Quaternion& X,
461 const Vector3& z,
const Quaternion& Z)
464 Y = X.Conjugate() * Z;
469 const Vector3& x,
const Matrix3& X,
470 const Vector3& z,
const Vector3& Z)
473 Y =
project(Vector3::ZERO, X, Z);
478 const Vector3& x,
const Quaternion& X,
479 const Vector3& z,
const Vector3& Z)
482 Y =
project(Vector3::ZERO, X, Z);
487 const Vector3& y,
const Matrix3& Y,
488 const Vector3& z,
const Matrix3& Z)
490 X = Z.TimesTranspose(Y);
496 const Vector3& y,
const Quaternion& Y,
497 const Vector3& z,
const Quaternion& Z)
499 X = Z * Y.Conjugate();
505 template<
class R>
void fromAngleAxisString(R &r,
const std::string &angleAxis)
509 std::istringstream ris(angleAxis);
512 NUKLEI_ASSERT_AFE(axis.Length(), 1);
513 axis = normalized(axis);
514 r.FromAxisAngle(axis, angle);
518 template<
class R> std::string toAngleAxisString(
const R &r)
522 r.ToAxisAngle(axis, angle);
529 multivariateGaussian(
const GVector &x,
const GVector &m,
const GMatrix &cov,
533 NUKLEI_FAST_DEBUG_ASSERT(d = m.GetSize());
534 const GVector diff = x-m;
535 const GMatrix inv = la::inverse(cov);
536 const GVector tmp = inv * diff;
537 double val = diff.Dot(tmp);
538 double ret = std::exp(-.5 * val);
539 ret /= std::pow(2*M_PI,
double(d)/2) * std::sqrt(la::determinant(cov));
546 NUKLEI_SERIALIZATION_NAMESPACE_BEGIN
548 template<
class Archive>
549 void serialize(Archive & ar, nuklei_wmf::Vector3<nuklei::coord_t> &v,
const unsigned int version)
551 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"x", v.X());
552 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"y", v.Y());
553 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"z", v.Z());
556 template<
class Archive>
557 void serialize(Archive & ar, nuklei_wmf::Quaternion<nuklei::coord_t> &q,
const unsigned int version)
559 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"w", q.W());
560 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"x", q.X());
561 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"y", q.Y());
562 ar & NUKLEI_SERIALIZATION_MAKE_NVP(
"z", q.Z());
565 template<
class Archive>
566 void serialize(Archive & ar, nuklei_wmf::Matrix3<nuklei::coord_t> &m,
const unsigned int version)
568 nuklei_wmf::Quaternion<nuklei::coord_t> q = nuklei::la::quaternionCopy(m);
569 serialize(ar, q, version);
570 nuklei::la::copyRotation(m, q);
574 NUKLEI_SERIALIZATION_NAMESPACE_END