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