Simbody  3.5
CoordinateAxis.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines