]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.cpp
Sync w. JSBSim CVS (merge from PRE_OSG_PLIB_20061029 branch)
[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 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57 FORWARD DECLARATIONS
58 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
59
60 namespace JSBSim {
61
62 static const char *IdSrc = "$Id$";
63 static const char *IdHdr = ID_XMLELEMENT;
64
65 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
66 CLASS IMPLEMENTATION
67 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
68
69 Element::Element(string nm)
70 {
71   name   = nm;
72   parent = 0L;
73   element_index = 0;
74
75   // convert ["from"]["to"] = factor, so: from * factor = to
76   convert["M"]["FT"] = 3.2808399;
77   convert["FT"]["M"] = 1.0/convert["M"]["FT"];
78   convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
79   convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
80   convert["FT"]["IN"] = 12.0;
81   convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
82   convert["LBS"]["KG"] = 0.45359237;
83   convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
84   convert["SLUG*FT2"]["KG*M2"] = 1.35594;
85   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"];
88   convert["LBS/FT"]["N/M"] = 14.5939;
89   convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
90   convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
91   convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
92   convert["WATTS"]["HP"] = 0.001341022;
93   convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
94   convert["N"]["LBS"] = 0.22482;
95   convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
96   convert["KTS"]["FT/SEC"] = 1.68781;
97   convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
98   convert["FT*LBS"]["N*M"] = 1.35581795;
99   convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
100   convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
101   convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
102
103   convert["M"]["M"] = 1.00;
104   convert["FT"]["FT"] = 1.00;
105   convert["IN"]["IN"] = 1.00;
106   convert["IN3"]["IN3"] = 1.00;
107   convert["DEG"]["DEG"] = 1.00;
108   convert["RAD"]["RAD"] = 1.00;
109   convert["M2"]["M2"] = 1.00;
110   convert["FT2"]["FT2"] = 1.00;
111   convert["KG*M2"]["KG*M2"] = 1.00;
112   convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
113   convert["KG"]["KG"] = 1.00;
114   convert["LBS"]["LBS"] = 1.00;
115   convert["LBS/FT"]["LBS/FT"] = 1.00;
116   convert["LBS/SEC"]["LBS/SEC"] = 1.00;
117   convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
118   convert["N/M"]["N/M"] = 1.00;
119   convert["N/M/SEC"]["N/M/SEC"] = 1.00;
120   convert["PSI"]["PSI"] = 1.00;
121   convert["PSF"]["PSF"] = 1.00;
122   convert["INHG"]["INHG"] = 1.00;
123   convert["HP"]["HP"] = 1.00;
124   convert["N"]["N"] = 1.00;
125   convert["WATTS"]["WATTS"] = 1.00;
126   convert["LBS/SEC"]["LBS/SEC"] = 1.00;
127   convert["FT/SEC"]["FT/SEC"] = 1.00;
128   convert["KTS"]["KTS"] = 1.00;
129   convert["FT*LBS"]["FT*LBS"] = 1.00;
130   convert["N*M"]["N*M"] = 1.00;
131 }
132
133 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
134
135 Element::~Element(void)
136 {
137   for (unsigned int i=0; i<children.size(); i++) delete children[i];
138   data_lines.clear();
139   attributes.clear();
140   attribute_key.clear();
141 }
142
143 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144
145 string Element::GetAttributeValue(string attr)
146 {
147   int select=-1;
148   for (unsigned int i=0; i<attribute_key.size(); i++) {
149     if (attribute_key[i] == attr) select = i;
150   }
151   if (select < 0) return string("");
152   else return attributes[attr];
153 }
154
155 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
156
157 double Element::GetAttributeValueAsNumber(string attr)
158 {
159   string attribute = GetAttributeValue(attr);
160
161   if (attribute.empty()) return 99e99;
162   else return (atof(attribute.c_str()));
163 }
164
165 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
166
167 Element* Element::GetElement(unsigned int el)
168 {
169   if (children.size() > el) {
170     element_index = el;
171     return children[el];
172   }
173   else {
174     element_index = 0;
175     return 0L;
176   }
177 }
178
179 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180
181 Element* Element::GetNextElement(void)
182 {
183   if (children.size() > element_index+1) {
184     element_index++;
185     return children[element_index];
186   } else {
187     element_index = 0;
188     return 0L;
189   }
190 }
191
192 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
193
194 string Element::GetDataLine(unsigned int i)
195 {
196   if (data_lines.size() > 0) return data_lines[i];
197   else return string("");
198 }
199
200 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
201
202 double Element::GetDataAsNumber(void)
203 {
204   if (data_lines.size() == 1) {
205     return atof(data_lines[0].c_str());
206   } else {
207     cerr << "Attempting to get single data value from multiple lines" << endl;
208     return 0;
209   }
210 }
211
212 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213
214 unsigned int Element::GetNumElements(string element_name)
215 {
216   unsigned int number_of_elements=0;
217   Element* el=FindElement(element_name);
218   while (el) {
219     number_of_elements++;
220     el=FindNextElement(element_name);
221   }
222   return number_of_elements;
223 }
224
225 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
226
227 Element* Element::FindElement(string el)
228 {
229   if (el.empty() && children.size() >= 1) {
230     element_index = 1;
231     return children[0];
232   }
233   for (unsigned int i=0; i<children.size(); i++) {
234     if (el == children[i]->GetName()) {
235       element_index = i+1;
236       return children[i];
237     }
238   }
239   element_index = 0;
240   return 0L;
241 }
242
243 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244
245 Element* Element::FindNextElement(string el)
246 {
247   if (el.empty()) {
248     if (element_index < children.size()) {
249       return children[element_index++];
250     } else {
251       element_index = 0;
252       return 0L;
253     }
254   }
255   for (unsigned int i=element_index; i<children.size(); i++) {
256     if (el == children[i]->GetName()) {
257       element_index = i+1;
258       return children[i];
259     }
260   }
261   element_index = 0;
262   return 0L;
263 }
264
265 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
266
267 double Element::FindElementValueAsNumber(string el)
268 {
269   Element* element = FindElement(el);
270   if (element) {
271     return element->GetDataAsNumber();
272   } else {
273     cerr << "Attempting to get single data value from multiple lines" << endl;
274     return 0;
275   }
276 }
277
278 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
279
280 string Element::FindElementValue(string el)
281 {
282   Element* element = FindElement(el);
283   if (element) {
284     return element->GetDataLine();
285   } else {
286     return "";
287   }
288 }
289
290 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
291
292 double Element::FindElementValueAsNumberConvertTo(string el, string target_units)
293 {
294   Element* element = FindElement(el);
295
296   if (!element) {
297     cerr << "Attempting to get non-existent element " << el << endl;
298     exit(0);
299   }
300
301   string supplied_units = element->GetAttributeValue("unit");
302
303   if (!supplied_units.empty()) {
304     if (convert.find(supplied_units) == convert.end()) {
305       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
306            << " conversion in FGXMLElement.cpp." << endl;
307       exit(-1);
308     }
309     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
310       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
311                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
312       exit(-1);
313     }
314   }
315
316   double value = element->GetDataAsNumber();
317   if (!supplied_units.empty()) {
318     value *= convert[supplied_units][target_units];
319   }
320
321   return value;
322 }
323
324 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325
326 double Element::FindElementValueAsNumberConvertFromTo( string el,
327                                                        string supplied_units,
328                                                        string target_units)
329 {
330   Element* element = FindElement(el);
331   
332   if (!element) {
333     cerr << "Attempting to get non-existent element " << el << endl;
334     exit(0);
335   }
336   
337   if (!supplied_units.empty()) {
338     if (convert.find(supplied_units) == convert.end()) {
339       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
340            << " conversion in FGXMLElement.cpp." << endl;
341       exit(-1);
342     }
343     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
344       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
345                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
346       exit(-1);
347     }
348   }
349
350   double value = element->GetDataAsNumber();
351   if (!supplied_units.empty()) {
352     value *= convert[supplied_units][target_units];
353   }
354
355   return value;
356 }
357
358 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
359
360 FGColumnVector3 Element::FindElementTripletConvertTo( string target_units)
361 {
362   FGColumnVector3 triplet;
363   Element* item;
364   double value=0.0;
365   string supplied_units = GetAttributeValue("unit");
366
367   if (!supplied_units.empty()) {
368     if (convert.find(supplied_units) == convert.end()) {
369       cerr << endl << "Supplied unit: \"" << supplied_units << "\" does not exist (typo?). Add new unit"
370            << " conversion in FGXMLElement.cpp." << endl;
371       exit(-1);
372     }
373     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
374       cerr << endl << "Supplied unit: \"" << supplied_units << "\" cannot be converted to "
375                    << target_units << ". Add new unit conversion in FGXMLElement.cpp or fix typo" << endl;
376       exit(-1);
377     }
378   }
379
380   item = FindElement("x");
381   if (!item) item = FindElement("roll");
382   if (item) {
383     value = item->GetDataAsNumber();
384     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
385   } else {
386     value = 0.0;
387     cerr << "Could not find an X triplet item for this column vector." << endl;
388   }
389   triplet(1) = value;
390
391   item = FindElement("y");
392   if (!item) item = FindElement("pitch");
393   if (item) {
394     value = item->GetDataAsNumber();
395     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
396   } else {
397     value = 0.0;
398     cerr << "Could not find a Y triplet item for this column vector." << endl;
399   }
400   triplet(2) = value;
401
402   item = FindElement("z");
403   if (!item) item = FindElement("yaw");
404   if (item) {
405     value = item->GetDataAsNumber();
406     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
407   } else {
408     value = 0.0;
409     cerr << "Could not find a Z triplet item for this column vector." << endl;
410   }
411   triplet(3) = value;
412
413   return triplet;
414 }
415
416 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
417
418 void Element::Print(unsigned int level)
419 {
420   unsigned int i, spaces;
421
422   level+=2;
423   for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
424   cout << "Element Name: " << name;
425   for (i=0; i<attributes.size(); i++) {
426     cout << "  " << attribute_key[i] << " = " << attributes[attribute_key[i]];
427   }
428   cout << endl;
429   for (i=0; i<data_lines.size(); i++) {
430     for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
431     cout << data_lines[i] << endl;
432   }
433   for (i=0; i<children.size(); i++) {
434     children[i]->Print(level);
435   }
436 }
437
438 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
439
440 void Element::AddAttribute(string name, string value)
441 {
442   attribute_key.push_back(name);
443   attributes[name] = value;
444 }
445
446 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
447
448 void Element::AddData(string d)
449 {
450   unsigned int string_start = (unsigned int)d.find_first_not_of(" \t");
451   if (string_start > 0) {
452     d.erase(0,string_start);
453   }
454   data_lines.push_back(d);
455 }
456
457 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
458
459 } // end namespace JSBSim