James Turner:
This is a little intrusive on the KLN89 code, but avoids the wasteful cloning of the airports, runways and navaids which current happens, and also combines the ugly string ordering code.
This commit is contained in:
parent
8d5de1659c
commit
289f2f5f0d
7 changed files with 274 additions and 665 deletions
src
Airports
Instrumentation
Navaids
|
@ -321,23 +321,41 @@ FGAirport* FGAirportList::search( const string& id)
|
|||
return (itr == airports_by_id.end() ? NULL : itr->second);
|
||||
}
|
||||
|
||||
// wrap an FGIdentOrdering in an STL-compatible functor. not the most
|
||||
// efficent / pretty thing in the world, but avoids template nastiness in the
|
||||
// headers, and we're only doing O(log(N)) comparisoms per search
|
||||
class orderingFunctor
|
||||
{
|
||||
public:
|
||||
orderingFunctor(FGIdentOrdering* aOrder) :
|
||||
mOrdering(aOrder)
|
||||
{ assert(aOrder); }
|
||||
|
||||
// search for first subsequent alphabetically to supplied id
|
||||
const FGAirport* FGAirportList::findFirstById( const string& id, bool exact )
|
||||
bool operator()(const airport_map::value_type& aA, const std::string& aB) const
|
||||
{
|
||||
return mOrdering->compare(aA.first,aB);
|
||||
}
|
||||
|
||||
private:
|
||||
FGIdentOrdering* mOrdering;
|
||||
};
|
||||
|
||||
const FGAirport* FGAirportList::findFirstById(const std::string& aIdent, FGIdentOrdering* aOrder)
|
||||
{
|
||||
airport_map_iterator itr;
|
||||
if (exact) {
|
||||
itr = airports_by_id.find(id);
|
||||
if (aOrder) {
|
||||
orderingFunctor func(aOrder);
|
||||
itr = std::lower_bound(airports_by_id.begin(),airports_by_id.end(), aIdent, func);
|
||||
} else {
|
||||
itr = airports_by_id.lower_bound(id);
|
||||
itr = airports_by_id.lower_bound(aIdent);
|
||||
}
|
||||
if (itr == airports_by_id.end()) {
|
||||
return (NULL);
|
||||
} else {
|
||||
return (itr->second);
|
||||
}
|
||||
}
|
||||
|
||||
if (itr == airports_by_id.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// search for the airport nearest the specified position
|
||||
FGAirport* FGAirportList::search(double lon_deg, double lat_deg, double max_range)
|
||||
|
@ -354,6 +372,7 @@ FGAirport* FGAirportList::search(double lon_deg, double lat_deg,
|
|||
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;
|
||||
|
|
|
@ -117,6 +117,14 @@ public:
|
|||
virtual bool pass(FGAirport*) { return true; }
|
||||
};
|
||||
|
||||
class FGIdentOrdering {
|
||||
public:
|
||||
virtual ~FGIdentOrdering()
|
||||
{ ; }
|
||||
|
||||
virtual bool compare(const std::string& aA, const std::string& aB) const
|
||||
{ return aA < aB; }
|
||||
};
|
||||
|
||||
typedef std::map < std::string, FGAirport* > airport_map;
|
||||
typedef airport_map::iterator airport_map_iterator;
|
||||
|
@ -152,11 +160,11 @@ public:
|
|||
|
||||
// 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"
|
||||
// optional ordering can make letters come before numbers
|
||||
// Implementation assumes airport codes are unique.
|
||||
// Returns NULL if unsucessfull.
|
||||
const FGAirport* findFirstById( const std::string& id, bool exact = false );
|
||||
const FGAirport* findFirstById(const std::string& aIdent, FGIdentOrdering* aOrder = NULL);
|
||||
|
||||
// search for the airport closest to the specified position
|
||||
// (currently a linear inefficient search so it's probably not
|
||||
|
|
|
@ -940,21 +940,21 @@ void KLN89FplPage::Knob2Left1() {
|
|||
_bEntWp = true;
|
||||
_fp0SelWpId.clear(); // Waypoints don't become the DTO default whilst being entered.
|
||||
|
||||
bool multi;
|
||||
const GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1), multi, false);
|
||||
GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1));
|
||||
if(NULL == wp) {
|
||||
// no-op
|
||||
} else {
|
||||
if(_entWp == NULL) {
|
||||
_entWp = new GPSWaypoint;
|
||||
if(_entWp) {
|
||||
*_entWp = *wp; // copy
|
||||
delete wp;
|
||||
} else {
|
||||
_entWp = wp;
|
||||
if(_fplPos + (_uLinePos - 4) >= _kln89->_flightPlans[_subPage]->waypoints.size()) {
|
||||
_kln89->_flightPlans[_subPage]->waypoints.push_back(_entWp);
|
||||
} else {
|
||||
_kln89->_flightPlans[_subPage]->waypoints.insert(_kln89->_flightPlans[_subPage]->waypoints.begin()+(_fplPos + (_uLinePos - 4)), _entWp);
|
||||
}
|
||||
}
|
||||
// copy
|
||||
*_entWp = *wp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1013,21 +1013,21 @@ void KLN89FplPage::Knob2Right1() {
|
|||
_bEntWp = true;
|
||||
_fp0SelWpId.clear(); // Waypoints don't become the DTO default whilst being entered.
|
||||
|
||||
bool multi;
|
||||
const GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1), multi, false);
|
||||
GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1));
|
||||
if(NULL == wp) {
|
||||
// no-op
|
||||
} else {
|
||||
if(_entWp == NULL) {
|
||||
_entWp = new GPSWaypoint;
|
||||
if(_entWp) {
|
||||
*_entWp = *wp; // copy
|
||||
delete wp;
|
||||
} else {
|
||||
_entWp = wp;
|
||||
if(_fplPos + (_uLinePos - 4) >= _kln89->_flightPlans[_subPage]->waypoints.size()) {
|
||||
_kln89->_flightPlans[_subPage]->waypoints.push_back(_entWp);
|
||||
} else {
|
||||
_kln89->_flightPlans[_subPage]->waypoints.insert(_kln89->_flightPlans[_subPage]->waypoints.begin()+(_fplPos + (_uLinePos - 4)), _entWp);
|
||||
}
|
||||
}
|
||||
// copy
|
||||
*_entWp = *wp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,15 @@ GPSWaypoint::GPSWaypoint() {
|
|||
appType = GPS_APP_NONE;
|
||||
}
|
||||
|
||||
GPSWaypoint::GPSWaypoint(const std::string& aIdent, float aLat, float aLon, GPSWpType aType) :
|
||||
id(aIdent),
|
||||
lat(aLat),
|
||||
lon(aLon),
|
||||
type(aType),
|
||||
appType(GPS_APP_NONE)
|
||||
{
|
||||
}
|
||||
|
||||
GPSWaypoint::~GPSWaypoint() {}
|
||||
|
||||
string GPSWaypoint::GetAprId() {
|
||||
|
@ -129,6 +138,33 @@ string GPSWaypoint::GetAprId() {
|
|||
else return(id);
|
||||
}
|
||||
|
||||
GPSWaypoint* GPSWaypoint::createFromFix(const FGFix* aFix)
|
||||
{
|
||||
assert(aFix);
|
||||
return new GPSWaypoint(aFix->get_ident(),
|
||||
aFix->get_lat() * SG_DEGREES_TO_RADIANS,
|
||||
aFix->get_lon() * SG_DEGREES_TO_RADIANS,
|
||||
GPS_WP_INT);
|
||||
}
|
||||
|
||||
GPSWaypoint* GPSWaypoint::createFromNav(const FGNavRecord* aNav)
|
||||
{
|
||||
assert(aNav);
|
||||
return new GPSWaypoint(aNav->get_ident(),
|
||||
aNav->get_lat() * SG_DEGREES_TO_RADIANS,
|
||||
aNav->get_lon() * SG_DEGREES_TO_RADIANS,
|
||||
(aNav->get_fg_type() == FG_NAV_VOR ? GPS_WP_VOR : GPS_WP_NDB));
|
||||
}
|
||||
|
||||
GPSWaypoint* GPSWaypoint::createFromAirport(const FGAirport* aApt)
|
||||
{
|
||||
assert(aApt);
|
||||
return new GPSWaypoint(aApt->getId(),
|
||||
aApt->getLatitude() * SG_DEGREES_TO_RADIANS,
|
||||
aApt->getLongitude() * SG_DEGREES_TO_RADIANS,
|
||||
GPS_WP_APT);
|
||||
}
|
||||
|
||||
ostream& operator << (ostream& os, GPSAppWpType type) {
|
||||
switch(type) {
|
||||
case(GPS_IAF): return(os << "IAF");
|
||||
|
@ -301,11 +337,6 @@ DCLGPS::DCLGPS(RenderArea2D* instrument) {
|
|||
|
||||
DCLGPS::~DCLGPS() {
|
||||
delete _time;
|
||||
for(gps_waypoint_map_iterator itr = _waypoints.begin(); itr != _waypoints.end(); ++itr) {
|
||||
for(unsigned int i = 0; i < (*itr).second.size(); ++i) {
|
||||
delete(((*itr).second)[i]);
|
||||
}
|
||||
}
|
||||
delete _approachFP; // Don't need to delete the waypoints inside since they point to
|
||||
// the waypoints in the approach database.
|
||||
// TODO - may need to delete the approach database!!
|
||||
|
@ -330,331 +361,8 @@ void DCLGPS::init() {
|
|||
globals->get_commands()->addCommand("kln89_knob2left1", do_kln89_knob2left1);
|
||||
globals->get_commands()->addCommand("kln89_knob2right1", do_kln89_knob2right1);
|
||||
|
||||
// Build the GPS-specific databases.
|
||||
// TODO - consider splitting into real life GPS database regions - eg Americas, Europe etc.
|
||||
// Note that this needs to run after FG's airport and nav databases are up and running
|
||||
_waypoints.clear();
|
||||
const airport_list* apts = globals->get_airports()->getAirportList();
|
||||
for(unsigned int i = 0; i < apts->size(); ++i) {
|
||||
FGAirport* a = (*apts)[i];
|
||||
GPSWaypoint* w = new GPSWaypoint;
|
||||
w->id = a->getId();
|
||||
w->lat = a->getLatitude() * SG_DEGREES_TO_RADIANS;
|
||||
w->lon = a->getLongitude() * SG_DEGREES_TO_RADIANS;
|
||||
w->type = GPS_WP_APT;
|
||||
gps_waypoint_map_iterator wtr = _waypoints.find(a->getId());
|
||||
if(wtr == _waypoints.end()) {
|
||||
gps_waypoint_array arr;
|
||||
arr.push_back(w);
|
||||
_waypoints[w->id] = arr;
|
||||
} else {
|
||||
wtr->second.push_back(w);
|
||||
}
|
||||
}
|
||||
nav_map_type navs = globals->get_navlist()->get_navaids();
|
||||
for(nav_map_iterator itr = navs.begin(); itr != navs.end(); ++itr) {
|
||||
nav_list_type nlst = itr->second;
|
||||
for(unsigned int i = 0; i < nlst.size(); ++i) {
|
||||
FGNavRecord* n = nlst[i];
|
||||
if(n->get_fg_type() == FG_NAV_VOR || n->get_fg_type() == FG_NAV_NDB) { // We don't bother with ILS etc.
|
||||
GPSWaypoint* w = new GPSWaypoint;
|
||||
w->id = n->get_ident();
|
||||
w->lat = n->get_lat() * SG_DEGREES_TO_RADIANS;
|
||||
w->lon = n->get_lon() * SG_DEGREES_TO_RADIANS;
|
||||
w->type = (n->get_fg_type() == FG_NAV_VOR ? GPS_WP_VOR : GPS_WP_NDB);
|
||||
gps_waypoint_map_iterator wtr = _waypoints.find(n->get_ident());
|
||||
if(wtr == _waypoints.end()) {
|
||||
gps_waypoint_array arr;
|
||||
arr.push_back(w);
|
||||
_waypoints[w->id] = arr;
|
||||
} else {
|
||||
wtr->second.push_back(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const fix_map_type* fixes = globals->get_fixlist()->getFixList();
|
||||
for(fix_map_const_iterator itr = fixes->begin(); itr != fixes->end(); ++itr) {
|
||||
FGFix f = itr->second;
|
||||
GPSWaypoint* w = new GPSWaypoint;
|
||||
w->id = f.get_ident();
|
||||
w->lat = f.get_lat() * SG_DEGREES_TO_RADIANS;
|
||||
w->lon = f.get_lon() * SG_DEGREES_TO_RADIANS;
|
||||
w->type = GPS_WP_INT;
|
||||
gps_waypoint_map_iterator wtr = _waypoints.find(f.get_ident());
|
||||
if(wtr == _waypoints.end()) {
|
||||
gps_waypoint_array arr;
|
||||
arr.push_back(w);
|
||||
_waypoints[w->id] = arr;
|
||||
} else {
|
||||
wtr->second.push_back(w);
|
||||
}
|
||||
}
|
||||
// TODO - add USR waypoints as well.
|
||||
|
||||
// Not sure if this should be here, but OK for now.
|
||||
CreateDefaultFlightPlans();
|
||||
|
||||
// Hack - hardwire some instrument approaches for testing.
|
||||
// TODO - read these from file - either all at startup or as needed.
|
||||
FGNPIAP* iap = new FGNPIAP;
|
||||
iap->_id = "KHWD";
|
||||
iap->_name = "VOR/DME OR GPS-B";
|
||||
iap->_abbrev = "VOR/D";
|
||||
iap->_rwyStr = "B";
|
||||
iap->_IAF.clear();
|
||||
iap->_IAP.clear();
|
||||
iap->_MAP.clear();
|
||||
// -------
|
||||
GPSWaypoint* wp = new GPSWaypoint;
|
||||
wp->id = "SUNOL";
|
||||
bool multi;
|
||||
// Nasty using the find any function here, but it saves converting data from FGFix etc.
|
||||
const GPSWaypoint* fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "MABRY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "IMPLY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAP;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "DECOT";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_FAF;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "MAPVV";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAP;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "OAK";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAHP;
|
||||
iap->_MAP.push_back(wp);
|
||||
// -------
|
||||
_np_iap[iap->_id].push_back(iap);
|
||||
// -----------------------
|
||||
// -----------------------
|
||||
iap = new FGNPIAP;
|
||||
iap->_id = "KHWD";
|
||||
iap->_name = "VOR OR GPS-A";
|
||||
iap->_abbrev = "VOR-";
|
||||
iap->_rwyStr = "A";
|
||||
iap->_IAF.clear();
|
||||
iap->_IAP.clear();
|
||||
iap->_MAP.clear();
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "SUNOL";
|
||||
// Nasty using the find any function here, but it saves converting data from FGFix etc.
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "MABRY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "IMPLY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAP;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "DECOT";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_FAF;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "MAPVV";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAP;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "OAK";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAHP;
|
||||
iap->_MAP.push_back(wp);
|
||||
// -------
|
||||
_np_iap[iap->_id].push_back(iap);
|
||||
// ------------------
|
||||
// ------------------
|
||||
/*
|
||||
// Ugh - don't load this one - the waypoints required aren't in fix.dat.gz - result: program crash!
|
||||
// TODO - make the IAP loader robust to absent waypoints.
|
||||
iap = new FGNPIAP;
|
||||
iap->_id = "KHWD";
|
||||
iap->_name = "GPS RWY 28L";
|
||||
iap->_abbrev = "GPS";
|
||||
iap->_rwyStr = "28L";
|
||||
iap->_IAF.clear();
|
||||
iap->_IAP.clear();
|
||||
iap->_MAP.clear();
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "SUNOL";
|
||||
// Nasty using the find any function here, but it saves converting data from FGFix etc.
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "SJC";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "JOCPI";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAP;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "SUDGE";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_FAF;
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "RW28L";
|
||||
wp->appType = GPS_MAP;
|
||||
if(wp->id.substr(0, 2) == "RW" && wp->appType == GPS_MAP) {
|
||||
// Assume that this is a missed-approach point based on the runway number
|
||||
// Get the runway threshold location etc
|
||||
} else {
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp == NULL) {
|
||||
cout << "Failed to find waypoint " << wp->id << " in database...\n";
|
||||
} else {
|
||||
*wp = *fp;
|
||||
}
|
||||
}
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "OAK";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAHP;
|
||||
iap->_MAP.push_back(wp);
|
||||
// -------
|
||||
_np_iap[iap->_id].push_back(iap);
|
||||
*/
|
||||
iap = new FGNPIAP;
|
||||
iap->_id = "C83";
|
||||
iap->_name = "GPS RWY 30";
|
||||
iap->_abbrev = "GPS";
|
||||
iap->_rwyStr = "30";
|
||||
iap->_IAF.clear();
|
||||
iap->_IAP.clear();
|
||||
iap->_MAP.clear();
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "MAXNI";
|
||||
// Nasty using the find any function here, but it saves converting data from FGFix etc.
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp) {
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
}
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "PATYY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp) {
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
}
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "TRACY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp) {
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAF;
|
||||
iap->_IAF.push_back(wp);
|
||||
}
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "TRACY";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp) {
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_IAP;
|
||||
iap->_IAP.push_back(wp);
|
||||
}
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "BABPI";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp) {
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_FAF;
|
||||
iap->_IAP.push_back(wp);
|
||||
}
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "AMOSY";
|
||||
wp->appType = GPS_MAP;
|
||||
if(wp->id.substr(0, 2) == "RW" && wp->appType == GPS_MAP) {
|
||||
// Assume that this is a missed-approach point based on the runway number
|
||||
// TODO: Get the runway threshold location etc
|
||||
cout << "TODO - implement missed-approach point based on rwy no.\n";
|
||||
} else {
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
if(fp == NULL) {
|
||||
cout << "Failed to find waypoint " << wp->id << " in database...\n";
|
||||
} else {
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAP;
|
||||
}
|
||||
}
|
||||
iap->_IAP.push_back(wp);
|
||||
// -------
|
||||
wp = new GPSWaypoint;
|
||||
wp->id = "HAIRE";
|
||||
fp = FindFirstById(wp->id, multi, true);
|
||||
*wp = *fp;
|
||||
wp->appType = GPS_MAHP;
|
||||
iap->_MAP.push_back(wp);
|
||||
// -------
|
||||
_np_iap[iap->_id].push_back(iap);
|
||||
}
|
||||
|
||||
void DCLGPS::bind() {
|
||||
|
@ -962,8 +670,7 @@ double DCLGPS::GetCDIDeflection() const {
|
|||
|
||||
void DCLGPS::DtoInitiate(const string& s) {
|
||||
//cout << "DtoInitiate, s = " << s << '\n';
|
||||
bool multi;
|
||||
const GPSWaypoint* wp = FindFirstById(s, multi, true);
|
||||
const GPSWaypoint* wp = FindFirstByExactId(s);
|
||||
if(wp) {
|
||||
//cout << "Waypoint found, starting dto operation!\n";
|
||||
_dto = true;
|
||||
|
@ -972,6 +679,7 @@ void DCLGPS::DtoInitiate(const string& s) {
|
|||
_fromWaypoint.lon = _gpsLon;
|
||||
_fromWaypoint.type = GPS_WP_VIRT;
|
||||
_fromWaypoint.id = "DTOWP";
|
||||
delete wp;
|
||||
} else {
|
||||
//cout << "Waypoint not found, ignoring dto request\n";
|
||||
// Should bring up the user waypoint page, but we're not implementing that yet.
|
||||
|
@ -1105,10 +813,10 @@ double DCLGPS::GetTimeToWaypoint(const string& id) {
|
|||
} else if(id == _activeWaypoint.id) {
|
||||
return(_eta);
|
||||
} else {
|
||||
bool multi;
|
||||
const GPSWaypoint* wp = FindFirstById(id, multi, true);
|
||||
const GPSWaypoint* wp = FindFirstByExactId(id);
|
||||
if(wp == NULL) return(-1.0);
|
||||
double distm = GetGreatCircleDistance(_gpsLat, _gpsLon, wp->lat, wp->lon);
|
||||
delete wp;
|
||||
return(distm / _groundSpeed_ms);
|
||||
}
|
||||
return(-1.0); // Hopefully we never get here!
|
||||
|
@ -1312,78 +1020,115 @@ void DCLGPS::CreateFlightPlan(GPSFlightPlan* fp, vector<string> ids, vector<GPSW
|
|||
|
||||
/***************************************/
|
||||
|
||||
const GPSWaypoint* DCLGPS::ActualFindFirstById(const string& id, bool exact) {
|
||||
gps_waypoint_map_const_iterator itr;
|
||||
if(exact) {
|
||||
itr = _waypoints.find(id);
|
||||
} else {
|
||||
itr = _waypoints.lower_bound(id);
|
||||
/**
|
||||
* STL functor for use with algorithms. This comapres strings according to
|
||||
* the KLN-89's notion of ordering, with digits after letters.
|
||||
* Also implements FGIdentOrdering so it can be passed into the various list
|
||||
* find helpers.
|
||||
*/
|
||||
|
||||
class stringOrderKLN89 : public FGIdentOrdering
|
||||
{
|
||||
public:
|
||||
bool operator()(const gps_waypoint_map::value_type& aA, const std::string& aB) const
|
||||
{
|
||||
return compare(aA.first, aB);
|
||||
}
|
||||
if(itr == _waypoints.end()) {
|
||||
return(NULL);
|
||||
} else {
|
||||
// TODO - don't just return the first one - either return all or the nearest one.
|
||||
return((itr->second)[0]);
|
||||
|
||||
bool operator()(const std::string& aS1, const std::string& aS2) const
|
||||
{
|
||||
return compare(aS1, aS2);
|
||||
}
|
||||
|
||||
virtual bool compare(const std::string& aS1, const std::string& aS2) const
|
||||
{
|
||||
if (aS1.empty()) return true;
|
||||
if (aS2.empty()) return false;
|
||||
|
||||
char* a = (char*) aS1.c_str();
|
||||
char* b = (char*) aS2.c_str();
|
||||
|
||||
for ( ; *a && *b; ++a, ++b) {
|
||||
if (*a == *b) continue;
|
||||
|
||||
bool aDigit = isdigit(*a);
|
||||
bool bDigit = isdigit(*b);
|
||||
|
||||
if (aDigit == bDigit) {
|
||||
return (*a < *b); // we already know they're not equal
|
||||
}
|
||||
|
||||
// digit-ness differs
|
||||
if (aDigit) return false; // s1 = KS9 goes *after* s2 = KSA
|
||||
assert(bDigit);
|
||||
return true; // s1 = KSF, s2 = KS5, s1 is indeed < s2
|
||||
}
|
||||
|
||||
if (*b) return true; // *a == 0, s2 is longer
|
||||
return false; // s1 is longer, or strings are equal
|
||||
}
|
||||
};
|
||||
|
||||
GPSWaypoint* DCLGPS::FindFirstById(const string& id) const
|
||||
{
|
||||
stringOrderKLN89 ordering;
|
||||
nav_list_type vors = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, false);
|
||||
nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, false);
|
||||
const FGFix* fix = globals->get_fixlist()->findFirstByIdent(id, &ordering);
|
||||
const FGAirport* apt = globals->get_airports()->findFirstById(id, &ordering);
|
||||
// search local gps waypoints (USR)
|
||||
|
||||
// pick the best - ugly logic, sorry. This is a temporary fix to getting rid
|
||||
// of the huge local waypoint table, it'll die when there's a way to query
|
||||
// this stuff centrally.
|
||||
// what we're doing is using map inserts to order the result, then using
|
||||
// the first entry (begin()) as the lowest, hence best, match
|
||||
map<string, GPSWpType, stringOrderKLN89> sorter;
|
||||
if (fix) sorter[fix->get_ident()] = GPS_WP_INT;
|
||||
if (apt) sorter[apt->getId()] = GPS_WP_APT;
|
||||
if (!vors.empty()) sorter[vors.front()->get_ident()] = GPS_WP_VOR;
|
||||
if (!ndbs.empty()) sorter[ndbs.front()->get_ident()] = GPS_WP_NDB;
|
||||
|
||||
if (sorter.empty()) return NULL; // no results at all
|
||||
GPSWpType ty = sorter.begin()->second;
|
||||
|
||||
switch (ty) {
|
||||
case GPS_WP_INT:
|
||||
return GPSWaypoint::createFromFix(fix);
|
||||
|
||||
case GPS_WP_APT:
|
||||
return GPSWaypoint::createFromAirport(apt);
|
||||
|
||||
case GPS_WP_VOR:
|
||||
return GPSWaypoint::createFromNav(vors.front());
|
||||
|
||||
case GPS_WP_NDB:
|
||||
return GPSWaypoint::createFromNav(ndbs.front());
|
||||
default:
|
||||
return NULL; // can't happen
|
||||
}
|
||||
}
|
||||
|
||||
const GPSWaypoint* DCLGPS::FindFirstById(const string& id, bool &multi, bool exact) {
|
||||
multi = false;
|
||||
if(exact) return(ActualFindFirstById(id, exact));
|
||||
GPSWaypoint* DCLGPS::FindFirstByExactId(const string& id) const
|
||||
{
|
||||
if (const FGAirport* apt = globals->get_airports()->search(id)) {
|
||||
return GPSWaypoint::createFromAirport(apt);
|
||||
}
|
||||
|
||||
// OK, that was the easy case, now the fuzzy case
|
||||
const GPSWaypoint* w1 = ActualFindFirstById(id);
|
||||
if(w1 == NULL) return(w1);
|
||||
if (const FGFix* fix = globals->get_fixlist()->search(id)) {
|
||||
return GPSWaypoint::createFromFix(fix);
|
||||
}
|
||||
|
||||
// The non-trivial code from here to the end of the function is all to deal with the fact that
|
||||
// the KLN89 alphabetical order (numbers AFTER letters) differs from ASCII order (numbers BEFORE letters).
|
||||
string id2 = id;
|
||||
//string id3 = id+'0';
|
||||
string id4 = id+'A';
|
||||
// Increment the last char to provide the boundary. Note that 'Z' -> '[' but we also need to check '0' for all since GPS has numbers after letters
|
||||
//bool alfa = isalpha(id2[id2.size() - 1]);
|
||||
id2[id2.size() - 1] = id2[id2.size() - 1] + 1;
|
||||
const GPSWaypoint* w2 = ActualFindFirstById(id2);
|
||||
//FGAirport* a3 = globals->get_airports()->findFirstById(id3);
|
||||
const GPSWaypoint* w4 = ActualFindFirstById(id4);
|
||||
//cout << "Strings sent were " << id << ", " << id2 << " and " << id4 << '\n';
|
||||
//cout << "Airports returned were (a1, a2, a4): " << a1->getId() << ", " << a2->getId() << ", " << a4->getId() << '\n';
|
||||
//cout << "Pointers were " << a1 << ", " << a2 << ", " << a4 << '\n';
|
||||
nav_list_type vors = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, true);
|
||||
if (!vors.empty()) {
|
||||
return GPSWaypoint::createFromNav(vors.front());
|
||||
}
|
||||
|
||||
// TODO - the below handles the imediately following char OK
|
||||
// eg id = "KD" returns "KDAA" instead of "KD5"
|
||||
// but it doesn't handle numbers / letters further down the string,
|
||||
// eg - id = "I" returns "IA01" instead of "IAN"
|
||||
// We either need to provide a custom comparison operator, or recurse this function if !isalpha further down the string.
|
||||
// (Currenly fixed with recursion).
|
||||
nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, true);
|
||||
if (!ndbs.empty()) {
|
||||
return GPSWaypoint::createFromNav(ndbs.front());
|
||||
}
|
||||
|
||||
if(w4 != w2) { // A-Z match - preferred
|
||||
//cout << "A-Z match!\n";
|
||||
if(w4->id.size() - id.size() > 2) {
|
||||
// Check for numbers further on
|
||||
for(unsigned int i=id.size(); i<w4->id.size(); ++i) {
|
||||
if(!isalpha(w4->id[i])) {
|
||||
//cout << "SUBSTR is " << (a4->getId()).substr(0, i) << '\n';
|
||||
return(FindFirstById(w4->id.substr(0, i), multi, exact));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(w4);
|
||||
} else if(w1 != w2) { // 0-9 match
|
||||
//cout << "0-9 match!\n";
|
||||
if(w1->id.size() - id.size() > 2) {
|
||||
// Check for numbers further on
|
||||
for(unsigned int i=id.size(); i<w1->id.size(); ++i) {
|
||||
if(!isalpha(w1->id[i])) {
|
||||
//cout << "SUBSTR2 is " << (a4->getId()).substr(0, i) << '\n';
|
||||
return(FindFirstById(w1->id.substr(0, i), multi, exact));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(w1);
|
||||
} else { // No match
|
||||
return(NULL);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1407,55 +1152,6 @@ FGNavRecord* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact)
|
|||
}
|
||||
return(NULL); // Shouldn't get here!
|
||||
}
|
||||
#if 0
|
||||
Overlays::NAV* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact) {
|
||||
// NOTE - at the moment multi is never set.
|
||||
multi = false;
|
||||
if(exact) return(_overlays->FindFirstVorById(id, exact));
|
||||
|
||||
// OK, that was the easy case, now the fuzzy case
|
||||
Overlays::NAV* n1 = _overlays->FindFirstVorById(id);
|
||||
if(n1 == NULL) return(n1);
|
||||
|
||||
string id2 = id;
|
||||
string id3 = id+'0';
|
||||
string id4 = id+'A';
|
||||
// Increment the last char to provide the boundary. Note that 'Z' -> '[' but we also need to check '0' for all since GPS has numbers after letters
|
||||
bool alfa = isalpha(id2[id2.size() - 1]);
|
||||
id2[id2.size() - 1] = id2[id2.size() - 1] + 1;
|
||||
Overlays::NAV* n2 = _overlays->FindFirstVorById(id2);
|
||||
//Overlays::NAV* n3 = _overlays->FindFirstVorById(id3);
|
||||
//Overlays::NAV* n4 = _overlays->FindFirstVorById(id4);
|
||||
//cout << "Strings sent were " << id << ", " << id2 << ", " << id3 << ", " << id4 << '\n';
|
||||
|
||||
|
||||
if(alfa) {
|
||||
if(n1 != n2) { // match
|
||||
return(n1);
|
||||
} else {
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(n1 != n2) {
|
||||
// Something matches - the problem is the number/letter preference order is reversed between the GPS and the STL
|
||||
if(n4 != n2) {
|
||||
// There's a letter match - return that
|
||||
return(n4);
|
||||
} else {
|
||||
// By definition we must have a number match
|
||||
if(n3 == n2) cout << "HELP - LOGIC FLAW in find VOR!\n";
|
||||
return(n3);
|
||||
}
|
||||
} else {
|
||||
// No match
|
||||
return(NULL);
|
||||
}
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
#endif //0
|
||||
|
||||
// TODO - add the ASCII / alphabetical stuff from the Atlas version
|
||||
FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact) {
|
||||
|
@ -1476,179 +1172,25 @@ FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact)
|
|||
}
|
||||
return(NULL); // Shouldn't get here!
|
||||
}
|
||||
#if 0
|
||||
Overlays::NAV* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact) {
|
||||
// NOTE - at the moment multi is never set.
|
||||
multi = false;
|
||||
if(exact) return(_overlays->FindFirstNDBById(id, exact));
|
||||
|
||||
// OK, that was the easy case, now the fuzzy case
|
||||
Overlays::NAV* n1 = _overlays->FindFirstNDBById(id);
|
||||
if(n1 == NULL) return(n1);
|
||||
|
||||
string id2 = id;
|
||||
string id3 = id+'0';
|
||||
string id4 = id+'A';
|
||||
// Increment the last char to provide the boundary. Note that 'Z' -> '[' but we also need to check '0' for all since GPS has numbers after letters
|
||||
bool alfa = isalpha(id2[id2.size() - 1]);
|
||||
id2[id2.size() - 1] = id2[id2.size() - 1] + 1;
|
||||
Overlays::NAV* n2 = _overlays->FindFirstNDBById(id2);
|
||||
//Overlays::NAV* n3 = _overlays->FindFirstNDBById(id3);
|
||||
//Overlays::NAV* n4 = _overlays->FindFirstNDBById(id4);
|
||||
//cout << "Strings sent were " << id << ", " << id2 << ", " << id3 << ", " << id4 << '\n';
|
||||
|
||||
|
||||
if(alfa) {
|
||||
if(n1 != n2) { // match
|
||||
return(n1);
|
||||
} else {
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if(n1 != n2) {
|
||||
// Something matches - the problem is the number/letter preference order is reversed between the GPS and the STL
|
||||
if(n4 != n2) {
|
||||
// There's a letter match - return that
|
||||
return(n4);
|
||||
} else {
|
||||
// By definition we must have a number match
|
||||
if(n3 == n2) cout << "HELP - LOGIC FLAW in find VOR!\n";
|
||||
return(n3);
|
||||
}
|
||||
} else {
|
||||
// No match
|
||||
return(NULL);
|
||||
}
|
||||
*/
|
||||
return NULL;
|
||||
}
|
||||
#endif //0
|
||||
|
||||
// TODO - add the ASCII / alphabetical stuff from the Atlas version
|
||||
const FGFix* DCLGPS::FindFirstIntById(const string& id, bool &multi, bool exact) {
|
||||
// NOTE - at the moment multi is never set, and indeed can't be
|
||||
// since FG can only map one Fix per ID at the moment.
|
||||
multi = false;
|
||||
if(exact) return(globals->get_fixlist()->findFirstByIdent(id, exact));
|
||||
if (exact) return globals->get_fixlist()->search(id);
|
||||
|
||||
const FGFix* f1 = globals->get_fixlist()->findFirstByIdent(id, exact);
|
||||
if(f1 == NULL) return(f1);
|
||||
|
||||
// The non-trivial code from here to the end of the function is all to deal with the fact that
|
||||
// the KLN89 alphabetical order (numbers AFTER letters) differs from ASCII order (numbers BEFORE letters).
|
||||
// It is copied from the airport version which is definately needed, but at present I'm not actually
|
||||
// sure if any fixes in FG or real-life have numbers in them!
|
||||
string id2 = id;
|
||||
//string id3 = id+'0';
|
||||
string id4 = id+'A';
|
||||
// Increment the last char to provide the boundary. Note that 'Z' -> '[' but we also need to check '0' for all since GPS has numbers after letters
|
||||
//bool alfa = isalpha(id2[id2.size() - 1]);
|
||||
id2[id2.size() - 1] = id2[id2.size() - 1] + 1;
|
||||
const FGFix* f2 = globals->get_fixlist()->findFirstByIdent(id2);
|
||||
//const FGFix* a3 = globals->get_fixlist()->findFirstByIdent(id3);
|
||||
const FGFix* f4 = globals->get_fixlist()->findFirstByIdent(id4);
|
||||
|
||||
// TODO - the below handles the imediately following char OK
|
||||
// eg id = "KD" returns "KDAA" instead of "KD5"
|
||||
// but it doesn't handle numbers / letters further down the string,
|
||||
// eg - id = "I" returns "IA01" instead of "IAN"
|
||||
// We either need to provide a custom comparison operator, or recurse this function if !isalpha further down the string.
|
||||
// (Currenly fixed with recursion).
|
||||
|
||||
if(f4 != f2) { // A-Z match - preferred
|
||||
//cout << "A-Z match!\n";
|
||||
if(f4->get_ident().size() - id.size() > 2) {
|
||||
// Check for numbers further on
|
||||
for(unsigned int i=id.size(); i<f4->get_ident().size(); ++i) {
|
||||
if(!isalpha(f4->get_ident()[i])) {
|
||||
//cout << "SUBSTR is " << (a4->getId()).substr(0, i) << '\n';
|
||||
return(FindFirstIntById(f4->get_ident().substr(0, i), multi, exact));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(f4);
|
||||
} else if(f1 != f2) { // 0-9 match
|
||||
//cout << "0-9 match!\n";
|
||||
if(f1->get_ident().size() - id.size() > 2) {
|
||||
// Check for numbers further on
|
||||
for(unsigned int i=id.size(); i<f1->get_ident().size(); ++i) {
|
||||
if(!isalpha(f1->get_ident()[i])) {
|
||||
//cout << "SUBSTR2 is " << (a4->getId()).substr(0, i) << '\n';
|
||||
return(FindFirstIntById(f1->get_ident().substr(0, i), multi, exact));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(f1);
|
||||
} else { // No match
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return NULL; // Don't think we can ever get here.
|
||||
stringOrderKLN89 ordering;
|
||||
return globals->get_fixlist()->findFirstByIdent(id, &ordering);
|
||||
}
|
||||
|
||||
const FGAirport* DCLGPS::FindFirstAptById(const string& id, bool &multi, bool exact) {
|
||||
// NOTE - at the moment multi is never set.
|
||||
//cout << "FindFirstAptById, id = " << id << '\n';
|
||||
multi = false;
|
||||
if(exact) return(globals->get_airports()->findFirstById(id, exact));
|
||||
if(exact) return(globals->get_airports()->search(id));
|
||||
|
||||
// OK, that was the easy case, now the fuzzy case
|
||||
const FGAirport* a1 = globals->get_airports()->findFirstById(id);
|
||||
if(a1 == NULL) return(a1);
|
||||
|
||||
// The non-trivial code from here to the end of the function is all to deal with the fact that
|
||||
// the KLN89 alphabetical order (numbers AFTER letters) differs from ASCII order (numbers BEFORE letters).
|
||||
string id2 = id;
|
||||
//string id3 = id+'0';
|
||||
string id4 = id+'A';
|
||||
// Increment the last char to provide the boundary. Note that 'Z' -> '[' but we also need to check '0' for all since GPS has numbers after letters
|
||||
//bool alfa = isalpha(id2[id2.size() - 1]);
|
||||
id2[id2.size() - 1] = id2[id2.size() - 1] + 1;
|
||||
const FGAirport* a2 = globals->get_airports()->findFirstById(id2);
|
||||
//FGAirport* a3 = globals->get_airports()->findFirstById(id3);
|
||||
const FGAirport* a4 = globals->get_airports()->findFirstById(id4);
|
||||
//cout << "Strings sent were " << id << ", " << id2 << " and " << id4 << '\n';
|
||||
//cout << "Airports returned were (a1, a2, a4): " << a1->getId() << ", " << a2->getId() << ", " << a4->getId() << '\n';
|
||||
//cout << "Pointers were " << a1 << ", " << a2 << ", " << a4 << '\n';
|
||||
|
||||
// TODO - the below handles the imediately following char OK
|
||||
// eg id = "KD" returns "KDAA" instead of "KD5"
|
||||
// but it doesn't handle numbers / letters further down the string,
|
||||
// eg - id = "I" returns "IA01" instead of "IAN"
|
||||
// We either need to provide a custom comparison operator, or recurse this function if !isalpha further down the string.
|
||||
// (Currenly fixed with recursion).
|
||||
|
||||
if(a4 != a2) { // A-Z match - preferred
|
||||
//cout << "A-Z match!\n";
|
||||
if(a4->getId().size() - id.size() > 2) {
|
||||
// Check for numbers further on
|
||||
for(unsigned int i=id.size(); i<a4->getId().size(); ++i) {
|
||||
if(!isalpha(a4->getId()[i])) {
|
||||
//cout << "SUBSTR is " << (a4->getId()).substr(0, i) << '\n';
|
||||
return(FindFirstAptById(a4->getId().substr(0, i), multi, exact));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(a4);
|
||||
} else if(a1 != a2) { // 0-9 match
|
||||
//cout << "0-9 match!\n";
|
||||
if(a1->getId().size() - id.size() > 2) {
|
||||
// Check for numbers further on
|
||||
for(unsigned int i=id.size(); i<a1->getId().size(); ++i) {
|
||||
if(!isalpha(a1->getId()[i])) {
|
||||
//cout << "SUBSTR2 is " << (a4->getId()).substr(0, i) << '\n';
|
||||
return(FindFirstAptById(a1->getId().substr(0, i), multi, exact));
|
||||
}
|
||||
}
|
||||
}
|
||||
return(a1);
|
||||
} else { // No match
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
stringOrderKLN89 ordering;
|
||||
return globals->get_airports()->findFirstById(id, &ordering);
|
||||
}
|
||||
|
||||
FGNavRecord* DCLGPS::FindClosestVor(double lat_rad, double lon_rad) {
|
||||
|
|
|
@ -91,6 +91,13 @@ ostream& operator << (ostream& os, GPSAppWpType type);
|
|||
|
||||
struct GPSWaypoint {
|
||||
GPSWaypoint();
|
||||
|
||||
GPSWaypoint(const std::string& aIdent, float lat, float lon, GPSWpType aType);
|
||||
|
||||
static GPSWaypoint* createFromFix(const FGFix* aFix);
|
||||
static GPSWaypoint* createFromNav(const FGNavRecord* aNav);
|
||||
static GPSWaypoint* createFromAirport(const FGAirport* aApt);
|
||||
|
||||
~GPSWaypoint();
|
||||
string GetAprId(); // Returns the id with i, f, m or h added if appropriate. (Initial approach fix, final approach fix, etc)
|
||||
string id;
|
||||
|
@ -407,14 +414,13 @@ protected:
|
|||
//
|
||||
|
||||
// Data and lookup functions
|
||||
// All waypoints mapped by id.
|
||||
gps_waypoint_map _waypoints;
|
||||
private:
|
||||
// Worker function for the below.
|
||||
const GPSWaypoint* ActualFindFirstById(const string& id, bool exact = false);
|
||||
|
||||
|
||||
protected:
|
||||
// Find first of any type of waypoint by id. (TODO - Possibly we should return multiple waypoints here).
|
||||
const GPSWaypoint* FindFirstById(const string& id, bool &multi, bool exact = false);
|
||||
GPSWaypoint* FindFirstById(const string& id) const;
|
||||
GPSWaypoint* FindFirstByExactId(const string& id) const;
|
||||
|
||||
FGNavRecord* FindFirstVorById(const string& id, bool &multi, bool exact = false);
|
||||
FGNavRecord* FindFirstNDBById(const string& id, bool &multi, bool exact = false);
|
||||
const FGAirport* FindFirstAptById(const string& id, bool &multi, bool exact = false);
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include "fixlist.hxx"
|
||||
#include "Airports/simple.hxx";
|
||||
|
||||
using std::pair;
|
||||
|
||||
|
||||
|
@ -120,17 +122,45 @@ bool FGFixList::query_and_offset( const string& ident, double lon, double lat,
|
|||
return true;
|
||||
}
|
||||
|
||||
const FGFix* FGFixList::findFirstByIdent( const string& ident, bool exact)
|
||||
const FGFix* FGFixList::search(const string& ident)
|
||||
{
|
||||
fix_map_iterator itr = fixlist.find(ident);
|
||||
if (itr == fixlist.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &itr->second;
|
||||
}
|
||||
|
||||
class orderingFunctor
|
||||
{
|
||||
public:
|
||||
orderingFunctor(FGIdentOrdering* aOrder) :
|
||||
mOrdering(aOrder)
|
||||
{ assert(aOrder); }
|
||||
|
||||
bool operator()(const fix_map_type::value_type& aA, const std::string& aB) const
|
||||
{
|
||||
return mOrdering->compare(aA.first,aB);
|
||||
}
|
||||
|
||||
private:
|
||||
FGIdentOrdering* mOrdering;
|
||||
};
|
||||
|
||||
const FGFix* FGFixList::findFirstByIdent( const string& ident, FGIdentOrdering* aOrder)
|
||||
{
|
||||
fix_map_iterator itr;
|
||||
if(exact) {
|
||||
itr = fixlist.find(ident);
|
||||
if (aOrder) {
|
||||
orderingFunctor func(aOrder);
|
||||
itr = std::lower_bound(fixlist.begin(),fixlist.end(), ident, func);
|
||||
} else {
|
||||
itr = fixlist.lower_bound(ident);
|
||||
}
|
||||
if(itr == fixlist.end()) {
|
||||
return(NULL);
|
||||
} else {
|
||||
return(&(itr->second));
|
||||
|
||||
if (itr == fixlist.end()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &itr->second;
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ typedef multimap < string, FGFix > fix_map_type;
|
|||
typedef fix_map_type::iterator fix_map_iterator;
|
||||
typedef fix_map_type::const_iterator fix_map_const_iterator;
|
||||
|
||||
class FGIdentOrdering; // FIXME, currently declared in Airports/simple.hxx
|
||||
|
||||
class FGFixList {
|
||||
|
||||
fix_map_type fixlist;
|
||||
|
@ -58,11 +60,13 @@ public:
|
|||
// query the database for the specified fix
|
||||
bool query( const string& ident, FGFix *f );
|
||||
|
||||
const FGFix* search(const string& ident);
|
||||
|
||||
// Find fix of requested type with closest exact or following ident
|
||||
// (by ACSII values) to that supplied (ie. a lower-bound lookup).
|
||||
// Supplying true for exact forces only exact matches to be returned (similar to above function)
|
||||
// Returns NULL if no match found.
|
||||
const FGFix* findFirstByIdent( const string& ident, bool exact = false );
|
||||
const FGFix* findFirstByIdent( const string& ident, FGIdentOrdering* aOrder = NULL);
|
||||
|
||||
// query the database for the specified fix, lon and lat are
|
||||
// in degrees, elev is in meters
|
||||
|
|
Loading…
Add table
Reference in a new issue