Simbody
|
00001 #ifndef SimTK_COORDINATEAXIS_H 00002 #define SimTK_COORDINATEAXIS_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 and Paul Mitiguy * 00014 * Contributors: * 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 <cassert> 00039 00040 namespace SimTK { 00041 00060 class CoordinateAxis { 00061 public: 00064 explicit CoordinateAxis( int i ) : m_myAxisId(i) {assertIndexIsInRange(i);} 00065 00067 operator int() const {return m_myAxisId;} 00068 00073 CoordinateAxis getNextAxis() const 00074 { return CoordinateAxis((m_myAxisId+1) % 3); } 00075 00080 CoordinateAxis getPreviousAxis() const 00081 { return CoordinateAxis((m_myAxisId+2) % 3); } 00082 00090 CoordinateAxis getThirdAxis( const CoordinateAxis& axis2 ) const { 00091 assert( isDifferentAxis(axis2) ); 00092 CoordinateAxis nextAxis = getNextAxis(); 00093 return nextAxis.isDifferentAxis(axis2) ? nextAxis : axis2.getNextAxis(); 00094 } 00095 00097 bool isXAxis() const {return m_myAxisId == 0;} 00099 bool isYAxis() const {return m_myAxisId == 1;} 00101 bool isZAxis() const {return m_myAxisId == 2;} 00104 bool isNextAxis( const CoordinateAxis& axis2 ) const 00105 { return int(getNextAxis()) == int(axis2); } 00108 bool isPreviousAxis( const CoordinateAxis& axis2 ) const 00109 { return int(getPreviousAxis()) == int(axis2); } 00112 bool isSameAxis( const CoordinateAxis& axis2 ) const 00113 { return m_myAxisId == int(axis2); } 00115 bool areAllSameAxes( const CoordinateAxis& axis2, const CoordinateAxis &axis3 ) const 00116 { return isSameAxis(axis2) && isSameAxis(axis3); } 00119 bool isDifferentAxis( const CoordinateAxis& axis2 ) const 00120 { return m_myAxisId != int(axis2); } 00124 bool areAllDifferentAxes( const CoordinateAxis& axis2, const CoordinateAxis& axis3 ) const 00125 { return isDifferentAxis(axis2) && isDifferentAxis(axis3) && axis2.isDifferentAxis(axis3); } 00129 bool isForwardCyclical( const CoordinateAxis& axis2 ) const 00130 { return isNextAxis(axis2); } 00134 bool isReverseCyclical( const CoordinateAxis& axis2 ) const 00135 { return isPreviousAxis(axis2); } 00136 00140 int dotProduct( const CoordinateAxis& axis2 ) const 00141 { return isSameAxis(axis2) ? 1 : 0; } 00147 int crossProductSign( const CoordinateAxis& axis2 ) const 00148 { return isSameAxis(axis2) ? 0 : (isNextAxis(axis2) ? 1 : -1); } 00156 CoordinateAxis crossProductAxis( const CoordinateAxis& axis2 ) const 00157 { return isSameAxis(axis2) ? CoordinateAxis(m_myAxisId) 00158 : getThirdAxis(axis2); } 00165 CoordinateAxis crossProduct( const CoordinateAxis& axis2, int& sign ) const 00166 { sign = crossProductSign(axis2); return crossProductAxis(axis2); } 00167 00170 static const CoordinateAxis& getCoordinateAxis( int i ); 00171 00175 static bool isIndexInRange( int i ) { return 0<=i && i<=2; } 00178 static void assertIndexIsInRange( int i ) { assert( isIndexInRange(i) ); } 00179 00180 // Forward declarations for subsequent helper classes 00181 class XCoordinateAxis; class YCoordinateAxis; class ZCoordinateAxis; 00182 protected: // turn off doxygen here; these aren't for users 00184 class XTypeAxis{}; 00185 class YTypeAxis{}; 00186 class ZTypeAxis{}; 00187 00188 CoordinateAxis( const XTypeAxis& ) : m_myAxisId(0) {} 00189 CoordinateAxis( const YTypeAxis& ) : m_myAxisId(1) {} 00190 CoordinateAxis( const ZTypeAxis& ) : m_myAxisId(2) {} 00192 private: 00193 00194 int m_myAxisId; 00195 }; 00196 00197 00198 // Helper classes that allow compile time recognition of axis directions. 00199 class CoordinateAxis::XCoordinateAxis : public CoordinateAxis { 00200 public: XCoordinateAxis() : CoordinateAxis(XTypeAxis()) {} 00201 }; 00202 class CoordinateAxis::YCoordinateAxis : public CoordinateAxis { 00203 public: YCoordinateAxis() : CoordinateAxis(YTypeAxis()) {} 00204 }; 00205 class CoordinateAxis::ZCoordinateAxis : public CoordinateAxis { 00206 public: ZCoordinateAxis() : CoordinateAxis(ZTypeAxis()) {} 00207 }; 00208 00211 static const CoordinateAxis::XCoordinateAxis XAxis; 00214 static const CoordinateAxis::YCoordinateAxis YAxis; 00217 static const CoordinateAxis::ZCoordinateAxis ZAxis; 00218 00219 inline const CoordinateAxis& CoordinateAxis::getCoordinateAxis(int i) { 00220 assertIndexIsInRange(i); 00221 return (i==0 ? static_cast<const CoordinateAxis&>(XAxis) 00222 : (i==1 ? static_cast<const CoordinateAxis&>(YAxis) 00223 : static_cast<const CoordinateAxis&>(ZAxis))); 00224 } 00225 00227 inline bool operator==(const CoordinateAxis& a1, const CoordinateAxis& a2) 00228 { return a1.isSameAxis(a2); } 00229 00231 inline bool operator!=(const CoordinateAxis& a1, const CoordinateAxis& a2) 00232 { return a1.isDifferentAxis(a2); } 00233 00234 00249 class CoordinateDirection { 00250 public: 00253 class Negative {}; 00254 00257 CoordinateDirection(const CoordinateAxis& axis) 00258 : m_axis(axis), m_direction(1) {} 00259 00262 CoordinateDirection(const CoordinateAxis& axis, Negative) 00263 : m_axis(axis), m_direction(-1) {} 00264 00272 CoordinateDirection(const CoordinateAxis& axis, int direction) 00273 : m_axis(axis), m_direction(direction) 00274 { assert(direction==1 || direction==-1); } 00275 00279 CoordinateAxis getAxis() const {return m_axis;} 00282 int getDirection() const {return m_direction;} 00283 00286 bool hasSameAxis(const CoordinateDirection& dir2) const 00287 { return m_axis.isSameAxis(dir2.getAxis()); } 00288 00292 bool isSameAxisAndDirection(const CoordinateDirection& dir2) const 00293 { return m_axis==dir2.getAxis() && m_direction==dir2.getDirection(); } 00294 00298 int dotProduct( const CoordinateDirection& dir2 ) const 00299 { if (m_axis != dir2.getAxis()) return 0; 00300 return m_direction == dir2.getDirection() ? 1 : -1; } 00301 00307 int crossProductSign( const CoordinateDirection& dir2 ) const 00308 { if (m_axis == dir2.getAxis()) return 0; 00309 return m_axis.crossProductSign(dir2.getAxis()) 00310 * m_direction * dir2.getDirection(); } 00311 00319 CoordinateAxis crossProductAxis( const CoordinateDirection& dir2 ) const 00320 { return m_axis.crossProductAxis(dir2.getAxis()); } 00321 00329 CoordinateAxis crossProduct( const CoordinateDirection& dir2, int& sign ) const 00330 { sign = crossProductSign(dir2); return crossProductAxis(dir2); } 00331 00332 // Local class declarations for helper classes. 00333 class NegXDirection; class NegYDirection; class NegZDirection; 00334 private: 00335 CoordinateAxis m_axis; // XAxis, YAxis, or ZAxis 00336 int m_direction; // 1 or -1 00337 }; 00338 00339 00340 // Helper classes that allow compile time recognition of negative axis 00341 // directions. 00342 class CoordinateDirection::NegXDirection : public CoordinateDirection { 00343 public: NegXDirection() : CoordinateDirection(XAxis,Negative()) {} 00344 }; 00345 class CoordinateDirection::NegYDirection : public CoordinateDirection { 00346 public: NegYDirection() : CoordinateDirection(YAxis,Negative()) {} 00347 }; 00348 class CoordinateDirection::NegZDirection : public CoordinateDirection { 00349 public: NegZDirection() : CoordinateDirection(ZAxis,Negative()) {} 00350 }; 00351 00352 // Predefine constants for the negative X,Y,Z directions. 00353 static const CoordinateDirection::NegXDirection NegXAxis; 00354 static const CoordinateDirection::NegYDirection NegYAxis; 00355 static const CoordinateDirection::NegZDirection NegZAxis; 00356 00358 inline bool operator==(const CoordinateDirection& d1, 00359 const CoordinateDirection& d2) 00360 { return d1.isSameAxisAndDirection(d2); } 00361 00363 inline bool operator!=(const CoordinateDirection& d1, 00364 const CoordinateDirection& d2) 00365 { return !d1.isSameAxisAndDirection(d2); } 00366 00369 inline const CoordinateDirection::NegXDirection& 00370 operator-(const CoordinateAxis::XCoordinateAxis&){return NegXAxis;} 00373 inline const CoordinateDirection::NegYDirection& 00374 operator-(const CoordinateAxis::YCoordinateAxis&){return NegYAxis;} 00377 inline const CoordinateDirection::NegZDirection& 00378 operator-(const CoordinateAxis::ZCoordinateAxis&){return NegZAxis;} 00379 00382 inline CoordinateDirection 00383 operator-(const CoordinateAxis& axis) 00384 { return CoordinateDirection(axis,CoordinateDirection::Negative()); } 00385 00388 inline CoordinateDirection 00389 operator+(const CoordinateAxis& axis) 00390 { return CoordinateDirection(axis); } 00391 00394 inline const CoordinateAxis::XCoordinateAxis& 00395 operator-(const CoordinateDirection::NegXDirection&){return XAxis;} 00398 inline const CoordinateAxis::YCoordinateAxis& 00399 operator-(const CoordinateDirection::NegYDirection&){return YAxis;} 00402 inline const CoordinateAxis::ZCoordinateAxis& 00403 operator-(const CoordinateDirection::NegZDirection&){return ZAxis;} 00404 00407 inline CoordinateDirection 00408 operator-(const CoordinateDirection& dir) 00409 { return CoordinateDirection(dir.getAxis(), -dir.getDirection()); } 00410 00411 } // End of namespace 00412 00413 #endif // SimTK_COORDINATEAXIS_H 00414 00415 00416