Simbody
3.5
|
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) 00058 { assert(isIndexInRange(i)); } 00059 00061 operator int() const {return m_myAxisId;} 00062 00067 CoordinateAxis getNextAxis() const 00068 { return CoordinateAxis((m_myAxisId+1) % 3); } 00069 00074 CoordinateAxis getPreviousAxis() const 00075 { return CoordinateAxis((m_myAxisId+2) % 3); } 00076 00084 CoordinateAxis getThirdAxis( const CoordinateAxis& axis2 ) const { 00085 assert( isDifferentAxis(axis2) ); 00086 CoordinateAxis nextAxis = getNextAxis(); 00087 return nextAxis.isDifferentAxis(axis2) ? nextAxis : axis2.getNextAxis(); 00088 } 00089 00091 bool isXAxis() const {return m_myAxisId == 0;} 00093 bool isYAxis() const {return m_myAxisId == 1;} 00095 bool isZAxis() const {return m_myAxisId == 2;} 00098 bool isNextAxis( const CoordinateAxis& axis2 ) const 00099 { return int(getNextAxis()) == int(axis2); } 00102 bool isPreviousAxis( const CoordinateAxis& axis2 ) const 00103 { return int(getPreviousAxis()) == int(axis2); } 00106 bool isSameAxis( const CoordinateAxis& axis2 ) const 00107 { return m_myAxisId == int(axis2); } 00109 bool areAllSameAxes( const CoordinateAxis& axis2, 00110 const CoordinateAxis &axis3 ) const 00111 { return isSameAxis(axis2) && isSameAxis(axis3); } 00114 bool isDifferentAxis( const CoordinateAxis& axis2 ) const 00115 { return m_myAxisId != int(axis2); } 00119 bool areAllDifferentAxes( const CoordinateAxis& axis2, 00120 const CoordinateAxis& axis3 ) const 00121 { return isDifferentAxis(axis2) && isDifferentAxis(axis3) 00122 && axis2.isDifferentAxis(axis3); } 00126 bool isForwardCyclical( const CoordinateAxis& axis2 ) const 00127 { return isNextAxis(axis2); } 00131 bool isReverseCyclical( const CoordinateAxis& axis2 ) const 00132 { return isPreviousAxis(axis2); } 00133 00137 int dotProduct( const CoordinateAxis& axis2 ) const 00138 { return isSameAxis(axis2) ? 1 : 0; } 00144 int crossProductSign( const CoordinateAxis& axis2 ) const 00145 { return isSameAxis(axis2) ? 0 : (isNextAxis(axis2) ? 1 : -1); } 00153 CoordinateAxis crossProductAxis( const CoordinateAxis& axis2 ) const 00154 { return isSameAxis(axis2) ? CoordinateAxis(m_myAxisId) 00155 : getThirdAxis(axis2); } 00163 CoordinateAxis crossProduct( const CoordinateAxis& axis2, int& sign ) const 00164 { sign = crossProductSign(axis2); return crossProductAxis(axis2); } 00165 00168 static const CoordinateAxis& getCoordinateAxis( int i ); 00169 00173 static bool isIndexInRange( int i ) { return 0<=i && i<=2; } 00174 00175 // Forward declarations for subsequent helper classes 00176 class XCoordinateAxis; class YCoordinateAxis; class ZCoordinateAxis; 00177 protected: // turn off doxygen here; these aren't for users 00179 class XTypeAxis{}; 00180 class YTypeAxis{}; 00181 class ZTypeAxis{}; 00182 00183 CoordinateAxis( const XTypeAxis& ) : m_myAxisId(0) {} 00184 CoordinateAxis( const YTypeAxis& ) : m_myAxisId(1) {} 00185 CoordinateAxis( const ZTypeAxis& ) : m_myAxisId(2) {} 00187 private: 00188 00189 int m_myAxisId; 00190 }; 00191 00192 00193 // Helper classes that allow compile time recognition of axis directions. 00194 class CoordinateAxis::XCoordinateAxis : public CoordinateAxis { 00195 public: XCoordinateAxis() : CoordinateAxis(XTypeAxis()) {} 00196 }; 00197 class CoordinateAxis::YCoordinateAxis : public CoordinateAxis { 00198 public: YCoordinateAxis() : CoordinateAxis(YTypeAxis()) {} 00199 }; 00200 class CoordinateAxis::ZCoordinateAxis : public CoordinateAxis { 00201 public: ZCoordinateAxis() : CoordinateAxis(ZTypeAxis()) {} 00202 }; 00203 00206 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::XCoordinateAxis XAxis; 00209 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::YCoordinateAxis YAxis; 00212 extern SimTK_SimTKCOMMON_EXPORT const CoordinateAxis::ZCoordinateAxis ZAxis; 00213 00214 inline const CoordinateAxis& CoordinateAxis::getCoordinateAxis(int i) { 00215 assert(isIndexInRange(i)); 00216 return (i==0 ? static_cast<const CoordinateAxis&>(XAxis) 00217 : (i==1 ? static_cast<const CoordinateAxis&>(YAxis) 00218 : static_cast<const CoordinateAxis&>(ZAxis))); 00219 } 00220 00222 inline bool operator==(const CoordinateAxis& a1, const CoordinateAxis& a2) 00223 { return a1.isSameAxis(a2); } 00224 00226 inline bool operator!=(const CoordinateAxis& a1, const CoordinateAxis& a2) 00227 { return a1.isDifferentAxis(a2); } 00228 00229 00244 class CoordinateDirection { 00245 public: 00248 class Negative {}; 00249 00252 CoordinateDirection(const CoordinateAxis& axis) 00253 : m_axis(axis), m_direction(1) {} 00254 00257 CoordinateDirection(const CoordinateAxis& axis, Negative) 00258 : m_axis(axis), m_direction(-1) {} 00259 00267 CoordinateDirection(const CoordinateAxis& axis, int direction) 00268 : m_axis(axis), m_direction(direction) 00269 { assert(direction==1 || direction==-1); } 00270 00274 CoordinateAxis getAxis() const {return m_axis;} 00277 int getDirection() const {return m_direction;} 00278 00281 bool hasSameAxis(const CoordinateDirection& dir2) const 00282 { return m_axis.isSameAxis(dir2.getAxis()); } 00283 00287 bool isSameAxisAndDirection(const CoordinateDirection& dir2) const 00288 { return m_axis==dir2.getAxis() && m_direction==dir2.getDirection(); } 00289 00293 int dotProduct( const CoordinateDirection& dir2 ) const 00294 { if (m_axis != dir2.getAxis()) return 0; 00295 return m_direction == dir2.getDirection() ? 1 : -1; } 00296 00302 int crossProductSign( const CoordinateDirection& dir2 ) const 00303 { if (m_axis == dir2.getAxis()) return 0; 00304 return m_axis.crossProductSign(dir2.getAxis()) 00305 * m_direction * dir2.getDirection(); } 00306 00314 CoordinateAxis crossProductAxis( const CoordinateDirection& dir2 ) const 00315 { return m_axis.crossProductAxis(dir2.getAxis()); } 00316 00324 CoordinateAxis crossProduct( const CoordinateDirection& dir2, 00325 int& sign ) const 00326 { sign = crossProductSign(dir2); return crossProductAxis(dir2); } 00327 00328 // Local class declarations for helper classes. 00329 class NegXDirection; class NegYDirection; class NegZDirection; 00330 private: 00331 CoordinateAxis m_axis; // XAxis, YAxis, or ZAxis 00332 int m_direction; // 1 or -1 00333 }; 00334 00335 00336 // Helper classes that allow compile time recognition of negative axis 00337 // directions. 00338 class CoordinateDirection::NegXDirection : public CoordinateDirection { 00339 public: NegXDirection() : CoordinateDirection(XAxis,Negative()) {} 00340 }; 00341 class CoordinateDirection::NegYDirection : public CoordinateDirection { 00342 public: NegYDirection() : CoordinateDirection(YAxis,Negative()) {} 00343 }; 00344 class CoordinateDirection::NegZDirection : public CoordinateDirection { 00345 public: NegZDirection() : CoordinateDirection(ZAxis,Negative()) {} 00346 }; 00347 00348 // Predefine constants for the negative X,Y,Z directions. 00349 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegXDirection 00350 NegXAxis; 00351 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegYDirection 00352 NegYAxis; 00353 extern SimTK_SimTKCOMMON_EXPORT const CoordinateDirection::NegZDirection 00354 NegZAxis; 00355 00357 inline bool operator==(const CoordinateDirection& d1, 00358 const CoordinateDirection& d2) 00359 { return d1.isSameAxisAndDirection(d2); } 00360 00362 inline bool operator!=(const CoordinateDirection& d1, 00363 const CoordinateDirection& d2) 00364 { return !d1.isSameAxisAndDirection(d2); } 00365 00368 inline const CoordinateDirection::NegXDirection& 00369 operator-(const CoordinateAxis::XCoordinateAxis&){return NegXAxis;} 00372 inline const CoordinateDirection::NegYDirection& 00373 operator-(const CoordinateAxis::YCoordinateAxis&){return NegYAxis;} 00376 inline const CoordinateDirection::NegZDirection& 00377 operator-(const CoordinateAxis::ZCoordinateAxis&){return NegZAxis;} 00378 00381 inline CoordinateDirection 00382 operator-(const CoordinateAxis& axis) 00383 { return CoordinateDirection(axis,CoordinateDirection::Negative()); } 00384 00387 inline CoordinateDirection 00388 operator+(const CoordinateAxis& axis) 00389 { return CoordinateDirection(axis); } 00390 00393 inline const CoordinateAxis::XCoordinateAxis& 00394 operator-(const CoordinateDirection::NegXDirection&){return XAxis;} 00397 inline const CoordinateAxis::YCoordinateAxis& 00398 operator-(const CoordinateDirection::NegYDirection&){return YAxis;} 00401 inline const CoordinateAxis::ZCoordinateAxis& 00402 operator-(const CoordinateDirection::NegZDirection&){return ZAxis;} 00403 00406 inline CoordinateDirection 00407 operator-(const CoordinateDirection& dir) 00408 { return CoordinateDirection(dir.getAxis(), -dir.getDirection()); } 00409 00410 } // End of namespace 00411 00412 #endif // SimTK_SimTKCOMMON_COORDINATE_AXIS_H_ 00413 00414 00415