]> git.mxchange.org Git - flightgear.git/blob - src/FDM/JSBSim/input_output/FGXMLElement.cpp
Fix for bug 1304 - crash loading XML route
[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 (jon@jsbsim.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 <cmath>
32 #include <cstdlib>
33 #include <iostream>
34 #include <sstream>
35
36 #include "FGXMLElement.h"
37 #include "string_utilities.h"
38
39 using namespace std;
40
41 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 FORWARD DECLARATIONS
43 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
44
45 namespace JSBSim {
46
47 IDENT(IdSrc,"$Id: FGXMLElement.cpp,v 1.45 2014/01/13 10:46:02 ehofman Exp $");
48 IDENT(IdHdr,ID_XMLELEMENT);
49
50 bool Element::converterIsInitialized = false;
51 map <string, map <string, double> > Element::convert;
52
53 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
54 CLASS IMPLEMENTATION
55 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
56
57 Element::Element(const string& nm)
58 {
59   name   = nm;
60   parent = 0L;
61   element_index = 0;
62   line_number = -1;
63
64   if (!converterIsInitialized) {
65     converterIsInitialized = true;
66     // convert ["from"]["to"] = factor, so: from * factor = to
67     // Length
68     convert["M"]["FT"] = 3.2808399;
69     convert["FT"]["M"] = 1.0/convert["M"]["FT"];
70     convert["CM"]["FT"] = 0.032808399;
71     convert["FT"]["CM"] = 1.0/convert["CM"]["FT"];
72     convert["KM"]["FT"] = 3280.8399;
73     convert["FT"]["KM"] = 1.0/convert["KM"]["FT"];
74     convert["FT"]["IN"] = 12.0;
75     convert["IN"]["FT"] = 1.0/convert["FT"]["IN"];
76     convert["IN"]["M"] = convert["IN"]["FT"] * convert["FT"]["M"];
77     convert["M"]["IN"] = convert["M"]["FT"] * convert["FT"]["IN"];
78     // Area
79     convert["M2"]["FT2"] = convert["M"]["FT"]*convert["M"]["FT"];
80     convert["FT2"]["M2"] = 1.0/convert["M2"]["FT2"];
81     convert["CM2"]["FT2"] = convert["CM"]["FT"]*convert["CM"]["FT"];
82     convert["FT2"]["CM2"] = 1.0/convert["CM2"]["FT2"];
83     convert["M2"]["IN2"] = convert["M"]["IN"]*convert["M"]["IN"];
84     convert["IN2"]["M2"] = 1.0/convert["M2"]["IN2"];
85     convert["FT2"]["IN2"] = 144.0;
86     convert["IN2"]["FT2"] = 1.0/convert["FT2"]["IN2"];
87     // Volume
88     convert["IN3"]["CC"] = 16.387064;
89     convert["CC"]["IN3"] = 1.0/convert["IN3"]["CC"];
90     convert["FT3"]["IN3"] = 1728.0;
91     convert["IN3"]["FT3"] = 1.0/convert["FT3"]["IN3"];
92     convert["M3"]["FT3"] = 35.3146667;
93     convert["FT3"]["M3"] = 1.0/convert["M3"]["FT3"];
94     convert["LTR"]["IN3"] = 61.0237441;
95     convert["IN3"]["LTR"] = 1.0/convert["LTR"]["IN3"];
96     // Mass & Weight
97     convert["LBS"]["KG"] = 0.45359237;
98     convert["KG"]["LBS"] = 1.0/convert["LBS"]["KG"];
99     convert["SLUG"]["KG"] = 14.59390;
100     convert["KG"]["SLUG"] = 1.0/convert["SLUG"]["KG"];
101     // Moments of Inertia
102     convert["SLUG*FT2"]["KG*M2"] = 1.35594;
103     convert["KG*M2"]["SLUG*FT2"] = 1.0/convert["SLUG*FT2"]["KG*M2"];
104     // Angles
105     convert["RAD"]["DEG"] = 180.0/M_PI;
106     convert["DEG"]["RAD"] = 1.0/convert["RAD"]["DEG"];
107     // Angular rates
108     convert["RAD/SEC"]["DEG/SEC"] = convert["RAD"]["DEG"];
109     convert["DEG/SEC"]["RAD/SEC"] = 1.0/convert["RAD/SEC"]["DEG/SEC"];
110     // Spring force
111     convert["LBS/FT"]["N/M"] = 14.5939;
112     convert["N/M"]["LBS/FT"] = 1.0/convert["LBS/FT"]["N/M"];
113     // Damping force
114     convert["LBS/FT/SEC"]["N/M/SEC"] = 14.5939;
115     convert["N/M/SEC"]["LBS/FT/SEC"] = 1.0/convert["LBS/FT/SEC"]["N/M/SEC"];
116     // Damping force (Square Law)
117     convert["LBS/FT2/SEC2"]["N/M2/SEC2"] = 47.880259;
118     convert["N/M2/SEC2"]["LBS/FT2/SEC2"] = 1.0/convert["LBS/FT2/SEC2"]["N/M2/SEC2"];
119     // Power
120     convert["WATTS"]["HP"] = 0.001341022;
121     convert["HP"]["WATTS"] = 1.0/convert["WATTS"]["HP"];
122     // Force
123     convert["N"]["LBS"] = 0.22482;
124     convert["LBS"]["N"] = 1.0/convert["N"]["LBS"];
125     // Velocity
126     convert["KTS"]["FT/SEC"] = 1.68781;
127     convert["FT/SEC"]["KTS"] = 1.0/convert["KTS"]["FT/SEC"];
128     convert["M/S"]["FT/S"] = 3.2808399;
129     convert["M/SEC"]["FT/SEC"] = 3.2808399;
130     convert["FT/S"]["M/S"] = 1.0/convert["M/S"]["FT/S"];
131     convert["M/SEC"]["FT/SEC"] = 3.2808399;
132     convert["FT/SEC"]["M/SEC"] = 1.0/convert["M/SEC"]["FT/SEC"];
133     convert["KM/SEC"]["FT/SEC"] = 3280.8399;
134     convert["FT/SEC"]["KM/SEC"] = 1.0/convert["KM/SEC"]["FT/SEC"];
135     // Torque
136     convert["FT*LBS"]["N*M"] = 1.35581795;
137     convert["N*M"]["FT*LBS"] = 1/convert["FT*LBS"]["N*M"];
138     // Valve
139     convert["M4*SEC/KG"]["FT4*SEC/SLUG"] = convert["M"]["FT"]*convert["M"]["FT"]*
140       convert["M"]["FT"]*convert["M"]["FT"]/convert["KG"]["SLUG"];
141     convert["FT4*SEC/SLUG"]["M4*SEC/KG"] =
142       1.0/convert["M4*SEC/KG"]["FT4*SEC/SLUG"];
143     // Pressure
144     convert["INHG"]["PSF"] = 70.7180803;
145     convert["PSF"]["INHG"] = 1.0/convert["INHG"]["PSF"];
146     convert["ATM"]["INHG"] = 29.9246899;
147     convert["INHG"]["ATM"] = 1.0/convert["ATM"]["INHG"];
148     convert["PSI"]["INHG"] = 2.03625437;
149     convert["INHG"]["PSI"] = 1.0/convert["PSI"]["INHG"];
150     convert["INHG"]["PA"] = 3386.0; // inches Mercury to pascals
151     convert["PA"]["INHG"] = 1.0/convert["INHG"]["PA"];
152     convert["LBS/FT2"]["N/M2"] = 14.5939/convert["FT"]["M"];
153     convert["N/M2"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["N/M2"];
154     convert["LBS/FT2"]["PA"] = convert["LBS/FT2"]["N/M2"];
155     convert["PA"]["LBS/FT2"] = 1.0/convert["LBS/FT2"]["PA"];
156     // Mass flow
157     convert["KG/MIN"]["LBS/MIN"] = convert["KG"]["LBS"];
158     // Fuel Consumption
159     convert["LBS/HP*HR"]["KG/KW*HR"] = 0.6083;
160     convert["KG/KW*HR"]["LBS/HP*HR"] = 1.0/convert["LBS/HP*HR"]["KG/KW*HR"];
161     // Density
162     convert["KG/L"]["LBS/GAL"] = 8.3454045;
163     convert["LBS/GAL"]["KG/L"] = 1.0/convert["KG/L"]["LBS/GAL"];
164
165     // Length
166     convert["M"]["M"] = 1.00;
167     convert["KM"]["KM"] = 1.00;
168     convert["FT"]["FT"] = 1.00;
169     convert["IN"]["IN"] = 1.00;
170     // Area
171     convert["M2"]["M2"] = 1.00;
172     convert["FT2"]["FT2"] = 1.00;
173     // Volume
174     convert["IN3"]["IN3"] = 1.00;
175     convert["CC"]["CC"] = 1.0;
176     convert["M3"]["M3"] = 1.0;
177     convert["FT3"]["FT3"] = 1.0;
178     convert["LTR"]["LTR"] = 1.0;
179     // Mass & Weight
180     convert["KG"]["KG"] = 1.00;
181     convert["LBS"]["LBS"] = 1.00;
182     // Moments of Inertia
183     convert["KG*M2"]["KG*M2"] = 1.00;
184     convert["SLUG*FT2"]["SLUG*FT2"] = 1.00;
185     // Angles
186     convert["DEG"]["DEG"] = 1.00;
187     convert["RAD"]["RAD"] = 1.00;
188     // Angular rates
189     convert["DEG/SEC"]["DEG/SEC"] = 1.00;
190     convert["RAD/SEC"]["RAD/SEC"] = 1.00;
191     // Spring force
192     convert["LBS/FT"]["LBS/FT"] = 1.00;
193     convert["N/M"]["N/M"] = 1.00;
194     // Damping force
195     convert["LBS/FT/SEC"]["LBS/FT/SEC"] = 1.00;
196     convert["N/M/SEC"]["N/M/SEC"] = 1.00;
197     // Damping force (Square law)
198     convert["LBS/FT2/SEC2"]["LBS/FT2/SEC2"] = 1.00;
199     convert["N/M2/SEC2"]["N/M2/SEC2"] = 1.00;
200     // Power
201     convert["HP"]["HP"] = 1.00;
202     convert["WATTS"]["WATTS"] = 1.00;
203     // Force
204     convert["N"]["N"] = 1.00;
205     // Velocity
206     convert["FT/SEC"]["FT/SEC"] = 1.00;
207     convert["KTS"]["KTS"] = 1.00;
208     convert["M/S"]["M/S"] = 1.0;
209     convert["M/SEC"]["M/SEC"] = 1.0;
210     convert["KM/SEC"]["KM/SEC"] = 1.0;
211     // Torque
212     convert["FT*LBS"]["FT*LBS"] = 1.00;
213     convert["N*M"]["N*M"] = 1.00;
214     // Valve
215     convert["M4*SEC/KG"]["M4*SEC/KG"] = 1.0;
216     convert["FT4*SEC/SLUG"]["FT4*SEC/SLUG"] = 1.0;
217     // Pressure
218     convert["PSI"]["PSI"] = 1.00;
219     convert["PSF"]["PSF"] = 1.00;
220     convert["INHG"]["INHG"] = 1.00;
221     convert["ATM"]["ATM"] = 1.0;
222     convert["PA"]["PA"] = 1.0;
223     convert["N/M2"]["N/M2"] = 1.00;
224     convert["LBS/FT2"]["LBS/FT2"] = 1.00;
225     // Mass flow
226     convert["LBS/SEC"]["LBS/SEC"] = 1.00;
227     convert["KG/MIN"]["KG/MIN"] = 1.0;
228     convert["LBS/MIN"]["LBS/MIN"] = 1.0;
229     // Fuel Consumption
230     convert["LBS/HP*HR"]["LBS/HP*HR"] = 1.0;
231     convert["KG/KW*HR"]["KG/KW*HR"] = 1.0;
232     // Density
233     convert["KG/L"]["KG/L"] = 1.0;
234     convert["LBS/GAL"]["LBS/GAL"] = 1.0;
235   }
236 }
237
238 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
239
240 Element::~Element(void)
241 {
242   for (unsigned int i=0; i<children.size(); i++) delete children[i];
243   data_lines.clear();
244   attributes.clear();
245 }
246
247 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248
249 string Element::GetAttributeValue(const string& attr)
250 {
251   if (HasAttribute(attr))  return attributes[attr];
252   else                     return ("");
253 }
254
255 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
256
257 bool Element::HasAttribute(const string& attr)
258 {
259   map<string, string>::iterator found = attributes.find(attr);
260
261   return found != attributes.end();
262 }
263
264 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
265
266 double Element::GetAttributeValueAsNumber(const string& attr)
267 {
268   string attribute = GetAttributeValue(attr);
269
270   if (attribute.empty()) {
271     cerr << ReadFrom() << "Expecting numeric attribute value, but got no data"
272          << endl;
273     exit(-1);
274   }
275   else {
276     double number=0;
277     if (is_number(trim(attribute)))
278       number = atof(attribute.c_str());
279     else {
280       cerr << ReadFrom() << "Expecting numeric attribute value, but got: "
281            << attribute << endl;
282       exit(-1);
283     }
284     
285     return (number);
286   }
287 }
288
289 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
290
291 Element* Element::GetElement(unsigned int el)
292 {
293   if (children.size() > el) {
294     element_index = el;
295     return children[el];
296   }
297   else {
298     element_index = 0;
299     return 0L;
300   }
301 }
302
303 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304
305 Element* Element::GetNextElement(void)
306 {
307   if (children.size() > element_index+1) {
308     element_index++;
309     return children[element_index];
310   } else {
311     element_index = 0;
312     return 0L;
313   }
314 }
315
316 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317
318 string Element::GetDataLine(unsigned int i)
319 {
320   if (data_lines.size() > 0) return data_lines[i];
321   else return string("");
322 }
323
324 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325
326 double Element::GetDataAsNumber(void)
327 {
328   if (data_lines.size() == 1) {
329     double number=0;
330     if (is_number(trim(data_lines[0])))
331       number = atof(data_lines[0].c_str());
332     else {
333       cerr << ReadFrom() << "Expected numeric value, but got: " << data_lines[0]
334            << endl;
335       exit(-1);
336     }
337
338     return number;
339   } else if (data_lines.size() == 0) {
340     cerr << ReadFrom() << "Expected numeric value, but got no data" << endl;
341     exit(-1);
342   } else {
343     cerr << ReadFrom() << "Attempting to get single data value in element "
344          << "<" << name << ">" << endl
345          << " from multiple lines:" << endl;
346     for(unsigned int i=0; i<data_lines.size(); ++i)
347       cerr << data_lines[i] << endl;
348     exit(-1);
349   }
350 }
351
352 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
353
354 unsigned int Element::GetNumElements(const string& element_name)
355 {
356   unsigned int number_of_elements=0;
357   Element* el=FindElement(element_name);
358   while (el) {
359     number_of_elements++;
360     el=FindNextElement(element_name);
361   }
362   return number_of_elements;
363 }
364
365 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
366
367 Element* Element::FindElement(const string& el)
368 {
369   if (el.empty() && children.size() >= 1) {
370     element_index = 1;
371     return children[0];
372   }
373   for (unsigned int i=0; i<children.size(); i++) {
374     if (el == children[i]->GetName()) {
375       element_index = i+1;
376       return children[i];
377     }
378   }
379   element_index = 0;
380   return 0L;
381 }
382
383 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384
385 Element* Element::FindNextElement(const string& el)
386 {
387   if (el.empty()) {
388     if (element_index < children.size()) {
389       return children[element_index++];
390     } else {
391       element_index = 0;
392       return 0L;
393     }
394   }
395   for (unsigned int i=element_index; i<children.size(); i++) {
396     if (el == children[i]->GetName()) {
397       element_index = i+1;
398       return children[i];
399     }
400   }
401   element_index = 0;
402   return 0L;
403 }
404
405 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
406
407 double Element::FindElementValueAsNumber(const string& el)
408 {
409   Element* element = FindElement(el);
410   if (element) {
411     double value = element->GetDataAsNumber();
412     value = DisperseValue(element, value);
413     return value;
414   } else {
415     cerr << ReadFrom() << "Attempting to get non-existent element " << el
416          << endl;
417     exit(-1);
418   }
419 }
420
421 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
422
423 string Element::FindElementValue(const string& el)
424 {
425   Element* element = FindElement(el);
426   if (element) {
427     return element->GetDataLine();
428   } else {
429     return "";
430   }
431 }
432
433 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434
435 double Element::FindElementValueAsNumberConvertTo(const string& el, const string& target_units)
436 {
437   Element* element = FindElement(el);
438
439   if (!element) {
440     cerr << ReadFrom() << "Attempting to get non-existent element " << el
441          << endl;
442     exit(-1);
443   }
444
445   string supplied_units = element->GetAttributeValue("unit");
446
447   if (!supplied_units.empty()) {
448     if (convert.find(supplied_units) == convert.end()) {
449       cerr << element->ReadFrom() << "Supplied unit: \""
450            << supplied_units << "\" does not exist (typo?)." << endl;
451       exit(-1);
452     }
453     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
454       cerr << element->ReadFrom() << "Supplied unit: \""
455            << supplied_units << "\" cannot be converted to " << target_units
456            << endl;
457       exit(-1);
458     }
459   }
460
461   double value = element->GetDataAsNumber();
462   if (!supplied_units.empty()) {
463     value *= convert[supplied_units][target_units];
464   }
465
466   value = DisperseValue(element, value, supplied_units, target_units);
467
468   return value;
469 }
470
471 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
472
473 double Element::FindElementValueAsNumberConvertFromTo( const string& el,
474                                                        const string& supplied_units,
475                                                        const string& target_units)
476 {
477   Element* element = FindElement(el);
478
479   if (!element) {
480     cerr << "Attempting to get non-existent element " << el << endl;
481     exit(-1);
482   }
483
484   if (!supplied_units.empty()) {
485     if (convert.find(supplied_units) == convert.end()) {
486       cerr << element->ReadFrom() << "Supplied unit: \""
487            << supplied_units << "\" does not exist (typo?)." << endl;
488       exit(-1);
489     }
490     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
491       cerr << element->ReadFrom() << "Supplied unit: \""
492            << supplied_units << "\" cannot be converted to " << target_units
493            << endl;
494       exit(-1);
495     }
496   }
497
498   double value = element->GetDataAsNumber();
499   if (!supplied_units.empty()) {
500     value *= convert[supplied_units][target_units];
501   }
502
503   value = DisperseValue(element, value, supplied_units, target_units);
504
505   return value;
506 }
507
508 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
509
510 FGColumnVector3 Element::FindElementTripletConvertTo( const string& target_units)
511 {
512   FGColumnVector3 triplet;
513   Element* item;
514   double value=0.0;
515   string supplied_units = GetAttributeValue("unit");
516
517   if (!supplied_units.empty()) {
518     if (convert.find(supplied_units) == convert.end()) {
519       cerr << ReadFrom() << "Supplied unit: \""
520            << supplied_units << "\" does not exist (typo?)." << endl;
521       exit(-1);
522     }
523     if (convert[supplied_units].find(target_units) == convert[supplied_units].end()) {
524       cerr << ReadFrom() << "Supplied unit: \""
525            << supplied_units << "\" cannot be converted to " << target_units
526            << endl;
527       exit(-1);
528     }
529   }
530
531   item = FindElement("x");
532   if (!item) item = FindElement("roll");
533   if (item) {
534     value = item->GetDataAsNumber();
535     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
536     triplet(1) = DisperseValue(item, value, supplied_units, target_units);
537   } else {
538     triplet(1) = 0.0;
539   }
540   
541
542   item = FindElement("y");
543   if (!item) item = FindElement("pitch");
544   if (item) {
545     value = item->GetDataAsNumber();
546     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
547     triplet(2) = DisperseValue(item, value, supplied_units, target_units);
548   } else {
549     triplet(2) = 0.0;
550   }
551
552   item = FindElement("z");
553   if (!item) item = FindElement("yaw");
554   if (item) {
555     value = item->GetDataAsNumber();
556     if (!supplied_units.empty()) value *= convert[supplied_units][target_units];
557     triplet(3) = DisperseValue(item, value, supplied_units, target_units);
558   } else {
559     triplet(3) = 0.0;
560   }
561
562   return triplet;
563 }
564
565 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
566
567 double Element::DisperseValue(Element *e, double val, const std::string supplied_units, const std::string target_units)
568 {
569   double value=val;
570   double disp=0.0;
571   if (e->HasAttribute("dispersion")) {
572     disp = e->GetAttributeValueAsNumber("dispersion");
573     if (!supplied_units.empty()) disp *= convert[supplied_units][target_units];
574     string attType = e->GetAttributeValue("type");
575     if (attType == "gaussian") {
576       double grn = GaussianRandomNumber();
577       value = val + disp*grn;
578 /*      std::cout << "DISPERSION GAUSSIAN: Initial: " << val
579                 << "  Dispersion: " << disp
580                 << "  Gaussian Rand Num: " << grn
581                 << "  Total Dispersed Value: " << value << endl; */
582     } else if (attType == "uniform") {
583       double urn = ((((double)rand()/RAND_MAX)-0.5)*2.0);
584       value = val + disp * urn;
585 /*      std::cout << "DISPERSION UNIFORM: Initial: " << val
586                 << "  Dispersion: " << disp
587                 << "  Uniform Rand Num: " << urn
588                 << "  Total Dispersed Value: " << value << endl; */
589     } else {
590       cerr << ReadFrom() << "Unknown dispersion type" << attType << endl;
591       exit(-1);
592     }
593
594   }
595   return value;
596 }
597
598 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
599
600 double Element::GaussianRandomNumber(void)
601 {
602   static double V1, V2, S;
603   static int phase = 0;
604   double X;
605
606   if (phase == 0) {
607     V1 = V2 = S = X = 0.0;
608
609     do {
610       double U1 = (double)rand() / RAND_MAX;
611       double U2 = (double)rand() / RAND_MAX;
612
613       V1 = 2 * U1 - 1;
614       V2 = 2 * U2 - 1;
615       S = V1 * V1 + V2 * V2;
616     } while(S >= 1 || S == 0);
617
618     X = V1 * sqrt(-2 * log(S) / S);
619   } else
620     X = V2 * sqrt(-2 * log(S) / S);
621
622   phase = 1 - phase;
623
624   return X;
625 }
626
627 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
628
629 void Element::Print(unsigned int level)
630 {
631   unsigned int i, spaces;
632
633   level+=2;
634   for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
635   cout << "Element Name: " << name;
636
637   map<string, string>::iterator it;
638   for (it = attributes.begin(); it != attributes.end(); ++it)
639     cout << "  " << it->first << " = " << it->second;
640
641   cout << endl;
642   for (i=0; i<data_lines.size(); i++) {
643     for (spaces=0; spaces<=level; spaces++) cout << " "; // format output
644     cout << data_lines[i] << endl;
645   }
646   for (i=0; i<children.size(); i++) {
647     children[i]->Print(level);
648   }
649 }
650
651 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
652
653 void Element::AddAttribute(const string& name, const string& value)
654 {
655   attributes[name] = value;
656 }
657
658 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659
660 void Element::AddData(string d)
661 {
662   string::size_type string_start = d.find_first_not_of(" \t");
663   if (string_start != string::npos && string_start > 0) {
664     d.erase(0,string_start);
665   }
666   data_lines.push_back(d);
667 }
668
669 //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
670
671 string Element::ReadFrom(void) const
672 {
673   ostringstream message;
674
675   message << endl
676           << "In file " << GetFileName() << ": line " << GetLineNumber()
677           << endl;
678
679   return message.str();
680 }
681
682 } // end namespace JSBSim