]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.cpp
Merge branch 'topic/tape' into next
[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
33 #include <cmath>
34 #include <cstdlib>
35
36 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
37 FORWARD DECLARATIONS
38 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
39
40 namespace JSBSim {
41
42 static const char *IdSrc = "$Id$";
43 static const char *IdHdr = ID_XMLELEMENT;
44
45 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
46 CLASS IMPLEMENTATION
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
48
49 Element::Element(string nm)
50 {
51   name   = nm;
52   parent = 0L;
53   element_index = 0;
54
55   // convert ["from"]["to"] = factor, so: from * factor = to
56   // Length
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"];
63   // Area
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"];
68   convert["FT2"]["IN2"] = 144.0;
69   convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"];
70   // Volume
71   convert["IN3"]["CC"] = 16.387064;
72   convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"];
73   convert["FT3"]["IN3"] = 1728.0;
74   convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"];
75   convert["M3"]["FT3"] = 35.3146667;
76   convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
77   convert["LTR"]["IN3"] = 61.0237441;
78   convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
79   // Mass & Weight
80   convert["LBS"]["KG"] = 0.45359237;
81   convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
82   convert["SLUG"]["KG"] = 14.59390;
83   convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"];
84   // Moments of Inertia
85   convert["SLUG*FT2"]["KG*M2"] = 1.35594;
86   convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
87   // Angles
88   convert["RAD"]["DEG"] = 360.0/(2.0*3.1415926);
89   convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
90   // Spring force
91   convert["LBS/FT"]["N/M"] = 14.5939;
92   convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
93   // Damping force
94   convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
95   convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
96   // Damping force (Square Law)
97   convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259;
98   convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"];
99   // Power
100   convert["WATTS"]["HP"] = 0.001341022;
101   convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
102   // Force
103   convert["N"]["LBS"] = 0.22482;
104   convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
105   // Velocity
106   convert["KTS"]["FT/SEC"] = 1.68781;
107   convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
108   convert["M/S"]["FT/S"] = 3.2808399;
109   convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
110   // Torque
111   convert["FT*LBS"]["N*M"] = 1.35581795;
112   convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
113   // Valve
114   convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]*
115     convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"];
116   convert["FT4*SEC/SLUG"]["M4*SEC/KG"] =
117     1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"];
118   // Pressure
119   convert["INHG"]["PSF"] = 70.7180803;
120   convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"];
121   convert["ATM"]["INHG"] = 29.9246899;
122   convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"];
123   convert["PSI"]["INHG"] = 2.03625437;
124   convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"];
125   convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals
126   convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"];
127   convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"];
128   convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"];
129   convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"];
130   convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
131   // Mass flow
132   convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
133   // Fuel Consumption
134   convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083;
135   convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"];
136
137   // Length
138   convert["M"]["M"] = 1.00;
139   convert["FT"]["FT"] = 1.00;
140   convert["IN"]["IN"] = 1.00;
141   // Area
142   convert["M2"]["M2"] = 1.00;
143   convert["FT2"]["FT2"] = 1.00;
144   // Volume
145   convert["IN3"]["IN3"] = 1.00;
146   convert["CC"]["CC"] = 1.0;
147   convert["M3"]["M3"] = 1.0;
148   convert["FT3"]["FT3"] = 1.0;
149   convert["LTR"]["LTR"] = 1.0;
150   // Mass & Weight
151   convert["KG"]["KG"] = 1.00;
152   convert["LBS"]["LBS"] = 1.00;
153   // Moments of Inertia
154   convert["KG*M2"]["KG*M2"] = 1.00;
155   convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
156   // Angles
157   convert["DEG"]["DEG"] = 1.00;
158   convert["RAD"]["RAD"] = 1.00;
159   // Spring force
160   convert["LBS/FT"]["LBS/FT"] = 1.00;
161   convert["N/M"]["N/M"] = 1.00;
162   // Damping force
163   convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
164   convert["N/M/SEC"]["N/M/SEC"] = 1.00;
165   // Damping force (Square law)
166   convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00;
167   convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00;
168   // Power
169   convert["HP"]["HP"] = 1.00;
170   convert["WATTS"]["WATTS"] = 1.00;
171   // Force
172   convert["N"]["N"] = 1.00;
173   // Velocity
174   convert["FT/SEC"]["FT/SEC"] = 1.00;
175   convert["KTS"]["KTS"] = 1.00;
176   convert["M/S"]["M/S"] = 1.0;
177   // Torque
178   convert["FT*LBS"]["FT*LBS"] = 1.00;
179   convert["N*M"]["N*M"] = 1.00;
180   // Valve
181   convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0;
182   convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0;
183   // Pressure
184   convert["PSI"]["PSI"] = 1.00;
185   convert["PSF"]["PSF"] = 1.00;
186   convert["INHG"]["INHG"] = 1.00;
187   convert["ATM"]["ATM"] = 1.0;
188   convert["PA"]["PA"] = 1.0;
189   convert["N/M2"]["N/M2"] = 1.00;
190   convert["LBS/FT2"]["LBS/FT2"] = 1.00;
191   // Mass flow
192   convert["LBS/SEC"]["LBS/SEC"] = 1.00;
193   convert["KG/MIN"]["KG/MIN"] = 1.0;
194   convert["LBS/MIN"]["LBS/MIN"] = 1.0;
195   // Fuel Consumption
196   convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0;
197   convert["KG/KW*HR"]["KG/KW*HR"] = 1.0;
198 }
199
200 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201
202 Element::~Element(void)
203 {
204   for (unsigned int i=0; i<children.size(); i++) delete children[i];
205   data_lines.clear();
206   attributes.clear();
207   attribute_key.clear();
208 }
209
210 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
211
212 string Element::GetAttributeValue(string attr)
213 {
214   int select=-1;
215   for (unsigned int i=0; i<attribute_key.size(); i++) {
216     if (attribute_key[i] == attr) select = i;
217   }
218   if (select < 0) return string("");
219   else return attributes[attr];
220 }
221
222 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223
224 double Element::GetAttributeValueAsNumber(string attr)
225 {
226   string attribute = GetAttributeValue(attr);
227
228   if (attribute.empty()) return HUGE_VAL;
229   else return (atof(attribute.c_str()));
230 }
231
232 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233
234 Element* Element::GetElement(unsigned int el)
235 {
236   if (children.size() > el) {
237     element_index = el;
238     return children[el];
239   }
240   else {
241     element_index = 0;
242     return 0L;
243   }
244 }
245
246 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247
248 Element* Element::GetNextElement(void)
249 {
250   if (children.size() > element_index+1) {
251     element_index++;
252     return children[element_index];
253   } else {
254     element_index = 0;
255     return 0L;
256   }
257 }
258
259 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260
261 string Element::GetDataLine(unsigned int i)
262 {
263   if (data_lines.size() > 0) return data_lines[i];
264   else return string("");
265 }
266
267 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
268
269 double Element::GetDataAsNumber(void)
270 {
271   if (data_lines.size() == 1) {
272     return atof(data_lines[0].c_str());
273   } else if (data_lines.size() == 0) {
274     return HUGE_VAL;
275   } else {
276     cerr << "Attempting to get single data value from multiple lines in element " << name << endl;
277     return HUGE_VAL;
278   }
279 }
280
281 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
282
283 unsigned int Element::GetNumElements(string element_name)
284 {
285   unsigned int number_of_elements=0;
286   Element* el=FindElement(element_name);
287   while (el) {
288     number_of_elements++;
289     el=FindNextElement(element_name);
290   }
291   return number_of_elements;
292 }
293
294 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295
296 Element* Element::FindElement(string el)
297 {
298   if (el.empty() && children.size() >= 1) {
299     element_index = 1;
300     return children[0];
301   }
302   for (unsigned int i=0; i<children.size(); i++) {
303     if (el == children[i]->GetName()) {
304       element_index = i+1;
305       return children[i];
306     }
307   }
308   element_index = 0;
309   return 0L;
310 }
311
312 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
313
314 Element* Element::FindNextElement(string el)
315 {
316   if (el.empty()) {
317     if (element_index < children.size()) {
318       return children[element_index++];
319     } else {
320       element_index = 0;
321       return 0L;
322     }
323   }
324   for (unsigned int i=element_index; i<children.size(); i++) {
325     if (el == children[i]->GetName()) {
326       element_index = i+1;
327       return children[i];
328     }
329   }
330   element_index = 0;
331   return 0L;
332 }
333
334 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
335
336 double Element::FindElementValueAsNumber(string el)
337 {
338   Element* element = FindElement(el);
339   if (element) {
340     return element->GetDataAsNumber();
341   } else {
342     cerr << "Attempting to get single data value from multiple lines" << endl;
343     return 0;
344   }
345 }
346
347 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
348
349 string Element::FindElementValue(string el)
350 {
351   Element* element = FindElement(el);
352   if (element) {
353     return element->GetDataLine();
354   } else {
355     return "";
356   }
357 }
358
359 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
360
361 double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
362 {
363   Element* element = FindElement(el);
364
365   if (!element) {
366     cerr << "Attempting to get non-existent element " << el << endl;
367     exit(0);
368   }
369
370   string supplied_units = element->GetAttributeValue("unit");
371
372   if (!supplied_units.empty()) {
373     if (convert.find(supplied_units) == convert.end()) {
374       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
375            << " conversion in FGXMLElement.cpp." << endl;
376       exit(-1);
377     }
378     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
379       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
380                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
381       exit(-1);
382     }
383   }
384
385   double value = element->GetDataAsNumber();
386   if (!supplied_units.empty()) {
387     value *= convert[supplied_units][target_units];
388   }
389
390   return value;
391 }
392
393 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
394
395 double Element::FindElementValueAsNumberConvertFromTo( string el,
396                                                        string supplied_units,
397                                                        string target_units)
398 {
399   Element* element = FindElement(el);
400
401   if (!element) {
402     cerr << "Attempting to get non-existent element " << el << endl;
403     exit(0);
404   }
405
406   if (!supplied_units.empty()) {
407     if (convert.find(supplied_units) == convert.end()) {
408       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
409            << " conversion in FGXMLElement.cpp." << endl;
410       exit(-1);
411     }
412     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
413       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
414                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
415       exit(-1);
416     }
417   }
418
419   double value = element->GetDataAsNumber();
420   if (!supplied_units.empty()) {
421     value *= convert[supplied_units][target_units];
422   }
423
424   return value;
425 }
426
427 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428
429 FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
430 {
431   FGColumnVector3 triplet;
432   Element* item;
433   double value=0.0;
434   string supplied_units = GetAttributeValue("unit");
435
436   if (!supplied_units.empty()) {
437     if (convert.find(supplied_units) == convert.end()) {
438       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
439            << " conversion in FGXMLElement.cpp." << endl;
440       exit(-1);
441     }
442     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
443       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
444                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
445       exit(-1);
446     }
447   }
448
449   item = FindElement("x");
450   if (!item) item = FindElement("roll");
451   if (item) {
452     value = item->GetDataAsNumber();
453     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
454   } else {
455     value = 0.0;
456     cerr << "Could not find an X triplet item for this column vector." << endl;
457   }
458   triplet(1) = value;
459
460   item = FindElement("y");
461   if (!item) item = FindElement("pitch");
462   if (item) {
463     value = item->GetDataAsNumber();
464     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
465   } else {
466     value = 0.0;
467     cerr << "Could not find a Y triplet item for this column vector." << endl;
468   }
469   triplet(2) = value;
470
471   item = FindElement("z");
472   if (!item) item = FindElement("yaw");
473   if (item) {
474     value = item->GetDataAsNumber();
475     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
476   } else {
477     value = 0.0;
478     cerr << "Could not find a Z triplet item for this column vector." << endl;
479   }
480   triplet(3) = value;
481
482   return triplet;
483 }
484
485 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
486
487 void Element::Print(unsigned int level)
488 {
489   unsigned int i, spaces;
490
491   level+=2;
492   for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
493   cout << "Element Name: " << name;
494   for (i=0; i<attributes.size(); i++) {
495     cout << "  " << attribute_key[i] << " = " << attributes[attribute_key[i]];
496   }
497   cout << endl;
498   for (i=0; i<data_lines.size(); i++) {
499     for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
500     cout << data_lines[i] << endl;
501   }
502   for (i=0; i<children.size(); i++) {
503     children[i]->Print(level);
504   }
505 }
506
507 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
508
509 void Element::AddAttribute(string name, string value)
510 {
511   attribute_key.push_back(name);
512   attributes[name] = value;
513 }
514
515 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
516
517 void Element::AddData(string d)
518 {
519   unsigned int string_start = (unsigned int)d.find_first_not_of(" \t");
520   if (string_start > 0) {
521     d.erase(0,string_start);
522   }
523   data_lines.push_back(d);
524 }
525
526 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
527
528 } // end namespace JSBSim