# include <config.h>
#endif
-#include <cmath> // fabs()
#include <cstdio> // sprintf()
#include <cstdlib> // atoi()
+#include <cassert>
#include <simgear/compiler.h>
-#include <simgear/debug/logstream.hxx>
-#include <Main/fg_props.hxx>
+
+#include <simgear/props/props.hxx>
#include <string>
-#include <map>
#include "runways.hxx"
-using std::istream;
-using std::multimap;
-using std::string;
+#include <Airports/airport.hxx>
+#include <Navaids/procedure.hxx>
+#include <Navaids/navrecord.hxx>
+#include <Navaids/NavDataCache.hxx>
-/*
- * surface codes
- * 1 - asphalt
- * 2 - concrete
- * 3 - turf
- * 4 - dirt
- * 5 - gravel
- * 6 - asphalt helipad
- * 7 - concrete helipad
- * 8 - turf helipad
- * 9 - dirt helipad
- * 12 - lakebed
- */
-
-static FGPositioned::Type runwayTypeFromNumber(const std::string& aRwyNo)
-{
- return (aRwyNo[0] == 'x') ? FGPositioned::TAXIWAY : FGPositioned::RUNWAY;
-}
-
-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;
-}
+using std::string;
-FGRunway::FGRunway(FGAirport* aAirport, const string& rwy_no,
+FGRunway::FGRunway(PositionedID aGuid,
+ PositionedID aAirport, const string& aIdent,
const SGGeod& aGeod,
const double heading, const double length,
const double width,
const double displ_thresh,
const double stopway,
- const int surface_code,
- bool reciprocal) :
- FGPositioned(runwayTypeFromNumber(rwy_no), cleanRunwayNo(rwy_no), aGeod,
- (runwayTypeFromNumber(rwy_no) == FGPositioned::RUNWAY)),
+ const int surface_code) :
+ FGRunwayBase(aGuid, RUNWAY, aIdent, aGeod,
+ heading, length, width, surface_code),
_airport(aAirport),
- _reciprocal(reciprocal)
+ _reciprocal(0),
+ _displ_thresh(displ_thresh),
+ _stopway(stopway),
+ _ils(0)
{
- _heading = heading;
- _length = length;
- _width = width;
- _displ_thresh = displ_thresh;
- _stopway = stopway;
-
- _surface_code = surface_code;
}
string FGRunway::reverseIdent(const string& aRunwayIdent)
return buf;
}
-double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt) const
+double FGRunway::score(double aLengthWt, double aWidthWt, double aSurfaceWt, double aIlsWt) 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;
+
+ int ils = (_ils != 0);
- return _length * aLengthWt + _width * aWidthWt + surface * aSurfaceWt + 1e-20;
+ return _length * aLengthWt + _width * aWidthWt + surface * aSurfaceWt + ils * aIlsWt + 1e-20;
}
-bool FGRunway::isTaxiway() const
+SGGeod FGRunway::begin() const
{
- return (type() == TAXIWAY);
+ return pointOnCenterline(0.0);
+}
+
+SGGeod FGRunway::end() const
+{
+ return pointOnCenterline(lengthM());
}
SGGeod FGRunway::threshold() const
{
- return pointOnCenterline(0.0);
+ return pointOnCenterline(_displ_thresh);
}
-SGGeod FGRunway::reverseThreshold() const
+void FGRunway::setReciprocalRunway(PositionedID other)
{
- return pointOnCenterline(lengthM());
+ assert(_reciprocal==0);
+ _reciprocal = other;
+}
+
+FGAirport* FGRunway::airport() const
+{
+ return loadById<FGAirport>(_airport);
+}
+
+FGRunway* FGRunway::reciprocalRunway() const
+{
+ return loadById<FGRunway>(_reciprocal);
+}
+
+FGNavRecord* FGRunway::ILS() const
+{
+ if (_ils == 0) {
+ return NULL;
+ }
+
+ return loadById<FGNavRecord>(_ils);
+}
+
+FGNavRecord* FGRunway::glideslope() const
+{
+ flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
+ PositionedID gsId = cache->findNavaidForRunway(guid(), FGPositioned::GS);
+ if (gsId == 0) {
+ return NULL;
+ }
+
+ return loadById<FGNavRecord>(gsId);
+}
+
+flightgear::SIDList FGRunway::getSIDs() const
+{
+ FGAirport* apt = airport();
+ flightgear::SIDList result;
+ for (unsigned int i=0; i<apt->numSIDs(); ++i) {
+ flightgear::SID* s = apt->getSIDByIndex(i);
+ if (s->isForRunway(this)) {
+ result.push_back(s);
+ }
+ } // of SIDs at the airport iteration
+
+ return result;
}
-SGGeod FGRunway::displacedThreshold() const
+flightgear::STARList FGRunway::getSTARs() const
{
- return pointOnCenterline(_displ_thresh * SG_FEET_TO_METER);
+ FGAirport* apt = airport();
+ flightgear::STARList result;
+ for (unsigned int i=0; i<apt->numSTARs(); ++i) {
+ flightgear::STAR* s = apt->getSTARByIndex(i);
+ if (s->isForRunway(this)) {
+ result.push_back(s);
+ }
+ } // of STARs at the airport iteration
+
+ return result;
}
-SGGeod FGRunway::pointOnCenterline(double aOffset) const
+flightgear::ApproachList
+FGRunway::getApproaches(flightgear::ProcedureType type) const
{
- SGGeod result;
- double dummyAz2;
- double halfLengthMetres = lengthM() * 0.5;
+ FGAirport* apt = airport();
+ flightgear::ApproachList result;
+ for (unsigned int i=0; i<apt->numApproaches(); ++i)
+ {
+ flightgear::Approach* s = apt->getApproachByIndex(i);
+ if( s->runway() == this
+ && (type == flightgear::PROCEDURE_INVALID || type == s->type()) )
+ {
+ result.push_back(s);
+ }
+ } // of approaches at the airport iteration
- SGGeodesy::direct(mPosition, _heading,
- aOffset - halfLengthMetres,
- result, dummyAz2);
return result;
}
-bool FGRunway::isHardSurface() const
+void FGRunway::updateThreshold(const SGGeod& newThreshold, double newHeading,
+ double newDisplacedThreshold,
+ double newStopway)
{
- return ((_surface_code == 1) || (_surface_code == 2));
+ modifyPosition(newThreshold);
+ _heading = newHeading;
+ _stopway = newStopway;
+ _displ_thresh = newDisplacedThreshold;
}
+FGHelipad::FGHelipad(PositionedID aGuid,
+ PositionedID aAirport, const string& aIdent,
+ const SGGeod& aGeod,
+ const double heading, const double length,
+ const double width,
+ const int surface_code) :
+ FGRunwayBase(aGuid, RUNWAY, aIdent, aGeod,
+ heading, length, width, surface_code)
+{
+}