]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.cpp
Clean up header file use of iostream and "using" declarations
[flightgear.git] / src / FDM / JSBSim / input_output / FGXMLElement.cpp
1 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2
3  Author:       Jon Berndt
4  Date started: 09/28/2004
5  Purpose:      XML element class
6  Called by:    FGXMLParse
7
8  ------------- Copyright (C) 2001  Jon S. Berndt (jsb@hal-pc.org) -------------
9
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
13  version.
14
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
18  details.
19
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.
23
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.
26
27 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
28 INCLUDES
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
30
31 #include "FGXMLElement.h"
32 #ifdef FGFS
33 #  ifndef __BORLANDC__
34 #    include <simgear/compiler.h>
35 #  endif
36 #  ifdef SG_HAVE_STD_INCLUDES
37 #    include <cmath>
38 #    include <cstdlib>
39 #  else
40 #    include <math.h>
41 #    include <stdlib.h>
42 #  endif
43 #else
44 #  if defined (sgi) && !defined(__GNUC__)
45 #    include <math.h>
46 #    include <stdlib.h>
47 #  else
48 #    include <cmath>
49 #    include <cstdlib>
50 #  endif
51 #endif
52
53 #include <stdlib.h>
54 #include <math.h>
55
56 #include <iostream>
57
58 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
59 FORWARD DECLARATIONS
60 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
61
62 namespace JSBSim {
63
64 static const char *IdSrc = "$Id$";
65 static const char *IdHdr = ID_XMLELEMENT;
66
67 using std::cerr;
68 using std::cout;
69 using std::endl;
70
71 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
72 CLASS IMPLEMENTATION
73 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
74
75 Element::Element(string nm)
76 {
77   name   = nm;
78   parent = 0L;
79   element_index = 0;
80
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"];
108
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;
137 }
138
139 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140
141 Element::~Element(void)
142 {
143   for (unsigned int i=0; i<children.size(); i++) delete children[i];
144   data_lines.clear();
145   attributes.clear();
146   attribute_key.clear();
147 }
148
149 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
150
151 string Element::GetAttributeValue(string attr)
152 {
153   int select=-1;
154   for (unsigned int i=0; i<attribute_key.size(); i++) {
155     if (attribute_key[i] == attr) select = i;
156   }
157   if (select < 0) return string("");
158   else return attributes[attr];
159 }
160
161 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
162
163 double Element::GetAttributeValueAsNumber(string attr)
164 {
165   string attribute = GetAttributeValue(attr);
166
167   if (attribute.empty()) return 99e99;
168   else return (atof(attribute.c_str()));
169 }
170
171 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172
173 Element* Element::GetElement(unsigned int el)
174 {
175   if (children.size() > el) {
176     element_index = el;
177     return children[el];
178   }
179   else {
180     element_index = 0;
181     return 0L;
182   }
183 }
184
185 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
186
187 Element* Element::GetNextElement(void)
188 {
189   if (children.size() > element_index+1) {
190     element_index++;
191     return children[element_index];
192   } else {
193     element_index = 0;
194     return 0L;
195   }
196 }
197
198 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
199
200 string Element::GetDataLine(unsigned int i)
201 {
202   if (data_lines.size() > 0) return data_lines[i];
203   else return string("");
204 }
205
206 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
207
208 double Element::GetDataAsNumber(void)
209 {
210   if (data_lines.size() == 1) {
211     return atof(data_lines[0].c_str());
212   } else {
213     cerr << "Attempting to get single data value from multiple lines" << endl;
214     return 0;
215   }
216 }
217
218 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
219
220 unsigned int Element::GetNumElements(string element_name)
221 {
222   unsigned int number_of_elements=0;
223   Element* el=FindElement(element_name);
224   while (el) {
225     number_of_elements++;
226     el=FindNextElement(element_name);
227   }
228   return number_of_elements;
229 }
230
231 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
232
233 Element* Element::FindElement(string el)
234 {
235   if (el.empty() && children.size() >= 1) {
236     element_index = 1;
237     return children[0];
238   }
239   for (unsigned int i=0; i<children.size(); i++) {
240     if (el == children[i]->GetName()) {
241       element_index = i+1;
242       return children[i];
243     }
244   }
245   element_index = 0;
246   return 0L;
247 }
248
249 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
250
251 Element* Element::FindNextElement(string el)
252 {
253   if (el.empty()) {
254     if (element_index < children.size()) {
255       return children[element_index++];
256     } else {
257       element_index = 0;
258       return 0L;
259     }
260   }
261   for (unsigned int i=element_index; i<children.size(); i++) {
262     if (el == children[i]->GetName()) {
263       element_index = i+1;
264       return children[i];
265     }
266   }
267   element_index = 0;
268   return 0L;
269 }
270
271 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
272
273 double Element::FindElementValueAsNumber(string el)
274 {
275   Element* element = FindElement(el);
276   if (element) {
277     return element->GetDataAsNumber();
278   } else {
279     cerr << "Attempting to get single data value from multiple lines" << endl;
280     return 0;
281   }
282 }
283
284 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
285
286 string Element::FindElementValue(string el)
287 {
288   Element* element = FindElement(el);
289   if (element) {
290     return element->GetDataLine();
291   } else {
292     return "";
293   }
294 }
295
296 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
297
298 double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
299 {
300   Element* element = FindElement(el);
301
302   if (!element) {
303     cerr << "Attempting to get non-existent element " << el << endl;
304     exit(0);
305   }
306
307   string supplied_units = element->GetAttributeValue("unit");
308
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;
313       exit(-1);
314     }
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;
318       exit(-1);
319     }
320   }
321
322   double value = element->GetDataAsNumber();
323   if (!supplied_units.empty()) {
324     value *= convert[supplied_units][target_units];
325   }
326
327   return value;
328 }
329
330 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
331
332 double Element::FindElementValueAsNumberConvertFromTo( string el,
333                                                        string supplied_units,
334                                                        string target_units)
335 {
336   Element* element = FindElement(el);
337   
338   if (!element) {
339     cerr << "Attempting to get non-existent element " << el << endl;
340     exit(0);
341   }
342   
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;
347       exit(-1);
348     }
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;
352       exit(-1);
353     }
354   }
355
356   double value = element->GetDataAsNumber();
357   if (!supplied_units.empty()) {
358     value *= convert[supplied_units][target_units];
359   }
360
361   return value;
362 }
363
364 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
365
366 FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
367 {
368   FGColumnVector3 triplet;
369   Element* item;
370   double value=0.0;
371   string supplied_units = GetAttributeValue("unit");
372
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;
377       exit(-1);
378     }
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;
382       exit(-1);
383     }
384   }
385
386   item = FindElement("x");
387   if (!item) item = FindElement("roll");
388   if (item) {
389     value = item->GetDataAsNumber();
390     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
391   } else {
392     value = 0.0;
393     cerr << "Could not find an X triplet item for this column vector." << endl;
394   }
395   triplet(1) = value;
396
397   item = FindElement("y");
398   if (!item) item = FindElement("pitch");
399   if (item) {
400     value = item->GetDataAsNumber();
401     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
402   } else {
403     value = 0.0;
404     cerr << "Could not find a Y triplet item for this column vector." << endl;
405   }
406   triplet(2) = value;
407
408   item = FindElement("z");
409   if (!item) item = FindElement("yaw");
410   if (item) {
411     value = item->GetDataAsNumber();
412     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
413   } else {
414     value = 0.0;
415     cerr << "Could not find a Z triplet item for this column vector." << endl;
416   }
417   triplet(3) = value;
418
419   return triplet;
420 }
421
422 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
423
424 void Element::Print(unsigned int level)
425 {
426   unsigned int i, spaces;
427
428   level+=2;
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]];
433   }
434   cout << endl;
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;
438   }
439   for (i=0; i<children.size(); i++) {
440     children[i]->Print(level);
441   }
442 }
443
444 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
445
446 void Element::AddAttribute(string name, string value)
447 {
448   attribute_key.push_back(name);
449   attributes[name] = value;
450 }
451
452 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
453
454 void Element::AddData(string d)
455 {
456   unsigned int string_start = (unsigned int)d.find_first_not_of(" \t");
457   if (string_start > 0) {
458     d.erase(0,string_start);
459   }
460   data_lines.push_back(d);
461 }
462
463 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
464
465 } // end namespace JSBSim