Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Math.cpp

Go to the documentation of this file.
00001 /*
00002  * Math.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2003 Chris Wallace
00007  *
00008  * Fly! Legacy is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  * Fly! Legacy is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  *   along with Fly! Legacy; if not, write to the Free Software
00020  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  */
00022 
00027 #include "../Include/Utility.h"
00028 
00029 //
00030 // Wrap a float value to the range [0, 2 * PI), typically used to normalize
00031 //   an angle in radians
00032 //
00033 double WrapTwoPi (double rad) {
00034   while (rad < 0)
00035     rad += (SG_PI * 2);
00036   while (rad > (SG_PI * 2))
00037     rad -= (SG_PI * 2);
00038 
00039   return rad;
00040 }
00041 
00042 
00043 //
00044 // Wrap a float value to the range [0, PI), typically used to normalize
00045 //   an angle in radians
00046 //
00047 double WrapPi (double rad) {
00048   while (rad < 0)
00049     rad += SG_PI;
00050   while (rad > SG_PI)
00051     rad -= SG_PI;
00052 
00053   return rad;
00054 }
00055 
00056 
00057 //
00058 // Wrap a float value to the range [0, 360), typically used to normalize
00059 //   an angle in degrees
00060 //
00061 double Wrap360 (double deg)
00062 {
00063   while (deg < 0)
00064     deg += 360;
00065   while (deg >= 360)
00066     deg -= 360;
00067 
00068   return deg;
00069 }
00070 
00071 //
00072 // Wrap an integer value to the range [0, 360), typically used to normalize
00073 //   an angle in degrees
00074 //
00075 int Wrap360 (int deg)
00076 {
00077   while (deg < 0)
00078     deg += 360;
00079   while (deg >= 360)
00080     deg -= 360;
00081 
00082   return deg;
00083 }
00084 
00085 //
00086 // Wrap a float value to the range [-180, 180), typically used to normalize
00087 //   an angle in degrees
00088 //
00089 double Wrap180 (double deg)
00090 {
00091   // First wrap 0..360
00092   deg = Wrap360 (deg);
00093 
00094   if (deg > 180) {
00095     // Negate
00096     deg -= 360;
00097   }
00098 
00099   return deg;
00100 }
00101 
00102 //
00103 // Wrap a float value to the range [0, 24), typically used to normalize
00104 //   a value representing hours of the day
00105 //
00106 float Wrap24 (float hrs)
00107 {
00108   while (hrs < 0.0f)
00109     hrs += 24.0f;
00110   while (hrs >= 24.0f)
00111     hrs -= 24.0f;
00112 
00113   return hrs;
00114 }
00115 
00116 //
00117 // Wrap a float value to the range [0, 60), typically used to normalize
00118 //   a value representing minutes in an hour or seconds in a minute
00119 //
00120 float Wrap60 (float min)
00121 {
00122   while (min < 0.0f)
00123     min += 60.0f;
00124   while (min >= 60.0f)
00125     min -= 60.0f;
00126 
00127   return min;
00128 }
00129 
00130 
00131 
00132 Tag StringToTag (const char* s)
00133 {
00134   Tag tag = 0;
00135   
00136   tag = (s[0] << 24)
00137     + (s[1] << 16)
00138     + (s[2] << 8)
00139     + (s[3]);
00140   return tag;
00141 }
00142 
00143 char *TagString (char* s, Tag tag)
00144 {
00145   TagToString (s, tag);
00146   return s;
00147 }
00148 
00149 void TagToString (char* s, Tag tag)
00150 {
00151   s[0] = (char)((tag >> 24) & 0xff);
00152   s[1] = (char)((tag >> 16) & 0xff);
00153   s[2] = (char)((tag >> 8) & 0xff);
00154   s[3] = (char)((tag) & 0xff);
00155   s[4] = '\0';
00156 }
00157 
00158 
00159 double WrapArcsec (double arcsec)
00160 {
00161   double rc = arcsec;
00162 
00163   static const double WrapValue = (360 * 3600);
00164 
00165   while (rc < 0) rc += WrapValue;
00166   while (rc > WrapValue) rc -= WrapValue;
00167 
00168   return rc;
00169 }
00170 
00171 
00172 //
00173 // Calculate the number of feet in one arcsecond of longitude at the given latitude.
00174 //
00175 // Arguments:
00176 //    lat     Latitude in arcseconds (+ is N hemisphere)
00177 //
00178 double FeetPerLonArcsec (double lat)
00179 {
00180   double latRad = DegToRad (lat / 3600.0);
00181   double circumference = cos(latRad) * MEAN_CIRCUMFERENCE;
00182   double feetPerLonArcsec = circumference / (360.0 * 3600.0);
00183 
00184   return feetPerLonArcsec;
00185 }
00186 
00187 //
00188 // Calculate a new position based on a starting point and a vector offset in feet:
00189 //   v.x = E/W offset      (+ is East)
00190 //   v.y = N/S offset      (+ is North)
00191 //   v.z = Altitude offset (+ is higher)
00192 //
00193 // This function is only accurate for small vector offsets (a few miles)
00194 //
00195 SPosition AddVector(SPosition &from, SVector &v)
00196 {
00197   SPosition to;
00198 
00199   // Calculate arcseconds of latitude offset based on constants defined above
00200   double arcsecLat = v.y / FEET_PER_LAT_ARCSEC;
00201   to.lat = from.lat + arcsecLat;
00202 
00203   // Calculate actual number of feet per longitude arcsec at this latitude
00204   double feetPerLonArcsec = FeetPerLonArcsec (from.lat);
00205   double arcsecLon = v.x / feetPerLonArcsec;
00206   to.lon = WrapArcsec (from.lon + arcsecLon);
00207 
00208   // Altitude is already in feet, simply add the offset
00209   to.alt = from.alt + v.z;
00210 
00211   return to;
00212 }
00213 
00214 //
00215 // SubtractVector computes a new global position based on a starting position
00216 //   and an offset vector.  This is essentially the same as AddVector except
00217 //   the distances are inverted (i.e. an argument to AddVector of +20 feet
00218 //   is equivalent to the same argument to SubtractVector of -20 feet).
00219 //
00220 SPosition SubtractVector(SPosition &from, SVector &v)
00221 {
00222   SVector vNew;
00223   vNew.x = -v.x;
00224   vNew.y = -v.y;
00225   vNew.z = -v.z;
00226   return AddVector (from, vNew);
00227 }
00228 
00229 //
00230 // SubtractPosition computes the vector offset between two globe positions.
00231 //   See "AddVector" for details on the result.
00232 //
00233 SVector SubtractPosition(SPosition &from, SPosition &to)
00234 {
00235   SVector v;
00236 
00237   // Calculate number of arcseconds difference in latitude
00238   double arcsecLat = to.lat - from.lat;
00239   v.z = arcsecLat * FEET_PER_LAT_ARCSEC;
00240 
00241   // Calculate arcsecond difference in longitude
00242   double arcsecLon = WrapArcsec(to.lon - from.lon);
00243   v.x = arcsecLon * FeetPerLonArcsec (from.lat);
00244 
00245   // Altitude is already in feet, simply subtract
00246   v.y = to.alt - from.alt;
00247 
00248   return v;
00249 }
00250 
00251 
00252 //
00253 // Unit conversion functions
00254 //
00255 
00256 float NmToMi (float nm)
00257 {
00258   return (nm / MILES_PER_NM);
00259 }
00260 
00261 float MiToNm (float mi)
00262 {
00263   return (mi * MILES_PER_NM);
00264 }
00265 
00266 float FeetToNm (float feet)
00267 {
00268   return feet / FEET_PER_NM;
00269 }
00270 
00271 float NmToFeet (float nm)
00272 {
00273   return nm * FEET_PER_NM;
00274 }
00275 
00276 float FpsToKt (float fps)
00277 {
00278   return FeetToNm (fps * 3600);
00279 }
00280 
00281 
00282 // Metric conversions
00283 
00284 double FeetToMetres (double ft)
00285 {
00286   return (ft * METRES_PER_FOOT);
00287 }
00288 
00289 double MetresToFeet (double m)
00290 {
00291   return (m / METRES_PER_FOOT);
00292 }
00293 
00294 float KmToNm (float km)
00295 {
00296   return (km * KM_PER_NM);
00297 }
00298 
00299 float NmToKm (float nm)
00300 {
00301   return (nm / KM_PER_NM);
00302 }
00303 
00304 
00305 
00306 // Trigonometric conversions
00307 
00308 float RadToDeg (float rad)
00309 {
00310   return rad * 180 / PI;
00311 }
00312 
00313 double RadToDeg (double rad)
00314 {
00315   return rad * 180 / PI;
00316 }
00317 
00318 float DegToRad (float deg)
00319 {
00320   return deg * PI / 180;
00321 }
00322 
00323 double DegToRad (double deg)
00324 {
00325   return deg * PI / 180;
00326 }
00327 
00328 
00329 //
00330 // Simple vector sum
00331 //
00332 SVector VectorSum (SVector v1, SVector v2)
00333 {
00334   SVector rc;
00335   rc.x = v1.x + v2.x;
00336   rc.y = v1.y + v2.y;
00337   rc.z = v1.z + v2.z;
00338   return rc;
00339 }
00340 
00341 
00342 //
00343 // Simple vector subtraction
00344 //
00345 SVector VectorDifference (SVector v1, SVector v2)
00346 {
00347   SVector rc;
00348   rc.x = v1.x - v2.x;
00349   rc.y = v1.y - v2.y;
00350   rc.z = v1.z - v2.z;
00351   return rc;
00352 }
00353 
SourceForge.net Logo Documentation generated by doxygen