00001
00002
00003
00004
00005
00006
00007 #ifndef SimTK_UNITVEC_H
00008 #define SimTK_UNITVEC_H
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include "SimTKcommon/SmallMatrix.h"
00043
00044 #include <iosfwd>
00045
00046
00047
00048 namespace SimTK {
00049
00050
00051
00052
00053 template <class P, int S> class UnitVec;
00054 template <class P, int S> class UnitRow;
00055
00056
00057 typedef UnitVec<Real,1> UnitVec3;
00058
00059
00060
00066
00067 template <class P, int S>
00068 class UnitVec : public Vec<3,P,S> {
00069 typedef P RealP;
00070 public:
00071 typedef Vec<3,P,S> BaseVec;
00072 typedef UnitRow<P,S> TransposeType;
00073
00076 UnitVec() : BaseVec(NTraits<P>::getNaN()) {}
00077
00080 UnitVec(const UnitVec& u)
00081 : BaseVec( static_cast<const BaseVec&>(u) ) {}
00082
00085 template <int S2> UnitVec(const UnitVec<P,S2>& u)
00086 : BaseVec( static_cast<const typename UnitVec<P,S2>::BaseVec&>(u) ) {}
00087
00089 explicit UnitVec(const BaseVec& v) : BaseVec(v/v.norm()) {}
00092 template <int S2>
00093 explicit UnitVec(const Vec<3,P,S2>& v) : BaseVec(v/v.norm()) {}
00094
00098 UnitVec(const RealP& x, const RealP& y, const RealP& z) : BaseVec(x,y,z)
00099 { static_cast<BaseVec&>(*this) /= BaseVec::norm(); }
00100
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
00121
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
00138
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 };
00171
00172
00173 template <class P, int S> inline UnitVec<P,1>
00174 UnitVec<P,S>::perp() const {
00175
00176
00177 const UnitVec<P,1> u(abs());
00178 const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2)
00179 : (u[1] <= u[2] ? 1 : 2);
00180
00181 return UnitVec<P,1>( *this % UnitVec<P,1>(minAxis) );
00182 }
00183
00184
00185
00190
00191 template <class P, int S>
00192 class UnitRow : public Row<3,P,S> {
00193 typedef P RealP;
00194 public:
00195 typedef Row<3,P,S> BaseRow;
00196 typedef UnitVec<P,S> TransposeType;
00197
00198 UnitRow() : BaseRow(NTraits<P>::getNaN()) { }
00199
00201 UnitRow(const UnitRow& u)
00202 : BaseRow(static_cast<const BaseRow&>(u)) {}
00203
00206 template <int S2> UnitRow(const UnitRow<P,S2>& u)
00207 : BaseRow(static_cast<const typename UnitRow<P,S2>::BaseRow&>(u)) { }
00208
00210 UnitRow& operator=(const UnitRow& u)
00211 { BaseRow::operator=(static_cast<const BaseRow&>(u));
00212 return *this; }
00213
00215 template <int S2> UnitRow& operator=(const UnitRow<P,S2>& u)
00216 { BaseRow::operator=(static_cast<const typename UnitRow<P,S2>::BaseRow&>(u));
00217 return *this; }
00218
00220 explicit UnitRow(const BaseRow& v) : BaseRow(v/v.norm()) {}
00223 template <int S2>
00224 explicit UnitRow(const Row<3,P,S2>& v) : BaseRow(v/v.norm()) {}
00225
00228 UnitRow(const RealP& x, const RealP& y, const RealP& z)
00229 : BaseRow(x,y,z)
00230 { static_cast<BaseRow&>(*this) /= BaseRow::norm(); }
00231
00233 explicit UnitRow(int axis) : BaseRow(0)
00234 { assert(0 <= axis && axis <= 2);
00235 BaseRow::operator[](axis) = 1; }
00236
00238 const BaseRow& asRow3() const {return static_cast<const BaseRow&>(*this);}
00239
00240
00241
00242
00245 UnitRow<P,1> negate() const { return UnitRow<P,1>(-asRow3(),true); }
00248 UnitRow<P,1> operator-() const { return negate();}
00249
00252 const TransposeType& operator~() const {return *reinterpret_cast<const TransposeType*>(this);}
00255 TransposeType& operator~() {return *reinterpret_cast<TransposeType*>(this);}
00256
00257
00258
00259
00263 const RealP& operator[](int i) const { return BaseRow::operator[](i); }
00267 const RealP& operator()(int i) const { return BaseRow::operator()(i); }
00268
00274 UnitRow<P,1> abs() const {return UnitRow<P,1>(asRow3().abs(),true);}
00275
00279 inline UnitRow<P,1> perp() const;
00280
00281
00282
00283 UnitRow( const BaseRow& v, bool ) : BaseRow(v) { }
00284 template <int S2> UnitRow( const Row<3,P,S2>& v, bool ) : BaseRow(v) { }
00285 };
00286
00287 template <class P, int S>
00288 inline UnitRow<P,1> UnitRow<P,S>::perp() const {
00289
00290
00291 const UnitRow<P,1> u(abs());
00292 const int minAxis = u[0] <= u[1] ? (u[0] <= u[2] ? 0 : 2)
00293 : (u[1] <= u[2] ? 1 : 2);
00294
00295 return UnitRow<P,1>(*this % UnitRow<P,1>(minAxis));
00296 }
00297
00298
00299
00300
00301 }
00302
00303
00304 #endif // SimTK_UNITVEC_H_
00305
00306
00307