53 : nRows(NRows), nCols(1), PropertyManager(nullptr)
62 lastRowIndex=lastColumnIndex=2;
68 : nRows(NRows), nCols(NCols), PropertyManager(nullptr)
77 lastRowIndex=lastColumnIndex=2;
85 colCounter = t.colCounter;
86 rowCounter = t.rowCounter;
87 tableCounter = t.tableCounter;
91 dimension = t.dimension;
92 internal = t.internal;
94 lookupProperty[0] = t.lookupProperty[0];
95 lookupProperty[1] = t.lookupProperty[1];
96 lookupProperty[2] = t.lookupProperty[2];
100 for (
unsigned int r=0; r<=nRows; r++) {
101 for (
unsigned int c=0; c<=nCols; c++) {
102 Data[r][c] = t.Data[r][c];
105 lastRowIndex = t.lastRowIndex;
106 lastColumnIndex = t.lastColumnIndex;
107 lastTableIndex = t.lastTableIndex;
116 unsigned int nCols=0;
117 while ((position = test_line.find_first_not_of(
" \t", position)) != string::npos) {
119 position = test_line.find_first_of(
" \t", position);
127 const std::string& Prefix)
128 : PropertyManager(propMan)
135 string operation_types =
"function, product, sum, difference, quotient,"
136 "pow, abs, sin, cos, asin, acos, tan, atan, table";
145 if (call_type ==
string(
"internal")) {
147 string parent_type = parent_element->
GetName();
148 if (operation_types.find(parent_type) == string::npos) {
153 <<
" An internal table cannot be nested within another type,"
154 <<
" such as a function. The 'internal' keyword of table "
155 << Name <<
"is ignored." << endl;
157 }
else if (!call_type.empty()) {
158 std::cerr << el->ReadFrom()
159 <<
" An unknown table type attribute is listed: " << call_type
161 throw BaseException(
"Unknown table type.");
177 <<
fgred <<
" This table specifies both 'internal' call type" << endl
178 <<
" and specific lookup properties via the 'independentVar' element." << endl
179 <<
" These are mutually exclusive specifications. The 'internal'" << endl
180 <<
" attribute will be ignored." <<
fgdef << endl << endl;
184 while (axisElement) {
185 string property_string = axisElement->GetDataLine();
186 if (property_string.find(
"#") != string::npos) {
188 property_string =
replace(property_string,
"#",Prefix);
194 string lookup_axis = axisElement->GetAttributeValue(
"lookup");
195 if (lookup_axis ==
string(
"row")) {
196 lookupProperty[eRow] = node;
197 }
else if (lookup_axis ==
string(
"column")) {
198 lookupProperty[eColumn] = node;
199 }
else if (lookup_axis ==
string(
"table")) {
200 lookupProperty[eTable] = node;
201 }
else if (!lookup_axis.empty()) {
202 throw BaseException(
"Lookup table axis specification not understood: " + lookup_axis);
204 lookupProperty[eRow] = node;
210 }
else if (internal) {
223 <<
"Invalid number of columns in table" << endl;
229 if (brkpt_string.empty()) {
233 <<
"No independentVars found, and table is not marked as internal,"
234 <<
" nor is it a 3D table." << endl;
235 throw BaseException(
"No independent variable found for table.");
240 if (brkpt_string.empty()) {
241 tableData = el->FindElement(
"tableData");
249 if (line.find_first_not_of(
"0123456789.-+eE \t\n") != string::npos) {
250 cerr <<
" In file " << tableData->
GetFileName() << endl
251 <<
" Illegal character found in line "
252 << tableData->
GetLineNumber() +
i + 1 <<
": " << endl << line << endl;
267 lastRowIndex = lastColumnIndex = 2;
277 <<
"Not enough columns in table data" << endl;
282 <<
"Not enough rows in table data" << endl;
291 lastRowIndex = lastColumnIndex = 2;
301 lastRowIndex = lastColumnIndex = 2;
304 Tables.reserve(nTables);
306 for (
i=0;
i<nTables;
i++) {
307 Tables.push_back(
new FGTable(PropertyManager, tableData));
309 Tables[
i]->lookupProperty[eRow] = lookupProperty[eRow];
310 Tables[
i]->lookupProperty[eColumn] = lookupProperty[eColumn];
317 cout <<
"No dimension given" << endl;
332 for (b=2; b<=nTables; ++b) {
333 if (Data[b][1] <= Data[b-1][1]) {
336 <<
" FGTable: breakpoint lookup is not monotonically increasing" << endl
337 <<
" in breakpoint " << b;
338 if (nameel != 0) std::cerr <<
" of table in " << nameel->
GetAttributeValue(
"name");
339 std::cerr <<
":" <<
reset << endl
340 <<
" " << Data[b][1] <<
"<=" << Data[b-1][1] << endl;
341 throw BaseException(
"Breakpoint lookup is not monotonically increasing");
348 for (c=2; c<=nCols; ++c) {
349 if (Data[0][c] <= Data[0][c-1]) {
352 <<
" FGTable: column lookup is not monotonically increasing" << endl
353 <<
" in column " << c;
354 if (nameel != 0) std::cerr <<
" of table in " << nameel->
GetAttributeValue(
"name");
355 std::cerr <<
":" <<
reset << endl
356 <<
" " << Data[0][c] <<
"<=" << Data[0][c-1] << endl;
357 throw BaseException(
"FGTable: column lookup is not monotonically increasing");
364 for (r=2; r<=nRows; ++r) {
365 if (Data[r][0]<=Data[r-1][0]) {
368 <<
" FGTable: row lookup is not monotonically increasing" << endl
370 if (nameel != 0) std::cerr <<
" of table in " << nameel->
GetAttributeValue(
"name");
371 std::cerr <<
":" <<
reset << endl
372 <<
" " << Data[r][0] <<
"<=" << Data[r-1][0] << endl;
373 throw BaseException(
"FGTable: row lookup is not monotonically increasing");
385double** FGTable::Allocate(
void)
387 Data =
new double*[nRows+1];
388 for (
unsigned int r=0; r<=nRows; r++) {
389 Data[r] =
new double[nCols+1];
390 for (
unsigned int c=0; c<=nCols; c++) {
403 if (!Name.empty() && !internal) {
404 string tmp = PropertyManager->mkPropertyName(Name,
false);
406 if (node && node->isTied())
407 PropertyManager->Untie(node);
411 for (
unsigned int i=0;
i<nTables;
i++)
delete Tables[
i];
414 for (
unsigned int r=0; r<=nRows; r++)
delete[] Data[r];
429 assert(lookupProperty[eRow]);
430 temp = lookupProperty[eRow]->getDoubleValue();
434 assert(lookupProperty[eRow]);
435 assert(lookupProperty[eColumn]);
439 assert(lookupProperty[eRow]);
440 assert(lookupProperty[eColumn]);
441 assert(lookupProperty[eTable]);
446 cerr <<
"Attempted to GetValue() for invalid/unknown table type" << endl;
447 throw(
string(
"Attempted to GetValue() for invalid/unknown table type"));
455 double Factor, Value, Span;
456 unsigned int r = lastRowIndex;
460 if( key <= Data[1][0] ) {
464 }
else if ( key >= Data[nRows][0] ) {
467 return Data[nRows][1];
475 while (r > 2 && Data[r-1][0] > key) { r--; }
476 while (r < nRows && Data[r][0] < key) { r++; }
481 Span = Data[r][0] - Data[r-1][0];
483 Factor = (key - Data[r-1][0]) / Span;
484 if (Factor > 1.0) Factor = 1.0;
489 Value = Factor*(Data[r][1] - Data[r-1][1]) + Data[r-1][1];
498 double rFactor, cFactor, col1temp, col2temp, Value;
499 unsigned int r = lastRowIndex;
500 unsigned int c = lastColumnIndex;
502 while(r > 2 && Data[r-1][0] > rowKey) { r--; }
503 while(r < nRows && Data[r] [0] < rowKey) { r++; }
505 while(c > 2 && Data[0][c-1] > colKey) { c--; }
506 while(c < nCols && Data[0][c] < colKey) { c++; }
511 rFactor = (rowKey - Data[r-1][0]) / (Data[r][0] - Data[r-1][0]);
512 cFactor = (colKey - Data[0][c-1]) / (Data[0][c] - Data[0][c-1]);
514 if (rFactor > 1.0) rFactor = 1.0;
515 else if (rFactor < 0.0) rFactor = 0.0;
517 if (cFactor > 1.0) cFactor = 1.0;
518 else if (cFactor < 0.0) cFactor = 0.0;
520 col1temp = rFactor*(Data[r][c-1] - Data[r-1][c-1]) + Data[r-1][c-1];
521 col2temp = rFactor*(Data[r][c] - Data[r-1][c]) + Data[r-1][c];
523 Value = col1temp + cFactor*(col2temp - col1temp);
532 double Factor, Value, Span;
533 unsigned int r = lastRowIndex;
538 if( tableKey <= Data[1][1] ) {
540 return Tables[0]->GetValue(rowKey, colKey);
541 }
else if ( tableKey >= Data[nRows][1] ) {
543 return Tables[nRows-1]->GetValue(rowKey, colKey);
551 while(r > 2 && Data[r-1][1] > tableKey) { r--; }
552 while(r < nRows && Data[r] [1] < tableKey) { r++; }
557 Span = Data[r][1] - Data[r-1][1];
559 Factor = (tableKey - Data[r-1][1]) / Span;
560 if (Factor > 1.0) Factor = 1.0;
565 Value = Factor*(Tables[r-1]->GetValue(rowKey, colKey) - Tables[r-2]->
GetValue(rowKey, colKey))
566 + Tables[r-2]->GetValue(rowKey, colKey);
579 if (Type == tt1D) startRow = 1;
581 for (
unsigned int r=startRow; r<=nRows; r++) {
582 for (
unsigned int c=startCol; c<=nCols; c++) {
583 if (r != 0 || c != 0) {
584 in_stream >> Data[r][c];
596 Data[rowCounter][colCounter] = n;
597 if (colCounter == (
int)nCols) {
621 if (Type == tt1D || Type == tt3D) startRow = 1;
622 if (Type == tt3D) startCol = 1;
624#if defined (sgi) && !defined(__GNUC__) && (_COMPILER_VERSION < 740)
625 unsigned long flags = cout.setf(ios::fixed);
627 ios::fmtflags flags = cout.setf(ios::fixed);
632 cout <<
" 1 dimensional table with " << nRows <<
" rows." << endl;
635 cout <<
" 2 dimensional table with " << nRows <<
" rows, " << nCols <<
" columns." << endl;
638 cout <<
" 3 dimensional table with " << nRows <<
" rows, "
639 << nCols <<
" columns "
640 << nTables <<
" tables." << endl;
644 for (
unsigned int r=startRow; r<=nRows; r++) {
646 for (
unsigned int c=startCol; c<=nCols; c++) {
647 if (r == 0 && c == 0) {
650 cout << Data[r][c] <<
" ";
653 Tables[r-1]->Print();
664void FGTable::bind(
Element* el,
const string& Prefix)
666 typedef double (
FGTable::*PMF)(void)
const;
668 if ( !Name.empty() && !internal) {
669 if (!Prefix.empty()) {
671 if (Name.find(
"#") != string::npos) {
672 Name =
replace(Name,
"#", Prefix);
675 <<
"Malformed table name with number: " << Prefix
676 <<
" and property name: " << Name
677 <<
" but no \"#\" sign for substitution." << endl;
680 Name = Prefix +
"/" + Name;
683 string tmp = PropertyManager->mkPropertyName(Name,
false);
685 if (PropertyManager->HasNode(tmp)) {
686 FGPropertyNode* _property = PropertyManager->GetNode(tmp);
687 if (_property->isTied()) {
689 <<
"Property " << tmp <<
" has already been successfully bound (late)." << endl;
690 throw(
"Failed to bind the property to an existing already tied node.");
716void FGTable::Debug(
int from)
726 if (from == 0) cout <<
"Instantiated: FGTable" << endl;
727 if (from == 1) cout <<
"Destroyed: FGTable" << endl;
const std::string & GetName(void) const
Retrieves the element name.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
unsigned int GetNumDataLines(void)
Returns the number of lines of data stored.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
int GetLineNumber(void) const
Returns the line number at which the element has been defined.
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
Element * GetParent(void)
Returns a pointer to the parent of an element.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
unsigned int GetNumElements(void)
Returns the number of child elements for this element.
Element * FindElement(const std::string &el="")
Searches for a specified element.
const std::string & GetFileName(void) const
Returns the name of the file in which the element has been read.
Element * FindNextElement(const std::string &el="")
Searches for the next element as specified.
static char fgdef[6]
default text
static char highint[5]
highlights text
static char reset[5]
resets text properties
static char fgred[6]
red text
double getDoubleValue(void) const
Class wrapper for property handling.
FGPropertyNode * GetNode(const std::string &path, bool create=false)
Get a property node.
Represents a property value which can use late binding.
double GetValue(void) const
void operator<<(std::istream &)
Read the table in.
FGTable(const FGTable &table)
This is the very important copy constructor.
SGSharedPtr< FGPropertyValue > FGPropertyValue_ptr
unsigned int FindNumColumns(const string &test_line)
bool is_number(const std::string &str)
std::string replace(std::string str, const std::string &old, const std::string &newstr)