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:
parent
90f498be4d
commit
301054204e
43 changed files with 682 additions and 784 deletions
|
@ -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>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <Traffic/SchedFlight.hxx>
|
||||
#include <Traffic/Schedule.hxx>
|
||||
#include <ATC/trafficcontrol.hxx>
|
||||
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
using std::vector;
|
||||
using std::string;
|
||||
|
||||
class FGTaxiRoute;
|
||||
|
||||
class FGAIFlightPlan {
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
//#include <Main/fg_props.hxx>
|
||||
//#include <Airports/runways.hxx>
|
||||
|
||||
#include <Airports/dynamics.hxx>
|
||||
|
||||
#include <AIModel/AIFlightPlan.hxx>
|
||||
|
||||
//#include <string>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include <stdio.h> // sprintf
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <osg/CullFace>
|
||||
#include <osg/Depth>
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#endif
|
||||
|
||||
#include "kln89_page_fpl.hxx"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue