1
0
Fork 0

David Luff:

Attached is a patch to the airport data storage that I would like committed
after review if acceptable.  Currently the storage of airports mapped by ID
is by locally created objects - about 12 Meg or so created on the stack if
I am not mistaken.  I've changed this to creating the airports on the heap,
and storing pointers to them - see FGAirportList.add(...) in
src/Airports/simple.cxx.  I believe that this is probably better practice,
and it's certainly cured some strange problems I was seeing when accessing
the airport data with some gps unit code.  Changes resulting from this have
cascaded through a few files which access the data - 11 files are modified
in all.  Melchior and Durk - you might want to test this and shout if there
are problems since the metar and traffic code are probably the biggest
users of the airport data.  I've also added a fuzzy search function that
returns the next matching airport code in ASCII sequence in order to
support gps units that have autocompletion of partially entered codes.

More generally, the simple airport class seems to have grown a lot with the
fairly recent addition of the parking, runway preference and schedule time
code.  It is no longer just an encapsulation of the global airport data
file, and has grown to 552 bytes in size when unpopulated (about 1/2 a K!).
 My personal opinion is that we should look to just store the basic data in
apt.dat for all global airports in a simple airport class, plus globally
needed data (metar available?), and then have the traffic, AI and ATC
subsystems create more advanced airports for themselves as needed in the
area of interest.  Once a significant number of airports worldwide have
ground networks and parking defined, it will be impractical and unnecessary
to store them all in memory.  That's just a thought for the future though.
This commit is contained in:
curt 2005-09-20 20:26:57 +00:00
parent c9d90d13ed
commit 0bb1494452
11 changed files with 181 additions and 154 deletions

View file

@ -292,22 +292,22 @@ double GetAngleDiff_deg( const double &a1, const double &a2) {
// in fg_init.cxx, and are just here temporarily until some rationalisation occurs.
// find basic airport location info from airport database
bool dclFindAirportID( const string& id, FGAirport *a ) {
FGAirport result;
const FGAirport* result;
if ( id.length() ) {
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
result = globals->get_airports()->search( id );
if ( result.getId().empty() ) {
result = globals->get_airports()->search(id);
if ( result == NULL ) {
SG_LOG( SG_GENERAL, SG_WARN,
"Failed to find " << id << " in basic.dat.gz" );
"Failed to find " << id << " in apt.dat.gz" );
return false;
}
} else {
return false;
}
*a = result;
*a = *result;
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("

View file

@ -243,10 +243,8 @@ bool fgAirportDBLoad( FGAirportList *airports, FGRunwayList *runways,
if ( ident == "#" || ident == "//" ) {
metar_in >> skipeol;
} else {
const FGAirport &a = airports->search( ident );
if ( a.getId() == ident ) {
airports->has_metar( ident );
}
const FGAirport* a = airports->search( ident );
if ( a ) airports->has_metar( ident );
}
}

View file

@ -1170,19 +1170,21 @@ FGAirportList::FGAirportList()
ulCloseDir(d);
}
FGAirportList::~FGAirportList( void ) {
for(unsigned int i = 0; i < airports_array.size(); ++i) {
delete airports_array[i];
}
}
// add an entry to the list
void FGAirportList::add( const string id, const double longitude,
const double latitude, const double elevation,
const string name, const bool has_metar )
{
FGRunwayPreference rwyPrefs;
FGAirport a(id, longitude, latitude, elevation, name, has_metar);
//a._id = id;
//a._longitude = longitude;
//a._latitude = latitude;
//a._elevation = elevation;
//a._name = name;
//a._has_metar = has_metar;
FGRunwayPreference rwyPrefs;
FGAirport* a = new FGAirport(id, longitude, latitude, elevation, name, has_metar);
SGPath parkpath( globals->get_fg_root() );
parkpath.append( "/Airports/AI/" );
parkpath.append(id);
@ -1194,52 +1196,63 @@ void FGAirportList::add( const string id, const double longitude,
rwyPrefPath.append("rwyuse.xml");
if (ai_dirs.find(id.c_str()) != ai_dirs.end()
&& parkpath.exists())
{
try {
readXML(parkpath.str(),a);
}
catch (const sg_exception &e) {
//cerr << "unable to read " << parkpath.str() << endl;
}
}
{
try {
readXML(parkpath.str(),*a);
}
catch (const sg_exception &e) {
//cerr << "unable to read " << parkpath.str() << endl;
}
}
if (ai_dirs.find(id.c_str()) != ai_dirs.end()
&& rwyPrefPath.exists())
{
try {
readXML(rwyPrefPath.str(), rwyPrefs);
a.setRwyUse(rwyPrefs);
}
catch (const sg_exception &e) {
//cerr << "unable to read " << rwyPrefPath.str() << endl;
//exit(1);
}
}
{
try {
readXML(rwyPrefPath.str(), rwyPrefs);
a->setRwyUse(rwyPrefs);
}
catch (const sg_exception &e) {
//cerr << "unable to read " << rwyPrefPath.str() << endl;
//exit(1);
}
}
airports_by_id[a.getId()] = a;
airports_by_id[a->getId()] = a;
// try and read in an auxilary file
airports_array.push_back( &airports_by_id[a.getId()] );
airports_array.push_back( a );
SG_LOG( SG_GENERAL, SG_BULK, "Adding " << id << " pos = " << longitude
<< ", " << latitude << " elev = " << elevation );
}
// search for the specified id
FGAirport FGAirportList::search( const string& id) {
return airports_by_id[id];
FGAirport* FGAirportList::search( const string& id) {
airport_map_iterator itr = airports_by_id.find(id);
return(itr == airports_by_id.end() ? NULL : itr->second);
}
// search for the specified id and return a pointer
FGAirport* FGAirportList::search( const string& id, FGAirport *result) {
FGAirport* retval = airports_by_id[id].getAddress();
//cerr << "Returning Airport of string " << id << " results in " << retval->getId();
return retval;
// search for first subsequent alphabetically to supplied id
const FGAirport* FGAirportList::findFirstById( const string& id, bool exact ) {
airport_map_iterator itr;
if(exact) {
itr = airports_by_id.find(id);
} else {
itr = airports_by_id.lower_bound(id);
}
if(itr == airports_by_id.end()) {
return(NULL);
} else {
return(itr->second);
}
}
// search for the airport nearest the specified position
FGAirport FGAirportList::search( double lon_deg, double lat_deg,
FGAirport* FGAirportList::search( double lon_deg, double lat_deg,
bool with_metar ) {
int closest = 0;
int closest = -1;
double min_dist = 360.0;
unsigned int i;
for ( i = 0; i < airports_array.size(); ++i ) {
@ -1254,23 +1267,23 @@ FGAirport FGAirportList::search( double lon_deg, double lat_deg,
}
}
return *airports_array[closest];
return ( closest > -1 ? airports_array[closest] : NULL );
}
// Destructor
FGAirportList::~FGAirportList( void ) {
}
int
FGAirportList::size () const
{
return airports_array.size();
}
const FGAirport *FGAirportList::getAirport( int index ) const
const FGAirport *FGAirportList::getAirport( unsigned int index ) const
{
return airports_array[index];
if(index < airports_array.size()) {
return(airports_array[index]);
} else {
return(NULL);
}
}
@ -1278,7 +1291,9 @@ const FGAirport *FGAirportList::getAirport( int index ) const
* Mark the specified airport record as not having metar
*/
void FGAirportList::no_metar( const string &id ) {
airports_by_id[id].setMetar(false);
if(airports_by_id.find(id) != airports_by_id.end()) {
airports_by_id[id]->setMetar(false);
}
}
@ -1286,5 +1301,7 @@ void FGAirportList::no_metar( const string &id ) {
* Mark the specified airport record as (yes) having metar
*/
void FGAirportList::has_metar( const string &id ) {
airports_by_id[id].setMetar(true);
if(airports_by_id.find(id) != airports_by_id.end()) {
airports_by_id[id]->setMetar(true);
}
}

View file

@ -236,16 +236,16 @@ typedef vector<FGParking>::const_iterator FGParkingVecConstIterator;
class FGAirport : public XMLVisitor{
private:
string _id;
double _longitude;
double _latitude;
double _elevation;
double _longitude; // degrees
double _latitude; // degrees
double _elevation; // ft
string _code; // depricated and can be removed
string _name;
bool _has_metar;
FGParkingVec parkings;
FGRunwayPreference rwyPrefs;
time_t lastUpdate;
time_t lastUpdate;
string prevTrafficType;
stringVec landing;
stringVec takeoff;
@ -270,13 +270,15 @@ public:
FGParking *getParking(int i); // { if (i < parkings.size()) return parkings[i]; else return 0;};
void releaseParking(int id);
string getParkingName(int i);
const string getId() const { return _id;};
string getId() const { return _id;};
const string &getName() const { return _name;};
FGAirport *getAddress() { return this; };
double getLongitude() { return _longitude;};
double getLatitude() { return _latitude; };
double getElevation() { return _elevation;};
bool getMetar() { return _has_metar;};
// Returns degrees
double getLongitude() const { return _longitude;};
// Returns degrees
double getLatitude() const { return _latitude; };
// Returns ft
double getElevation() const { return _elevation;};
bool getMetar() const { return _has_metar;};
void setId(string id) { _id = id;};
@ -295,7 +297,7 @@ public:
virtual void error (const char * message, int line, int column);
};
typedef map < string, FGAirport > airport_map;
typedef map < string, FGAirport* > airport_map;
typedef airport_map::iterator airport_map_iterator;
typedef airport_map::const_iterator const_airport_map_iterator;
@ -323,31 +325,33 @@ public:
const double elevation, const string name, const bool has_metar );
// search for the specified id.
// Returns true if successful, otherwise returns false.
// On success, airport data is returned thru "airport" pointer.
// "airport" is not changed if "apt" is not found.
FGAirport search( const string& id );
// Returns NULL if unsucessfull.
FGAirport* search( const string& id );
// Search for the next airport in ASCII sequence to the supplied id.
// eg. id = "KDC" or "KDCA" would both return "KDCA".
// If exact = true then only exact matches are returned.
// NOTE: Numbers come prior to A-Z in ASCII sequence so id = "LD" would return "LD57", not "LDDP"
// Implementation assumes airport codes are unique.
// Returns NULL if unsucessfull.
const FGAirport* findFirstById( const string& id, bool exact = false );
// 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.) If with_metar is true, then only
// return station id's marked as having metar data.
FGAirport search( double lon_deg, double lat_deg, bool with_metar );
// search and return a pointer;
FGAirport* search( const string& id, FGAirport *result);
// Returns NULL if fails (unlikely unless none have metar and with_metar spec'd!)
FGAirport* search( double lon_deg, double lat_deg, bool with_metar );
/**
* Return the number of airports in the list.
*/
int size() const;
/**
* Return a specific airport, by position.
*/
const FGAirport *getAirport( int index ) const;
const FGAirport *getAirport( unsigned int index ) const;
/**
* Mark the specified airport record as not having metar

View file

@ -402,26 +402,30 @@ FGMetarEnvironmentCtrl::init ()
metar_max_age->setLongValue(60 * 24 * 7);
while ( !found_metar && (_error_count < 3) ) {
FGAirport a = globals->get_airports()
->search( longitude->getDoubleValue(),
latitude->getDoubleValue(),
true );
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() );
const FGAirport* a = globals->get_airports()
->search( longitude->getDoubleValue(),
latitude->getDoubleValue(),
true );
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() );
}
}
}
metar_max_age->setLongValue(max_age);
@ -460,23 +464,29 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
// if time for a new search request, push it onto the request
// queue
if ( search_elapsed > search_interval_sec ) {
FGAirport a = globals->get_airports()
->search( longitude->getDoubleValue(),
latitude->getDoubleValue(),
true );
if ( last_apt.getId() != a.getId()
|| fetch_elapsed > same_station_interval_sec )
{
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = " << a.getId());
request_queue.push( a.getId() );
last_apt = a;
_icao = a.getId();
search_elapsed = 0.0;
fetch_elapsed = 0.0;
const FGAirport* a = globals->get_airports()
->search( longitude->getDoubleValue(),
latitude->getDoubleValue(),
true );
if ( a ) {
if ( last_apt.getId() != a->getId()
|| fetch_elapsed > same_station_interval_sec )
{
SG_LOG( SG_GENERAL, SG_INFO, "closest station w/ metar = "
<< a->getId());
request_queue.push( a->getId() );
last_apt = *a;
_icao = a->getId();
search_elapsed = 0.0;
fetch_elapsed = 0.0;
} else {
search_elapsed = 0.0;
SG_LOG( SG_GENERAL, SG_INFO, "same station, waiting = "
<< same_station_interval_sec - fetch_elapsed );
}
} else {
search_elapsed = 0.0;
SG_LOG( SG_GENERAL, SG_INFO, "same station, waiting = "
<< same_station_interval_sec - fetch_elapsed );
SG_LOG( SG_GENERAL, SG_WARN,
"Unable to find any airports with metar" );
}
}
@ -541,8 +551,10 @@ FGMetarEnvironmentCtrl::fetch_data( const string &icao )
}
// fetch station elevation if exists
FGAirport a = globals->get_airports()->search( icao );
station_elevation_ft = a.getElevation();
const FGAirport* a = globals->get_airports()->search( icao );
if ( a ) {
station_elevation_ft = a->getElevation();
}
// fetch current metar data
try {

View file

@ -401,8 +401,8 @@ void FGClouds::buildScenario( string scenario ) {
if( station == "XXXX" )
station_elevation_ft = fgGetDouble("/position/ground-elev-m", 0.0);
else {
FGAirport a = globals->get_airports()->search( station );
station_elevation_ft = a.getElevation();
const FGAirport* a = globals->get_airports()->search( station );
station_elevation_ft = (a ? a->getElevation() : 0.0);
}
for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) {

View file

@ -15,7 +15,7 @@ AirportList::AirportList (int x, int y, int width, int height)
_nAirports = _airports->size();
_content = new char *[_nAirports+1];
for (int i = 0; i < _nAirports; i++) {
for (unsigned int i = 0; i < _nAirports; i++) {
const FGAirport *airport = _airports->getAirport(i);
snprintf(buf, 1023, "%s %s",
airport->getId().c_str(),
@ -33,7 +33,7 @@ AirportList::AirportList (int x, int y, int width, int height)
AirportList::~AirportList ()
{
for (int i = 0; i < _nAirports; i++) {
for (unsigned int i = 0; i < _nAirports; i++) {
delete _content[i];
_content[i] = 0;
}

View file

@ -340,15 +340,15 @@ GPS::update (double delta_time_sec)
// If the get-nearest-airport-node is true.
// Get the nearest airport, and set it as waypoint 1.
if (_get_nearest_airport_node->getBoolValue()) {
FGAirport a;
//cout << "Airport found" << endl;
a = globals->get_airports()->search(longitude_deg, latitude_deg, false);
_wp1_ID_node->setStringValue(a.getId().c_str());
wp1_longitude_deg = a.getLongitude();
wp1_latitude_deg = a.getLatitude();
_wp1_name_node->setStringValue(a.getName().c_str());
_get_nearest_airport_node->setBoolValue(false);
_last_wp1_ID = wp1_ID = a.getId().c_str();
const FGAirport* a = globals->get_airports()->search(longitude_deg, latitude_deg, false);
if(a) {
_wp1_ID_node->setStringValue(a->getId().c_str());
wp1_longitude_deg = a->getLongitude();
wp1_latitude_deg = a->getLatitude();
_wp1_name_node->setStringValue(a->getName().c_str());
_get_nearest_airport_node->setBoolValue(false);
_last_wp1_ID = wp1_ID = a->getId().c_str();
}
}
// If the waypoint 0 ID has changed, try to find the new ID
@ -357,13 +357,11 @@ GPS::update (double delta_time_sec)
string waypont_type =
_wp0_waypoint_type_node->getStringValue();
if (waypont_type == "airport") {
FGAirport a;
a = globals->get_airports()->search( wp0_ID );
if ( a.getId() == wp0_ID ) {
//cout << "Airport found" << endl;
wp0_longitude_deg = a.getLongitude();
wp0_latitude_deg = a.getLatitude();
_wp0_name_node->setStringValue(a.getName().c_str());
const FGAirport* a = globals->get_airports()->search( wp0_ID );
if ( a ) {
wp0_longitude_deg = a->getLongitude();
wp0_latitude_deg = a->getLatitude();
_wp0_name_node->setStringValue(a->getName().c_str());
}
}
else if (waypont_type == "nav") {
@ -396,13 +394,11 @@ GPS::update (double delta_time_sec)
string waypont_type =
_wp1_waypoint_type_node->getStringValue();
if (waypont_type == "airport") {
FGAirport a;
a = globals->get_airports()->search( wp1_ID );
if ( a.getId() == wp1_ID ) {
//cout << "Airport found" << endl;
wp1_longitude_deg = a.getLongitude();
wp1_latitude_deg = a.getLatitude();
_wp1_name_node->setStringValue(a.getName().c_str());
const FGAirport* a = globals->get_airports()->search( wp1_ID );
if ( a ) {
wp1_longitude_deg = a->getLongitude();
wp1_latitude_deg = a->getLatitude();
_wp1_name_node->setStringValue(a->getName().c_str());
}
}
else if (waypont_type == "nav") {

View file

@ -620,22 +620,22 @@ bool fgInitConfig ( int argc, char **argv ) {
// find basic airport location info from airport database
bool fgFindAirportID( const string& id, FGAirport *a ) {
FGAirport result;
const FGAirport* result;
if ( id.length() ) {
SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
result = globals->get_airports()->search( id );
if ( result.getId().empty() ) {
if ( result == NULL ) {
SG_LOG( SG_GENERAL, SG_ALERT,
"Failed to find " << id << " in basic.dat.gz" );
"Failed to find " << id << " in apt.dat.gz" );
return false;
}
} else {
return false;
}
*a = result;
*a = *result;
SG_LOG( SG_GENERAL, SG_INFO,
"Position for " << id << " is ("

View file

@ -95,9 +95,9 @@ bool fgNavDBInit( FGAirportList *airports,
if ( fabs(r->get_elev_ft()) < 0.01 && r->get_apt_id().length() ) {
// cout << r->get_type() << " " << r->get_apt_id() << " zero elev"
// << endl;
FGAirport a = airports->search( r->get_apt_id() );
if ( a.getId() == r->get_apt_id() ) {
r->set_elev_ft( a.getElevation() );
const FGAirport* a = airports->search( r->get_apt_id() );
if ( a ) {
r->set_elev_ft( a->getElevation() );
// cout << " setting to " << a.elevation << endl;
}
}

View file

@ -257,14 +257,14 @@ FGAirport * FGScheduledFlight::getArrivalAirport ()
bool FGScheduledFlight::initializeAirports()
{
//cerr << "Initializing using : " << depId << " " << arrId << endl;
departurePort = globals->get_airports()->search( depId, departurePort );
if(departurePort->getId().empty())
departurePort = globals->get_airports()->search(depId);
if(departurePort == NULL)
{
cerr << "Could not find " << depId << endl;
return false;
}
arrivalPort = globals->get_airports()->search(arrId, arrivalPort);
if(arrivalPort->getId().empty())
arrivalPort = globals->get_airports()->search(arrId);
if(arrivalPort == NULL)
{
cerr << "Could not find " << arrId << endl;
return false;