00001 //----------------------------------------------------------------------------- 00002 // File: UnitVec.h 00003 // Classes: UnitVec and UnitRow 00004 // Parents: Vec and Row 00005 // Purpose: Unit vector class (pure direction - magnitude is always 1.0) 00006 //----------------------------------------------------------------------------- 00007 #ifndef SimTK_UNITVEC_H 00008 #define SimTK_UNITVEC_H 00009 00010 /* -------------------------------------------------------------------------- * 00011 * SimTK Core: SimTK Simmatrix(tm) * 00012 * -------------------------------------------------------------------------- * 00013 * This is part of the SimTK Core biosimulation toolkit originating from * 00014 * Simbios, the NIH National Center for Physics-Based Simulation of * 00015 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00016 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00017 * * 00018 * Portions copyright (c) 2005-7 Stanford University and the Authors. * 00019 * Authors: Michael Sherman * 00020 * Contributors: Paul Mitiguy * 00021 * * 00022 * Permission is hereby granted, free of charge, to any person obtaining a * 00023 * copy of this software and associated documentation files (the "Software"), * 00024 * to deal in the Software without restriction, including without limitation * 00025 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00026 * and/or sell copies of the Software, and to permit persons to whom the * 00027 * Software is furnished to do so, subject to the following conditions: * 00028 * * 00029 * The above copyright notice and this permission notice shall be included in * 00030 * all copies or substantial portions of the Software. * 00031 * * 00032 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00033 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00034 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00035 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00036 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00037 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00038 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00039 * -------------------------------------------------------------------------- */ 00040 00041 //----------------------------------------------------------------------------- 00042 #include "SimTKcommon/SmallMatrix.h" 00043 //----------------------------------------------------------------------------- 00044 #include <iosfwd> // Forward declaration of iostream 00045 //----------------------------------------------------------------------------- 00046 00047 //----------------------------------------------------------------------------- 00048 namespace SimTK { 00049 00050 //----------------------------------------------------------------------------- 00051 // Forward declarations 00052 template <int S> class UnitRow; 00053 00054 00055 //----------------------------------------------------------------------------- 00061 //----------------------------------------------------------------------------- 00062 template <int S> 00063 class UnitVec : public Vec<3,Real,S> { 00064 public: 00065 typedef Vec<3,Real,S> BaseVec; 00066 typedef UnitRow<S> TransposeType; 00067 00068 UnitVec() : BaseVec(NaN) { } 00069 00070 // Copy constructor. 00071 UnitVec(const UnitVec& u) : BaseVec( static_cast<const BaseVec&>(u) ) {} 00072 00073 // Automatic conversion from UnitVec with different stride. 00074 template <int S2> UnitVec(const UnitVec<S2>& u) : BaseVec( static_cast<const typename UnitVec<S2>::BaseVec&>(u) ) {} 00075 00076 // Explicit conversion from Vec to UnitVec, requiring expensive normalization. 00077 explicit UnitVec(const BaseVec& v) : BaseVec(v/v.norm()) {} 00078 template <int S2> explicit UnitVec(const Vec<3,Real,S2>& v) : BaseVec( v/v.norm() ) {} 00079 00080 UnitVec(const Real& x, const Real& y, const Real& z) : BaseVec(x,y,z) { static_cast<BaseVec&>(*this) /= BaseVec::norm(); } 00081 00082 // Create a unit axis vector 100 010 001 00083 explicit UnitVec(int axis) : BaseVec(0) { 00084 assert(0 <= axis && axis <= 2); 00085 BaseVec::operator[](axis) = 1.; 00086 } 00087 00088 UnitVec& operator=(const UnitVec& u) { 00089 BaseVec::operator=(static_cast<const BaseVec&>(u)); 00090 return *this; 00091 } 00092 template <int S2> UnitVec& operator=(const UnitVec<S2>& u) { 00093 BaseVec::operator=(static_cast<const typename UnitVec<S2>::BaseVec&>(u)); 00094 return *this; 00095 } 00096 00097 const BaseVec& asVec3() const {return static_cast<const BaseVec&>(*this);} 00098 00099 // Override Vec3 methods which preserve length. These return the 00100 // packed UnitVec regardless of our stride. 00101 UnitVec<1> negate() const {return UnitVec<1>(-asVec3(),true);} 00102 UnitVec<1> operator-() const {return negate();} 00103 00104 const TransposeType& operator~() const { return *reinterpret_cast<const TransposeType*>(this); } 00105 TransposeType& operator~() { return *reinterpret_cast<TransposeType*>(this); } 00106 00107 // We have to define these here so that the non-const ones won't be 00108 // inherited. We don't trust anyone to write on one element of a UnitVec! 00109 const Real& operator[](int i) const { return BaseVec::operator[](i); } 00110 const Real& operator()(int i) const { return BaseVec::operator()(i); } 00111 00112 // Return a vector whose measure numbers are the absolute values 00113 // of the ones here. This will still have unit length but will be 00114 // a reflection of this unit vector into the first octant (+x,+y,+z). 00115 // Note that we are returning the packed form of UnitVec regardless 00116 // of our stride here. 00117 UnitVec<1> abs() const { return UnitVec<1>( asVec3().abs(), true ); } 00118 00119 // Return a unit vector perpendicular to this one (arbitrary). 00120 inline UnitVec<1> perp() const; 00121 00122 // This constructor is only for our friends whom we trust to 00123 // give us an already-normalized vector. 00124 UnitVec( const BaseVec& v, bool ) : BaseVec(v) { } 00125 template <int S2> UnitVec( const Vec<3,Real,S2>& v, bool ) : BaseVec(v) { } 00126 }; 00127 00128 00129 template <int S> 00130 inline UnitVec<1> UnitVec<S>::perp() const { 00131 // Choose the coordinate axis which makes the largest angle 00132 // with this vector, that is, has the "least u" along it. 00133 const UnitVec<1> u(abs()); // reflect to first octant 00134 const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2) 00135 : (u[1] <= u[2] ? 1 : 2); 00136 // Cross returns a Vec3 result which is then normalized. 00137 return UnitVec<1>( *this % UnitVec<1>(minAxis) ); 00138 } 00139 00140 00141 //----------------------------------------------------------------------------- 00146 //----------------------------------------------------------------------------- 00147 template <int S> 00148 class UnitRow : public Row<3,Real,S> { 00149 public: 00150 typedef Row<3,Real,S> BaseRow; 00151 typedef UnitVec<S> TransposeType; 00152 00153 UnitRow() : BaseRow(NaN) { } 00154 00155 // Copy constructor. 00156 UnitRow(const UnitRow& u) 00157 : BaseRow(static_cast<const BaseRow&>(u)) { } 00158 00159 // Automatic conversion from UnitRow with different stride. 00160 template <int S2> UnitRow(const UnitRow<S2>& u) 00161 : BaseRow(static_cast<const typename UnitRow<S2>::BaseRow&>(u)) { } 00162 00163 // Copy assignment. 00164 UnitRow& operator=(const UnitRow& u) { 00165 BaseRow::operator=(static_cast<const BaseRow&>(u)); 00166 return *this; 00167 } 00168 // Assignment from UnitRow with different stride. 00169 template <int S2> UnitRow& operator=(const UnitRow<S2>& u) { 00170 BaseRow::operator=(static_cast<const typename UnitRow<S2>::BaseRow&>(u)); 00171 return *this; 00172 } 00173 00174 // Explicit conversion from Row to UnitRow, requiring expensive normalization. 00175 explicit UnitRow(const BaseRow& v) : BaseRow(v/v.norm()) { } 00176 template <int S2> explicit UnitRow(const Row<3,Real,S2>& v) 00177 : BaseRow(v/v.norm()) { } 00178 00179 UnitRow(const Real& x, const Real& y, const Real& z) : BaseRow(x,y,z) { 00180 static_cast<BaseRow&>(*this) /= BaseRow::norm(); 00181 } 00182 00183 // Create a unit axis vector 100 010 001 00184 explicit UnitRow(int axis) : BaseRow(0) { 00185 assert(0 <= axis && axis <= 2); 00186 BaseRow::operator[](axis) = 1.; 00187 } 00188 00189 const BaseRow& asRow3() const { return static_cast<const BaseRow&>(*this); } 00190 00191 // Override Row3 methods which preserve length. These return the 00192 // packed UnitRow regardless of our stride. 00193 UnitRow<1> negate() const { return UnitRow<1>(-asRow3(),true); } 00194 UnitRow<1> operator-() const { return negate();} 00195 00196 const TransposeType& operator~() const { return *reinterpret_cast<const TransposeType*>(this); } 00197 TransposeType& operator~() { return *reinterpret_cast<TransposeType*>(this); } 00198 00199 // We have to define these here so that the non-const ones won't be 00200 // inherited. We don't trust anyone to write on one element of a UnitRow! 00201 const Real& operator[](int i) const { return BaseRow::operator[](i); } 00202 const Real& operator()(int i) const { return BaseRow::operator()(i); } 00203 00204 // Return a vector whose measure numbers are the absolute values 00205 // of the ones here. This will still have unit length but will be 00206 // a reflection of this unit vector into the first octant (+x,+y,+z). 00207 // Note that we are returning the packed form of UnitVec regardless 00208 // of our stride here. 00209 UnitRow<1> abs() const { return UnitRow<1>(asRow3().abs(),true); } 00210 00211 // Return a unit row vector perpendicular to this one (arbitrary). 00212 inline UnitRow<1> perp() const; 00213 00214 // This constructor is only for our friends whom we trust to 00215 // give us an already-normalized vector. 00216 UnitRow( const BaseRow& v, bool ) : BaseRow(v) { } 00217 template <int S2> UnitRow( const Row<3,Real,S2>& v, bool ) : BaseRow(v) { } 00218 }; 00219 00220 template <int S> 00221 inline UnitRow<1> UnitRow<S>::perp() const { 00222 // Choose the coordinate axis which makes the largest angle 00223 // with this vector, that is, has the "least u" along it. 00224 const UnitRow<1> u(abs()); // reflect to first octant 00225 const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2) 00226 : (u[1] <= u[2] ? 1 : 2); 00227 // Cross returns a Row3 result which is then normalized. 00228 return UnitRow<1>(*this % UnitRow<1>(minAxis)); 00229 } 00230 00231 00232 // UnitVec3 is more intelligible name for UnitVec<1> now that UnitVec class is defined 00233 typedef UnitVec<1> UnitVec3; 00234 00235 00236 //------------------------------------------------------------------------------ 00237 } // End of namespace SimTK 00238 00239 //-------------------------------------------------------------------------- 00240 #endif // SimTK_UNITVEC_H_ 00241 //-------------------------------------------------------------------------- 00242 00243