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