Simbody
|
00001 #ifndef SimTK_UNITVEC_H 00002 #define SimTK_UNITVEC_H 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simmatrix(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core 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. * 00011 * * 00012 * Portions copyright (c) 2005-10 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: Paul Mitiguy * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00038 #include "SimTKcommon/SmallMatrix.h" 00039 #include "SimTKcommon/internal/CoordinateAxis.h" 00040 00041 #include <iosfwd> // Forward declaration of iostream 00042 00043 namespace SimTK { 00044 00045 //----------------------------------------------------------------------------- 00046 // Forward declarations. These are templatized by precision P and and stride S 00047 // but always have length 3. TODO: this should be generalized to other lengths. 00048 template <class P, int S> class UnitVec; 00049 template <class P, int S> class UnitRow; 00050 00051 // UnitVec3 is more intelligible name for UnitVec<Real,1>. 00052 typedef UnitVec<Real,1> UnitVec3; 00053 typedef UnitVec<float,1> fUnitVec3; 00054 typedef UnitVec<double,1> dUnitVec3; 00055 00056 //----------------------------------------------------------------------------- 00062 //----------------------------------------------------------------------------- 00063 template <class P, int S> 00064 class UnitVec : public Vec<3,P,S> { 00065 typedef P RealP; 00066 public: 00067 typedef Vec<3,P,S> BaseVec; 00068 typedef UnitRow<P,S> TransposeType; 00069 00072 UnitVec() : BaseVec(NTraits<P>::getNaN()) {} 00073 00076 UnitVec(const UnitVec& u) 00077 : BaseVec( static_cast<const BaseVec&>(u) ) {} 00078 00081 template <int S2> UnitVec(const UnitVec<P,S2>& u) 00082 : BaseVec( static_cast<const typename UnitVec<P,S2>::BaseVec&>(u) ) {} 00083 00085 explicit UnitVec(const BaseVec& v) : BaseVec(v/v.norm()) {} 00088 template <int S2> 00089 explicit UnitVec(const Vec<3,P,S2>& v) : BaseVec(v/v.norm()) {} 00090 00094 UnitVec(const RealP& x, const RealP& y, const RealP& z) : BaseVec(x,y,z) 00095 { static_cast<BaseVec&>(*this) /= BaseVec::norm(); } 00096 00099 UnitVec(const CoordinateAxis& axis) : BaseVec(0) 00100 { BaseVec::operator[](axis) = 1; } 00101 00105 UnitVec(const CoordinateDirection& dir) : BaseVec(0) 00106 { BaseVec::operator[](dir.getAxis()) = RealP(dir.getDirection()); } 00107 00110 explicit UnitVec(int axis) : BaseVec(0) 00111 { assert(0 <= axis && axis <= 2); 00112 BaseVec::operator[](axis) = 1; } 00113 00115 UnitVec& operator=(const UnitVec& u) 00116 { BaseVec::operator=(static_cast<const BaseVec&>(u)); 00117 return *this; } 00118 00121 template <int S2> UnitVec& operator=(const UnitVec<P,S2>& u) 00122 { BaseVec::operator=(static_cast<const typename UnitVec<P,S2>::BaseVec&>(u)); 00123 return *this; } 00124 00126 const BaseVec& asVec3() const {return static_cast<const BaseVec&>(*this);} 00127 00128 // Override Vec3 methods which preserve length. These return a 00129 // packed UnitVec regardless of our stride. 00130 00133 UnitVec<P,1> negate() const {return UnitVec<P,1>(-asVec3(),true);} 00136 UnitVec<P,1> operator-() const {return negate();} 00137 00140 const TransposeType& operator~() const {return *reinterpret_cast<const TransposeType*>(this);} 00143 TransposeType& operator~() {return *reinterpret_cast<TransposeType*>(this);} 00144 00145 // We have to define these here so that the non-const ones won't be 00146 // inherited. We don't trust anyone to write on one element of a UnitVec! 00147 00151 const RealP& operator[](int i) const { return BaseVec::operator[](i); } 00155 const RealP& operator()(int i) const { return BaseVec::operator()(i); } 00156 00162 UnitVec<P,1> abs() const {return UnitVec<P,1>( asVec3().abs(), true );} 00163 00167 inline UnitVec<P,1> perp() const; 00168 00172 UnitVec(const BaseVec& v, bool) : BaseVec(v) {} 00177 template <int S2> UnitVec(const Vec<3,RealP,S2>& v, bool) : BaseVec(v) { } 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 00301 // This constructor is only for our friends whom we trust to 00302 // give us an already-normalized vector. 00303 UnitRow( const BaseRow& v, bool ) : BaseRow(v) { } 00304 template <int S2> UnitRow( const Row<3,P,S2>& v, bool ) : BaseRow(v) { } 00305 }; 00306 00307 template <class P, int S> 00308 inline UnitRow<P,1> UnitRow<P,S>::perp() const { 00309 // Choose the coordinate axis which makes the largest angle 00310 // with this vector, that is, has the "least u" along it. 00311 const UnitRow<P,1> u(abs()); // reflect to first octant 00312 const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2) 00313 : (u[1] <= u[2] ? 1 : 2); 00314 // Cross returns a Row3 result which is then normalized. 00315 return UnitRow<P,1>(*this % UnitRow<P,1>(minAxis)); 00316 } 00317 00318 00321 template <class P, int S1, int S2> inline bool 00322 operator==(const UnitRow<P,S1>& u1, const UnitRow<P,S2>& u2) 00323 { return u1.asRow3() == u2.asRow3(); } 00324 00328 template <class P, int S1, int S2> inline bool 00329 operator!=(const UnitRow<P,S1>& u1, const UnitRow<P,S2>& u2) 00330 { return !(u1==u2); } 00331 00332 //------------------------------------------------------------------------------ 00333 } // End of namespace SimTK 00334 00335 //-------------------------------------------------------------------------- 00336 #endif // SimTK_UNITVEC_H_ 00337 //-------------------------------------------------------------------------- 00338 00339