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 }