Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/Transform.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)1996 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: Transform.cpp 1029 2004-02-11 20:45:54Z jungd $
00019   $Revision: 1.4 $
00020   $Date: 2004-02-11 15:45:54 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022         
00023 ****************************************************************************/
00024 
00025 #include <base/Transform>
00026 
00027 using base::Transform;
00028 using base::Matrix4;
00029 using base::Vector3;
00030 using base::Point3;
00031 using base::Quat4;
00032 
00033 
00034 // constructors
00035 Transform::Transform(const Vector3& translation)
00036   : isIdentity(translation==Vector3(0,0,0)), isPureTranslationRotation(true), 
00037     hasTranslation(translation!=Vector3(0,0,0)), hasRotation(false),
00038     trans(translation) {}
00039     
00040 Transform::Transform(const Orient& rotation)
00041   : isIdentity(rotation.equals(Quat4())), isPureTranslationRotation(true),
00042     hasTranslation(false), hasRotation(!rotation.equals(Quat4())),
00043     orient(rotation) {}
00044 
00045 Transform::Transform(const Quat4& rotation)
00046   : isIdentity(rotation.equals(Quat4())), isPureTranslationRotation(true),
00047     hasTranslation(false), hasRotation(!rotation.equals(Quat4())),
00048     orient(rotation) {}
00049 
00050 Transform::Transform(const Matrix3& rotation)
00051   : isIdentity(false), isPureTranslationRotation(false),
00052     hasTranslation(false), hasRotation(true),
00053     t(rotation) {}
00054 
00055 Transform::Transform(const Vector3& translation, const Orient& rotation)
00056   : isIdentity(false), isPureTranslationRotation(true), 
00057     hasTranslation(translation!=Vector3(0,0,0)), hasRotation(!rotation.equals(Quat4())),
00058     orient(rotation), trans(translation) {}
00059     
00060 Transform::Transform(const Vector3& translation, const Quat4& rotation)
00061   : isIdentity(false), isPureTranslationRotation(true), 
00062     hasTranslation(translation!=Vector3(0,0,0)), hasRotation(!rotation.equals(Quat4())),
00063     orient(rotation), trans(translation) {}
00064     
00065 Transform::Transform(const Vector3& translation, const Matrix3& rotation)
00066   : isIdentity(false), isPureTranslationRotation(false), 
00067     hasTranslation(true), hasRotation(true),
00068     t(rotation) 
00069 {
00070   t.setTranslationComponent(translation); 
00071 }
00072     
00073 Transform::Transform(const Matrix4& t)
00074   : isIdentity(false), isPureTranslationRotation(false), t(t) {}
00075   
00076 Transform::Transform(const Transform& tr) 
00077   : isIdentity(tr.isIdentity), isPureTranslationRotation(tr.isPureTranslationRotation),
00078     hasTranslation(tr.hasTranslation), hasRotation(tr.hasRotation),
00079     orient(tr.orient), trans(tr.trans), t(tr.t) {}
00080 
00081 
00082 Transform& Transform::operator=(const Transform& t)
00083 { 
00084   isIdentity=t.isIdentity;
00085   isPureTranslationRotation=t.isPureTranslationRotation;
00086   hasTranslation = t.hasTranslation;
00087   hasRotation = t.hasRotation;
00088 
00089   if (!isIdentity) {
00090     if (!isPureTranslationRotation) 
00091       this->t=t.t;
00092     else {
00093       orient = t.orient;
00094       trans = t.trans;
00095     }
00096   }
00097   return *this;
00098 }
00099 
00100 //!!! this is broken when one side is a matrix and the other not    
00101 bool Transform::operator==(const Transform& rhs) const
00102 {
00103   if (isIdentity && rhs.isIdentity) return true;
00104   
00105   if (isPureTranslationRotation) {
00106     if (hasTranslation) {
00107       if (hasRotation) {
00108         return (orient == rhs.orient) && (trans == rhs.trans);
00109       }
00110       return (trans == rhs.trans);
00111     }
00112     return (orient == rhs.orient);
00113   }
00114   return t == rhs.t;
00115 }
00116 
00117 //!!! this is broken when one side is a matrix and the other not    
00118 bool Transform::equals(const Transform& rhs, Real epsilon) const throw()
00119 {
00120   if (isIdentity && rhs.isIdentity) return true;
00121   
00122   if (isPureTranslationRotation) {
00123     if (hasTranslation) {
00124       if (hasRotation) {
00125         return (orient.equals(rhs.orient,epsilon)) && (trans.equals(rhs.trans,epsilon));
00126       }
00127       return (trans.equals(rhs.trans,epsilon));
00128     }
00129     return (orient.equals(rhs.orient,epsilon));
00130   }
00131   return t.equals(rhs.t,epsilon);
00132 }
00133     
00134     
00135     
00136 
00137 Matrix4 Transform::getTransform() const
00138 {
00139   if (isIdentity)
00140     return Matrix4();
00141   
00142   if (isPureTranslationRotation) {
00143     Matrix4 tm;
00144     if (hasRotation)
00145       tm = orient.getQuat4(); 
00146     if (hasTranslation)
00147       tm.setTranslationComponent(trans);
00148     return tm;
00149   }
00150   else
00151     return t;
00152 }
00153 
00154 
00155 void Transform::setToRotation(const Vector3& axis, Real angle)
00156 {
00157   isIdentity = false;
00158   isPureTranslationRotation = true;
00159   hasTranslation=false;
00160   hasRotation=true;
00161   Quat4 q;
00162   q.setRotation(axis,angle);
00163   orient = q;
00164 }
00165 
00166 
00167 void Transform::setToRotation(const Quat4& orient)
00168 {
00169   isIdentity = false;
00170   isPureTranslationRotation = true;
00171   hasTranslation=false;
00172   hasRotation=true;
00173   this->orient=orient;
00174 }
00175 
00176 void Transform::setToTranslation(const Vector3& trans)
00177 {
00178   isIdentity = false;
00179   isPureTranslationRotation = true;
00180   hasTranslation=true;
00181   hasRotation=false;
00182   this->trans=trans;
00183 }
00184 
00185 
00186 void Transform::setRotationComponent(const Vector3& axis, Real angle)
00187 {
00188   if (isIdentity || isPureTranslationRotation) {
00189     hasRotation=true;
00190     Quat4 q;
00191     q.setRotation(axis,angle);
00192     orient = q;
00193     if (isIdentity)  
00194       hasTranslation=isIdentity=false;
00195   }
00196   else {
00197     Matrix4 r(Quat4(axis,angle));
00198     r.e(4,4)=0;
00199     Matrix4 sm(t);
00200     sm.e(1,1)=sm.e(1,2)=sm.e(1,3)=sm.e(2,1)=sm.e(2,2)=sm.e(2,3)=sm.e(3,1)=sm.e(3,2)=sm.e(3,3)=0;
00201     sm+=r;
00202     t=sm;
00203   }
00204 }
00205 
00206 
00207 void Transform::setRotationComponent(const Quat4& orient)
00208 {
00209   if (isIdentity || isPureTranslationRotation) {
00210     hasRotation=true;
00211     this->orient=orient;
00212     if (isIdentity)  
00213       hasTranslation=isIdentity=false;
00214   }
00215   else {
00216     Matrix4 r(orient);
00217     r.e(4,4)=0;
00218     Matrix4 sm(t);
00219     sm.e(1,1)=sm.e(1,2)=sm.e(1,3)=sm.e(2,1)=sm.e(2,2)=sm.e(2,3)=sm.e(3,1)=sm.e(3,2)=sm.e(3,3)=0;
00220     sm+=r;
00221     t=sm;
00222   }
00223 }
00224 
00225 
00226 void Transform::setRotationComponent(const Orient& orient)
00227 {
00228   if (isIdentity || isPureTranslationRotation) {
00229     hasRotation=true;
00230     this->orient=orient;
00231     if (isIdentity)  
00232       hasTranslation=isIdentity=false;
00233   }
00234   else {
00235     Matrix4 r(orient);
00236     r.e(4,4)=0;
00237     Matrix4 sm(t);
00238     sm.e(1,1)=sm.e(1,2)=sm.e(1,3)=sm.e(2,1)=sm.e(2,2)=sm.e(2,3)=sm.e(3,1)=sm.e(3,2)=sm.e(3,3)=0;
00239     sm+=r;
00240     t=sm;
00241   }
00242 }
00243 
00244 
00245 void Transform::setRotationComponent(const Matrix3& rotation)
00246 {
00247   if (isIdentity || isPureTranslationRotation) {
00248     hasRotation=true;
00249     this->orient = rotation;
00250     if (isIdentity)  
00251       hasTranslation=isIdentity=false;
00252   }
00253   else {
00254     const Matrix3& R(rotation);
00255     t(1,1)=R(1,1); t(1,2)=R(1,2); t(1,3)=R(1,3);
00256     t(2,1)=R(2,1); t(2,2)=R(2,2); t(2,3)=R(2,3);
00257     t(3,1)=R(3,1); t(3,2)=R(3,2); t(3,3)=R(3,3);
00258   }
00259 }
00260 
00261 
00262 void Transform::setTranslationComponent(const Vector3& trans)
00263 {
00264   if (isIdentity || isPureTranslationRotation) {
00265     hasTranslation=true;
00266     this->trans=trans;
00267     if (isIdentity)
00268       hasRotation=isIdentity=false;
00269   }
00270   else {
00271     t.setTranslationComponent(trans);
00272   }
00273 }
00274 
00275 
00276 void Transform::setTransform(const Matrix4& m)
00277 {
00278   isIdentity=false;
00279   isPureTranslationRotation=false;
00280   t=m;
00281 }
00282 
00283 
00284 Transform& Transform::invert()
00285 {
00286   if (isIdentity) return *this;
00287   if (!isPureTranslationRotation)
00288     t.invert(); 
00289   else {
00290     if (!hasTranslation)
00291       orient.invert();
00292     else {
00293       if (!hasRotation)
00294         trans = -trans;
00295       else {
00296         t = getTransform();
00297         t.invert();
00298         isPureTranslationRotation = false;
00299         hasTranslation = hasRotation = true;
00300         isIdentity = (t.equals(Matrix4(1)));
00301       }
00302     }
00303   }
00304   return *this;
00305 }
00306 
00307 
00308 
00309 void Transform::transformPoint(Point3& p) const
00310 {
00311   if (isIdentity) return;
00312   if (isPureTranslationRotation) {
00313     if (hasRotation) orient.rotatePoint(p);
00314     if (hasTranslation) p+=trans;
00315   }
00316   else
00317     p = t*p;
00318 }
00319 
00320 void Transform::transformPoint(Point4& p) const
00321 {
00322   if (isIdentity) return;
00323   if (isPureTranslationRotation) {
00324     if (hasRotation) orient.rotatePoint(p);
00325     if (hasTranslation) p+=trans;
00326   }
00327   else
00328     p=t*p;
00329 }
00330 
00331 
00332 base::Point3 Transform::rotate(const Point3& p) const
00333 {
00334   if (isIdentity) return p;
00335   if (isPureTranslationRotation) {
00336     if (hasRotation) return orient.rotate(p);
00337   }
00338   else {
00339     Matrix3 R = t;
00340     return R*p;
00341   }
00342   return p;
00343 }
00344 
00345 
00346 base::Point3 Transform::translate(const Point3& p) const
00347 {
00348   if (isIdentity) return p;
00349   if (isPureTranslationRotation) {
00350     if (hasTranslation) return p+trans;
00351   }
00352   else {
00353     return Point3(p.x+t(1,4),p.y+t(2,4),p.z+t(3,4)); // check!!!
00354   }
00355   return p;
00356 }
00357 
00358 
00359 
00360 Transform& Transform::operator*=(const Transform& rhs)
00361 {
00362   if (rhs.identity()) return *this;
00363 
00364   if (isIdentity) {
00365     *this = rhs;
00366     return *this;
00367   }
00368 
00369   if (isPureTranslationRotation && rhs.isPureTranslationRotation) {
00370 
00371     if (hasTranslation && !hasRotation) {
00372 
00373       if (!rhs.containsRotation()) {
00374         trans += rhs.trans;
00375         return *this;
00376       }
00377 
00378       Vector3 lhstrans(trans);
00379       *this = rhs;
00380       setTranslationComponent(lhstrans + trans);
00381       return *this;
00382     }
00383 
00384     if (hasRotation && !hasTranslation && rhs.containsRotation() && !rhs.containsTranslation()) {
00385       Quat4 thisq(orient.getQuat4());
00386       Quat4 rhsq(rhs.orient.getQuat4());
00387       orient = thisq*rhsq;
00388       return *this;
00389     }
00390 
00391   }
00392 
00393   this->t = getTransform(); // convert this to Matrix4 transform
00394   this->t *= rhs.getTransform();
00395   isPureTranslationRotation=false;
00396 
00397   return *this;
00398 }
00399 
00400 
00401 std::ostream& base::operator<<(std::ostream& out, const Transform& t)
00402 {
00403   if (t.identity()) {
00404     out << "T:" << Matrix4();
00405   }
00406   else {
00407     if (t.isTransRotationOnly()) {
00408       out << "r:" << t.getRotation() << " t:" << t.getTranslation();
00409     }
00410     else
00411       out << "T:" << t.getTransform();
00412   }
00413 
00414   return out;
00415 }

Generated on Thu Jul 29 15:56:16 2004 for OpenSim by doxygen 1.3.6