Simbody  3.4 (development)
UnitVec.h
Go to the documentation of this file.
00001 #ifndef SimTK_UNITVEC_H 
00002 #define SimTK_UNITVEC_H 
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                       Simbody(tm): SimTKcommon                             *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK biosimulation toolkit originating from           *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody.  *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-12 Stanford University and the Authors.        *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors: Paul Mitiguy                                                 *
00015  *                                                                            *
00016  * Licensed under the Apache License, Version 2.0 (the "License"); you may    *
00017  * not use this file except in compliance with the License. You may obtain a  *
00018  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0.         *
00019  *                                                                            *
00020  * Unless required by applicable law or agreed to in writing, software        *
00021  * distributed under the License is distributed on an "AS IS" BASIS,          *
00022  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
00023  * See the License for the specific language governing permissions and        *
00024  * limitations under the License.                                             *
00025  * -------------------------------------------------------------------------- */
00026 
00030 #include "SimTKcommon/SmallMatrix.h"
00031 #include "SimTKcommon/internal/CoordinateAxis.h"
00032 
00033 #include <iosfwd>  // Forward declaration of iostream
00034 
00035 namespace SimTK {
00036 
00037 //-----------------------------------------------------------------------------
00038 // Forward declarations. These are templatized by precision P and and stride S
00039 // but always have length 3. TODO: this should be generalized to other lengths.
00040 template <class P, int S> class UnitVec;
00041 template <class P, int S> class UnitRow;
00042 
00043 // UnitVec3 is more intelligible name for UnitVec<Real,1>.
00044 typedef UnitVec<Real,1>     UnitVec3;
00045 typedef UnitVec<float,1>    fUnitVec3;
00046 typedef UnitVec<double,1>   dUnitVec3;
00047 
00048 //-----------------------------------------------------------------------------
00054 //-----------------------------------------------------------------------------
00055 template <class P, int S>
00056 class UnitVec : public Vec<3,P,S> {
00057     typedef P   RealP;
00058 public:
00059     typedef Vec<3,P,S>      BaseVec;
00060     typedef UnitRow<P,S>    TransposeType;
00061 
00064     UnitVec() : BaseVec(NTraits<P>::getNaN()) {}
00065 
00068     UnitVec(const UnitVec& u) 
00069     :   BaseVec( static_cast<const BaseVec&>(u) ) {}
00070 
00073     template <int S2> UnitVec(const UnitVec<P,S2>& u) 
00074     :   BaseVec( static_cast<const typename UnitVec<P,S2>::BaseVec&>(u) ) {}
00075 
00077     explicit UnitVec(const BaseVec& v) : BaseVec(v/v.norm()) {}
00080     template <int S2> 
00081     explicit UnitVec(const Vec<3,P,S2>& v) : BaseVec(v/v.norm())  {}
00082 
00086     UnitVec(const RealP& x, const RealP& y, const RealP& z) : BaseVec(x,y,z)  
00087     {   static_cast<BaseVec&>(*this) /= BaseVec::norm(); }
00088 
00091     UnitVec(const CoordinateAxis& axis) : BaseVec(0) 
00092     {   BaseVec::operator[](axis) = 1; }
00093 
00097     UnitVec(const CoordinateDirection& dir) : BaseVec(0) 
00098     {   BaseVec::operator[](dir.getAxis()) = RealP(dir.getDirection()); }
00099 
00102     explicit UnitVec(int axis) : BaseVec(0) 
00103     {   assert(0 <= axis && axis <= 2);
00104         BaseVec::operator[](axis) = 1; }
00105 
00107     UnitVec& operator=(const UnitVec& u) 
00108     {   BaseVec::operator=(static_cast<const BaseVec&>(u)); 
00109         return *this; }
00110 
00113     template <int S2> UnitVec& operator=(const UnitVec<P,S2>& u) 
00114     {   BaseVec::operator=(static_cast<const typename UnitVec<P,S2>::BaseVec&>(u));
00115         return *this; }
00116 
00118     const BaseVec& asVec3() const {return static_cast<const BaseVec&>(*this);}
00119 
00120     // Override Vec3 methods which preserve length. These return a 
00121     // packed UnitVec regardless of our stride.
00122 
00125     UnitVec<P,1> negate()    const {return UnitVec<P,1>(-asVec3(),true);}
00128     UnitVec<P,1> operator-() const {return negate();}
00129 
00132     const TransposeType& operator~() const {return *reinterpret_cast<const TransposeType*>(this);}
00135     TransposeType& operator~() {return *reinterpret_cast<TransposeType*>(this);}
00136 
00137     // We have to define these here so that the non-const ones won't be
00138     // inherited. We don't trust anyone to write on one element of a UnitVec!
00139 
00143     const RealP&  operator[](int i) const  { return BaseVec::operator[](i); }
00147     const RealP&  operator()(int i) const  { return BaseVec::operator()(i); }
00148 
00154     UnitVec<P,1> abs() const {return UnitVec<P,1>( asVec3().abs(), true );}
00155 
00159     inline UnitVec<P,1> perp() const;
00160 
00164     UnitVec(const BaseVec& v, bool) : BaseVec(v) {}
00169     template <int S2> UnitVec(const Vec<3,RealP,S2>& v, bool) : BaseVec(v) { }
00170 
00176     static const UnitVec& getAs(const RealP* p)  
00177     {   return *reinterpret_cast<const UnitVec*>(p); }
00178 };
00179 
00180 
00181 template <class P, int S> inline UnitVec<P,1> 
00182 UnitVec<P,S>::perp() const {
00183     // Choose the coordinate axis which makes the largest angle
00184     // with this vector, that is, has the "least u" along it.
00185     const UnitVec<P,1> u(abs());    // reflect to first octant
00186     const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2)
00187                                      : (u[1] <= u[2] ? 1 : 2);
00188     // Cross returns a Vec3 result which is then normalized.
00189     return UnitVec<P,1>( *this % UnitVec<P,1>(minAxis) );
00190 }
00191 
00194 template <class P, int S1, int S2> inline bool
00195 operator==(const UnitVec<P,S1>& u1, const UnitVec<P,S2>& u2)
00196 {   return u1.asVec3() == u2.asVec3(); }
00197 
00201 template <class P, int S1, int S2> inline bool
00202 operator!=(const UnitVec<P,S1>& u1, const UnitVec<P,S2>& u2)
00203 {   return !(u1==u2); }
00204 
00205 //-----------------------------------------------------------------------------
00210 //-----------------------------------------------------------------------------
00211 template <class P, int S>
00212 class UnitRow : public Row<3,P,S> {
00213     typedef P   RealP;
00214 public:
00215     typedef Row<3,P,S>      BaseRow;
00216     typedef UnitVec<P,S>    TransposeType;
00217 
00218     UnitRow() : BaseRow(NTraits<P>::getNaN()) { }
00219 
00221     UnitRow(const UnitRow& u) 
00222     :   BaseRow(static_cast<const BaseRow&>(u)) {}
00223 
00226     template <int S2> UnitRow(const UnitRow<P,S2>& u)
00227     :   BaseRow(static_cast<const typename UnitRow<P,S2>::BaseRow&>(u)) { }
00228 
00230     UnitRow& operator=(const UnitRow& u) 
00231     {   BaseRow::operator=(static_cast<const BaseRow&>(u)); 
00232         return *this; }
00233 
00235     template <int S2> UnitRow& operator=(const UnitRow<P,S2>& u) 
00236     {   BaseRow::operator=(static_cast<const typename UnitRow<P,S2>::BaseRow&>(u));
00237         return *this; }
00238 
00240     explicit UnitRow(const BaseRow& v) : BaseRow(v/v.norm()) {}
00243     template <int S2> 
00244     explicit UnitRow(const Row<3,P,S2>& v) : BaseRow(v/v.norm()) {}
00245 
00248     UnitRow(const RealP& x, const RealP& y, const RealP& z)
00249     :   BaseRow(x,y,z)
00250     {   static_cast<BaseRow&>(*this) /= BaseRow::norm(); }
00251 
00253     explicit UnitRow(int axis) : BaseRow(0) 
00254     {   assert(0 <= axis && axis <= 2);
00255         BaseRow::operator[](axis) = 1; }
00256 
00258     const BaseRow& asRow3() const  {return static_cast<const BaseRow&>(*this);}
00259 
00260     // Override Row3 methods which preserve length. These return the 
00261     // packed UnitRow regardless of our stride.
00262 
00265     UnitRow<P,1> negate()    const  { return UnitRow<P,1>(-asRow3(),true); }
00268     UnitRow<P,1> operator-() const  { return negate();}
00269 
00272     const TransposeType&  operator~() const {return *reinterpret_cast<const TransposeType*>(this);}
00275     TransposeType& operator~() {return *reinterpret_cast<TransposeType*>(this);}
00276 
00277     // We have to define these here so that the non-const ones won't be
00278     // inherited. We don't trust anyone to write on one element of a UnitRow!
00279 
00283     const RealP&  operator[](int i) const  { return BaseRow::operator[](i); }
00287     const RealP&  operator()(int i) const  { return BaseRow::operator()(i); }
00288 
00294     UnitRow<P,1> abs() const {return UnitRow<P,1>(asRow3().abs(),true);}
00295 
00299     inline UnitRow<P,1> perp() const;
00300 
00304     UnitRow( const BaseRow& v, bool ) : BaseRow(v) { }
00309     template <int S2> UnitRow( const Row<3,P,S2>& v, bool ) : BaseRow(v) { }
00310 
00316     static const UnitRow& getAs(const RealP* p)  
00317     {   return *reinterpret_cast<const UnitRow*>(p); }
00318 };
00319 
00320 template <class P, int S>
00321 inline UnitRow<P,1> UnitRow<P,S>::perp() const {
00322     // Choose the coordinate axis which makes the largest angle
00323     // with this vector, that is, has the "least u" along it.
00324     const UnitRow<P,1> u(abs());    // reflect to first octant
00325     const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2)
00326                                      : (u[1] <= u[2] ? 1 : 2);
00327     // Cross returns a Row3 result which is then normalized.
00328     return UnitRow<P,1>(*this % UnitRow<P,1>(minAxis));
00329 }
00330 
00331 
00334 template <class P, int S1, int S2> inline bool
00335 operator==(const UnitRow<P,S1>& u1, const UnitRow<P,S2>& u2)
00336 {   return u1.asRow3() == u2.asRow3(); }
00337 
00341 template <class P, int S1, int S2> inline bool
00342 operator!=(const UnitRow<P,S1>& u1, const UnitRow<P,S2>& u2)
00343 {   return !(u1==u2); }
00344 
00345 //------------------------------------------------------------------------------
00346 }  // End of namespace SimTK
00347 
00348 //--------------------------------------------------------------------------
00349 #endif // SimTK_UNITVEC_H_
00350 //--------------------------------------------------------------------------
00351 
00352 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines