44bool Element::converterIsInitialized =
false;
45map <string, map <string, double> > Element::convert;
58 if (!converterIsInitialized) {
59 converterIsInitialized =
true;
62 convert[
"M"][
"FT"] = 3.2808399;
63 convert[
"FT"][
"M"] = 1.0/convert[
"M"][
"FT"];
64 convert[
"CM"][
"FT"] = 0.032808399;
65 convert[
"FT"][
"CM"] = 1.0/convert[
"CM"][
"FT"];
66 convert[
"KM"][
"FT"] = 3280.8399;
67 convert[
"FT"][
"KM"] = 1.0/convert[
"KM"][
"FT"];
68 convert[
"FT"][
"IN"] = 12.0;
69 convert[
"IN"][
"FT"] = 1.0/convert[
"FT"][
"IN"];
70 convert[
"IN"][
"M"] = convert[
"IN"][
"FT"] * convert[
"FT"][
"M"];
71 convert[
"M"][
"IN"] = convert[
"M"][
"FT"] * convert[
"FT"][
"IN"];
73 convert[
"M2"][
"FT2"] = convert[
"M"][
"FT"]*convert[
"M"][
"FT"];
74 convert[
"FT2"][
"M2"] = 1.0/convert[
"M2"][
"FT2"];
75 convert[
"CM2"][
"FT2"] = convert[
"CM"][
"FT"]*convert[
"CM"][
"FT"];
76 convert[
"FT2"][
"CM2"] = 1.0/convert[
"CM2"][
"FT2"];
77 convert[
"M2"][
"IN2"] = convert[
"M"][
"IN"]*convert[
"M"][
"IN"];
78 convert[
"IN2"][
"M2"] = 1.0/convert[
"M2"][
"IN2"];
79 convert[
"FT2"][
"IN2"] = 144.0;
80 convert[
"IN2"][
"FT2"] = 1.0/convert[
"FT2"][
"IN2"];
82 convert[
"IN3"][
"CC"] = 16.387064;
83 convert[
"CC"][
"IN3"] = 1.0/convert[
"IN3"][
"CC"];
84 convert[
"FT3"][
"IN3"] = 1728.0;
85 convert[
"IN3"][
"FT3"] = 1.0/convert[
"FT3"][
"IN3"];
86 convert[
"M3"][
"FT3"] = 35.3146667;
87 convert[
"FT3"][
"M3"] = 1.0/convert[
"M3"][
"FT3"];
88 convert[
"LTR"][
"IN3"] = 61.0237441;
89 convert[
"IN3"][
"LTR"] = 1.0/convert[
"LTR"][
"IN3"];
90 convert[
"GAL"][
"FT3"] = 0.133681;
91 convert[
"FT3"][
"GAL"] = 1.0/convert[
"GAL"][
"FT3"];
92 convert[
"IN3"][
"GAL"] = convert[
"IN3"][
"FT3"]*convert[
"FT3"][
"GAL"];
93 convert[
"LTR"][
"GAL"] = convert[
"LTR"][
"IN3"]*convert[
"IN3"][
"GAL"];
94 convert[
"M3"][
"GAL"] = 1000.*convert[
"LTR"][
"GAL"];
95 convert[
"CC"][
"GAL"] = convert[
"CC"][
"IN3"]*convert[
"IN3"][
"GAL"];
97 convert[
"LBS"][
"KG"] = 0.45359237;
98 convert[
"KG"][
"LBS"] = 1.0/convert[
"LBS"][
"KG"];
99 convert[
"SLUG"][
"KG"] = 14.59390;
100 convert[
"KG"][
"SLUG"] = 1.0/convert[
"SLUG"][
"KG"];
102 convert[
"SLUG*FT2"][
"KG*M2"] = 1.35594;
103 convert[
"KG*M2"][
"SLUG*FT2"] = 1.0/convert[
"SLUG*FT2"][
"KG*M2"];
105 convert[
"RAD"][
"DEG"] = 180.0/
M_PI;
106 convert[
"DEG"][
"RAD"] = 1.0/convert[
"RAD"][
"DEG"];
108 convert[
"RAD/SEC"][
"DEG/SEC"] = convert[
"RAD"][
"DEG"];
109 convert[
"DEG/SEC"][
"RAD/SEC"] = 1.0/convert[
"RAD/SEC"][
"DEG/SEC"];
111 convert[
"LBS/FT"][
"N/M"] = 14.5939;
112 convert[
"N/M"][
"LBS/FT"] = 1.0/convert[
"LBS/FT"][
"N/M"];
114 convert[
"LBS/FT/SEC"][
"N/M/SEC"] = 14.5939;
115 convert[
"N/M/SEC"][
"LBS/FT/SEC"] = 1.0/convert[
"LBS/FT/SEC"][
"N/M/SEC"];
117 convert[
"LBS/FT2/SEC2"][
"N/M2/SEC2"] = 47.880259;
118 convert[
"N/M2/SEC2"][
"LBS/FT2/SEC2"] = 1.0/convert[
"LBS/FT2/SEC2"][
"N/M2/SEC2"];
120 convert[
"WATTS"][
"HP"] = 0.001341022;
121 convert[
"HP"][
"WATTS"] = 1.0/convert[
"WATTS"][
"HP"];
123 convert[
"N"][
"LBS"] = 0.22482;
124 convert[
"LBS"][
"N"] = 1.0/convert[
"N"][
"LBS"];
126 convert[
"KTS"][
"FT/SEC"] = 1.68781;
127 convert[
"FT/SEC"][
"KTS"] = 1.0/convert[
"KTS"][
"FT/SEC"];
128 convert[
"M/S"][
"FT/S"] = 3.2808399;
129 convert[
"M/S"][
"KTS"] = convert[
"M/S"][
"FT/S"]/convert[
"KTS"][
"FT/SEC"];
130 convert[
"M/SEC"][
"FT/SEC"] = 3.2808399;
131 convert[
"FT/S"][
"M/S"] = 1.0/convert[
"M/S"][
"FT/S"];
132 convert[
"M/SEC"][
"FT/SEC"] = 3.2808399;
133 convert[
"FT/SEC"][
"M/SEC"] = 1.0/convert[
"M/SEC"][
"FT/SEC"];
134 convert[
"KM/SEC"][
"FT/SEC"] = 3280.8399;
135 convert[
"FT/SEC"][
"KM/SEC"] = 1.0/convert[
"KM/SEC"][
"FT/SEC"];
137 convert[
"FT*LBS"][
"N*M"] = 1.35581795;
138 convert[
"N*M"][
"FT*LBS"] = 1/convert[
"FT*LBS"][
"N*M"];
140 convert[
"M4*SEC/KG"][
"FT4*SEC/SLUG"] = convert[
"M"][
"FT"]*convert[
"M"][
"FT"]*
141 convert[
"M"][
"FT"]*convert[
"M"][
"FT"]/convert[
"KG"][
"SLUG"];
142 convert[
"FT4*SEC/SLUG"][
"M4*SEC/KG"] =
143 1.0/convert[
"M4*SEC/KG"][
"FT4*SEC/SLUG"];
145 convert[
"INHG"][
"PSF"] = 70.7180803;
146 convert[
"PSF"][
"INHG"] = 1.0/convert[
"INHG"][
"PSF"];
147 convert[
"ATM"][
"INHG"] = 29.9246899;
148 convert[
"INHG"][
"ATM"] = 1.0/convert[
"ATM"][
"INHG"];
149 convert[
"PSI"][
"INHG"] = 2.03625437;
150 convert[
"INHG"][
"PSI"] = 1.0/convert[
"PSI"][
"INHG"];
151 convert[
"INHG"][
"PA"] = 3386.0;
152 convert[
"PA"][
"INHG"] = 1.0/convert[
"INHG"][
"PA"];
153 convert[
"LBS/FT2"][
"N/M2"] = 14.5939/convert[
"FT"][
"M"];
154 convert[
"N/M2"][
"LBS/FT2"] = 1.0/convert[
"LBS/FT2"][
"N/M2"];
155 convert[
"LBS/FT2"][
"PA"] = convert[
"LBS/FT2"][
"N/M2"];
156 convert[
"PA"][
"LBS/FT2"] = 1.0/convert[
"LBS/FT2"][
"PA"];
158 convert[
"KG/MIN"][
"LBS/MIN"] = convert[
"KG"][
"LBS"];
159 convert[
"KG/SEC"][
"LBS/SEC"] = convert[
"KG"][
"LBS"];
160 convert [
"N/SEC"][
"LBS/SEC"] = 0.224808943;
161 convert [
"LBS/SEC"][
"N/SEC"] = 1.0/convert [
"N/SEC"][
"LBS/SEC"];
163 convert[
"LBS/HP*HR"][
"KG/KW*HR"] = 0.6083;
164 convert[
"KG/KW*HR"][
"LBS/HP*HR"] = 1.0/convert[
"LBS/HP*HR"][
"KG/KW*HR"];
166 convert[
"KG/L"][
"LBS/GAL"] = 8.3454045;
167 convert[
"LBS/GAL"][
"KG/L"] = 1.0/convert[
"KG/L"][
"LBS/GAL"];
169 convert[
"FT3/SEC2"][
"M3/SEC2"] = convert[
"FT3"][
"M3"];
170 convert[
"M3/SEC2"][
"FT3/SEC2"] = convert[
"M3"][
"FT3"];
173 convert[
"M"][
"M"] = 1.00;
174 convert[
"KM"][
"KM"] = 1.00;
175 convert[
"FT"][
"FT"] = 1.00;
176 convert[
"IN"][
"IN"] = 1.00;
178 convert[
"M2"][
"M2"] = 1.00;
179 convert[
"FT2"][
"FT2"] = 1.00;
181 convert[
"IN3"][
"IN3"] = 1.00;
182 convert[
"CC"][
"CC"] = 1.0;
183 convert[
"M3"][
"M3"] = 1.0;
184 convert[
"FT3"][
"FT3"] = 1.0;
185 convert[
"LTR"][
"LTR"] = 1.0;
186 convert[
"GAL"][
"GAL"] = 1.0;
188 convert[
"KG"][
"KG"] = 1.00;
189 convert[
"LBS"][
"LBS"] = 1.00;
191 convert[
"KG*M2"][
"KG*M2"] = 1.00;
192 convert[
"SLUG*FT2"][
"SLUG*FT2"] = 1.00;
194 convert[
"DEG"][
"DEG"] = 1.00;
195 convert[
"RAD"][
"RAD"] = 1.00;
197 convert[
"DEG/SEC"][
"DEG/SEC"] = 1.00;
198 convert[
"RAD/SEC"][
"RAD/SEC"] = 1.00;
200 convert[
"LBS/FT"][
"LBS/FT"] = 1.00;
201 convert[
"N/M"][
"N/M"] = 1.00;
203 convert[
"LBS/FT/SEC"][
"LBS/FT/SEC"] = 1.00;
204 convert[
"N/M/SEC"][
"N/M/SEC"] = 1.00;
206 convert[
"LBS/FT2/SEC2"][
"LBS/FT2/SEC2"] = 1.00;
207 convert[
"N/M2/SEC2"][
"N/M2/SEC2"] = 1.00;
209 convert[
"HP"][
"HP"] = 1.00;
210 convert[
"WATTS"][
"WATTS"] = 1.00;
212 convert[
"N"][
"N"] = 1.00;
214 convert[
"FT/SEC"][
"FT/SEC"] = 1.00;
215 convert[
"KTS"][
"KTS"] = 1.00;
216 convert[
"M/S"][
"M/S"] = 1.0;
217 convert[
"M/SEC"][
"M/SEC"] = 1.0;
218 convert[
"KM/SEC"][
"KM/SEC"] = 1.0;
220 convert[
"FT*LBS"][
"FT*LBS"] = 1.00;
221 convert[
"N*M"][
"N*M"] = 1.00;
223 convert[
"M4*SEC/KG"][
"M4*SEC/KG"] = 1.0;
224 convert[
"FT4*SEC/SLUG"][
"FT4*SEC/SLUG"] = 1.0;
226 convert[
"PSI"][
"PSI"] = 1.00;
227 convert[
"PSF"][
"PSF"] = 1.00;
228 convert[
"INHG"][
"INHG"] = 1.00;
229 convert[
"ATM"][
"ATM"] = 1.0;
230 convert[
"PA"][
"PA"] = 1.0;
231 convert[
"N/M2"][
"N/M2"] = 1.00;
232 convert[
"LBS/FT2"][
"LBS/FT2"] = 1.00;
234 convert[
"LBS/SEC"][
"LBS/SEC"] = 1.00;
235 convert[
"KG/MIN"][
"KG/MIN"] = 1.0;
236 convert[
"LBS/MIN"][
"LBS/MIN"] = 1.0;
237 convert[
"N/SEC"][
"N/SEC"] = 1.0;
239 convert[
"LBS/HP*HR"][
"LBS/HP*HR"] = 1.0;
240 convert[
"KG/KW*HR"][
"KG/KW*HR"] = 1.0;
242 convert[
"KG/L"][
"KG/L"] = 1.0;
243 convert[
"LBS/GAL"][
"LBS/GAL"] = 1.0;
245 convert[
"FT3/SEC2"][
"FT3/SEC2"] = 1.0;
246 convert[
"M3/SEC2"][
"M3/SEC2"] = 1.0;
254 for (
unsigned int i = 0;
i < children.size(); ++
i)
272 attributes[key] = value;
283 if (attribute.empty()) {
285 s <<
ReadFrom() <<
"Expecting numeric attribute value, but got no data";
286 cerr << s.str() << endl;
287 throw length_error(s.str());
292 number =
atof(attribute.c_str());
295 s <<
ReadFrom() <<
"Expecting numeric attribute value, but got: " << attribute;
296 cerr << s.str() << endl;
297 throw invalid_argument(s.str());
308 if (children.size() > el) {
322 if (children.size() > element_index+1) {
324 return children[element_index];
335 if (data_lines.size() > 0)
return data_lines[
i];
336 else return string(
"");
343 if (data_lines.size() == 1) {
346 number =
atof(data_lines[0].c_str());
349 s <<
ReadFrom() <<
"Expected numeric value, but got: " << data_lines[0];
350 cerr << s.str() << endl;
351 throw invalid_argument(s.str());
355 }
else if (data_lines.size() == 0) {
357 s <<
ReadFrom() <<
"Expected numeric value, but got no data";
358 cerr << s.str() << endl;
359 throw length_error(s.str());
361 cerr <<
ReadFrom() <<
"Attempting to get single data value in element "
362 <<
"<" << name <<
">" << endl
363 <<
" from multiple lines:" << endl;
364 for(
unsigned int i=0;
i<data_lines.size(); ++
i)
365 cerr << data_lines[
i] << endl;
367 s <<
ReadFrom() <<
"Attempting to get single data value in element "
368 <<
"<" << name <<
">"
369 <<
" from multiple lines (" << data_lines.size() <<
").";
370 throw length_error(s.str());
378 unsigned int number_of_elements=0;
381 number_of_elements++;
384 return number_of_elements;
391 if (el.empty() && children.size() >= 1) {
395 for (
unsigned int i=0;
i<children.size();
i++) {
410 if (element_index < children.size()) {
411 return children[element_index++];
417 for (
unsigned int i=element_index;
i<children.size();
i++) {
438 s <<
ReadFrom() <<
"Attempting to get non-existent element " << el;
439 cerr << s.str() << endl;
440 throw length_error(s.str());
460 cerr <<
ReadFrom() <<
"Attempting to get non-existent element " << el <<
" ;returning false"
486 s <<
ReadFrom() <<
"Attempting to get non-existent element " << el;
487 cerr << s.str() << endl;
488 throw length_error(s.str());
493 if (!supplied_units.empty()) {
494 if (convert.find(supplied_units) == convert.end()) {
496 s << element->
ReadFrom() <<
"Supplied unit: \"" << supplied_units
497 <<
"\" does not exist (typo?).";
498 cerr << s.str() << endl;
499 throw invalid_argument(s.str());
501 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
503 s << element->
ReadFrom() <<
"Supplied unit: \"" << supplied_units
504 <<
"\" cannot be converted to " << target_units;
505 cerr << s.str() << endl;
506 throw invalid_argument(s.str());
513 if ((supplied_units ==
"RAD") && (fabs(value) > 2 *
M_PI)) {
515 << value <<
" RAD is outside the range [ -2*M_PI RAD ; +2*M_PI RAD ]"
518 if ((supplied_units ==
"DEG") && (fabs(value) > 360.0)) {
520 << value <<
" DEG is outside the range [ -360 DEG ; +360 DEG ]"
525 if (!supplied_units.empty()) {
526 value *= convert[supplied_units][target_units];
529 if ((target_units ==
"RAD") && (fabs(value) > 2 *
M_PI)) {
531 << value <<
" RAD is outside the range [ -2*M_PI RAD ; +2*M_PI RAD ]"
534 if ((target_units ==
"DEG") && (fabs(value) > 360.0)) {
536 << value <<
" DEG is outside the range [ -360 DEG ; +360 DEG ]"
540 value =
DisperseValue(element, value, supplied_units, target_units);
548 const string& supplied_units,
549 const string& target_units)
555 s <<
ReadFrom() <<
"Attempting to get non-existent element " << el;
556 cerr << s.str() << endl;
557 throw length_error(s.str());
560 if (!supplied_units.empty()) {
561 if (convert.find(supplied_units) == convert.end()) {
563 s << element->
ReadFrom() <<
"Supplied unit: \"" << supplied_units
564 <<
"\" does not exist (typo?).";
565 cerr << s.str() << endl;
566 throw invalid_argument(s.str());
568 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
570 s << element->
ReadFrom() <<
"Supplied unit: \"" << supplied_units
571 <<
"\" cannot be converted to " << target_units;
572 cerr << s.str() << endl;
573 throw invalid_argument(s.str());
578 if (!supplied_units.empty()) {
579 value *= convert[supplied_units][target_units];
582 value =
DisperseValue(element, value, supplied_units, target_units);
596 if (!supplied_units.empty()) {
597 if (convert.find(supplied_units) == convert.end()) {
599 s <<
ReadFrom() <<
"Supplied unit: \"" << supplied_units
600 <<
"\" does not exist (typo?).";
601 cerr << s.str() << endl;
602 throw invalid_argument(s.str());
604 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
606 s <<
ReadFrom() <<
"Supplied unit: \"" << supplied_units
607 <<
"\" cannot be converted to " << target_units;
608 cerr << s.str() << endl;
609 throw invalid_argument(s.str());
617 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
618 triplet(1) =
DisperseValue(item, value, supplied_units, target_units);
628 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
629 triplet(2) =
DisperseValue(item, value, supplied_units, target_units);
638 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
639 triplet(3) =
DisperseValue(item, value, supplied_units, target_units);
650 const std::string& target_units)
654 bool disperse =
false;
656 char* num = getenv(
"JSBSIM_DISPERSE");
658 disperse = (
atoi(num) == 1);
662 std::cerr <<
"Could not process JSBSIM_DISPERSE environment variable: Assumed NO dispersions." << endl;
667 if (!supplied_units.empty()) disp *= convert[supplied_units][target_units];
669 if (attType ==
"gaussian" || attType ==
"gaussiansigned") {
671 if (attType ==
"gaussian") {
672 value = val + disp*grn;
674 value = (val + disp*grn)*(fabs(grn)/grn);
676 }
else if (attType ==
"uniform" || attType ==
"uniformsigned") {
677 double urn = ((((double)rand()/RAND_MAX)-0.5)*2.0);
678 if (attType ==
"uniform") {
679 value = val + disp * urn;
681 value = (val + disp * urn)*(fabs(urn)/urn);
685 s <<
ReadFrom() <<
"Unknown dispersion type" << attType;
686 cerr << s.str() << endl;
687 throw domain_error(s.str());
698 unsigned int i, spaces;
701 for (spaces=0; spaces<=level; spaces++) cout <<
" ";
702 cout <<
"Element Name: " << name;
704 map<string, string>::iterator it;
705 for (it = attributes.begin(); it != attributes.end(); ++it)
706 cout <<
" " << it->first <<
" = " << it->second;
709 for (
i=0;
i<data_lines.size();
i++) {
710 for (spaces=0; spaces<=level; spaces++) cout <<
" ";
711 cout << data_lines[
i] << endl;
713 for (
i=0;
i<children.size();
i++) {
714 children[
i]->Print(level);
722 attributes[name] = value;
729 string::size_type string_start = d.find_first_not_of(
" \t");
730 if (string_start != string::npos && string_start > 0) {
731 d.erase(0,string_start);
733 data_lines.push_back(d);
740 ostringstream message;
746 return message.str();
753 map<string, string>::iterator it;
755 for (it=el->attributes.begin(); it != el->attributes.end(); ++it) {
756 if (attributes.find(it->first) == attributes.end())
757 attributes[it->first] = it->second;
760 cout << el->
ReadFrom() <<
" Attribute '" << it->first <<
"' is overridden in file "
762 <<
" The value '" << attributes[it->first] <<
"' will be used instead of '"
763 << it->second <<
"'." << endl;
double FindElementValueAsNumberConvertTo(const std::string &el, const std::string &target_units)
Searches for the named element and converts and returns the data belonging to it.
const std::string & GetName(void) const
Retrieves the element name.
void AddAttribute(const std::string &name, const std::string &value)
Stores an attribute belonging to this element.
double FindElementValueAsNumber(const std::string &el="")
Searches for the named element and returns the data belonging to it as a number.
FGColumnVector3 FindElementTripletConvertTo(const std::string &target_units)
Composes a 3-element column vector for the supplied location or orientation.
void SetParent(Element *p)
This function sets the value of the parent class attribute to the supplied Element pointer.
std::string ReadFrom(void) const
Return a string that contains a description of the location where the current XML element was read fr...
void Print(unsigned int level=0)
Prints the element.
Element * GetNextElement(void)
Returns a pointer to the next element in the list.
double FindElementValueAsNumberConvertFromTo(const std::string &el, const std::string &supplied_units, const std::string &target_units)
Searches for the named element and converts and returns the data belonging to it.
double GetAttributeValueAsNumber(const std::string &key)
Retrieves an attribute value as a double precision real number.
bool FindElementValueAsBoolean(const std::string &el="")
Searches for the named element and returns the data belonging to it as a bool.
std::string FindElementValue(const std::string &el="")
Searches for the named element and returns the string data belonging to it.
int GetLineNumber(void) const
Returns the line number at which the element has been defined.
~Element(void)
Destructor.
Element(const std::string &nm)
Constructor.
void AddData(std::string d)
Stores data belonging to this element.
std::string GetDataLine(unsigned int i=0)
Gets a line of data belonging to an element.
bool HasAttribute(const std::string &key)
Determines if an element has the supplied attribute.
std::string GetAttributeValue(const std::string &key)
Retrieves an attribute.
unsigned int GetNumElements(void)
Returns the number of child elements for this element.
Element * GetElement(unsigned int el=0)
Returns a pointer to the element requested by index.
bool SetAttributeValue(const std::string &key, const std::string &value)
Modifies an attribute.
double GetDataAsNumber(void)
Converts the element data to a number.
double DisperseValue(Element *e, double val, const std::string &supplied_units="", const std::string &target_units="")
void MergeAttributes(Element *el)
Merges the attributes of the current element with another 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.
This class implements a 3 element column vector.
static double GaussianRandomNumber(void)
static double atof(const string &str)
static int atoi(const string &str)
bool is_number(const std::string &str)
std::string & trim(std::string &str)