2003-03-05 18:02:24 +00:00
|
|
|
// runways.cxx -- a simple class to manage airport runway info
|
2000-08-16 01:28:33 +00:00
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started August 2000.
|
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
|
2000-08-16 01:28:33 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
2006-02-21 01:16:04 +00:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2000-08-16 01:28:33 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2008-04-13 21:12:36 +00:00
|
|
|
#include <cstdio> // sprintf()
|
|
|
|
#include <cstdlib> // atoi()
|
2010-08-07 12:00:33 +00:00
|
|
|
#include <cassert>
|
2000-08-16 01:28:33 +00:00
|
|
|
|
|
|
|
#include <simgear/compiler.h>
|
|
|
|
|
2009-08-29 13:24:33 +00:00
|
|
|
#include <simgear/props/props.hxx>
|
2009-08-29 18:26:54 +00:00
|
|
|
|
2008-07-25 18:38:29 +00:00
|
|
|
#include <string>
|
2000-08-16 01:28:33 +00:00
|
|
|
|
|
|
|
#include "runways.hxx"
|
|
|
|
|
2009-10-11 11:37:13 +00:00
|
|
|
#include <Airports/simple.hxx>
|
|
|
|
#include <Navaids/procedure.hxx>
|
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
using std::string;
|
2000-08-16 01:28:33 +00:00
|
|
|
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
static std::string cleanRunwayNo(const std::string& aRwyNo)
|
2004-12-22 23:57:07 +00:00
|
|
|
{
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
if (aRwyNo[0] == 'x') {
|
|
|
|
return std::string(); // no ident for taxiways
|
|
|
|
}
|
|
|
|
|
|
|
|
string result(aRwyNo);
|
2008-08-14 18:13:39 +00:00
|
|
|
// canonicalise runway ident
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
if ((aRwyNo.size() == 1) || !isdigit(aRwyNo[1])) {
|
|
|
|
result = "0" + aRwyNo;
|
|
|
|
}
|
2000-08-16 01:28:33 +00:00
|
|
|
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
// trim off trailing garbage
|
|
|
|
if (result.size() > 2) {
|
|
|
|
char suffix = toupper(result[2]);
|
|
|
|
if (suffix == 'X') {
|
|
|
|
result = result.substr(0, 2);
|
2003-08-29 04:11:23 +00:00
|
|
|
}
|
2008-08-14 18:13:39 +00:00
|
|
|
}
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2008-08-14 18:13:39 +00:00
|
|
|
|
2008-12-29 22:23:22 +00:00
|
|
|
FGRunway::FGRunway(FGAirport* aAirport, const string& aIdent,
|
2008-12-24 14:48:30 +00:00
|
|
|
const SGGeod& aGeod,
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
const double heading, const double length,
|
|
|
|
const double width,
|
|
|
|
const double displ_thresh,
|
|
|
|
const double stopway,
|
|
|
|
const int surface_code,
|
|
|
|
bool reciprocal) :
|
2008-12-29 22:23:22 +00:00
|
|
|
FGRunwayBase(RUNWAY, cleanRunwayNo(aIdent), aGeod, heading, length, width, surface_code, true),
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
_airport(aAirport),
|
2009-09-16 00:17:12 +00:00
|
|
|
_isReciprocal(reciprocal),
|
|
|
|
_reciprocal(NULL),
|
2008-12-29 22:23:22 +00:00
|
|
|
_displ_thresh(displ_thresh),
|
2009-06-11 21:53:30 +00:00
|
|
|
_stopway(stopway),
|
|
|
|
_ils(NULL)
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
{
|
2000-08-16 01:28:33 +00:00
|
|
|
}
|
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
string FGRunway::reverseIdent(const string& aRunwayIdent)
|
|
|
|
{
|
|
|
|
// Helipads don't have a seperate number per end
|
|
|
|
if (aRunwayIdent.size() && (aRunwayIdent[0] == 'H' || aRunwayIdent[0] == 'h' || aRunwayIdent[0] == 'x')) {
|
|
|
|
return aRunwayIdent;
|
|
|
|
}
|
2000-08-16 01:28:33 +00:00
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
std::string ident(aRunwayIdent);
|
2003-03-20 09:38:06 +00:00
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
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) {
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
char suffix = toupper(ident[2]);
|
|
|
|
if(suffix == 'L') {
|
|
|
|
buf[2] = 'R';
|
|
|
|
} else if (suffix == 'R') {
|
|
|
|
buf[2] = 'L';
|
2003-08-29 04:11:23 +00:00
|
|
|
} else {
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
// something else, just copy
|
|
|
|
buf[2] = suffix;
|
2003-08-29 04:11:23 +00:00
|
|
|
}
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
|
|
|
|
buf[3] = 0;
|
2008-08-14 18:13:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
2000-08-16 01:28:33 +00:00
|
|
|
}
|
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt) const
|
2001-05-15 00:00:08 +00:00
|
|
|
{
|
2008-08-14 18:13:39 +00:00
|
|
|
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;
|
2000-08-16 01:28:33 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 16:15:48 +00:00
|
|
|
SGGeod FGRunway::begin() const
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
{
|
|
|
|
return pointOnCenterline(0.0);
|
|
|
|
}
|
|
|
|
|
2009-01-03 16:15:48 +00:00
|
|
|
SGGeod FGRunway::end() const
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
{
|
|
|
|
return pointOnCenterline(lengthM());
|
|
|
|
}
|
|
|
|
|
2009-01-03 16:15:48 +00:00
|
|
|
SGGeod FGRunway::threshold() const
|
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.
2008-09-11 08:38:09 +00:00
|
|
|
{
|
|
|
|
return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER);
|
|
|
|
}
|
|
|
|
|
2009-08-29 10:21:21 +00:00
|
|
|
void FGRunway::processThreshold(SGPropertyNode* aThreshold)
|
|
|
|
{
|
|
|
|
assert(ident() == aThreshold->getStringValue("rwy"));
|
2009-08-29 18:26:54 +00:00
|
|
|
|
|
|
|
double lon = aThreshold->getDoubleValue("lon"),
|
|
|
|
lat = aThreshold->getDoubleValue("lat");
|
|
|
|
SGGeod newThreshold(SGGeod::fromDegM(lon, lat, mPosition.getElevationM()));
|
|
|
|
|
|
|
|
_heading = aThreshold->getDoubleValue("hdg-deg");
|
|
|
|
_displ_thresh = aThreshold->getDoubleValue("displ-m") * SG_METER_TO_FEET;
|
|
|
|
_stopway = aThreshold->getDoubleValue("stopw-m") * SG_METER_TO_FEET;
|
|
|
|
|
2009-12-05 10:55:55 +00:00
|
|
|
// compute the new runway center, based on the threshold lat/lon and length,
|
|
|
|
double offsetFt = (0.5 * _length);
|
2009-08-29 18:26:54 +00:00
|
|
|
SGGeod newCenter;
|
|
|
|
double dummy;
|
|
|
|
SGGeodesy::direct(newThreshold, _heading, offsetFt * SG_FEET_TO_METER, newCenter, dummy);
|
|
|
|
mPosition = newCenter;
|
|
|
|
}
|
2009-09-16 00:17:12 +00:00
|
|
|
|
|
|
|
void FGRunway::setReciprocalRunway(FGRunway* other)
|
|
|
|
{
|
|
|
|
assert(_reciprocal==NULL);
|
|
|
|
assert((other->_reciprocal == NULL) || (other->_reciprocal == this));
|
|
|
|
|
|
|
|
_reciprocal = other;
|
|
|
|
}
|
|
|
|
|
2009-10-11 11:37:13 +00:00
|
|
|
std::vector<flightgear::SID*> FGRunway::getSIDs()
|
|
|
|
{
|
|
|
|
std::vector<flightgear::SID*> result;
|
|
|
|
for (unsigned int i=0; i<_airport->numSIDs(); ++i) {
|
|
|
|
flightgear::SID* s = _airport->getSIDByIndex(i);
|
|
|
|
if (s->isForRunway(this)) {
|
|
|
|
result.push_back(s);
|
|
|
|
}
|
|
|
|
} // of SIDs at the airport iteration
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<flightgear::STAR*> FGRunway::getSTARs()
|
|
|
|
{
|
|
|
|
std::vector<flightgear::STAR*> result;
|
|
|
|
for (unsigned int i=0; i<_airport->numSTARs(); ++i) {
|
|
|
|
flightgear::STAR* s = _airport->getSTARByIndex(i);
|
|
|
|
if (s->isForRunway(this)) {
|
|
|
|
result.push_back(s);
|
|
|
|
}
|
|
|
|
} // of STARs at the airport iteration
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|