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"
34 # include <simgear/compiler.h>
36 # ifdef SG_HAVE_STD_INCLUDES
44 # if defined (sgi) && !defined(__GNUC__)
58 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
64 static const char *IdSrc = "$Id$";
65 static const char *IdHdr = ID_XMLELEMENT;
71 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
75 Element::Element(string nm)
81 // convert ["from"]["to"] = factor, so: from * factor = to
82 convert["M"]["FT"] = 3.2808399;
83 convert["FT"]["M"] = 1.0/convert["M"]["FT"];
84 convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
85 convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
86 convert["FT"]["IN"] = 12.0;
87 convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
88 convert["LBS"]["KG"] = 0.45359237;
89 convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
90 convert["SLUG*FT2"]["KG*M2"] = 1.35594;
91 convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
92 convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
93 convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
94 convert["LBS/FT"]["N/M"] = 14.5939;
95 convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
96 convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
97 convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
98 convert["WATTS"]["HP"] = 0.001341022;
99 convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
100 convert["N"]["LBS"] = 0.22482;
101 convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
102 convert["KTS"]["FT/SEC"] = 1.68781;
103 convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
104 convert["FT*LBS"]["N*M"] = 1.35581795;
105 convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
106 convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
107 convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
109 convert["M"]["M"] = 1.00;
110 convert["FT"]["FT"] = 1.00;
111 convert["IN"]["IN"] = 1.00;
112 convert["IN3"]["IN3"] = 1.00;
113 convert["DEG"]["DEG"] = 1.00;
114 convert["RAD"]["RAD"] = 1.00;
115 convert["M2"]["M2"] = 1.00;
116 convert["FT2"]["FT2"] = 1.00;
117 convert["KG*M2"]["KG*M2"] = 1.00;
118 convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
119 convert["KG"]["KG"] = 1.00;
120 convert["LBS"]["LBS"] = 1.00;
121 convert["LBS/FT"]["LBS/FT"] = 1.00;
122 convert["LBS/SEC"]["LBS/SEC"] = 1.00;
123 convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
124 convert["N/M"]["N/M"] = 1.00;
125 convert["N/M/SEC"]["N/M/SEC"] = 1.00;
126 convert["PSI"]["PSI"] = 1.00;
127 convert["PSF"]["PSF"] = 1.00;
128 convert["INHG"]["INHG"] = 1.00;
129 convert["HP"]["HP"] = 1.00;
130 convert["N"]["N"] = 1.00;
131 convert["WATTS"]["WATTS"] = 1.00;
132 convert["LBS/SEC"]["LBS/SEC"] = 1.00;
133 convert["FT/SEC"]["FT/SEC"] = 1.00;
134 convert["KTS"]["KTS"] = 1.00;
135 convert["FT*LBS"]["FT*LBS"] = 1.00;
136 convert["N*M"]["N*M"] = 1.00;
139 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
141 Element::~Element(void)
143 for (unsigned int i=0; i<children.size(); i++) delete children[i];
146 attribute_key.clear();
149 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151 string Element::GetAttributeValue(string attr)
154 for (unsigned int i=0; i<attribute_key.size(); i++) {
155 if (attribute_key[i] == attr) select = i;
157 if (select < 0) return string("");
158 else return attributes[attr];
161 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
163 double Element::GetAttributeValueAsNumber(string attr)
165 string attribute = GetAttributeValue(attr);
167 if (attribute.empty()) return 99e99;
168 else return (atof(attribute.c_str()));
171 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
173 Element* Element::GetElement(unsigned int el)
175 if (children.size() > el) {
185 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
187 Element* Element::GetNextElement(void)
189 if (children.size() > element_index+1) {
191 return children[element_index];
198 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 string Element::GetDataLine(unsigned int i)
202 if (data_lines.size() > 0) return data_lines[i];
203 else return string("");
206 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
208 double Element::GetDataAsNumber(void)
210 if (data_lines.size() == 1) {
211 return atof(data_lines[0].c_str());
213 cerr << "Attempting to get single data value from multiple lines" << endl;
218 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220 unsigned int Element::GetNumElements(string element_name)
222 unsigned int number_of_elements=0;
223 Element* el=FindElement(element_name);
225 number_of_elements++;
226 el=FindNextElement(element_name);
228 return number_of_elements;
231 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233 Element* Element::FindElement(string el)
235 if (el.empty() && children.size() >= 1) {
239 for (unsigned int i=0; i<children.size(); i++) {
240 if (el == children[i]->GetName()) {
249 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251 Element* Element::FindNextElement(string el)
254 if (element_index < children.size()) {
255 return children[element_index++];
261 for (unsigned int i=element_index; i<children.size(); i++) {
262 if (el == children[i]->GetName()) {
271 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
273 double Element::FindElementValueAsNumber(string el)
275 Element* element = FindElement(el);
277 return element->GetDataAsNumber();
279 cerr << "Attempting to get single data value from multiple lines" << endl;
284 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286 string Element::FindElementValue(string el)
288 Element* element = FindElement(el);
290 return element->GetDataLine();
296 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
298 double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
300 Element* element = FindElement(el);
303 cerr << "Attempting to get non-existent element " << el << endl;
307 string supplied_units = element->GetAttributeValue("unit");
309 if (!supplied_units.empty()) {
310 if (convert.find(supplied_units) == convert.end()) {
311 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
312 << " conversion in FGXMLElement.cpp." << endl;
315 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
316 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
317 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
322 double value = element->GetDataAsNumber();
323 if (!supplied_units.empty()) {
324 value *= convert[supplied_units][target_units];
330 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 double Element::FindElementValueAsNumberConvertFromTo( string el,
333 string supplied_units,
336 Element* element = FindElement(el);
339 cerr << "Attempting to get non-existent element " << el << endl;
343 if (!supplied_units.empty()) {
344 if (convert.find(supplied_units) == convert.end()) {
345 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
346 << " conversion in FGXMLElement.cpp." << endl;
349 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
350 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
351 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
356 double value = element->GetDataAsNumber();
357 if (!supplied_units.empty()) {
358 value *= convert[supplied_units][target_units];
364 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366 FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
368 FGColumnVector3 triplet;
371 string supplied_units = GetAttributeValue("unit");
373 if (!supplied_units.empty()) {
374 if (convert.find(supplied_units) == convert.end()) {
375 cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
376 << " conversion in FGXMLElement.cpp." << endl;
379 if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
380 cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
381 << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
386 item = FindElement("x");
387 if (!item) item = FindElement("roll");
389 value = item->GetDataAsNumber();
390 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
393 cerr << "Could not find an X triplet item for this column vector." << endl;
397 item = FindElement("y");
398 if (!item) item = FindElement("pitch");
400 value = item->GetDataAsNumber();
401 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
404 cerr << "Could not find a Y triplet item for this column vector." << endl;
408 item = FindElement("z");
409 if (!item) item = FindElement("yaw");
411 value = item->GetDataAsNumber();
412 if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
415 cerr << "Could not find a Z triplet item for this column vector." << endl;
422 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
424 void Element::Print(unsigned int level)
426 unsigned int i, spaces;
429 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
430 cout << "Element Name: " << name;
431 for (i=0; i<attributes.size(); i++) {
432 cout << " " << attribute_key[i] << " = " << attributes[attribute_key[i]];
435 for (i=0; i<data_lines.size(); i++) {
436 for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
437 cout << data_lines[i] << endl;
439 for (i=0; i<children.size(); i++) {
440 children[i]->Print(level);
444 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
446 void Element::AddAttribute(string name, string value)
448 attribute_key.push_back(name);
449 attributes[name] = value;
452 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
454 void Element::AddData(string d)
456 unsigned int string_start = (unsigned int)d.find_first_not_of(" \t");
457 if (string_start > 0) {
458 d.erase(0,string_start);
460 data_lines.push_back(d);
463 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
465 } // end namespace JSBSim