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 #include <base/Orient>
00026
00027 using base::Orient;
00028
00029 #include <base/Math>
00030 #include <base/Serializer>
00031
00032
00033 using base::Byte;
00034 using base::Math;
00035 using base::Matrix3;
00036 using base::Matrix4;
00037 using base::Vector3;
00038 using base::Point4;
00039 using base::Quat4;
00040 using base::Vector;
00041 using base::Matrix;
00042
00043 Byte Orient::EulSafe[4] = { 0,1,2,0 };
00044 Byte Orient::EulNext[4] = { 1,2,0,1 };
00045
00046 const Orient::Representation Orient::EulerXYZs = eulerRep(X,Even, NonRepeating,Static);
00047 const Orient::Representation Orient::EulerXYXs = eulerRep(X,Even, Repeating,Static);
00048 const Orient::Representation Orient::EulerXZYs = eulerRep(X,Odd , NonRepeating,Static);
00049 const Orient::Representation Orient::EulerXZXs = eulerRep(X,Odd , Repeating,Static);
00050 const Orient::Representation Orient::EulerYZXs = eulerRep(Y,Even, NonRepeating,Static);
00051 const Orient::Representation Orient::EulerYZYs = eulerRep(Y,Even, Repeating,Static);
00052 const Orient::Representation Orient::EulerYXZs = eulerRep(Y,Odd , NonRepeating,Static);
00053 const Orient::Representation Orient::EulerYXYs = eulerRep(Y,Odd , Repeating,Static);
00054 const Orient::Representation Orient::EulerZXYs = eulerRep(Z,Even, NonRepeating,Static);
00055 const Orient::Representation Orient::EulerZXZs = eulerRep(Z,Even, Repeating,Static);
00056 const Orient::Representation Orient::EulerZYXs = eulerRep(Z,Odd , NonRepeating,Static);
00057 const Orient::Representation Orient::EulerZYZs = eulerRep(Z,Odd , Repeating,Static);
00058
00059 const Orient::Representation Orient::EulerZYXr = eulerRep(X,Even, NonRepeating,Rotating);
00060 const Orient::Representation Orient::EulerXYXr = eulerRep(X,Even, Repeating,Rotating);
00061 const Orient::Representation Orient::EulerYZXr = eulerRep(X,Odd , NonRepeating,Rotating);
00062 const Orient::Representation Orient::EulerXZXr = eulerRep(X,Odd , Repeating,Rotating);
00063 const Orient::Representation Orient::EulerXZYr = eulerRep(Y,Even, NonRepeating,Rotating);
00064 const Orient::Representation Orient::EulerYZYr = eulerRep(Y,Even, Repeating,Rotating);
00065 const Orient::Representation Orient::EulerZXYr = eulerRep(Y,Odd , NonRepeating,Rotating);
00066 const Orient::Representation Orient::EulerYXYr = eulerRep(Y,Odd , Repeating,Rotating);
00067 const Orient::Representation Orient::EulerYXZr = eulerRep(Z,Even, NonRepeating,Rotating);
00068 const Orient::Representation Orient::EulerZXZr = eulerRep(Z,Even, Repeating,Rotating);
00069 const Orient::Representation Orient::EulerXYZr = eulerRep(Z,Odd , NonRepeating,Rotating);
00070 const Orient::Representation Orient::EulerZYZr = eulerRep(Z,Odd , Repeating,Rotating);
00071
00072 const Orient::Representation Orient::EulerRPY = eulerRep(X,Even, NonRepeating,Static);
00073
00074
00075
00076
00077
00078 Orient::Orient()
00079 : rep(EulerRPY), v(zeroVector(3))
00080 {
00081 }
00082
00083
00084 Orient::Orient(Representation representation)
00085 : rep(representation), v(zeroVector(3))
00086 {
00087 Assert(rep < RepEnd);
00088 if (rep == Mat) {
00089 m = MatrixRef(NewObj Matrix(3,3));
00090 *m = identityMatrix(3,3);
00091 }
00092 else {
00093 if (rep == Quat) {
00094 Quat4 q;
00095 v.resize(4);
00096 v[0]=q.v.x; v[1]=q.v.y; v[2]=q.v.z; v[3]=q.w;
00097 }
00098 }
00099 }
00100
00101
00102 Orient::Orient(const Quat4& q)
00103 : rep(Quat), v(4)
00104 {
00105 v[0]=q.v.x; v[1]=q.v.y; v[2]=q.v.z; v[3]=q.w;
00106 }
00107
00108
00109 Orient::Orient(Real roll, Real pitch, Real yaw)
00110 : rep(EulerRPY), v(3)
00111 {
00112 v[0]=roll; v[1]=pitch; v[2]=yaw;
00113 }
00114
00115
00116
00117 Orient::Orient(const Vector& v, Representation representation)
00118 : rep(representation)
00119 {
00120 Assert(rep < RepEnd);
00121 Assertm( (rep==Quat)?(v.size()==4):true, "Quaternion has 4 components");
00122 if (rep==Mat) {
00123 Assertm( v.size() == 9, "Rotation matrix has 9 components");
00124 m = MatrixRef(NewObj Matrix(3,3));
00125 (*m)(0,0) = v[0]; (*m)(0,1) = v[1]; (*m)(0,2) = v[2];
00126 (*m)(1,0) = v[3]; (*m)(1,1) = v[4]; (*m)(1,2) = v[5];
00127 (*m)(2,0) = v[6]; (*m)(2,1) = v[7]; (*m)(2,2) = v[8];
00128 }
00129 else {
00130 if (rep!=Quat) {
00131 Assertm( v.size()==3, "vector should have 3 components");
00132 this->v.reset(v);
00133 }
00134 else {
00135 Quat4 q(v[0],v[1],v[2],v[3]);
00136 q.normalize();
00137 this->v.resize(4);
00138 this->v[0]=q.v.x; this->v[1]=q.v.y; this->v[2]=q.v.z; this->v[3]=q.w;
00139 }
00140 }
00141 }
00142
00143
00144 Orient::Orient(const Matrix3& m3)
00145 : rep(Mat), m(NewObj Matrix(3,3))
00146 {
00147 (*m)(0,0) = m3(1,1);
00148 (*m)(0,1) = m3(1,2);
00149 (*m)(0,2) = m3(1,3);
00150 (*m)(1,0) = m3(2,1);
00151 (*m)(1,1) = m3(2,2);
00152 (*m)(1,2) = m3(2,3);
00153 (*m)(2,0) = m3(3,1);
00154 (*m)(2,1) = m3(3,2);
00155 (*m)(2,2) = m3(3,3);
00156 }
00157
00158
00159 Orient::Orient(const Matrix& m)
00160 : rep(Mat), m(NewObj Matrix(3,3))
00161 {
00162 Assert(m.size1()==3);
00163 Assert(m.size2()==3);
00164 *(this->m) = m;
00165 }
00166
00167
00168 Orient::Orient(const Orient& copy)
00169 : rep(copy.rep)
00170 {
00171 if (rep!=Mat) {
00172 v.resize(copy.v.size());
00173 v = copy.v;
00174 }
00175 else {
00176 m = MatrixRef(NewObj Matrix(*copy.m));
00177 *m = *copy.m;
00178 }
00179 }
00180
00181
00182 Orient::~Orient()
00183 {
00184 if (rep==Mat)
00185 delete &(*m);
00186 }
00187
00188
00189 Orient& Orient::operator=(const Matrix3& mt)
00190 {
00191 if (rep != Mat)
00192 m = MatrixRef(NewObj Matrix(3,3));
00193 rep = Mat;
00194 (*m)(0,0) = mt(1,1); (*m)(0,1) = mt(1,2); (*m)(0,2) = mt(1,3);
00195 (*m)(1,0) = mt(2,1); (*m)(1,1) = mt(2,2); (*m)(1,2) = mt(2,3);
00196 (*m)(2,0) = mt(3,1); (*m)(2,1) = mt(3,2); (*m)(2,2) = mt(3,3);
00197 return *this;
00198 }
00199
00200
00201
00202
00203 base::String Orient::representationString(Representation rep)
00204 {
00205 if (rep == Quat) return String("Quat");
00206 else if (rep == Mat) return String("Matrix");
00207 else if (rep == Rodriguez) return String("Rodriguez");
00208 else if (rep == EulerXYZs) return String("EulerXYZs");
00209 else if (rep == EulerXYXs) return String("EulerXYXs");
00210 else if (rep == EulerXZYs) return String("EulerXZYs");
00211 else if (rep == EulerXZXs) return String("EulerXZXs");
00212 else if (rep == EulerYZXs) return String("EulerYZXs");
00213 else if (rep == EulerYZYs) return String("EulerYZYs");
00214 else if (rep == EulerYXZs) return String("EulerYXZs");
00215 else if (rep == EulerYXYs) return String("EulerYXYs");
00216 else if (rep == EulerZXYs) return String("EulerZXYs");
00217 else if (rep == EulerZXZs) return String("EulerZXZs");
00218 else if (rep == EulerZYXs) return String("EulerZYXs");
00219 else if (rep == EulerZYZs) return String("EulerZYZs");
00220 else if (rep == EulerZYXr) return String("EulerZYXr");
00221 else if (rep == EulerXYXr) return String("EulerXYXr");
00222 else if (rep == EulerYZXr) return String("EulerYZXr");
00223 else if (rep == EulerXZXr) return String("EulerXZXr");
00224 else if (rep == EulerXZYr) return String("EulerXZYr");
00225 else if (rep == EulerYZYr) return String("EulerYZYr");
00226 else if (rep == EulerZXYr) return String("EulerZXYr");
00227 else if (rep == EulerYXYr) return String("EulerYXYr");
00228 else if (rep == EulerYXZr) return String("EulerYXZr");
00229 else if (rep == EulerZXZr) return String("EulerZXZr");
00230 else if (rep == EulerXYZr) return String("EulerXYZr");
00231 else if (rep == EulerZYZr) return String("EulerZYZr");
00232 else throw std::invalid_argument(Exception("unknown representation"));
00233 }
00234
00235
00236
00237
00238
00239 Matrix Orient::getRotationMatrix() const
00240 {
00241 Orient r(*this); r.changeRep(Mat);
00242 return Matrix(*r.m);
00243 }
00244
00245
00246 Matrix3 Orient::getRotationMatrix3() const
00247 {
00248 Orient r(*this); r.changeRep(Mat);
00249 Matrix& m(*r.m);
00250 Matrix3 m3(m(0,0), m(0,1), m(0,2),
00251 m(1,0), m(1,1), m(1,2),
00252 m(2,0), m(2,1), m(2,2));
00253 return m3;
00254 }
00255
00256 Quat4 Orient::getQuat4() const
00257 {
00258 if (rep == Quat)
00259 return Quat4(v[0],v[1],v[2],v[3]);
00260 else {
00261 Orient r(*this);
00262 r.changeRep(Quat);
00263 return Quat4(r.v[0],r.v[1],r.v[2],r.v[3]);
00264 }
00265 }
00266
00267 Vector Orient::getVector(Representation representation) const
00268 {
00269 Orient c;
00270 const Orient* r(this);
00271 if (rep != representation) {
00272 c = *this;
00273 c.changeRep(representation);
00274 r = &c;
00275 }
00276
00277 if (representation!=Mat) {
00278 return r->v;
00279 }
00280 else {
00281 Vector v(9);
00282 const Matrix& m(*(r->m));
00283 v[0] = m(0,0); v[1] = m(0,1); v[2] = m(0,2);
00284 v[3] = m(1,0); v[4] = m(1,1); v[5] = m(1,2);
00285 v[6] = m(2,0); v[7] = m(2,1); v[8] = m(2,2);
00286 return v;
00287 }
00288 }
00289
00290
00291 Vector3 Orient::getVector3(Representation representation) const
00292 {
00293 Vector v( getVector(representation) );
00294 return Vector3(v[0],v[1],v[2]);
00295 }
00296
00297
00298
00299 Orient& Orient::operator=(const Orient& copy) throw()
00300 {
00301 if (© != this) {
00302 Assert(copy.rep < RepEnd);
00303 if (rep!=Mat) {
00304 if (copy.rep!=Mat) {
00305 rep=copy.rep;
00306 v.reset(copy.v);
00307 }
00308 else {
00309 rep=copy.rep;
00310 m = MatrixRef(NewObj Matrix(*copy.m));
00311 }
00312 }
00313 else {
00314 if (copy.rep!=Mat) {
00315 delete &(*m);
00316 rep=copy.rep;
00317 v.reset(copy.v);
00318 }
00319 else {
00320 *m = *copy.m;
00321 }
00322 }
00323 }
00324 return *this;
00325 }
00326
00327
00328 void Orient::setIdentity(Orient::Representation representation)
00329 {
00330 Assert(representation < RepEnd)
00331 if (representation == Quat) {
00332 if (rep == Mat)
00333 delete &(*m);
00334 rep = Quat;
00335 Quat4 q;
00336 v.resize(4);
00337 v[0]=q.v.x; v[1]=q.v.y; v[2]=q.v.z; v[3]=q.w;
00338 }
00339 else if (representation == Mat) {
00340 if (rep != Mat)
00341 m = MatrixRef(NewObj Matrix(3,3));
00342 rep = Mat;
00343 (*m)(0,0) = 1; (*m)(0,1) = 0; (*m)(0,2) = 0;
00344 (*m)(1,0) = 0; (*m)(1,1) = 1; (*m)(1,2) = 0;
00345 (*m)(2,0) = 0; (*m)(2,1) = 0; (*m)(2,2) = 1;
00346 }
00347 else {
00348 rep = representation;
00349 v.resize(3);
00350 v[0]=v[1]=v[2]=0;
00351 }
00352
00353 }
00354
00355
00356 void Orient::setFromRotationComponent(const Matrix4& mt)
00357 {
00358 if (rep != Mat) {
00359 m = MatrixRef(NewObj Matrix(3,3));
00360 rep = Mat;
00361 }
00362 (*m)(0,0) = mt(1,1); (*m)(0,1) = mt(1,2); (*m)(0,2) = mt(1,3);
00363 (*m)(1,0) = mt(2,1); (*m)(1,1) = mt(2,2); (*m)(1,2) = mt(2,3);
00364 (*m)(2,0) = mt(3,1); (*m)(2,1) = mt(3,2); (*m)(2,2) = mt(3,3);
00365 }
00366
00367
00368
00369
00370 bool Orient::operator==(const Orient& o) const throw()
00371 {
00372 if (&o == this) return true;
00373
00374 Assert(o.rep < RepEnd);
00375
00376 if (rep == o.rep) {
00377 if (rep!=Mat) {
00378 if (v.size() == o.v.size())
00379 return v == o.v;
00380 else
00381 return false;
00382 }
00383 return *m == *o.m;
00384 }
00385
00386
00387 Orient tthis(*this);
00388 try {
00389 tthis.changeRep(o.rep);
00390 if (o.rep!=Mat)
00391 return tthis.v == o.v;
00392 return *tthis.m == *o.m;
00393 } catch (std::exception&) {}
00394 Orient to(o);
00395 try {
00396 to.changeRep(rep);
00397 if (rep!=Mat)
00398 return v == to.v;
00399 return *m == *to.m;
00400 } catch (std::exception&) {
00401 return false;
00402 }
00403 }
00404
00405
00406
00407
00408 bool Orient::equals(const Orient& o, Real epsilon) const throw()
00409 {
00410 if (&o == this) return true;
00411
00412 Assert(o.rep < RepEnd);
00413
00414 if (rep == o.rep) {
00415 if (rep!=Mat) {
00416 if (v.size() == o.v.size())
00417 return base::equals(v, o.v, epsilon);
00418 else
00419 return false;
00420 }
00421 return base::equals(*m, *o.m, epsilon);
00422 }
00423
00424
00425 Orient tthis(*this);
00426 try {
00427 tthis.changeRep(o.rep);
00428 if (o.rep!=Mat)
00429 return base::equals(tthis.v, o.v, epsilon);
00430 return base::equals(*(tthis.m), *o.m, epsilon);
00431 } catch (std::exception&) {}
00432 Orient to(o);
00433 try {
00434 to.changeRep(rep);
00435 if (rep!=Mat)
00436 return base::equals(v, to.v, epsilon);
00437 return base::equals(*m, *to.m, epsilon);
00438 } catch (std::exception&) {
00439 return false;
00440 }
00441
00442 }
00443
00444
00445
00446 void Orient::changeRep(Representation newRep) const
00447 {
00448 Assert(rep < RepEnd);
00449 Assert(newRep < RepEnd);
00450
00451 if (rep == newRep) return;
00452
00453
00454
00455 if (isEuler()) {
00456
00457 if (newRep == Quat) {
00458
00459 Quat4 qu;
00460 Real a[3], ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
00461 Axis i,j,k,h;
00462 Parity n;
00463 Repetition s;
00464 Frame f;
00465 getRep(rep,i,j,k,h,n,s,f);
00466 if (f==Rotating) {Real t = v[X]; v[X] = v[Z]; v[Z] = t;}
00467 if (n==Odd) v[Y] = -v[Y];
00468 ti = v[X]*0.5; tj = v[Y]*0.5; th = v[Z]*0.5;
00469 ci = Math::cos(ti); cj = Math::cos(tj); ch = Math::cos(th);
00470 si = Math::sin(ti); sj = Math::sin(tj); sh = Math::sin(th);
00471 cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
00472 if (s==Repeating) {
00473 a[i] = cj*(cs + sc);
00474 a[j] = sj*(cc + ss);
00475 a[k] = sj*(cs - sc);
00476 qu.w = cj*(cc - ss);
00477 } else {
00478 a[i] = cj*sc - sj*cs;
00479 a[j] = cj*ss + sj*cc;
00480 a[k] = cj*cs - sj*sc;
00481 qu.w = cj*cc + sj*ss;
00482 }
00483 if (n==Odd) a[j] = -a[j];
00484 qu.v.x = a[X]; qu.v.y = a[Y]; qu.v.z = a[Z];
00485 v.resize(4);
00486 v[X]=qu.v.x; v[Y]=qu.v.y; v[Z]=qu.v.z; v[W]=qu.w;
00487 rep=Quat;
00488 return;
00489
00490 }
00491 else if (newRep == Mat) {
00492
00493 m = MatrixRef(NewObj Matrix(3,3));
00494 Matrix& M(*this->m);
00495
00496 Real ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss;
00497 Axis i,j,k,h;
00498 Parity n;
00499 Repetition s;
00500 Frame f;
00501 getRep(rep,i,j,k,h,n,s,f);
00502 if (f==Rotating) {Real t = v[X]; v[X] = v[Z]; v[Z] = t;}
00503 if (n==Odd) { v[X] = -v[X]; v[Y] = -v[Y]; v[Z] = -v[Z];}
00504 ti = v[X]; tj = v[Y]; th = v[Z];
00505 ci = Math::cos(ti); cj = Math::cos(tj); ch = Math::cos(th);
00506 si = Math::sin(ti); sj = Math::sin(tj); sh = Math::sin(th);
00507 cc = ci*ch; cs = ci*sh; sc = si*ch; ss = si*sh;
00508 if (s==Repeating) {
00509 M(i,i) = cj; M(i,j) = sj*si; M(i,k) = sj*ci;
00510 M(j,i) = sj*sh; M(j,j) = -cj*ss+cc; M(j,k) = -cj*cs-sc;
00511 M(k,i) = -sj*ch; M(k,j) = cj*sc+cs; M(k,k) = cj*cc-ss;
00512 } else {
00513 M(i,i) = cj*ch; M(i,j) = sj*sc-cs; M(i,k) = sj*cc+ss;
00514 M(j,i) = cj*sh; M(j,j) = sj*ss+cc; M(j,k) = sj*cs-sc;
00515 M(k,i) = -sj; M(k,j) = cj*si; M(k,k) = cj*ci;
00516 }
00517
00518 rep=Mat;
00519 return;
00520 }
00521 else {
00522
00523 changeRep(Quat);
00524 changeRep(newRep);
00525 return;
00526 }
00527
00528 }
00529 else if (rep == Quat) {
00530
00531 if (isEuler(newRep)) {
00532
00533 changeRep(Mat);
00534 changeRep(newRep);
00535 return;
00536
00537 }
00538 else if (newRep == Mat) {
00539
00540 Real nq = v[0]*v[0]+v[1]*v[1]+v[2]*v[2]+v[3]*v[3];
00541
00542 Real s = (nq> Real(0))? (Real(2)/base::sqrt(nq)):Real(0);
00543
00544 Real xs = v[0]*s, ys = v[1]*s, zs = v[2]*s;
00545 Real wx = v[3]*xs,wy = v[3]*ys,wz = v[3]*zs;
00546 Real xx = v[0]*xs,xy = v[0]*ys,xz = v[0]*zs;
00547 Real yy = v[1]*ys,yz = v[1]*zs,zz = v[2]*zs;
00548
00549 m = MatrixRef(NewObj Matrix(3,3));
00550
00551 (*m)(0,0) = Real(1) - (yy+zz);
00552 (*m)(1,0) = xy+wz;
00553 (*m)(2,0) = xz-wy;
00554 (*m)(0,1) = xy - wz;
00555 (*m)(1,1) = Real(1) - (xx+zz);
00556 (*m)(2,1) = yz+wx;
00557 (*m)(0,2) = xz+wy;
00558 (*m)(1,2) = yz-wx;
00559 (*m)(2,2) = Real(1) - (xx+yy);
00560 rep = Mat;
00561 return;
00562 }
00563 else if (newRep == Quat)
00564 {
00565 return;
00566 }
00567
00568 }
00569 else if (rep == Mat) {
00570
00571 if (isEuler(newRep)) {
00572
00573 const Matrix& M(*this->m);
00574 v.resize(3);
00575 Axis i,j,k,h;
00576 Parity n;
00577 Repetition s;
00578 Frame f;
00579 getRep(newRep,i,j,k,h,n,s,f);
00580 if (s==Repeating) {
00581 Real sy = Math::sqrt(M(i,j)*M(i,j) + M(i,k)*M(i,k));
00582 if (sy > 16*consts::minReal) {
00583 v[X] = Math::atan2(M(i,j), M(i,k));
00584 v[Y] = Math::atan2(sy, M(i,i));
00585 v[Z] = Math::atan2(M(j,i), -M(k,i));
00586 } else {
00587 v[X] = Math::atan2(-M(j,k), M(j,j));
00588 v[Y] = Math::atan2(sy, M(i,i));
00589 v[Z] = 0;
00590 }
00591 } else {
00592 Real cy = Math::sqrt(M(i,i)*M(i,i) + M(j,i)*M(j,i));
00593 if (cy > 16*consts::minReal) {
00594 v[X] = Math::atan2(M(k,j), M(k,k));
00595 v[Y] = Math::atan2(-M(k,i), cy);
00596 v[Z] = Math::atan2(M(j,i), M(i,i));
00597 } else {
00598 v[X] = Math::atan2(-M(j,k), M(j,j));
00599 v[Y] = Math::atan2(-M(k,i), cy);
00600 v[Z] = 0;
00601 }
00602 }
00603 if (n==Odd) {v[X] = -v[X]; v[Y] = - v[Y]; v[Z] = -v[Z];}
00604 if (f==Rotating) {Real t = v[X]; v[X] = v[Z]; v[Z] = t;}
00605
00606 rep=newRep;
00607 return;
00608
00609 }
00610 else if (newRep == Quat) {
00611
00612
00613
00614 const Matrix& m(*this->m);
00615 v.resize(4);
00616
00617 Real tr = 1 + m(0,0) + m(1,1) + m(2,2);
00618 if (tr > consts::epsilon) {
00619 Real s = sqrt(tr)*2.0;
00620 v[0] = (m(2,1) - m(1,2))/s;
00621 v[1] = (m(0,2) - m(2,0))/s;
00622 v[2] = (m(1,0) - m(0,1))/s;
00623 v[3] = 0.25*s;
00624 }
00625 else {
00626
00627 if ((m(0,0) > m(1,1)) && (m(0,0) > m(2,2))) {
00628 Real s = sqrt(1+m(0,0)-m(1,1)-m(2,2))*2.0;
00629 v[0] = 0.25*s;
00630 v[1] = (m(1,0)+m(0,1))/s;
00631 v[2] = (m(0,2)+m(2,0))/s;
00632 v[3] = (m(2,1)-m(1,2))/s;
00633 }
00634 else if (m(1,1) > m(2,2)) {
00635 Real s = sqrt(1+m(1,1)-m(0,0)-m(2,2))*2.0;
00636 v[0] = (m(1,0)+m(0,1))/s;
00637 v[1] = 0.25*s;
00638 v[2] = (m(2,1)+m(1,2))/s;
00639 v[3] = (m(0,2)-m(2,0))/s;
00640 }
00641 else {
00642 Real s = sqrt(1+m(2,2)-m(0,0)-m(1,1))*2.0;
00643 v[0] = (m(0,2)+m(2,0))/s;
00644 v[1] = (m(2,1)+m(1,2))/s;
00645 v[2] = 0.25*s;
00646 v[3] = (m(1,0)-m(0,1))/s;
00647 }
00648 }
00649
00650 rep=Quat;
00651 return;
00652 }
00653 else if (newRep == Mat) {
00654 return;
00655 }
00656
00657
00658 }
00659
00660 throw std::runtime_error(Exception("conversion from "+representationString(rep)+" to "+representationString(newRep)+" unsupported"));
00661
00662 }
00663
00664
00665
00666
00667
00668 Matrix Orient::getBinv() const
00669 {
00670 Matrix Binv;
00671
00672 if (rep == EulerRPY) {
00673
00674
00675 Binv.resize(3,3);
00676
00677
00678 const Real& beta(v[1]);
00679 const Real& gamma(v[2]);
00680 Real cb = Math::cos(beta);
00681 Real cg = Math::cos(gamma);
00682 Real sb = Math::sin(beta);
00683 Real sg = Math::sin(gamma);
00684
00685 Binv(0,0) = cg*cb; Binv(0,1) = -sg; Binv(0,2) = 0;
00686 Binv(1,0) = sg*cb; Binv(1,1) = cg; Binv(1,2) = 0;
00687 Binv(2,0) = -sb; Binv(2,1) = 0; Binv(2,2) = 1;
00688 }
00689 else if (rep == Quat) {
00690
00691 Binv.resize(3,4);
00692
00693
00694
00695
00696 const Real& qx(v[0]);
00697 const Real& qy(v[1]);
00698 const Real& qz(v[2]);
00699 const Real& qw(v[3]);
00700
00701 Binv(0,0) = -qx; Binv(0,1) = +qw; Binv(0,2) = +qz; Binv(0,3) = -qy;
00702 Binv(1,0) = -qy; Binv(1,1) = -qz; Binv(1,2) = +qw; Binv(1,3) = +qx;
00703 Binv(2,0) = -qz; Binv(2,1) = +qy; Binv(2,2) = -qx; Binv(2,3) = +qw;
00704 Binv = 2.0*Binv;
00705
00706 }
00707 else {
00708 throw std::runtime_error(Exception("Binv generation from current orientation representation unsupported"));
00709 }
00710
00711 return Binv;
00712 }
00713
00714
00715
00716 Orient Orient::interpolate(const Orient& lower, const Orient& upper, Real t)
00717 {
00718 Math::bound(t, 0.0, 1.0);
00719
00720 if (t == 0.0) return lower;
00721 if (t == 1.0) return upper;
00722
00723
00724
00725 Orient ofrom(lower); ofrom.changeRep(Quat);
00726 Orient oto(upper); oto.changeRep(Quat);
00727 Quat4 from(ofrom[0], ofrom[1], ofrom[2], ofrom[3]);
00728 Quat4 to(oto[0], oto[1], oto[2], oto[3]);
00729
00730 Quat4 interp(Quat4::interpolate(from,to,t));
00731
00732 return Orient(interp);
00733 }
00734
00735
00736 Orient& Orient::invert()
00737 {
00738 if (rep == Mat) {
00739 Matrix3 m3( base::toMatrix3(*m) );
00740 m3.invert();
00741 *m = base::fromMatrix3(m3);
00742 }
00743 else {
00744 Quat4 q( getQuat4() );
00745 q.invert();
00746 *this = q;
00747 }
00748 return *this;
00749 }
00750
00751
00752
00753
00754 void Orient::serialize(Serializer& s)
00755 {
00756 Representation oldrep(rep);
00757 s(rep,"rep");
00758
00759 if (s.isOutput()) {
00760 if (rep!=Mat)
00761 s(v,"v");
00762 else
00763 s(*m,"m");
00764 }
00765 else {
00766 if (rep!=Mat) {
00767 if (oldrep==Mat) {
00768 delete &(*m);
00769 m=MatrixRef(0);
00770 }
00771 s(v,"v");
00772 }
00773 else {
00774 if (oldrep!=Mat)
00775 m = MatrixRef(NewObj Matrix(3,3));
00776 s(*m,"m");
00777 }
00778 }
00779 Assert(rep < RepEnd);
00780 }
00781
00782
00783
00784
00785