1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
4 Date started: 09/28/2004
5 Purpose: XML element class
8 ------------- Copyright (C) 2001 Jon S. Berndt (jsb@hal-pc.org) -------------
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
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 Lesser General Public License for more
20 You should have received a copy of the GNU Lesser 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.
24 Further information about the GNU Lesser General Public License can also be found on
25 the world wide web at http://www.gnu.org.
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
31 #include "FGXMLElement.h"
36 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
42 static const char *IdSrc = "$Id$";
43 static const char *IdHdr = ID_XMLELEMENT;
45 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
49 Element::Element(string nm)
55 // convert ["from"]["to"] = factor, so: from * factor = to
57 convert["M"]["FT"] = 3.2808399;
58 convert["FT"]["M"] = 1.0/convert["M"]["FT"];
59 convert["FT"]["IN"] = 12.0;
60 convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
61 convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
62 convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
64 convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
65 convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
66 convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"];
67 convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"];
69 convert["IN3"]["CC"] = 16.387064;
70 convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"];
71 convert["FT3"]["IN3"] = 1728.0;
72 convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"];
73 convert["M3"]["FT3"] = 35.3146667;
74 convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
75 convert["LTR"]["IN3"] = 61.0237441;
76 convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
78 convert["LBS"]["KG"] = 0.45359237;
79 convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
80 convert["SLUG"]["KG"] = 14.59390;
81 convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"];
83 convert["SLUG*FT2"]["KG*M2"] = 1.35594;
84 convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
86 convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
87 convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
89 convert["LBS/FT"]["N/M"] = 14.5939;
90 convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
92 convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
93 convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
94 // Damping force (Square Law)
95 convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259;
96 convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"];
98 convert["WATTS"]["HP"] = 0.001341022;
99 convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
101 convert["N"]["LBS"] = 0.22482;
102 convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
104 convert["KTS"]["FT/SEC"] = 1.68781;
105 convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
106 convert["M/S"]["FT/S"] = 3.2808399;
107 convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
109 convert["FT*LBS"]["N*M"] = 1.35581795;
110 convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
112 convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]*
113 convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"];
114 convert["FT4*SEC/SLUG"]["M4*SEC/KG"] =
115 1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"];
117 convert["INHG"]["PSF"] = 70.7180803;
118 convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"];
119 convert["ATM"]["INHG"] = 29.9246899;
120 convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"];
121 convert["PSI"]["INHG"] = 2.03625437;
122 convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"];
123 convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals
124 convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"];
125 convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"];
126 convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"];
127 convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"];
128 convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
130 convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
133 convert["M"]["M"] = 1.00;
134 convert["FT"]["FT"] = 1.00;
135 convert["IN"]["IN"] = 1.00;
137 convert["M2"]["M2"] = 1.00;
138 convert["FT2"]["FT2"] = 1.00;
140 convert["IN3"]["IN3"] = 1.00;
141 convert["CC"]["CC"] = 1.0;
142 convert["M3"]["M3"] = 1.0;
143 convert["FT3"]["FT3"] = 1.0;
144 convert["LTR"]["LTR"] = 1.0;
146 convert["KG"]["KG"] = 1.00;
147 convert["LBS"]["LBS"] = 1.00;
148 // Moments of Inertia
149 convert["KG*M2"]["KG*M2"] = 1.00;
150 convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
152 convert["DEG"]["DEG"] = 1.00;
153 convert["RAD"]["RAD"] = 1.00;
155 convert["LBS/FT"]["LBS/FT"] = 1.00;
156 convert["N/M"]["N/M"] = 1.00;
158 convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
159 convert["N/M/SEC"]["N/M/SEC"] = 1.00;
160 // Damping force (Square law)
161 convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00;
162 convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00;
164 convert["HP"]["HP"] = 1.00;
165 convert["WATTS"]["WATTS"] = 1.00;
167 convert["N"]["N"] = 1.00;
169 convert["FT/SEC"]["FT/SEC"] = 1.00;
170 convert["KTS"]["KTS"] = 1.00;
171 convert["M/S"]["M/S"] = 1.0;
173 convert["FT*LBS"]["FT*LBS"] = 1.00;
174 convert["N*M"]["N*M"] = 1.00;
176 convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0;
177 convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0;
179 convert["PSI"]["PSI"] = 1.00;
180 convert["PSF"]["PSF"] = 1.00;
181 convert["INHG"]["INHG"] = 1.00;
182 convert["ATM"]["ATM"] = 1.0;
183 convert["PA"]["PA"] = 1.0;
184 convert["N/M2"]["N/M2"] = 1.00;
185 convert["LBS/FT2"]["LBS/FT2"] = 1.00;
187 convert["LBS/SEC"]["LBS/SEC"] = 1.00;
188 convert["KG/MIN"]["KG/MIN"] = 1.0;
189 convert["LBS/MIN"]["LBS/MIN"] = 1.0;
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
194 Element::~Element(void)
196 for (unsigned int i=0; i<children.size(); i++) delete children[i];
199 attribute_key.clear();
202 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 string Element::GetAttributeValue(string attr)
207 for (unsigned int i=0; i<attribute_key.size(); i++) {
208 if (attribute_key[i] == attr) select = i;
210 if (select < 0) return string("");
211 else return attributes[attr];
214 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
216 double Element::GetAttributeValueAsNumber(string attr)
218 string attribute = GetAttributeValue(attr);
220 if (attribute.empty()) return HUGE_VAL;
221 else return (atof(attribute.c_str()));
224 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226 Element* Element::GetElement(unsigned int el)
228 if (children.size() > el) {
238 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
240 Element* Element::GetNextElement(void)
242 if (children.size() > element_index+1) {
244 return children[element_index];
251 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
253 string Element::GetDataLine(unsigned int i)
255 if (data_lines.size() > 0) return data_lines[i];
256 else return string("");
259 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
261 double Element::GetDataAsNumber(void)
263 if (data_lines.size() == 1) {
264 return atof(data_lines[0].c_str());
265 } else if (data_lines.size() == 0) {
268 cerr << "Attempting to get single data value from multiple lines in element " << name << endl;
273 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 unsigned int Element::GetNumElements(string element_name)
277 unsigned int number_of_elements=0;
278 Element* el=FindElement(element_name);
280 number_of_elements++;
281 el=FindNextElement(element_name);
283 return number_of_elements;
286 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288 Element* Element::FindElement(string el)
290 if (el.empty() && children.size() >= 1) {
294 for (unsigned int i=0; i<children.size(); i++) {
295 if (el == children[i]->GetName()) {
304 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306 Element* Element::FindNextElement(string el)
309 if (element_index < children.size()) {
310 return children[element_index++];
316 for (unsigned int i=element_index; i<children.size(); i++) {
317 if (el == children[i]->GetName()) {
326 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
328 double Element::FindElementValueAsNumber(string el)
330 Element* element = FindElement(el);
332 return element->GetDataAsNumber();
334 cerr << "Attempting to get single data value from multiple lines" << endl;
339 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341 string Element::FindElementValue(string el)
343 Element* element = FindElement(el);
345 return element->GetDataLine();
351 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353 double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
355 Element* element = FindElement(el);
358 cerr << "Attempting to get non-existent element " << el << endl;
362 string supplied_units = element->GetAttributeValue("unit");
364 if (!supplied_units.empty()) {
365 if (convert.find(supplied_units) == convert.end()) {
366 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
367 << " conversion in FGXMLElement.cpp." << endl;
370 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
371 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
372 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
377 double value = element->GetDataAsNumber();
378 if (!supplied_units.empty()) {
379 value *= convert[supplied_units][target_units];
385 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
387 double Element::FindElementValueAsNumberConvertFromTo( string el,
388 string supplied_units,
391 Element* element = FindElement(el);
394 cerr << "Attempting to get non-existent element " << el << endl;
398 if (!supplied_units.empty()) {
399 if (convert.find(supplied_units) == convert.end()) {
400 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
401 << " conversion in FGXMLElement.cpp." << endl;
404 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
405 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
406 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
411 double value = element->GetDataAsNumber();
412 if (!supplied_units.empty()) {
413 value *= convert[supplied_units][target_units];
419 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
421 FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
423 FGColumnVector3 triplet;
426 string supplied_units = GetAttributeValue("unit");
428 if (!supplied_units.empty()) {
429 if (convert.find(supplied_units) == convert.end()) {
430 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
431 << " conversion in FGXMLElement.cpp." << endl;
434 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
435 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
436 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
441 item = FindElement("x");
442 if (!item) item = FindElement("roll");
444 value = item->GetDataAsNumber();
445 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
448 cerr << "Could not find an X triplet item for this column vector." << endl;
452 item = FindElement("y");
453 if (!item) item = FindElement("pitch");
455 value = item->GetDataAsNumber();
456 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
459 cerr << "Could not find a Y triplet item for this column vector." << endl;
463 item = FindElement("z");
464 if (!item) item = FindElement("yaw");
466 value = item->GetDataAsNumber();
467 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
470 cerr << "Could not find a Z triplet item for this column vector." << endl;
477 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
479 void Element::Print(unsigned int level)
481 unsigned int i, spaces;
484 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
485 cout << "Element Name: " << name;
486 for (i=0; i<attributes.size(); i++) {
487 cout << " " << attribute_key[i] << " = " << attributes[attribute_key[i]];
490 for (i=0; i<data_lines.size(); i++) {
491 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
492 cout << data_lines[i] << endl;
494 for (i=0; i<children.size(); i++) {
495 children[i]->Print(level);
499 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
501 void Element::AddAttribute(string name, string value)
503 attribute_key.push_back(name);
504 attributes[name] = value;
507 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509 void Element::AddData(string d)
511 unsigned int string_start = (unsigned int)d.find_first_not_of(" \t");
512 if (string_start > 0) {
513 d.erase(0,string_start);
515 data_lines.push_back(d);
518 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
520 } // end namespace JSBSim