From 301054204e0412eb31f06477e32cfe6f1fcb0792 Mon Sep 17 00:00:00 2001 From: durk Date: Thu, 14 Aug 2008 18:13:39 +0000 Subject: [PATCH] James Turner: Improved runway management code: - Runways are now part of an airport, instead of a separate list - Runways are no longer represented as a boring struct, but as a class of their own. -Improved runway access to unify various runway access methods. --- src/AIModel/AIAircraft.cxx | 1 + src/AIModel/AIAircraft.hxx | 1 + src/AIModel/AIFlightPlan.cxx | 6 +- src/AIModel/AIFlightPlan.hxx | 1 + src/AIModel/AIFlightPlanCreate.cxx | 45 +-- src/AIModel/AIFlightPlanCreateCruise.cxx | 12 +- src/AIModel/AIFlightPlanCreatePushBack.cxx | 1 + src/ATC/trafficcontrol.cxx | 3 +- src/ATCDCL/AILocalTraffic.cxx | 20 +- src/ATCDCL/AIMgr.cxx | 2 + src/ATCDCL/approach.cxx | 29 +- src/ATCDCL/atis.cxx | 6 +- src/ATCDCL/ground.cxx | 83 +++-- src/ATCDCL/tower.cxx | 146 ++++----- src/Airports/apt_loader.cxx | 26 +- src/Airports/apt_loader.hxx | 11 +- src/Airports/dynamics.cxx | 18 +- src/Airports/groundnetwork.cxx | 2 + src/Airports/runwayprefs.cxx | 39 +-- src/Airports/runwayprefs.hxx | 2 +- src/Airports/runways.cxx | 328 +++++-------------- src/Airports/runways.hxx | 112 ++----- src/Airports/simple.cxx | 155 ++++++++- src/Airports/simple.hxx | 82 ++--- src/Cockpit/hud_rwy.cxx | 11 +- src/Cockpit/panel.cxx | 1 + src/Environment/environment_mgr.cxx | 12 + src/Environment/environment_mgr.hxx | 2 + src/Instrumentation/HUD/HUD_runway.cxx | 12 +- src/Instrumentation/KLN89/kln89_page_apt.cxx | 30 +- src/Instrumentation/KLN89/kln89_page_fpl.cxx | 2 + src/Instrumentation/groundradar.cxx | 49 ++- src/Instrumentation/groundradar.hxx | 7 +- src/Instrumentation/mk_viii.cxx | 78 +++-- src/Main/fg_init.cxx | 34 +- src/Main/globals.cxx | 2 - src/Main/globals.hxx | 7 - src/Main/main.cxx | 4 + src/Main/options.cxx | 4 + src/MultiPlayer/multiplaymgr.cxx | 3 + src/Navaids/navdb.cxx | 28 +- src/Navaids/navdb.hxx | 2 +- src/Scripting/NasalSys.cxx | 41 +-- 43 files changed, 679 insertions(+), 781 deletions(-) diff --git a/src/AIModel/AIAircraft.cxx b/src/AIModel/AIAircraft.cxx index 7d6d0d2c5..c9f185bf0 100644 --- a/src/AIModel/AIAircraft.cxx +++ b/src/AIModel/AIAircraft.cxx @@ -29,6 +29,7 @@ #include
#include #include +#include #include #include diff --git a/src/AIModel/AIAircraft.hxx b/src/AIModel/AIAircraft.hxx index d609ef92a..9722e3556 100644 --- a/src/AIModel/AIAircraft.hxx +++ b/src/AIModel/AIAircraft.hxx @@ -26,6 +26,7 @@ #include #include +#include #include using std::string; diff --git a/src/AIModel/AIFlightPlan.cxx b/src/AIModel/AIFlightPlan.cxx index 6f3f3dc41..e9035eddb 100644 --- a/src/AIModel/AIFlightPlan.cxx +++ b/src/AIModel/AIFlightPlan.cxx @@ -20,6 +20,8 @@ # include #endif +#include + #include #include #include @@ -34,13 +36,15 @@ #include
#include #include - +#include #include #include #include "AIFlightPlan.hxx" +using std::cerr; + FGAIFlightPlan::FGAIFlightPlan(const string& filename) { diff --git a/src/AIModel/AIFlightPlan.hxx b/src/AIModel/AIFlightPlan.hxx index 1525c6621..fba78887f 100644 --- a/src/AIModel/AIFlightPlan.hxx +++ b/src/AIModel/AIFlightPlan.hxx @@ -32,6 +32,7 @@ using std::vector; using std::string; +class FGTaxiRoute; class FGAIFlightPlan { diff --git a/src/AIModel/AIFlightPlanCreate.cxx b/src/AIModel/AIFlightPlanCreate.cxx index 98da9247c..89797696f 100644 --- a/src/AIModel/AIFlightPlanCreate.cxx +++ b/src/AIModel/AIFlightPlanCreate.cxx @@ -20,6 +20,7 @@ #include "AIFlightPlan.hxx" #include #include +#include #include #include @@ -137,16 +138,8 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction, } string rwyClass = getRunwayClassFromTrafficType(fltType); apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << - activeRunway << - " at airport " << apt->getId() << " of class " << rwyClass << " (1)"); - exit(1); - } - + rwy = apt->getRunwayByIdent(activeRunway); + // Determine the beginning of he runway heading = rwy._heading; double azimuth = heading + 180.0; @@ -503,15 +496,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee //string name; string rwyClass = getRunwayClassFromTrafficType(fltType); apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << - activeRunway << - " at airport " << apt->getId()<< " of class " << rwyClass << " (2)"); - exit(1); - } + rwy = apt->getRunwayByIdent(activeRunway); } // Acceleration point, 105 meters into the runway, heading = rwy._heading; @@ -637,15 +622,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed, //string name; string rwyClass = getRunwayClassFromTrafficType(fltType); apt->getDynamics()->getActiveRunway(rwyClass, 1, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << - activeRunway << - " at airport " << apt->getId()<< " of class " << rwyClass << " (3)"); - exit(1); - } + rwy = apt->getRunwayByIdent(activeRunway); } @@ -774,16 +751,8 @@ void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType) // allow "mil" and "gen" as well string rwyClass = getRunwayClassFromTrafficType(fltType); apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway); - if (!(globals->get_runways()->search(apt->getId(), - activeRunway, - &rwy))) - { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << - activeRunway << - " at airport " << apt->getId()<< " of class " << rwyClass << " (4)"); - exit(1); - } - + rwy = apt->getRunwayByIdent(activeRunway); + heading = rwy._heading; azimuth = heading + 180.0; while ( azimuth >= 360.0 ) { azimuth -= 360.0; } diff --git a/src/AIModel/AIFlightPlanCreateCruise.cxx b/src/AIModel/AIFlightPlanCreateCruise.cxx index 28f0b8de6..d6d790978 100755 --- a/src/AIModel/AIFlightPlanCreateCruise.cxx +++ b/src/AIModel/AIFlightPlanCreateCruise.cxx @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -334,15 +335,8 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep, string rwyClass = getRunwayClassFromTrafficType(fltType); arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway); - if (!(globals->get_runways()->search(arr->getId(), - activeRunway, - &rwy))) - { - SG_LOG(SG_INPUT, SG_ALERT, "Failed to find runway " << - activeRunway << - " at airport " << arr->getId()<< " of class " << rwyClass << " (5)"); - exit(1); - } + rwy = arr->getRunwayByIdent(activeRunway); + heading = rwy._heading; azimuth = heading + 180.0; while ( azimuth >= 360.0 ) { azimuth -= 360.0; } diff --git a/src/AIModel/AIFlightPlanCreatePushBack.cxx b/src/AIModel/AIFlightPlanCreatePushBack.cxx index a2deb0a3c..cc2a141e8 100644 --- a/src/AIModel/AIFlightPlanCreatePushBack.cxx +++ b/src/AIModel/AIFlightPlanCreatePushBack.cxx @@ -20,6 +20,7 @@ #include "AIFlightPlan.hxx" #include #include +#include #include #include diff --git a/src/ATC/trafficcontrol.cxx b/src/ATC/trafficcontrol.cxx index c5a3c45e5..99c833c3c 100644 --- a/src/ATC/trafficcontrol.cxx +++ b/src/ATC/trafficcontrol.cxx @@ -28,7 +28,8 @@ #include #include #include - +#include +#include /*************************************************************************** * FGTrafficRecord diff --git a/src/ATCDCL/AILocalTraffic.cxx b/src/ATCDCL/AILocalTraffic.cxx index 2afd62ea9..2156fbe13 100644 --- a/src/ATCDCL/AILocalTraffic.cxx +++ b/src/ATCDCL/AILocalTraffic.cxx @@ -174,15 +174,16 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) { // Now we need to get the threshold position and rwy heading - FGRunway runway; - bool rwyGood = globals->get_runways()->search(id, rwy.rwyID, &runway); - if(rwyGood) { - double hdg = runway._heading; - double other_way = hdg - 180.0; - while(other_way <= 0.0) { - other_way += 360.0; - } + const FGAirport* apt = fgFindAirportID(id); + assert(apt); + FGRunway runway(apt->getRunwayByIdent(rwy.rwyID)); + double hdg = runway._heading; + double other_way = hdg - 180.0; + while(other_way <= 0.0) { + other_way += 360.0; + } + // move to the +l end/center of the runway //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n'; Point3D origin = Point3D(runway._lon, runway._lat, aptElev); @@ -207,9 +208,6 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) { ortho.Init(rwy.threshold_pos, rwy.hdg); rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos); // should come out as zero rwy.end2ortho = ortho.ConvertToLocal(takeoff_end); - } else { - SG_LOG(SG_ATC, SG_ALERT, "Help - can't get good runway at airport " << id << " in FGAILocalTraffic!!"); - } } diff --git a/src/ATCDCL/AIMgr.cxx b/src/ATCDCL/AIMgr.cxx index c8f7b8b02..5d4da1d86 100644 --- a/src/ATCDCL/AIMgr.cxx +++ b/src/ATCDCL/AIMgr.cxx @@ -23,6 +23,8 @@ # include #endif +#include + #include
#include
#include diff --git a/src/ATCDCL/approach.cxx b/src/ATCDCL/approach.cxx index 296e3446b..c935cbc29 100644 --- a/src/ATCDCL/approach.cxx +++ b/src/ATCDCL/approach.cxx @@ -30,6 +30,8 @@ #include "ATCDialog.hxx" #include +#include + #include #include #include @@ -559,26 +561,15 @@ double FGApproach::round_alt( const bool hl, double alt ) { void FGApproach::get_active_runway() { //cout << "Entering FGApproach::get_active_runway()\n"; - FGEnvironment stationweather = - ((FGEnvironmentMgr *)globals->get_subsystem("environment")) - ->getEnvironment(lat, lon, elev); - - double hdg = stationweather.get_wind_from_heading_deg(); - - FGRunway runway; - if ( globals->get_runways()->search( ident, int(hdg), &runway) ) { - active_runway = runway._rwy_no; - active_rw_hdg = runway._heading; - active_rw_lon = runway._lon; - active_rw_lat = runway._lat; - active_rw_len = runway._length; - //cout << "Active runway is: " << active_runway << " heading = " - // << active_rw_hdg - // << " lon = " << active_rw_lon - // << " lat = " << active_rw_lat <getActiveRunwayForUsage(); + active_runway = runway._rwy_no; + active_rw_hdg = runway._heading; + active_rw_lon = runway._lon; + active_rw_lat = runway._lat; + active_rw_len = runway._length; } // ======================================================================== diff --git a/src/ATCDCL/atis.cxx b/src/ATCDCL/atis.cxx index 30a7f5af7..4f9d93de4 100644 --- a/src/ATCDCL/atis.cxx +++ b/src/ATCDCL/atis.cxx @@ -210,8 +210,10 @@ void FGATIS::UpdateTransmission() { + ConvertNumToSpokenDigits(tempstr2) + " degrees"; } - string rwy_no = globals->get_runways()->search(ident, int(hdg)); - if(rwy_no != "NN") { + const FGAirport* apt = fgFindAirportID(ident); + assert(apt); + string rwy_no = apt->getActiveRunwayForUsage()._rwy_no; + if(rwy_no != "NN") { transmission += " / Landing_and_departing_runway "; transmission += ConvertRwyNumToSpokenString(atoi(rwy_no.c_str())); //cout << "in atis.cxx, r.rwy_no = " << rwy_no << " r.id = " << r->id << " r.heading = " << r->heading << endl; diff --git a/src/ATCDCL/ground.cxx b/src/ATCDCL/ground.cxx index e1909885c..2a6643e00 100644 --- a/src/ATCDCL/ground.cxx +++ b/src/ATCDCL/ground.cxx @@ -22,6 +22,8 @@ # include #endif +#include + #include #include #include @@ -358,53 +360,42 @@ void FGGround::Update(double dt) { // will be initialised before ground so we can't do that. void FGGround::DoRwyDetails() { //cout << "GetRwyDetails called" << endl; - - // Based on the airport-id and wind get the active runway - - //wind - double hdg = wind_from_hdg->getDoubleValue(); - double speed = wind_speed_knots->getDoubleValue(); - hdg = (speed == 0.0 ? 270.0 : hdg); - //cout << "Heading = " << hdg << '\n'; - - FGRunway runway; - bool rwyGood = globals->get_runways()->search(ident, int(hdg), &runway); - if(rwyGood) { - activeRwy = runway._rwy_no; - rwy.rwyID = runway._rwy_no; - SG_LOG(SG_ATC, SG_INFO, "In FGGround, active runway for airport " << ident << " is " << activeRwy); - // Get the threshold position - double other_way = runway._heading - 180.0; - while(other_way <= 0.0) { - other_way += 360.0; - } - // move to the +l end/center of the runway - //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n'; - Point3D origin = Point3D(runway._lon, runway._lat, aptElev); - Point3D ref = origin; - double tshlon, tshlat, tshr; - double tolon, tolat, tor; - rwy.length = runway._length * SG_FEET_TO_METER; - geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), other_way, - rwy.length / 2.0 - 25.0, &tshlat, &tshlon, &tshr ); - geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), runway._heading, - rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor ); - // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user. - // now copy what we need out of runway into rwy - rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev); - Point3D takeoff_end = Point3D(tolon, tolat, aptElev); - //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n'; - //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n'; - rwy.hdg = runway._heading; - // Set the projection for the local area based on this active runway - ortho.Init(rwy.threshold_pos, rwy.hdg); - rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos); // should come out as zero - rwy.end2ortho = ortho.ConvertToLocal(takeoff_end); - } else { - SG_LOG(SG_ATC, SG_ALERT, "Help - can't get good runway in FGTower!!"); - activeRwy = "NN"; - } + const FGAirport* apt = fgFindAirportID(ident); + assert(apt); + FGRunway runway = apt->getActiveRunwayForUsage(); + + activeRwy = runway._rwy_no; + rwy.rwyID = runway._rwy_no; + SG_LOG(SG_ATC, SG_INFO, "In FGGround, active runway for airport " << ident << " is " << activeRwy); + + // Get the threshold position + double other_way = runway._heading - 180.0; + while(other_way <= 0.0) { + other_way += 360.0; + } + // move to the +l end/center of the runway + //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n'; + Point3D origin = Point3D(runway._lon, runway._lat, aptElev); + Point3D ref = origin; + double tshlon, tshlat, tshr; + double tolon, tolat, tor; + rwy.length = runway._length * SG_FEET_TO_METER; + geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), other_way, + rwy.length / 2.0 - 25.0, &tshlat, &tshlon, &tshr ); + geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), runway._heading, + rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor ); + // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user. + // now copy what we need out of runway into rwy + rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev); + Point3D takeoff_end = Point3D(tolon, tolat, aptElev); + //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n'; + //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n'; + rwy.hdg = runway._heading; + // Set the projection for the local area based on this active runway + ortho.Init(rwy.threshold_pos, rwy.hdg); + rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos); // should come out as zero + rwy.end2ortho = ortho.ConvertToLocal(takeoff_end); } // Return a random gate ID of an unused gate. diff --git a/src/ATCDCL/tower.cxx b/src/ATCDCL/tower.cxx index e61109bfb..e2b2ce605 100644 --- a/src/ATCDCL/tower.cxx +++ b/src/ATCDCL/tower.cxx @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -1510,61 +1511,53 @@ void FGTower::DoRwyDetails() { // Based on the airport-id and wind get the active runway - //wind - double hdg = wind_from_hdg->getDoubleValue(); - double speed = wind_speed_knots->getDoubleValue(); - hdg = (speed == 0.0 ? 270.0 : hdg); - //cout << "Heading = " << hdg << '\n'; - - FGRunway runway; - bool rwyGood = globals->get_runways()->search(ident, int(hdg), &runway); - if(rwyGood) { - //cout << "RUNWAY GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD\n"; - activeRwy = runway._rwy_no; - rwy.rwyID = runway._rwy_no; - SG_LOG(SG_ATC, SG_INFO, "Active runway for airport " << ident << " is " << activeRwy); - - // Get the threshold position - double other_way = runway._heading - 180.0; - while(other_way <= 0.0) { - other_way += 360.0; - } - // move to the +l end/center of the runway - //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n'; - Point3D origin = Point3D(runway._lon, runway._lat, aptElev); - Point3D ref = origin; - double tshlon, tshlat, tshr; - double tolon, tolat, tor; - rwy.length = runway._length * SG_FEET_TO_METER; - rwy.width = runway._width * SG_FEET_TO_METER; - geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), other_way, - rwy.length / 2.0 - 25.0, &tshlat, &tshlon, &tshr ); - geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), runway._heading, - rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor ); - // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user. - // now copy what we need out of runway into rwy - rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev); - Point3D takeoff_end = Point3D(tolon, tolat, aptElev); - //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n'; - //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n'; - rwy.hdg = runway._heading; - // Set the projection for the local area based on this active runway - ortho.Init(rwy.threshold_pos, rwy.hdg); - rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos); // should come out as zero - rwy.end2ortho = ortho.ConvertToLocal(takeoff_end); - - // Set the pattern direction - // TODO - we'll check for a facilities file with this in eventually - for now assume left traffic except - // for certain circumstances (RH parallel rwy). - rwy.patternDirection = -1; // Left - if(rwy.rwyID.size() == 3) { - rwy.patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1); - } - //cout << "Doing details, rwy.patterDirection is " << rwy.patternDirection << '\n'; - } else { - SG_LOG(SG_ATC, SG_ALERT, "Help - can't get good runway in FGTower!!"); - activeRwy = "NN"; - } + const FGAirport* apt = fgFindAirportID(ident); + assert(apt); + FGRunway runway = apt->getActiveRunwayForUsage(); + + //cout << "RUNWAY GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD\n"; + + activeRwy = runway._rwy_no; + rwy.rwyID = runway._rwy_no; + SG_LOG(SG_ATC, SG_INFO, "Active runway for airport " << ident << " is " << activeRwy); + + // Get the threshold position + double other_way = runway._heading - 180.0; + while(other_way <= 0.0) { + other_way += 360.0; + } + // move to the +l end/center of the runway + //cout << "Runway center is at " << runway._lon << ", " << runway._lat << '\n'; + Point3D origin = Point3D(runway._lon, runway._lat, aptElev); + Point3D ref = origin; + double tshlon, tshlat, tshr; + double tolon, tolat, tor; + rwy.length = runway._length * SG_FEET_TO_METER; + rwy.width = runway._width * SG_FEET_TO_METER; + geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), other_way, + rwy.length / 2.0 - 25.0, &tshlat, &tshlon, &tshr ); + geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), runway._heading, + rwy.length / 2.0 - 25.0, &tolat, &tolon, &tor ); + // Note - 25 meters in from the runway end is a bit of a hack to put the plane ahead of the user. + // now copy what we need out of runway into rwy + rwy.threshold_pos = Point3D(tshlon, tshlat, aptElev); + Point3D takeoff_end = Point3D(tolon, tolat, aptElev); + //cout << "Threshold position = " << tshlon << ", " << tshlat << ", " << aptElev << '\n'; + //cout << "Takeoff position = " << tolon << ", " << tolat << ", " << aptElev << '\n'; + rwy.hdg = runway._heading; + // Set the projection for the local area based on this active runway + ortho.Init(rwy.threshold_pos, rwy.hdg); + rwy.end1ortho = ortho.ConvertToLocal(rwy.threshold_pos); // should come out as zero + rwy.end2ortho = ortho.ConvertToLocal(takeoff_end); + + // Set the pattern direction + // TODO - we'll check for a facilities file with this in eventually - for now assume left traffic except + // for certain circumstances (RH parallel rwy). + rwy.patternDirection = -1; // Left + if(rwy.rwyID.size() == 3) { + rwy.patternDirection = (rwy.rwyID.substr(2,1) == "R" ? 1 : -1); + } + //cout << "Doing details, rwy.patterDirection is " << rwy.patternDirection << '\n'; } @@ -1596,28 +1589,27 @@ bool FGTower::OnAnyRunway(const Point3D& pt, bool onGround) { } // Based on the airport-id, go through all the runways and check for a point in them - - // TODO - do we actually need to search for the airport - surely we already know our ident and - // can just search runways of our airport??? - //cout << "Airport ident is " << ad.ident << '\n'; - FGRunway runway; - bool rwyGood = globals->get_runways()->search(ad.ident, &runway); - if(!rwyGood) { - SG_LOG(SG_ATC, SG_WARN, "Unable to find any runways for airport ID " << ad.ident << " in FGTower"); - } - bool on = false; - while(runway._id == ad.ident) { - on = OnRunway(pt, runway); - //cout << "Runway " << runway._rwy_no << ": On = " << (on ? "true\n" : "false\n"); - if(on) { - if(onGround == false) - return(true); - if(runway._rwy_no != "xx") - return(true); - } - globals->get_runways()->next(&runway); - } - return(on); + + const FGAirport* apt = fgFindAirportID(ad.ident); + assert(apt); + + for (unsigned int i=0; inumRunways(); ++i) { + if (OnRunway(pt, apt->getRunwayByIndex(i))) { + return true; + } + } + + // if onGround is true, we only match real runways, so we're done + if (onGround) return false; + + // try taxiways as well + for (unsigned int i=0; inumTaxiways(); ++i) { + if (OnRunway(pt, apt->getTaxiwayByIndex(i))) { + return true; + } + } + + return false; } diff --git a/src/Airports/apt_loader.cxx b/src/Airports/apt_loader.cxx index 896be4ea1..8ea854f70 100644 --- a/src/Airports/apt_loader.cxx +++ b/src/Airports/apt_loader.cxx @@ -44,17 +44,17 @@ #include "apt_loader.hxx" -static void addAirport(FGAirportList *airports, const string& apt_id, const string& apt_name, +FGAirport* addAirport(FGAirportList *airports, const string& apt_id, const string& apt_name, int rwy_count, double rwy_lat_accum, double rwy_lon_accum, double last_rwy_heading, double apt_elev, SGGeod& tower, bool got_tower, int type) { if (apt_id.empty()) - return; + return NULL; if (!rwy_count) { SG_LOG(SG_GENERAL, SG_ALERT, "ERROR: No runways for " << apt_id << ", skipping." ); - return; + return NULL; } double lat = rwy_lat_accum / (double)rwy_count; @@ -69,14 +69,14 @@ static void addAirport(FGAirportList *airports, const string& apt_id, const stri tower = SGGeod::fromDegFt(lon + fudge_lon, lat + fudge_lat, apt_elev + tower_height); } - airports->add(apt_id, SGGeod::fromDegFt(lon, lat, apt_elev), tower, apt_name, false, + return airports->add(apt_id, SGGeod::fromDegFt(lon, lat, apt_elev), tower, apt_name, false, type == 1/*airport*/, type == 16/*seaport*/, type == 17/*heliport*/); } // Load the airport data base from the specified aptdb file. The // metar file is used to mark the airports as having metar available // or not. -bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways, +bool fgAirportDBLoad( FGAirportList *airports, const string &aptdb_file, const string &metar_file ) { // @@ -100,7 +100,8 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways, string line; char tmp[2049]; tmp[2048] = 0; - + vector runways; + unsigned int line_id = 0; unsigned int line_num = 0; double rwy_lon_accum = 0.0; @@ -150,9 +151,15 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways, SG_LOG( SG_GENERAL, SG_BULK, "Next airport = " << id << " " << elev ); - addAirport(airports, last_apt_id, last_apt_name, rwy_count, rwy_lat_accum, rwy_lon_accum, + FGAirport* apt = addAirport(airports, last_apt_id, last_apt_name, rwy_count, rwy_lat_accum, rwy_lon_accum, last_rwy_heading, last_apt_elev, last_tower, got_tower, last_apt_type); + for (unsigned int r=0; r< runways.size(); ++r) { + apt->addRunway(runways[r]); + } + + runways.clear(); + last_apt_id = id; last_apt_elev = elev; last_apt_name = ""; @@ -210,11 +217,12 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways, double smoothness = atof( token[13].c_str() ); bool dist_remaining = (atoi( token[14].c_str() ) == 1 ); - runways->add( last_apt_id, rwy_no, lon, lat, heading, length, + FGRunway rwy(last_apt_id, rwy_no, lon, lat, heading, length, width, displ_thresh1, displ_thresh2, stopway1, stopway2, lighting_flags, surface_code, shoulder_code, marking_code, smoothness, - dist_remaining ); + dist_remaining); + runways.push_back(rwy); } else if ( line_id == 18 ) { // beacon entry (ignore) } else if ( line_id == 14 ) { diff --git a/src/Airports/apt_loader.hxx b/src/Airports/apt_loader.hxx index ea13216a5..883e0384d 100644 --- a/src/Airports/apt_loader.hxx +++ b/src/Airports/apt_loader.hxx @@ -25,26 +25,17 @@ #ifndef _FG_APT_LOADER_HXX #define _FG_APT_LOADER_HXX - -#ifdef HAVE_CONFIG_H -# include -#endif - #include #include -using std::string; - #include "simple.hxx" -#include "runways.hxx" // Load the airport data base from the specified aptdb file. The // metar file is used to mark the airports as having metar available // or not. -bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways, - const string &aptdb_file, const string &metar_file ); +bool fgAirportDBLoad( FGAirportList *airports, const string &aptdb_file, const std::string &metar_file ); #endif // _FG_APT_LOADER_HXX diff --git a/src/Airports/dynamics.cxx b/src/Airports/dynamics.cxx index 39c305cca..41b77bae1 100644 --- a/src/Airports/dynamics.cxx +++ b/src/Airports/dynamics.cxx @@ -419,7 +419,7 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s currentlyActive = &ulActive; } // - currRunwayGroup->setActive(_ap->getId(), + currRunwayGroup->setActive(_ap, windSpeed, windHeading, maxTail, @@ -485,20 +485,8 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s string FGAirportDynamics::chooseRunwayFallback() { - FGEnvironment - stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment")) - ->getEnvironment(getLatitude(), - getLongitude(), - getElevation()); - - double windSpeed = stationweather.get_wind_speed_kt(); - double windHeading = stationweather.get_wind_from_heading_deg(); - if (windSpeed == 0) { - windHeading = 270; // This forces West-facing rwys to be used in no-wind situations - //which is consistent with Flightgear's initial setup. - } - - return globals->get_runways()->search(_ap->getId(), int(windHeading)); + FGRunway rwy = _ap->getActiveRunwayForUsage(); + return rwy._rwy_no; } void FGAirportDynamics::addParking(FGParking& park) { diff --git a/src/Airports/groundnetwork.cxx b/src/Airports/groundnetwork.cxx index a4cefee0d..b4f48caee 100644 --- a/src/Airports/groundnetwork.cxx +++ b/src/Airports/groundnetwork.cxx @@ -41,6 +41,8 @@ //#include
//#include +#include + #include //#include diff --git a/src/Airports/runwayprefs.cxx b/src/Airports/runwayprefs.cxx index a6112e44e..ae204474e 100644 --- a/src/Airports/runwayprefs.cxx +++ b/src/Airports/runwayprefs.cxx @@ -194,7 +194,7 @@ RunwayGroup& RunwayGroup:: operator= (const RunwayGroup &other) return *this; } -void RunwayGroup::setActive(const string &aptId, +void RunwayGroup::setActive(const FGAirport* airport, double windSpeed, double windHeading, double maxTail, @@ -234,15 +234,10 @@ void RunwayGroup::setActive(const string &aptId, // validSelection = true; for (int j = 0; j < activeRwys; j++) - { - - name = rwyList[j].getRwyList(i); - //cerr << "Name of Runway: " << name; - if (globals->get_runways()->search( aptId, - name, - &rwy)) - { - //cerr << "Succes" << endl; + { + rwy = airport->getRunwayByIdent(rwyList[j].getRwyList(i)); + + //cerr << "Succes" << endl; hdgDiff = fabs(windHeading - rwy._heading); //cerr << "Wind Heading: " << windHeading << "Runway Heading: " <get_runways()->search( aptId, - name, - &rwy)) - { + name = rwyList[choice[j]].getRwyList(i); + rwy = airport->getRunwayByIdent(name); + //cerr << "Succes" << endl; hdgDiff = fabs(windHeading - rwy._heading); if (hdgDiff > 180) @@ -327,10 +315,7 @@ void RunwayGroup::setActive(const string &aptId, tailWind = -windSpeed * cos(hdgDiff); if ((tailWind > maxTail) || (crossWind > maxCross)) validSelection = false; - }else { - SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId ); - exit(1); - } + } if (validSelection) diff --git a/src/Airports/runwayprefs.hxx b/src/Airports/runwayprefs.hxx index d3fccdcc2..c9ac72709 100644 --- a/src/Airports/runwayprefs.hxx +++ b/src/Airports/runwayprefs.hxx @@ -112,7 +112,7 @@ public: void setName(const string& nm) { name = nm; }; void add(const RunwayList& list) { rwyList.push_back(list);}; - void setActive(const string& aptId, double windSpeed, double windHeading, double maxTail, double maxCross, stringVec *curr); + void setActive(const FGAirport* airport, double windSpeed, double windHeading, double maxTail, double maxCross, stringVec *curr); int getNrActiveRunways() { return nrActive;}; void getActive(int i, string& name, string& type); diff --git a/src/Airports/runways.cxx b/src/Airports/runways.cxx index 3ea0b64cf..fa92e91d5 100644 --- a/src/Airports/runways.cxx +++ b/src/Airports/runways.cxx @@ -40,10 +40,13 @@ using std::istream; using std::multimap; +using std::string; +FGRunway::FGRunway() +{ +} -// add an entry to the list -void FGRunwayList::add( const string& id, const string& rwy_no, +FGRunway::FGRunway( const string& id, const string& rwy_no, const double longitude, const double latitude, const double heading, const double length, const double width, @@ -53,267 +56,92 @@ void FGRunwayList::add( const string& id, const string& rwy_no, const string& shoulder_code, const int marking_code, const double smoothness, const bool dist_remaining ) { - FGRunway rwy; - - rwy._id = id; - rwy._rwy_no = rwy_no; - // strip trailing "x" if it exists in runway number - string tmp = rwy._rwy_no.substr(2, 1); - if ( tmp == "x" ) { - rwy._rwy_no = rwy._rwy_no.substr(0, 2); + _rwy_no = rwy_no; + if (rwy_no[0] == 'x') { + _type = "taxiway"; + } else { + _type = "runway"; + + // canonicalise runway ident + if ((rwy_no.size() == 1) || !isdigit(rwy_no[1])) { + _rwy_no = "0" + rwy_no; } - rwy._lon = longitude; - rwy._lat = latitude; - rwy._heading = heading; - rwy._length = length; - rwy._width = width; - rwy._displ_thresh1 = displ_thresh1; - rwy._displ_thresh2 = displ_thresh2; - rwy._stopway1 = stopway1; - rwy._stopway2 = stopway2; - - rwy._lighting_flags = lighting_flags; - rwy._surface_code = surface_code; - rwy._shoulder_code = shoulder_code; - rwy._marking_code = marking_code; - rwy._smoothness = smoothness; - rwy._dist_remaining = dist_remaining; - - if ( rwy_no[0] == 'x' ) { - rwy._type = "taxiway"; - } else { - rwy._type = "runway"; + if ((_rwy_no.size() > 2) && (_rwy_no[2] == 'x')) { + _rwy_no = _rwy_no.substr(0, 2); } - runways.insert(pair(rwy._id, rwy)); + } + + _id = id; + _lon = longitude; + _lat = latitude; + _heading = heading; + _length = length; + _width = width; + _displ_thresh1 = displ_thresh1; + _displ_thresh2 = displ_thresh2; + _stopway1 = stopway1; + _stopway2 = stopway2; + + _lighting_flags = lighting_flags; + _surface_code = surface_code; + _shoulder_code = shoulder_code; + _marking_code = marking_code; + _smoothness = smoothness; + _dist_remaining = dist_remaining; } +string FGRunway::reverseIdent(const string& aRunwayIdent) +{ + // Helipads don't have a seperate number per end + if (aRunwayIdent.size() && (aRunwayIdent[0] == 'H' || aRunwayIdent[0] == 'h' || aRunwayIdent[0] == 'x')) { + return aRunwayIdent; + } -// Return reverse rwy number -// eg 01 -> 19 -// 03L -> 21R -static string GetReverseRunwayNo(string& rwyno) { - // cout << "Original rwyno = " << rwyNo << '\n'; + std::string ident(aRunwayIdent); - // Helipads don't have a seperate number per end - if(rwyno.size() && (rwyno[0] == 'H' || rwyno[0] == 'h' || rwyno[0] == 'x')) { - return rwyno; - } - - // standardize input number - string tmp = rwyno.substr(1, 1); - if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) { - tmp = rwyno; - rwyno = "0" + tmp; - SG_LOG( SG_GENERAL, SG_INFO, - "Standardising rwy number from " << tmp << " to " << rwyno ); - } - - char buf[4]; - int rn = atoi(rwyno.substr(0,2).c_str()); - rn += 18; - while(rn > 36) { - rn -= 36; - } - sprintf(buf, "%02i", rn); - if(rwyno.size() == 3) { - if(rwyno.substr(2,1) == "L") { - buf[2] = 'R'; - buf[3] = '\0'; - } else if (rwyno.substr(2,1) == "R") { - buf[2] = 'L'; - buf[3] = '\0'; - } else if (rwyno.substr(2,1) == "C") { - buf[2] = 'C'; - buf[3] = '\0'; - } else if (rwyno.substr(2,1) == "T") { - buf[2] = 'T'; - buf[3] = '\0'; - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " - << rwyno << " passed to GetReverseRunwayNo(...)"); - } - } - return(buf); -} - - -// search for the specified apt id (wierd!) -bool FGRunwayList::search( const string& aptid, FGRunway* r ) { - runway_map_iterator pos; - - pos = runways.lower_bound(aptid); - if ( pos != runways.end() ) { - current = pos; - *r = pos->second; - return true; + char buf[4]; + int rn = atoi(ident.substr(0,2).c_str()); + rn += 18; + while(rn > 36) { + rn -= 36; + } + + sprintf(buf, "%02i", rn); + if(ident.size() == 3) { + if(ident.substr(2,1) == "L") { + buf[2] = 'R'; + buf[3] = '\0'; + } else if (ident.substr(2,1) == "R") { + buf[2] = 'L'; + buf[3] = '\0'; + } else if (ident.substr(2,1) == "C") { + buf[2] = 'C'; + buf[3] = '\0'; + } else if (ident.substr(2,1) == "T") { + buf[2] = 'T'; + buf[3] = '\0'; } else { - return false; + SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " + << aRunwayIdent << " passed to FGRunway::reverseIdent"); } + } + + return buf; } - -// search for the specified apt id and runway no -bool FGRunwayList::search( const string& aptid, const string& rwyno, - FGRunway *r ) +double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt) const { - string revrwyno = ""; - string runwayno = rwyno; - if ( runwayno.length() ) { - // standardize input number - string tmp = runwayno.substr(1, 1); - if (( tmp == "L" || tmp == "R" || tmp == "C" ) - || (runwayno.size() == 1)) - { - tmp = runwayno; - runwayno = "0" + tmp; - SG_LOG( SG_GENERAL, SG_INFO, "Standardising rwy number from " - << tmp << " to " << runwayno ); - } - revrwyno = GetReverseRunwayNo(runwayno); - } - runway_map_iterator pos; - for ( pos = runways.lower_bound( aptid ); - pos != runways.upper_bound( aptid ); ++pos) - { - if ( pos->second._rwy_no == runwayno ) { - current = pos; - *r = pos->second; - return true; - } else if ( pos->second._rwy_no == revrwyno ) { - // Search again with the other-end runway number. - // Remember we have to munge the heading and rwy_no - // results if this one matches - current = pos; - *r = pos->second; - // NOTE - matching revrwyno implies that runwayno was - // actually correct. - r->_rwy_no = runwayno; - r->_heading += 180.0; - return true; - } - } - - return false; -} - - -// (wierd!) -FGRunway FGRunwayList::search( const string& aptid ) { - FGRunway a; - search( aptid, &a ); - return a; + int surface = 1; + if (_surface_code == 12 || _surface_code == 5) // dry lakebed & gravel + surface = 2; + else if (_surface_code == 1 || _surface_code == 2) // asphalt & concrete + surface = 3; + + return _length * aLengthWt + _width * aWidthWt + surface * aSurfaceWt + 1e-20; } - -// Return the runway closest to a given heading -bool FGRunwayList::search( const string& aptid, const int tgt_hdg, - FGRunway *runway ) +bool FGRunway::isTaxiway() const { - string rwyNo = search(aptid, tgt_hdg); - return(rwyNo == "NN" ? false : search(aptid, rwyNo, runway)); -} - - -// Return the runway number of the runway closest to a given heading -string FGRunwayList::search( const string& aptid, const int hdg ) { - //SG_LOG(SG_GENERAL, SG_ALERT, "searching runway for " << aptid - // << " with target heading " << hdg); - - FGRunway r; - if (!search(aptid, &r)) { - SG_LOG(SG_GENERAL, SG_ALERT, "Failed to find " - << aptid << " in database."); - return "NN"; - } - - SGPropertyNode *param = fgGetNode("/sim/airport/runways/search", true); - double lenwgt = param->getDoubleValue("length-weight", 0.01); - double widwgt = param->getDoubleValue("width-weight", 0.01); - double surfwgt = param->getDoubleValue("surface-weight", 10); - double devwgt = param->getDoubleValue("deviation-weight", 1); - - FGRunway best; - double max = 0.0; - bool reversed = false; - - do { - if (r._id != aptid) - break; - if (r._type != "runway") - continue; - - int surface = 1; - if (r._surface_code == 12 || r._surface_code == 5) // dry lakebed & gravel - surface = 2; - else if (r._surface_code == 1 || r._surface_code == 2) // asphalt & concrete - surface = 3; - - double quality, bad, diff; - double good = lenwgt * r._length + widwgt * r._width + surfwgt * surface + 1e-20; - - // this side - diff = hdg - r._heading; - while (diff < -180) - diff += 360; - while (diff >= 180) - diff -= 360; - bad = fabs(devwgt * diff) + 1e-20; - - quality = good / bad; - //SG_LOG(SG_GENERAL, SG_ALERT, " runway " << r._rwy_no << " -> " << quality); - if (quality > max) { - max = quality; - best = r; - reversed = false; - } - - // other side - diff = hdg - r._heading - 180; - while (diff < -180) - diff += 360; - while (diff >= 180) - diff -= 360; - bad = fabs(devwgt * diff) + 1e-20; - - quality = good / bad; - //SG_LOG(SG_GENERAL, SG_ALERT, " runway " << GetReverseRunwayNo(r._rwy_no) - // << " -> " << quality); - if (quality > max) { - max = quality; - best = r; - reversed = true; - } - - } while (next(&r)); - - return reversed ? GetReverseRunwayNo(best._rwy_no) : best._rwy_no; -} - - -bool FGRunwayList::next( FGRunway* runway ) { - ++current; - if ( current != runways.end() ) { - *runway = current->second; - return true; - } else { - return false; - } -} - - -FGRunway FGRunwayList::next() { - FGRunway result; - - ++current; - if ( current != runways.end() ) { - result = current->second; - } - - return result; -} - - -// Destructor -FGRunwayList::~FGRunwayList( void ) { + return (_rwy_no[0] == 'x'); } diff --git a/src/Airports/runways.hxx b/src/Airports/runways.hxx index 532c777cf..34c884531 100644 --- a/src/Airports/runways.hxx +++ b/src/Airports/runways.hxx @@ -24,37 +24,43 @@ #ifndef _FG_RUNWAYS_HXX #define _FG_RUNWAYS_HXX - -#ifndef __cplusplus -# error This library requires C++ -#endif - - -#ifdef HAVE_CONFIG_H -# include -#endif - #include #include -#include +#include -using std::string; -using std::multimap; - - -struct ltstr { - bool operator()(const string& s1, const string& s2) const { - return s1 < s2; - } -}; - - -struct FGRunway { - - string _id; - string _rwy_no; - string _type; // runway / taxiway +class FGRunway +{ +public: + FGRunway(); + + FGRunway(const std::string& id, const std::string& rwy_no, + const double longitude, const double latitude, + const double heading, const double length, + const double width, + const double displ_thresh1, const double displ_thresh2, + const double stopway1, const double stopway2, + const std::string& lighting_flags, const int surface_code, + const std::string& shoulder_code, const int marking_code, + const double smoothness, const bool dist_remaining); + + /** + * given a runway identifier (06, 18L, 31R) compute the identifier for the + * opposite heading runway (24, 36R, 13L) string. + */ + static std::string reverseIdent(const std::string& aRunayIdent); + + /** + * score this runway according to the specified weights. Used by + * FGAirport::findBestRunwayForHeading + */ + double score(double aLengthWt, double aWidthWt, double aSurfaceWt) const; + + bool isTaxiway() const; + + std::string _id; + std::string _rwy_no; + std::string _type; // runway / taxiway double _lon; double _lat; @@ -66,60 +72,14 @@ struct FGRunway { double _stopway1; double _stopway2; - string _lighting_flags; + std::string _lighting_flags; int _surface_code; - string _shoulder_code; + std::string _shoulder_code; int _marking_code; double _smoothness; bool _dist_remaining; }; -typedef multimap < string, FGRunway, ltstr > runway_map; -typedef runway_map::iterator runway_map_iterator; -typedef runway_map::const_iterator const_runway_map_iterator; - -class FGRunwayList { - -private: - - runway_map runways; - runway_map_iterator current; - -public: - - // Constructor (new) - FGRunwayList() {} - - // Destructor - ~FGRunwayList(); - - // add an entry to the list - void add( const string& id, const string& rwy_no, - const double longitude, const double latitude, - const double heading, const double length, const double width, - const double displ_thresh1, const double displ_thresh2, - const double stopway1, const double stopway2, - const string& lighting_flags, const int surface_code, - const string& shoulder_code, const int marking_code, - const double smoothness, const bool dist_remaining ); - - // search for the specified apt id. - // Returns true if successful, otherwise returns false. - // On success, runway data is returned thru "runway" pointer. - // "runway" is not changed if "apt" is not found. - bool search( const string& aptid, FGRunway* runway ); - bool search( const string& aptid, const string& rwyno, FGRunway* runway ); - - // DCL - search for runway closest to desired heading in degrees - bool search( const string& aptid, const int hdg, FGRunway* runway ); - - // Return the runway number of the runway closest to a given heading - string search( const string& aptid, const int tgt_hdg ); - - FGRunway search( const string& aptid ); - bool next( FGRunway* runway ); - FGRunway next(); -}; - +typedef std::vector FGRunwayVector; #endif // _FG_RUNWAYS_HXX diff --git a/src/Airports/simple.cxx b/src/Airports/simple.cxx index 018b44cea..c8a62a233 100644 --- a/src/Airports/simple.cxx +++ b/src/Airports/simple.cxx @@ -46,6 +46,7 @@ #include
#include
#include +#include #include @@ -103,9 +104,159 @@ FGAirportDynamics * FGAirport::getDynamics() return _dynamics; } +unsigned int FGAirport::numRunways() const +{ + return mRunways.size(); +} + +FGRunway FGAirport::getRunwayByIndex(unsigned int aIndex) const +{ + assert(aIndex >= 0 && aIndex < mRunways.size()); + return mRunways[aIndex]; +} + +bool FGAirport::hasRunwayWithIdent(const string& aIdent) const +{ + bool dummy; + return (getIteratorForRunwayIdent(aIdent, dummy) != mRunways.end()); +} + +FGRunway FGAirport::getRunwayByIdent(const string& aIdent) const +{ + bool reversed; + FGRunwayVector::const_iterator it = getIteratorForRunwayIdent(aIdent, reversed); + if (it == mRunways.end()) { + SG_LOG(SG_GENERAL, SG_ALERT, "no such runway '" << aIdent << "' at airport " << _id); + throw sg_range_exception("unknown runway " + aIdent + " at airport:" + _id, "FGAirport::getRunwayByIdent"); + } + + if (!reversed) { + return *it; + } + + FGRunway result(*it); + result._heading += 180.0; + result._rwy_no = FGRunway::reverseIdent(it->_rwy_no); + return result; +} +FGRunwayVector::const_iterator +FGAirport::getIteratorForRunwayIdent(const string& aIdent, bool& aReversed) const +{ + string ident(aIdent); + if ((aIdent.size() == 1) || !isdigit(aIdent[1])) { + ident = "0" + aIdent; + } + + string reversedRunway = FGRunway::reverseIdent(ident); + FGRunwayVector::const_iterator it = mRunways.begin(); + + for (; it != mRunways.end(); ++it) { + if (it->_rwy_no == ident) { + aReversed = false; + return it; + } + + if (it->_rwy_no == reversedRunway) { + aReversed = true; + return it; + } + } + return it; // end() +} + +static double normaliseBearing(double aBearing) +{ + while (aBearing < -180.0) { + aBearing += 360.0; + } + + while (aBearing > 180.0) { + aBearing -= 180.0; + } + + return aBearing; +} +FGRunway FGAirport::findBestRunwayForHeading(double aHeading) const +{ + FGRunwayVector::const_iterator it = mRunways.begin(); + FGRunway result; + double currentBestQuality = 0.0; + + SGPropertyNode *param = fgGetNode("/sim/airport/runways/search", true); + double lengthWeight = param->getDoubleValue("length-weight", 0.01); + double widthWeight = param->getDoubleValue("width-weight", 0.01); + double surfaceWeight = param->getDoubleValue("surface-weight", 10); + double deviationWeight = param->getDoubleValue("deviation-weight", 1); + + for (; it != mRunways.end(); ++it) { + double good = it->score(lengthWeight, widthWeight, surfaceWeight); + + // first side + double dev = normaliseBearing(aHeading - it->_heading); + double bad = fabs(deviationWeight * dev) + 1e-20; + double quality = good / bad; + + if (quality > currentBestQuality) { + currentBestQuality = quality; + result = *it; + } + + dev = normaliseBearing(aHeading - it->_heading - 180.0); + bad = fabs(deviationWeight * dev) + 1e-20; + quality = good / bad; + + if (quality > currentBestQuality) { + currentBestQuality = quality; + result = *it; + result._heading += 180.0; + result._rwy_no = FGRunway::reverseIdent(it->_rwy_no); + } + } + + return result; +} + +unsigned int FGAirport::numTaxiways() const +{ + return mTaxiways.size(); +} + +FGRunway FGAirport::getTaxiwayByIndex(unsigned int aIndex) const +{ + assert(aIndex >= 0 && aIndex < mTaxiways.size()); + return mTaxiways[aIndex]; +} + +void FGAirport::addRunway(const FGRunway& aRunway) +{ + if (aRunway.isTaxiway()) { + mTaxiways.push_back(aRunway); + } else { + mRunways.push_back(aRunway); + } +} + +FGRunway FGAirport::getActiveRunwayForUsage() const +{ + static FGEnvironmentMgr* envMgr = NULL; + if (!envMgr) { + envMgr = (FGEnvironmentMgr *) globals->get_subsystem("environment"); + } + + FGEnvironment stationWeather(envMgr->getEnvironment(_location)); + + double windSpeed = stationWeather.get_wind_speed_kt(); + double hdg = stationWeather.get_wind_from_heading_deg(); + if (windSpeed <= 0.0) { + hdg = 270; // This forces West-facing rwys to be used in no-wind situations + // which is consistent with Flightgear's initial setup. + } + + return findBestRunwayForHeading(hdg); +} /****************************************************************************** * FGAirportList @@ -145,7 +296,7 @@ FGAirportList::~FGAirportList( void ) // add an entry to the list -void FGAirportList::add( const string &id, const SGGeod& location, const SGGeod& tower_location, +FGAirport* FGAirportList::add( const string &id, const SGGeod& location, const SGGeod& tower_location, const string &name, bool has_metar, bool is_airport, bool is_seaport, bool is_heliport) { @@ -158,6 +309,8 @@ void FGAirportList::add( const string &id, const SGGeod& location, const SGGeod& airports_array.push_back( a ); SG_LOG( SG_GENERAL, SG_BULK, "Adding " << id << " pos = " << location.getLongitudeDeg() << ", " << location.getLatitudeDeg() << " elev = " << location.getElevationFt() ); + + return a; } diff --git a/src/Airports/simple.hxx b/src/Airports/simple.hxx index 78a53e750..ca3ebcd4d 100644 --- a/src/Airports/simple.hxx +++ b/src/Airports/simple.hxx @@ -27,15 +27,6 @@ #ifndef _FG_SIMPLE_HXX #define _FG_SIMPLE_HXX - -#ifndef __cplusplus -# error This library requires C++ -#endif - - -#ifdef HAVE_CONFIG_H -# include -#endif #include #include @@ -45,29 +36,20 @@ #include #include -#include "runwayprefs.hxx" -#include "parking.hxx" -#include "groundnetwork.hxx" -#include "dynamics.hxx" - - -using std::string; -using std::map; -using std::set; -using std::vector; - - +#include "Airports/runways.hxx" +// forward decls +class FGAirportDynamics; /*************************************************************************************** * **************************************************************************************/ class FGAirport { private: - string _id; + std::string _id; SGGeod _location; SGGeod _tower_location; - string _name; + std::string _name; bool _has_metar; bool _is_airport; bool _is_seaport; @@ -77,12 +59,13 @@ private: public: FGAirport(); // FGAirport(const FGAirport &other); - FGAirport(const string& id, const SGGeod& location, const SGGeod& tower, const string& name, + FGAirport(const std::string& id, const SGGeod& location, const SGGeod& tower, + const std::string& name, bool has_metar, bool is_airport, bool is_seaport, bool is_heliport); ~FGAirport(); - const string& getId() const { return _id; } - const string& getName() const { return _name; } + const std::string& getId() const { return _id; } + const std::string& getName() const { return _name; } double getLongitude() const { return _location.getLongitudeDeg(); } // Returns degrees double getLatitude() const { return _location.getLatitudeDeg(); } @@ -95,14 +78,35 @@ public: const SGGeod& getTowerLocation() const { return _tower_location; } - void setId(const string& id) { _id = id; } + void setId(const std::string& id) { _id = id; } void setMetar(bool value) { _has_metar = value; } - FGAirportDynamics *getDynamics(); + FGRunway getActiveRunwayForUsage() const; + FGAirportDynamics *getDynamics(); + + unsigned int numRunways() const; + FGRunway getRunwayByIndex(unsigned int aIndex) const; + + bool hasRunwayWithIdent(const std::string& aIdent) const; + FGRunway getRunwayByIdent(const std::string& aIdent) const; + FGRunway findBestRunwayForHeading(double aHeading) const; + + unsigned int numTaxiways() const; + FGRunway getTaxiwayByIndex(unsigned int aIndex) const; + + void addRunway(const FGRunway& aRunway); private: + /** + * Helper to locate a runway by ident + */ + FGRunwayVector::const_iterator getIteratorForRunwayIdent(const std::string& aIdent, bool& aReversed) const; + FGAirport operator=(FGAirport &other); FGAirport(const FGAirport&); + + std::vector mRunways; + std::vector mTaxiways; }; @@ -114,11 +118,11 @@ public: }; -typedef map < string, FGAirport* > airport_map; +typedef std::map < std::string, FGAirport* > airport_map; typedef airport_map::iterator airport_map_iterator; typedef airport_map::const_iterator const_airport_map_iterator; -typedef vector < FGAirport * > airport_list; +typedef std::vector < FGAirport * > airport_list; typedef airport_list::iterator airport_list_iterator; typedef airport_list::const_iterator const_airport_list_iterator; @@ -138,13 +142,13 @@ public: ~FGAirportList(); // add an entry to the list - void add( const string& id, const SGGeod& location, const SGGeod& tower, - const string& name, bool has_metar, bool is_airport, + FGAirport* add( const std::string& id, const SGGeod& location, const SGGeod& tower, + const std::string& name, bool has_metar, bool is_airport, bool is_seaport, bool is_heliport ); // search for the specified id. // Returns NULL if unsucessfull. - FGAirport* search( const string& id ); + FGAirport* search( const std::string& id ); // Search for the next airport in ASCII sequence to the supplied id. // eg. id = "KDC" or "KDCA" would both return "KDCA". @@ -152,7 +156,7 @@ public: // NOTE: Numbers come prior to A-Z in ASCII sequence so id = "LD" would return "LD57", not "LDDP" // Implementation assumes airport codes are unique. // Returns NULL if unsucessfull. - const FGAirport* findFirstById( const string& id, bool exact = false ); + const FGAirport* findFirstById( const std::string& id, bool exact = false ); // search for the airport closest to the specified position // (currently a linear inefficient search so it's probably not @@ -179,23 +183,23 @@ public: /** * Mark the specified airport record as not having metar */ - void no_metar( const string &id ); + void no_metar( const std::string &id ); /** * Mark the specified airport record as (yes) having metar */ - void has_metar( const string &id ); + void has_metar( const std::string &id ); }; // find basic airport location info from airport database -const FGAirport *fgFindAirportID( const string& id); +const FGAirport *fgFindAirportID( const std::string& id); // get airport elevation -double fgGetAirportElev( const string& id ); +double fgGetAirportElev( const std::string& id ); // get airport position -Point3D fgGetAirportPos( const string& id ); +Point3D fgGetAirportPos( const std::string& id ); #endif // _FG_SIMPLE_HXX diff --git a/src/Cockpit/hud_rwy.cxx b/src/Cockpit/hud_rwy.cxx index f70ed6d77..91fe234f8 100644 --- a/src/Cockpit/hud_rwy.cxx +++ b/src/Cockpit/hud_rwy.cxx @@ -177,10 +177,11 @@ void runway_instr::draw() bool runway_instr::get_active_runway(FGRunway& runway) { - FGEnvironment stationweather = - ((FGEnvironmentMgr *)globals->get_subsystem("environment"))->getEnvironment(); - double hdg = stationweather.get_wind_from_heading_deg(); - return globals->get_runways()->search(fgGetString("/sim/presets/airport-id"), int(hdg), &runway); + const FGAirport* apt = fgFindAirportID(fgGetString("/sim/presets/airport-id")); + if (!apt) return false; + + runway = apt->getActiveRunwayForUsage(); + return (!runway._rwy_no.empty()); } @@ -432,7 +433,7 @@ void runway_instr::setLineWidth() else alt_nm *= SG_METER_TO_NM; - //Calculate distance away from runway, C = v(A²+B²) + //Calculate distance away from runway, C = v(A≤+B≤) distance = sqrt(alt_nm * alt_nm + distance*distance); if (distance < scaleDist) glLineWidth(1.0 + ((lnScale - 1) * ((scaleDist - distance) / scaleDist))); diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index a940df8c3..a7b860afa 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -33,6 +33,7 @@ #include // sprintf #include +#include #include #include diff --git a/src/Environment/environment_mgr.cxx b/src/Environment/environment_mgr.cxx index 5440ba253..8806b674e 100644 --- a/src/Environment/environment_mgr.cxx +++ b/src/Environment/environment_mgr.cxx @@ -285,6 +285,18 @@ FGEnvironmentMgr::getEnvironment (double lat, double lon, double alt) const return env; } +FGEnvironment +FGEnvironmentMgr::getEnvironment(const SGGeod& aPos) const +{ + // Always returns the same environment + // for now; we'll make it interesting + // later. + FGEnvironment env = *_environment; + env.set_elevation_ft(aPos.getElevationFt()); + return env; + +} + void FGEnvironmentMgr::_update_fdm () const { diff --git a/src/Environment/environment_mgr.hxx b/src/Environment/environment_mgr.hxx index e45e35330..7e0bc6821 100644 --- a/src/Environment/environment_mgr.hxx +++ b/src/Environment/environment_mgr.hxx @@ -25,6 +25,7 @@ #include #include +#include #ifdef SG_HAVE_STD_INCLUDES # include @@ -70,6 +71,7 @@ public: virtual FGEnvironment getEnvironment (double lat, double lon, double alt) const; + virtual FGEnvironment getEnvironment(const SGGeod& aPos) const; private: void _update_fdm () const; diff --git a/src/Instrumentation/HUD/HUD_runway.cxx b/src/Instrumentation/HUD/HUD_runway.cxx index 434b73c2e..286360cd2 100644 --- a/src/Instrumentation/HUD/HUD_runway.cxx +++ b/src/Instrumentation/HUD/HUD_runway.cxx @@ -170,13 +170,15 @@ void HUD::Runway::draw() bool HUD::Runway::get_active_runway(FGRunway& runway) { - FGEnvironment stationweather = - ((FGEnvironmentMgr *)globals->get_subsystem("environment"))->getEnvironment(); - double hdg = stationweather.get_wind_from_heading_deg(); - return globals->get_runways()->search(fgGetString("/sim/presets/airport-id"), int(hdg), &runway); + const FGAirport* apt = fgFindAirportID(fgGetString("/sim/presets/airport-id")); + if (!apt) return false; + + runway = apt->getActiveRunwayForUsage(); + return (!runway._rwy_no.empty()); } + void HUD::Runway::get_rwy_points(sgdVec3 *_points3d) { double alt = current_aircraft.fdm_state->get_Runway_altitude() * SG_FEET_TO_METER; @@ -424,7 +426,7 @@ void HUD::Runway::setLineWidth() alt_nm *= SG_METER_TO_NM; - //Calculate distance away from runway, C = v(A²+B²) + //Calculate distance away from runway, C = v(A≤+B≤) distance = sqrt(alt_nm * alt_nm + distance*distance); if (distance < _scale_dist) glLineWidth(1.0 + ((_line_scale - 1) * ((_scale_dist - distance) / _scale_dist))); diff --git a/src/Instrumentation/KLN89/kln89_page_apt.cxx b/src/Instrumentation/KLN89/kln89_page_apt.cxx index 5830bdc34..0be5c4acd 100644 --- a/src/Instrumentation/KLN89/kln89_page_apt.cxx +++ b/src/Instrumentation/KLN89/kln89_page_apt.cxx @@ -514,23 +514,19 @@ void KLN89AptPage::UpdateAirport(const string& id) { // Runways _aptRwys.clear(); - FGRunway r; - bool haveRwy = globals->get_runways()->search(id, &r); - while(haveRwy && r._id == id) { - // Insert the runway with longest at the start of the array - for(unsigned int i = 0; i <= _aptRwys.size(); ++i) { - if(i == _aptRwys.size()) { - _aptRwys.push_back(r); - break; - } else { - if(r._length > _aptRwys[i]._length) { - _aptRwys.insert(_aptRwys.begin() + i, r); - break; - } - } - } - haveRwy = globals->get_runways()->next(&r); - } + const FGAirport* apt = fgFindAirportID(id); + assert(apt); + + // build local array, longest runway first + for (unsigned int r=0; rnumRunways(); ++r) { + FGRunway rwy(apt->getRunwayByIndex(r)); + if ((r > 0) && (rwy._length > _aptRwys.front()._length)) { + _aptRwys.insert(_aptRwys.begin(), rwy); + } else { + _aptRwys.push_back(rwy); + } + } + _nRwyPages = (_aptRwys.size() + 1) / 2; // 2 runways per page. if(_nFreqPages < 1) _nFreqPages = 1; if(_nRwyPages < 1) _nRwyPages = 1; diff --git a/src/Instrumentation/KLN89/kln89_page_fpl.cxx b/src/Instrumentation/KLN89/kln89_page_fpl.cxx index 0ed7cdff5..24b04055e 100644 --- a/src/Instrumentation/KLN89/kln89_page_fpl.cxx +++ b/src/Instrumentation/KLN89/kln89_page_fpl.cxx @@ -26,7 +26,9 @@ #endif #include "kln89_page_fpl.hxx" + #include +#include using namespace std; diff --git a/src/Instrumentation/groundradar.cxx b/src/Instrumentation/groundradar.cxx index 02f8ca1a4..ee000f234 100644 --- a/src/Instrumentation/groundradar.cxx +++ b/src/Instrumentation/groundradar.cxx @@ -112,13 +112,30 @@ void GroundRadar::createTexture(const char* texture_name) FGTextureManager::addTexture(texture_name, getTexture()); } +void GroundRadar::addRunwayVertices(const FGRunway& aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices) +{ + double az1, az2, dist_m; + geo_inverse_wgs_84(aTowerLat, aTowerLon, aRunway._lat, aRunway._lon, &az1, &az2, &dist_m); + + osg::Vec3 center = fromPolar(az1, dist_m * aScale) + osg::Vec3(256, 256, 0); + osg::Vec3 leftcenter = fromPolar(aRunway._heading, aRunway._length * SG_FEET_TO_METER * aScale / 2) + center; + osg::Vec3 lefttop = fromPolar(aRunway._heading - 90, aRunway._width * SG_FEET_TO_METER * aScale / 2) + leftcenter; + osg::Vec3 leftbottom = leftcenter * 2 - lefttop; + osg::Vec3 rightbottom = center * 2 - lefttop; + osg::Vec3 righttop = center * 2 - leftbottom; + + aVertices->push_back(lefttop); + aVertices->push_back(leftbottom); + aVertices->push_back(rightbottom); + aVertices->push_back(righttop); +} + void GroundRadar::updateTexture() { osg::ref_ptr rwy_vertices = new osg::Vec3Array; osg::ref_ptr taxi_vertices = new osg::Vec3Array; const string airport_name = _airport_node->getStringValue(); - FGRunwayList* runways = globals->get_runways(); const FGAirport* airport = fgFindAirportID(airport_name); if (airport == 0) @@ -128,26 +145,22 @@ void GroundRadar::updateTexture() const double tower_lat = tower_location.getLatitudeDeg(); const double tower_lon = tower_location.getLongitudeDeg(); double scale = SG_METER_TO_NM * 200 / _range_node->getDoubleValue(); + + const FGAirport* apt = fgFindAirportID(airport_name); + assert(apt); - for (FGRunway runway = runways->search(airport_name); runway._id == airport_name; runway = runways->next()) + for (unsigned int i=0; inumRunways(); ++i) { - double az1, az2, dist_m; - geo_inverse_wgs_84(tower_lat, tower_lon, runway._lat, runway._lon, &az1, &az2, &dist_m); - - osg::Vec3 center = fromPolar(az1, dist_m * scale) + osg::Vec3(256, 256, 0); - osg::Vec3 leftcenter = fromPolar(runway._heading, runway._length * SG_FEET_TO_METER * scale / 2) + center; - osg::Vec3 lefttop = fromPolar(runway._heading - 90, runway._width * SG_FEET_TO_METER * scale / 2) + leftcenter; - osg::Vec3 leftbottom = leftcenter * 2 - lefttop; - osg::Vec3 rightbottom = center * 2 - lefttop; - osg::Vec3 righttop = center * 2 - leftbottom; - - osg::Vec3Array* vertices = runway._rwy_no[0] == 'x' ? taxi_vertices.get() : rwy_vertices.get(); - vertices->push_back(lefttop); - vertices->push_back(leftbottom); - vertices->push_back(rightbottom); - vertices->push_back(righttop); + FGRunway runway(apt->getRunwayByIndex(i)); + addRunwayVertices(runway, tower_lat, tower_lon, scale, rwy_vertices.get()); } - + + for (unsigned int i=0; inumTaxiways(); ++i) + { + FGRunway runway(apt->getTaxiwayByIndex(i)); + addRunwayVertices(runway, tower_lat, tower_lon, scale, taxi_vertices.get()); + } + osg::Vec3Array* vertices = new osg::Vec3Array(*taxi_vertices.get()); vertices->insert(vertices->end(), rwy_vertices->begin(), rwy_vertices->end()); _geom->setVertexArray(vertices); diff --git a/src/Instrumentation/groundradar.hxx b/src/Instrumentation/groundradar.hxx index 8839143fa..0836a526b 100644 --- a/src/Instrumentation/groundradar.hxx +++ b/src/Instrumentation/groundradar.hxx @@ -25,6 +25,9 @@ #include #include "od_gauge.hxx" +// forward decls +class FGRunway; + //////////////////////////////////////////////////////////////////////// // Built-in layer for the atc radar. //////////////////////////////////////////////////////////////////////// @@ -39,7 +42,9 @@ public: protected: void createTexture(const char* texture_name); - + + void addRunwayVertices(const FGRunway& aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices); + osg::ref_ptr _geom; SGPropertyNode_ptr _airport_node; SGPropertyNode_ptr _range_node; diff --git a/src/Instrumentation/mk_viii.cxx b/src/Instrumentation/mk_viii.cxx index fc34f0b79..f423a70f5 100755 --- a/src/Instrumentation/mk_viii.cxx +++ b/src/Instrumentation/mk_viii.cxx @@ -4288,19 +4288,15 @@ MK_VIII::Mode6Handler::test_runway (const FGRunway *_runway) bool MK_VIII::Mode6Handler::test_airport (const FGAirport *airport) { - FGRunway r; - if (globals->get_runways()->search(airport->getId(), &r)) - do - { - if (test_runway(&r)) - return true; - - // reciprocal runway - r._heading = get_reciprocal_heading(r._heading); - if (test_runway(&r)) - return true; - } - while (globals->get_runways()->next(&r) && r._id == airport->getId()); + for (unsigned int r=0; rnumRunways(); ++r) { + FGRunway rwy(airport->getRunwayByIndex(r)); + + if (test_runway(&rwy)) return true; + + // reciprocal runway + rwy._heading = get_reciprocal_heading(rwy._heading); + if (test_runway(&rwy)) return true; + } return false; } @@ -4525,46 +4521,46 @@ void MK_VIII::TCFHandler::select_runway (const FGAirport *airport, FGRunway *_runway) { +/* FGRunway r; bool status = globals->get_runways()->search(airport->getId(), &r); assert(status); + } + while (globals->get_runways()->next(&r) && r._id == airport->getId()); + */ + double min_diff = 360; - do + + for (unsigned int r=0; rnumRunways(); ++r) { + FGRunway rwy(airport->getRunwayByIndex(r)); + double diff = get_azimuth_difference(&rwy); + if (diff < min_diff) + { + min_diff = diff; + *_runway = rwy; + } + + // reciprocal runway + rwy._heading = get_reciprocal_heading(rwy._heading); + diff = get_azimuth_difference(&rwy); + if (diff < min_diff) { - double diff; - - diff = get_azimuth_difference(&r); - if (diff < min_diff) - { - min_diff = diff; - *_runway = r; - } - - // reciprocal runway - r._heading = get_reciprocal_heading(r._heading); - diff = get_azimuth_difference(&r); - if (diff < min_diff) - { - min_diff = diff; - *_runway = r; - } + min_diff = diff; + *_runway = rwy; } - while (globals->get_runways()->next(&r) && r._id == airport->getId()); + } // of airport runways iteration } bool MK_VIII::TCFHandler::test_airport (const FGAirport *airport) { - FGRunway r; - if (globals->get_runways()->search(airport->getId(), &r)) - do - { - if (r._length >= mk->conf.runway_database) - return true; - } - while (globals->get_runways()->next(&r) && r._id == airport->getId()); - + for (unsigned int r=0; rnumRunways(); ++r) { + if (airport->getRunwayByIndex(r)._length >= mk->conf.runway_database) { + return true; + } + } + return false; } diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 15e3caaa3..20b2f2447 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -67,6 +67,8 @@ #include #include #include +#include + #include #include #include @@ -751,8 +753,6 @@ void fgInitTowerLocationListener() { // Set current_options lon/lat given an airport id and heading (degrees) static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) { - FGRunway r; - if ( id.empty() ) return false; @@ -761,11 +761,9 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) { "Attempting to set starting position from airport code " << id << " heading " << tgt_hdg ); - if ( ! globals->get_runways()->search( id, (int)tgt_hdg, &r ) ) { - SG_LOG( SG_GENERAL, SG_ALERT, - "Failed to find a good runway for " << id << '\n' ); - return false; - } + const FGAirport* apt = fgFindAirportID(id); + if (!apt) return false; + FGRunway r = apt->findBestRunwayForHeading(tgt_hdg); fgSetString("/sim/atc/runway", r._rwy_no.c_str()); double lat2, lon2, az2; @@ -872,8 +870,6 @@ static bool fgSetPosFromAirportIDandParkpos( const string& id, const string& par // Set current_options lon/lat given an airport id and runway number static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy, bool rwy_req ) { - FGRunway r; - if ( id.empty() ) return false; @@ -882,12 +878,20 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy, bo "Attempting to set starting position for " << id << ":" << rwy ); - if ( ! globals->get_runways()->search( id, rwy, &r ) ) { - SG_LOG( SG_GENERAL, rwy_req ? SG_ALERT : SG_INFO, + const FGAirport* apt = fgFindAirportID(id); + if (!apt) { + SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find airport:" << id); + return false; + } + + if (!apt->hasRunwayWithIdent(rwy)) { + SG_LOG( SG_GENERAL, rwy_req ? SG_ALERT : SG_INFO, "Failed to find runway " << rwy << " at airport " << id << ". Using default runway." ); - return false; + return false; } + + FGRunway r(apt->getRunwayByIdent(rwy)); fgSetString("/sim/atc/runway", r._rwy_no.c_str()); double lat2, lon2, az2; @@ -1143,10 +1147,8 @@ fgInitNav () FGAirportList *airports = new FGAirportList(); globals->set_airports( airports ); - FGRunwayList *runways = new FGRunwayList(); - globals->set_runways( runways ); - fgAirportDBLoad( airports, runways, aptdb.str(), p_metar.str() ); + fgAirportDBLoad( airports, aptdb.str(), p_metar.str() ); FGNavList *navlist = new FGNavList; FGNavList *loclist = new FGNavList; @@ -1179,7 +1181,7 @@ fgInitNav () double threshold = fgGetDouble( "/sim/navdb/localizers/auto-align-threshold-deg", 5.0 ); - fgNavDBAlignLOCwithRunway( runways, loclist, threshold ); + fgNavDBAlignLOCwithRunway( airports, loclist, threshold ); } SG_LOG(SG_GENERAL, SG_INFO, " Fixes"); diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 30e3585fe..bf7ff48c4 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -81,7 +81,6 @@ FGGlobals::FGGlobals() : current_panel( NULL ), soundmgr( NULL ), airports( NULL ), - runways( NULL ), ATC_mgr( NULL ), AI_mgr( NULL ), controls( NULL ), @@ -135,7 +134,6 @@ FGGlobals::~FGGlobals() delete soundmgr; delete airports; - delete runways; delete ATC_mgr; delete AI_mgr; delete controls; diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 0c3de7f8a..efabd4e72 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -55,7 +55,6 @@ class SGSubsystemMgr; class SGSubsystem; class FGAirportList; -class FGRunwayList; class FGAIMgr; class FGATCMgr; class FGAircraftModel; @@ -142,9 +141,6 @@ private: // Simple Airport List FGAirportList *airports; - // Runway List - FGRunwayList *runways; - // ATC manager FGATCMgr *ATC_mgr; @@ -253,9 +249,6 @@ public: inline FGAirportList *get_airports() const { return airports; } inline void set_airports( FGAirportList *a ) {airports = a; } - inline FGRunwayList *get_runways() const { return runways; } - inline void set_runways( FGRunwayList *r ) {runways = r; } - inline FGATCMgr *get_ATC_mgr() const { return ATC_mgr; } inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; } diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 712eb1a5f..b38b3536a 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -32,6 +32,8 @@ # include #endif +#include + #include #include @@ -87,6 +89,8 @@ extern float init_volume; using namespace flightgear; +using std::cerr; + // This is a record containing a bit of global housekeeping information FGGeneral general; diff --git a/src/Main/options.cxx b/src/Main/options.cxx index c16f3c690..08910ba21 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -35,6 +35,7 @@ #include // strcmp() #include +#include #include #include @@ -63,6 +64,9 @@ using std::string; using std::sort; +using std::cout; +using std::cerr; +using std::endl; #ifndef VERSION #define VERSION "CVS "__DATE__ diff --git a/src/MultiPlayer/multiplaymgr.cxx b/src/MultiPlayer/multiplaymgr.cxx index b83559776..c92a992b5 100644 --- a/src/MultiPlayer/multiplaymgr.cxx +++ b/src/MultiPlayer/multiplaymgr.cxx @@ -31,6 +31,7 @@ #include #endif +#include #include #include @@ -43,6 +44,8 @@ #include "multiplaymgr.hxx" #include "mpmessages.hxx" +using std::cerr; + #define MAX_PACKET_SIZE 1200 #define MAX_TEXT_SIZE 128 diff --git a/src/Navaids/navdb.cxx b/src/Navaids/navdb.cxx index 089639f04..a8d2fbdd7 100644 --- a/src/Navaids/navdb.cxx +++ b/src/Navaids/navdb.cxx @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -268,7 +269,7 @@ static void update_loc_position( FGNavRecord *loc, FGRunway *rwy, // it then "moves" the localizer and updates it's heading so it // *perfectly* aligns with the runway, but is still the same distance // from the runway threshold. -void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist, +void fgNavDBAlignLOCwithRunway( FGAirportList *airports, FGNavList *loclist, double threshold ) { nav_map_type navmap = loclist->get_navaids(); @@ -277,18 +278,19 @@ void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist, nav_list_type locs = freq->second; nav_list_const_iterator loc = locs.begin(); while ( loc != locs.end() ) { - string name = (*loc)->get_name(); - string::size_type pos1 = name.find(" "); - string id = name.substr(0, pos1); - name = name.substr(pos1+1); - string::size_type pos2 = name.find(" "); - string rwy = name.substr(0, pos2); - - FGRunway r; - if ( runways->search(id, rwy, &r) ) { - update_loc_position( (*loc), &r, threshold ); - } - ++loc; + vector parts = simgear::strutils::split((*loc)->get_name()); + if (parts.size() < 2) { + SG_LOG(SG_GENERAL, SG_ALERT, "can't parse navaid " << (*loc)->get_ident() + << " name for airport/runway:" << (*loc)->get_name()); + continue; + } + + FGAirport* airport = airports->search(parts[0]); + if (!airport) continue; // not found + + FGRunway r = airport->getRunwayByIdent(parts[1]); + update_loc_position( (*loc), &r, threshold ); + ++loc; } ++freq; } diff --git a/src/Navaids/navdb.hxx b/src/Navaids/navdb.hxx index 825fa1e62..3c2321221 100644 --- a/src/Navaids/navdb.hxx +++ b/src/Navaids/navdb.hxx @@ -52,7 +52,7 @@ bool fgNavDBInit( FGAirportList *airports, // it then "moves" the localizer and updates it's heading so it // *perfectly* aligns with the runway, but is still the same distance // from the runway threshold. -void fgNavDBAlignLOCwithRunway( FGRunwayList *runways, FGNavList *loclist, +void fgNavDBAlignLOCwithRunway( FGAirportList *airport, FGNavList *loclist, double threshold ); #endif // _FG_NAVDB_HXX diff --git a/src/Scripting/NasalSys.cxx b/src/Scripting/NasalSys.cxx index 1177b2102..639801d0d 100644 --- a/src/Scripting/NasalSys.cxx +++ b/src/Scripting/NasalSys.cxx @@ -548,37 +548,32 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args) string id = apt->getId(); string name = apt->getName(); - + // set runway hash - FGRunwayList *rwylst = globals->get_runways(); - FGRunway rwy; naRef rwys = naNewHash(c); - if(rwylst->search(id, &rwy)) { - do { - if(rwy._id != id) break; - if(rwy._type[0] != 'r') continue; - - naRef rwyid = naStr_fromdata(naNewString(c), + for (unsigned int r=0; rnumRunways(); ++r) { + FGRunway rwy(apt->getRunwayByIndex(r)); + + naRef rwyid = naStr_fromdata(naNewString(c), const_cast(rwy._rwy_no.c_str()), rwy._rwy_no.length()); - naRef rwydata = naNewHash(c); + naRef rwydata = naNewHash(c); #define HASHSET(s,l,n) naHash_set(rwydata, naStr_fromdata(naNewString(c),s,l),n) - HASHSET("id", 2, rwyid); - HASHSET("lat", 3, naNum(rwy._lat)); - HASHSET("lon", 3, naNum(rwy._lon)); - HASHSET("heading", 7, naNum(rwy._heading)); - HASHSET("length", 6, naNum(rwy._length * SG_FEET_TO_METER)); - HASHSET("width", 5, naNum(rwy._width * SG_FEET_TO_METER)); - HASHSET("threshold1", 10, naNum(rwy._displ_thresh1 * SG_FEET_TO_METER)); - HASHSET("threshold2", 10, naNum(rwy._displ_thresh2 * SG_FEET_TO_METER)); - HASHSET("stopway1", 8, naNum(rwy._stopway1 * SG_FEET_TO_METER)); - HASHSET("stopway2", 8, naNum(rwy._stopway2 * SG_FEET_TO_METER)); + HASHSET("id", 2, rwyid); + HASHSET("lat", 3, naNum(rwy._lat)); + HASHSET("lon", 3, naNum(rwy._lon)); + HASHSET("heading", 7, naNum(rwy._heading)); + HASHSET("length", 6, naNum(rwy._length * SG_FEET_TO_METER)); + HASHSET("width", 5, naNum(rwy._width * SG_FEET_TO_METER)); + HASHSET("threshold1", 10, naNum(rwy._displ_thresh1 * SG_FEET_TO_METER)); + HASHSET("threshold2", 10, naNum(rwy._displ_thresh2 * SG_FEET_TO_METER)); + HASHSET("stopway1", 8, naNum(rwy._stopway1 * SG_FEET_TO_METER)); + HASHSET("stopway2", 8, naNum(rwy._stopway2 * SG_FEET_TO_METER)); #undef HASHSET - naHash_set(rwys, rwyid, rwydata); - } while(rwylst->next(&rwy)); + naHash_set(rwys, rwyid, rwydata); } - + // set airport hash naRef aptdata = naNewHash(c); #define HASHSET(s,l,n) naHash_set(aptdata, naStr_fromdata(naNewString(c),s,l),n) -- 2.39.5