#endif
#include <cstdlib>
+#include <cstring> // for strcmp
+#include <boost/foreach.hpp>
#include "dynamicloader.hxx"
+#include <Navaids/NavDataCache.hxx>
+#include <Airports/dynamics.hxx>
+#include <Airports/simple.hxx>
+
+/*****************************************************************************
+ * Helper function for parsing position string
+ ****************************************************************************/
+static double processPosition(const string &pos)
+{
+ string prefix;
+ string subs;
+ string degree;
+ string decimal;
+ int sign = 1;
+ double value;
+ subs = pos;
+ prefix= subs.substr(0,1);
+ if (prefix == string("S") || (prefix == string("W")))
+ sign = -1;
+ subs = subs.substr(1, subs.length());
+ degree = subs.substr(0, subs.find(" ",0));
+ decimal = subs.substr(subs.find(" ",0), subs.length());
+
+ value = sign * (atof(degree.c_str()) + atof(decimal.c_str())/60.0);
+ return value;
+}
+
FGAirportDynamicsXMLLoader::FGAirportDynamicsXMLLoader(FGAirportDynamics* dyn):
- XMLVisitor(), _dynamics(dyn) {}
+ XMLVisitor(), _dynamics(dyn)
+{}
void FGAirportDynamicsXMLLoader::startXML () {
//cout << "FGAirportDynamicsLoader::Start XML" << endl;
}
-void FGAirportDynamicsXMLLoader::endXML () {
- //cout << "End XML" << endl;
+void FGAirportDynamicsXMLLoader::endXML ()
+{
+ std::map<PositionedID, int>::iterator it;
+ flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
+
+ for (it = _parkingPushbacks.begin(); it != _parkingPushbacks.end(); ++it) {
+ std::map<int, PositionedID>::iterator j = _idMap.find(it->second);
+ if (j == _idMap.end()) {
+ SG_LOG(SG_GENERAL, SG_WARN, "bad groundnet, no node for index:" << it->first);
+ continue;
+ }
+
+ cache->setParkingPushBackRoute(it->first, j->second);
+ }
+
+ BOOST_FOREACH(PositionedID id, _unreferencedNodes) {
+ SG_LOG(SG_GENERAL, SG_WARN, "unreferenced groundnet node:" << id);
+ }
+
}
-void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts) {
- // const char *attval;
- FGParking park;
- FGTaxiNode taxiNode;
- FGTaxiSegment taxiSegment;
+void FGAirportDynamicsXMLLoader::startParking(const XMLAttributes &atts)
+{
+ string type;
int index = 0;
- string idxStr;
- taxiSegment.setIndex(index);
- //cout << "Start element " << name << endl;
- string attname;
- string value;
- string gateName;
- string gateNumber;
- string attval;
- string lat;
- string lon;
- int holdPointType;
- int pushBackPoint;
+ string gateName, gateNumber;
+ string lat, lon;
+ double heading = 0.0;
+ double radius = 1.0;
+ string airlineCodes;
+ int pushBackRoute = 0;
- if (name == string("Parking"))
- {
- pushBackPoint = 0;
- for (int i = 0; i < atts.size(); i++)
+ for (int i = 0; i < atts.size(); i++)
{
- //cout << " " << atts.getName(i) << '=' << atts.getValue(i) << endl;
- attname = atts.getName(i);
- if (attname == string("index")) {
- park.setIndex(std::atoi(atts.getValue(i)));
- idxStr = atts.getValue(i);
- }
- else if (attname == string("type"))
- park.setType(atts.getValue(i));
- else if (attname == string("name"))
- gateName = atts.getValue(i);
- else if (attname == string("number"))
+ string attname(atts.getName(i));
+ if (attname == "index") {
+ index = std::atoi(atts.getValue(i));
+ } else if (attname == "type")
+ type = atts.getValue(i);
+ else if (attname == "name")
+ gateName = atts.getValue(i);
+ else if (attname == "number")
gateNumber = atts.getValue(i);
- else if (attname == string("lat"))
- park.setLatitude(atts.getValue(i));
- else if (attname == string("lon"))
- park.setLongitude(atts.getValue(i));
- else if (attname == string("heading"))
- park.setHeading(std::atof(atts.getValue(i)));
- else if (attname == string("radius")) {
- string radius = atts.getValue(i);
- if (radius.find("M") != string::npos)
- radius = radius.substr(0, radius.find("M",0));
- //cerr << "Radius " << radius <<endl;
- park.setRadius(std::atof(radius.c_str()));
+ else if (attname == "lat")
+ lat = atts.getValue(i);
+ else if (attname == "lon")
+ lon = atts.getValue(i);
+ else if (attname == "heading")
+ heading = std::atof(atts.getValue(i));
+ else if (attname == "radius") {
+ string radiusStr = atts.getValue(i);
+ if (radiusStr.find("M") != string::npos)
+ radiusStr = radiusStr.substr(0, radiusStr.find("M",0));
+ radius = std::atof(radiusStr.c_str());
}
- else if (attname == string("airlineCodes"))
- park.setCodes(atts.getValue(i));
- else if (attname == string("pushBackRoute")) {
- pushBackPoint = std::atoi(atts.getValue(i));
- //park.setPushBackPoint(std::atoi(atts.getValue(i)));
-
- }
- }
- park.setPushBackPoint(pushBackPoint);
- park.setName((gateName+gateNumber));
- //cerr << "Parking " << idxStr << "( " << gateName << gateNumber << ") has pushBackPoint " << pushBackPoint << endl;
- _dynamics->addParking(park);
+ else if (attname == "airlineCodes")
+ airlineCodes = atts.getValue(i);
+ else if (attname == "pushBackRoute") {
+ pushBackRoute = std::atoi(atts.getValue(i));
}
- if (name == string("node"))
- {
- for (int i = 0; i < atts.size() ; i++)
- {
- attname = atts.getName(i);
- if (attname == string("index"))
- taxiNode.setIndex(std::atoi(atts.getValue(i)));
- if (attname == string("lat"))
- taxiNode.setLatitude(atts.getValue(i));
- if (attname == string("lon"))
- taxiNode.setLongitude(atts.getValue(i));
- if (attname == string("isOnRunway"))
- taxiNode.setOnRunway((bool) std::atoi(atts.getValue(i)));
- if (attname == string("holdPointType")) {
- attval = atts.getValue(i);
- if (attval==string("none")) {
- holdPointType=0;
- } else if (attval==string("normal")) {
- holdPointType=1;
- } else if (attval==string("CAT II/III")) {
- holdPointType=3;
- } else if (attval==string("PushBack")) {
- holdPointType=3;
- } else {
- holdPointType=0;
- }
- //cerr << "Setting Holding point to " << holdPointType << endl;
- taxiNode.setHoldPointType(holdPointType);
- }
}
- _dynamics->getGroundNetwork()->addNode(taxiNode);
- }
- if (name == string("arc"))
- {
- taxiSegment.setIndex(++index);
- for (int i = 0; i < atts.size() ; i++)
+
+ SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
+
+ PositionedID guid = flightgear::NavDataCache::instance()->insertParking(gateName + gateNumber, pos,
+ _dynamics->parent()->guid(),
+ heading, radius, type, airlineCodes);
+ if (pushBackRoute > 0) {
+ _parkingPushbacks[guid] = pushBackRoute;
+ }
+
+ _idMap[index] = guid;
+}
+
+void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts)
+{
+ int index = 0;
+ string lat, lon;
+ bool onRunway = false;
+ int holdPointType = 0;
+
+ for (int i = 0; i < atts.size() ; i++)
{
- attname = atts.getName(i);
- if (attname == string("begin"))
- taxiSegment.setStartNodeRef(std::atoi(atts.getValue(i)));
- if (attname == string("end"))
- taxiSegment.setEndNodeRef(std::atoi(atts.getValue(i)));
- if (attname == string("isPushBackRoute"))
- taxiSegment.setPushBackType((bool) std::atoi(atts.getValue(i)));
- }
- _dynamics->getGroundNetwork()->addSegment(taxiSegment);
+ string attname(atts.getName(i));
+ if (attname == "index")
+ index = std::atoi(atts.getValue(i));
+ else if (attname == "lat")
+ lat = atts.getValue(i);
+ else if (attname == "lon")
+ lon = atts.getValue(i);
+ else if (attname == "isOnRunway")
+ onRunway = std::atoi(atts.getValue(i)) != 0;
+ else if (attname == "holdPointType") {
+ string attval = atts.getValue(i);
+ if (attval=="none") {
+ holdPointType=0;
+ } else if (attval=="normal") {
+ holdPointType=1;
+ } else if (attval=="CAT II/III") {
+ holdPointType=3;
+ } else if (attval=="PushBack") {
+ holdPointType=3;
+ } else {
+ holdPointType=0;
+ }
}
- // sort by radius, in asending order, so that smaller gates are first in the list
+ }
+
+ if (_idMap.find(index) != _idMap.end()) {
+ SG_LOG(SG_GENERAL, SG_WARN, "duplicate ground-net index:" << index);
+ }
+
+ SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat)));
+ PositionedID guid = flightgear::NavDataCache::instance()->insertTaxiNode(pos,
+ _dynamics->parent()->guid(), holdPointType, onRunway);
+ _idMap[index] = guid;
+ _unreferencedNodes.insert(guid);
}
-void FGAirportDynamicsXMLLoader::endElement (const char * name) {
- //cout << "End element " << name << endl;
- if (name == string("version")) {
- _dynamics->getGroundNetwork()->addVersion(atoi(value.c_str()));
- //std::cerr << "version" << value<< std::endl;
- }
- if (name == string("AWOS")) {
- _dynamics->addAwosFreq(atoi(value.c_str()));
- //cerr << "Adding AWOS" << value<< endl;
- }
- if (name == string("UNICOM")) {
- _dynamics->addUnicomFreq(atoi(value.c_str()));
- //cerr << "UNICOM" << value<< endl;
- }
-if (name == string("CLEARANCE")) {
- _dynamics->addClearanceFreq(atoi(value.c_str()));
- //cerr << "Adding CLEARANCE" << value<< endl;
+void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts)
+{
+ int begin = 0, end = 0;
+ bool isPushBackRoute = false;
+
+ for (int i = 0; i < atts.size() ; i++)
+ {
+ string attname = atts.getName(i);
+ if (attname == "begin")
+ begin = std::atoi(atts.getValue(i));
+ else if (attname == "end")
+ end = std::atoi(atts.getValue(i));
+ else if (attname == "isPushBackRoute")
+ isPushBackRoute = std::atoi(atts.getValue(i)) != 0;
+ }
+
+ IntPair e(begin, end);
+ if (_arcSet.find(e) != _arcSet.end()) {
+ SG_LOG(SG_GENERAL, SG_WARN, _dynamics->parent()->ident() << " ground-net: skipping duplicate edge:" << begin << "->" << end);
+ return;
}
-if (name == string("GROUND")) {
- _dynamics->addGroundFreq(atoi(value.c_str()));
- //cerr << "Adding GROUND" << value<< endl;
+
+ _arcSet.insert(e);
+ flightgear::NavDataCache::instance()->insertGroundnetEdge(_dynamics->parent()->guid(),
+ _idMap[begin], _idMap[end]);
+
+ _unreferencedNodes.erase(_idMap[begin]);
+ _unreferencedNodes.erase(_idMap[end]);
+
+ if (isPushBackRoute) {
+ flightgear::NavDataCache::instance()->markGroundnetAsPushback(_idMap[end]);
}
+}
-if (name == string("TOWER")) {
- _dynamics->addTowerFreq(atoi(value.c_str()));
- //cerr << "Adding TOWER" << value<< endl;
- }
-if (name == string("APPROACH")) {
- _dynamics->addApproachFreq(atoi(value.c_str()));
- //cerr << "Adding approach" << value<< endl;
+void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts)
+{
+ if (!strcmp("Parking", name)) {
+ startParking(atts);
+ } else if (!strcmp("node", name)) {
+ startNode(atts);
+ } else if (!strcmp("arc", name)) {
+ startArc(atts);
}
+}
+void FGAirportDynamicsXMLLoader::endElement (const char * name)
+{
+ int valueAsInt = atoi(value.c_str());
+ if (!strcmp("version", name)) {
+ _dynamics->getGroundNetwork()->addVersion(valueAsInt);
+ } else if (!strcmp("AWOS", name)) {
+ _dynamics->addAwosFreq(valueAsInt);
+ } else if (!strcmp("UNICOM", name)) {
+ _dynamics->addUnicomFreq(valueAsInt);
+ } else if (!strcmp("CLEARANCE", name)) {
+ _dynamics->addClearanceFreq(valueAsInt);
+ } else if (!strcmp("GROUND", name)) {
+ _dynamics->addGroundFreq(valueAsInt);
+ } else if (!strcmp("TOWER", name)) {
+ _dynamics->addTowerFreq(valueAsInt);
+ } else if (!strcmp("APPROACH", name)) {
+ _dynamics->addApproachFreq(valueAsInt);
+ }
}
void FGAirportDynamicsXMLLoader::data (const char * s, int len) {