#include "ATCutils.hxx"
#include "tower.hxx"
+// extern from Airports/simple.cxx
+extern Point3D fgGetAirportPos( const std::string& id );
+
FGAIGAVFRTraffic::FGAIGAVFRTraffic() {
ATC = globals->get_ATC_mgr();
_towerContactedIncoming = false;
using namespace simgear;
+// extern from Airports/simple.cxx
+extern Point3D fgGetAirportPos( const std::string& id );
+
FGAIMgr::FGAIMgr() {
ATC = globals->get_ATC_mgr();
initDone = false;
metar_in >> skipeol;
} else {
const FGAirport* a = airports->search( ident );
- if ( a ) airports->has_metar( ident );
+ if ( a ) const_cast<FGAirport*>(a)->setMetar(true);
}
}
// try and read in an auxilary file
airports_array.push_back( a );
- SG_LOG( SG_GENERAL, SG_BULK, "Adding " << id << " pos = " << location.getLongitudeDeg()
- << ", " << location.getLatitudeDeg() << " elev = " << location.getElevationFt() );
-
return a;
}
-
// search for the specified id
FGAirport* FGAirportList::search( const string& id)
{
return (itr == airports_by_id.end() ? NULL : itr->second);
}
-// search for the airport nearest the specified position
-FGAirport* FGAirportList::search(double lon_deg, double lat_deg, double max_range)
-{
- static FGAirportSearchFilter accept_any;
- return search(lon_deg, lat_deg, max_range, accept_any);
-}
-
-
-// search for the airport nearest the specified position and
-// passing the filter
-FGAirport* FGAirportList::search(double lon_deg, double lat_deg,
- double max_range,
- FGAirportSearchFilter& filter)
-{
- double min_dist = max_range;
-
- airport_list_iterator it = airports_array.begin();
- airport_list_iterator end = airports_array.end();
- airport_list_iterator closest = end;
- for (; it != end; ++it) {
- if (!filter.pass(*it))
- continue;
-
- // crude manhatten distance based on lat/lon difference
- double d = fabs(lon_deg - (*it)->getLongitude())
- + fabs(lat_deg - (*it)->getLatitude());
- if (d < min_dist) {
- closest = it;
- min_dist = d;
- }
- }
- return closest != end ? *closest : 0;
-}
-
-
int
FGAirportList::size () const
{
}
}
-
-/**
- * Mark the specified airport record as not having metar
- */
-void FGAirportList::no_metar( const string &id )
-{
- if(airports_by_id.find(id) != airports_by_id.end()) {
- airports_by_id[id]->setMetar(false);
- }
-}
-
-
-/**
- * Mark the specified airport record as (yes) having metar
- */
-void FGAirportList::has_metar( const string &id )
-{
- if(airports_by_id.find(id) != airports_by_id.end()) {
- airports_by_id[id]->setMetar(true);
- }
-}
-
-
// find basic airport location info from airport database
const FGAirport *fgFindAirportID( const string& id)
{
#include <string>
#include <map>
-#include <set>
#include <vector>
-#include <simgear/math/point3d.hxx>
#include "Navaids/positioned.hxx"
// forward decls
std::vector<FGRunwayPtr> mTaxiways;
};
-
-class FGAirportSearchFilter {
-public:
- virtual ~FGAirportSearchFilter() {}
- // all airports pass the filter by default
- virtual bool pass(FGAirport*) { return true; }
-};
-
typedef std::map < std::string, FGAirport* > airport_map;
typedef airport_map::iterator airport_map_iterator;
typedef airport_map::const_iterator const_airport_map_iterator;
// Returns NULL if unsucessfull.
FGAirport* search( const std::string& id );
- // search for the airport closest to the specified position
- // (currently a linear inefficient search so it's probably not
- // best to use this at runtime.) An FGAirportSearchFilter class
- // can be used to restrict the possible choices to a subtype.
- // max_range limits search - specified as an arc distance, in degrees
- FGAirport* search( double lon_deg, double lat_deg, double max_range );
- FGAirport* search( double lon_deg, double lat_deg, double max_range, FGAirportSearchFilter& );
-
/**
* Return the number of airports in the list.
*/
*/
const FGAirport *getAirport( unsigned int index ) const;
- /**
- * Mark the specified airport record as not having metar
- */
- void no_metar( const std::string &id );
-
- /**
- * Mark the specified airport record as (yes) having metar
- */
- void has_metar( const std::string &id );
-
};
// find basic airport location info from airport database
// get airport elevation
double fgGetAirportElev( const std::string& id );
-// get airport position
-Point3D fgGetAirportPos( const std::string& id );
-
#endif // _FG_SIMPLE_HXX
# include "config.h"
#endif
-#include <stdlib.h>
-#include <math.h>
#include <algorithm>
#include <simgear/debug/logstream.hxx>
#include <Main/fg_props.hxx>
#include <Main/util.hxx>
+#include "Environment/fgmetar.hxx"
#include "environment_mgr.hxx"
#include "environment_ctrl.hxx"
using std::sort;
-class metar_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->getMetar(); }
-} metar_only;
-
+class AirportWithMetar : public FGPositioned::Filter
+{
+public:
+ virtual bool pass(FGPositioned* aPos) const
+ {
+ if ((aPos->type() < FGPositioned::AIRPORT) || (aPos->type() > FGPositioned::SEAPORT)) {
+ return false;
+ }
+
+ FGAirport* apt = static_cast<FGAirport*>(aPos);
+ return apt->getMetar();
+ }
+};
\f
////////////////////////////////////////////////////////////////////////
// Implementation of FGEnvironmentCtrl abstract base class.
void
FGMetarEnvironmentCtrl::init ()
{
- const SGPropertyNode *longitude
- = fgGetNode( "/position/longitude-deg", true );
- const SGPropertyNode *latitude
- = fgGetNode( "/position/latitude-deg", true );
+ SGGeod pos = SGGeod::fromDeg(
+ fgGetDouble("/position/longitude-deg", true),
+ fgGetDouble( "/position/latitude-deg", true));
metar_loaded = false;
bool found_metar = false;
metar_max_age->setLongValue(0);
while ( !found_metar && (_error_count < 3) ) {
- const FGAirport* a = globals->get_airports()
- ->search( longitude->getDoubleValue(),
- latitude->getDoubleValue(),
- 360.0,
- metar_only );
- if ( a ) {
- FGMetarResult result = fetch_data( a->getId() );
- if ( result.m != NULL ) {
- SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
- << a->getId());
- last_apt = a;
- _icao = a->getId();
- search_elapsed = 0.0;
- fetch_elapsed = 0.0;
- update_metar_properties( result.m );
- update_env_config();
- env->init();
- found_metar = true;
- } else {
- // mark as no metar so it doesn't show up in subsequent
- // searches.
- SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = "
- << a->getId() );
- globals->get_airports()->no_metar( a->getId() );
- }
+ AirportWithMetar filter;
+ FGPositionedRef a = FGPositioned::findClosest(pos, 10000.0, &filter);
+ if (!a) {
+ break;
}
- }
+
+ FGMetarResult result = fetch_data(a->ident());
+ if ( result.m != NULL ) {
+ SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
+ << a->ident());
+ last_apt = a;
+ _icao = a->ident();
+ search_elapsed = 0.0;
+ fetch_elapsed = 0.0;
+ update_metar_properties( result.m );
+ update_env_config();
+ env->init();
+ found_metar = true;
+ } else {
+ // mark as no metar so it doesn't show up in subsequent
+ // searches.
+ SG_LOG( SG_GENERAL, SG_INFO, "no metar at metar = " << a->ident() );
+ static_cast<FGAirport*>(a.ptr())->setMetar(false);
+ }
+ } // of airprot-with-metar search iteration
+
metar_max_age->setLongValue(max_age);
}
void
FGMetarEnvironmentCtrl::update(double delta_time_sec)
{
-
_dt += delta_time_sec;
if (_error_count >= 3)
return;
= fgGetNode( "/position/longitude-deg", true );
static const SGPropertyNode *latitude
= fgGetNode( "/position/latitude-deg", true );
+ SGGeod pos = SGGeod::fromDeg(longitude->getDoubleValue(),
+ latitude->getDoubleValue());
+
search_elapsed += delta_time_sec;
fetch_elapsed += delta_time_sec;
interpolate_elapsed += delta_time_sec;
// if time for a new search request, push it onto the request
// queue
if ( search_elapsed > search_interval_sec ) {
- const FGAirport* a = globals->get_airports()
- ->search( longitude->getDoubleValue(),
- latitude->getDoubleValue(),
- 360.0,
- metar_only );
- if ( a ) {
- if ( !last_apt || last_apt->getId() != a->getId()
+ AirportWithMetar filter;
+ FGPositionedRef a = FGPositioned::findClosest(pos, 10000.0, &filter);
+ if (a) {
+ if ( !last_apt || last_apt->ident() != a->ident()
|| fetch_elapsed > same_station_interval_sec )
{
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
- << a->getId());
- request_queue.push( a->getId() );
+ << a->ident());
+ request_queue.push( a->ident() );
last_apt = a;
- _icao = a->getId();
+ _icao = a->ident();
search_elapsed = 0.0;
fetch_elapsed = 0.0;
} else {
SG_LOG( SG_GENERAL, SG_INFO, "same station, waiting = "
<< same_station_interval_sec - fetch_elapsed );
}
+
} else {
- SG_LOG( SG_GENERAL, SG_WARN,
+ SG_LOG( SG_GENERAL, SG_WARN,
"Unable to find any airports with metar" );
}
} else if ( interpolate_elapsed > EnvironmentUpdatePeriodSec ) {
// searches, and signal an immediate re-search.
SG_LOG( SG_GENERAL, SG_WARN,
"no metar at station = " << result.icao );
- globals->get_airports()->no_metar( result.icao );
+ const FGAirport* apt = globals->get_airports()->search(result.icao);
+ const_cast<FGAirport*>(apt)->setMetar(false);
search_elapsed = 9999.0;
}
}
#ifndef _ENVIRONMENT_CTRL_HXX
#define _ENVIRONMENT_CTRL_HXX
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
#include <simgear/compiler.h>
#include <simgear/structure/subsystem_mgr.hxx>
-#include <simgear/environment/metar.hxx>
#if defined(ENABLE_THREADS)
# include <OpenThreads/Thread>
# include <simgear/threads/SGQueue.hxx>
#endif
-#include <cmath>
#include <queue>
#include <vector>
-using std::queue;
-using std::vector;
+#include "Navaids/positioned.hxx"
+#include "Environment/environment.hxx"
+// forward decls
class SGPropertyNode;
class FGAirport;
+class FGMetar;
-#include "environment.hxx"
-#include "fgmetar.hxx"
-
-
-\f
/**
* Interface to control environment information for a specific location.
*/
static bool lessThan(bucket *a, bucket *b);
};
- void read_table (const SGPropertyNode * node, vector<bucket *> &table);
- void do_interpolate (vector<bucket *> &table, double altitude_ft,
+ void read_table (const SGPropertyNode * node, std::vector<bucket *> &table);
+ void do_interpolate (std::vector<bucket *> &table, double altitude_ft,
FGEnvironment * environment);
FGEnvironment env1, env2; // temporaries
- vector<bucket *> _boundary_table;
- vector<bucket *> _aloft_table;
+ std::vector<bucket *> _boundary_table;
+ std::vector<bucket *> _aloft_table;
};
// A convenience wrapper around FGMetar
struct FGMetarResult {
- string icao;
+ std::string icao;
FGMetar *m;
};
private:
FGInterpolateEnvironmentCtrl *env;
- string _icao;
+ std::string _icao;
bool metar_loaded;
float station_elevation_ft;
float search_interval_sec;
float search_elapsed;
float fetch_elapsed;
float interpolate_elapsed;
- const FGAirport *last_apt;
+ FGPositionedRef last_apt;
SGPropertyNode_ptr proxy_host;
SGPropertyNode_ptr proxy_port;
SGPropertyNode_ptr proxy_auth;
/**
* FIFO queue which holds a pointer to the fetched metar data.
*/
- SGBlockingQueue < string > request_queue;
+ SGBlockingQueue <std::string > request_queue;
/**
* FIFO queue which holds a pointer to the fetched metar data.
/**
* FIFO queue which holds a pointer to the fetched metar data.
*/
- queue < string > request_queue;
+ std::queue <std::string > request_queue;
/**
* FIFO queue which holds a pointer to the fetched metar data.
*/
- queue < FGMetarResult > result_queue;
+ std::queue < FGMetarResult > result_queue;
#endif
#if defined(ENABLE_THREADS)
return false;
}
-bool MK_VIII::Mode6Handler::AirportFilter::pass(FGAirport* a)
+bool MK_VIII::Mode6Handler::AirportFilter::pass(FGPositioned* a) const
{
- return self->test_airport(a);
+ if (a->type() != FGPositioned::AIRPORT) {
+ return false;
+ }
+
+ bool ok = self->test_airport(static_cast<FGAirport*>(a));
+ return ok;
}
void
}
// Search for the closest runway threshold in range 5
- // nm. Passing 0.5 degrees (approximatively 30 nm) to
+ // nm. Passing 30nm to
// get_closest_airport() provides enough margin for large
// airports, which may have a runway located far away from the
// airport's reference point.
AirportFilter filter(this);
- const FGAirport *airport = globals->get_airports()->search(
- mk_data(gps_latitude).get(), mk_data(gps_longitude).get(),
- 0.5, filter);
-
- if (airport) {
- runway.elevation = airport->getElevation();
+ FGPositionedRef apt = FGPositioned::findClosest(
+ SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()),
+ 30.0, &filter);
+ if (apt) {
+ runway.elevation = apt->elevation();
}
- has_runway.set(airport != NULL);
+ has_runway.set(apt != NULL);
}
void
return _runway;
}
-bool MK_VIII::TCFHandler::AirportFilter::pass(FGAirport *a)
+bool MK_VIII::TCFHandler::AirportFilter::pass(FGPositioned* aPos) const
{
- for (unsigned int r=0; r<a->numRunways(); ++r) {
- if (a->getRunwayByIndex(r)->lengthFt() >= mk->conf.runway_database) {
- return true;
- }
+ if (aPos->type() != FGPositioned::AIRPORT) {
+ return false;
}
-
- return false;
+
+ FGAirport* apt = static_cast<FGAirport*>(aPos);
+ return apt->hasHardRunwayOfLengthFt(mk->conf.runway_database);
}
-
+
void
MK_VIII::TCFHandler::update_runway ()
{
}
// Search for the intended destination runway of the closest
- // airport in range 15 nm. Passing 0.5 degrees (approximatively
- // 30 nm) to get_closest_airport() provides enough margin for
+ // airport in range 15 nm. Passing 30nm to get_closest_airport()
+ // provides enough margin for
// large airports, which may have a runway located far away from
// the airport's reference point.
AirportFilter filter(mk);
- const FGAirport *airport = globals->get_airports()->search(
- mk_data(gps_longitude).get(), mk_data(gps_latitude).get(),
- 0.5, filter);
-
- if (!airport) return;
+ FGPositionedRef apt = FGPositioned::findClosest(
+ SGGeod::fromDeg(mk_data(gps_longitude).get(), mk_data(gps_latitude).get()),
+ 30.0, &filter);
+
+ if (!apt) return;
has_runway = true;
- FGRunway* _runway = select_runway(airport);
-
+ FGRunway* _runway = select_runway(static_cast<FGAirport*>(apt.ptr()));
+
runway.center.latitude = _runway->latitude();
runway.center.longitude = _runway->longitude();
- runway.elevation = airport->getElevation();
+ runway.elevation = apt->elevation();
double half_length_m = _runway->lengthM() * 0.5;
runway.half_length = half_length_m * SG_METER_TO_NM;
unsigned int get_bank_angle_alerts ();
void update_bank_angle ();
- class AirportFilter : public FGAirportSearchFilter
+ class AirportFilter : public FGPositioned::Filter
{
public:
AirportFilter(Mode6Handler *s)
: self(s) {}
- virtual bool pass(FGAirport *a);
+ virtual bool pass(FGPositioned *a) const;
private:
Mode6Handler* self;
bool is_tcf ();
bool is_rfcf ();
- class AirportFilter : public FGAirportSearchFilter
+ class AirportFilter : public FGPositioned::Filter
{
public:
AirportFilter(MK_VIII *device)
: mk(device) {}
- virtual bool pass(FGAirport *a);
+ virtual bool pass(FGPositioned *a) const;
private:
MK_VIII* mk;
#undef HASHSET
}
-
-class airport_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->isAirport(); }
-} airport;
-class seaport_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->isSeaport(); }
-} seaport;
-class heliport_filter : public FGAirportSearchFilter {
- virtual bool pass(FGAirport *a) { return a->isHeliport(); }
-} heliport;
+class AirportInfoFilter : public FGPositioned::Filter
+{
+public:
+ AirportInfoFilter() :
+ type(FGPositioned::AIRPORT)
+ { }
+
+ virtual bool pass(FGPositioned* aPos) const
+ {
+ return (aPos->type() == type);
+ }
+
+ FGPositioned::Type type;
+};
// Returns data hash for particular or nearest airport of a <type>, or nil
-// on error. Only one side of each runway is contained.
+// on error.
//
// airportinfo(<id>); e.g. "KSFO"
// airportinfo(<type>); type := ("airport"|"seaport"|"heliport")
{
static SGConstPropertyNode_ptr latn = fgGetNode("/position/latitude-deg", true);
static SGConstPropertyNode_ptr lonn = fgGetNode("/position/longitude-deg", true);
- double lat, lon;
-
- FGAirportList *aptlst = globals->get_airports();
- FGAirport *apt;
+ SGGeod pos;
+ FGPositionedRef ref;
+
if(argc >= 2 && naIsNum(args[0]) && naIsNum(args[1])) {
- lat = args[0].num;
- lon = args[1].num;
+ pos = SGGeod::fromDeg(args[1].num, args[0].num);
args += 2;
argc -= 2;
} else {
- lat = latn->getDoubleValue();
- lon = lonn->getDoubleValue();
+ pos = SGGeod::fromDeg(lonn->getDoubleValue(), latn->getDoubleValue());
}
- double maxRange = 360.0; // expose this? or pick a smaller value?
+ double maxRange = 10000.0; // expose this? or pick a smaller value?
+
+ AirportInfoFilter filter; // defaults to airports only
if(argc == 0) {
- apt = aptlst->search(lon, lat, maxRange, airport);
+ // fine, just fall through and use AIRPORT
} else if(argc == 1 && naIsString(args[0])) {
const char *s = naStr_data(args[0]);
- if(!strcmp(s, "airport")) apt = aptlst->search(lon, lat, maxRange, airport);
- else if(!strcmp(s, "seaport")) apt = aptlst->search(lon, lat, maxRange, seaport);
- else if(!strcmp(s, "heliport")) apt = aptlst->search(lon, lat, maxRange, heliport);
- else apt = aptlst->search(s);
+ if (!strcmp(s, "airport")) filter.type = FGPositioned::AIRPORT;
+ else if(!strcmp(s, "seaport")) filter.type = FGPositioned::SEAPORT;
+ else if(!strcmp(s, "heliport")) filter.type = FGPositioned::HELIPORT;
+ else {
+ // user provided an <id>, hopefully
+ ref = globals->get_airports()->search(s);
+ if (!ref) {
+ naRuntimeError(c, "airportinfo() couldn't find airport:%s", s);
+ return naNil();
+ }
+ }
} else {
naRuntimeError(c, "airportinfo() with invalid function arguments");
return naNil();
}
- if(!apt) return naNil();
-
- string id = apt->getId();
- string name = apt->getName();
+
+ if (!ref) {
+ ref = FGPositioned::findClosest(pos, maxRange, &filter);
+ }
+
+ if(!ref) return naNil();
+ FGAirport *apt = static_cast<FGAirport*>(ref.ptr());
+
+ string id = apt->ident();
+ string name = apt->name();
// set runway hash
naRef rwys = naNewHash(c);