40 #include "input_output/FGXMLElement.h" 41 #include "input_output/FGPropertyManager.h" 50 IDENT(IdSrc,
"$Id: FGTable.cpp,v 1.32 2016/05/22 09:08:05 bcoconni Exp $");
51 IDENT(IdHdr,ID_TABLE);
57 FGTable::FGTable(
int NRows) : nRows(NRows), nCols(1), PropertyManager(0)
66 lastRowIndex=lastColumnIndex=2;
71 FGTable::FGTable(
int NRows,
int NCols) : nRows(NRows), nCols(NCols), PropertyManager(0)
80 lastRowIndex=lastColumnIndex=2;
88 colCounter = t.colCounter;
89 rowCounter = t.rowCounter;
90 tableCounter = t.tableCounter;
94 dimension = t.dimension;
95 internal = t.internal;
97 lookupProperty[0] = t.lookupProperty[0];
98 lookupProperty[1] = t.lookupProperty[1];
99 lookupProperty[2] = t.lookupProperty[2];
103 for (
unsigned int r=0; r<=nRows; r++) {
104 for (
unsigned int c=0; c<=nCols; c++) {
105 Data[r][c] = t.Data[r][c];
108 lastRowIndex = t.lastRowIndex;
109 lastColumnIndex = t.lastColumnIndex;
110 lastTableIndex = t.lastTableIndex;
120 string property_string;
129 string operation_types =
"function, product, sum, difference, quotient," 130 "pow, abs, sin, cos, asin, acos, tan, atan, table";
139 if (call_type ==
string(
"internal")) {
141 parent_type = parent_element->
GetName();
142 if (operation_types.find(parent_type) == string::npos) {
146 throw(
" An internal table cannot be nested within another type," 147 " such as a function. The 'internal' keyword is ignored.");
149 }
else if (!call_type.empty()) {
150 throw(
" An unknown table type attribute is listed: " 151 ". Execution cannot continue.");
166 cerr << endl <<
fgred <<
" This table specifies both 'internal' call type" << endl;
167 cerr <<
" and specific lookup properties via the 'independentVar' element." << endl;
168 cerr <<
" These are mutually exclusive specifications. The 'internal'" << endl;
169 cerr <<
" attribute will be ignored." <<
fgdef << endl << endl;
173 for (i=0; i<3; i++) lookupProperty[i] = 0;
175 while (axisElement) {
178 node = PropertyManager->GetNode(property_string);
182 throw(
"IndependentVar property, " + property_string +
" in Table definition is not defined.");
186 if (lookup_axis ==
string(
"row")) {
187 lookupProperty[eRow] = node;
188 }
else if (lookup_axis ==
string(
"column")) {
189 lookupProperty[eColumn] = node;
190 }
else if (lookup_axis ==
string(
"table")) {
191 lookupProperty[eTable] = node;
192 }
else if (!lookup_axis.empty()) {
193 throw(
"Lookup table axis specification not understood: " + lookup_axis);
195 lookupProperty[eRow] = node;
201 }
else if (
internal) {
210 if (FindNumColumns(test_line) == 2) dimension = 1;
211 else if (FindNumColumns(test_line) > 2) dimension = 2;
213 cerr <<
"Invalid number of columns in table" << endl;
219 if (brkpt_string.empty()) {
221 throw(
"No independent variable found for table.");
226 if (brkpt_string.empty()) {
245 lastRowIndex = lastColumnIndex = 2;
253 if (nCols < 2)
throw(
string(
"Not enough columns in table data."));
255 throw(
string(
"Not enough rows in the table data."));
263 lastRowIndex = lastColumnIndex = 2;
273 lastRowIndex = lastColumnIndex = 2;
276 Tables.reserve(nTables);
278 for (i=0; i<nTables; i++) {
279 Tables.push_back(
new FGTable(PropertyManager, tableData));
281 Tables[i]->SetRowIndexProperty(lookupProperty[eRow]);
282 Tables[i]->SetColumnIndexProperty(lookupProperty[eColumn]);
289 cout <<
"No dimension given" << endl;
304 for (b=2; b<=nTables; ++b) {
305 if (Data[b][1] <= Data[b-1][1]) {
306 stringstream errormsg;
308 <<
" FGTable: breakpoint lookup is not monotonically increasing" << endl
309 <<
" in breakpoint " << b;
310 if (nameel != 0) errormsg <<
" of table in " << nameel->
GetAttributeValue(
"name");
311 errormsg <<
":" <<
reset << endl
312 <<
" " << Data[b][1] <<
"<=" << Data[b-1][1] << endl;
313 throw(errormsg.str());
320 for (c=2; c<=nCols; ++c) {
321 if (Data[0][c] <= Data[0][c-1]) {
322 stringstream errormsg;
324 <<
" FGTable: column lookup is not monotonically increasing" << endl
325 <<
" in column " << c;
326 if (nameel != 0) errormsg <<
" of table in " << nameel->
GetAttributeValue(
"name");
327 errormsg <<
":" <<
reset << endl
328 <<
" " << Data[0][c] <<
"<=" << Data[0][c-1] << endl;
329 throw(errormsg.str());
336 for (r=2; r<=nRows; ++r) {
337 if (Data[r][0]<=Data[r-1][0]) {
338 stringstream errormsg;
340 <<
" FGTable: row lookup is not monotonically increasing" << endl
342 if (nameel != 0) errormsg <<
" of table in " << nameel->
GetAttributeValue(
"name");
343 errormsg <<
":" <<
reset << endl
344 <<
" " << Data[r][0] <<
"<=" << Data[r-1][0] << endl;
345 throw(errormsg.str());
352 if (debug_lvl & 1) Print();
357 double** FGTable::Allocate(
void)
359 Data =
new double*[nRows+1];
360 for (
unsigned int r=0; r<=nRows; r++) {
361 Data[r] =
new double[nCols+1];
362 for (
unsigned int c=0; c<=nCols; c++) {
374 for (
unsigned int i=0; i<nTables; i++)
delete Tables[i];
377 for (
unsigned int r=0; r<=nRows; r++)
delete[] Data[r];
385 unsigned int FGTable::FindNumColumns(
const string& test_line)
389 unsigned int nCols=0;
390 while ((position = test_line.find_first_not_of(
" \t", position)) != string::npos) {
392 position = test_line.find_first_of(
" \t", position);
399 double FGTable::GetValue(
void)
const 406 temp = lookupProperty[eRow]->getDoubleValue();
407 temp2 = GetValue(temp);
410 return GetValue(lookupProperty[eRow]->getDoubleValue(),
411 lookupProperty[eColumn]->getDoubleValue());
413 return GetValue(lookupProperty[eRow]->getDoubleValue(),
414 lookupProperty[eColumn]->getDoubleValue(),
415 lookupProperty[eTable]->getDoubleValue());
417 cerr <<
"Attempted to GetValue() for invalid/unknown table type" << endl;
418 throw(
string(
"Attempted to GetValue() for invalid/unknown table type"));
424 double FGTable::GetValue(
double key)
const 426 double Factor, Value, Span;
427 unsigned int r = lastRowIndex;
431 if( key <= Data[1][0] ) {
435 }
else if ( key >= Data[nRows][0] ) {
438 return Data[nRows][1];
446 while (r > 2 && Data[r-1][0] > key) { r--; }
447 while (r < nRows && Data[r][0] < key) { r++; }
452 Span = Data[r][0] - Data[r-1][0];
454 Factor = (key - Data[r-1][0]) / Span;
455 if (Factor > 1.0) Factor = 1.0;
460 Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1];
467 double FGTable::GetValue(
double rowKey,
double colKey)
const 469 double rFactor, cFactor, col1temp, col2temp, Value;
470 unsigned int r = lastRowIndex;
471 unsigned int c = lastColumnIndex;
473 while(r > 2 && Data[r-1][0] > rowKey) { r--; }
474 while(r < nRows && Data[r] [0] < rowKey) { r++; }
476 while(c > 2 && Data[0][c-1] > colKey) { c--; }
477 while(c < nCols && Data[0][c] < colKey) { c++; }
482 rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]);
483 cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]);
485 if (rFactor > 1.0) rFactor = 1.0;
486 else if (rFactor < 0.0) rFactor = 0.0;
488 if (cFactor > 1.0) cFactor = 1.0;
489 else if (cFactor < 0.0) cFactor = 0.0;
491 col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1];
492 col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c];
494 Value = col1temp + cFactor*(col2temp - col1temp);
501 double FGTable::GetValue(
double rowKey,
double colKey,
double tableKey)
const 503 double Factor, Value, Span;
504 unsigned int r = lastRowIndex;
509 if( tableKey <= Data[1][1] ) {
511 return Tables[0]->GetValue(rowKey, colKey);
512 }
else if ( tableKey >= Data[nRows][1] ) {
514 return Tables[nRows-1]->GetValue(rowKey, colKey);
522 while(r > 2 && Data[r-1][1] > tableKey) { r--; }
523 while(r < nRows && Data[r] [1] < tableKey) { r++; }
528 Span = Data[r][1] - Data[r-1][1];
530 Factor = (tableKey - Data[r-1][1]) / Span;
531 if (Factor > 1.0) Factor = 1.0;
536 Value = Factor*(Tables[r-1]->GetValue(rowKey, colKey) - Tables[r-2]->GetValue(rowKey, colKey))
537 + Tables[r-2]->GetValue(rowKey, colKey);
550 if (Type == tt1D) startRow = 1;
552 for (
unsigned int r=startRow; r<=nRows; r++) {
553 for (
unsigned int c=startCol; c<=nCols; c++) {
554 if (r != 0 || c != 0) {
555 in_stream >> Data[r][c];
567 Data[rowCounter][colCounter] = n;
568 if (colCounter == (
int)nCols) {
587 void FGTable::Print(
void)
592 if (Type == tt1D || Type == tt3D) startRow = 1;
593 if (Type == tt3D) startCol = 1;
595 #if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740) 596 unsigned long flags = cout.setf(ios::fixed);
598 ios::fmtflags flags = cout.setf(ios::fixed);
603 cout <<
" 1 dimensional table with " << nRows <<
" rows." << endl;
606 cout <<
" 2 dimensional table with " << nRows <<
" rows, " << nCols <<
" columns." << endl;
609 cout <<
" 3 dimensional table with " << nRows <<
" rows, " 610 << nCols <<
" columns " 611 << nTables <<
" tables." << endl;
615 for (
unsigned int r=startRow; r<=nRows; r++) {
617 for (
unsigned int c=startCol; c<=nCols; c++) {
618 if (r == 0 && c == 0) {
621 cout << Data[r][c] <<
" ";
624 Tables[r-1]->Print();
635 void FGTable::bind(
void)
637 typedef double (
FGTable::*PMF)(void)
const;
638 if ( !Name.empty() && !
internal) {
640 PropertyManager->
Tie( tmp,
this, (PMF)&FGTable::GetValue);
662 void FGTable::Debug(
int from)
664 if (debug_lvl <= 0)
return;
671 if (debug_lvl & 2 ) {
672 if (from == 0) cout <<
"Instantiated: FGTable" << endl;
673 if (from == 1) cout <<
"Destroyed: FGTable" << endl;
675 if (debug_lvl & 4 ) {
677 if (debug_lvl & 8 ) {
679 if (debug_lvl & 16) {
681 if (debug_lvl & 64) {
683 cout << IdSrc << endl;
684 cout << IdHdr << endl;
Element * GetParent(void)
Returns a pointer to the parent of an element.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
std::string mkPropertyName(std::string name, bool lowercase)
Property-ify a name replaces spaces with '-' and, optionally, makes name all lower case...
Class wrapper for property handling.
static char reset[5]
resets text properties
Element * FindElement(const std::string &el="")
Searches for a specified element.
void operator<<(std::istream &)
Read the table in.
unsigned int GetNumDataLines(void)
Returns the number of lines of data stored.
static char fgred[6]
red text
FGTable(const FGTable &table)
This is the very important copy constructor.
void Tie(const std::string &name, bool *pointer, bool useDefault=true)
Tie a property to an external bool variable.
static char fgdef[6]
default text
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
const std::string & GetName(void) const
Retrieves the element name.
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
unsigned int GetNumElements(void)
Returns the number of child elements for this element.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
static char highint[5]
highlights text