1
0
Fork 0

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.
This commit is contained in:
durk 2008-08-14 18:13:39 +00:00
parent 90f498be4d
commit 301054204e
43 changed files with 682 additions and 784 deletions

View file

@ -29,6 +29,7 @@
#include <Main/viewer.hxx>
#include <Scenery/scenery.hxx>
#include <Scenery/tilemgr.hxx>
#include <Airports/dynamics.hxx>
#include <string>
#include <math.h>

View file

@ -26,6 +26,7 @@
#include <Traffic/SchedFlight.hxx>
#include <Traffic/Schedule.hxx>
#include <ATC/trafficcontrol.hxx>
#include <string>
using std::string;

View file

@ -20,6 +20,8 @@
# include <config.h>
#endif
#include <iostream>
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx>
@ -34,13 +36,15 @@
#include <Main/fg_init.hxx>
#include <Airports/simple.hxx>
#include <Airports/runways.hxx>
#include <Airports/groundnetwork.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
#include "AIFlightPlan.hxx"
using std::cerr;
FGAIFlightPlan::FGAIFlightPlan(const string& filename)
{

View file

@ -32,6 +32,7 @@
using std::vector;
using std::string;
class FGTaxiRoute;
class FGAIFlightPlan {

View file

@ -20,6 +20,7 @@
#include "AIFlightPlan.hxx"
#include <simgear/math/sg_geodesy.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
@ -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; }

View file

@ -27,6 +27,7 @@
#include <Navaids/awynet.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>
@ -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; }

View file

@ -20,6 +20,7 @@
#include "AIFlightPlan.hxx"
#include <simgear/math/sg_geodesy.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <Environment/environment_mgr.hxx>
#include <Environment/environment.hxx>

View file

@ -28,7 +28,8 @@
#include <AIModel/AIAircraft.hxx>
#include <AIModel/AIFlightPlan.hxx>
#include <Traffic/TrafficMgr.hxx>
#include <Airports/groundnetwork.hxx>
#include <Airports/dynamics.hxx>
/***************************************************************************
* FGTrafficRecord

View file

@ -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!!");
}
}

View file

@ -23,6 +23,8 @@
# include <config.h>
#endif
#include <iostream>
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <simgear/misc/sg_path.hxx>

View file

@ -30,6 +30,8 @@
#include "ATCDialog.hxx"
#include <Airports/runways.hxx>
#include <Airports/simple.hxx>
#include <simgear/constants.h>
#include <simgear/math/polar3d.hxx>
#include <simgear/misc/sg_path.hxx>
@ -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 <<endl;
}
else cout << "FGRunways search failed\n";
const FGAirport* apt = fgFindAirportID(ident);
assert(apt);
FGRunway runway = apt->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;
}
// ========================================================================

View file

@ -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;

View file

@ -22,6 +22,8 @@
# include <config.h>
#endif
#include <iostream>
#include <simgear/misc/sg_path.hxx>
#include <simgear/math/sg_random.h>
#include <simgear/debug/logstream.hxx>
@ -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.

View file

@ -31,6 +31,7 @@
#include <sstream>
#include <iomanip>
#include <iostream>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
@ -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; i<apt->numRunways(); ++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; i<apt->numTaxiways(); ++i) {
if (OnRunway(pt, apt->getTaxiwayByIndex(i))) {
return true;
}
}
return false;
}

View file

@ -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<FGRunway> 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 ) {

View file

@ -25,26 +25,17 @@
#ifndef _FG_APT_LOADER_HXX
#define _FG_APT_LOADER_HXX
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/compiler.h>
#include <string>
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

View file

@ -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) {

View file

@ -41,6 +41,8 @@
//#include <Main/fg_props.hxx>
//#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <AIModel/AIFlightPlan.hxx>
//#include <string>

View file

@ -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: " <<rwy._heading << endl;
//cerr << "Wind Speed : " << windSpeed << endl;
@ -263,12 +258,9 @@ void RunwayGroup::setActive(const string &aptId,
{
//cerr << ". [Valid] ";
}
}else {
SG_LOG( SG_GENERAL, SG_INFO, "Failed to find runway " << name << " at " << aptId );
exit(1);
}
//cerr << endl;
}
//cerr << endl;
} // of active runways iteration
if (validSelection)
{
//cerr << "Valid selection : " << i << endl;;
@ -311,13 +303,9 @@ void RunwayGroup::setActive(const string &aptId,
bool validSelection = true;
for (int j = 0; j < 2; j++)
{
//cerr << "I J " << i << " " << j << endl;
name = rwyList[choice[j]].getRwyList(i);
//cerr << "Name of Runway: " << name << endl;
if (globals->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)

View file

@ -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);

View file

@ -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<const string, FGRunway>(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;
}
// Return reverse rwy number
// eg 01 -> 19
// 03L -> 21R
static string GetReverseRunwayNo(string& rwyno) {
// cout << "Original rwyno = " << rwyNo << '\n';
// 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;
} else {
return false;
}
}
// search for the specified apt id and runway no
bool FGRunwayList::search( const string& aptid, const string& rwyno,
FGRunway *r )
string FGRunway::reverseIdent(const string& aRunwayIdent)
{
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;
}
}
// Helipads don't have a seperate number per end
if (aRunwayIdent.size() && (aRunwayIdent[0] == 'H' || aRunwayIdent[0] == 'h' || aRunwayIdent[0] == 'x')) {
return aRunwayIdent;
}
return false;
}
// (wierd!)
FGRunway FGRunwayList::search( const string& aptid ) {
FGRunway a;
search( aptid, &a );
return a;
}
// Return the runway closest to a given heading
bool FGRunwayList::search( const string& aptid, const int tgt_hdg,
FGRunway *runway )
{
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;
std::string ident(aRunwayIdent);
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;
}
FGRunway FGRunwayList::next() {
FGRunway result;
++current;
if ( current != runways.end() ) {
result = current->second;
}
return result;
double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt) const
{
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;
}
// Destructor
FGRunwayList::~FGRunwayList( void ) {
bool FGRunway::isTaxiway() const
{
return (_rwy_no[0] == 'x');
}

View file

@ -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 <config.h>
#endif
#include <simgear/compiler.h>
#include <string>
#include <map>
#include <vector>
using std::string;
using std::multimap;
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;
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
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<FGRunway> FGRunwayVector;
#endif // _FG_RUNWAYS_HXX

View file

@ -46,6 +46,7 @@
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <string>
@ -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;
}

View file

@ -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 <config.h>
#endif
#include <simgear/math/point3d.hxx>
#include <simgear/compiler.h>
@ -45,29 +36,20 @@
#include <set>
#include <vector>
#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<FGRunway> mRunways;
std::vector<FGRunway> 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

View file

@ -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)));

View file

@ -33,6 +33,7 @@
#include <stdio.h> // sprintf
#include <string.h>
#include <iostream>
#include <osg/CullFace>
#include <osg/Depth>

View file

@ -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
{

View file

@ -25,6 +25,7 @@
#include <simgear/compiler.h>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/math/SGMath.hxx>
#ifdef SG_HAVE_STD_INCLUDES
# include <cmath>
@ -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;

View file

@ -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)));

View file

@ -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; r<apt->numRunways(); ++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;

View file

@ -26,7 +26,9 @@
#endif
#include "kln89_page_fpl.hxx"
#include <algorithm>
#include <iostream>
using namespace std;

View file

@ -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<osg::Vec3Array> rwy_vertices = new osg::Vec3Array;
osg::ref_ptr<osg::Vec3Array> 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; i<apt->numRunways(); ++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; i<apt->numTaxiways(); ++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);

View file

@ -25,6 +25,9 @@
#include <simgear/props/props.hxx>
#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<osg::Geometry> _geom;
SGPropertyNode_ptr _airport_node;
SGPropertyNode_ptr _range_node;

View file

@ -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; r<airport->numRunways(); ++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);
double min_diff = 360;
do
{
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;
}
}
}
while (globals->get_runways()->next(&r) && r._id == airport->getId());
*/
double min_diff = 360;
for (unsigned int r=0; r<airport->numRunways(); ++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)
{
min_diff = diff;
*_runway = rwy;
}
} // 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; r<airport->numRunways(); ++r) {
if (airport->getRunwayByIndex(r)._length >= mk->conf.runway_database) {
return true;
}
}
return false;
}

View file

@ -67,6 +67,8 @@
#include <Airports/apt_loader.hxx>
#include <Airports/runways.hxx>
#include <Airports/simple.hxx>
#include <Airports/dynamics.hxx>
#include <AIModel/AIManager.hxx>
#include <ATCDCL/ATCmgr.hxx>
#include <ATCDCL/AIMgr.hxx>
@ -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");

View file

@ -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;

View file

@ -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; }

View file

@ -32,6 +32,8 @@
# include <signal.h>
#endif
#include <iostream>
#include <plib/netSocket.h>
#include <osg/Camera>
@ -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;

View file

@ -35,6 +35,7 @@
#include <string.h> // strcmp()
#include <algorithm>
#include <iostream>
#include <string>
#include <plib/ul.h>
@ -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__

View file

@ -31,6 +31,7 @@
#include <config.h>
#endif
#include <iostream>
#include <plib/netSocket.h>
#include <simgear/misc/stdint.hxx>
@ -43,6 +44,8 @@
#include "multiplaymgr.hxx"
#include "mpmessages.hxx"
using std::cerr;
#define MAX_PACKET_SIZE 1200
#define MAX_TEXT_SIZE 128

View file

@ -30,6 +30,7 @@
#include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/strutils.hxx>
#include <Airports/runways.hxx>
#include <Airports/simple.hxx>
@ -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<string> 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;
}

View file

@ -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

View file

@ -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; r<apt->numRunways(); ++r) {
FGRunway rwy(apt->getRunwayByIndex(r));
naRef rwyid = naStr_fromdata(naNewString(c),
const_cast<char *>(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)