00001 //----------------------------------------------------------------------------- 00002 // File: CoordinateAxis.h 00003 // Class: CoordinateAxis 00004 // Parent: None 00005 // Purpose: Converts XAxis, YAxis, ZAxis to 0, 1, 2 - but with the ability 00006 // for the compiler to differentiate the types and method signatures. 00007 //----------------------------------------------------------------------------- 00008 #ifndef SIMTK_COORDINATEAXIS_H 00009 #define SIMTK_COORDINATEAXIS_H 00010 00011 /* -------------------------------------------------------------------------- * 00012 * SimTK Core: SimTK Simmatrix(tm) * 00013 * -------------------------------------------------------------------------- * 00014 * This is part of the SimTK Core biosimulation toolkit originating from * 00015 * Simbios, the NIH National Center for Physics-Based Simulation of * 00016 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00017 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00018 * * 00019 * Portions copyright (c) 2005-7 Stanford University and the Authors. * 00020 * Authors: Michael Sherman and Paul Mitiguy * 00021 * Contributors: * 00022 * * 00023 * Permission is hereby granted, free of charge, to any person obtaining a * 00024 * copy of this software and associated documentation files (the "Software"), * 00025 * to deal in the Software without restriction, including without limitation * 00026 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00027 * and/or sell copies of the Software, and to permit persons to whom the * 00028 * Software is furnished to do so, subject to the following conditions: * 00029 * * 00030 * The above copyright notice and this permission notice shall be included in * 00031 * all copies or substantial portions of the Software. * 00032 * * 00033 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00034 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00035 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00036 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00037 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00038 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00039 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00040 * -------------------------------------------------------------------------- */ 00041 00042 //----------------------------------------------------------------------------- 00043 #include <cassert> 00044 00045 //----------------------------------------------------------------------------- 00046 namespace SimTK { 00047 00048 //----------------------------------------------------------------------------- 00049 // These classes allow the compiler to identify specific arguments as types, i.e., 00050 // XAxis is a specific type of class and allows the compiler to match to a specific method. 00051 // In addition, these classes allow easy conversion of XAxis to 0, YAxis to 1, ZAxis to 2. 00052 //----------------------------------------------------------------------------- 00053 class CoordinateAxis { 00054 public: 00055 // This typecasts CoordinateAxis into an int 00056 operator int() const { return myAxisId; } 00057 00058 // XAxis.getNextAxis() returns YAxis; 00059 // YAxis.getNextAxis() returns ZAxis; 00060 // ZAxis.getNextAxis() returns XAxis; 00061 CoordinateAxis getNextAxis() const { return CoordinateAxis( (myAxisId+1) % 3 ); } 00062 00063 // XAxis.getPreviousAxis() returns ZAxis; 00064 // YAxis.getPreviousAxis() returns XAxis; 00065 // ZAxis.getPreviousAxis() returns YAxis; 00066 CoordinateAxis getPreviousAxis() const { return CoordinateAxis( (myAxisId+2) % 3 ); } 00067 00068 // XAxis.getThirdAxis(YAxis) returns ZAxis; 00069 // XAxis.getThirdAxis(ZAxis) returns YAxis; 00070 // YAxis.getThirdAxis(ZAxis) returns XAxis; 00071 CoordinateAxis getThirdAxis( const CoordinateAxis& axis2 ) const { 00072 assert( isDifferentAxis(axis2) ); 00073 CoordinateAxis nextAxis = getNextAxis(); 00074 return nextAxis.isDifferentAxis(axis2) ? nextAxis : axis2.getNextAxis(); 00075 } 00076 00077 // Compare various axes. 00078 bool isXAxis() const { return myAxisId == 0; } 00079 bool isYAxis() const { return myAxisId == 1; } 00080 bool isZAxis() const { return myAxisId == 2; } 00081 bool isNextAxis( const CoordinateAxis& axis2 ) const { return int(getNextAxis()) == int(axis2); } 00082 bool isPreviousAxis( const CoordinateAxis& axis2 ) const { return int(getPreviousAxis()) == int(axis2); } 00083 bool isSameAxis( const CoordinateAxis& axis2 ) const { return myAxisId == int(axis2); } 00084 bool areAllSameAxes( const CoordinateAxis& axis2, const CoordinateAxis &axis3 ) const { return isSameAxis(axis2) && isSameAxis(axis3); } 00085 bool isDifferentAxis( const CoordinateAxis& axis2 ) const { return myAxisId != int(axis2); } 00086 bool areAllDifferentAxes( const CoordinateAxis& axis2, const CoordinateAxis& axis3 ) const { return isDifferentAxis(axis2) && isDifferentAxis(axis3) && axis2.isDifferentAxis(axis3); } 00087 bool isForwardCyclical( const CoordinateAxis& axis2 ) const { return isNextAxis(axis2); } 00088 bool isReverseCyclical( const CoordinateAxis& axis2 ) const { return isPreviousAxis(axis2); } 00089 00090 // Quasi dot-product and cross-product 00091 int dotProduct( const CoordinateAxis& axis2 ) const { return isSameAxis(axis2) ? 1 : 0; } 00092 int crossProductSign( const CoordinateAxis& axis2 ) const { return isSameAxis(axis2) ? 0 : (isNextAxis(axis2) ? 1 : -1); } 00093 CoordinateAxis crossProductAxis( const CoordinateAxis& axis2 ) const { return isSameAxis(axis2) ? CoordinateAxis(myAxisId) : getThirdAxis(axis2); } 00094 CoordinateAxis crossProduct( const CoordinateAxis& axis2, int& sign ) const { sign = crossProductSign(axis2); return crossProductAxis(axis2); } 00095 00096 // Get the appropriate CoordinateAxis 00097 // Check whether or not an index is in proper range 00098 static CoordinateAxis getCoordinateAxis( int i ) { assertIndexIsInRange(i); return (i==0) ? CoordinateAxis(XTypeAxis()) : ((i==1) ? CoordinateAxis(YTypeAxis()) : CoordinateAxis(ZTypeAxis()) ); } 00099 static bool isIndexInRange( int i ) { return i>=0 && i<=2; } 00100 static void assertIndexIsInRange( int i ) { assert( isIndexInRange(i) ); } 00101 00102 // Forward declarations for subsequent helper classes 00103 class XCoordinateAxis; class YCoordinateAxis; class ZCoordinateAxis; 00104 00105 protected: 00106 // Declaration of very simple classes 00107 class XTypeAxis{}; class YTypeAxis{}; class ZTypeAxis{}; 00108 00109 CoordinateAxis( const XTypeAxis& ) : myAxisId(0) {} 00110 CoordinateAxis( const YTypeAxis& ) : myAxisId(1) {} 00111 CoordinateAxis( const ZTypeAxis& ) : myAxisId(2) {} 00112 private: 00113 explicit CoordinateAxis( int i ) : myAxisId(i) { assertIndexIsInRange(i); } 00114 00115 int myAxisId; 00116 }; 00117 00118 00119 // Helper classes that make it possible to treat an Axis like an integer 00120 class CoordinateAxis::XCoordinateAxis : public CoordinateAxis { 00121 public: XCoordinateAxis() : CoordinateAxis(XTypeAxis()) {} 00122 }; 00123 class CoordinateAxis::YCoordinateAxis : public CoordinateAxis { 00124 public: YCoordinateAxis() : CoordinateAxis(YTypeAxis()) {} 00125 }; 00126 class CoordinateAxis::ZCoordinateAxis : public CoordinateAxis { 00127 public: ZCoordinateAxis() : CoordinateAxis(ZTypeAxis()) {} 00128 }; 00129 00130 00131 // Predefine constants XAxis, YAxis, ZAxis which implicitly convert to integers 0, 1, 2 respectively. 00132 static const CoordinateAxis::XCoordinateAxis XAxis; 00133 static const CoordinateAxis::YCoordinateAxis YAxis; 00134 static const CoordinateAxis::ZCoordinateAxis ZAxis; 00135 00136 00137 //------------------------------------------------------------------------------ 00138 } // End of namespace 00139 00140 //-------------------------------------------------------------------------- 00141 #endif // SIMTK_COORDINATEAXIS_H_ 00142 //-------------------------------------------------------------------------- 00143 00144