From: James Turner Date: Tue, 1 Dec 2015 00:01:27 +0000 (+0000) Subject: Checkpoint - ground-net skips the cache X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=fc887b106bbb199ffe9c042b8271eae1be26c9aa;p=flightgear.git Checkpoint - ground-net skips the cache --- diff --git a/src/AIModel/AIFlightPlan.hxx b/src/AIModel/AIFlightPlan.hxx index 31e4f8698..ee39a5b5d 100644 --- a/src/AIModel/AIFlightPlan.hxx +++ b/src/AIModel/AIFlightPlan.hxx @@ -187,7 +187,7 @@ private: time_t arrivalTime; // For AI/ATC purposes. int leg; ParkingAssignment gate; - PositionedID lastNodeVisited; + FGTaxiNodeRef lastNodeVisited; std::string activeRunway; std::string name; bool isValid; diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index e39fb57ca..4b055abd6 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -247,11 +247,11 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, return true; } - PositionedID runwayId = 0; + FGTaxiNodeRef runwayNode; if (gn->getVersion() > 0) { - runwayId = gn->findNearestNodeOnRunway(runwayTakeoff); + FGTaxiNodeRef runwayNode = gn->findNearestNodeOnRunway(runwayTakeoff); } else { - runwayId = gn->findNearestNode(runwayTakeoff); + FGTaxiNodeRef runwayNode = gn->findNearestNode(runwayTakeoff); } // A negative gateId indicates an overflow parking, use a @@ -262,17 +262,15 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, // taxiRoute = new FGTaxiRoute; // Determine which node to start from. - PositionedID node = 0; + FGTaxiNodeRef node; // Find out which node to start from FGParking *park = gate.parking(); if (park) { node = park->getPushBackPoint(); - if (node == -1) { - node = park->guid(); - } else if (node == 0) { + if (node == 0) { // Handle case where parking doesn't have a node if (firstFlight) { - node = park->guid(); + node = park; } else { node = lastNodeVisited; } @@ -280,8 +278,8 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, } FGTaxiRoute taxiRoute; - if ( runwayId != 0 ) - taxiRoute = gn->findShortestRoute(node, runwayId); + if ( runwayNode ) + taxiRoute = gn->findShortestRoute(node, runwayNode); if (taxiRoute.empty()) { createDefaultTakeoffTaxi(ac, apt, rwy); @@ -289,6 +287,8 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, } taxiRoute.first(); + FGTaxiNodeRef skipNode; + //bool isPushBackPoint = false; if (firstFlight) { // If this is called during initialization, randomly @@ -298,13 +298,13 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, // but make sure we always keep two active waypoints // to prevent a segmentation fault for (int i = 0; i < nrWaypointsToSkip - 3; i++) { - taxiRoute.next(&node, &route); + taxiRoute.next(skipNode, &route); } gate.release(); // free up our gate as required } else { if (taxiRoute.size() > 1) { - taxiRoute.next(&node, &route); // chop off the first waypoint, because that is already the last of the pushback route + taxiRoute.next(skipNode, &route); // chop off the first waypoint, because that is already the last of the pushback route } } @@ -315,13 +315,11 @@ bool FGAIFlightPlan::createTakeoffTaxi(FGAIAircraft * ac, bool firstFlight, // Note that the line wpt->setRouteIndex was commented out by revision [afcdbd] 2012-01-01, // which breaks the rendering functions. // These can probably be generated on the fly however. - while (taxiRoute.next(&node, &route)) { + while (taxiRoute.next(node, &route)) { char buffer[10]; - snprintf(buffer, 10, "%lld", (long long int) node); - FGTaxiNode *tn = - apt->getDynamics()->getGroundNetwork()->findNode(node); + snprintf(buffer, 10, "%d", node->getIndex()); FGAIWaypoint *wpt = - createOnGround(ac, buffer, tn->geod(), apt->getElevation(), + createOnGround(ac, buffer, node->geod(), apt->getElevation(), ac->getPerformance()->vTaxi()); wpt->setRouteIndex(route); //cerr << "Nodes left " << taxiRoute->nodesLeft() << " "; @@ -388,11 +386,11 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, return true; } - PositionedID runwayId = 0; + FGTaxiNodeRef runwayNode; if (gn->getVersion() == 1) { - runwayId = gn->findNearestNodeOnRunway(lastWptPos); + runwayNode = gn->findNearestNodeOnRunway(lastWptPos); } else { - runwayId = gn->findNearestNode(lastWptPos); + runwayNode = gn->findNearestNode(lastWptPos); } //cerr << "Using network node " << runwayId << endl; // A negative gateId indicates an overflow parking, use a @@ -400,26 +398,25 @@ bool FGAIFlightPlan::createLandingTaxi(FGAIAircraft * ac, FGAirport * apt, // Starting from gate 0 doesn't work, so don't try it FGTaxiRoute taxiRoute; if (gate.isValid()) - taxiRoute = gn->findShortestRoute(runwayId, gate.parking()->guid()); + taxiRoute = gn->findShortestRoute(runwayNode, gate.parking()); if (taxiRoute.empty()) { createDefaultLandingTaxi(ac, apt); return true; } - PositionedID node; + FGTaxiNodeRef node; taxiRoute.first(); int size = taxiRoute.size(); // Omit the last two waypoints, as // those are created by createParking() // int route; for (int i = 0; i < size - 2; i++) { - taxiRoute.next(&node, &route); + taxiRoute.next(node, &route); char buffer[10]; - snprintf(buffer, 10, "%lld", (long long int) node); - FGTaxiNode *tn = gn->findNode(node); + snprintf(buffer, 10, "%d", node->getIndex()); FGAIWaypoint *wpt = - createOnGround(ac, buffer, tn->geod(), apt->getElevation(), + createOnGround(ac, buffer, node->geod(), apt->getElevation(), ac->getPerformance()->vTaxi()); wpt->setRouteIndex(route); @@ -638,10 +635,9 @@ bool FGAIFlightPlan::createDescent(FGAIAircraft * ac, FGAirport * apt, } double dAlt = 0; // = alt - (apt->getElevation() + 2000); - FGTaxiNode * tn = 0; + FGTaxiNodeRef tn; if (apt->getDynamics()->getGroundNetwork()) { - int node = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint); - tn = apt->getDynamics()->getGroundNetwork()->findNode(node); + tn = apt->getDynamics()->getGroundNetwork()->findNearestNode(refPoint); } if (tn) { @@ -967,14 +963,13 @@ bool FGAIFlightPlan::createLanding(FGAIAircraft * ac, FGAirport * apt, } coord = rwy->pointOnCenterline(mindist); - int nodeId = 0; + FGTaxiNodeRef tn; if (gn->getVersion() > 0) { - nodeId = gn->findNearestNodeOnRunway(coord, rwy); + tn = gn->findNearestNodeOnRunway(coord, rwy); } else { - nodeId = gn->findNearestNode(coord); + tn = gn->findNearestNode(coord); } - FGTaxiNode* tn = gn->findNode(nodeId); if (tn) { wpt = createOnGround(ac, buffer, tn->geod(), currElev, vTaxi); pushBackWaypoint(wpt); diff --git a/src/AIModel/AIFlightPlanCreatePushBack.cxx b/src/AIModel/AIFlightPlanCreatePushBack.cxx index d19f61e55..b7bddd76e 100644 --- a/src/AIModel/AIFlightPlanCreatePushBack.cxx +++ b/src/AIModel/AIFlightPlanCreatePushBack.cxx @@ -87,7 +87,7 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, FGGroundNetwork* groundNet = dep->getDynamics()->getGroundNetwork(); FGParking *parking = gate.parking(); if (parking && parking->getPushBackPoint() > 0) { - FGTaxiRoute route = groundNet->findShortestRoute(parking->guid(), parking->getPushBackPoint(), false); + FGTaxiRoute route = groundNet->findShortestRoute(parking, parking->getPushBackPoint(), false); int size = route.size(); if (size < 2) { @@ -96,15 +96,14 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, } route.first(); - PositionedID node; + FGTaxiNodeRef node; int rte; - while (route.next(&node, &rte)) + while (route.next(node, &rte)) { char buffer[10]; - snprintf (buffer, 10, "%lld", (long long int) node); - FGTaxiNode *tn = groundNet->findNode(node); - FGAIWaypoint *wpt = createOnGround(ac, string(buffer), tn->geod(), dep->getElevation(), vTaxiBackward); + snprintf (buffer, 10, "%d", node->getIndex()); + FGAIWaypoint *wpt = createOnGround(ac, string(buffer), node->geod(), dep->getElevation(), vTaxiBackward); /* if (previous) { @@ -128,14 +127,14 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac, ac->setTaxiClearanceRequest(false); double az2 = 0.0; - FGTaxiSegment* pushForwardSegment = dep->getDynamics()->getGroundNetwork()->findSegment(parking->guid(), 0); + FGTaxiSegment* pushForwardSegment = dep->getDynamics()->getGroundNetwork()->findSegment(parking, 0); // there aren't any routes for this parking. if (!pushForwardSegment) { SG_LOG(SG_AI, SG_ALERT, "Gate " << parking->ident() << "doesn't seem to have routes associated with it."); return false; } - lastNodeVisited = pushForwardSegment->getEnd()->getIndex(); + lastNodeVisited = pushForwardSegment->getEnd(); double distance = pushForwardSegment->getLength(); double parkingHeading = parking->getHeading(); diff --git a/src/ATC/atc_mgr.cxx b/src/ATC/atc_mgr.cxx index 0116c68ba..c511b66f6 100644 --- a/src/ATC/atc_mgr.cxx +++ b/src/ATC/atc_mgr.cxx @@ -109,7 +109,7 @@ void FGATCManager::init() { // No valid parking location, so either at the runway or at a random location. if (pk.isValid()) { - dcs->setParkingAvailable(pk.parking()->guid(), false); + dcs->setParkingAvailable(pk.parking(), false); fp = new FGAIFlightPlan; controller = apt->getDynamics()->getStartupController(); int stationFreq = apt->getDynamics()->getGroundFrequency(1); diff --git a/src/Airports/airport.cxx b/src/Airports/airport.cxx index 56cdaf139..13f7a7a87 100644 --- a/src/Airports/airport.cxx +++ b/src/Airports/airport.cxx @@ -90,6 +90,7 @@ FGAirport::FGAirport( PositionedID aGuid, FGAirport::~FGAirport() { + SG_LOG(SG_NAVAID, SG_INFO, "deleting airport:" << ident()); delete _dynamics; } diff --git a/src/Airports/dynamicloader.cxx b/src/Airports/dynamicloader.cxx index b2b435d73..a5b08d4a4 100644 --- a/src/Airports/dynamicloader.cxx +++ b/src/Airports/dynamicloader.cxx @@ -26,6 +26,7 @@ #include #include #include +#include using std::string; @@ -62,21 +63,21 @@ void FGAirportDynamicsXMLLoader::startXML () { void FGAirportDynamicsXMLLoader::endXML () { - std::map::iterator it; - flightgear::NavDataCache* cache = flightgear::NavDataCache::instance(); + ParkingPushbackIndex::const_iterator it; for (it = _parkingPushbacks.begin(); it != _parkingPushbacks.end(); ++it) { - std::map::iterator j = _idMap.find(it->second); - if (j == _idMap.end()) { + NodeIndexMap::const_iterator j = _indexMap.find(it->second); + if (j == _indexMap.end()) { SG_LOG(SG_NAVAID, SG_WARN, "bad groundnet, no node for index:" << it->first); continue; } + + it->first->setPushBackPoint(j->second); - cache->setParkingPushBackRoute(it->first, j->second); } - BOOST_FOREACH(PositionedID id, _unreferencedNodes) { - SG_LOG(SG_NAVAID, SG_WARN, "unreferenced groundnet node:" << id); + BOOST_FOREACH(FGTaxiNodeRef node, _unreferencedNodes) { + SG_LOG(SG_NAVAID, SG_WARN, "unreferenced groundnet node:" << node->ident()); } } @@ -124,14 +125,16 @@ void FGAirportDynamicsXMLLoader::startParking(const XMLAttributes &atts) SGGeod pos(SGGeod::fromDeg(processPosition(lon), processPosition(lat))); - PositionedID guid = flightgear::NavDataCache::instance()->insertParking(gateName + gateNumber, pos, - _dynamics->parent()->guid(), - heading, radius, type, airlineCodes); + FGParkingRef parking(new FGParking(index, + pos, heading, radius, + gateName + gateNumber, + type, airlineCodes)); if (pushBackRoute > 0) { - _parkingPushbacks[guid] = pushBackRoute; + _parkingPushbacks[parking] = pushBackRoute; } - _idMap[index] = guid; + _indexMap[index] = parking; + _dynamics->getGroundNetwork()->addParking(parking); } void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts) @@ -168,15 +171,14 @@ void FGAirportDynamicsXMLLoader::startNode(const XMLAttributes &atts) } } - if (_idMap.find(index) != _idMap.end()) { + if (_indexMap.find(index) != _indexMap.end()) { SG_LOG(SG_NAVAID, 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); + FGTaxiNodeRef node(new FGTaxiNode(index, pos, onRunway, holdPointType)); + _indexMap[index] = node; + _unreferencedNodes.insert(node); } void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts) @@ -201,16 +203,28 @@ void FGAirportDynamicsXMLLoader::startArc(const XMLAttributes &atts) return; } - _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]); + NodeIndexMap::const_iterator it; + FGTaxiNodeRef fromNode, toNode; + it = _indexMap.find(begin); + if (it == _indexMap.end()) { + SG_LOG(SG_NAVAID, SG_WARN, "ground-net: bad edge:" << begin << "->" << end << ", begin index unknown"); + return; + } else { + _unreferencedNodes.erase(it->second); + fromNode = it->second; } + + it = _indexMap.find(end); + if (it == _indexMap.end()) { + SG_LOG(SG_NAVAID, SG_WARN, "ground-net: bad edge:" << begin << "->" << end << ", end index unknown"); + return; + } else { + _unreferencedNodes.erase(it->second); + toNode = it->second; + } + + _arcSet.insert(e); + _dynamics->getGroundNetwork()->addSegment(fromNode, toNode); } void FGAirportDynamicsXMLLoader::startElement (const char * name, const XMLAttributes &atts) diff --git a/src/Airports/dynamicloader.hxx b/src/Airports/dynamicloader.hxx index 24500a46a..d9a5e7819 100644 --- a/src/Airports/dynamicloader.hxx +++ b/src/Airports/dynamicloader.hxx @@ -19,7 +19,7 @@ #include #include "dynamics.hxx" -#include +#include class FGAirportDynamicsXMLLoader : public XMLVisitor { public: @@ -43,19 +43,21 @@ private: FGAirportDynamics* _dynamics; std::string value; - // map from local (groundnet.xml) to global (nav-cache) IDs for nodes - std::map _idMap; + // map from local (groundnet.xml) ids to parking instances + typedef std::map NodeIndexMap; + NodeIndexMap _indexMap; // data integrity - watch for unreferenced nodes and duplicated edges typedef std::pair IntPair; std::set _arcSet; - std::set _unreferencedNodes; + std::set _unreferencedNodes; // map from allocated parking position to its local push-back node // used to defer binding the push-back node until we've processed // all nodes - std::map _parkingPushbacks; + typedef std::map ParkingPushbackIndex; + ParkingPushbackIndex _parkingPushbacks; }; #endif diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 5d5ed0557..9d17f2b34 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -65,7 +65,7 @@ public: ~ParkingAssignmentPrivate() { - airport->getDynamics()->releaseParking(parking->guid()); + airport->getDynamics()->releaseParking(parking); } void release() @@ -81,8 +81,8 @@ public: } unsigned int refCount; - SGSharedPtr parking; - SGSharedPtr airport; + FGParkingRef parking; + FGAirportRef airport; }; ParkingAssignment::ParkingAssignment() : @@ -179,28 +179,29 @@ FGParking* FGAirportDynamics::innerGetAvailableParking(double radius, const stri const string & airline, bool skipEmptyAirlineCode) { - flightgear::NavDataCache* cache = flightgear::NavDataCache::instance(); - BOOST_FOREACH(PositionedID pk, cache->findAirportParking(_ap->guid(), flType, radius)) { - if (!isParkingAvailable(pk)) { - continue; - } - - FGParking* parking = getParking(pk); - if (skipEmptyAirlineCode && parking->getCodes().empty()) { - continue; - } - - if (!airline.empty() && !parking->getCodes().empty()) { - if (parking->getCodes().find(airline, 0) == string::npos) { - continue; - } + const FGParkingList& parkings(groundNetwork.allParkings()); + FGParkingList::const_iterator it; + for (it = parkings.begin(); it != parkings.end(); ++it) { + FGParkingRef parking = *it; + if (!isParkingAvailable(parking)) { + continue; + } + + if (skipEmptyAirlineCode && parking->getCodes().empty()) { + continue; + } + + if (!airline.empty() && !parking->getCodes().empty()) { + if (parking->getCodes().find(airline, 0) == string::npos) { + continue; + } + } + + setParkingAvailable(parking, false); + return parking; } - - setParkingAvailable(pk, false); - return parking; - } - - return NULL; + + return NULL; } ParkingAssignment FGAirportDynamics::getAvailableParking(double radius, const string & flType, @@ -226,46 +227,34 @@ ParkingAssignment FGAirportDynamics::getAvailableParking(double radius, const st return result ? ParkingAssignment(result, _ap) : ParkingAssignment(); } -FGParkingRef FGAirportDynamics::getParking(PositionedID id) const -{ - return FGPositioned::loadById(id); -} - -string FGAirportDynamics::getParkingName(PositionedID id) const -{ - FGParking* p = getParking(id); - if (p) { - return p->getName(); - } - - return string(); -} - ParkingAssignment FGAirportDynamics::getParkingByName(const std::string& name) const { - PositionedID guid = flightgear::NavDataCache::instance()->airportItemWithIdent(parent()->guid(), FGPositioned::PARKING, name); - if (guid == 0) { - return ParkingAssignment(); - } - - return ParkingAssignment(getParking(guid), _ap); + const FGParkingList& parkings(groundNetwork.allParkings()); + FGParkingList::const_iterator it; + for (it = parkings.begin(); it != parkings.end(); ++it) { + if ((*it)->name() == name) { + return ParkingAssignment(*it, _ap); + } + } + + return ParkingAssignment(); } -void FGAirportDynamics::setParkingAvailable(PositionedID guid, bool available) +void FGAirportDynamics::setParkingAvailable(FGParking* park, bool available) { if (available) { - releaseParking(guid); + releaseParking(park); } else { - occupiedParkings.insert(guid); + occupiedParkings.insert(park); } } -bool FGAirportDynamics::isParkingAvailable(PositionedID parking) const +bool FGAirportDynamics::isParkingAvailable(FGParking* parking) const { return (occupiedParkings.find(parking) == occupiedParkings.end()); } -void FGAirportDynamics::releaseParking(PositionedID id) +void FGAirportDynamics::releaseParking(FGParking* id) { ParkingSet::iterator it = occupiedParkings.find(id); if (it == occupiedParkings.end()) { @@ -275,6 +264,41 @@ void FGAirportDynamics::releaseParking(PositionedID id) occupiedParkings.erase(it); } +class GetParkingsPredicate +{ + bool mustBeAvailable; + std::string type; + const FGAirportDynamics* dynamics; +public: + GetParkingsPredicate(bool b, const std::string& ty, const FGAirportDynamics* dyn) : + mustBeAvailable(b), + type(ty), + dynamics(dyn) + {} + + bool operator()(const FGParkingRef& park) const + { + if (!type.empty() && (park->getType() != type)) + return true; + + if (mustBeAvailable && !dynamics->isParkingAvailable(park)) { + return true; + } + + return false; + } +}; + +FGParkingList FGAirportDynamics::getParkings(bool onlyAvailable, const std::string &type) const +{ + FGParkingList result(groundNetwork.allParkings()); + + GetParkingsPredicate pred(onlyAvailable, type, this); + FGParkingList::iterator it = std::remove_if(result.begin(), result.end(), pred); + result.erase(it, result.end()); + return result; +} + void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref) { rwyPrefs = ref; diff --git a/src/Airports/dynamics.hxx b/src/Airports/dynamics.hxx index 1368570da..75a97f598 100644 --- a/src/Airports/dynamics.hxx +++ b/src/Airports/dynamics.hxx @@ -58,10 +58,12 @@ class FGAirportDynamics { private: FGAirport* _ap; - typedef std::set ParkingSet; + typedef std::set ParkingSet; // if a parking item is in this set, it is occupied ParkingSet occupiedParkings; + + FGRunwayPreference rwyPrefs; FGStartupController startupController; FGGroundNetwork groundNetwork; @@ -134,13 +136,14 @@ public: ParkingAssignment getAvailableParking(double radius, const std::string& fltype, const std::string& acType, const std::string& airline); - void setParkingAvailable(PositionedID guid, bool available); + void setParkingAvailable(FGParking* park, bool available); - bool isParkingAvailable(PositionedID parking) const; + bool isParkingAvailable(FGParking* parking) const; - FGParkingRef getParking(PositionedID i) const; - void releaseParking(PositionedID id); - std::string getParkingName(PositionedID i) const; + FGParkingRef getParking(FGParking* i) const; + void releaseParking(FGParking* id); + + FGParkingList getParkings(bool onlyAvailable, const std::string& type) const; /** * Find a parking gate index by name. Note names are often not unique diff --git a/src/Airports/gnnode.cxx b/src/Airports/gnnode.cxx index 619e2e115..84f3aac54 100644 --- a/src/Airports/gnnode.cxx +++ b/src/Airports/gnnode.cxx @@ -14,10 +14,12 @@ using namespace flightgear; * FGTaxiNode *************************************************************************/ -FGTaxiNode::FGTaxiNode(PositionedID aGuid, const SGGeod& pos, bool aOnRunway, int aHoldType) : - FGPositioned(aGuid, FGPositioned::PARKING, "", pos), +FGTaxiNode::FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType) : + FGPositioned(TRANSIENT_ID, FGPositioned::PARKING, "", pos), + m_index(index), isOnRunway(aOnRunway), - holdType(aHoldType) + holdType(aHoldType), + m_isPushback(false) { } @@ -45,16 +47,23 @@ double FGTaxiNode::getElevationFt() SGGeod newPos = pos; newPos.setElevationM(elevationEnd); // this will call modifyPosition to update mPosition - NavDataCache* cache = NavDataCache::instance(); - NavDataCache::Transaction txn(cache); - cache->updatePosition(guid(), newPos); - txn.commit(); + modifyPosition(newPos); } } return pos.getElevationFt(); } +int FGTaxiNode::getIndex() const +{ + return m_index; +} + +void FGTaxiNode::setIsPushback() +{ + m_isPushback = true; +} + double FGTaxiNode::getElevationM() { return getElevationFt() * SG_FEET_TO_METER; diff --git a/src/Airports/gnnode.hxx b/src/Airports/gnnode.hxx index 2d4c16a9e..437bc5a86 100644 --- a/src/Airports/gnnode.hxx +++ b/src/Airports/gnnode.hxx @@ -24,11 +24,14 @@ class FGTaxiNode : public FGPositioned { protected: + const int m_index; + bool isOnRunway; int holdType; + bool m_isPushback; public: - FGTaxiNode(PositionedID aGuid, const SGGeod& pos, bool aOnRunway, int aHoldType); + FGTaxiNode(int index, const SGGeod& pos, bool aOnRunway, int aHoldType); virtual ~FGTaxiNode(); void setElevation(double val); @@ -36,9 +39,13 @@ public: double getElevationM (); double getElevationFt(); - PositionedID getIndex() const { return guid(); }; + int getIndex() const; + int getHoldPointType() const { return holdType; }; bool getIsOnRunway() const { return isOnRunway; }; + bool isPushback() const { return m_isPushback; } + + void setIsPushback(); }; #endif diff --git a/src/Airports/groundnetwork.cxx b/src/Airports/groundnetwork.cxx index a6ad1f5c4..a2c9b39ae 100644 --- a/src/Airports/groundnetwork.cxx +++ b/src/Airports/groundnetwork.cxx @@ -65,7 +65,7 @@ using flightgear::NavDataCache; * FGTaxiSegment **************************************************************************/ -FGTaxiSegment::FGTaxiSegment(PositionedID aStart, PositionedID aEnd) : +FGTaxiSegment::FGTaxiSegment(FGTaxiNode* aStart, FGTaxiNode* aEnd) : startNode(aStart), endNode(aEnd), isActive(0), @@ -84,12 +84,12 @@ SGGeod FGTaxiSegment::getCenter() const FGTaxiNodeRef FGTaxiSegment::getEnd() const { - return FGPositioned::loadById(endNode); + return const_cast(endNode); } FGTaxiNodeRef FGTaxiSegment::getStart() const { - return FGPositioned::loadById(startNode); + return const_cast(startNode); } double FGTaxiSegment::getLength() const @@ -145,7 +145,7 @@ void FGTaxiSegment::unblock(time_t now) /*************************************************************************** * FGTaxiRoute **************************************************************************/ -bool FGTaxiRoute::next(PositionedID *nde, int *rte) +bool FGTaxiRoute::next(FGTaxiNodeRef& node, int *rte) { if (nodes.size() != (routes.size()) + 1) { SG_LOG(SG_GENERAL, SG_ALERT, "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size()); @@ -153,7 +153,7 @@ bool FGTaxiRoute::next(PositionedID *nde, int *rte) } if (currNode == nodes.end()) return false; - *nde = *(currNode); + node = *(currNode); if (currNode != nodes.begin()) { *rte = *(currRoute); currRoute++; @@ -191,63 +191,19 @@ FGGroundNetwork::FGGroundNetwork() : FGGroundNetwork::~FGGroundNetwork() { -// JMT 2012-09-8 - disabling the groundnet-caching as part of enabling the -// navcache. The problem isn't the NavCache - it's that for the past few years, -// we have not being running destructors on FGPositioned classes, and hence, -// not running this code. -// When I fix FGPositioned lifetimes (unloading-at-runtime support), this -// will need to be re-visited so it can run safely during shutdown. -#if 0 - saveElevationCache(); -#endif + BOOST_FOREACH(FGTaxiSegment* seg, segments) { delete seg; } -} -void FGGroundNetwork::saveElevationCache() -{ -#if 0 - bool saveData = false; - ofstream cachefile; - if (fgGetBool("/sim/ai/groundnet-cache")) { - SGPath cacheData(globals->get_fg_home()); - cacheData.append("ai"); - string airport = parent->getId(); - - 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(0755); - } - cacheData.append(airport + "-groundnet-cache.txt"); - cachefile.open(cacheData.str().c_str()); - saveData = true; - } - } - cachefile << "[GroundNetcachedata:ref:2011:09:04]" << endl; - for (IndexTaxiNodeMap::iterator node = nodes.begin(); - node != nodes.end(); node++) { - if (saveData) { - cachefile << node->second->getIndex () << " " - << node->second->getElevationM (parent->getElevation()*SG_FEET_TO_METER) << " " - << endl; - } - } - if (saveData) { - cachefile.close(); - } -#endif + // owning references to ground-net nodes will also drop } void FGGroundNetwork::init(FGAirport* pr) { if (networkInitialized) { + SG_LOG(SG_GENERAL, SG_WARN, "duplicate ground-network init"); FGATCController::init(); - //cerr << "FGground network already initialized" << endl; return; } @@ -257,7 +213,6 @@ void FGGroundNetwork::init(FGAirport* pr) nextSave = 0; int index = 1; - loadSegments(); // establish pairing of segments BOOST_FOREACH(FGTaxiSegment* segment, segments) { @@ -274,87 +229,53 @@ void FGGroundNetwork::init(FGAirport* pr) opp->oppositeDirection = segment; } } - - if (fgGetBool("/sim/ai/groundnet-cache")) { - parseCache(); - } networkInitialized = true; } -void FGGroundNetwork::loadSegments() +FGTaxiNodeRef FGGroundNetwork::findNearestNode(const SGGeod & aGeod) const { - flightgear::NavDataCache* cache = flightgear::NavDataCache::instance(); -// iterate over all ground-net nodes in this airport - BOOST_FOREACH(PositionedID node, cache->groundNetNodes(parent->guid(), false)) { - // find all segments leaving the node - BOOST_FOREACH(PositionedID end, cache->groundNetEdgesFrom(node, false)) { - segments.push_back(new FGTaxiSegment(node, end)); + double d = DBL_MAX; + SGVec3d cartPos = SGVec3d::fromGeod(aGeod); + FGTaxiNodeRef result; + + FGTaxiNodeVector::const_iterator it; + for (it = m_nodes.begin(); it != m_nodes.end(); ++it) { + double localDistanceSqr = distSqr(cartPos, (*it)->cart()); + if (localDistanceSqr < d) { + d = localDistanceSqr; + result = *it; + } } - } + + return result; } -void FGGroundNetwork::parseCache() +FGTaxiNodeRef FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod, FGRunway* aRunway) const { - SGPath cacheData(globals->get_fg_home()); - cacheData.append("ai"); - string airport = parent->getId(); - - if (airport.empty()) { - return; - } -#if 0 - char buffer[128]; - ::snprintf(buffer, 128, "%c/%c/%c/", - airport[0], airport[1], airport[2]); - cacheData.append(buffer); - if (!cacheData.exists()) { - cacheData.create_dir(0755); - } - 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); + SG_UNUSED(aRunway); + + double d = DBL_MAX; + SGVec3d cartPos = SGVec3d::fromGeod(aGeod); + FGTaxiNodeRef result = 0; + FGTaxiNodeVector::const_iterator it; + for (it = m_nodes.begin(); it != m_nodes.end(); ++it) { + if (!(*it)->getIsOnRunway()) + continue; + + double localDistanceSqr = distSqr(cartPos, (*it)->cart()); + if (localDistanceSqr < d) { + d = localDistanceSqr; + result = *it; } - } } - } -#endif -} - -int FGGroundNetwork::findNearestNode(const SGGeod & aGeod) const -{ - const bool onRunway = false; - return NavDataCache::instance()->findGroundNetNode(parent->guid(), aGeod, onRunway); -} -int FGGroundNetwork::findNearestNodeOnRunway(const SGGeod & aGeod, FGRunway* aRunway) const -{ - const bool onRunway = true; - return NavDataCache::instance()->findGroundNetNode(parent->guid(), aGeod, onRunway, aRunway); + return result; } -FGTaxiNodeRef FGGroundNetwork::findNode(PositionedID idx) const +const FGParkingList &FGGroundNetwork::allParkings() const { - return FGPositioned::loadById(idx); + return m_parkings; } FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx) const @@ -367,7 +288,7 @@ FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx) const } } -FGTaxiSegment* FGGroundNetwork::findSegment(PositionedID from, PositionedID to) const +FGTaxiSegment* FGGroundNetwork::findSegment(const FGTaxiNode* from, const FGTaxiNode* to) const { if (from == 0) { return NULL; @@ -405,41 +326,22 @@ public: FGTaxiNodeRef previousNode; }; -FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID end, - bool fullSearch) +FGTaxiRoute FGGroundNetwork::findShortestRoute(FGTaxiNode* start, FGTaxiNode* end, bool fullSearch) { + if (!start || !end) { + throw sg_exception("Bad arguments to findShortestRoute"); + } //implements Dijkstra's algorithm to find shortest distance route from start to end //taken from http://en.wikipedia.org/wiki/Dijkstra's_algorithm - FGTaxiNodeVector unvisited; - flightgear::NavDataCache* cache = flightgear::NavDataCache::instance(); + FGTaxiNodeVector unvisited(m_nodes); std::map searchData; - - BOOST_FOREACH(PositionedID n, cache->groundNetNodes(parent->guid(), !fullSearch)) { - unvisited.push_back(findNode(n)); - } - - FGTaxiNode *firstNode = findNode(start); - if (!firstNode) - { - SG_LOG(SG_GENERAL, SG_ALERT, - "Error in ground network. Failed to find first waypoint: " << start - << " at " << ((parent) ? parent->getId() : "")); - return FGTaxiRoute(); - } - searchData[firstNode].score = 0.0; - FGTaxiNode *lastNode = findNode(end); - if (!lastNode) - { - SG_LOG(SG_GENERAL, SG_ALERT, - "Error in ground network. Failed to find last waypoint: " << end - << " at " << ((parent) ? parent->getId() : "")); - return FGTaxiRoute(); - } + searchData[start].score = 0.0; while (!unvisited.empty()) { - FGTaxiNode *best = unvisited.front(); - BOOST_FOREACH(FGTaxiNode* i, unvisited) { + // find lowest scored unvisited + FGTaxiNodeRef best = unvisited.front(); + BOOST_FOREACH(FGTaxiNodeRef i, unvisited) { if (searchData[i].score < searchData[best].score) { best = i; } @@ -450,22 +352,21 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID remove(unvisited.begin(), unvisited.end(), best); unvisited.erase(newend, unvisited.end()); - if (best == lastNode) { // found route or best not connected + if (best == end) { // found route or best not connected break; } - BOOST_FOREACH(PositionedID targetId, cache->groundNetEdgesFrom(best->guid(), !fullSearch)) { - FGTaxiNodeRef tgt = FGPositioned::loadById(targetId); - double edgeLength = dist(best->cart(), tgt->cart()); - double alt = searchData[best].score + edgeLength + edgePenalty(tgt); - if (alt < searchData[tgt].score) { // Relax (u,v) - searchData[tgt].score = alt; - searchData[tgt].previousNode = best; + BOOST_FOREACH(FGTaxiNodeRef target, segmentsFrom(best)) { + double edgeLength = dist(best->cart(), target->cart()); + double alt = searchData[best].score + edgeLength + edgePenalty(target); + if (alt < searchData[target].score) { // Relax (u,v) + searchData[target].score = alt; + searchData[target].previousNode = best; } } // of outgoing arcs/segments from current best node iteration } // of unvisited nodes remaining - if (searchData[lastNode].score == HUGE_VAL) { + if (searchData[end].score == HUGE_VAL) { // no valid route found if (fullSearch) { SG_LOG(SG_GENERAL, SG_ALERT, @@ -477,13 +378,13 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID } // assemble route from backtrace information - PositionedIDVec nodes; + FGTaxiNodeVector nodes; intVec routes; - FGTaxiNode *bt = lastNode; + FGTaxiNode *bt = end; while (searchData[bt].previousNode != 0) { - nodes.push_back(bt->guid()); - FGTaxiSegment *segment = findSegment(searchData[bt].previousNode->guid(), bt->guid()); + nodes.push_back(bt); + FGTaxiSegment *segment = findSegment(searchData[bt].previousNode, bt); int idx = segment->getIndex(); routes.push_back(idx); bt = searchData[bt].previousNode; @@ -492,7 +393,7 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(PositionedID start, PositionedID nodes.push_back(start); reverse(nodes.begin(), nodes.end()); reverse(routes.begin(), routes.end()); - return FGTaxiRoute(nodes, routes, searchData[lastNode].score, 0); + return FGTaxiRoute(nodes, routes, searchData[end].score, 0); } /* ATC Related Functions */ @@ -611,11 +512,6 @@ void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon, double heading, double speed, double alt, double dt) { - time_t currentTime = time(NULL); - if (nextSave < currentTime) { - saveElevationCache(); - nextSave = currentTime + 100 + rand() % 200; - } // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to // Transmit air-to-ground "Ready to taxi request: // Transmit ground to air approval / hold @@ -688,6 +584,20 @@ void FGGroundNetwork::updateAircraftInformation(int id, double lat, double lon, } } + +FGTaxiNodeRef FGGroundNetwork::findNodeByIndex(int index) const +{ + FGTaxiNodeVector::const_iterator it; + for (it = m_nodes.begin(); it != m_nodes.end(); ++it) { + if ((*it)->getIndex() == index) { + return *it; + } + } + + return FGTaxiNodeRef(); +} + + /** Scan for a speed adjustment change. Find the nearest aircraft that is in front and adjust speed when we get too close. Only do this when current position and/or @@ -984,6 +894,46 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat, //current->setState(0); } +void FGGroundNetwork::addSegment(const FGTaxiNodeRef &from, const FGTaxiNodeRef &to) +{ + FGTaxiSegment* seg = new FGTaxiSegment(from, to); + segments.push_back(seg); + + FGTaxiNodeVector::iterator it = std::find(m_nodes.begin(), m_nodes.end(), from); + if (it == m_nodes.end()) { + m_nodes.push_back(from); + } + + it = std::find(m_nodes.begin(), m_nodes.end(), to); + if (it == m_nodes.end()) { + m_nodes.push_back(to); + } +} + +void FGGroundNetwork::addParking(const FGParkingRef &park) +{ + m_parkings.push_back(park); + + + FGTaxiNodeVector::iterator it = std::find(m_nodes.begin(), m_nodes.end(), park); + if (it == m_nodes.end()) { + m_nodes.push_back(park); + } +} + +FGTaxiNodeVector FGGroundNetwork::segmentsFrom(const FGTaxiNodeRef &from) const +{ + FGTaxiNodeVector result; + FGTaxiSegmentVector::const_iterator it; + for (it = segments.begin(); it != segments.end(); ++it) { + if ((*it)->getStart() == from) { + result.push_back((*it)->getEnd()); + } + } + + return result; +} + /** * Check whether situations occur where the current aircraft is waiting for itself * due to higher order interactions. diff --git a/src/Airports/groundnetwork.hxx b/src/Airports/groundnetwork.hxx index 80b7e0256..8e9b55cf9 100644 --- a/src/Airports/groundnetwork.hxx +++ b/src/Airports/groundnetwork.hxx @@ -32,6 +32,8 @@ #include "parking.hxx" #include +class FGAirportDynamicsXMLLoader; + class Block { private: @@ -54,18 +56,20 @@ public: class FGTaxiSegment { private: - const PositionedID startNode; - const PositionedID endNode; + // weak (non-owning) pointers deliberately here: + // the ground-network owns the nodes + const FGTaxiNode* startNode; + const FGTaxiNode* endNode; bool isActive; BlockList blockTimes; int index; - FGTaxiSegment *oppositeDirection; + FGTaxiSegment *oppositeDirection; // also deliberatley weak friend class FGGroundNetwork; public: - FGTaxiSegment(PositionedID start, PositionedID end); + FGTaxiSegment(FGTaxiNode* start, FGTaxiNode* end); void setIndex (int val) { index = val; @@ -107,10 +111,10 @@ public: class FGTaxiRoute { private: - PositionedIDVec nodes; + FGTaxiNodeVector nodes; intVec routes; double distance; - PositionedIDVec::iterator currNode; + FGTaxiNodeVector::iterator currNode; intVec::iterator currRoute; public: @@ -120,7 +124,7 @@ public: currRoute = routes.begin(); }; - FGTaxiRoute(const PositionedIDVec& nds, intVec rts, double dist, int dpth) { + FGTaxiRoute(const FGTaxiNodeVector& nds, intVec rts, double dist, int dpth) { nodes = nds; routes = rts; distance = dist; @@ -151,7 +155,7 @@ public: bool empty () { return nodes.empty(); }; - bool next(PositionedID *nde, int *rte); + bool next(FGTaxiNodeRef& nde, int *rte); void first() { currNode = nodes.begin(); @@ -171,6 +175,8 @@ public: class FGGroundNetwork : public FGATCController { private: + friend class FGAirportDynamicsXMLLoader; + bool hasNetwork; bool networkInitialized; time_t nextSave; @@ -187,6 +193,10 @@ private: FGTowerController *towerController; FGAirport *parent; + FGParkingList m_parkings; + FGTaxiNodeVector m_nodes; + + FGTaxiNodeRef findNodeByIndex(int index) const; //void printRoutingError(string); @@ -196,9 +206,11 @@ private: double heading, double speed, double alt); - void parseCache(); - - void loadSegments(); + void addSegment(const FGTaxiNodeRef& from, const FGTaxiNodeRef& to); + void addParking(const FGParkingRef& park); + + FGTaxiNodeVector segmentsFrom(const FGTaxiNodeRef& from) const; + public: FGGroundNetwork(); ~FGGroundNetwork(); @@ -214,21 +226,22 @@ public: towerController = twrCtrlr; }; - int findNearestNode(const SGGeod& aGeod) const; - int findNearestNodeOnRunway(const SGGeod& aGeod, FGRunway* aRunway = NULL) const; + FGTaxiNodeRef findNearestNode(const SGGeod& aGeod) const; + FGTaxiNodeRef findNearestNodeOnRunway(const SGGeod& aGeod, FGRunway* aRunway = NULL) const; + + FGTaxiSegment *findSegment(unsigned int idx) const; + + const FGParkingList& allParkings() const; - FGTaxiNodeRef findNode(PositionedID idx) const; - FGTaxiSegment *findSegment(unsigned idx) const; - /** * Find the taxiway segment joining two (ground-net) nodes. Returns * NULL if no such segment exists. - * It is permitted to pass 0 for the 'to' ID, indicating that any + * It is permitted to pass HULL for the 'to' indicating that any * segment originating at 'from' is acceptable. */ - FGTaxiSegment* findSegment(PositionedID from, PositionedID to) const; + FGTaxiSegment *findSegment(const FGTaxiNode* from, const FGTaxiNode* to) const; - FGTaxiRoute findShortestRoute(PositionedID start, PositionedID end, bool fullSearch=true); + FGTaxiRoute findShortestRoute(FGTaxiNode* start, FGTaxiNode* end, bool fullSearch=true); virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute, double lat, double lon, double hdg, double spd, double alt, @@ -245,7 +258,6 @@ public: virtual std::string getName(); virtual void update(double dt); - void saveElevationCache(); void addVersion(int v) {version = v; }; }; diff --git a/src/Airports/parking.cxx b/src/Airports/parking.cxx index 032a12549..b5c8f1ef0 100644 --- a/src/Airports/parking.cxx +++ b/src/Airports/parking.cxx @@ -36,21 +36,26 @@ * FGParking ********************************************************************************/ -FGParking::FGParking(PositionedID aGuid, const SGGeod& pos, +FGParking::FGParking(int index, + const SGGeod& pos, double aHeading, double aRadius, - const std::string& name, const std::string& aType, - const std::string& codes, - PositionedID pushBackNode) : - FGTaxiNode(aGuid, pos, false, 0), + const std::string& name, + const std::string& aType, + const std::string& codes) : + FGTaxiNode(index, pos, false, 0), heading(aHeading), radius(aRadius), parkingName(name), type(aType), - airlineCodes(codes), - pushBackPoint(pushBackNode) + airlineCodes(codes) { } FGParking::~FGParking() { } + +void FGParking::setPushBackPoint(const FGTaxiNodeRef &node) +{ + pushBackPoint = node; +} diff --git a/src/Airports/parking.hxx b/src/Airports/parking.hxx index 70f512820..996655365 100644 --- a/src/Airports/parking.hxx +++ b/src/Airports/parking.hxx @@ -36,7 +36,7 @@ #include // for std::auto_ptr #include "gnnode.hxx" - +#include class FGParking : public FGTaxiNode { @@ -46,15 +46,15 @@ private: const std::string parkingName; const std::string type; const std::string airlineCodes; - const PositionedID pushBackPoint; + FGTaxiNodeRef pushBackPoint; SG_DISABLE_COPY(FGParking); public: - FGParking(PositionedID aGuid, const SGGeod& pos, + FGParking(int index, + const SGGeod& pos, double heading, double radius, const std::string& name, const std::string& type, - const std::string& codes, - PositionedID pushBackNode); + const std::string& codes); virtual ~FGParking(); double getHeading () const { return heading; }; @@ -67,7 +67,8 @@ public: // TODO do parkings have different name and ident? virtual const std::string& name() const { return parkingName; } - int getPushBackPoint () { return pushBackPoint; }; + void setPushBackPoint(const FGTaxiNodeRef& node); + FGTaxiNodeRef getPushBackPoint () { return pushBackPoint; }; bool operator< (const FGParking &other) const { return radius < other.radius; }; diff --git a/src/Airports/xmlloader.cxx b/src/Airports/xmlloader.cxx index a4dddabc6..bc54e1247 100644 --- a/src/Airports/xmlloader.cxx +++ b/src/Airports/xmlloader.cxx @@ -49,25 +49,12 @@ void XMLLoader::load(FGAirportDynamics* d) return; } - flightgear::NavDataCache* cache = flightgear::NavDataCache::instance(); - //if (!cache->isCachedFileModified(path) || cache->isReadOnly()) { - // return; - //} - + SG_LOG(SG_NAVAID, SG_INFO, "reading groundnet data from " << path); SGTimeStamp t; try { - flightgear::NavDataCache::Transaction txn(cache); - t.stamp(); - { - // drop all current data - cache->dropGroundnetFor(d->parent()->guid()); - FGAirportDynamicsXMLLoader visitor(d); readXML(path.str(), visitor); - } // ensure visitor is destroyed so its destructor runs - cache->stampCacheFile(path); - txn.commit(); } catch (sg_exception& e) { SG_LOG(SG_NAVAID, SG_INFO, "parsing groundnet XML failed:" << e.getFormattedMessage()); } diff --git a/src/GUI/LocationWidget.cxx b/src/GUI/LocationWidget.cxx index f3f6d8dfa..ab186f967 100644 --- a/src/GUI/LocationWidget.cxx +++ b/src/GUI/LocationWidget.cxx @@ -699,6 +699,7 @@ void LocationWidget::onLocationChanged() } } +#if 0 m_ui->parkingCombo->clear(); FGAirportDynamics* dynamics = apt->getDynamics(); PositionedIDVec parkings = NavDataCache::instance()->airportItemsOfType(m_location->guid(), @@ -717,6 +718,7 @@ void LocationWidget::onLocationChanged() m_ui->airportDiagram->addParking(park); } } +#endif } else if (m_locationIsLatLon) { m_ui->stack->setCurrentIndex(1); diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 661bc2fbd..0e9dc485b 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -1410,12 +1410,6 @@ do_set_scenery_paths(const SGPropertyNode* arg) globals->append_fg_scenery(root.str()); } - // might need to drop ground-nets from the DB. Also need to drop - // them from memory, but this is tricky since FGAirportDynamics holds - // an instance directly, and AI code may have pointers to ground-net - // nodes. For now we'll leave-in memory versions untouched. - flightgear::NavDataCache::instance()->dropGroundnetsIfRequired(); - return true; } diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 2d34b8fc3..6e803d94f 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -616,11 +616,6 @@ fgInitNav () } } - // depend on when the NavCache was initialised, scenery paths may not - // have been setup. This is a safe place to consistently check the value, - // and drop the ground-nets if something has changed - cache->dropGroundnetsIfRequired(); - FGTACANList *channellist = new FGTACANList; globals->set_channellist( channellist ); diff --git a/src/Main/positioninit.cxx b/src/Main/positioninit.cxx index 681296687..366f122cb 100644 --- a/src/Main/positioninit.cxx +++ b/src/Main/positioninit.cxx @@ -261,7 +261,7 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par // The parking will be released after this function returns. // As a temporary measure, I'll try to reserve the parking via the atc_manager, which should work, because it uses the same // mechanism as the AI traffic code. - dcs->setParkingAvailable(pka.parking()->guid(), false); + dcs->setParkingAvailable(pka.parking(), false); fgApplyStartOffset(pka.parking()->geod(), pka.parking()->getHeading()); return true; } diff --git a/src/Navaids/CacheSchema.h b/src/Navaids/CacheSchema.h index b3665beb2..e92c62f27 100644 --- a/src/Navaids/CacheSchema.h +++ b/src/Navaids/CacheSchema.h @@ -1,7 +1,7 @@ #ifndef FG_NAVCACHE_SCHEMA_HXX #define FG_NAVCACHE_SCHEMA_HXX -const int SCHEMA_VERSION = 14; +const int SCHEMA_VERSION = 15; #define SCHEMA_SQL \ "CREATE TABLE properties (key VARCHAR, value VARCHAR);" \ @@ -31,14 +31,7 @@ const int SCHEMA_VERSION = 14; "CREATE INDEX airway_ident ON airway(ident);" \ \ "CREATE TABLE airway_edge (network INT,airway INT64,a INT64,b INT64);" \ -"CREATE INDEX airway_edge_from ON airway_edge(a);" \ -\ -"CREATE TABLE taxi_node (hold_type INT,on_runway BOOL,pushback BOOL);" \ -"CREATE TABLE parking (heading FLOAT,radius INT,gate_type VARCHAR," \ - "airlines VARCHAR,pushback INT64);" \ -"CREATE TABLE groundnet_edge (airport INT64,a INT64,b INT64);" \ -"CREATE INDEX groundnet_edge_airport ON groundnet_edge(airport);" \ -"CREATE INDEX groundnet_edge_from ON groundnet_edge(a);" +"CREATE INDEX airway_edge_from ON airway_edge(a);" #endif diff --git a/src/Navaids/NavDataCache.cxx b/src/Navaids/NavDataCache.cxx index 4942b902d..3f60bbba9 100644 --- a/src/Navaids/NavDataCache.cxx +++ b/src/Navaids/NavDataCache.cxx @@ -600,47 +600,6 @@ public: isPosInAirway = prepare("SELECT rowid FROM airway_edge WHERE network=?1 AND a=?2"); airwayEdgesFrom = prepare("SELECT airway, b FROM airway_edge WHERE network=?1 AND a=?2"); - - // parking / taxi-node graph - insertTaxiNode = prepare("INSERT INTO taxi_node (rowid, hold_type, on_runway, pushback) VALUES(?1, ?2, ?3, 0)"); - insertParkingPos = prepare("INSERT INTO parking (rowid, heading, radius, gate_type, airlines) " - "VALUES (?1, ?2, ?3, ?4, ?5)"); - setParkingPushBack = prepare("UPDATE parking SET pushback=?2 WHERE rowid=?1"); - - loadTaxiNodeStmt = prepare("SELECT hold_type, on_runway FROM taxi_node WHERE rowid=?1"); - loadParkingPos = prepare("SELECT heading, radius, gate_type, airlines, pushback FROM parking WHERE rowid=?1"); - taxiEdgesFrom = prepare("SELECT b FROM groundnet_edge WHERE a=?1"); - pushbackEdgesFrom = prepare("SELECT b FROM groundnet_edge, taxi_node WHERE " - "a=?1 AND groundnet_edge.b = taxi_node.rowid AND pushback=1"); - - insertTaxiEdge = prepare("INSERT INTO groundnet_edge (airport, a,b) VALUES(?1, ?2, ?3)"); - - markTaxiNodeAsPushback = prepare("UPDATE taxi_node SET pushback=1 WHERE rowid=?1"); - airportTaxiNodes = prepare("SELECT rowid FROM positioned WHERE (type=?2 OR type=?3) AND airport=?1"); - sqlite3_bind_int(airportTaxiNodes, 2, FGPositioned::PARKING); - sqlite3_bind_int(airportTaxiNodes, 3, FGPositioned::TAXI_NODE); - - airportPushbackNodes = prepare("SELECT positioned.rowid FROM positioned, taxi_node WHERE "\ - "airport=?1 AND positioned.rowid=taxi_node.rowid AND pushback=1 " - "AND (type=?2 OR type=?3)"); - sqlite3_bind_int(airportPushbackNodes, 2, FGPositioned::PARKING); - sqlite3_bind_int(airportPushbackNodes, 3, FGPositioned::TAXI_NODE); - - findNearestTaxiNode = prepare("SELECT positioned.rowid FROM positioned, taxi_node WHERE " - "positioned.rowid = taxi_node.rowid AND airport=?1 " - "ORDER BY distanceCartSqr(cart_x, cart_y, cart_z, ?2, ?3, ?4) " - "LIMIT 1"); - - findNearestRunwayTaxiNode = prepare("SELECT positioned.rowid FROM positioned, taxi_node WHERE " - "positioned.rowid = taxi_node.rowid AND airport=?1 " - "AND on_runway=1 " - "ORDER BY distanceCartSqr(cart_x, cart_y, cart_z, ?2, ?3, ?4) "); - - findAirportParking = prepare("SELECT positioned.rowid FROM positioned, parking WHERE " - "airport=?1 AND type=?4 AND " - "radius >= ?2 AND gate_type = ?3 AND " - "parking.rowid=positioned.rowid"); - sqlite3_bind_int(findAirportParking, 4, FGPositioned::PARKING); } void writeIntProperty(const string& key, int value) @@ -758,36 +717,6 @@ public: return n; } - FGPositioned* loadParking(sqlite3_int64 rowId, - const string& name, const SGGeod& pos, - PositionedID airport) - { - sqlite3_bind_int64(loadParkingPos, 1, rowId); - execSelect1(loadParkingPos); - - double heading = sqlite3_column_double(loadParkingPos, 0); - int radius = sqlite3_column_int(loadParkingPos, 1); - string aircraftType((char*) sqlite3_column_text(loadParkingPos, 2)); - string airlines((char*) sqlite3_column_text(loadParkingPos, 3)); - PositionedID pushBack = sqlite3_column_int64(loadParkingPos, 4); - reset(loadParkingPos); - - return new FGParking(rowId, pos, heading, radius, name, aircraftType, airlines, pushBack); - } - - FGPositioned* loadTaxiNode(sqlite3_int64 rowId, const SGGeod& pos, - PositionedID airport) - { - sqlite3_bind_int64(loadTaxiNodeStmt, 1, rowId); - execSelect1(loadTaxiNodeStmt); - - int hold_type = sqlite3_column_int(loadTaxiNodeStmt, 0); - bool onRunway = sqlite3_column_int(loadTaxiNodeStmt, 1); - reset(loadTaxiNodeStmt); - - return new FGTaxiNode(rowId, pos, onRunway, hold_type); - } - PositionedID insertPositioned(FGPositioned::Type ty, const string& ident, const string& name, const SGGeod& pos, PositionedID apt, bool spatialIndex) @@ -949,12 +878,6 @@ public: sqlite3_stmt_ptr findAirway, insertAirwayEdge, isPosInAirway, airwayEdgesFrom, insertAirway; -// groundnet (parking, taxi node graph) - sqlite3_stmt_ptr loadTaxiNodeStmt, loadParkingPos, insertTaxiNode, insertParkingPos; - sqlite3_stmt_ptr taxiEdgesFrom, pushbackEdgesFrom, insertTaxiEdge, markTaxiNodeAsPushback, - airportTaxiNodes, airportPushbackNodes, findNearestTaxiNode, findAirportParking, - setParkingPushBack, findNearestRunwayTaxiNode; - // since there's many permutations of ident/name queries, we create // them programtically, but cache the exact query by its raw SQL once // used. @@ -1043,12 +966,6 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid, case FGPositioned::FREQ_UNICOM: return loadComm(rowid, ty, ident, name, pos, aptId); - case FGPositioned::TAXI_NODE: - return loadTaxiNode(rowid, pos, aptId); - - case FGPositioned::PARKING: - return loadParking(rowid, ident, pos, aptId); - default: return NULL; } @@ -1200,19 +1117,6 @@ bool NavDataCache::isRebuildRequired() return false; } -bool NavDataCache::dropGroundnetsIfRequired() -{ - string sceneryPaths = simgear::strutils::join(globals->get_fg_scenery(), ";"); - if (readStringProperty("scenery_paths") != sceneryPaths) { - SG_LOG(SG_NAVCACHE, SG_INFO, "NavCache: scenery paths changed, dropping ground nets"); - dropAllGroundnets(); - writeStringProperty("scenery_paths", sceneryPaths); - return true; - } - - return false; -} - NavDataCache::RebuildPhase NavDataCache::rebuild() { if (!d->rebuilder.get()) { @@ -2081,162 +1985,6 @@ PositionedID NavDataCache::findNavaidForRunway(PositionedID runway, FGPositioned d->reset(d->findNavaidForRunway); return result; } - -PositionedID -NavDataCache::insertParking(const std::string& name, const SGGeod& aPos, - PositionedID aAirport, - double aHeading, int aRadius, const std::string& aAircraftType, - const std::string& aAirlines) -{ - sqlite3_int64 rowId = d->insertPositioned(FGPositioned::PARKING, name, "", aPos, aAirport, false); - -// we need to insert a row into the taxi_node table, otherwise we can't maintain -// the appropriate pushback flag. - sqlite3_bind_int64(d->insertTaxiNode, 1, rowId); - sqlite3_bind_int(d->insertTaxiNode, 2, 0); - sqlite3_bind_int(d->insertTaxiNode, 3, 0); - d->execInsert(d->insertTaxiNode); - - sqlite3_bind_int64(d->insertParkingPos, 1, rowId); - sqlite3_bind_double(d->insertParkingPos, 2, aHeading); - sqlite3_bind_int(d->insertParkingPos, 3, aRadius); - sqlite_bind_stdstring(d->insertParkingPos, 4, aAircraftType); - sqlite_bind_stdstring(d->insertParkingPos, 5, aAirlines); - return d->execInsert(d->insertParkingPos); -} - -void NavDataCache::setParkingPushBackRoute(PositionedID parking, PositionedID pushBackNode) -{ - sqlite3_bind_int64(d->setParkingPushBack, 1, parking); - sqlite3_bind_int64(d->setParkingPushBack, 2, pushBackNode); - d->execUpdate(d->setParkingPushBack); -} - -PositionedID -NavDataCache::insertTaxiNode(const SGGeod& aPos, PositionedID aAirport, int aHoldType, bool aOnRunway) -{ - sqlite3_int64 rowId = d->insertPositioned(FGPositioned::TAXI_NODE, string(), string(), aPos, aAirport, false); - sqlite3_bind_int64(d->insertTaxiNode, 1, rowId); - sqlite3_bind_int(d->insertTaxiNode, 2, aHoldType); - sqlite3_bind_int(d->insertTaxiNode, 3, aOnRunway); - return d->execInsert(d->insertTaxiNode); -} - -void NavDataCache::insertGroundnetEdge(PositionedID aAirport, PositionedID from, PositionedID to) -{ - sqlite3_bind_int64(d->insertTaxiEdge, 1, aAirport); - sqlite3_bind_int64(d->insertTaxiEdge, 2, from); - sqlite3_bind_int64(d->insertTaxiEdge, 3, to); - d->execInsert(d->insertTaxiEdge); -} - -PositionedIDVec NavDataCache::groundNetNodes(PositionedID aAirport, bool onlyPushback) -{ - sqlite3_stmt_ptr q = onlyPushback ? d->airportPushbackNodes : d->airportTaxiNodes; - sqlite3_bind_int64(q, 1, aAirport); - return d->selectIds(q); -} - -void NavDataCache::markGroundnetAsPushback(PositionedID nodeId) -{ - sqlite3_bind_int64(d->markTaxiNodeAsPushback, 1, nodeId); - d->execUpdate(d->markTaxiNodeAsPushback); -} - -static double headingDifferenceDeg(double crs1, double crs2) -{ - double diff = crs2 - crs1; - SG_NORMALIZE_RANGE(diff, -180.0, 180.0); - return diff; -} - -PositionedID NavDataCache::findGroundNetNode(PositionedID airport, const SGGeod& aPos, - bool onRunway, FGRunway* aRunway) -{ - sqlite3_stmt_ptr q = onRunway ? d->findNearestRunwayTaxiNode : d->findNearestTaxiNode; - sqlite3_bind_int64(q, 1, airport); - - SGVec3d cartPos(SGVec3d::fromGeod(aPos)); - sqlite3_bind_double(q, 2, cartPos.x()); - sqlite3_bind_double(q, 3, cartPos.y()); - sqlite3_bind_double(q, 4, cartPos.z()); - - PositionedID result = 0; - while (d->execSelect(q)) { - PositionedID id = sqlite3_column_int64(q, 0); - if (!aRunway) { - result = id; - break; - } - - // ensure found node lies on the runway - FGPositionedRef node = loadById(id); - double course = SGGeodesy::courseDeg(node->geod(), aRunway->end()); - if (fabs(headingDifferenceDeg(course, aRunway->headingDeg())) < 3.0 ) { - result = id; - break; - } - } - - d->reset(q); - return result; -} - -PositionedIDVec NavDataCache::groundNetEdgesFrom(PositionedID pos, bool onlyPushback) -{ - sqlite3_stmt_ptr q = onlyPushback ? d->pushbackEdgesFrom : d->taxiEdgesFrom; - sqlite3_bind_int64(q, 1, pos); - return d->selectIds(q); -} - -PositionedIDVec NavDataCache::findAirportParking(PositionedID airport, const std::string& flightType, - int radius) -{ - sqlite3_bind_int64(d->findAirportParking, 1, airport); - sqlite3_bind_int(d->findAirportParking, 2, radius); - sqlite_bind_stdstring(d->findAirportParking, 3, flightType); - - return d->selectIds(d->findAirportParking); -} - -void NavDataCache::dropGroundnetFor(PositionedID aAirport) -{ - sqlite3_stmt_ptr q = d->prepare("DELETE FROM parking WHERE rowid IN (SELECT rowid FROM positioned WHERE type=?1 AND airport=?2)"); - sqlite3_bind_int(q, 1, FGPositioned::PARKING); - sqlite3_bind_int64(q, 2, aAirport); - d->execUpdate(q); - - q = d->prepare("DELETE FROM taxi_node WHERE rowid IN (SELECT rowid FROM positioned WHERE (type=?1 OR type=?2) AND airport=?3)"); - sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE); - sqlite3_bind_int(q, 2, FGPositioned::PARKING); - sqlite3_bind_int64(q, 3, aAirport); - d->execUpdate(q); - - q = d->prepare("DELETE FROM positioned WHERE (type=?1 OR type=?2) AND airport=?3"); - sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE); - sqlite3_bind_int(q, 2, FGPositioned::PARKING); - sqlite3_bind_int64(q, 3, aAirport); - d->execUpdate(q); - - q = d->prepare("DELETE FROM groundnet_edge WHERE airport=?1"); - sqlite3_bind_int64(q, 1, aAirport); - d->execUpdate(q); -} - -void NavDataCache::dropAllGroundnets() -{ - SG_LOG(SG_NAVCACHE, SG_INFO, "dropping ground-net data"); - beginTransaction(); - d->runSQL("DELETE FROM groundnet_edge"); - d->runSQL("DELETE FROM parking"); - d->runSQL("DELETE FROM taxi_node"); - - sqlite3_stmt_ptr q = d->prepare("DELETE FROM positioned WHERE (type=?1 OR type=?2)"); - sqlite3_bind_int(q, 1, FGPositioned::TAXI_NODE); - sqlite3_bind_int(q, 2, FGPositioned::PARKING); - d->execUpdate(q); - commitTransaction(); -} bool NavDataCache::isReadOnly() const { diff --git a/src/Navaids/NavDataCache.hxx b/src/Navaids/NavDataCache.hxx index a59257848..615be64f9 100644 --- a/src/Navaids/NavDataCache.hxx +++ b/src/Navaids/NavDataCache.hxx @@ -68,13 +68,7 @@ public: * This can happen is the cache file is missing or damaged, or one of the ** global input files is changed. */ - bool isRebuildRequired(); - - /** - * check if cached scenery paths have changed, and if so, drop scenery- - * dependant data such as ground-nets. - */ - bool dropGroundnetsIfRequired(); + bool isRebuildRequired(); enum RebuildPhase { @@ -91,8 +85,8 @@ public: */ RebuildPhase rebuild(); - unsigned int rebuildPhaseCompletionPercentage() const; - void setRebuildPhaseProgress(RebuildPhase ph, unsigned int percent = 0); + unsigned int rebuildPhaseCompletionPercentage() const; + void setRebuildPhaseProgress(RebuildPhase ph, unsigned int percent = 0); bool isCachedFileModified(const SGPath& path) const; void stampCacheFile(const SGPath& path); @@ -140,27 +134,6 @@ public: PositionedID createPOI(FGPositioned::Type ty, const std::string& ident, const SGGeod& aPos); bool removePOI(FGPositioned::Type ty, const std::string& aIdent); - - void dropGroundnetFor(PositionedID aAirport); - - /** - * Remove all ground-nets globally from the cache. - * This includes parking and taxi-nodes and edges between them. It's useful - * when scenery paths change, since the ground-nets depend on the scenery. - * Using this we can avoid havind to rebuild the entire cache. - */ - void dropAllGroundnets(); - - PositionedID insertParking(const std::string& name, const SGGeod& aPos, - PositionedID aAirport, - double aHeading, int aRadius, const std::string& aAircraftType, - const std::string& aAirlines); - - void setParkingPushBackRoute(PositionedID parking, PositionedID pushBackNode); - - PositionedID insertTaxiNode(const SGGeod& aPos, PositionedID aAirport, int aHoldType, bool aOnRunway); - - void insertGroundnetEdge(PositionedID aAirport, PositionedID from, PositionedID to); /// update the metar flag associated with an airport void setAirportMetar(const std::string& icao, bool hasMetar); @@ -269,18 +242,6 @@ public: */ AirwayEdgeVec airwayEdgesFrom(int network, PositionedID pos); -// ground-network - PositionedIDVec groundNetNodes(PositionedID aAirport, bool onlyPushback); - void markGroundnetAsPushback(PositionedID nodeId); - - PositionedID findGroundNetNode(PositionedID airport, const SGGeod& aPos, - bool onRunway, FGRunway* aRunway = NULL); - PositionedIDVec groundNetEdgesFrom(PositionedID pos, bool onlyPushback); - - PositionedIDVec findAirportParking(PositionedID airport, const std::string& flightType, - int radius); - - class Transaction { public: diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx index 73f9ff05e..c877f9901 100644 --- a/src/Navaids/positioned.cxx +++ b/src/Navaids/positioned.cxx @@ -64,6 +64,7 @@ static bool validateFilter(FGPositioned::Filter* filter) return true; } +const PositionedID FGPositioned::TRANSIENT_ID = -2; /////////////////////////////////////////////////////////////////////////////// @@ -82,7 +83,6 @@ FGPositioned::FGPositioned( PositionedID aGuid, FGPositioned::~FGPositioned() { -// std::cout << "destroying:" << mIdent << "/" << nameForType(mType) << std::endl; } FGPositioned* diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx index 59b23b1dd..5187f8ddb 100644 --- a/src/Navaids/positioned.hxx +++ b/src/Navaids/positioned.hxx @@ -42,6 +42,7 @@ namespace flightgear { class NavDataCache; } class FGPositioned : public SGReferenced { public: + static const PositionedID TRANSIENT_ID; typedef enum { INVALID = 0, diff --git a/src/Scripting/NasalPositioned.cxx b/src/Scripting/NasalPositioned.cxx index 6a52a0847..275929de2 100644 --- a/src/Scripting/NasalPositioned.cxx +++ b/src/Scripting/NasalPositioned.cxx @@ -1352,20 +1352,10 @@ static naRef f_airport_parking(naContext c, naRef me, int argc, naRef* args) } FGAirportDynamics* dynamics = apt->getDynamics(); - PositionedIDVec parkings = flightgear::NavDataCache::instance()->airportItemsOfType(apt->guid(), - FGPositioned::PARKING); - - BOOST_FOREACH(PositionedID parking, parkings) { - // filter out based on availability and type - if (onlyAvailable && !dynamics->isParkingAvailable(parking)) { - continue; - } - - FGParking* park = dynamics->getParking(parking); - if (!type.empty() && (park->getType() != type)) { - continue; - } - + FGParkingList parkings = dynamics->getParkings(onlyAvailable, type); + FGParkingList::const_iterator it; + for (it = parkings.begin(); it != parkings.end(); ++it) { + FGParkingRef park = *it; const SGGeod& parkLoc = park->geod(); naRef ph = naNewHash(c); hashset(c, ph, "name", stringToNasal(c, park->getName())); diff --git a/src/Scripting/NasalPositioned_cppbind.cxx b/src/Scripting/NasalPositioned_cppbind.cxx index 7ef63d02c..eef345155 100644 --- a/src/Scripting/NasalPositioned_cppbind.cxx +++ b/src/Scripting/NasalPositioned_cppbind.cxx @@ -208,27 +208,8 @@ f_airport_parking(FGAirport& apt, nasal::CallContext ctx) { std::string type = ctx.getArg(0); bool only_available = ctx.getArg(1); - FGAirportDynamics* dynamics = apt.getDynamics(); - PositionedIDVec parkings = - flightgear::NavDataCache::instance() - ->airportItemsOfType(apt.guid(), FGPositioned::PARKING); - - FGParkingList ret; - BOOST_FOREACH(PositionedID parking, parkings) - { - // filter out based on availability and type - if( only_available && !dynamics->isParkingAvailable(parking) ) - continue; - - FGParking* park = dynamics->getParking(parking); - if( !type.empty() && (park->getType() != type) ) - continue; - - ret.push_back(park); - } - - return ret; + return dynamics->getParkings(only_available, type); } /**