1
0
Fork 0

James Turner:

Convert FGRunway to be heap-based, and inherit FGPositioned. This is a large, ugly change, since FGRunway was essentially a plain struct, with no accessors or abstraction. This change adds various helpers and accessors to FGRunway, but doesn't change many places to use them - that will be a follow up series of patches. It's still a large patch, but outside of FGAirport and FGRunway, mostly mechanical search-and-replace.

An interesting part of this change is that reciprocal runways now exist as independent objects, rather than being created on the fly by the search methods. This simplifies some pieces of code that search for and iterate runways. For users who only want one 'end' of a runway, the new 'isReciprocal' predicate allows them to ignore the 'other' end. Current the only user of this is the 'ground-radar' ATC feature. If we had data on which runways are truly 'single-ended', it would now be trivial to use this in the airport loader to *not* create the reciprocal.
This commit is contained in:
ehofman 2008-09-11 08:38:09 +00:00
parent 3b486e1aee
commit aa78341698
30 changed files with 388 additions and 331 deletions

View file

@ -24,7 +24,6 @@
#include <string>
#include <Airports/simple.hxx>
#include <Airports/runways.hxx>
#include <Navaids/awynet.hxx>
#include "AIBase.hxx"
@ -33,6 +32,7 @@ using std::vector;
using std::string;
class FGTaxiRoute;
class FGRunway;
class FGAIFlightPlan {
@ -93,7 +93,8 @@ public:
void setTime(time_t st) { start_time = st; }
int getGate() const { return gateId; }
double getLeadInAngle() const { return leadInAngle; }
const string& getRunway() const { return rwy._rwy_no; }
const string& getRunway() const;
void setRepeat(bool r) { repeat = r; }
bool getRepeat(void) const { return repeat; }
void restart(void);
@ -105,7 +106,7 @@ public:
bool isActive(time_t time) {return time >= this->getStartTime();}
private:
FGRunway rwy;
FGRunway* rwy;
typedef vector <waypoint*> wpt_vector_type;
typedef wpt_vector_type::const_iterator wpt_vector_iterator;

View file

@ -141,11 +141,11 @@ void FGAIFlightPlan::createTaxi(bool firstFlight, int direction,
rwy = apt->getRunwayByIdent(activeRunway);
// Determine the beginning of he runway
heading = rwy._heading;
heading = rwy->headingDeg();
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length * SG_FEET_TO_METER * 0.5 - 5.0,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
rwy->lengthM() * 0.5 - 5.0,
&lat2, &lon2, &az2 );
if (apt->getDynamics()->getGroundNetwork()->exists())
@ -499,11 +499,11 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
rwy = apt->getRunwayByIdent(activeRunway);
}
// Acceleration point, 105 meters into the runway,
heading = rwy._heading;
heading = rwy->headingDeg();
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length * SG_FEET_TO_METER * 0.5 - 105.0,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
rwy->lengthM() * 0.5 - 105.0,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "accel";
@ -532,8 +532,8 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
wpt = new waypoint;
wpt->name = "SOC";
wpt->latitude = rwy._lat;
wpt->longitude = rwy._lon;
wpt->latitude = rwy->latitude();
wpt->longitude = rwy->longitude();
wpt->altitude = apt->getElevation()+1000;
wpt->speed = speed;
wpt->crossat = -10000;
@ -545,8 +545,8 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
rwy._length * SG_FEET_TO_METER,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading,
rwy->lengthM(),
&lat2, &lon2, &az2 );
wpt = new waypoint;
@ -567,7 +567,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
// Tower control until they have reached the 3000 ft climb point
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading,
5000,
&lat2, &lon2, &az2 );
@ -586,7 +586,7 @@ void FGAIFlightPlan::createTakeOff(bool firstFlight, FGAirport *apt, double spee
wpt->routeIndex = 0;
waypoints.push_back(wpt);
// geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
// geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading,
// 100000,
// &lat2, &lon2, &az2 );
// wpt = new waypoint;
@ -626,11 +626,11 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
}
heading = rwy._heading;
heading = rwy->headingDeg();
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
//cerr << "Creating climb at : " << rwy._id << " " << rwy._rwy_no << endl;
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading,
10*SG_NM_TO_METER,
&lat2, &lon2, &az2 );
wpt = new waypoint;
@ -648,7 +648,7 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading,
20*SG_NM_TO_METER,
&lat2, &lon2, &az2 );
wpt = new waypoint;
@ -709,12 +709,12 @@ void FGAIFlightPlan::createClimb(bool firstFlight, FGAirport *apt, double speed,
// " at airport " << arr->getId());
// exit(1);
// }
// heading = rwy._heading;
// heading = rwy->headingDeg();
// azimuth = heading + 180.0;
// while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
// geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
// geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
// 110000,
// &lat2, &lon2, &az2 );
// wpt = new waypoint;
@ -753,10 +753,10 @@ void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
apt->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
rwy = apt->getRunwayByIdent(activeRunway);
heading = rwy._heading;
heading = rwy->headingDeg();
azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
100000,
&lat2, &lon2, &az2 );
@ -775,7 +775,7 @@ void FGAIFlightPlan::createDecent(FGAirport *apt, const string &fltType)
waypoints.push_back(wpt);
// Three thousand ft. Slowing down to 160 kts
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
8*SG_NM_TO_METER,
&lat2, &lon2, &az2 );
wpt = new waypoint;
@ -807,13 +807,13 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
waypoint *wpt;
heading = rwy._heading;
heading = rwy->headingDeg();
azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
//Runway Threshold
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length*0.45 * SG_FEET_TO_METER,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
rwy->lengthM() *0.45,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");
@ -830,13 +830,13 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
waypoints.push_back(wpt);
//Full stop at the runway centerpoint
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
rwy._length*0.45,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
rwy->lengthFt() *0.45,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "Center"; //wpt_node->getStringValue("name", "END");
wpt->latitude = rwy._lat;
wpt->longitude = rwy._lon;
wpt->latitude = rwy->latitude();
wpt->longitude = rwy->longitude();
wpt->altitude = apt->getElevation();
wpt->speed = 30;
wpt->crossat = -10000;
@ -847,8 +847,8 @@ void FGAIFlightPlan::createLanding(FGAirport *apt)
wpt->routeIndex = 0;
waypoints.push_back(wpt);
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, heading,
rwy._length*0.45 * SG_FEET_TO_METER,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), heading,
rwy->lengthM() *0.45,
&lat2, &lon2, &az2 );
wpt = new waypoint;
wpt->name = "Threshold"; //wpt_node->getStringValue("name", "END");

View file

@ -271,7 +271,7 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
// {
// cerr << "Creating cruise to EHAM " << latitude << " " << longitude << endl;
// }
heading = rwy._heading;
heading = rwy->headingDeg();
azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
@ -337,12 +337,12 @@ void FGAIFlightPlan::createCruise(bool firstFlight, FGAirport *dep,
arr->getDynamics()->getActiveRunway(rwyClass, 2, activeRunway);
rwy = arr->getRunwayByIdent(activeRunway);
heading = rwy._heading;
heading = rwy->headingDeg();
azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
geo_direct_wgs_84 ( 0, rwy._lat, rwy._lon, azimuth,
geo_direct_wgs_84 ( 0, rwy->latitude(), rwy->longitude(), azimuth,
110000,
&lat2, &lon2, &az2 );
wpt = new waypoint;

View file

@ -167,9 +167,9 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) {
const FGAirport* apt = fgFindAirportID(id);
assert(apt);
FGRunway runway(apt->getActiveRunwayForUsage());
FGRunway* runway(apt->getActiveRunwayForUsage());
double hdg = runway._heading;
double hdg = runway->headingDeg();
double other_way = hdg - 180.0;
while(other_way <= 0.0) {
other_way += 360.0;
@ -177,12 +177,12 @@ void FGAILocalTraffic::GetRwyDetails(const string& id) {
// 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 origin = Point3D(runway->longitude(), runway->latitude(), 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;
rwy.length = runway->lengthM();
rwy.width = runway->widthM();
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(), hdg,

View file

@ -293,10 +293,10 @@ double GetAngleDiff_deg( const double &a1, const double &a2) {
// Runway stuff
// Given a Point3D (lon/lat/elev) and an FGRunway struct, determine if the point lies on the runway
bool OnRunway(const Point3D& pt, const FGRunway& rwy) {
bool OnRunway(const Point3D& pt, const FGRunway* rwy) {
FGATCAlignedProjection ortho;
Point3D centre(rwy._lon, rwy._lat, 0.0); // We don't need the elev
ortho.Init(centre, rwy._heading);
Point3D centre(rwy->longitude(), rwy->latitude(), 0.0); // We don't need the elev
ortho.Init(centre, rwy->headingDeg());
Point3D xyc = ortho.ConvertToLocal(centre);
Point3D xyp = ortho.ConvertToLocal(pt);
@ -304,8 +304,8 @@ bool OnRunway(const Point3D& pt, const FGRunway& rwy) {
//cout << "Length offset = " << fabs(xyp.y() - xyc.y()) << '\n';
//cout << "Width offset = " << fabs(xyp.x() - xyc.x()) << '\n';
if((fabs(xyp.y() - xyc.y()) < ((rwy._length/2.0) + 5.0))
&& (fabs(xyp.x() - xyc.x()) < (rwy._width/2.0))) {
if((fabs(xyp.y() - xyc.y()) < ((rwy->lengthFt()/2.0) + 5.0))
&& (fabs(xyp.x() - xyc.x()) < (rwy->widthFt()/2.0))) {
return(true);
}

View file

@ -99,5 +99,5 @@ double GetAngleDiff_deg( const double &a1, const double &a2);
****************/
// Given a Point3D (lon/lat/elev) and an FGRunway struct, determine if the point lies on the runway
bool OnRunway(const Point3D& pt, const FGRunway& rwy);
bool OnRunway(const Point3D& pt, const FGRunway* rwy);

View file

@ -563,13 +563,13 @@ void FGApproach::get_active_runway() {
const FGAirport* apt = fgFindAirportID(ident);
assert(apt);
FGRunway runway = apt->getActiveRunwayForUsage();
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;
active_runway = runway->ident();
active_rw_hdg = runway->headingDeg();
active_rw_lon = runway->longitude();
active_rw_lat = runway->latitude();
active_rw_len = runway->lengthFt();
}
// ========================================================================

View file

@ -212,7 +212,7 @@ void FGATIS::UpdateTransmission() {
const FGAirport* apt = fgFindAirportID(ident);
assert(apt);
string rwy_no = apt->getActiveRunwayForUsage()._rwy_no;
string rwy_no = apt->getActiveRunwayForUsage()->ident();
if(rwy_no != "NN") {
transmission += " / Landing_and_departing_runway ";
transmission += ConvertRwyNumToSpokenString(atoi(rwy_no.c_str()));

View file

@ -363,27 +363,27 @@ void FGGround::DoRwyDetails() {
const FGAirport* apt = fgFindAirportID(ident);
assert(apt);
FGRunway runway = apt->getActiveRunwayForUsage();
FGRunway* runway = apt->getActiveRunwayForUsage();
activeRwy = runway._rwy_no;
rwy.rwyID = runway._rwy_no;
activeRwy = runway->ident();
rwy.rwyID = runway->ident();
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;
double other_way = runway->headingDeg() - 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 origin = Point3D(runway->longitude(), runway->latitude(), aptElev);
Point3D ref = origin;
double tshlon, tshlat, tshr;
double tolon, tolat, tor;
rwy.length = runway._length * SG_FEET_TO_METER;
rwy.length = runway->lengthM();
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,
geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), runway->headingDeg(),
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
@ -391,7 +391,7 @@ void FGGround::DoRwyDetails() {
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;
rwy.hdg = runway->headingDeg();
// 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

View file

@ -1513,38 +1513,36 @@ void FGTower::DoRwyDetails() {
const FGAirport* apt = fgFindAirportID(ident);
assert(apt);
FGRunway runway = apt->getActiveRunwayForUsage();
//cout << "RUNWAY GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOD\n";
FGRunway* runway = apt->getActiveRunwayForUsage();
activeRwy = runway._rwy_no;
rwy.rwyID = runway._rwy_no;
SG_LOG(SG_ATC, SG_INFO, "Active runway for airport " << ident << " is " << activeRwy);
activeRwy = runway->ident();
rwy.rwyID = runway->ident();
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;
double other_way = runway->headingDeg() - 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 origin = Point3D(runway->longitude(), runway->latitude(), 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;
rwy.length = runway->lengthM();
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,
geo_direct_wgs_84 ( aptElev, ref.lat(), ref.lon(), runway->headingDeg(),
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;
rwy.hdg = runway->headingDeg();
// 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

View file

@ -100,7 +100,7 @@ bool fgAirportDBLoad( FGAirportList *airports,
string line;
char tmp[2049];
tmp[2048] = 0;
vector<FGRunway> runways;
vector<FGRunwayPtr> runways;
unsigned int line_id = 0;
unsigned int line_num = 0;
@ -212,10 +212,15 @@ bool fgAirportDBLoad( FGAirportList *airports,
int surface_code = atoi( token[10].c_str() );
FGRunway rwy(rwy_no, lon, lat, heading, length,
width, displ_thresh1, displ_thresh2,
stopway1, stopway2, surface_code);
FGRunway* rwy = new FGRunway(NULL, rwy_no, lon, lat, heading, length,
width, displ_thresh1, stopway1, surface_code, false);
FGRunway* reciprocal = new FGRunway(NULL, FGRunway::reverseIdent(rwy_no),
lon, lat, heading + 180.0, length, width,
displ_thresh2, stopway2, surface_code, true);
runways.push_back(rwy);
runways.push_back(reciprocal);
} else if ( line_id == 18 ) {
// beacon entry (ignore)
} else if ( line_id == 14 ) {

View file

@ -485,8 +485,8 @@ void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, s
string FGAirportDynamics::chooseRunwayFallback()
{
FGRunway rwy = _ap->getActiveRunwayForUsage();
return rwy._rwy_no;
FGRunway* rwy = _ap->getActiveRunwayForUsage();
return rwy->ident();
}
void FGAirportDynamics::addParking(FGParking& park) {

View file

@ -202,7 +202,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
stringVec *currentlyActive)
{
FGRunway rwy;
FGRunway* rwy;
int activeRwys = rwyList.size(); // get the number of runways active
int nrOfPreferences;
// bool found = true;
@ -238,7 +238,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
rwy = airport->getRunwayByIdent(rwyList[j].getRwyList(i));
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy._heading);
hdgDiff = fabs(windHeading - rwy->headingDeg());
//cerr << "Wind Heading: " << windHeading << "Runway Heading: " <<rwy._heading << endl;
//cerr << "Wind Speed : " << windSpeed << endl;
if (hdgDiff > 180)
@ -307,7 +307,7 @@ void RunwayGroup::setActive(const FGAirport* airport,
rwy = airport->getRunwayByIdent(name);
//cerr << "Succes" << endl;
hdgDiff = fabs(windHeading - rwy._heading);
hdgDiff = fabs(windHeading - rwy->headingDeg());
if (hdgDiff > 180)
hdgDiff = 360 - hdgDiff;
hdgDiff *= ((2*M_PI)/360.0); // convert to radians

View file

@ -42,43 +42,55 @@ using std::istream;
using std::multimap;
using std::string;
FGRunway::FGRunway()
static FGPositioned::Type runwayTypeFromNumber(const std::string& aRwyNo)
{
return (aRwyNo[0] == 'x') ? FGPositioned::TAXIWAY : FGPositioned::RUNWAY;
}
FGRunway::FGRunway(const string& rwy_no,
static std::string cleanRunwayNo(const std::string& aRwyNo)
{
if (aRwyNo[0] == 'x') {
return std::string(); // no ident for taxiways
}
string result(aRwyNo);
// canonicalise runway ident
if ((aRwyNo.size() == 1) || !isdigit(aRwyNo[1])) {
result = "0" + aRwyNo;
}
// trim off trailing garbage
if (result.size() > 2) {
char suffix = toupper(result[2]);
if (suffix == 'X') {
result = result.substr(0, 2);
}
}
return result;
}
FGRunway::FGRunway(FGAirport* aAirport, 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 int surface_code)
const double displ_thresh,
const double stopway,
const int surface_code,
bool reciprocal) :
FGPositioned(runwayTypeFromNumber(rwy_no), cleanRunwayNo(rwy_no), latitude, longitude, 0.0),
_airport(aAirport),
_reciprocal(reciprocal)
{
_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;
}
if ((_rwy_no.size() > 2) && (_rwy_no[2] == 'x')) {
_rwy_no = _rwy_no.substr(0, 2);
}
}
_rwy_no = ident();
_lon = longitude;
_lat = latitude;
_heading = heading;
_length = length;
_width = width;
_displ_thresh1 = displ_thresh1;
_displ_thresh2 = displ_thresh2;
_stopway1 = stopway1;
_stopway2 = stopway2;
_displ_thresh = displ_thresh;
_stopway = stopway;
_surface_code = surface_code;
}
@ -101,22 +113,17 @@ string FGRunway::reverseIdent(const string& aRunwayIdent)
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';
char suffix = toupper(ident[2]);
if(suffix == 'L') {
buf[2] = 'R';
} else if (suffix == 'R') {
buf[2] = 'L';
} else {
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code "
<< aRunwayIdent << " passed to FGRunway::reverseIdent");
// something else, just copy
buf[2] = suffix;
}
buf[3] = 0;
}
return buf;
@ -135,5 +142,32 @@ double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt) con
bool FGRunway::isTaxiway() const
{
return (_rwy_no[0] == 'x');
return (type() == TAXIWAY);
}
SGGeod FGRunway::threshold() const
{
return pointOnCenterline(0.0);
}
SGGeod FGRunway::reverseThreshold() const
{
return pointOnCenterline(lengthM());
}
SGGeod FGRunway::displacedThreshold() const
{
return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER);
}
SGGeod FGRunway::pointOnCenterline(double aOffset) const
{
SGGeod result;
double dummyAz2;
double halfLengthMetres = lengthM() * 0.5;
SGGeodesy::direct(mPosition, _heading,
aOffset - halfLengthMetres,
result, dummyAz2);
return result;
}

View file

@ -26,52 +26,121 @@
#include <simgear/compiler.h>
#include <string>
#include <vector>
#include <simgear/math/sg_geodesy.hxx>
class FGRunway
{
#include "Navaids/positioned.hxx"
#include <string>
// forward decls
class FGAirport;
class FGRunway : public FGPositioned
{
FGAirport* _airport; ///< owning airport
bool _reciprocal;
public:
FGRunway();
FGRunway(const std::string& rwy_no,
FGRunway(FGAirport* aAirport, 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 int surface_code);
const double displ_thresh,
const double stopway,
const int surface_code,
const bool reciprocal);
/**
* given a runway identifier (06, 18L, 31R) compute the identifier for the
* opposite heading runway (24, 36R, 13L) string.
* reciprocal 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;
/**
* Test if this runway is the reciprocal. This allows users who iterate
* over runways to avoid counting runways twice, if desired.
*/
bool isReciprocal() const
{ return _reciprocal; }
/**
* Test if this is a taxiway or not
*/
bool isTaxiway() const;
/**
* Get the runway threshold point - this is syntatic sugar, equivalent to
* calling pointOnCenterline(0.0);
*/
SGGeod threshold() const;
/**
* Get the (possibly displaced) threshold point.
*/
SGGeod displacedThreshold() const;
/**
* Get the opposite threshold - this is equivalent to calling
* pointOnCenterline(lengthFt());
*/
SGGeod reverseThreshold() const;
/**
* Retrieve a position on the extended runway centerline. Positive values
* are in the direction of the runway heading, negative values are in the
* opposited direction. 0.0 corresponds to the (non-displaced) threshold
*/
SGGeod pointOnCenterline(double aOffset) const;
/**
* Runway length in ft
*/
double lengthFt() const
{ return _length; }
double lengthM() const
{ return _length * SG_FEET_TO_METER; }
double widthFt() const
{ return _width; }
double widthM() const
{ return _width * SG_FEET_TO_METER; }
/**
* Runway heading in degrees.
*/
double headingDeg() const
{ return _heading; }
/**
* Airport this runway is located at
*/
FGAirport* airport() const
{ return _airport; }
// FIXME - should die once airport / runway creation is cleaned up
void setAirport(FGAirport* aAirport)
{ _airport = aAirport; }
std::string _rwy_no;
std::string _type; // runway / taxiway
double _lon;
double _lat;
double _displ_thresh;
double _stopway;
double _heading;
double _length;
double _width;
double _displ_thresh1;
double _displ_thresh2;
double _stopway1;
double _stopway2;
int _surface_code;
};
typedef std::vector<FGRunway> FGRunwayVector;
#endif // _FG_RUNWAYS_HXX

View file

@ -47,6 +47,7 @@
#include <Main/fg_props.hxx>
#include <Airports/runways.hxx>
#include <Airports/dynamics.hxx>
#include <Airports/runways.hxx>
#include <string>
@ -109,7 +110,7 @@ unsigned int FGAirport::numRunways() const
return mRunways.size();
}
FGRunway FGAirport::getRunwayByIndex(unsigned int aIndex) const
FGRunway* FGAirport::getRunwayByIndex(unsigned int aIndex) const
{
assert(aIndex >= 0 && aIndex < mRunways.size());
return mRunways[aIndex];
@ -117,48 +118,31 @@ FGRunway FGAirport::getRunwayByIndex(unsigned int aIndex) const
bool FGAirport::hasRunwayWithIdent(const string& aIdent) const
{
bool dummy;
return (getIteratorForRunwayIdent(aIdent, dummy) != mRunways.end());
return (getIteratorForRunwayIdent(aIdent) != mRunways.end());
}
FGRunway FGAirport::getRunwayByIdent(const string& aIdent) const
FGRunway* FGAirport::getRunwayByIdent(const string& aIdent) const
{
bool reversed;
FGRunwayVector::const_iterator it = getIteratorForRunwayIdent(aIdent, reversed);
Runway_iterator it = getIteratorForRunwayIdent(aIdent);
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;
return *it;
}
FGRunwayVector::const_iterator
FGAirport::getIteratorForRunwayIdent(const string& aIdent, bool& aReversed) const
FGAirport::Runway_iterator
FGAirport::getIteratorForRunwayIdent(const string& aIdent) 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();
Runway_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;
if ((*it)->ident() == ident) {
return it;
}
}
@ -179,10 +163,10 @@ static double normaliseBearing(double aBearing)
return aBearing;
}
FGRunway FGAirport::findBestRunwayForHeading(double aHeading) const
FGRunway* FGAirport::findBestRunwayForHeading(double aHeading) const
{
FGRunwayVector::const_iterator it = mRunways.begin();
FGRunway result;
Runway_iterator it = mRunways.begin();
FGRunway* result = NULL;
double currentBestQuality = 0.0;
SGPropertyNode *param = fgGetNode("/sim/airport/runways/search", true);
@ -192,10 +176,9 @@ FGRunway FGAirport::findBestRunwayForHeading(double aHeading) const
double deviationWeight = param->getDoubleValue("deviation-weight", 1);
for (; it != mRunways.end(); ++it) {
double good = it->score(lengthWeight, widthWeight, surfaceWeight);
double good = (*it)->score(lengthWeight, widthWeight, surfaceWeight);
// first side
double dev = normaliseBearing(aHeading - it->_heading);
double dev = normaliseBearing(aHeading - (*it)->headingDeg());
double bad = fabs(deviationWeight * dev) + 1e-20;
double quality = good / bad;
@ -203,17 +186,6 @@ FGRunway FGAirport::findBestRunwayForHeading(double aHeading) const
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;
@ -224,22 +196,24 @@ unsigned int FGAirport::numTaxiways() const
return mTaxiways.size();
}
FGRunway FGAirport::getTaxiwayByIndex(unsigned int aIndex) const
FGRunway* FGAirport::getTaxiwayByIndex(unsigned int aIndex) const
{
assert(aIndex >= 0 && aIndex < mTaxiways.size());
return mTaxiways[aIndex];
}
void FGAirport::addRunway(const FGRunway& aRunway)
void FGAirport::addRunway(FGRunway* aRunway)
{
if (aRunway.isTaxiway()) {
aRunway->setAirport(this);
if (aRunway->isTaxiway()) {
mTaxiways.push_back(aRunway);
} else {
mRunways.push_back(aRunway);
}
}
FGRunway FGAirport::getActiveRunwayForUsage() const
FGRunway* FGAirport::getActiveRunwayForUsage() const
{
static FGEnvironmentMgr* envMgr = NULL;
if (!envMgr) {

View file

@ -27,8 +27,6 @@
#ifndef _FG_SIMPLE_HXX
#define _FG_SIMPLE_HXX
#include <simgear/math/point3d.hxx>
#include <simgear/compiler.h>
#include <string>
@ -36,10 +34,15 @@
#include <set>
#include <vector>
#include "Airports/runways.hxx"
#include <simgear/math/point3d.hxx>
#include "Navaids/positioned.hxx"
// forward decls
class FGAirportDynamics;
class FGRunway;
typedef SGSharedPtr<FGRunway> FGRunwayPtr;
/***************************************************************************************
*
@ -81,32 +84,34 @@ public:
void setId(const std::string& id) { _id = id; }
void setMetar(bool value) { _has_metar = value; }
FGRunway getActiveRunwayForUsage() const;
FGRunway* getActiveRunwayForUsage() const;
FGAirportDynamics *getDynamics();
unsigned int numRunways() const;
FGRunway getRunwayByIndex(unsigned int aIndex) 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;
FGRunway* getRunwayByIdent(const std::string& aIdent) const;
FGRunway* findBestRunwayForHeading(double aHeading) const;
unsigned int numTaxiways() const;
FGRunway getTaxiwayByIndex(unsigned int aIndex) const;
FGRunway* getTaxiwayByIndex(unsigned int aIndex) const;
void addRunway(const FGRunway& aRunway);
void addRunway(FGRunway* aRunway);
private:
typedef std::vector<FGRunwayPtr>::const_iterator Runway_iterator;
/**
* Helper to locate a runway by ident
*/
FGRunwayVector::const_iterator getIteratorForRunwayIdent(const std::string& aIdent, bool& aReversed) const;
Runway_iterator getIteratorForRunwayIdent(const std::string& aIdent) const;
FGAirport operator=(FGAirport &other);
FGAirport(const FGAirport&);
std::vector<FGRunway> mRunways;
std::vector<FGRunway> mTaxiways;
std::vector<FGRunwayPtr> mRunways;
std::vector<FGRunwayPtr> mTaxiways;
};

View file

@ -47,6 +47,7 @@
#include <GUI/new_gui.hxx> // FGFontCache
#include <Main/globals.hxx>
#include <Scenery/scenery.hxx>
#include <Airports/runways.hxx>
#include "hud.hxx"

View file

@ -61,10 +61,11 @@ namespace osg {
#include <Main/fg_props.hxx>
#include <Main/globals.hxx>
#include <Main/viewmgr.hxx>
#include <Airports/runways.hxx>
#include <plib/sg.h>
class FGRunway;
using std::deque;
using std::vector;
@ -509,7 +510,7 @@ private:
bool drawLine(const sgdVec3& a1, const sgdVec3& a2,
const sgdVec3& p1, const sgdVec3& p2);
void drawArrow();
bool get_active_runway(FGRunway& rwy);
FGRunway* get_active_runway();
void get_rwy_points(sgdVec3 *points);
void setLineWidth(void);
@ -517,7 +518,7 @@ private:
double mm[16],pm[16], arrowScale, arrowRad, lnScale;
double scaleDist, default_pitch, default_heading;
GLint view[4];
FGRunway runway;
FGRunway* runway;
FGViewer* cockpit_view;
unsigned short stippleOut, stippleCen;
bool drawIA, drawIAAlways;

View file

@ -82,7 +82,7 @@ runway_instr::runway_instr(const SGPropertyNode *node) :
void runway_instr::draw()
{
if (!is_broken() && get_active_runway(runway)) {
if (!is_broken() && (runway = get_active_runway())) {
glPushAttrib(GL_LINE_STIPPLE | GL_LINE_STIPPLE_PATTERN | GL_LINE_WIDTH);
float modelView[4][4], projMat[4][4];
bool anyLines;
@ -175,39 +175,38 @@ void runway_instr::draw()
}
bool runway_instr::get_active_runway(FGRunway& runway)
FGRunway* runway_instr::get_active_runway()
{
const FGAirport* apt = fgFindAirportID(fgGetString("/sim/presets/airport-id"));
if (!apt) return false;
if (!apt) return NULL;
runway = apt->getActiveRunwayForUsage();
return (!runway._rwy_no.empty());
return apt->getActiveRunwayForUsage();
}
void runway_instr::get_rwy_points(sgdVec3 *points3d)
{
double alt = current_aircraft.fdm_state->get_Runway_altitude() * SG_FEET_TO_METER;
double length = (runway._length / 2.0) * SG_FEET_TO_METER;
double width = (runway._width / 2.0) * SG_FEET_TO_METER;
double length = runway->lengthM() * 0.5;
double width = runway->widthM() * 0.5;
double frontLat, frontLon, backLat, backLon,az, tempLat, tempLon;
geo_direct_wgs_84(alt, runway._lat, runway._lon, runway._heading, length, &backLat, &backLon, &az);
geo_direct_wgs_84(alt, runway->_lat, runway->_lon, runway->_heading, length, &backLat, &backLon, &az);
sgGeodToCart(backLat * SG_DEGREES_TO_RADIANS, backLon * SG_DEGREES_TO_RADIANS, alt, points3d[4]);
geo_direct_wgs_84(alt, runway._lat, runway._lon, runway._heading + 180, length, &frontLat, &frontLon, &az);
geo_direct_wgs_84(alt, runway->_lat, runway->_lon, runway->_heading + 180, length, &frontLat, &frontLon, &az);
sgGeodToCart(frontLat * SG_DEGREES_TO_RADIANS, frontLon * SG_DEGREES_TO_RADIANS, alt, points3d[5]);
geo_direct_wgs_84(alt, backLat, backLon, runway._heading + 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, backLat, backLon, runway->_heading + 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, points3d[0]);
geo_direct_wgs_84(alt, backLat, backLon, runway._heading - 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, backLat, backLon, runway->_heading - 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, points3d[1]);
geo_direct_wgs_84(alt, frontLat, frontLon, runway._heading - 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, frontLat, frontLon, runway->_heading - 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, points3d[2]);
geo_direct_wgs_84(alt, frontLat, frontLon, runway._heading + 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, frontLat, frontLon, runway->_heading + 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, points3d[3]);
}
@ -387,8 +386,8 @@ void runway_instr::drawArrow()
Point3D ac(0.0), rwy(0.0);
ac.setlat(current_aircraft.fdm_state->get_Latitude_deg());
ac.setlon(current_aircraft.fdm_state->get_Longitude_deg());
rwy.setlat(runway._lat);
rwy.setlon(runway._lon);
rwy.setlat(runway->_lat);
rwy.setlon(runway->_lon);
float theta = GetHeadingFromTo(ac, rwy);
theta -= fgGetDouble("/orientation/heading-deg");
theta = -theta;
@ -418,8 +417,8 @@ void runway_instr::setLineWidth()
{
//Calculate the distance from the runway, A
double course, distance;
calc_gc_course_dist(Point3D(runway._lon * SGD_DEGREES_TO_RADIANS,
runway._lat * SGD_DEGREES_TO_RADIANS, 0.0),
calc_gc_course_dist(Point3D(runway->longitude() * SGD_DEGREES_TO_RADIANS,
runway->latitude() * SGD_DEGREES_TO_RADIANS, 0.0),
Point3D(current_aircraft.fdm_state->get_Longitude(),
current_aircraft.fdm_state->get_Latitude(), 0.0 ),
&course, &distance);

View file

@ -577,7 +577,7 @@ private:
bool boundOutsidePoints(sgdVec3& v, sgdVec3& m);
bool drawLine(const sgdVec3& a1, const sgdVec3& a2, const sgdVec3& p1, const sgdVec3& p2);
void drawArrow();
bool get_active_runway(FGRunway& rwy);
FGRunway* get_active_runway();
void get_rwy_points(sgdVec3 *points);
void setLineWidth();
@ -592,7 +592,7 @@ private:
double _default_pitch;
double _default_heading;
GLint _view[4];
FGRunway _runway;
FGRunway* _runway;
FGViewer* _cockpit_view;
unsigned short _stipple_out; // stipple pattern of the outline of the runway
unsigned short _stipple_center; // stipple pattern of the center line of the runway

View file

@ -74,7 +74,8 @@ HUD::Runway::Runway(HUD *hud, const SGPropertyNode *node, float x, float y) :
void HUD::Runway::draw()
{
if (!get_active_runway(_runway))
_runway = get_active_runway();
if (!_runway)
return;
glPushAttrib(GL_LINE_STIPPLE | GL_LINE_STIPPLE_PATTERN | GL_LINE_WIDTH);
@ -168,13 +169,12 @@ void HUD::Runway::draw()
}
bool HUD::Runway::get_active_runway(FGRunway& runway)
FGRunway* HUD::Runway::get_active_runway()
{
const FGAirport* apt = fgFindAirportID(fgGetString("/sim/presets/airport-id"));
if (!apt) return false;
if (!apt) return NULL;
runway = apt->getActiveRunwayForUsage();
return (!runway._rwy_no.empty());
return apt->getActiveRunwayForUsage();
}
@ -182,26 +182,26 @@ bool HUD::Runway::get_active_runway(FGRunway& runway)
void HUD::Runway::get_rwy_points(sgdVec3 *_points3d)
{
double alt = current_aircraft.fdm_state->get_Runway_altitude() * SG_FEET_TO_METER;
double length = (_runway._length / 2.0) * SG_FEET_TO_METER;
double width = (_runway._width / 2.0) * SG_FEET_TO_METER;
double length = _runway->lengthM() * 0.5;
double width = _runway->widthM() * 0.5;
double frontLat, frontLon, backLat, backLon,az, tempLat, tempLon;
geo_direct_wgs_84(alt, _runway._lat, _runway._lon, _runway._heading, length, &backLat, &backLon, &az);
geo_direct_wgs_84(alt, _runway->latitude(), _runway->longitude(), _runway->headingDeg(), length, &backLat, &backLon, &az);
sgGeodToCart(backLat * SG_DEGREES_TO_RADIANS, backLon * SG_DEGREES_TO_RADIANS, alt, _points3d[4]);
geo_direct_wgs_84(alt, _runway._lat, _runway._lon, _runway._heading + 180, length, &frontLat, &frontLon, &az);
geo_direct_wgs_84(alt, _runway->latitude(), _runway->longitude(), _runway->headingDeg() + 180, length, &frontLat, &frontLon, &az);
sgGeodToCart(frontLat * SG_DEGREES_TO_RADIANS, frontLon * SG_DEGREES_TO_RADIANS, alt, _points3d[5]);
geo_direct_wgs_84(alt, backLat, backLon, _runway._heading + 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, backLat, backLon, _runway->headingDeg() + 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, _points3d[0]);
geo_direct_wgs_84(alt, backLat, backLon, _runway._heading - 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, backLat, backLon, _runway->headingDeg() - 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, _points3d[1]);
geo_direct_wgs_84(alt, frontLat, frontLon, _runway._heading - 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, frontLat, frontLon, _runway->headingDeg() - 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, _points3d[2]);
geo_direct_wgs_84(alt, frontLat, frontLon, _runway._heading + 90, width, &tempLat, &tempLon, &az);
geo_direct_wgs_84(alt, frontLat, frontLon, _runway->headingDeg() + 90, width, &tempLat, &tempLon, &az);
sgGeodToCart(tempLat * SG_DEGREES_TO_RADIANS, tempLon * SG_DEGREES_TO_RADIANS, alt, _points3d[3]);
}
@ -380,8 +380,8 @@ void HUD::Runway::drawArrow()
Point3D ac(0.0), rwy(0.0);
ac.setlat(current_aircraft.fdm_state->get_Latitude_deg());
ac.setlon(current_aircraft.fdm_state->get_Longitude_deg());
rwy.setlat(_runway._lat);
rwy.setlon(_runway._lon);
rwy.setlat(_runway->latitude());
rwy.setlon(_runway->longitude());
float theta = GetHeadingFromTo(ac, rwy);
theta -= fgGetDouble("/orientation/heading-deg");
theta = -theta;
@ -412,8 +412,8 @@ void HUD::Runway::setLineWidth()
{
//Calculate the distance from the runway, A
double course, distance;
calc_gc_course_dist(Point3D(_runway._lon * SGD_DEGREES_TO_RADIANS,
_runway._lat * SGD_DEGREES_TO_RADIANS, 0.0),
calc_gc_course_dist(Point3D(_runway->longitude() * SGD_DEGREES_TO_RADIANS,
_runway->latitude() * SGD_DEGREES_TO_RADIANS, 0.0),
Point3D(current_aircraft.fdm_state->get_Longitude(),
current_aircraft.fdm_state->get_Latitude(), 0.0 ),
&course, &distance);

View file

@ -28,6 +28,8 @@
#include "kln89_page_apt.hxx"
#include <ATCDCL/commlist.hxx>
#include <Main/globals.hxx>
#include <Airports/runways.hxx>
// This function is copied from Airports/runways.cxx
// TODO - Make the original properly available and remove this instance!!!!
@ -202,8 +204,8 @@ void KLN89AptPage::Update(double dt) {
// I guess we can make a heuristic guess as to fuel availability from the runway sizes
// For now assume that airports with asphalt or concrete runways will have at least 100L,
// and that runways over 4000ft will have JET.
if(_aptRwys[0]._surface_code <= 2) {
if(_aptRwys[0]._length >= 4000) {
if(_aptRwys[0]->_surface_code <= 2) {
if(_aptRwys[0]->lengthFt() >= 4000) {
_kln89->DrawText("JET 100L", 2, 0, 1);
} else {
_kln89->DrawText("100L", 2, 0, 1);
@ -223,17 +225,17 @@ void KLN89AptPage::Update(double dt) {
string s;
if(i < _aptRwys.size()) {
// Rwy No.
string s = _aptRwys[i]._rwy_no;
string s = _aptRwys[i]->ident();
_kln89->DrawText(s, 2, 9, 3);
_kln89->DrawText("/", 2, 12, 3);
_kln89->DrawText(GetReverseRunwayNo(s), 2, 13, 3);
// Length
s = GPSitoa(int(float(_aptRwys[i]._length) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5));
s = GPSitoa(int(float(_aptRwys[i]->lengthFt()) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5));
_kln89->DrawText(s, 2, 5 - s.size(), 2);
_kln89->DrawText((_kln89->_altUnits == GPS_ALT_UNITS_FT ? "ft" : "m"), 2, 5, 2);
// Surface
// TODO - why not store these strings as an array?
switch(_aptRwys[i]._surface_code) {
switch(_aptRwys[i]->_surface_code) {
case 1:
// Asphalt - fall through
case 2:
@ -271,17 +273,17 @@ void KLN89AptPage::Update(double dt) {
i++;
if(i < _aptRwys.size()) {
// Rwy No.
string s = _aptRwys[i]._rwy_no;
string s = _aptRwys[i]->ident();
_kln89->DrawText(s, 2, 9, 1);
_kln89->DrawText("/", 2, 12, 1);
_kln89->DrawText(GetReverseRunwayNo(s), 2, 13, 1);
// Length
s = GPSitoa(int(float(_aptRwys[i]._length) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5));
s = GPSitoa(int(float(_aptRwys[i]->lengthFt()) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5));
_kln89->DrawText(s, 2, 5 - s.size(), 0);
_kln89->DrawText((_kln89->_altUnits == GPS_ALT_UNITS_FT ? "ft" : "m"), 2, 5, 0);
// Surface
// TODO - why not store these strings as an array?
switch(_aptRwys[i]._surface_code) {
switch(_aptRwys[i]->_surface_code) {
case 1:
// Asphalt - fall through
case 2:
@ -519,8 +521,8 @@ void KLN89AptPage::UpdateAirport(const string& id) {
// 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)) {
FGRunway* rwy(apt->getRunwayByIndex(r));
if ((r > 0) && (rwy->lengthFt() > _aptRwys.front()->lengthFt())) {
_aptRwys.insert(_aptRwys.begin(), rwy);
} else {
_aptRwys.push_back(rwy);

View file

@ -26,7 +26,7 @@
#include "kln89.hxx"
#include <Airports/runways.hxx>
class FGRunway;
struct AptFreq {
string service;
@ -60,7 +60,7 @@ private:
string _save_apt_id;
const FGAirport* ap;
vector<FGRunway> _aptRwys;
vector<FGRunway*> _aptRwys;
vector<AptFreq> _aptFreqs;
iap_list_type _iaps;

View file

@ -112,14 +112,14 @@ 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)
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);
geo_inverse_wgs_84(aTowerLat, aTowerLon, aRunway->latitude(), aRunway->longitude(), &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 leftcenter = fromPolar(aRunway->headingDeg(), aRunway->lengthM() * aScale / 2) + center;
osg::Vec3 lefttop = fromPolar(aRunway->headingDeg() - 90, aRunway->widthM() * aScale / 2) + leftcenter;
osg::Vec3 leftbottom = leftcenter * 2 - lefttop;
osg::Vec3 rightbottom = center * 2 - lefttop;
osg::Vec3 righttop = center * 2 - leftbottom;
@ -151,13 +151,15 @@ void GroundRadar::updateTexture()
for (unsigned int i=0; i<apt->numRunways(); ++i)
{
FGRunway runway(apt->getRunwayByIndex(i));
FGRunway* runway(apt->getRunwayByIndex(i));
if (runway->isReciprocal()) continue;
addRunwayVertices(runway, tower_lat, tower_lon, scale, rwy_vertices.get());
}
for (unsigned int i=0; i<apt->numTaxiways(); ++i)
{
FGRunway runway(apt->getTaxiwayByIndex(i));
FGRunway* runway(apt->getTaxiwayByIndex(i));
addRunwayVertices(runway, tower_lat, tower_lon, scale, taxi_vertices.get());
}

View file

@ -43,7 +43,7 @@ public:
protected:
void createTexture(const char* texture_name);
void addRunwayVertices(const FGRunway& aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices);
void addRunwayVertices(const FGRunway* aRunway, double aTowerLat, double aTowerLon, double aScale, osg::Vec3Array* aVertices);
osg::ref_ptr<osg::Geometry> _geom;
SGPropertyNode_ptr _airport_node;

View file

@ -4260,13 +4260,9 @@ bool
MK_VIII::Mode6Handler::test_airport (const FGAirport *airport)
{
for (unsigned int r=0; r<airport->numRunways(); ++r) {
FGRunway rwy(airport->getRunwayByIndex(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;
if (test_runway(rwy)) return true;
}
return false;
@ -4497,33 +4493,15 @@ void
MK_VIII::TCFHandler::select_runway (const FGAirport *airport,
FGRunway *_runway)
{
/*
FGRunway r;
bool status = globals->get_runways()->search(airport->getId(), &r);
assert(status);
}
while (globals->get_runways()->next(&r) && r._id == airport->getId());
*/
double min_diff = 360;
for (unsigned int r=0; r<airport->numRunways(); ++r) {
FGRunway rwy(airport->getRunwayByIndex(r));
double diff = get_azimuth_difference(&rwy);
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;
_runway = rwy;
}
} // of airport runways iteration
}
@ -4531,7 +4509,7 @@ MK_VIII::TCFHandler::select_runway (const FGAirport *airport,
bool MK_VIII::TCFHandler::AirportFilter::pass(FGAirport *a)
{
for (unsigned int r=0; r<a->numRunways(); ++r) {
if (a->getRunwayByIndex(r)._length >= mk->conf.runway_database) {
if (a->getRunwayByIndex(r)->lengthFt() >= mk->conf.runway_database) {
return true;
}
}
@ -4561,15 +4539,15 @@ MK_VIII::TCFHandler::update_runway ()
has_runway = true;
FGRunway _runway;
select_runway(airport, &_runway);
FGRunway* _runway;
select_runway(airport, _runway);
runway.center.latitude = _runway._lat;
runway.center.longitude = _runway._lon;
runway.center.latitude = _runway->latitude();
runway.center.longitude = _runway->longitude();
runway.elevation = airport->getElevation();
double half_length_m = _runway._length / 2 * SG_FEET_TO_METER;
double half_length_m = _runway->lengthM() * 0.5;
runway.half_length = half_length_m * SG_METER_TO_NM;
// b3 ________________ b0
@ -4579,8 +4557,8 @@ MK_VIII::TCFHandler::update_runway ()
// b2 b1
// get heading to runway threshold (h0) and end (h1)
runway.edges[0].heading = _runway._heading;
runway.edges[1].heading = get_reciprocal_heading(_runway._heading);
runway.edges[0].heading = _runway->headingDeg();
runway.edges[1].heading = get_reciprocal_heading(_runway->headingDeg());
double az;
@ -4604,7 +4582,7 @@ MK_VIII::TCFHandler::update_runway ()
&runway.edges[1].position.longitude,
&az);
double half_width_m = _runway._width / 2 * SG_FEET_TO_METER;
double half_width_m = _runway->widthM() * 0.5;
// get position of threshold bias area edges (b0 and b1)
get_bias_area_edges(&runway.edges[0].position,

View file

@ -764,20 +764,15 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
const FGAirport* apt = fgFindAirportID(id);
if (!apt) return false;
FGRunway r = apt->findBestRunwayForHeading(tgt_hdg);
fgSetString("/sim/atc/runway", r._rwy_no.c_str());
FGRunway* r = apt->findBestRunwayForHeading(tgt_hdg);
fgSetString("/sim/atc/runway", r->ident().c_str());
double lat2, lon2, az2;
double heading = r._heading;
double heading = r->headingDeg();
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
SG_LOG( SG_GENERAL, SG_INFO,
"runway = " << r._lon << ", " << r._lat
<< " length = " << r._length * SG_FEET_TO_METER
<< " heading = " << azimuth );
geo_direct_wgs_84 ( 0, r._lat, r._lon, azimuth, r._length * SG_FEET_TO_METER * 0.5
geo_direct_wgs_84 ( 0, r->latitude(), r->longitude(), azimuth, r->lengthM() * 0.5
- fgGetDouble("/sim/airport/runways/start-offset-m", 5.0),
&lat2, &lon2, &az2 );
@ -892,20 +887,15 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy, bo
return false;
}
FGRunway r(apt->getRunwayByIdent(rwy));
fgSetString("/sim/atc/runway", r._rwy_no.c_str());
FGRunway* r(apt->getRunwayByIdent(rwy));
fgSetString("/sim/atc/runway", r->ident().c_str());
double lat2, lon2, az2;
double heading = r._heading;
double heading = r->headingDeg();
double azimuth = heading + 180.0;
while ( azimuth >= 360.0 ) { azimuth -= 360.0; }
SG_LOG( SG_GENERAL, SG_INFO,
"runway = " << r._lon << ", " << r._lat
<< " length = " << r._length * SG_FEET_TO_METER
<< " heading = " << azimuth );
geo_direct_wgs_84 ( 0, r._lat, r._lon, azimuth, r._length * SG_FEET_TO_METER * 0.5
geo_direct_wgs_84 ( 0, r->latitude(), r->longitude(), azimuth, r->lengthM() * 0.5
- fgGetDouble("/sim/airport/runways/start-offset-m", 5.0),
&lat2, &lon2, &az2 );

View file

@ -214,7 +214,7 @@ bool fgNavDBInit( FGAirportList *airports,
static void update_loc_position( FGNavRecord *loc, FGRunway *rwy,
double threshold )
{
double hdg = rwy->_heading;
double hdg = rwy->headingDeg();
hdg += 180.0;
if ( hdg > 360.0 ) {
hdg -= 360.0;
@ -222,8 +222,8 @@ static void update_loc_position( FGNavRecord *loc, FGRunway *rwy,
// calculate runway threshold point
double thresh_lat, thresh_lon, return_az;
geo_direct_wgs_84 ( 0.0, rwy->_lat, rwy->_lon, hdg,
rwy->_length/2.0 * SG_FEET_TO_METER,
geo_direct_wgs_84 ( 0.0, rwy->latitude(), rwy->longitude(), hdg,
rwy->lengthM() * 0.5,
&thresh_lat, &thresh_lon, &return_az );
// cout << "Threshold = " << thresh_lat << "," << thresh_lon << endl;
@ -249,7 +249,7 @@ static void update_loc_position( FGNavRecord *loc, FGRunway *rwy,
// cout << "orig heading = " << loc->get_multiuse() << endl;
// cout << "new heading = " << rwy->_heading << endl;
double hdg_diff = loc->get_multiuse() - rwy->_heading;
double hdg_diff = loc->get_multiuse() - rwy->headingDeg();
// clamp to [-180.0 ... 180.0]
if ( hdg_diff < -180.0 ) {
@ -261,7 +261,7 @@ static void update_loc_position( FGNavRecord *loc, FGRunway *rwy,
if ( fabs(hdg_diff) <= threshold ) {
loc->set_lat( nloc_lat );
loc->set_lon( nloc_lon );
loc->set_multiuse( rwy->_heading );
loc->set_multiuse( rwy->headingDeg() );
}
}
@ -290,8 +290,8 @@ void fgNavDBAlignLOCwithRunway( FGAirportList *airports, FGNavList *loclist,
FGAirport* airport = airports->search(parts[0]);
if (!airport) continue; // not found
FGRunway r = airport->getRunwayByIdent(parts[1]);
update_loc_position( (*loc), &r, threshold );
FGRunway* r = airport->getRunwayByIdent(parts[1]);
update_loc_position( (*loc), r, threshold );
++loc;
}
++freq;

View file

@ -555,24 +555,22 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args)
// set runway hash
naRef rwys = naNewHash(c);
for (unsigned int r=0; r<apt->numRunways(); ++r) {
FGRunway rwy(apt->getRunwayByIndex(r));
FGRunway* rwy(apt->getRunwayByIndex(r));
naRef rwyid = naStr_fromdata(naNewString(c),
const_cast<char *>(rwy._rwy_no.c_str()),
rwy._rwy_no.length());
const_cast<char *>(rwy->ident().c_str()),
rwy->ident().length());
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("lat", 3, naNum(rwy->latitude()));
HASHSET("lon", 3, naNum(rwy->longitude()));
HASHSET("heading", 7, naNum(rwy->headingDeg()));
HASHSET("length", 6, naNum(rwy->lengthM()));
HASHSET("width", 5, naNum(rwy->widthM()));
HASHSET("threshold1", 10, naNum(rwy->_displ_thresh * SG_FEET_TO_METER));
HASHSET("stopway1", 8, naNum(rwy->_stopway * SG_FEET_TO_METER));
#undef HASHSET
naHash_set(rwys, rwyid, rwydata);
}