Simbody
3.4 (development)
|
00001 #ifndef SimTK_SimTKCOMMON_COORDINATE_AXIS_H_ 00002 #define SimTK_SimTKCOMMON_COORDINATE_AXIS_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: * 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/internal/common.h" 00031 #include <cassert> 00032 00033 namespace SimTK { 00034 00053 class CoordinateAxis { 00054 public: 00057 explicit CoordinateAxis( int i ) : m_myAxisId(i) {assertIndexIsInRange(i);} 00058 00060 operator int() const {return m_myAxisId;} 00061 00066 CoordinateAxis getNextAxis() const 00067 { return CoordinateAxis((m_myAxisId+1) % 3); } 00068 00073 CoordinateAxis getPreviousAxis() const 00074 { return CoordinateAxis((m_myAxisId+2) % 3); } 00075 00083 CoordinateAxis getThirdAxis( const CoordinateAxis& axis2 ) const { 00084 assert( isDifferentAxis(axis2) ); 00085 CoordinateAxis nextAxis = getNextAxis(); 00086 return nextAxis.isDifferentAxis(axis2) ? nextAxis : axis2.getNextAxis(); 00087 } 00088 00090 bool isXAxis() const {return m_myAxisId == 0;} 00092 bool isYAxis() const {return m_myAxisId == 1;} 00094 bool isZAxis() const {return m_myAxisId == 2;} 00097 bool isNextAxis( const CoordinateAxis& axis2 ) const 00098 { return int(getNextAxis()) == int(axis2); } 00101 bool isPreviousAxis( const CoordinateAxis& axis2 ) const 00102 { return int(getPreviousAxis()) == int(axis2); } 00105 bool isSameAxis( const CoordinateAxis& axis2 ) const 00106 { return m_myAxisId == int(axis2); } 00108 bool areAllSameAxes( const CoordinateAxis& axis2, 00109 const CoordinateAxis &axis3 ) const 00110 { return isSameAxis(axis2) && isSameAxis(axis3); } 00113 bool isDifferentAxis( const CoordinateAxis& axis2 ) const 00114 { return m_myAxisId != int(axis2); } 00118 bool areAllDifferentAxes( const CoordinateAxis& axis2, 00119 const CoordinateAxis& axis3 ) const 00120 { return isDifferentAxis(axis2) && isDifferentAxis(axis3) 00121 && axis2.isDifferentAxis(axis3); } 00125 bool isForwardCyclical( const CoordinateAxis& axis2 ) const 00126 { return isNextAxis(axis2); } 00130 bool isReverseCyclical( const CoordinateAxis& axis2 ) const 00131 { return isPreviousAxis(axis2); } 00132 00136 int dotProduct( const CoordinateAxis& axis2 ) const 00137 { return isSameAxis(axis2) ? 1 : 0; } 00143 int crossProductSign( const CoordinateAxis& axis2 ) const 00144 { return isSameAxis(axis2) ? 0 : (isNextAxis(axis2) ? 1 : -1); } 00152 CoordinateAxis crossProductAxis( const CoordinateAxis& axis2 ) const 00153 { return isSameAxis(axis2) ? CoordinateAxis(m_myAxisId) 00154 : getThirdAxis(axis2); } 00162 CoordinateAxis crossProduct( const CoordinateAxis& axis2, int& sign ) const 00163 { sign = crossProductSign(axis2); return crossProductAxis(axis2); } 00164 00167 static const CoordinateAxis& getCoordinateAxis( int i ); 00168 00172 static bool isIndexInRange( int i ) { return 0<=i && i<=2; } 00175 static void assertIndexIsInRange( int i ) { assert( isIndexInRange(i) ); } 00176 00177 // Forward declarations for subsequent helper classes 00178 class XCoordinateAxis; class YCoordinateAxis; class ZCoordinateAxis; 00179 protected: // turn off doxygen here; these aren't for users 00181 class XTypeAxis{}; 00182 class YTypeAxis{}; 00183 class ZTypeAxis{}; 00184 00185 CoordinateAxis( const XTypeAxis& ) : m_myAxisId(0) {} 00186 CoordinateAxis( const YTypeAxis& ) : m_myAxisId(1) {} 00187 CoordinateAxis( const ZTypeAxis& ) : m_myAxisId(2) {} 00189 private: 00190 00191 int m_myAxisId; 00192 }; 00193 00194 00195 // Helper classes that allow compile time recognition of axis directions. 00196 class CoordinateAxis::XCoordinateAxis : public CoordinateAxis { 00197 public: XCoordinateAxis() : CoordinateAxis(XTypeAxis()) {} 00198 }; 00199 class CoordinateAxis::YCoordinateAxis : public CoordinateAxis { 00200 public: YCoordinateAxis() : CoordinateAxis(YTypeAxis()) {} 00201 }; 00202 class CoordinateAxis::ZCoordinateAxis : public CoordinateAxis { 00203 public: ZCoordinateAxis() : CoordinateAxis(ZTypeAxis()) {} 00204 }; 00205 00208 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::XCoordinateAxis XAxis; 00211 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::YCoordinateAxis YAxis; 00214 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::ZCoordinateAxis ZAxis; 00215 00216 inline const CoordinateAxis& CoordinateAxis::getCoordinateAxis(int i) { 00217 assertIndexIsInRange(i); 00218 return (i==0 ? static_cast<const CoordinateAxis&>(XAxis) 00219 : (i==1 ? static_cast<const CoordinateAxis&>(YAxis) 00220 : static_cast<const CoordinateAxis&>(ZAxis))); 00221 } 00222 00224 inline bool operator==(const CoordinateAxis& a1, const CoordinateAxis& a2) 00225 { return a1.isSameAxis(a2); } 00226 00228 inline bool operator!=(const CoordinateAxis& a1, const CoordinateAxis& a2) 00229 { return a1.isDifferentAxis(a2); } 00230 00231 00246 class CoordinateDirection { 00247 public: 00250 class Negative {}; 00251 00254 CoordinateDirection(const CoordinateAxis& axis) 00255 : m_axis(axis), m_direction(1) {} 00256 00259 CoordinateDirection(const CoordinateAxis& axis, Negative) 00260 : m_axis(axis), m_direction(-1) {} 00261 00269 CoordinateDirection(const CoordinateAxis& axis, int direction) 00270 : m_axis(axis), m_direction(direction) 00271 { assert(direction==1 || direction==-1); } 00272 00276 CoordinateAxis getAxis() const {return m_axis;} 00279 int getDirection() const {return m_direction;} 00280 00283 bool hasSameAxis(const CoordinateDirection& dir2) const 00284 { return m_axis.isSameAxis(dir2.getAxis()); } 00285 00289 bool isSameAxisAndDirection(const CoordinateDirection& dir2) const 00290 { return m_axis==dir2.getAxis() && m_direction==dir2.getDirection(); } 00291 00295 int dotProduct( const CoordinateDirection& dir2 ) const 00296 { if (m_axis != dir2.getAxis()) return 0; 00297 return m_direction == dir2.getDirection() ? 1 : -1; } 00298 00304 int crossProductSign( const CoordinateDirection& dir2 ) const 00305 { if (m_axis == dir2.getAxis()) return 0; 00306 return m_axis.crossProductSign(dir2.getAxis()) 00307 * m_direction * dir2.getDirection(); } 00308 00316 CoordinateAxis crossProductAxis( const CoordinateDirection& dir2 ) const 00317 { return m_axis.crossProductAxis(dir2.getAxis()); } 00318 00326 CoordinateAxis crossProduct( const CoordinateDirection& dir2, 00327 int& sign ) const 00328 { sign = crossProductSign(dir2); return crossProductAxis(dir2); } 00329 00330 // Local class declarations for helper classes. 00331 class NegXDirection; class NegYDirection; class NegZDirection; 00332 private: 00333 CoordinateAxis m_axis; // XAxis, YAxis, or ZAxis 00334 int m_direction; // 1 or -1 00335 }; 00336 00337 00338 // Helper classes that allow compile time recognition of negative axis 00339 // directions. 00340 class CoordinateDirection::NegXDirection : public CoordinateDirection { 00341 public: NegXDirection() : CoordinateDirection(XAxis,Negative()) {} 00342 }; 00343 class CoordinateDirection::NegYDirection : public CoordinateDirection { 00344 public: NegYDirection() : CoordinateDirection(YAxis,Negative()) {} 00345 }; 00346 class CoordinateDirection::NegZDirection : public CoordinateDirection { 00347 public: NegZDirection() : CoordinateDirection(ZAxis,Negative()) {} 00348 }; 00349 00350 // Predefine constants for the negative X,Y,Z directions. 00351 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegXDirection 00352 NegXAxis; 00353 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegYDirection 00354 NegYAxis; 00355 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegZDirection 00356 NegZAxis; 00357 00359 inline bool operator==(const CoordinateDirection& d1, 00360 const CoordinateDirection& d2) 00361 { return d1.isSameAxisAndDirection(d2); } 00362 00364 inline bool operator!=(const CoordinateDirection& d1, 00365 const CoordinateDirection& d2) 00366 { return !d1.isSameAxisAndDirection(d2); } 00367 00370 inline const CoordinateDirection::NegXDirection& 00371 operator-(const CoordinateAxis::XCoordinateAxis&){return NegXAxis;} 00374 inline const CoordinateDirection::NegYDirection& 00375 operator-(const CoordinateAxis::YCoordinateAxis&){return NegYAxis;} 00378 inline const CoordinateDirection::NegZDirection& 00379 operator-(const CoordinateAxis::ZCoordinateAxis&){return NegZAxis;} 00380 00383 inline CoordinateDirection 00384 operator-(const CoordinateAxis& axis) 00385 { return CoordinateDirection(axis,CoordinateDirection::Negative()); } 00386 00389 inline CoordinateDirection 00390 operator+(const CoordinateAxis& axis) 00391 { return CoordinateDirection(axis); } 00392 00395 inline const CoordinateAxis::XCoordinateAxis& 00396 operator-(const CoordinateDirection::NegXDirection&){return XAxis;} 00399 inline const CoordinateAxis::YCoordinateAxis& 00400 operator-(const CoordinateDirection::NegYDirection&){return YAxis;} 00403 inline const CoordinateAxis::ZCoordinateAxis& 00404 operator-(const CoordinateDirection::NegZDirection&){return ZAxis;} 00405 00408 inline CoordinateDirection 00409 operator-(const CoordinateDirection& dir) 00410 { return CoordinateDirection(dir.getAxis(), -dir.getDirection()); } 00411 00412 } // End of namespace 00413 00414 #endif // SimTK_SimTKCOMMON_COORDINATE_AXIS_H_ 00415 00416 00417