/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Author: Jon Berndt Date started: 09/28/2004 Purpose: XML element class Called by: FGXMLParse ------------- Copyright (C) 2001 Jon S. Berndt (jon@jsbsim.org) ------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. Further information about the GNU Lesser General Public License can also be found on the world wide web at http://www.gnu.org. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% INCLUDES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ #include "FGXMLElement.h" #include "FGJSBBase.h" using namespace std; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FORWARD DECLARATIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ namespace JSBSim { bool Element::converterIsInitialized = false; map > Element::convert; /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLASS IMPLEMENTATION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ Element::Element(const string& nm) { name = nm; parent = 0L; element_index = 0; line_number = -1; if (!converterIsInitialized) { converterIsInitialized = true; // convert ["from"]["to"] = factor, so: from * factor = to // Length convert["M"]["FT"] = 3.2808399; convert["FT"]["M"] = 1.0/convert["M"]["FT"]; convert["CM"]["FT"] = 0.032808399; convert["FT"]["CM"] = 1.0/convert["CM"]["FT"]; convert["KM"]["FT"] = 3280.8399; convert["FT"]["KM"] = 1.0/convert["KM"]["FT"]; convert["FT"]["IN"] = 12.0; convert["IN"]["FT"] = 1.0/convert["FT"]["IN"]; convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"]; convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"]; // Area convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"]; convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"]; convert["CM2"]["FT2"] = convert["CM"]["FT"]*convert["CM"]["FT"]; convert["FT2"]["CM2"] = 1.0/convert["CM2"]["FT2"]; convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"]; convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"]; convert["FT2"]["IN2"] = 144.0; convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"]; // Volume convert["IN3"]["CC"] = 16.387064; convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"]; convert["FT3"]["IN3"] = 1728.0; convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"]; convert["M3"]["FT3"] = 35.3146667; convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"]; convert["LTR"]["IN3"] = 61.0237441; convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"]; convert["GAL"]["FT3"] = 0.133681; convert["FT3"]["GAL"] = 1.0/convert["GAL"]["FT3"]; convert["IN3"]["GAL"] = convert["IN3"]["FT3"]*convert["FT3"]["GAL"]; convert["LTR"]["GAL"] = convert["LTR"]["IN3"]*convert["IN3"]["GAL"]; convert["M3"]["GAL"] = 1000.*convert["LTR"]["GAL"]; convert["CC"]["GAL"] = convert["CC"]["IN3"]*convert["IN3"]["GAL"]; // Mass & Weight convert["LBS"]["KG"] = 0.45359237; convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"]; convert["SLUG"]["KG"] = 14.59390; convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"]; // Moments of Inertia convert["SLUG*FT2"]["KG*M2"] = 1.35594; convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"]; // Angles convert["RAD"]["DEG"] = 180.0/M_PI; convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"]; // Angular rates convert["RAD/SEC"]["DEG/SEC"] = convert["RAD"]["DEG"]; convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"]; // Spring force convert["LBS/FT"]["N/M"] = 14.5939; convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"]; // Damping force convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939; convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"]; // Damping force (Square Law) convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259; convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"]; // Power convert["WATTS"]["HP"] = 0.001341022; convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"]; // Force convert["N"]["LBS"] = 0.22482; convert["LBS"]["N"] = 1.0/convert["N"]["LBS"]; // Velocity convert["KTS"]["FT/SEC"] = 1.68781; convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"]; convert["M/S"]["FT/S"] = 3.2808399; convert["M/S"]["KTS"] = convert["M/S"]["FT/S"]/convert["KTS"]["FT/SEC"]; convert["M/SEC"]["FT/SEC"] = 3.2808399; convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"]; convert["M/SEC"]["FT/SEC"] = 3.2808399; convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"]; convert["KM/SEC"]["FT/SEC"] = 3280.8399; convert["FT/SEC"]["KM/SEC"] = 1.0/convert["KM/SEC"]["FT/SEC"]; // Torque convert["FT*LBS"]["N*M"] = 1.35581795; convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"]; // Valve convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]* convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"]; convert["FT4*SEC/SLUG"]["M4*SEC/KG"] = 1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"]; // Pressure convert["INHG"]["PSF"] = 70.7180803; convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"]; convert["ATM"]["INHG"] = 29.9246899; convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"]; convert["PSI"]["INHG"] = 2.03625437; convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"]; convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"]; convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"]; convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"]; convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"]; convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"]; // Mass flow convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"]; convert ["N/SEC"]["LBS/SEC"] = 0.224808943; convert ["LBS/SEC"]["N/SEC"] = 1.0/convert ["N/SEC"]["LBS/SEC"]; // Fuel Consumption convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083; convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"]; // Density convert["KG/L"]["LBS/GAL"] = 8.3454045; convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"]; // Length convert["M"]["M"] = 1.00; convert["KM"]["KM"] = 1.00; convert["FT"]["FT"] = 1.00; convert["IN"]["IN"] = 1.00; // Area convert["M2"]["M2"] = 1.00; convert["FT2"]["FT2"] = 1.00; // Volume convert["IN3"]["IN3"] = 1.00; convert["CC"]["CC"] = 1.0; convert["M3"]["M3"] = 1.0; convert["FT3"]["FT3"] = 1.0; convert["LTR"]["LTR"] = 1.0; convert["GAL"]["GAL"] = 1.0; // Mass & Weight convert["KG"]["KG"] = 1.00; convert["LBS"]["LBS"] = 1.00; // Moments of Inertia convert["KG*M2"]["KG*M2"] = 1.00; convert["SLUG*FT2"]["SLUG*FT2"] = 1.00; // Angles convert["DEG"]["DEG"] = 1.00; convert["RAD"]["RAD"] = 1.00; // Angular rates convert["DEG/SEC"]["DEG/SEC"] = 1.00; convert["RAD/SEC"]["RAD/SEC"] = 1.00; // Spring force convert["LBS/FT"]["LBS/FT"] = 1.00; convert["N/M"]["N/M"] = 1.00; // Damping force convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00; convert["N/M/SEC"]["N/M/SEC"] = 1.00; // Damping force (Square law) convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00; convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00; // Power convert["HP"]["HP"] = 1.00; convert["WATTS"]["WATTS"] = 1.00; // Force convert["N"]["N"] = 1.00; // Velocity convert["FT/SEC"]["FT/SEC"] = 1.00; convert["KTS"]["KTS"] = 1.00; convert["M/S"]["M/S"] = 1.0; convert["M/SEC"]["M/SEC"] = 1.0; convert["KM/SEC"]["KM/SEC"] = 1.0; // Torque convert["FT*LBS"]["FT*LBS"] = 1.00; convert["N*M"]["N*M"] = 1.00; // Valve convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0; convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0; // Pressure convert["PSI"]["PSI"] = 1.00; convert["PSF"]["PSF"] = 1.00; convert["INHG"]["INHG"] = 1.00; convert["ATM"]["ATM"] = 1.0; convert["PA"]["PA"] = 1.0; convert["N/M2"]["N/M2"] = 1.00; convert["LBS/FT2"]["LBS/FT2"] = 1.00; // Mass flow convert["LBS/SEC"]["LBS/SEC"] = 1.00; convert["KG/MIN"]["KG/MIN"] = 1.0; convert["LBS/MIN"]["LBS/MIN"] = 1.0; convert["N/SEC"]["N/SEC"] = 1.0; // Fuel Consumption convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0; convert["KG/KW*HR"]["KG/KW*HR"] = 1.0; // Density convert["KG/L"]["KG/L"] = 1.0; convert["LBS/GAL"]["LBS/GAL"] = 1.0; } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element::~Element(void) { for (unsigned int i = 0; i < children.size(); ++i) children[i]->SetParent(0); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::GetAttributeValue(const string& attr) { if (HasAttribute(attr)) return attributes[attr]; else return (""); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool Element::SetAttributeValue(const std::string& key, const std::string& value) { bool ret = HasAttribute(key); if (ret) attributes[key] = value; return ret; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::GetAttributeValueAsNumber(const string& attr) { string attribute = GetAttributeValue(attr); if (attribute.empty()) { cerr << ReadFrom() << "Expecting numeric attribute value, but got no data" << endl; exit(-1); } else { double number=0; if (is_number(trim(attribute))) number = atof(attribute.c_str()); else { cerr << ReadFrom() << "Expecting numeric attribute value, but got: " << attribute << endl; exit(-1); } return (number); } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::GetElement(unsigned int el) { if (children.size() > el) { element_index = el; return children[el]; } else { element_index = 0; return 0L; } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::GetNextElement(void) { if (children.size() > element_index+1) { element_index++; return children[element_index]; } else { element_index = 0; return 0L; } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::GetDataLine(unsigned int i) { if (data_lines.size() > 0) return data_lines[i]; else return string(""); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::GetDataAsNumber(void) { if (data_lines.size() == 1) { double number=0; if (is_number(trim(data_lines[0]))) number = atof(data_lines[0].c_str()); else { cerr << ReadFrom() << "Expected numeric value, but got: " << data_lines[0] << endl; exit(-1); } return number; } else if (data_lines.size() == 0) { cerr << ReadFrom() << "Expected numeric value, but got no data" << endl; exit(-1); } else { cerr << ReadFrom() << "Attempting to get single data value in element " << "<" << name << ">" << endl << " from multiple lines:" << endl; for(unsigned int i=0; i= 1) { element_index = 1; return children[0]; } for (unsigned int i=0; iGetName()) { element_index = i+1; return children[i]; } } element_index = 0; return 0L; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Element* Element::FindNextElement(const string& el) { if (el.empty()) { if (element_index < children.size()) { return children[element_index++]; } else { element_index = 0; return 0L; } } for (unsigned int i=element_index; iGetName()) { element_index = i+1; return children[i]; } } element_index = 0; return 0L; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::FindElementValueAsNumber(const string& el) { Element* element = FindElement(el); if (element) { double value = element->GetDataAsNumber(); value = DisperseValue(element, value); return value; } else { cerr << ReadFrom() << "Attempting to get non-existent element " << el << endl; exit(-1); } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% bool Element::FindElementValueAsBoolean(const string& el) { Element* element = FindElement(el); if (element) { // check value as an ordinary number double value = element->GetDataAsNumber(); // now check how it should return data if (value == 0) { return false; } else { return true; } } else { cerr << ReadFrom() << "Attempting to get non-existent element " << el << " ;returning false" << endl; return false; } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::FindElementValue(const string& el) { Element* element = FindElement(el); if (element) { return element->GetDataLine(); } else { return ""; } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::FindElementValueAsNumberConvertTo(const string& el, const string& target_units) { Element* element = FindElement(el); if (!element) { cerr << ReadFrom() << "Attempting to get non-existent element " << el << endl; exit(-1); } string supplied_units = element->GetAttributeValue("unit"); if (!supplied_units.empty()) { if (convert.find(supplied_units) == convert.end()) { cerr << element->ReadFrom() << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?)." << endl; exit(-1); } if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { cerr << element->ReadFrom() << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " << target_units << endl; exit(-1); } } double value = element->GetDataAsNumber(); // Sanity check for angular values if ((supplied_units == "RAD") && (fabs(value) > 2 * M_PI)) { cerr << element->ReadFrom() << element->GetName() << " value " << value << " RAD is outside the range [ -2*M_PI RAD ; +2*M_PI RAD ]" << endl; } if ((supplied_units == "DEG") && (fabs(value) > 360.0)) { cerr << element->ReadFrom() << element->GetName() << " value " << value << " DEG is outside the range [ -360 DEG ; +360 DEG ]" << endl; } if (!supplied_units.empty()) { value *= convert[supplied_units][target_units]; } if ((target_units == "RAD") && (fabs(value) > 2 * M_PI)) { cerr << element->ReadFrom() << element->GetName() << " value " << value << " RAD is outside the range [ -2*M_PI RAD ; +2*M_PI RAD ]" << endl; } if ((target_units == "DEG") && (fabs(value) > 360.0)) { cerr << element->ReadFrom() << element->GetName() << " value " << value << " DEG is outside the range [ -360 DEG ; +360 DEG ]" << endl; } value = DisperseValue(element, value, supplied_units, target_units); return value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::FindElementValueAsNumberConvertFromTo( const string& el, const string& supplied_units, const string& target_units) { Element* element = FindElement(el); if (!element) { cerr << "Attempting to get non-existent element " << el << endl; exit(-1); } if (!supplied_units.empty()) { if (convert.find(supplied_units) == convert.end()) { cerr << element->ReadFrom() << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?)." << endl; exit(-1); } if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { cerr << element->ReadFrom() << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " << target_units << endl; exit(-1); } } double value = element->GetDataAsNumber(); if (!supplied_units.empty()) { value *= convert[supplied_units][target_units]; } value = DisperseValue(element, value, supplied_units, target_units); return value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units) { FGColumnVector3 triplet; Element* item; double value=0.0; string supplied_units = GetAttributeValue("unit"); if (!supplied_units.empty()) { if (convert.find(supplied_units) == convert.end()) { cerr << ReadFrom() << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?)." << endl; exit(-1); } if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) { cerr << ReadFrom() << "Supplied unit: \"" << supplied_units << "\" cannot be converted to " << target_units << endl; exit(-1); } } item = FindElement("x"); if (!item) item = FindElement("roll"); if (item) { value = item->GetDataAsNumber(); if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; triplet(1) = DisperseValue(item, value, supplied_units, target_units); } else { triplet(1) = 0.0; } item = FindElement("y"); if (!item) item = FindElement("pitch"); if (item) { value = item->GetDataAsNumber(); if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; triplet(2) = DisperseValue(item, value, supplied_units, target_units); } else { triplet(2) = 0.0; } item = FindElement("z"); if (!item) item = FindElement("yaw"); if (item) { value = item->GetDataAsNumber(); if (!supplied_units.empty()) value *= convert[supplied_units][target_units]; triplet(3) = DisperseValue(item, value, supplied_units, target_units); } else { triplet(3) = 0.0; } return triplet; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% double Element::DisperseValue(Element *e, double val, const std::string& supplied_units, const std::string& target_units) { double value=val; bool disperse = false; try { char* num = getenv("JSBSIM_DISPERSE"); if (num) { disperse = (atoi(num) == 1); // set dispersions } } catch (...) { // if error set to false disperse = false; std::cerr << "Could not process JSBSIM_DISPERSE environment variable: Assumed NO dispersions." << endl; } if (e->HasAttribute("dispersion") && disperse) { double disp = e->GetAttributeValueAsNumber("dispersion"); if (!supplied_units.empty()) disp *= convert[supplied_units][target_units]; string attType = e->GetAttributeValue("type"); if (attType == "gaussian" || attType == "gaussiansigned") { double grn = FGJSBBase::GaussianRandomNumber(); if (attType == "gaussian") { value = val + disp*grn; } else { // Assume gaussiansigned value = (val + disp*grn)*(fabs(grn)/grn); } } else if (attType == "uniform" || attType == "uniformsigned") { double urn = ((((double)rand()/RAND_MAX)-0.5)*2.0); if (attType == "uniform") { value = val + disp * urn; } else { // Assume uniformsigned value = (val + disp * urn)*(fabs(urn)/urn); } } else { cerr << ReadFrom() << "Unknown dispersion type" << attType << endl; exit(-1); } } return value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::Print(unsigned int level) { unsigned int i, spaces; level+=2; for (spaces=0; spaces<=level; spaces++) cout << " "; // format output cout << "Element Name: " << name; map::iterator it; for (it = attributes.begin(); it != attributes.end(); ++it) cout << " " << it->first << " = " << it->second; cout << endl; for (i=0; iPrint(level); } } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::AddAttribute(const string& name, const string& value) { attributes[name] = value; } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::AddData(string d) { string::size_type string_start = d.find_first_not_of(" \t"); if (string_start != string::npos && string_start > 0) { d.erase(0,string_start); } data_lines.push_back(d); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% string Element::ReadFrom(void) const { ostringstream message; message << endl << "In file " << GetFileName() << ": line " << GetLineNumber() << endl; return message.str(); } //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% void Element::MergeAttributes(Element* el) { map::iterator it; for (it=el->attributes.begin(); it != el->attributes.end(); ++it) { if (attributes.find(it->first) == attributes.end()) attributes[it->first] = it->second; else { if (FGJSBBase::debug_lvl > 0 && (attributes[it->first] != it->second)) cout << el->ReadFrom() << " Attribute '" << it->first << "' is overridden in file " << GetFileName() << ": line " << GetLineNumber() << endl << " The value '" << attributes[it->first] << "' will be used instead of '" << it->second << "'." << endl; } } } } // end namespace JSBSim