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

BaseObjects.cpp

Go to the documentation of this file.
00001 /*
00002  * DataMap.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * Copyright 2004 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  */
00023 
00032 #include "../Include/FlyLegacy.h"
00033 #include "../Include/Utility.h"
00034 #include "../Include/Globals.h"
00035 
00036 #include <map>
00037 using namespace std;
00038 
00039 
00040 //
00041 // CDataMapCoefficient
00042 //
00043 // This CDataLookup implements a simple linear mapping:
00044 //
00045 //  y = a * x;
00046 //
00047 
00048 class CDataMapCoefficient : public CDataLookup {
00049 public:
00050   // Constructors / Destructor
00051   CDataMapCoefficient (float f);
00052 
00053   // CDataLookup methods
00054   float Lookup (float x);
00055   
00056 protected:
00057   float a;        // Linear coefficient
00058 };
00059 
00060 CDataMapCoefficient::CDataMapCoefficient (float f)
00061 {
00062   this->a = f;
00063 }
00064 
00065 float CDataMapCoefficient::Lookup (float x)
00066 {
00067   return x * a;
00068 }
00069 
00070 //
00071 // CDataMapPolynomial
00072 //
00073 // This CDataLookup implements a polynomial mapping up to 9th order:
00074 //
00075 //                              2                 9
00076 //   y = a0 + (a1 * x) + (a2 * x)  + ... + (a9 * x)
00077 //
00078 //
00079 class CDataMapPolynomial : public CStreamObject, public CDataLookup {
00080 public:
00081   // Constructors / Destructor
00082   CDataMapPolynomial (void);
00083 //  CDataMapPolynomial (CDataMapPolynomial *p1,
00084 //                      CDataMapPolynomial *p2,
00085 //                      float scale)
00086 
00087   // CStreamObject methods
00088   int   Read (SStream *stream, Tag tag);
00089 
00090   // CDataLookup methods
00091   float Lookup (float x);
00092   void  Interpolate (CDataMapPolynomial *p1,
00093                      CDataMapPolynomial *p2,
00094                      float scale);
00095 
00096   // CDataMapPolynomial methods
00097   void  SetCoefficient (int i, float f);
00098 
00099 protected:
00100   float coeff[10];     // Polynomial coefficients
00101 };
00102 
00103 CDataMapPolynomial::CDataMapPolynomial (void)
00104 {
00105   int i;
00106   for (i=0; i<10; i++) coeff[i] = 0.0f;
00107 }
00108 
00109 //
00110 // This constructor creates a polynomial with interpolated coefficients
00111 //
00112 void CDataMapPolynomial::Interpolate (CDataMapPolynomial *p1,
00113                                       CDataMapPolynomial *p2,
00114                                       float scale)
00115 {
00116   int i;
00117   for (i=0; i<10; i++) {
00118     float d = p2->coeff[i] - p1->coeff[i];
00119     coeff[i] = p1->coeff[i] + (d * scale);
00120   }
00121 }
00122 
00123 void CDataMapPolynomial::SetCoefficient (int i, float a)
00124 {
00125   if (i < 10) coeff[i] = a;
00126 }
00127 
00128 int CDataMapPolynomial::Read (SStream *stream, Tag tag)
00129 {
00130   int rc = TAG_IGNORED;
00131 
00132   switch (tag) {
00133   case 'coef':
00134     {
00135       // From zero to four coefficients may be present
00136       char s[80];
00137       ReadString (s, 80, stream);
00138 
00139       char *delimiters = " \t";
00140       char *token = strtok (s, delimiters);
00141       int i = 0;
00142       while ((token != NULL) && (i < 10)) {
00143         float f = atof (token);
00144         SetCoefficient (i, f);
00145         token = strtok (NULL, delimiters);
00146         i++;
00147       }
00148     }
00149     rc = TAG_READ;
00150     break;
00151   }
00152 
00153   if (rc == TAG_IGNORED) {
00154     char s[64];
00155     TagToString (s, tag);
00156     globals->logWarning->Write ("CDataMapPolynomial::Read : Unknown tag %s", s);
00157   }
00158 
00159   return rc;
00160 }
00161 
00162 float CDataMapPolynomial::Lookup (float x)
00163 {
00164   float y = coeff[0];
00165   int i;
00166   for (i=1; i<10; i++) {
00167     if (coeff[i] != 0) {
00168       y += coeff[i] * x;
00169     }
00170     x *= x;
00171   }
00172   return y;
00173 }
00174 
00175 
00176 //
00177 // CDataMapTable
00178 //
00179 // The table mapping is the most complex (and flexible) method.  There are two
00180 //   basic subtypes of tables : <fmt1> and <fmt3>
00181 //
00182 // <fmt1> tables use a list of x,y data points to define the mapping curve.
00183 //   Simple linear interpolation between the data points is used for x-values
00184 //   that are not explicitly listed in the table data point list
00185 //
00186 // <fmt3> tables use a list of x-values and list of up to four polynomials
00187 //   that define a cubic polynomial to be applied at that x-value until the
00188 //   next breakpoint.
00189 //
00190 
00191 typedef enum {
00192   TABLE_FORMAT_UNKNOWN,
00193   TABLE_FORMAT_1,
00194   TABLE_FORMAT_3
00195 } ETableFormat;
00196 
00197 typedef struct {
00198   float x;
00199   float y;
00200 } SFmt1Entry;
00201 
00202 class CFmt3Entry {
00203 public:
00204   CFmt3Entry (void);
00205   virtual ~CFmt3Entry (void);
00206 
00207 public:
00208   float               x;
00209   CDataMapPolynomial *poly;
00210 };
00211 
00212 CFmt3Entry::CFmt3Entry (void)
00213 {
00214   x = 0;
00215   poly = new CDataMapPolynomial;
00216 }
00217 
00218 CFmt3Entry::~CFmt3Entry (void)
00219 {
00220   delete poly;
00221 }
00222 
00223 
00224 class CDataMapTable : public CDataLookup, public CStreamObject {
00225 public:
00226   // Constructors
00227   CDataMapTable (void);
00228 
00229   // CStreamObject methods
00230   int   Read (SStream *stream, Tag tag);
00231 
00232   // CDataLookup methods
00233   float     Lookup (float x);
00234 
00235   // CDataMapTable methods
00236   float     LookupFmt1 (float x);
00237   float     LookupFmt3 (float x);
00238 
00239 protected:
00240   ETableFormat                   format;
00241   vector<SFmt1Entry>             fmt1;
00242   vector<CFmt3Entry>             fmt3;
00243 };
00244 
00245 CDataMapTable::CDataMapTable (void)
00246 {
00247   format = TABLE_FORMAT_UNKNOWN;
00248 }
00249 
00250 int CDataMapTable::Read (SStream *stream, Tag tag)
00251 {
00252   char s[256];
00253 
00254   int rc = TAG_IGNORED;
00255 
00256   switch (tag) {
00257   case 'fmt1':
00258     // Format 1 table, simple mapping of x to y values with linear interpolation
00259     format = TABLE_FORMAT_1;
00260     ReadString (s, 256, stream);
00261     while (strstr (s, "<endf>") == NULL) {
00262       // Parse an x y data pair
00263       SFmt1Entry entry;
00264       if (sscanf (s, "%f %f", &entry.x, &entry.y) == 2) {
00265         fmt1.push_back (entry);
00266       } else {
00267         // Generate warning
00268         globals->logWarning->Write ("CDataMapTable : Invalid <fmt1> data %s", s);
00269       }
00270 
00271       // Read next line
00272 //      ReadString (s, 256, stream);
00273     }
00274     rc = TAG_READ;
00275     break;
00276 
00277   case 'fmt3':
00278     // Format 3 table of polynomial expressions
00279     format = TABLE_FORMAT_3;
00280     ReadString (s, 256, stream);
00281     while (strstr (s, "<endf>") == NULL) {
00282       CFmt3Entry entry;
00283       // Parse breakpoint x-value and polynomial coefficients
00284       char *delimiters = " \t";
00285       char *token = strtok (s, delimiters);
00286       entry.x = atof (token);
00287 
00288       token = strtok (NULL, delimiters);
00289       int i = 0;
00290       while ((token != NULL) && (i < 10)) {
00291         float f = atof (token);
00292         entry.poly->SetCoefficient (i, f);
00293         token = strtok (NULL, delimiters);
00294         i++;
00295       }
00296       fmt3.push_back (entry);
00297         // Instantiate new polynomial lookup
00298 //        CDataMapPolynomial *poly = new CDataMapPolynomial;
00299 //        for (int i=1; i<nArgs; i++) {
00300 //          poly->SetCoefficient (i-1, coeff[i-1]);
00301 //        }
00302         // Add coefficient to breakpoint list
00303 //        fmt3[x] = poly;
00304 //      } else {
00305         // Generate warning
00306 //        globals->logWarning->Write ("CDataMapTable : Invalid <fmt3> data %s", s);
00307 //      }
00308 
00309       // Read next line
00310 //      ReadString (s, 256, stream);
00311     }
00312     rc = TAG_READ;
00313     break;
00314   }
00315 
00316   if (rc == TAG_IGNORED) {
00317     char s[64];
00318     TagToString (s, tag);
00319     globals->logWarning->Write ("CDataMapTable::Read : Unknown tag %s", s);
00320   }
00321 
00322   return rc;
00323 }
00324 
00325 float CDataMapTable::LookupFmt1 (float x)
00326 {
00327   float y = 0.0f;
00328 
00329   if (!fmt1.empty()) {
00330 
00331     // Get references to first and last elements
00332     SFmt1Entry &front = fmt1.front();
00333     SFmt1Entry &back = fmt1.back();
00334 
00335     // Check for x-value below minimum breakpoint
00336     if (x <= front.x) {
00337       y = front.y;
00338     } else if (x >= back.x) {
00339       y = back.y;
00340     } else {
00341       // x-value is within table, need to find bracketing entries and iterpolate
00342       float x1, y1, x2, y2;
00343       vector<SFmt1Entry>::iterator i = fmt1.begin();
00344       x1 = 0;
00345       y1 = 0;
00346       x2 = i->x;
00347       y2 = i->y;
00348       i++;
00349       while ((i != fmt1.end()) && (x < x2)) {
00350         // Transfer upper bound to lower bound
00351         x1 = x2;
00352         y1 = y2;
00353 
00354         // Set new upper bound
00355         x2 = i->x;
00356         y2 = i->y;
00357 
00358         // Iterate to next element in the map
00359         i++;
00360       }
00361 
00362       // Interpolate between the two values
00363       float dy = y2 - y1;
00364       float dx = x2 - x1;
00365       y = y1 + (dy * ((x - x1) / dx));
00366     }
00367   }
00368 
00369   return y;
00370 }
00371 
00372 float CDataMapTable::LookupFmt3 (float x)
00373 {
00374   float y = 0.0f;
00375 
00376   // Each table entry in a fmt3 table is a set of up to ten polynomial
00377   //   equation coefficients a0, a1, ... a9.  The mapping function at
00378   //   each breakpoint is defined as:
00379   //     y = a0 + (a1 * x) + (a2 * x^2) + ... + (a9 * x^9)
00380   //
00381   if (!fmt3.empty()) {
00382 
00383     // Get references to first and last elements
00384     CFmt3Entry &front = fmt3.front();
00385     CFmt3Entry &back = fmt3.back();
00386 
00387     if (x <= front.x) {
00388       // Lookup value is less than minimum breakpoint
00389       y = front.poly->Lookup (x);
00390     } else if (x >= back.x) {
00391       // Lookup value is greater than maximum breakpoint
00392       y = back.poly->Lookup (x);
00393     } else {
00394       // x-value is within table, need to find bracketing entries and iterpolate
00395       float x1, x2;
00396       CDataMapPolynomial *poly1, *poly2;
00397       vector<CFmt3Entry>::iterator i = fmt3.begin();
00398       x1 = 0;
00399       poly1 = NULL;
00400       x2 = i->x;
00401       poly2 = i->poly;
00402       i++;
00403       while ((i != fmt3.end()) && (x < x2)) {
00404         // Transfer upper bound to lower bound
00405         x1 = x2;
00406         poly1 = poly2;
00407 
00408         // Set new upper bound
00409         x2 = i->x;
00410         poly2 = i->poly;
00411 
00412         // Iterate to next element in the map
00413         i++;
00414       }
00415 
00416       // Interpolate the polynomials
00417       float dx = x2 - x1;
00418       CDataMapPolynomial poly;
00419       poly.Interpolate (poly1, poly2, (x - x1) / dx);
00420       y = poly.Lookup (x);
00421     }
00422   }
00423 
00424   return y;
00425 }
00426 
00427 float CDataMapTable::Lookup (float x)
00428 {
00429   float y = 0.0f;
00430 
00431   switch (format) {
00432   case TABLE_FORMAT_1:
00433     y = LookupFmt1 (x);
00434     break;
00435   case TABLE_FORMAT_3:
00436     y = LookupFmt3 (x);
00437     break;
00438   default:
00439     // Undefined table format
00440     gtfo ("CDataMapTable::Lookup : Undefined table format : %d", format);
00441   }
00442 
00443   return y;
00444 }
00445 
00446 
00447 //
00448 // CDataMap
00449 //
00450 CDataMap::CDataMap (void)
00451 {
00452   dataSource = NULL;
00453 }
00454 
00455 int CDataMap::Read (SStream *stream, Tag tag)
00456 {
00457   int rc = TAG_IGNORED;
00458 
00459   // Multiple data map specifications can exist; only the last one is used,
00460   //   previous ones are ignored.  If the tag is a valid data map type,
00461   //   and the dataSource pointer has already been set, then we need to
00462   //   delete the old object before instantiating the new one
00463 
00464   switch (tag) {
00465   case 'cof1':
00466   case 'ply1':
00467   case 'tbl1':
00468     // Valid data map type
00469     if (dataSource != NULL) {
00470       // This spec overrides previous one; delete object first
00471       delete dataSource;
00472       dataSource = NULL;
00473     }
00474     break;
00475   }
00476 
00477   // Now instantiate the proper data map specification
00478   switch (tag) {
00479   case 'cof1':
00480     // Simple linear coefficient
00481     float f;
00482     ReadFloat (&f, stream);
00483     dataSource = new CDataMapCoefficient(f);
00484     rc = TAG_READ;
00485     break;
00486 
00487   case 'ply1':
00488     {
00489       // Polynomial a + bx + cx^2 + dx^3
00490       CDataMapPolynomial *poly = new CDataMapPolynomial;
00491       ReadFrom (poly, stream);
00492       dataSource = poly;
00493     }
00494     rc = TAG_READ;
00495     break;
00496 
00497   case 'tbl1':
00498     {
00499       // Data table
00500       CDataMapTable *table = new CDataMapTable;
00501       ReadFrom (table, stream);
00502       dataSource = table;
00503     }
00504     rc = TAG_READ;
00505     break;
00506   }
00507 
00508   if (rc == TAG_IGNORED) {
00509     char s[64];
00510     TagToString (s, tag);
00511     globals->logWarning->Write ("CDataMap::Read : Unknown tag %s", s);
00512   }
00513 
00514   return rc;
00515 }
00516 
00517 float CDataMap::Lookup (float x)
00518 {
00519   float rc = 0.0f;
00520   if (dataSource != NULL) {
00521     rc = dataSource->Lookup(x);
00522   }
00523   return rc;
00524 }
00525 
00526 /*
00527 
00528 
00529   
00530 //
00531 // CTuple is a single entry in a format 1 table, consisting of a simple x,y
00532 //   data pair.
00533 //
00534 
00535 class CTuple {
00536 public:
00537   CTuple (float initX, float initY) : x(initX), y(initY) {}
00538 
00539   //
00540   // Static function to linearly interpolate between two CTuple instances.
00541   //   The tuples must be ordered such that t1.x < t2.x.
00542   //
00543   static float Interpolate (float x, CTuple *t1, CTuple *t2)
00544   {
00545     if (x <= t1->x) return t1->y;
00546     if (x >= t2->x) return t2->y;
00547     float dx = t2->x - t1->x;
00548     return t1->y + ((t2->y - t1->y) * ((x - t1->x) / dx));
00549   }
00550 
00551 public:
00552   float x, y;
00553 };
00554 
00555 
00556 //
00557 // CPolynomial is a single entry in a format 1 table, representing a cubic
00558 //   polynomial of the form y = a0 + (a1 * x) + (a2 * x^2) + (a3 * x^3)
00559 //
00560 
00561 class CPolynomial {
00562 public:
00563   CPolynomial (int n, float initX, float initA0, float initA1, float initA2, float initA3)
00564   {
00565     x = a0 = a1 = a2 = a3 = 0;
00566     x = initX;
00567     if (n > 0) a0 = initA0;
00568     if (n > 1) a1 = initA1;
00569     if (n > 2) a2 = initA2;
00570     if (n > 3) a3 = initA3;
00571   }
00572 
00573   float Evaluate (float x)
00574   {
00575     float x2 = x * x;
00576     return a0 + (a1 * x) + (a2 * x2) + (a3 * x * x2);
00577   }
00578 
00579 public:
00580   float x;
00581   float a0, a1, a2, a3;
00582 };
00583 
00584 
00585 */
SourceForge.net Logo Documentation generated by doxygen