From b1ff365a8f0bf2f25f030ef2058c42f3052e0d8b Mon Sep 17 00:00:00 2001 From: James Turner Date: Tue, 25 Sep 2012 00:31:17 +0100 Subject: [PATCH] Make FGTaxiNode and FGParking inherit FGPositioned. In preparation for caching the groundnet in the NavCache, make taxi-nodes and parkings inherit from FGPositioned. As part of this, make them heap (as opposed to value) classes, disable their copy-constructors, remove many mutating operations, and give them real constructors. --- src/AIModel/AIFlightPlanCreate.cxx | 16 +- src/AIModel/AIFlightPlanCreatePushBack.cxx | 26 +- src/ATC/trafficcontrol.cxx | 13 +- src/Airports/dynamicloader.cxx | 278 ++++++------- src/Airports/dynamicloader.hxx | 4 + src/Airports/dynamics.cxx | 49 +-- src/Airports/dynamics.hxx | 2 +- src/Airports/gnnode.cxx | 94 ++--- src/Airports/gnnode.hxx | 79 ++-- src/Airports/groundnetwork.cxx | 428 +++++++++------------ src/Airports/groundnetwork.hxx | 113 +----- src/Airports/parking.cxx | 35 +- src/Airports/parking.hxx | 60 +-- src/Main/positioninit.cxx | 2 +- src/Navaids/positioned.cxx | 3 +- src/Navaids/positioned.hxx | 8 +- src/Scripting/NasalPositioned.cxx | 2 +- 17 files changed, 493 insertions(+), 719 deletions(-) diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index 30a698972..c49b4abe8 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -313,7 +313,7 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findNode(node); FGAIWaypoint *wpt = - createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), + createOnGround(ac, buffer, tn->geod(), apt->getElevation(), ac->getPerformance()->vTaxi()); wpt->setRouteIndex(route); //cerr << "Nodes left " << taxiRoute->nodesLeft() << " "; @@ -356,7 +356,7 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac, FGParking* parkPos = aAirport->getDynamics()->getParking(gateId); if (parkPos) { - wpt = createOnGround(ac, "ENDtaxi", parkPos->getGeod(), airportElev, + wpt = createOnGround(ac, "ENDtaxi", parkPos->geod(), airportElev, ac->getPerformance()->vTaxi()); pushBackWaypoint(wpt); } @@ -419,7 +419,7 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, snprintf(buffer, 10, "%d", node); FGTaxiNode *tn = gn->findNode(node); FGAIWaypoint *wpt = - createOnGround(ac, buffer, tn->getGeod(), apt->getElevation(), + createOnGround(ac, buffer, tn->geod(), apt->getElevation(), ac->getPerformance()->vTaxi()); wpt->setRouteIndex(route); pushBackWaypoint(wpt); @@ -969,14 +969,14 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt, if (!tn) break; - double dist = SGGeodesy::distanceM(coord, tn->getGeod()); + double dist = SGGeodesy::distanceM(coord, tn->geod()); if (dist < (min + 0.75)) { break; } min = dist; } if (tn) { - wpt = createOnGround(ac, buffer, tn->getGeod(), currElev, vTaxi); + wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi); pushBackWaypoint(wpt); } } @@ -1024,18 +1024,18 @@ bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt, double az; // unused SGGeod pos; - SGGeodesy::direct(parking->getGeod(), heading, 2.2 * parking->getRadius(), + SGGeodesy::direct(parking->geod(), heading, 2.2 * parking->getRadius(), pos, az); wpt = createOnGround(ac, "taxiStart", pos, aptElev, vTaxiReduced); pushBackWaypoint(wpt); - SGGeodesy::direct(parking->getGeod(), heading, 0.1 * parking->getRadius(), + SGGeodesy::direct(parking->geod(), heading, 0.1 * parking->getRadius(), pos, az); wpt = createOnGround(ac, "taxiStart2", pos, aptElev, vTaxiReduced); pushBackWaypoint(wpt); - wpt = createOnGround(ac, "END-Parking", parking->getGeod(), aptElev, + wpt = createOnGround(ac, "END-Parking", parking->geod(), aptElev, vTaxiReduced); pushBackWaypoint(wpt); return true; diff --git a/src/AIModel/AIFlightPlanCreatePushBack.cxx b/src/AIModel/AIFlightPlanCreatePushBack.cxx index 07d7eeca1..7ebdd7af1 100644 --- a/src/AIModel/AIFlightPlanCreatePushBack.cxx +++ b/src/AIModel/AIFlightPlanCreatePushBack.cxx @@ -93,8 +93,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, FGTaxiRoute route; //cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl; route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false); - parking->setPushBackRoute(new FGTaxiRoute(route)); - + parking->setPushBackRoute(std::auto_ptr(new FGTaxiRoute(route))); pushBackRoute = parking->getPushBackRoute(); int size = pushBackRoute->size(); @@ -111,7 +110,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node); //ids.pop_back(); //wpt = new waypoint; - FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->getGeod(), dep->getElevation(), vTaxiBackward); + FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->geod(), dep->getElevation(), vTaxiBackward); wpt->setRouteIndex(rte); pushBackWaypoint(wpt); @@ -126,34 +125,29 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, //cerr << "Creating final push forward point for gate " << gateId << endl; FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId); - FGTaxiSegmentVectorIterator ts = tn->getBeginRoute(); - FGTaxiSegmentVectorIterator te = tn->getEndRoute(); - // if the starting node equals the ending node, then there aren't any routes for this parking. + // there aren't any routes for this parking. // in cases like these we should flag the gate as being inoperative and return false - if (ts == te) { + if (tn->arcs().empty()) { SG_LOG(SG_AI, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it."); parking->setAvailable(false); return false; } - tn = (*ts)->getEnd(); - lastNodeVisited = tn->getIndex(); - if (tn == NULL) { - SG_LOG(SG_AI, SG_ALERT, "No valid taxinode found"); - exit(1); - } - double distance = (*ts)->getLength(); + + FGTaxiSegment* pushForwardSegment = tn->arcs().front(); + lastNodeVisited = pushForwardSegment->getEnd()->getIndex(); + double distance = pushForwardSegment->getLength(); double parkingHeading = parking->getHeading(); for (int i = 1; i < 10; i++) { SGGeod pushForwardPt; - SGGeodesy::direct(parking->getGeod(), parkingHeading, + SGGeodesy::direct(parking->geod(), parkingHeading, ((i / 10.0) * distance), pushForwardPt, az2); char buffer[16]; snprintf(buffer, 16, "pushback-%02d", i); FGAIWaypoint *wpt = createOnGround(ac, string(buffer), pushForwardPt, dep->getElevation(), vTaxiReduced); - wpt->setRouteIndex((*ts)->getIndex()); + wpt->setRouteIndex(pushForwardSegment->getIndex()); pushBackWaypoint(wpt); } // cerr << "Done " << endl; diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index 0c4e2e5d7..c71dd034d 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -1340,10 +1340,10 @@ void FGStartupController::render(bool visible) if (pos > 0) { FGTaxiSegment *segment = parent->getGroundNetwork()->findSegment(pos); SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude()))); - SGGeod end (SGGeod::fromDeg(segment->getEnd()->getLongitude(), segment->getEnd()->getLatitude())); + SGGeod end (segment->getEnd()->geod()); double length = SGGeodesy::distanceM(start, end); - //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod()); + //heading = SGGeodesy::headingDeg(start->geod(), end->geod()); double az2, heading; //, distanceM; SGGeodesy::inverse(start, end, heading, az2, length); @@ -1428,7 +1428,7 @@ void FGStartupController::render(bool visible) double elevationStart = segment->getStart()->getElevationM(parent->getElevation()*SG_FEET_TO_METER); double elevationEnd = segment->getEnd ()->getElevationM(parent->getElevation()*SG_FEET_TO_METER); if ((elevationStart == 0) || (elevationStart == parent->getElevation())) { - SGGeod center2 = segment->getStart()->getGeod(); + SGGeod center2 = segment->getStart()->geod(); center2.setElevationM(SG_MAX_ELEVATION_M); if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) { //elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5; @@ -1440,7 +1440,7 @@ void FGStartupController::render(bool visible) segment->getStart()->setElevation(elevationStart); } if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) { - SGGeod center2 = segment->getEnd()->getGeod(); + SGGeod center2 = segment->getEnd()->geod(); center2.setElevationM(SG_MAX_ELEVATION_M); if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) { //elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5; @@ -1459,8 +1459,9 @@ void FGStartupController::render(bool visible) //cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl; - - WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), elevationMean + 0.5 + dx, -(segment->getHeading()), slope ); + SGGeod segCenter(segment->getCenter()); + WorldCoordinate( obj_pos, segCenter.getLatitudeDeg(), + segCenter.getLongitudeDeg(), elevationMean + 0.5 + dx, -(segment->getHeading()), slope ); //WorldCoordinate( obj_pos, segment->getLatitude(), segment->getLongitude(), parent->getElevation()+8+dx, -(segment->getHeading()) ); diff --git a/src/Airports/dynamicloader.cxx b/src/Airports/dynamicloader.cxx index 26af2b711..2142a8622 100644 --- a/src/Airports/dynamicloader.cxx +++ b/src/Airports/dynamicloader.cxx @@ -21,8 +21,32 @@ #include "dynamicloader.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; @@ -32,150 +56,142 @@ void FGAirportDynamicsXMLLoader::endXML () { //cout << "End XML" << endl; } -void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts) { - // const char *attval; - FGParking park; - FGTaxiNode taxiNode; - FGTaxiSegment taxiSegment; - 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; +void FGAirportDynamicsXMLLoader::startParking(const XMLAttributes &atts) +{ + string type; + int index; + 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 <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); + + SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat))); + + FGParking* pk = new FGParking(0, index, pos, heading, radius, + gateName + gateNumber, type, airlineCodes); + pk->setPushBackPoint(pushBackRoute); + _dynamics->addParking(pk); +} + +void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts) +{ + int index; + string lat, lon; + bool onRunway; + int holdPointType; + + for (int i = 0; i < atts.size() ; i++) + { + 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 = (bool) std::atoi(atts.getValue(i)); + 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; + } } - if (name == string("arc")) - { - taxiSegment.setIndex(++index); - for (int i = 0; i < atts.size() ; i++) + } + + SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat))); + FGTaxiNode* taxiNode = new FGTaxiNode(0, index, pos, onRunway, holdPointType); + _dynamics->getGroundNetwork()->addNode(taxiNode); +} + +void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts) +{ + int begin, end; + bool isPushBackRoute = false; + + 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))); + 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 = (bool) std::atoi(atts.getValue(i)); } - _dynamics->getGroundNetwork()->addSegment(taxiSegment); - } - // sort by radius, in asending order, so that smaller gates are first in the list + + _dynamics->getGroundNetwork()->addSegment(new FGTaxiSegment(begin, end, isPushBackRoute)); } -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; - } -if (name == string("GROUND")) { - _dynamics->addGroundFreq(atoi(value.c_str())); - //cerr << "Adding GROUND" << 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); } +} -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::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) { diff --git a/src/Airports/dynamicloader.hxx b/src/Airports/dynamicloader.hxx index 672cda5af..0584d06ac 100644 --- a/src/Airports/dynamicloader.hxx +++ b/src/Airports/dynamicloader.hxx @@ -35,6 +35,10 @@ protected: virtual void error (const char * message, int line, int column); private: + void startParking(const XMLAttributes &atts); + void startNode(const XMLAttributes &atts); + void startArc(const XMLAttributes &atts); + FGAirportDynamics* _dynamics; string value; }; diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 21d45d08b..dde198356 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -91,8 +91,7 @@ int FGAirportDynamics::innerGetAvailableParking(double radius, const string & fl const string & airline, bool skipEmptyAirlineCode) { - FGParkingVecIterator i; - for (i = parkings.begin(); i != parkings.end(); i++) { + BOOST_FOREACH(FGParking* i, parkings) { // Taken by another aircraft, or no airline codes if (!i->isAvailable()) { continue; @@ -151,49 +150,43 @@ int FGAirportDynamics::getAvailableParking(double radius, const string & flType, FGParking *FGAirportDynamics::getParking(int id) { - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - return &(*i); - } + BOOST_FOREACH(FGParking* i, parkings) { + if (id == i->getIndex()) { + return i; } - return 0; + } + + return NULL; } string FGAirportDynamics::getParkingName(int id) { - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - return i->getName(); - } - } - - return string("overflow"); + FGParking* p = getParking(id); + if (p) { + return p->getName(); + } + + return string(); } int FGAirportDynamics::findParkingByName(const std::string& name) const { - FGParkingVec::const_iterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (i->getName() == name) { + BOOST_FOREACH(FGParking* i, parkings) { + if (name == i->getName()) { return i->getIndex(); } } - + return -1; } void FGAirportDynamics::releaseParking(int id) { if (id >= 0) { - - FGParkingVecIterator i = parkings.begin(); - for (i = parkings.begin(); i != parkings.end(); i++) { - if (id == i->getIndex()) { - i->setAvailable(true); - } - } + FGParking* parking = getParking(id); + if (parking) { + parking->setAvailable(true); + } } } @@ -380,7 +373,7 @@ string FGAirportDynamics::chooseRunwayFallback() return rwy->ident(); } -void FGAirportDynamics::addParking(FGParking & park) +void FGAirportDynamics::addParking(FGParking* park) { parkings.push_back(park); } diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index cb489bfa3..33481b12c 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -99,7 +99,7 @@ public: void getActiveRunway(const string& trafficType, int action, string& runway, double heading); - void addParking(FGParking& park); + void addParking(FGParking* park); /** * retrieve an available parking by GateID, or -1 if no suitable diff --git a/src/Airports/gnnode.cxx b/src/Airports/gnnode.cxx index 691a42064..41e746305 100644 --- a/src/Airports/gnnode.cxx +++ b/src/Airports/gnnode.cxx @@ -1,99 +1,63 @@ #include "gnnode.hxx" -#include "groundnetwork.hxx" -#include -#include +#include + +#include "groundnetwork.hxx" -#include #include
#include -using std::sort; -using std::string; - -/***************************************************************************** - * Helper function for parsing position string - ****************************************************************************/ -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()); - - - //cerr << sign << " "<< degree << " " << decimal << endl; - value = sign * (atof(degree.c_str()) + atof(decimal.c_str())/60.0); - //cerr << value <hasSmallerHeadingDiff(*b); -//} - -bool sortByLength(FGTaxiSegment *a, FGTaxiSegment *b) { - return a->getLength() > b->getLength(); -} - /************************************************************************** * FGTaxiNode *************************************************************************/ -void FGTaxiNode::setElevation(double val) -{ - geod.setElevationM(val); -} -void FGTaxiNode::setLatitude (double val) +FGTaxiNode::FGTaxiNode(PositionedID aGuid, int index, const SGGeod& pos, bool aOnRunway, int aHoldType) : + FGPositioned(aGuid, FGPositioned::PARKING, "", pos), + index(index), + isOnRunway(aOnRunway), + holdType(aHoldType) { - geod.setLatitudeDeg(val); + } -void FGTaxiNode::setLongitude(double val) +FGTaxiNode::~FGTaxiNode() { - geod.setLongitudeDeg(val); } -void FGTaxiNode::setLatitude (const string& val) +void FGTaxiNode::setElevation(double val) { - geod.setLatitudeDeg(processPosition(val)); + // ignored for the moment } -void FGTaxiNode::setLongitude(const string& val) -{ - geod.setLongitudeDeg(processPosition(val)); -} - double FGTaxiNode::getElevationFt(double refelev) { - double elevF = geod.getElevationFt(); + double elevF = elevation(); +#if 0 double elevationEnd = 0; if ((elevF == 0) || (elevF == refelev)) { - SGGeod center2 = geod; + SGGeod center2 = mPosition; FGScenery * local_scenery = globals->get_scenery(); center2.setElevationM(SG_MAX_ELEVATION_M); if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) { geod.setElevationM(elevationEnd); } } - //cerr << "Returning elevation : " << geod.getElevationM() << ". Ref elev (feet) = " << refelev << endl; - return geod.getElevationFt(); +#endif + return mPosition.getElevationFt(); } double FGTaxiNode::getElevationM(double refelev) { - //double refelevFt = refelev * SG_METER_TO_FEET; - //double retval = getElevationFt(refelevFt); - //cerr << "Returning elevation : " << geod.getElevationM() << ". Ref elev (meters) = " << refelev << endl; - return geod.getElevationM(); + return geod().getElevationM(); +} + +FGTaxiSegment* FGTaxiNode::getArcTo(FGTaxiNode* aEnd) const +{ + BOOST_FOREACH(FGTaxiSegment* arc, next) { + if (arc->getEnd() == aEnd) { + return arc; + } + } + + return NULL; } diff --git a/src/Airports/gnnode.hxx b/src/Airports/gnnode.hxx index c64b51fd0..5902badfb 100644 --- a/src/Airports/gnnode.hxx +++ b/src/Airports/gnnode.hxx @@ -20,76 +20,39 @@ #include #include -#include +#include + +#include class FGTaxiSegment; + typedef std::vector FGTaxiSegmentVector; typedef FGTaxiSegmentVector::iterator FGTaxiSegmentVectorIterator; bool sortByHeadingDiff(FGTaxiSegment *a, FGTaxiSegment *b); bool sortByLength (FGTaxiSegment *a, FGTaxiSegment *b); -class FGTaxiNode +class FGTaxiNode : public FGPositioned { protected: - SGGeod geod; int index; bool isOnRunway; int holdType; FGTaxiSegmentVector next; // a vector of pointers to all the segments leaving from this node - // used in way finding + // used in way finding - should really move to a dynamic struct double pathScore; FGTaxiNode* previousNode; FGTaxiSegment* previousSeg; -public: - FGTaxiNode() : - index(0), - isOnRunway(false), - holdType(0), - pathScore(0), - previousNode(0), - previousSeg(0) -{ -}; - - FGTaxiNode(const FGTaxiNode &other) : - geod(other.geod), - index(other.index), - isOnRunway(other.isOnRunway), - holdType(other.holdType), - next(other.next), - pathScore(other.pathScore), - previousNode(other.previousNode), - previousSeg(other.previousSeg) -{ -}; - -FGTaxiNode &operator =(const FGTaxiNode &other) -{ - geod = other.geod; - index = other.index; - isOnRunway = other.isOnRunway; - holdType = other.holdType; - next = other.next; - pathScore = other.pathScore; - previousNode = other.previousNode; - previousSeg = other.previousSeg; - return *this; -}; - - void setIndex(int idx) { index = idx; }; - void setLatitude (double val); - void setLongitude(double val); +public: + FGTaxiNode(PositionedID aGuid, int index, const SGGeod& pos, bool aOnRunway, int aHoldType); + virtual ~FGTaxiNode(); + void setElevation(double val); - void setLatitude (const std::string& val); - void setLongitude(const std::string& val); void addSegment(FGTaxiSegment *segment) { next.push_back(segment); }; - void setHoldPointType(int val) { holdType = val; }; - void setOnRunway(bool val) { isOnRunway = val; }; void setPathScore (double val) { pathScore = val; }; void setPreviousNode(FGTaxiNode *val) { previousNode = val; }; @@ -99,26 +62,28 @@ FGTaxiNode &operator =(const FGTaxiNode &other) FGTaxiSegment *getPreviousSegment() { return previousSeg; }; double getPathScore() { return pathScore; }; - double getLatitude() { return geod.getLatitudeDeg();}; - double getLongitude(){ return geod.getLongitudeDeg();}; - double getElevationM (double refelev=0); - double getElevationFt(double refelev=0); - - const SGGeod& getGeod() const { return geod; } + double getElevationM (double refelev); + double getElevationFt(double refelev); + int getIndex() const { return index; }; int getHoldPointType() const { return holdType; }; bool getIsOnRunway() const { return isOnRunway; }; - FGTaxiNode *getAddress() { return this;}; - FGTaxiSegmentVectorIterator getBeginRoute() { return next.begin(); }; - FGTaxiSegmentVectorIterator getEndRoute() { return next.end(); }; + const FGTaxiSegmentVector& arcs() const + { return next; } + + /// find the arg which leads from this node to another. + /// returns NULL if no such arc exists. + FGTaxiSegment* getArcTo(FGTaxiNode* aEnd) const; + bool operator<(const FGTaxiNode &other) const { return index < other.index; }; }; -typedef std::vector FGTaxiNodeVector; +typedef SGSharedPtr FGTaxiNode_ptr; +typedef std::vector FGTaxiNodeVector; typedef FGTaxiNodeVector::iterator FGTaxiNodeVectorIterator; #endif diff --git a/src/Airports/groundnetwork.cxx b/src/Airports/groundnetwork.cxx index 62449b0cb..c992f1e7b 100644 --- a/src/Airports/groundnetwork.cxx +++ b/src/Airports/groundnetwork.cxx @@ -27,7 +27,7 @@ #include #include #include - +#include #include #include @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -59,64 +60,47 @@ using std::string; * FGTaxiSegment **************************************************************************/ -void FGTaxiSegment::setStart(FGTaxiNodeVector * nodes) +FGTaxiSegment::FGTaxiSegment(int aStart, int aEnd, bool isPushBack) : + startNode(aStart), + endNode(aEnd), + length(0), + heading(0), + isActive(0), + isPushBackRoute(isPushBack), + start(0), + end(0), + index(0), + oppositeDirection(0) { - FGTaxiNodeVectorIterator i = nodes->begin(); - while (i != nodes->end()) { - //cerr << "Scanning start node index" << (*i)->getIndex() << endl; - if ((*i)->getIndex() == startNode) { - start = (*i)->getAddress(); - (*i)->addSegment(this); - return; - } - i++; - } - SG_LOG(SG_GENERAL, SG_ALERT, - "Could not find start node " << startNode << endl); -} +}; -void FGTaxiSegment::setEnd(FGTaxiNodeVector * nodes) +bool FGTaxiSegment::bindToNodes(const IndexTaxiNodeMap& nodes) { - FGTaxiNodeVectorIterator i = nodes->begin(); - while (i != nodes->end()) { - //cerr << "Scanning end node index" << (*i)->getIndex() << endl; - if ((*i)->getIndex() == endNode) { - end = (*i)->getAddress(); - return; - } - i++; - } - SG_LOG(SG_GENERAL, SG_ALERT, - "Could not find end node " << endNode << endl); + IndexTaxiNodeMap::const_iterator it = nodes.find(startNode); + if (it == nodes.end()) { + return false; + } + + start = it->second; + + it = nodes.find(endNode); + if (it == nodes.end()) { + return false; + } + + end = it->second; + + start->addSegment(this); + double az2; + SGGeodesy::inverse(start->geod(), end->geod(), heading, az2, length); + return true; } - - -// There is probably a computationally cheaper way of -// doing this. -void FGTaxiSegment::setDimensions(double elevation) +SGGeod FGTaxiSegment::getCenter() const { - length = SGGeodesy::distanceM(start->getGeod(), end->getGeod()); - //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod()); - - double az2; //, distanceM; - SGGeodesy::inverse(start->getGeod(), end->getGeod(), heading, az2, length); - double coveredDistance = length * 0.5; - SGGeodesy::direct(start->getGeod(), heading, coveredDistance, center, az2); - //start->setElevation(elevation); - //end->setElevation(elevation); - //cerr << "Centerpoint = (" << center.getLatitudeDeg() << ", " << center.getLongitudeDeg() << "). Heading = " << heading << endl; + return SGGeodesy::direct(start->geod(), heading, length * 0.5); } - -//void FGTaxiSegment::setCourseDiff(double crse) -//{ -// headingDiff = fabs(course - crse); - -// if (headingDiff > 180) -// headingDiff = fabs(headingDiff - 360); -//} - void FGTaxiSegment::block(int id, time_t blockTime, time_t now) { BlockListIterator i = blockTimes.begin(); @@ -193,7 +177,7 @@ bool FGTaxiRoute::next(int *nde, int *rte) SG_LOG(SG_GENERAL, SG_ALERT, "ALERT: Misconfigured TaxiRoute : " << nodes. size() << " " << routes.size()); - exit(1); + throw sg_range_exception("misconfigured taxi route"); } if (currNode == nodes.end()) return false; @@ -237,15 +221,6 @@ void FGTaxiRoute::rewind(int route) /*************************************************************************** * FGGroundNetwork() **************************************************************************/ -bool compare_nodes(FGTaxiNode * a, FGTaxiNode * b) -{ - return (*a) < (*b); -} - -bool compare_segments(FGTaxiSegment * a, FGTaxiSegment * b) -{ - return (*a) < (*b); -} bool compare_trafficrecords(FGTrafficRecord a, FGTrafficRecord b) { @@ -344,11 +319,11 @@ void FGGroundNetwork::saveElevationCache() { } } cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl; - for (FGTaxiNodeVectorIterator node = nodes.begin(); + for (IndexTaxiNodeMap::iterator node = nodes.begin(); node != nodes.end(); node++) { if (saveData) { - cachefile << (*node)->getIndex () << " " - << (*node)->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " " + cachefile << node->second->getIndex () << " " + << node->second->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " " << endl; } } @@ -357,33 +332,29 @@ void FGGroundNetwork::saveElevationCache() { } } -void FGGroundNetwork::addSegment(const FGTaxiSegment & seg) +void FGGroundNetwork::addSegment(FGTaxiSegment* seg) { - segments.push_back(new FGTaxiSegment(seg)); + segments.push_back(seg); } -void FGGroundNetwork::addNode(const FGTaxiNode & node) +void FGGroundNetwork::addNode(FGTaxiNode* node) { - nodes.push_back(new FGTaxiNode(node)); + assert(node); + IndexTaxiNodeMap::iterator it = nodes.find(node->getIndex()); + if (it != nodes.end()) { + throw sg_range_exception(); + } + + nodes.insert(it, std::make_pair(node->getIndex(), node)); } void FGGroundNetwork::addNodes(FGParkingVec * parkings) { - FGTaxiNode n; - FGParkingVecIterator i = parkings->begin(); - while (i != parkings->end()) { - n.setIndex(i->getIndex()); - n.setLatitude(i->getLatitude()); - n.setLongitude(i->getLongitude()); - n.setElevation(parent->getElevation()*SG_FEET_TO_METER); - nodes.push_back(new FGTaxiNode(n)); - - i++; - } + BOOST_FOREACH(FGParking* parking, *parkings) { + addNode(parking); + } } - - void FGGroundNetwork::init() { if (networkInitialized) { @@ -394,96 +365,77 @@ void FGGroundNetwork::init() hasNetwork = true; nextSave = 0; int index = 1; - sort(nodes.begin(), nodes.end(), compare_nodes); - //sort(segments.begin(), segments.end(), compare_segments()); - FGTaxiSegmentVectorIterator i = segments.begin(); - while (i != segments.end()) { - (*i)->setStart(&nodes); - (*i)->setEnd(&nodes); - (*i)->setDimensions(parent->getElevation() * SG_FEET_TO_METER); - (*i)->setIndex(index); - if ((*i)->isPushBack()) { - pushBackNodes.push_back((*i)->getEnd()); - } - //SG_LOG(SG_GENERAL, SG_BULK, "initializing segment " << (*i)->getIndex() << endl); - //SG_LOG(SG_GENERAL, SG_BULK, "Track distance = " << (*i)->getLength() << endl); - //SG_LOG(SG_GENERAL, SG_BULK, "Track runs from " << (*i)->getStart()->getIndex() << " to " - // << (*i)->getEnd()->getIndex() << endl); - i++; - index++; - } - - i = segments.begin(); - while (i != segments.end()) { - FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute(); - while (j != (*i)->getEnd()->getEndRoute()) { - if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex()) { -// int start1 = (*i)->getStart()->getIndex(); -// int end1 = (*i)->getEnd() ->getIndex(); -// int start2 = (*j)->getStart()->getIndex(); -// int end2 = (*j)->getEnd()->getIndex(); -// int oppIndex = (*j)->getIndex(); - //cerr << "Opposite of " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") " - // << "happens to be " << oppIndex << " (" << start2 << "," << end2 << ") " << endl; - (*i)->setOpposite(*j); - break; - } - j++; - } - i++; + + // bind segments to nodes + BOOST_FOREACH(FGTaxiSegment* segment, segments) { + if (!segment->bindToNodes(nodes)) { + SG_LOG(SG_GENERAL, SG_ALERT, "unable to bind taxiway segment"); + } + + segment->setIndex(index++); + if (segment->isPushBack()) { + pushBackNodes.push_back(segment->getEnd()); + } + } + + // establish pairing of segments + BOOST_FOREACH(FGTaxiSegment* segment, segments) { + FGTaxiSegment* opp = segment->getEnd()->getArcTo(segment->getStart()); + if (opp) { + segment->setOpposite(opp); + } } - //FGTaxiNodeVectorIterator j = nodes.begin(); - //while (j != nodes.end()) { - // if ((*j)->getHoldPointType() == 3) { - // pushBackNodes.push_back((*j)); - // } - // j++; - //} - //cerr << "Done initializing ground network" << endl; - //exit(1); + if (fgGetBool("/sim/ai/groundnet-cache")) { - SGPath cacheData(globals->get_fg_home()); - cacheData.append("ai"); - string airport = parent->getId(); + parseCache(); + } + + networkInitialized = true; +} - if ((airport) != "") { - char buffer[128]; - ::snprintf(buffer, 128, "%c/%c/%c/", - airport[0], airport[1], airport[2]); - cacheData.append(buffer); - if (!cacheData.exists()) { - cacheData.create_dir(0777); - } - int index; - double elev; - cacheData.append(airport + "-groundnet-cache.txt"); - if (cacheData.exists()) { - ifstream data(cacheData.c_str()); - string revisionStr; - data >> revisionStr; - if (revisionStr != "[GroundNetcachedata:ref:2011:09:04]") { - SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " << - cacheData.c_str() << " for Airport " << airport); - } else { - for (FGTaxiNodeVectorIterator i = nodes.begin(); - i != nodes.end(); - i++) { - (*i)->setElevation(parent->getElevation() * SG_FEET_TO_METER); - data >> index >> elev; - if (data.eof()) - break; - if (index != (*i)->getIndex()) { - SG_LOG(SG_GENERAL, SG_ALERT, "Index read from ground network cache at airport " << airport << " does not match index in the network itself"); - } else { - (*i)->setElevation(elev); - } - } - } - } +void FGGroundNetwork::parseCache() +{ + SGPath cacheData(globals->get_fg_home()); + cacheData.append("ai"); + string airport = parent->getId(); + + if (airport.empty()) { + return; + } + + char buffer[128]; + ::snprintf(buffer, 128, "%c/%c/%c/", + airport[0], airport[1], airport[2]); + cacheData.append(buffer); + if (!cacheData.exists()) { + cacheData.create_dir(0777); + } + int index; + double elev; + cacheData.append(airport + "-groundnet-cache.txt"); + if (cacheData.exists()) { + ifstream data(cacheData.c_str()); + string revisionStr; + data >> revisionStr; + if (revisionStr != "[GroundNetcachedata:ref:2011:09:04]") { + SG_LOG(SG_GENERAL, SG_ALERT,"GroundNetwork Warning: discarding outdated cachefile " << + cacheData.c_str() << " for Airport " << airport); + } else { + for (IndexTaxiNodeMap::iterator i = nodes.begin(); + i != nodes.end(); + i++) { + i->second->setElevation(parent->elevation() * SG_FEET_TO_METER); + data >> index >> elev; + if (data.eof()) + break; + if (index != i->second->getIndex()) { + SG_LOG(SG_GENERAL, SG_ALERT, "Index read from ground network cache at airport " << airport << " does not match index in the network itself"); + } else { + i->second->setElevation(elev); } + } } - //cerr << "Finished initializing " << parent->getId() << " groundnetwork " << endl; - networkInitialized = true; + } } int FGGroundNetwork::findNearestNode(const SGGeod & aGeod) @@ -491,13 +443,12 @@ int FGGroundNetwork::findNearestNode(const SGGeod & aGeod) double minDist = HUGE_VAL; int index = -1; - for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end(); - itr++) { - double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod()); + IndexTaxiNodeMap::iterator i; + for (i = nodes.begin(); i != nodes.end(); i++) { + double d = SGGeodesy::distanceM(aGeod, i->second->geod()); if (d < minDist) { minDist = d; - index = (*itr)->getIndex(); - //cerr << "Minimum distance of " << minDist << " for index " << index << endl; + index = i->first; } } @@ -509,42 +460,30 @@ int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod) double minDist = HUGE_VAL; int index = -1; - for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end(); - itr++) { - if (!((*itr)->getIsOnRunway())) { + IndexTaxiNodeMap::iterator i; + for (i = nodes.begin(); i != nodes.end(); i++) { + if (!i->second->getIsOnRunway()) { continue; } - double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod()); + + double d = SGGeodesy::distanceM(aGeod, i->second->geod()); if (d < minDist) { minDist = d; - index = (*itr)->getIndex(); - //cerr << "Minimum distance of " << minDist << " for index " << index << endl; + index = i->first; } } return index; } - -int FGGroundNetwork::findNearestNode(double lat, double lon) -{ - return findNearestNode(SGGeod::fromDeg(lon, lat)); -} - -FGTaxiNode *FGGroundNetwork::findNode(unsigned idx) -{ /* - for (FGTaxiNodeVectorIterator - itr = nodes.begin(); - itr != nodes.end(); itr++) - { - if (itr->getIndex() == idx) - return itr->getAddress(); - } */ - - if (idx < nodes.size()) - return nodes[idx]->getAddress(); - else - return 0; +FGTaxiNode* FGGroundNetwork::findNode(unsigned int idx) +{ + IndexTaxiNodeMap::iterator i = nodes.find(idx); + if (i == nodes.end()) { + return NULL; + } + + return i->second; } FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx) @@ -558,7 +497,7 @@ FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx) } */ if ((idx > 0) && (idx <= segments.size())) - return segments[idx - 1]->getAddress(); + return segments[idx - 1]; else { //cerr << "Alert: trying to find invalid segment " << idx << endl; return 0; @@ -575,18 +514,22 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, //double INFINITE = 100000000000.0; // initialize scoring values int nParkings = parent->getDynamics()->getNrOfParkings(); - FGTaxiNodeVector *currNodesSet; + FGTaxiNodeVector unvisited; + if (fullSearch) { - currNodesSet = &nodes; + // create vector from map values + IndexTaxiNodeMap::iterator i; + for (i = nodes.begin(); i != nodes.end(); i++) { + unvisited.push_back(i->second); + } } else { - currNodesSet = &pushBackNodes; + unvisited = pushBackNodes; } - - for (FGTaxiNodeVectorIterator - itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) { - (*itr)->setPathScore(HUGE_VAL); //infinity by all practical means - (*itr)->setPreviousNode(0); // - (*itr)->setPreviousSeg(0); // + + BOOST_FOREACH(FGTaxiNode* node, unvisited) { + node->setPathScore(HUGE_VAL); //infinity by all practical means + node->setPreviousNode(0); // + node->setPreviousSeg(0); // } FGTaxiNode *firstNode = findNode(start); @@ -608,49 +551,38 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, return FGTaxiRoute(); } - FGTaxiNodeVector unvisited(*currNodesSet); // working copy - while (!unvisited.empty()) { - FGTaxiNode *best = *(unvisited.begin()); - for (FGTaxiNodeVectorIterator - itr = unvisited.begin(); itr != unvisited.end(); itr++) { - if ((*itr)->getPathScore() < best->getPathScore()) - best = (*itr); + FGTaxiNode *best = unvisited.front(); + BOOST_FOREACH(FGTaxiNode* i, unvisited) { + if (i->getPathScore() < best->getPathScore()) { + best = i; + } } + // remove 'best' from the unvisited set FGTaxiNodeVectorIterator newend = remove(unvisited.begin(), unvisited.end(), best); unvisited.erase(newend, unvisited.end()); if (best == lastNode) { // found route or best not connected break; - } else { - for (FGTaxiSegmentVectorIterator - seg = best->getBeginRoute(); - seg != best->getEndRoute(); seg++) { - if (fullSearch || (*seg)->isPushBack()) { - FGTaxiNode *tgt = (*seg)->getEnd(); - if (!tgt) - { - SG_LOG(SG_GENERAL, SG_ALERT, - "Error in ground network. Found empty segment " - << " at " << ((parent) ? parent->getId() : "")); - return FGTaxiRoute(); - } - double alt = - best->getPathScore() + (*seg)->getLength() + - (*seg)->getPenalty(nParkings); - if (alt < tgt->getPathScore()) { // Relax (u,v) - tgt->setPathScore(alt); - tgt->setPreviousNode(best); - tgt->setPreviousSeg(*seg); // - } - } else { - // // cerr << "Skipping TaxiSegment " << (*seg)->getIndex() << endl; - } - } } - } + + BOOST_FOREACH(FGTaxiSegment* seg, best->arcs()) { + if (!fullSearch && !seg->isPushBack()) { + continue; // inelligible! + } + + FGTaxiNode *tgt = seg->getEnd(); + double alt = best->getPathScore() + seg->getLength() + + seg->getPenalty(nParkings); + if (alt < tgt->getPathScore()) { // Relax (u,v) + tgt->setPathScore(alt); + tgt->setPreviousNode(best); + tgt->setPreviousSeg(seg); + } + } // of outgoing arcs/segments from current best node iteration + } // of unvisited nodes remaining if (lastNode->getPathScore() == HUGE_VAL) { // no valid route found @@ -1080,7 +1012,7 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat, } bool origStatus = current->hasHoldPosition(); current->setHoldPosition(false); - SGGeod curr(SGGeod::fromDegM(lon, lat, alt)); + //SGGeod curr(SGGeod::fromDegM(lon, lat, alt)); int currentRoute = i->getCurrentPosition(); int nextRoute; if (i->getIntentions().size()) { @@ -1100,7 +1032,7 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat, // current->setHoldPosition(true); //} SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude()))); - SGGeod end (SGGeod::fromDeg(nx->getStart()->getLongitude(), nx->getStart()->getLatitude())); + SGGeod end (nx->getStart()->geod()); double distance = SGGeodesy::distanceM(start, end); if (nx->hasBlock(now) && (distance < i->getRadius() * 4)) { @@ -1379,10 +1311,10 @@ void FGGroundNetwork::render(bool visible) if (pos >= 0) { SGGeod start(SGGeod::fromDeg((i->getLongitude()), (i->getLatitude()))); - SGGeod end (SGGeod::fromDeg(segments[pos]->getEnd()->getLongitude(), segments[pos]->getEnd()->getLatitude())); + SGGeod end (segments[pos]->getEnd()->geod()); double length = SGGeodesy::distanceM(start, end); - //heading = SGGeodesy::headingDeg(start->getGeod(), end->getGeod()); + //heading = SGGeodesy::headingDeg(start->geod(), end->geod()); double az2, heading; //, distanceM; SGGeodesy::inverse(start, end, heading, az2, length); @@ -1466,7 +1398,7 @@ void FGGroundNetwork::render(bool visible) double elevationStart = segments[k]->getStart()->getElevationM(parent->getElevation()*SG_FEET_TO_METER); double elevationEnd = segments[k]->getEnd ()->getElevationM(parent->getElevation()*SG_FEET_TO_METER); if ((elevationStart == 0) || (elevationStart == parent->getElevation())) { - SGGeod center2 = segments[k]->getStart()->getGeod(); + SGGeod center2 = segments[k]->getStart()->geod(); center2.setElevationM(SG_MAX_ELEVATION_M); if (local_scenery->get_elevation_m( center2, elevationStart, NULL )) { // elevation_feet = elevationStart * SG_METER_TO_FEET + 0.5; @@ -1478,7 +1410,7 @@ void FGGroundNetwork::render(bool visible) segments[k]->getStart()->setElevation(elevationStart); } if ((elevationEnd == 0) || (elevationEnd == parent->getElevation())) { - SGGeod center2 = segments[k]->getEnd()->getGeod(); + SGGeod center2 = segments[k]->getEnd()->geod(); center2.setElevationM(SG_MAX_ELEVATION_M); if (local_scenery->get_elevation_m( center2, elevationEnd, NULL )) { // elevation_feet = elevationEnd * SG_METER_TO_FEET + 0.5; @@ -1497,8 +1429,8 @@ void FGGroundNetwork::render(bool visible) // cerr << "2. Using mean elevation : " << elevationMean << " and " << slope << endl; - - WorldCoordinate( obj_pos, segments[k]->getLatitude(), segments[k]->getLongitude(), elevationMean+ 0.5, -(segments[k]->getHeading()), slope ); + SGGeod segCenter = segments[k]->getCenter(); + WorldCoordinate( obj_pos, segCenter.getLatitudeDeg(), segCenter.getLongitudeDeg(), elevationMean+ 0.5, -(segments[k]->getHeading()), slope ); obj_trans->setMatrix( obj_pos ); //osg::Vec3 center(0, 0, 0) diff --git a/src/Airports/groundnetwork.hxx b/src/Airports/groundnetwork.hxx index b79bdfc69..35fd03c0d 100644 --- a/src/Airports/groundnetwork.hxx +++ b/src/Airports/groundnetwork.hxx @@ -24,17 +24,12 @@ #ifndef _GROUNDNETWORK_HXX_ #define _GROUNDNETWORK_HXX_ -#include -#include -#include -#include - - #include #include #include #include +#include class Block; @@ -48,10 +43,9 @@ class FGAIFlightPlan; // forward reference class FGAirport; // forward reference typedef std::vector FGTaxiSegmentVector; -typedef std::vector::iterator FGTaxiSegmentVectorIterator; +typedef FGTaxiSegmentVector::iterator FGTaxiSegmentVectorIterator; -//typedef vector FGTaxiSegmentPointerVector; -//typedef vector::iterator FGTaxiSegmentPointerVectorIterator; +typedef std::map IndexTaxiNodeMap; class Block { @@ -82,7 +76,6 @@ private: int endNode; double length; double heading; - SGGeod center; bool isActive; bool isPushBackRoute; BlockList blockTimes; @@ -91,75 +84,19 @@ private: int index; FGTaxiSegment *oppositeDirection; - - public: - FGTaxiSegment() : - startNode(0), - endNode(0), - length(0), - heading(0), - isActive(0), - isPushBackRoute(0), - start(0), - end(0), - index(0), - oppositeDirection(0) - { - }; - - FGTaxiSegment (const FGTaxiSegment &other) : - startNode (other.startNode), - endNode (other.endNode), - length (other.length), - heading (other.heading), - center (other.center), - isActive (other.isActive), - isPushBackRoute (other.isPushBackRoute), - blockTimes (other.blockTimes), - start (other.start), - end (other.end), - index (other.index), - oppositeDirection (other.oppositeDirection) - { - }; - - FGTaxiSegment& operator=(const FGTaxiSegment &other) - { - startNode = other.startNode; - endNode = other.endNode; - length = other.length; - heading = other.heading; - center = other.center; - isActive = other.isActive; - isPushBackRoute = other.isPushBackRoute; - blockTimes = other.blockTimes; - start = other.start; - end = other.end; - index = other.index; - oppositeDirection = other.oppositeDirection; - return *this; - }; - + FGTaxiSegment(int start, int end, bool isPushBack); + void setIndex (int val) { index = val; }; - void setStartNodeRef (int val) { - startNode = val; - }; - void setEndNodeRef (int val) { - endNode = val; - }; void setOpposite(FGTaxiSegment *opp) { oppositeDirection = opp; }; - void setStart(FGTaxiNodeVector *nodes); - void setEnd (FGTaxiNodeVector *nodes); - void setPushBackType(bool val) { - isPushBackRoute = val; - }; + bool bindToNodes(const IndexTaxiNodeMap& nodes); + void setDimensions(double elevation); void block(int id, time_t blockTime, time_t now); void unblock(time_t now); @@ -177,12 +114,10 @@ public: int getIndex() { return index; }; - double getLatitude() { - return center.getLatitudeDeg(); - }; - double getLongitude() { - return center.getLongitudeDeg(); - }; + + // compute the center of the arc + SGGeod getCenter() const; + double getHeading() { return heading; }; @@ -192,10 +127,6 @@ public: int getPenalty(int nGates); - FGTaxiSegment *getAddress() { - return this; - }; - bool operator<(const FGTaxiSegment &other) const { return index < other.index; }; @@ -203,11 +134,6 @@ public: FGTaxiSegment *opposite() { return oppositeDirection; }; - void setCourseDiff(double crse); - - - - }; @@ -304,12 +230,12 @@ private: //int maxDepth; int count; int version; - FGTaxiNodeVector nodes; - FGTaxiNodeVector pushBackNodes; + + IndexTaxiNodeMap nodes; + FGTaxiNodeVector pushBackNodes; + FGTaxiSegmentVector segments; - //intVec route; - //intVec nodesStack; - //intVec routesStack; + TaxiRouteVector routes; TrafficVector activeTraffic; TrafficVectorIterator currTraffic; @@ -328,14 +254,14 @@ private: double heading, double speed, double alt); - + void parseCache(); public: FGGroundNetwork(); ~FGGroundNetwork(); - void addNode (const FGTaxiNode& node); + void addNode (FGTaxiNode* node); void addNodes (FGParkingVec *parkings); - void addSegment(const FGTaxiSegment& seg); + void addSegment(FGTaxiSegment* seg); void setVersion (int v) { version = v;}; int getVersion() { return version; }; @@ -348,7 +274,6 @@ public: towerController = twrCtrlr; }; - int findNearestNode(double lat, double lon); int findNearestNode(const SGGeod& aGeod); int findNearestNodeOnRunway(const SGGeod& aGeod); diff --git a/src/Airports/parking.cxx b/src/Airports/parking.cxx index d1fb6512f..58928dfcf 100644 --- a/src/Airports/parking.cxx +++ b/src/Airports/parking.cxx @@ -36,21 +36,22 @@ /********************************************************************************* * FGParking ********************************************************************************/ -// FGParking::FGParking(double lat, -// double lon, -// double hdg, -// double rad, -// int idx, -// const string &name, -// const string &tpe, -// const string &codes) -// : FGTaxiNode(lat,lon,idx) -// { -// heading = hdg; -// parkingName = name; -// type = tpe; -// airlineCodes = codes; -// } -FGParking::~FGParking() { - delete pushBackRoute; + +FGParking::FGParking(PositionedID aGuid, int index, const SGGeod& pos, + double aHeading, double aRadius, + const std::string& name, const std::string& aType, + const std::string& codes) : + FGTaxiNode(aGuid, index, pos, false, 0), + heading(aHeading), + radius(aRadius), + parkingName(name), + type(aType), + airlineCodes(codes), + available(true), + pushBackPoint(0) +{ +} + +FGParking::~FGParking() +{ } diff --git a/src/Airports/parking.hxx b/src/Airports/parking.hxx index 1d009c03c..c16038c51 100644 --- a/src/Airports/parking.hxx +++ b/src/Airports/parking.hxx @@ -30,16 +30,19 @@ #endif #include +#include #include #include +#include // for std::auto_ptr #include "gnnode.hxx" class FGTaxiRoute; -class FGParking : public FGTaxiNode { +class FGParking : public FGTaxiNode +{ private: double heading; double radius; @@ -49,46 +52,15 @@ private: bool available; int pushBackPoint; - FGTaxiRoute *pushBackRoute; + std::auto_ptr pushBackRoute; + SG_DISABLE_COPY(FGParking); public: - FGParking() : - heading(0), - radius(0), - available(true), - pushBackPoint(0), - pushBackRoute(0) - { - }; - - FGParking(const FGParking &other) : - FGTaxiNode (other), - heading (other.heading), - radius (other.radius), - parkingName (other.parkingName), - type (other.type), - airlineCodes (other.airlineCodes), - available (other.available), - pushBackPoint(other.pushBackPoint), - pushBackRoute(other.pushBackRoute) - { - }; - - - FGParking& operator =(const FGParking &other) - { - FGTaxiNode::operator=(other); - heading = other.heading; - radius = other.radius; - parkingName = other.parkingName; - type = other.type; - airlineCodes = other.airlineCodes; - available = other.available; - pushBackPoint= other.pushBackPoint; - pushBackRoute= other.pushBackRoute; - return *this; - }; - ~FGParking(); + FGParking(PositionedID aGuid, int index, const SGGeod& pos, + double heading, double radius, + const std::string& name, const std::string& type, + const std::string& codes); + virtual ~FGParking(); void setHeading (double hdg) { heading = hdg; }; void setRadius (double rad) { radius = rad; }; @@ -97,7 +69,7 @@ public: void setType (const std::string& tpe) { type = tpe; }; void setCodes (const std::string& codes){ airlineCodes= codes;}; - void setPushBackRoute(FGTaxiRoute *val) { pushBackRoute = val; }; + void setPushBackRoute(std::auto_ptr val) { pushBackRoute = val; }; void setPushBackPoint(int val) { pushBackPoint = val; }; bool isAvailable () const { return available;}; @@ -110,7 +82,7 @@ public: std::string getCodes () const { return airlineCodes;}; std::string getName () const { return parkingName; }; - FGTaxiRoute * getPushBackRoute () { return pushBackRoute; }; + FGTaxiRoute * getPushBackRoute () { return pushBackRoute.get(); }; int getPushBackPoint () { return pushBackPoint; }; @@ -118,8 +90,8 @@ public: return radius < other.radius; }; }; -typedef std::vector FGParkingVec; -typedef std::vector::iterator FGParkingVecIterator; -typedef std::vector::const_iterator FGParkingVecConstIterator; +typedef std::vector FGParkingVec; +typedef FGParkingVec::iterator FGParkingVecIterator; +typedef FGParkingVec::const_iterator FGParkingVecConstIterator; #endif diff --git a/src/Main/positioninit.cxx b/src/Main/positioninit.cxx index fd5db70b1..d4cdd1799 100644 --- a/src/Main/positioninit.cxx +++ b/src/Main/positioninit.cxx @@ -223,7 +223,7 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par FGParking* parking = dcs->getParking(gateID); parking->setAvailable(false); - fgApplyStartOffset(parking->getGeod(), parking->getHeading()); + fgApplyStartOffset(parking->geod(), parking->getHeading()); return true; } diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 8c47ea46b..974f7a980 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -143,7 +143,7 @@ const char* FGPositioned::nameForType(Type aTy) case RUNWAY: return "runway"; case TAXIWAY: return "taxiway"; case PAVEMENT: return "pavement"; - case PARK_STAND: return "parking stand"; + case PARKING: return "parking stand"; case FIX: return "fix"; case VOR: return "VOR"; case NDB: return "NDB"; @@ -166,6 +166,7 @@ const char* FGPositioned::nameForType(Type aTy) case FREQ_CLEARANCE: return "clearance"; case FREQ_UNICOM: return "unicom"; case FREQ_APP_DEP: return "approach-departure"; + case TAXI_NODE: return "taxi-node"; default: return "unknown"; } diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index 7b7771b3f..e76ab83f6 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -48,7 +49,6 @@ public: RUNWAY, TAXIWAY, PAVEMENT, - PARK_STAND, WAYPOINT, FIX, NDB, @@ -77,6 +77,9 @@ public: FREQ_ENROUTE, FREQ_CLEARANCE, FREQ_UNICOM, +// groundnet items + PARKING, ///< parking position - might be a gate, or stand + TAXI_NODE, LAST_TYPE } Type; @@ -230,6 +233,9 @@ protected: const SGVec3d mCart; const Type mType; const std::string mIdent; + +private: + SG_DISABLE_COPY(FGPositioned); }; #endif // of FG_POSITIONED_HXX diff --git a/src/Scripting/NasalPositioned.cxx b/src/Scripting/NasalPositioned.cxx index 3ec918cbd..e6b56971c 100644 --- a/src/Scripting/NasalPositioned.cxx +++ b/src/Scripting/NasalPositioned.cxx @@ -1350,7 +1350,7 @@ static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args) continue; } - const SGGeod& parkLoc = park->getGeod(); + const SGGeod& parkLoc = park->geod(); naRef ph = naNewHash(c); hashset(c, ph, "name", stringToNasal(c, park->getName())); hashset(c, ph, "lat", naNum(parkLoc.getLatitudeDeg())); -- 2.39.5