]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/FGTable.cpp
Make yasim accept the launchbar and hook properties. They are not tied to anything...
[flightgear.git] / src / FDM / JSBSim / FGTable.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Module:       FGTable.cpp
4  Author:       Jon S. Berndt
5  Date started: 1/9/2001
6  Purpose:      Models a lookup table
7
8  ------------- Copyright (C) 2001  Jon S. Berndt (jsb@hal-pc.org) -------------
9
10  This program is free software; you can redistribute it and/or modify it under
11  the terms of the GNU General Public License as published by the Free Software
12  Foundation; either version 2 of the License, or (at your option) any later
13  version.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
18  details.
19
20  You should have received a copy of the GNU General Public License along with
21  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
22  Place - Suite 330, Boston, MA  02111-1307, USA.
23
24  Further information about the GNU General Public License can also be found on
25  the world wide web at http://www.gnu.org.
26
27 FUNCTIONAL DESCRIPTION
28 --------------------------------------------------------------------------------
29 Models a lookup table
30
31 HISTORY
32 --------------------------------------------------------------------------------
33 JSB  1/9/00          Created
34
35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
36 INCLUDES
37 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
38
39 #include "FGTable.h"
40
41 #if defined ( sgi ) && !defined( __GNUC__ ) && (_COMPILER_VERSION < 740)
42 #include <iomanip.h>
43 #else
44 #include <iomanip>
45 #endif
46
47 using namespace std;
48
49 namespace JSBSim {
50
51 static const char *IdSrc = "$Id$";
52 static const char *IdHdr = ID_TABLE;
53
54 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
55 CLASS IMPLEMENTATION
56 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
57
58
59 FGTable::FGTable(int NRows, int NCols, int NTables)
60                                  : nRows(NTables), nCols(1), nTables(NTables)
61 {
62   Type = tt3D;
63   colCounter = 1;
64   rowCounter = 1;
65
66   Data = Allocate(); // this data array will contain the keys for the associated tables
67   Tables.reserve(nTables);
68   for (int i=0; i<nTables; i++) Tables.push_back(FGTable(NRows, NCols));
69
70   Debug(0);
71 }
72
73 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
74
75 FGTable::FGTable(int NRows, int NCols) : nRows(NRows), nCols(NCols)
76 {
77   if (NCols > 1) {
78     Type = tt2D;
79     colCounter = 1;
80     rowCounter = 0;
81   } else if (NCols == 1) {
82     Type = tt1D;
83     colCounter = 0;
84     rowCounter = 1;
85   } else {
86     cerr << "FGTable cannot accept 'Rows=0'" << endl;
87   }
88
89   Data = Allocate();
90   lastRowIndex=lastColumnIndex=2;
91   Debug(0);
92 }
93
94 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95
96 FGTable::FGTable(int NRows) : nRows(NRows), nCols(1)
97 {
98   Type = tt1D;
99   colCounter = 0;
100   rowCounter = 1;
101
102   Data = Allocate();
103   Debug(0);
104   lastRowIndex=lastColumnIndex=2;
105 }
106
107 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
108
109 FGTable::FGTable(const FGTable& t)
110 {
111   Type = t.Type;
112   colCounter = t.colCounter;
113   rowCounter = t.rowCounter;
114   tableCounter = t.tableCounter;
115
116   nRows = t.nRows;
117   nCols = t.nCols;
118   nTables = t.nTables;
119
120   Tables = t.Tables;
121   Data = Allocate();
122   for (int r=0; r<=nRows; r++) {
123     for (int c=0; c<=nCols; c++) {
124       Data[r][c] = t.Data[r][c];
125     }
126   }
127   lastRowIndex = t.lastRowIndex;
128   lastColumnIndex = t.lastColumnIndex;
129   lastTableIndex = t.lastTableIndex;
130 }
131
132 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
133
134 double** FGTable::Allocate(void)
135 {
136   Data = new double*[nRows+1];
137   for (int r=0; r<=nRows; r++) {
138     Data[r] = new double[nCols+1];
139     for (int c=0; c<=nCols; c++) {
140       Data[r][c] = 0.0;
141     }
142   }
143   return Data;
144 }
145
146 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
147
148 FGTable::~FGTable()
149 {
150   if (nTables > 0) Tables.clear();
151   for (int r=0; r<=nRows; r++) if (Data[r]) delete[] Data[r];
152   if (Data) delete[] Data;
153   Debug(1);
154 }
155
156 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
157
158 double FGTable::GetValue(double key)
159 {
160   double Factor, Value, Span;
161   int r=lastRowIndex;
162
163   //if the key is off the end of the table, just return the
164   //end-of-table value, do not extrapolate
165   if( key <= Data[1][0] ) {
166     lastRowIndex=2;
167     //cout << "Key underneath table: " << key << endl;
168     return Data[1][1];
169   } else if ( key >= Data[nRows][0] ) {
170     lastRowIndex=nRows;
171     //cout << "Key over table: " << key << endl;
172     return Data[nRows][1];
173   }
174
175   // the key is somewhere in the middle, search for the right breakpoint
176   // assume the correct breakpoint has not changed since last frame or
177   // has only changed very little
178
179   if ( r > 2 && Data[r-1][0] > key ) {
180     while( Data[r-1][0] > key && r > 2) { r--; }
181   } else if ( Data[r][0] < key ) {
182     while( Data[r][0] <= key && r <= nRows) { r++; }
183   }
184
185   lastRowIndex=r;
186   // make sure denominator below does not go to zero.
187
188   Span = Data[r][0] - Data[r-1][0];
189   if (Span != 0.0) {
190     Factor = (key - Data[r-1][0]) / Span;
191     if (Factor > 1.0) Factor = 1.0;
192   } else {
193     Factor = 1.0;
194   }
195
196   Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1];
197
198   return Value;
199 }
200
201 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
202
203
204 double FGTable::GetValue(double rowKey, double colKey)
205 {
206   double rFactor, cFactor, col1temp, col2temp, Value;
207   int r=lastRowIndex;
208   int c=lastColumnIndex;
209
210   if ( r > 2 && Data[r-1][0] > rowKey ) {
211     while ( Data[r-1][0] > rowKey && r > 2) { r--; }
212   } else if ( Data[r][0] < rowKey ) {
213 //    cout << Data[r][0] << endl;
214     while ( r <= nRows && Data[r][0] <= rowKey ) { r++; }
215     if ( r > nRows ) r = nRows;
216   }
217
218   if ( c > 2 && Data[0][c-1] > colKey ) {
219     while( Data[0][c-1] > colKey && c > 2) { c--; }
220   } else if ( Data[0][c] < colKey ) {
221     while( Data[0][c] <= colKey && c <= nCols) { c++; }
222     if ( c > nCols ) c = nCols;
223   }
224
225   lastRowIndex=r;
226   lastColumnIndex=c;
227
228   rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]);
229   cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]);
230
231   if (rFactor > 1.0) rFactor = 1.0;
232   else if (rFactor < 0.0) rFactor = 0.0;
233
234   if (cFactor > 1.0) cFactor = 1.0;
235   else if (cFactor < 0.0) cFactor = 0.0;
236
237   col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1];
238   col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c];
239
240   Value = col1temp + cFactor*(col2temp - col1temp);
241
242   return Value;
243 }
244
245 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246
247 double FGTable::GetValue(double rowKey, double colKey, double tableKey)
248 {
249   double Factor, Value, Span;
250   int r=lastRowIndex;
251
252   //if the key is off the end  (or before the beginning) of the table,
253   // just return the boundary-table value, do not extrapolate
254
255   if( tableKey <= Data[1][1] ) {
256     lastRowIndex=2;
257     return Tables[0].GetValue(rowKey, colKey);
258   } else if ( tableKey >= Data[nRows][1] ) {
259     lastRowIndex=nRows;
260     return Tables[nRows-1].GetValue(rowKey, colKey);
261   }
262
263   // the key is somewhere in the middle, search for the right breakpoint
264   // assume the correct breakpoint has not changed since last frame or
265   // has only changed very little
266
267   if ( r > 2 && Data[r-1][1] > tableKey ) {
268     while( Data[r-1][1] > tableKey && r > 2) { r--; }
269   } else if ( Data[r][1] < tableKey ) {
270     while( Data[r][1] <= tableKey && r <= nRows) { r++; }
271   }
272
273   lastRowIndex=r;
274   // make sure denominator below does not go to zero.
275
276   Span = Data[r][1] - Data[r-1][1];
277   if (Span != 0.0) {
278     Factor = (tableKey - Data[r-1][1]) / Span;
279     if (Factor > 1.0) Factor = 1.0;
280   } else {
281     Factor = 1.0;
282   }
283
284   Value = Factor*(Tables[r-1].GetValue(rowKey, colKey) - Tables[r-2].GetValue(rowKey, colKey))
285                               + Tables[r-1].GetValue(rowKey, colKey);
286
287   return Value;
288 }
289
290 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291
292 void FGTable::operator<<(FGConfigFile& infile)
293 {
294   int startRow=0;
295   int startCol=0;
296   int tableCtr=0;
297
298   if (Type == tt1D || Type == tt3D) startRow = 1;
299   if (Type == tt3D) startCol = 1;
300
301   for (int r=startRow; r<=nRows; r++) {
302     for (int c=startCol; c<=nCols; c++) {
303       if (r != 0 || c != 0) {
304         infile >> Data[r][c];
305         if (Type == tt3D) {
306           Tables[tableCtr] << infile;
307           tableCtr++;
308         }
309       }
310     }
311   }
312 }
313
314 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
315
316 FGTable& FGTable::operator<<(const double n)
317 {
318   Data[rowCounter][colCounter] = n;
319   if (colCounter == nCols) {
320     colCounter = 0;
321     rowCounter++;
322   } else {
323     colCounter++;
324   }
325   return *this;
326 }
327
328 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
329
330 FGTable& FGTable::operator<<(const int n)
331 {
332   *this << (double)n;
333   return *this;
334 }
335
336 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
337
338 void FGTable::Print(void)
339 {
340   int startRow=0;
341   int startCol=0;
342
343   if (Type == tt1D || Type == tt3D) startRow = 1;
344   if (Type == tt3D) startCol = 1;
345
346 #if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
347   unsigned long flags = cout.setf(ios::fixed);
348 #else
349   ios::fmtflags flags = cout.setf(ios::fixed); // set up output stream
350 #endif
351
352   cout.precision(4);
353   for (int r=startRow; r<=nRows; r++) {
354     cout << "   ";
355     for (int c=startCol; c<=nCols; c++) {
356       if (r == 0 && c == 0) {
357         cout << "       ";
358       } else {
359         cout << Data[r][c] << " ";
360         if (Type == tt3D) {
361           cout << endl;
362           Tables[r-1].Print();
363         }
364       }
365     }
366     cout << endl;
367   }
368   cout.setf(flags); // reset
369 }
370
371 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 //    The bitmasked value choices are as follows:
373 //    unset: In this case (the default) JSBSim would only print
374 //       out the normally expected messages, essentially echoing
375 //       the config files as they are read. If the environment
376 //       variable is not set, debug_lvl is set to 1 internally
377 //    0: This requests JSBSim not to output any messages
378 //       whatsoever.
379 //    1: This value explicity requests the normal JSBSim
380 //       startup messages
381 //    2: This value asks for a message to be printed out when
382 //       a class is instantiated
383 //    4: When this value is set, a message is displayed when a
384 //       FGModel object executes its Run() method
385 //    8: When this value is set, various runtime state variables
386 //       are printed out periodically
387 //    16: When set various parameters are sanity checked and
388 //       a message is printed out when they go out of bounds
389
390 void FGTable::Debug(int from)
391 {
392   if (debug_lvl <= 0) return;
393
394   if (debug_lvl & 1) { // Standard console startup message output
395     if (from == 0) { // Constructor
396
397     }
398   }
399   if (debug_lvl & 2 ) { // Instantiation/Destruction notification
400     if (from == 0) cout << "Instantiated: FGTable" << endl;
401     if (from == 1) cout << "Destroyed:    FGTable" << endl;
402   }
403   if (debug_lvl & 4 ) { // Run() method entry print for FGModel-derived objects
404   }
405   if (debug_lvl & 8 ) { // Runtime state variables
406   }
407   if (debug_lvl & 16) { // Sanity checking
408   }
409   if (debug_lvl & 64) {
410     if (from == 0) { // Constructor
411       cout << IdSrc << endl;
412       cout << IdHdr << endl;
413     }
414   }
415 }
416 }