00001 #include "eAxis.h" 00002 00003 eAxis::eAxis(int number) 00004 { 00005 windings = NULL; 00006 windingAngles = NULL; 00007 Init(number); 00008 } 00009 00010 void eAxis::Init(int number) 00011 { 00012 numberWinding = (number < 1) ? 4 : number; 00013 if (windings) 00014 delete [] windings; 00015 if (windingAngles) 00016 delete [] windingAngles; // [] not really required as we are dealing with floats, not objects. 00017 00018 windings = new eCoord[numberWinding](); 00019 windingAngles = new REAL[numberWinding]; 00020 00021 ComputeWinding(); 00022 SnapWinding(); 00023 ComputeAngles(); 00024 } 00025 00026 void eAxis::Init(int number, eCoord predefinedAxis[], bool normalize) 00027 { 00028 if ( number < 1 || predefinedAxis == NULL) 00029 { 00030 Init(4); 00031 return; 00032 } 00033 00034 numberWinding = number; 00035 if (windings) 00036 delete [] windings; 00037 if (windingAngles) 00038 delete [] windingAngles; // [] not really required as we are dealing with floats, not objects. 00039 00040 windings = new eCoord[numberWinding](); 00041 windingAngles = new REAL[numberWinding]; 00042 00043 for(int i=0; i<number; i++) 00044 { 00045 windings[i] = predefinedAxis[i]; 00046 if (normalize) { 00047 windings[i].Normalize(); 00048 } 00049 } 00050 00051 SnapWinding(); 00052 ComputeAngles(); 00053 } 00054 00055 00056 eAxis::~eAxis() 00057 { 00058 if (windings) 00059 delete [] windings; 00060 if (windingAngles) 00061 delete [] windingAngles; // [] not really required as we are dealing with floats, not objects. 00062 } 00063 00064 void eAxis::Turn(int ¤tWinding, int direction) 00065 { 00066 if (direction > 1) direction = 1; 00067 if (direction < -1) direction = -1; 00068 currentWinding += direction + numberWinding; // + numberWinding to avoid any negative. They dont modulate well! 00069 currentWinding %= numberWinding; 00070 } 00071 00072 void eAxis::TurnRight(int &windingDirection) 00073 { 00074 windingDirection--; 00075 windingDirection += numberWinding; // + numberWinding to fix negative modulos 00076 windingDirection %= numberWinding; 00077 } 00078 00079 void eAxis::TurnLeft(int &windingDirection) 00080 { 00081 windingDirection++; 00082 windingDirection %= numberWinding; 00083 } 00084 00085 /* 00086 * Compute evenly spaced windings 00087 */ 00088 void eAxis::ComputeWinding() 00089 { 00090 unsigned int i; 00091 REAL tetha; 00092 for(i=0; i<numberWinding; i++) 00093 { 00094 tetha = M_PI*2*(numberWinding - i - 1)/numberWinding; 00095 windings[i].x = (cosf(tetha)); 00096 windings[i].y = (sinf(tetha)); 00097 } 00098 } 00099 00100 void eAxis::SnapWinding() 00101 { 00102 unsigned int i; 00103 for(i=0; i<numberWinding; i++) 00104 { 00105 eCoord & winding = windings[i]; 00106 if ( fabs(winding.x) < EPS ) 00107 winding.x = 0; 00108 if ( fabs(winding.y) < EPS ) 00109 winding.y = 0; 00110 } 00111 } 00112 00113 void eAxis::ComputeAngles() 00114 { 00115 unsigned int i; 00116 for(i=0; i<numberWinding; i++) 00117 { 00118 windingAngles[i] = eCoordToRad(windings[i]); 00119 } 00120 } 00121 00122 REAL remf(REAL x, REAL y) { 00123 return x - y*floorf(x/y); 00124 } 00125 00126 REAL angledifff(REAL x, REAL y) { 00127 return fabsf(remf(x - y + M_PI, 2*M_PI) - M_PI); 00128 } 00129 00130 /* 00131 * Given the direction described by (0,0) to pos, return the winding number 00132 * describing the closest axis/direction 00133 * 00134 */ 00135 int eAxis::NearestWinding (eCoord pos) 00136 { 00137 REAL posAngle = eCoordToRad(pos); 00138 00139 REAL closestval = angledifff(windingAngles[0], posAngle); 00140 unsigned int i, closestid = 0; 00141 for(i=1; i<numberWinding; i++) { 00142 REAL diff = angledifff(windingAngles[i], posAngle); 00143 if(diff < closestval) { 00144 closestid = i; 00145 closestval = diff; 00146 } 00147 } 00148 return closestid; 00149 } 00150 00151 eCoord eAxis::GetDirection (int winding) 00152 { 00153 winding %= numberWinding; 00154 return windings[winding]; 00155 }