00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 #include "domUtils.h"
00024 #include "frame.h"
00025 #include <math.h>
00026 
00027 using namespace qglviewer;
00028 using namespace std;
00029 
00030 
00035 Frame::Frame()
00036   : constraint_(NULL), referenceFrame_(NULL)
00037 {}
00038 
00045 Frame::Frame(const Vec& position, const Quaternion& orientation)
00046   : t_(position), q_(orientation), constraint_(NULL), referenceFrame_(NULL)
00047 {}
00048 
00054 Frame& Frame::operator=(const Frame& frame)
00055 {
00056   
00057   
00058   setTranslationAndRotation(frame.translation(), frame.rotation());
00059   setConstraint(frame.constraint());
00060   setReferenceFrame(frame.referenceFrame());
00061   return *this;
00062 }
00063 
00068 Frame::Frame(const Frame& frame)
00069   : QObject()
00070 {
00071   (*this) = frame;
00072 }
00073 
00075 
00123 const GLdouble* Frame::matrix() const
00124 {
00125   static GLdouble m[4][4];
00126   getMatrix(m);
00127   return (const GLdouble*)(m);
00128 }
00129 
00131 void Frame::getMatrix(GLdouble m[4][4]) const
00132 {
00133   q_.getMatrix(m);
00134 
00135   m[3][0] = t_[0];
00136   m[3][1] = t_[1];
00137   m[3][2] = t_[2];
00138 }
00139 
00141 void Frame::getMatrix(GLdouble m[16]) const
00142 {
00143   q_.getMatrix(m);
00144 
00145   m[12] = t_[0];
00146   m[13] = t_[1];
00147   m[14] = t_[2];
00148 }
00149 
00164 Frame Frame::inverse() const
00165 {
00166   Frame fr(-(q_.inverseRotate(t_)), q_.inverse());
00167   fr.setReferenceFrame(referenceFrame());
00168   return fr;
00169 }
00170 
00196 const GLdouble* Frame::worldMatrix() const
00197 {
00198   
00199   if (referenceFrame())
00200   {
00201     static Frame fr;
00202     fr.setTranslation(position());
00203     fr.setRotation(orientation());
00204     return fr.matrix();
00205   }
00206   else
00207     return matrix();
00208 }
00209 
00211 void Frame::getWorldMatrix(GLdouble m[4][4]) const
00212 {
00213   const GLdouble* mat = worldMatrix();
00214   for (int i=0; i<4; ++i)
00215     for (int j=0; j<4; ++j)
00216       m[i][j] = mat[i*4+j];
00217 }
00218 
00220 void Frame::getWorldMatrix(GLdouble m[16]) const
00221 {
00222   const GLdouble* mat = worldMatrix();
00223   for (int i=0; i<16; ++i)
00224       m[i] = mat[i];
00225 }
00226 
00228 void Frame::setFromMatrix(const GLdouble m[4][4])
00229 {
00230   if (fabs(m[3][3]) < 1E-8)
00231     {
00232       qWarning("Frame::setFromMatrix: Null homogeneous coefficient");
00233       return;
00234     }
00235 
00236   double rot[3][3];
00237   for (int i=0; i<3; ++i)
00238     {
00239       t_[i] = m[3][i] / m[3][3];
00240       for (int j=0; j<3; ++j)
00241         
00242         rot[i][j] = m[j][i] / m[3][3];
00243     }
00244   q_.setFromRotationMatrix(rot);
00245   Q_EMIT modified();
00246 }
00247 
00272 void Frame::setFromMatrix(const GLdouble m[16])
00273 {
00274   GLdouble mat[4][4];
00275   for (int i=0; i<4; ++i)
00276     for (int j=0; j<4; ++j)
00277       mat[i][j] = m[i*4+j];
00278   setFromMatrix(mat);
00279 }
00280 
00282 
00283 
00285 void Frame::setTranslation(float x, float y, float z)
00286 {
00287   setTranslation(Vec(x, y, z));
00288 }
00289 
00291 void Frame::getTranslation(float& x, float& y, float& z) const
00292 {
00293   const Vec t = translation();
00294   x = t[0];
00295   y = t[1];
00296   z = t[2];
00297 }
00298 
00300 void Frame::setRotation(double q0, double q1, double q2, double q3)
00301 {
00302   setRotation(Quaternion(q0, q1, q2, q3));
00303 }
00304 
00308 void Frame::getRotation(double& q0, double& q1, double& q2, double& q3) const
00309 {
00310   const Quaternion q = rotation();
00311   q0 = q[0];
00312   q1 = q[1];
00313   q2 = q[2];
00314   q3 = q[3];
00315 }
00316 
00318 
00327 void Frame::translate(const Vec& t)
00328 {
00329   Vec tbis = t;
00330   translate(tbis);
00331 }
00332 
00335 void Frame::translate(Vec& t)
00336 {
00337   if (constraint())
00338     constraint()->constrainTranslation(t, this);
00339   t_ += t;
00340   Q_EMIT modified();
00341 }
00342 
00344 void Frame::translate(float x, float y, float z)
00345 {
00346   Vec t(x,y,z);
00347   translate(t);
00348 }
00349 
00351 void Frame::translate(float& x, float& y, float& z)
00352 {
00353   Vec t(x,y,z);
00354   translate(t);
00355   x = t[0];
00356   y = t[1];
00357   z = t[2];
00358 }
00359 
00368 void Frame::rotate(const Quaternion& q)
00369 {
00370   Quaternion qbis = q;
00371   rotate(qbis);
00372 }
00373 
00376 void Frame::rotate(Quaternion& q)
00377 {
00378   if (constraint())
00379     constraint()->constrainRotation(q, this);
00380   q_ *= q;
00381   q_.normalize(); 
00382   Q_EMIT modified();
00383 }
00384 
00386 void Frame::rotate(double& q0, double& q1, double& q2, double& q3)
00387 {
00388   Quaternion q(q0,q1,q2,q3);
00389   rotate(q);
00390   q0 = q[0];
00391   q1 = q[1];
00392   q2 = q[2];
00393   q3 = q[3];
00394 }
00395 
00397 void Frame::rotate(double q0, double q1, double q2, double q3)
00398 {
00399   Quaternion q(q0,q1,q2,q3);
00400   rotate(q);
00401 }
00402 
00414 void Frame::rotateAroundPoint(Quaternion& rotation, const Vec& point)
00415 {
00416   if (constraint())
00417     constraint()->constrainRotation(rotation, this);
00418   q_ *= rotation;
00419   q_.normalize(); 
00420   Vec trans = point + Quaternion(inverseTransformOf(rotation.axis()), rotation.angle()).rotate(position()-point) - t_;
00421   if (constraint())
00422     constraint()->constrainTranslation(trans, this);
00423   t_ += trans;
00424   Q_EMIT modified();
00425 }
00426 
00429 void Frame::rotateAroundPoint(const Quaternion& rotation, const Vec& point)
00430 {
00431   Quaternion rot = rotation;
00432   rotateAroundPoint(rot, point);
00433 }
00434 
00436 
00443 void Frame::setPosition(const Vec& position)
00444 {
00445   if (referenceFrame())
00446     setTranslation(referenceFrame()->coordinatesOf(position));
00447   else
00448     setTranslation(position);
00449 }
00450 
00452 void Frame::setPosition(float x, float y, float z)
00453 {
00454   setPosition(Vec(x, y, z));
00455 }
00456 
00462 void Frame::setPositionAndOrientation(const Vec& position, const Quaternion& orientation)
00463 {
00464   if (referenceFrame())
00465     {
00466       t_ = referenceFrame()->coordinatesOf(position);
00467       q_ = referenceFrame()->orientation().inverse() * orientation;
00468     }
00469   else
00470     {
00471       t_ = position;
00472       q_ = orientation;
00473     }
00474   Q_EMIT modified();
00475 }
00476 
00477 
00483 void Frame::setTranslationAndRotation(const Vec& translation, const Quaternion& rotation)
00484 {
00485   t_ = translation;
00486   q_ = rotation;
00487   Q_EMIT modified();
00488 }
00489 
00490 
00492 void Frame::getPosition(float& x, float& y, float& z) const
00493 {
00494   Vec p = position();
00495   x = p.x;
00496   y = p.y;
00497   z = p.z;
00498 }
00499 
00505 void Frame::setOrientation(const Quaternion& orientation)
00506 {
00507   if (referenceFrame())
00508     setRotation(referenceFrame()->orientation().inverse() * orientation);
00509   else
00510     setRotation(orientation);
00511 }
00512 
00514 void Frame::setOrientation(double q0, double q1, double q2, double q3)
00515 {
00516   setOrientation(Quaternion(q0, q1, q2, q3));
00517 }
00518 
00526 void Frame::getOrientation(double& q0, double& q1, double& q2, double& q3) const
00527 {
00528   Quaternion o = orientation();
00529   q0 = o[0];
00530   q1 = o[1];
00531   q2 = o[2];
00532   q3 = o[3];
00533 }
00534 
00537 Quaternion Frame::orientation() const
00538 {
00539   Quaternion res = rotation();
00540   const Frame* fr = referenceFrame();
00541   while (fr != NULL)
00542     {
00543       res = fr->rotation() * res;
00544       fr  = fr->referenceFrame();
00545     }
00546   return res;
00547 }
00548 
00549 
00551 
00556 void Frame::setTranslationWithConstraint(Vec& translation)
00557 {
00558   Vec deltaT = translation - this->translation();
00559   if (constraint())
00560     constraint()->constrainTranslation(deltaT, this);
00561 
00562   setTranslation(this->translation() + deltaT);
00563   translation = this->translation();
00564 }
00565 
00570 void Frame::setRotationWithConstraint(Quaternion& rotation)
00571 {
00572   Quaternion deltaQ = this->rotation().inverse() * rotation;
00573   if (constraint())
00574     constraint()->constrainRotation(deltaQ, this);
00575 
00576   
00577   deltaQ.normalize();
00578 
00579   setRotation(this->rotation() * deltaQ);
00580   q_.normalize();
00581   rotation = this->rotation();
00582 }
00583 
00586 void Frame::setTranslationAndRotationWithConstraint(Vec& translation, Quaternion& rotation)
00587 {
00588   Vec deltaT = translation - this->translation();
00589   Quaternion deltaQ = this->rotation().inverse() * rotation;
00590 
00591   if (constraint())
00592     {
00593       constraint()->constrainTranslation(deltaT, this);
00594       constraint()->constrainRotation(deltaQ, this);
00595     }
00596 
00597   
00598   deltaQ.normalize();
00599 
00600   t_ += deltaT;
00601   q_ *= deltaQ;
00602   q_.normalize();
00603 
00604   translation = this->translation();
00605   rotation = this->rotation();
00606 
00607   Q_EMIT modified();
00608 }
00609 
00612 void Frame::setPositionWithConstraint(Vec& position)
00613 {
00614   if (referenceFrame())
00615     position = referenceFrame()->coordinatesOf(position);
00616 
00617   setTranslationWithConstraint(position);
00618 }
00619 
00622 void Frame::setOrientationWithConstraint(Quaternion& orientation)
00623 {
00624   if (referenceFrame())
00625     orientation = referenceFrame()->orientation().inverse() * orientation;
00626 
00627   setRotationWithConstraint(orientation);
00628 }
00629 
00632 void Frame::setPositionAndOrientationWithConstraint(Vec& position, Quaternion& orientation)
00633 {
00634   if (referenceFrame())
00635     {
00636       position = referenceFrame()->coordinatesOf(position);
00637       orientation = referenceFrame()->orientation().inverse() * orientation;
00638     }
00639   setTranslationAndRotationWithConstraint(position, orientation);
00640 }
00641 
00642 
00644 
00656 void Frame::setReferenceFrame(const Frame* const refFrame)
00657 {
00658   if (settingAsReferenceFrameWillCreateALoop(refFrame))
00659     qWarning("Frame::setReferenceFrame would create a loop in Frame hierarchy");
00660   else
00661     {
00662       bool identical = (referenceFrame_ == refFrame);
00663       referenceFrame_ = refFrame;
00664       if (!identical)
00665         Q_EMIT modified();
00666     }
00667 }
00668 
00671 bool Frame::settingAsReferenceFrameWillCreateALoop(const Frame* const frame)
00672 {
00673   const Frame* f = frame;
00674   while (f != NULL)
00675     {
00676       if (f == this)
00677         return true;
00678       f = f->referenceFrame();
00679     }
00680   return false;
00681 }
00682 
00684 
00693 Vec Frame::coordinatesOf(const Vec& src) const
00694 {
00695   if (referenceFrame())
00696     return localCoordinatesOf(referenceFrame()->coordinatesOf(src));
00697   else
00698     return localCoordinatesOf(src);
00699 }
00700 
00706 Vec Frame::inverseCoordinatesOf(const Vec& src) const
00707 {
00708   const Frame* fr = this;
00709   Vec res = src;
00710   while (fr != NULL)
00711     {
00712       res = fr->localInverseCoordinatesOf(res);
00713       fr  = fr->referenceFrame();
00714     }
00715   return res;
00716 }
00717 
00722 Vec Frame::localCoordinatesOf(const Vec& src) const
00723 {
00724   return rotation().inverseRotate(src - translation());
00725 }
00726 
00731 Vec Frame::localInverseCoordinatesOf(const Vec& src) const
00732 {
00733   return rotation().rotate(src) + translation();
00734 }
00735 
00740 Vec Frame::coordinatesOfFrom(const Vec& src, const Frame* const from) const
00741 {
00742   if (this == from)
00743     return src;
00744   else
00745     if (referenceFrame())
00746       return localCoordinatesOf(referenceFrame()->coordinatesOfFrom(src, from));
00747     else
00748       return localCoordinatesOf(from->inverseCoordinatesOf(src));
00749 }
00750 
00755 Vec Frame::coordinatesOfIn(const Vec& src, const Frame* const in) const
00756 {
00757   const Frame* fr = this;
00758   Vec res = src;
00759   while ((fr != NULL) && (fr != in))
00760     {
00761       res = fr->localInverseCoordinatesOf(res);
00762       fr  = fr->referenceFrame();
00763     }
00764 
00765   if (fr != in)
00766     
00767     
00768     res = in->coordinatesOf(res);
00769 
00770   return res;
00771 }
00772 
00774 
00776 void Frame::getCoordinatesOf(const float src[3], float res[3]) const
00777 {
00778   const Vec r = coordinatesOf(Vec(src));
00779   for (int i=0; i<3 ; ++i)
00780     res[i] = r[i];
00781 }
00782 
00784 void Frame::getInverseCoordinatesOf(const float src[3], float res[3]) const
00785 {
00786   const Vec r = inverseCoordinatesOf(Vec(src));
00787   for (int i=0; i<3 ; ++i)
00788     res[i] = r[i];
00789 }
00790 
00792 void Frame::getLocalCoordinatesOf(const float src[3], float res[3]) const
00793 {
00794   const Vec r = localCoordinatesOf(Vec(src));
00795   for (int i=0; i<3 ; ++i)
00796     res[i] = r[i];
00797 }
00798 
00800 void Frame::getLocalInverseCoordinatesOf(const float src[3], float res[3]) const
00801 {
00802   const Vec r = localInverseCoordinatesOf(Vec(src));
00803   for (int i=0; i<3 ; ++i)
00804     res[i] = r[i];
00805 }
00806 
00808 void Frame::getCoordinatesOfIn(const float src[3], float res[3], const Frame* const in) const
00809 {
00810   const Vec r = coordinatesOfIn(Vec(src), in);
00811   for (int i=0; i<3 ; ++i)
00812     res[i] = r[i];
00813 }
00814 
00816 void Frame::getCoordinatesOfFrom(const float src[3], float res[3], const Frame* const from) const
00817 {
00818   const Vec r = coordinatesOfFrom(Vec(src), from);
00819   for (int i=0; i<3 ; ++i)
00820     res[i] = r[i];
00821 }
00822 
00823 
00825 
00834 Vec Frame::transformOf(const Vec& src) const
00835 {
00836   if (referenceFrame())
00837     return localTransformOf(referenceFrame()->transformOf(src));
00838   else
00839     return localTransformOf(src);
00840 }
00841 
00847 Vec Frame::inverseTransformOf(const Vec& src) const
00848 {
00849   const Frame* fr = this;
00850   Vec res = src;
00851   while (fr != NULL)
00852     {
00853       res = fr->localInverseTransformOf(res);
00854       fr  = fr->referenceFrame();
00855     }
00856   return res;
00857 }
00858 
00863 Vec Frame::localTransformOf(const Vec& src) const
00864 {
00865   return rotation().inverseRotate(src);
00866 }
00867 
00872 Vec Frame::localInverseTransformOf(const Vec& src) const
00873 {
00874   return rotation().rotate(src);
00875 }
00876 
00881 Vec Frame::transformOfFrom(const Vec& src, const Frame* const from) const
00882 {
00883   if (this == from)
00884     return src;
00885   else
00886     if (referenceFrame())
00887       return localTransformOf(referenceFrame()->transformOfFrom(src, from));
00888     else
00889       return localTransformOf(from->inverseTransformOf(src));
00890 }
00891 
00896 Vec Frame::transformOfIn(const Vec& src, const Frame* const in) const
00897 {
00898   const Frame* fr = this;
00899   Vec    res = src;
00900   while ((fr != NULL) && (fr != in))
00901     {
00902       res = fr->localInverseTransformOf(res);
00903       fr  = fr->referenceFrame();
00904     }
00905 
00906   if (fr != in)
00907     
00908     
00909     res = in->transformOf(res);
00910 
00911   return res;
00912 }
00913 
00915 
00917 void Frame::getTransformOf(const float src[3], float res[3]) const
00918 {
00919   Vec r = transformOf(Vec(src));
00920   for (int i=0; i<3 ; ++i)
00921     res[i] = r[i];
00922 }
00923 
00925 void Frame::getInverseTransformOf(const float src[3], float res[3]) const
00926 {
00927   Vec r = inverseTransformOf(Vec(src));
00928   for (int i=0; i<3 ; ++i)
00929     res[i] = r[i];
00930 }
00931 
00933 void Frame::getLocalTransformOf(const float src[3], float res[3]) const
00934 {
00935   Vec r = localTransformOf(Vec(src));
00936   for (int i=0; i<3 ; ++i)
00937     res[i] = r[i];
00938 }
00939 
00941 void Frame::getLocalInverseTransformOf(const float src[3], float res[3]) const
00942 {
00943   Vec r = localInverseTransformOf(Vec(src));
00944   for (int i=0; i<3 ; ++i)
00945     res[i] = r[i];
00946 }
00947 
00949 void Frame::getTransformOfIn(const float src[3], float res[3], const Frame* const in) const
00950 {
00951   Vec r = transformOfIn(Vec(src), in);
00952   for (int i=0; i<3 ; ++i)
00953     res[i] = r[i];
00954 }
00955 
00957 void Frame::getTransformOfFrom(const float src[3], float res[3], const Frame* const from) const
00958 {
00959   Vec r = transformOfFrom(Vec(src), from);
00960   for (int i=0; i<3 ; ++i)
00961     res[i] = r[i];
00962 }
00963 
00965 
00985 QDomElement Frame::domElement(const QString& name, QDomDocument& document) const
00986 {
00987   
00988   QDomElement e = document.createElement(name);
00989   e.appendChild(position().domElement("position", document));
00990   e.appendChild(orientation().domElement("orientation", document));
00991   return e;
00992 }
00993 
01002 void Frame::initFromDOMElement(const QDomElement& element)
01003 {
01004   
01005 
01006   
01007   
01008   
01009   
01010 
01011   QDomElement child=element.firstChild().toElement();
01012   while (!child.isNull())
01013     {
01014       if (child.tagName() == "position")
01015         setPosition(Vec(child));
01016       if (child.tagName() == "orientation")
01017         setOrientation(Quaternion(child).normalized());
01018 
01019       child = child.nextSibling().toElement();
01020     }
01021 }
01022 
01024 
01045 void Frame::alignWithFrame(const Frame* const frame, bool move, float threshold)
01046 {
01047   Vec directions[2][3];
01048   for (int d=0; d<3; ++d)
01049     {
01050       Vec dir((d==0)? 1.0 : 0.0, (d==1)? 1.0 : 0.0, (d==2)? 1.0 : 0.0);
01051       if (frame)
01052         directions[0][d] = frame->inverseTransformOf(dir);
01053       else
01054         directions[0][d] = dir;
01055       directions[1][d] = inverseTransformOf(dir);
01056     }
01057 
01058   float maxProj = 0.0f;
01059   float proj;
01060   unsigned short index[2];
01061   index[0] = index[1] = 0;
01062   for (int i=0; i<3; ++i)
01063     for (int j=0; j<3; ++j)
01064       if ( (proj=fabs(directions[0][i]*directions[1][j])) >= maxProj )
01065         {
01066           index[0] = i;
01067           index[1] = j;
01068           maxProj  = proj;
01069         }
01070 
01071   Frame old;
01072   old=*this;
01073 
01074   float coef = directions[0][index[0]] * directions[1][index[1]];
01075   if (fabs(coef) >= threshold)
01076     {
01077       const Vec axis = cross(directions[0][index[0]], directions[1][index[1]]);
01078       float angle = asin(axis.norm());
01079       if (coef >= 0.0)
01080         angle = -angle;
01081       
01082       rotate(rotation().inverse() * Quaternion(axis, angle) * orientation());
01083 
01084       
01085       unsigned short d = (index[1]+1) % 3;
01086       Vec dir((d==0)? 1.0 : 0.0, (d==1)? 1.0 : 0.0, (d==2)? 1.0 : 0.0);
01087       dir = inverseTransformOf(dir);
01088 
01089       float max = 0.0f;
01090       for (int i=0; i<3; ++i)
01091         {
01092           float proj = fabs(directions[0][i]*dir);
01093           if (proj > max)
01094             {
01095               index[0] = i;
01096               max = proj;
01097             }
01098         }
01099 
01100       if (max >= threshold)
01101         {
01102           const Vec axis = cross(directions[0][index[0]], dir);
01103           float angle = asin(axis.norm());
01104           if (directions[0][index[0]] * dir >= 0.0)
01105             angle = -angle;
01106           
01107           rotate(rotation().inverse() * Quaternion(axis, angle) * orientation());
01108         }
01109     }
01110 
01111   if (move)
01112     {
01113       Vec center;
01114       if (frame)
01115         center = frame->position();
01116 
01117       
01118       translate(center - orientation().rotate(old.coordinatesOf(center)) - translation());
01119     }
01120 }
01121 
01126 void Frame::projectOnLine(const Vec& origin, const Vec& direction)
01127 {
01128   
01129   
01130   
01131   
01132   
01133   const Vec shift = origin - position();
01134   Vec proj = shift;
01135   proj.projectOnAxis(direction);
01136   translate(shift-proj);
01137 }