]> git.mxchange.org Git - flightgear.git/blob - src/Airports/dynamicloader.cxx
Merge /u/edauvergne/flightgear/ branch lat_lon_precision_fix_v3 into next
[flightgear.git] / src / Airports / dynamicloader.cxx
1 // This program is free software; you can redistribute it and/or
2 // modify it under the terms of the GNU General Public License as
3 // published by the Free Software Foundation; either version 2 of the
4 // License, or (at your option) any later version.
5 //
6 // This program is distributed in the hope that it will be useful, but
7 // WITHOUT ANY WARRANTY; without even the implied warranty of
8 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9 // General Public License for more details.
10 //
11 // You should have received a copy of the GNU General Public License
12 // along with this program; if not, write to the Free Software
13 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
14 //
15
16 #ifdef HAVE_CONFIG_H
17 #  include <config.h>
18 #endif
19
20 #include <cstdlib>
21 #include <cstring> // for strcmp
22 #include <boost/foreach.hpp>
23
24 #include "dynamicloader.hxx"
25
26 #include <Navaids/NavDataCache.hxx>
27 #include <Airports/dynamics.hxx>
28 #include <Airports/airport.hxx>
29 #include <Airports/groundnetwork.hxx>
30
31 using std::string;
32
33 /*****************************************************************************
34  * Helper function for parsing position string
35  ****************************************************************************/
36 static double processPosition(const string &pos)
37 {
38   string prefix;
39   string subs;
40   string degree;
41   string decimal;
42   int sign = 1;
43   double value;
44   subs = pos;
45   prefix= subs.substr(0,1);
46   if (prefix == string("S") || (prefix == string("W")))
47     sign = -1;
48   subs    = subs.substr(1, subs.length());
49   degree  = subs.substr(0, subs.find(" ",0));
50   decimal = subs.substr(subs.find(" ",0), subs.length());
51   
52   value = sign * (atof(degree.c_str()) + atof(decimal.c_str())/60.0);
53   return value;
54 }
55
56 FGAirportDynamicsXMLLoader::FGAirportDynamicsXMLLoader(FGAirportDynamics* dyn):
57     XMLVisitor(), _dynamics(dyn)
58 {}
59
60 void  FGAirportDynamicsXMLLoader::startXML () {
61   //cout << "FGAirportDynamicsLoader::Start XML" << endl;
62 }
63
64 void  FGAirportDynamicsXMLLoader::endXML ()
65 {
66   ParkingPushbackIndex::const_iterator it;
67   
68   for (it = _parkingPushbacks.begin(); it != _parkingPushbacks.end(); ++it) {
69     NodeIndexMap::const_iterator j = _indexMap.find(it->second);
70     if (j == _indexMap.end()) {
71       SG_LOG(SG_NAVAID, SG_WARN, "bad groundnet, no node for index:" << it->first);
72       continue;
73     }
74
75     it->first->setPushBackPoint(j->second);
76     
77   }
78   
79   BOOST_FOREACH(FGTaxiNodeRef node, _unreferencedNodes) {
80     SG_LOG(SG_NAVAID, SG_WARN, "unreferenced groundnet node:" << node->ident());
81   }
82   
83 }
84
85 void FGAirportDynamicsXMLLoader::startParking(const XMLAttributes &atts)
86 {
87   string type;
88   int index = 0;
89   string gateName, gateNumber;
90   string lat, lon;
91   double heading = 0.0;
92   double radius = 1.0;
93   string airlineCodes;
94   int pushBackRoute = 0;
95   
96   for (int i = 0; i < atts.size(); i++)
97         {
98     string attname(atts.getName(i));
99           if (attname == "index") {
100       index = std::atoi(atts.getValue(i));
101     } else if (attname == "type")
102             type = atts.getValue(i);
103     else if (attname == "name")
104       gateName = atts.getValue(i);
105           else if (attname == "number")
106             gateNumber = atts.getValue(i);
107           else if (attname == "lat")
108       lat = atts.getValue(i);
109           else if (attname == "lon")
110             lon = atts.getValue(i);
111           else if (attname == "heading")
112             heading = std::atof(atts.getValue(i));
113           else if (attname == "radius") {
114             string radiusStr = atts.getValue(i);
115             if (radiusStr.find("M") != string::npos)
116               radiusStr = radiusStr.substr(0, radiusStr.find("M",0));
117             radius = std::atof(radiusStr.c_str());
118           }
119           else if (attname == "airlineCodes")
120       airlineCodes = atts.getValue(i);
121     else if (attname == "pushBackRoute") {
122       pushBackRoute = std::atoi(atts.getValue(i));      
123     }
124         }
125  
126   SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
127   
128   FGParkingRef parking(new FGParking(index,
129                                      pos, heading, radius,
130                                      gateName + gateNumber,
131                                      type, airlineCodes));
132   if (pushBackRoute > 0) {
133     _parkingPushbacks[parking] = pushBackRoute;
134   }
135   
136   _indexMap[index] = parking;
137   _dynamics->getGroundNetwork()->addParking(parking);
138 }
139
140 void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts)
141 {
142   int index = 0;
143   string lat, lon;
144   bool onRunway = false;
145   int holdPointType = 0;
146   
147   for (int i = 0; i < atts.size() ; i++)
148         {
149           string attname(atts.getName(i));
150           if (attname == "index")
151             index = std::atoi(atts.getValue(i));
152           else if (attname == "lat")
153       lat = atts.getValue(i);
154           else if (attname == "lon")
155             lon = atts.getValue(i);
156     else if (attname == "isOnRunway")
157       onRunway = std::atoi(atts.getValue(i)) != 0;
158           else if (attname == "holdPointType") {
159       string attval = atts.getValue(i);
160       if (attval=="none") {
161         holdPointType=0;
162       } else if (attval=="normal") {
163         holdPointType=1;
164       } else if (attval=="CAT II/III") {
165         holdPointType=3;
166       } else if (attval=="PushBack") {
167         holdPointType=3;
168       } else {
169         holdPointType=0;
170       }
171     }
172         }
173   
174   if (_indexMap.find(index) != _indexMap.end()) {
175     SG_LOG(SG_NAVAID, SG_WARN, "duplicate ground-net index:" << index);
176   }
177   
178   SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
179   FGTaxiNodeRef node(new FGTaxiNode(index, pos, onRunway, holdPointType));
180   _indexMap[index] = node;
181   _unreferencedNodes.insert(node);
182 }
183
184 void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts)
185 {  
186   int begin = 0, end = 0;
187   bool isPushBackRoute = false;
188   
189   for (int i = 0; i < atts.size() ; i++)
190         {
191           string attname = atts.getName(i);
192           if (attname == "begin")
193             begin = std::atoi(atts.getValue(i));
194           else if (attname == "end")
195             end = std::atoi(atts.getValue(i));
196     else if (attname == "isPushBackRoute")
197             isPushBackRoute = std::atoi(atts.getValue(i)) != 0;
198         }
199   
200   IntPair e(begin, end);
201   if (_arcSet.find(e) != _arcSet.end()) {
202     SG_LOG(SG_NAVAID, SG_WARN, _dynamics->parent()->ident() << " ground-net: skipping duplicate edge:" << begin << "->" << end);
203     return;
204   }
205   
206   NodeIndexMap::const_iterator it;
207   FGTaxiNodeRef fromNode, toNode;
208   it = _indexMap.find(begin);
209   if (it == _indexMap.end()) {
210       SG_LOG(SG_NAVAID, SG_WARN, "ground-net: bad edge:" << begin << "->" << end << ", begin index unknown");
211       return;
212   } else {
213       _unreferencedNodes.erase(it->second);
214       fromNode = it->second;
215   }
216
217   it = _indexMap.find(end);
218   if (it == _indexMap.end()) {
219       SG_LOG(SG_NAVAID, SG_WARN, "ground-net: bad edge:" << begin << "->" << end << ", end index unknown");
220       return;
221   } else {
222       _unreferencedNodes.erase(it->second);
223       toNode = it->second;
224   }
225
226   _arcSet.insert(e);  
227   _dynamics->getGroundNetwork()->addSegment(fromNode, toNode);
228 }
229
230 void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts)
231 {
232   if (!strcmp("Parking", name)) {
233     startParking(atts);
234   } else if (!strcmp("node", name)) {
235     startNode(atts);
236   } else if (!strcmp("arc", name)) {
237     startArc(atts);
238   }
239 }
240
241 void  FGAirportDynamicsXMLLoader::endElement (const char * name)
242 {
243   int valueAsInt = atoi(value.c_str());
244   if (!strcmp("version", name)) {
245     _dynamics->getGroundNetwork()->addVersion(valueAsInt);
246   } else if (!strcmp("AWOS", name)) {
247     _dynamics->addAwosFreq(valueAsInt);
248   } else if (!strcmp("UNICOM", name)) {
249     _dynamics->addUnicomFreq(valueAsInt);
250   } else if (!strcmp("CLEARANCE", name)) {
251     _dynamics->addClearanceFreq(valueAsInt);
252   } else if (!strcmp("GROUND", name)) {
253     _dynamics->addGroundFreq(valueAsInt);
254   } else if (!strcmp("TOWER", name)) {
255     _dynamics->addTowerFreq(valueAsInt);
256   } else if (!strcmp("APPROACH", name)) {
257     _dynamics->addApproachFreq(valueAsInt);
258   }
259 }
260
261 void  FGAirportDynamicsXMLLoader::data (const char * s, int len) {
262   string token = string(s,len);
263   //cout << "Character data " << string(s,len) << endl;
264   if ((token.find(" ") == string::npos && (token.find('\n')) == string::npos))
265     value += token;
266   else
267     value = string("");
268 }
269
270 void  FGAirportDynamicsXMLLoader::pi (const char * target, const char * data) {
271   //cout << "Processing instruction " << target << ' ' << data << endl;
272 }
273
274 void  FGAirportDynamicsXMLLoader::warning (const char * message, int line, int column) {
275   SG_LOG(SG_IO, SG_WARN, "Warning: " << message << " (" << line << ',' << column << ')');
276 }
277
278 void  FGAirportDynamicsXMLLoader::error (const char * message, int line, int column) {
279   SG_LOG(SG_IO, SG_ALERT, "Error: " << message << " (" << line << ',' << column << ')');
280 }