James Turner : this patch
- updates how filtering is done on the various FGPositioned query functions - both spatial and ident-based. - updates the KLN-89b / DCLGPS code to use FGPositioned for all Navaid/Airport queries. me: Add few include directives in globals.cxx to avoid such MSVC warning messages : deletion of pointer to incomplete type 'FGAirportList'; no destructor called deletion of pointer to incomplete type 'FGNavList'; no destructor called deletion of pointer to incomplete type 'FGTACANList'; no destructor called deletion of pointer to incomplete type 'FGFixList'; no destructor called
This commit is contained in:
parent
32d3f6308c
commit
e2bf85e67e
10 changed files with 236 additions and 185 deletions
|
@ -46,6 +46,7 @@
|
||||||
#include <ATCDCL/ATCProjection.hxx>
|
#include <ATCDCL/ATCProjection.hxx>
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <simgear/math/point3d.hxx>
|
#include <simgear/math/point3d.hxx>
|
||||||
|
#include "Airports/simple.hxx"
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "kln89_page_apt.hxx"
|
#include "kln89_page_apt.hxx"
|
||||||
#include <ATCDCL/commlist.hxx>
|
#include "ATCDCL/commlist.hxx"
|
||||||
#include <Main/globals.hxx>
|
#include "Main/globals.hxx"
|
||||||
#include <Airports/runways.hxx>
|
#include "Airports/runways.hxx"
|
||||||
|
#include "Airports/simple.hxx"
|
||||||
|
|
||||||
// This function is copied from Airports/runways.cxx
|
// This function is copied from Airports/runways.cxx
|
||||||
// TODO - Make the original properly available and remove this instance!!!!
|
// TODO - Make the original properly available and remove this instance!!!!
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "kln89_page_int.hxx"
|
#include "kln89_page_int.hxx"
|
||||||
#include "Navaids/fix.hxx"
|
#include "Navaids/fix.hxx"
|
||||||
|
#include "Navaids/navrecord.hxx"
|
||||||
|
|
||||||
KLN89IntPage::KLN89IntPage(KLN89* parent)
|
KLN89IntPage::KLN89IntPage(KLN89* parent)
|
||||||
: KLN89Page(parent) {
|
: KLN89Page(parent) {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "kln89_page_ndb.hxx"
|
#include "kln89_page_ndb.hxx"
|
||||||
|
#include "Navaids/navrecord.hxx"
|
||||||
|
|
||||||
KLN89NDBPage::KLN89NDBPage(KLN89* parent)
|
KLN89NDBPage::KLN89NDBPage(KLN89* parent)
|
||||||
: KLN89Page(parent) {
|
: KLN89Page(parent) {
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "kln89_page_vor.hxx"
|
#include "kln89_page_vor.hxx"
|
||||||
|
#include "Navaids/navrecord.hxx"
|
||||||
|
|
||||||
KLN89VorPage::KLN89VorPage(KLN89* parent)
|
KLN89VorPage::KLN89VorPage(KLN89* parent)
|
||||||
: KLN89Page(parent) {
|
: KLN89Page(parent) {
|
||||||
|
|
|
@ -32,11 +32,12 @@
|
||||||
|
|
||||||
#include <Main/fg_props.hxx>
|
#include <Main/fg_props.hxx>
|
||||||
#include <Navaids/fix.hxx>
|
#include <Navaids/fix.hxx>
|
||||||
|
#include <Navaids/navrecord.hxx>
|
||||||
|
#include <Airports/simple.hxx>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
using std::cout;
|
|
||||||
|
|
||||||
//using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
// Command callbacks for FlightGear
|
// Command callbacks for FlightGear
|
||||||
|
|
||||||
|
@ -140,31 +141,43 @@ string GPSWaypoint::GetAprId() {
|
||||||
else return(id);
|
else return(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GPSWaypoint* GPSWaypoint::createFromFix(const FGFix* aFix)
|
static GPSWpType
|
||||||
|
GPSWpTypeFromFGPosType(FGPositioned::Type aType)
|
||||||
{
|
{
|
||||||
assert(aFix);
|
switch (aType) {
|
||||||
return new GPSWaypoint(aFix->get_ident(),
|
case FGPositioned::AIRPORT:
|
||||||
aFix->get_lat() * SG_DEGREES_TO_RADIANS,
|
case FGPositioned::SEAPORT:
|
||||||
aFix->get_lon() * SG_DEGREES_TO_RADIANS,
|
case FGPositioned::HELIPORT:
|
||||||
GPS_WP_INT);
|
return GPS_WP_APT;
|
||||||
|
|
||||||
|
case FGPositioned::VOR:
|
||||||
|
return GPS_WP_VOR;
|
||||||
|
|
||||||
|
case FGPositioned::NDB:
|
||||||
|
return GPS_WP_NDB;
|
||||||
|
|
||||||
|
case FGPositioned::WAYPOINT:
|
||||||
|
return GPS_WP_USR;
|
||||||
|
|
||||||
|
case FGPositioned::FIX:
|
||||||
|
return GPS_WP_INT;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return GPS_WP_USR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GPSWaypoint* GPSWaypoint::createFromNav(const FGNavRecord* aNav)
|
GPSWaypoint* GPSWaypoint::createFromPositioned(const FGPositioned* aPos)
|
||||||
{
|
{
|
||||||
assert(aNav);
|
if (!aPos) {
|
||||||
return new GPSWaypoint(aNav->get_ident(),
|
return NULL; // happens if find returns no match
|
||||||
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)
|
return new GPSWaypoint(aPos->ident(),
|
||||||
{
|
aPos->latitude() * SG_DEGREES_TO_RADIANS,
|
||||||
assert(aApt);
|
aPos->longitude() * SG_DEGREES_TO_RADIANS,
|
||||||
return new GPSWaypoint(aApt->getId(),
|
GPSWpTypeFromFGPosType(aPos->type())
|
||||||
aApt->getLatitude() * SG_DEGREES_TO_RADIANS,
|
);
|
||||||
aApt->getLongitude() * SG_DEGREES_TO_RADIANS,
|
|
||||||
GPS_WP_APT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ostream& operator << (ostream& os, GPSAppWpType type) {
|
ostream& operator << (ostream& os, GPSAppWpType type) {
|
||||||
|
@ -1071,132 +1084,83 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DCLGPSFilter : public FGPositioned::Filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool pass(const FGPositioned* aPos) const {
|
||||||
|
switch (aPos->type()) {
|
||||||
|
case FGPositioned::AIRPORT:
|
||||||
|
// how about heliports and seaports?
|
||||||
|
case FGPositioned::NDB:
|
||||||
|
case FGPositioned::VOR:
|
||||||
|
case FGPositioned::WAYPOINT:
|
||||||
|
case FGPositioned::FIX:
|
||||||
|
break;
|
||||||
|
default: return false; // reject all other types
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
GPSWaypoint* DCLGPS::FindFirstById(const string& id) const
|
GPSWaypoint* DCLGPS::FindFirstById(const string& id) const
|
||||||
{
|
{
|
||||||
stringOrderKLN89 ordering;
|
DCLGPSFilter filter;
|
||||||
nav_list_type vors = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, false);
|
FGPositionedRef result = FGPositioned::findNextWithPartialId(NULL, id, &filter);
|
||||||
nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, false);
|
return GPSWaypoint::createFromPositioned(result);
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GPSWaypoint* DCLGPS::FindFirstByExactId(const string& id) const
|
GPSWaypoint* DCLGPS::FindFirstByExactId(const string& id) const
|
||||||
{
|
{
|
||||||
if (const FGAirport* apt = globals->get_airports()->search(id)) {
|
SGGeod pos(SGGeod::fromRad(_lon, _lat));
|
||||||
return GPSWaypoint::createFromAirport(apt);
|
FGPositionedRef result = FGPositioned::findClosestWithIdent(id, pos);
|
||||||
}
|
return GPSWaypoint::createFromPositioned(result);
|
||||||
|
|
||||||
if (const FGFix* fix = globals->get_fixlist()->search(id)) {
|
|
||||||
return GPSWaypoint::createFromFix(fix);
|
|
||||||
}
|
|
||||||
|
|
||||||
nav_list_type vors = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, true);
|
|
||||||
if (!vors.empty()) {
|
|
||||||
return GPSWaypoint::createFromNav(vors.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
nav_list_type ndbs = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, true);
|
|
||||||
if (!ndbs.empty()) {
|
|
||||||
return GPSWaypoint::createFromNav(ndbs.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Host specific lookup functions
|
|
||||||
// TODO - add the ASCII / alphabetical stuff from the Atlas version
|
|
||||||
FGNavRecord* 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));
|
|
||||||
|
|
||||||
nav_list_type nav = globals->get_navlist()->findFirstByIdent(id, FG_NAV_VOR, exact);
|
|
||||||
|
|
||||||
if(nav.size() > 1) multi = true;
|
|
||||||
//return(nav.empty() ? NULL : *(nav.begin()));
|
|
||||||
|
|
||||||
// The above is sort of what we want - unfortunately we can't guarantee no NDB/ILS at the moment
|
|
||||||
if(nav.empty()) return(NULL);
|
|
||||||
|
|
||||||
for(nav_list_iterator it = nav.begin(); it != nav.end(); ++it) {
|
|
||||||
if((*it)->type() == FGPositioned::VOR) return(*it);
|
|
||||||
}
|
|
||||||
return(NULL); // Shouldn't get here!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO - add the ASCII / alphabetical stuff from the Atlas version
|
// TODO - add the ASCII / alphabetical stuff from the Atlas version
|
||||||
FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact) {
|
FGPositioned* DCLGPS::FindTypedFirstById(const string& id, FGPositioned::Type ty, bool &multi, bool exact)
|
||||||
// NOTE - at the moment multi is never set.
|
{
|
||||||
multi = false;
|
multi = false;
|
||||||
//if(exact) return(_overlays->FindFirstVorById(id, exact));
|
FGPositioned::TypeFilter filter(ty);
|
||||||
|
|
||||||
nav_list_type nav = globals->get_navlist()->findFirstByIdent(id, FG_NAV_NDB, exact);
|
if (exact) {
|
||||||
|
FGPositioned::List matches =
|
||||||
if(nav.size() > 1) multi = true;
|
FGPositioned::findAllWithIdentSortedByRange(id, SGGeod::fromRad(_lon, _lat), &filter);
|
||||||
//return(nav.empty() ? NULL : *(nav.begin()));
|
multi = (matches.size() > 1);
|
||||||
|
return matches.empty() ? NULL : matches.front().ptr();
|
||||||
// The above is sort of what we want - unfortunately we can't guarantee no NDB/ILS at the moment
|
|
||||||
if(nav.empty()) return(NULL);
|
|
||||||
|
|
||||||
for(nav_list_iterator it = nav.begin(); it != nav.end(); ++it) {
|
|
||||||
if((*it)->type() == FGPositioned::NDB) return(*it);
|
|
||||||
}
|
|
||||||
return(NULL); // Shouldn't get here!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FGFix* DCLGPS::FindFirstIntById(const string& id, bool &multi, bool exact) {
|
return FGPositioned::findNextWithPartialId(NULL, id, &filter);
|
||||||
// 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()->search(id);
|
|
||||||
|
|
||||||
stringOrderKLN89 ordering;
|
|
||||||
return globals->get_fixlist()->findFirstByIdent(id, &ordering);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const FGAirport* DCLGPS::FindFirstAptById(const string& id, bool &multi, bool exact) {
|
FGNavRecord* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact)
|
||||||
// NOTE - at the moment multi is never set.
|
{
|
||||||
//cout << "FindFirstAptById, id = " << id << '\n';
|
return dynamic_cast<FGNavRecord*>(FindTypedFirstById(id, FGPositioned::VOR, multi, exact));
|
||||||
multi = false;
|
}
|
||||||
if(exact) return(globals->get_airports()->search(id));
|
|
||||||
|
|
||||||
stringOrderKLN89 ordering;
|
FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact)
|
||||||
return globals->get_airports()->findFirstById(id, &ordering);
|
{
|
||||||
|
return dynamic_cast<FGNavRecord*>(FindTypedFirstById(id, FGPositioned::NDB, multi, exact));
|
||||||
|
}
|
||||||
|
|
||||||
|
const FGFix* DCLGPS::FindFirstIntById(const string& id, bool &multi, bool exact)
|
||||||
|
{
|
||||||
|
return dynamic_cast<FGFix*>(FindTypedFirstById(id, FGPositioned::FIX, multi, exact));
|
||||||
|
}
|
||||||
|
|
||||||
|
const FGAirport* DCLGPS::FindFirstAptById(const string& id, bool &multi, bool exact)
|
||||||
|
{
|
||||||
|
return dynamic_cast<FGAirport*>(FindTypedFirstById(id, FGPositioned::AIRPORT, multi, exact));
|
||||||
}
|
}
|
||||||
|
|
||||||
FGNavRecord* DCLGPS::FindClosestVor(double lat_rad, double lon_rad) {
|
FGNavRecord* DCLGPS::FindClosestVor(double lat_rad, double lon_rad) {
|
||||||
return(globals->get_navlist()->findClosest(lon_rad, lat_rad, 0.0, FG_NAV_VOR));
|
FGPositioned::TypeFilter filter(FGPositioned::VOR);
|
||||||
|
double cutoff = 1000; // nautical miles
|
||||||
|
FGPositionedRef v = FGPositioned::findClosest(SGGeod::fromRad(lon_rad, lat_rad), cutoff, &filter);
|
||||||
|
if (!v) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamic_cast<FGNavRecord*>(v.ptr());
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -32,15 +32,16 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <Navaids/navrecord.hxx>
|
|
||||||
#include <Navaids/navlist.hxx>
|
|
||||||
#include <Navaids/fixlist.hxx>
|
|
||||||
#include <Airports/simple.hxx>
|
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
|
#include <Navaids/positioned.hxx>
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
class SGTime;
|
class SGTime;
|
||||||
|
class FGPositioned;
|
||||||
|
|
||||||
|
// XXX fix me
|
||||||
|
class FGNavRecord;
|
||||||
|
class FGAirport;
|
||||||
|
class FGFix;
|
||||||
|
|
||||||
enum GPSDistanceUnits {
|
enum GPSDistanceUnits {
|
||||||
GPS_DIST_UNITS_NM = 0,
|
GPS_DIST_UNITS_NM = 0,
|
||||||
|
@ -94,9 +95,7 @@ struct GPSWaypoint {
|
||||||
|
|
||||||
GPSWaypoint(const std::string& aIdent, float lat, float lon, GPSWpType aType);
|
GPSWaypoint(const std::string& aIdent, float lat, float lon, GPSWpType aType);
|
||||||
|
|
||||||
static GPSWaypoint* createFromFix(const FGFix* aFix);
|
static GPSWaypoint* createFromPositioned(const FGPositioned* aFix);
|
||||||
static GPSWaypoint* createFromNav(const FGNavRecord* aNav);
|
|
||||||
static GPSWaypoint* createFromAirport(const FGAirport* aApt);
|
|
||||||
|
|
||||||
~GPSWaypoint();
|
~GPSWaypoint();
|
||||||
string GetAprId(); // Returns the id with i, f, m or h added if appropriate. (Initial approach fix, final approach fix, etc)
|
string GetAprId(); // Returns the id with i, f, m or h added if appropriate. (Initial approach fix, final approach fix, etc)
|
||||||
|
@ -428,6 +427,9 @@ protected:
|
||||||
// Find the closest VOR to a position in RADIANS.
|
// Find the closest VOR to a position in RADIANS.
|
||||||
FGNavRecord* FindClosestVor(double lat_rad, double lon_rad);
|
FGNavRecord* FindClosestVor(double lat_rad, double lon_rad);
|
||||||
|
|
||||||
|
// helper to implement the above FindFirstXXX methods
|
||||||
|
FGPositioned* FindTypedFirstById(const std::string& id, FGPositioned::Type ty, bool &multi, bool exact);
|
||||||
|
|
||||||
// Position, orientation and velocity.
|
// Position, orientation and velocity.
|
||||||
// These should be read from FG's built-in GPS logic if possible.
|
// These should be read from FG's built-in GPS logic if possible.
|
||||||
// Use the property node pointers below to do this.
|
// Use the property node pointers below to do this.
|
||||||
|
|
|
@ -47,6 +47,9 @@
|
||||||
#include <Navaids/awynet.hxx>
|
#include <Navaids/awynet.hxx>
|
||||||
#include <Scenery/scenery.hxx>
|
#include <Scenery/scenery.hxx>
|
||||||
#include <Scenery/tilemgr.hxx>
|
#include <Scenery/tilemgr.hxx>
|
||||||
|
#include <Airports\simple.hxx>
|
||||||
|
#include <Navaids\navlist.hxx>
|
||||||
|
#include <Navaids\fixlist.hxx>
|
||||||
|
|
||||||
#include "globals.hxx"
|
#include "globals.hxx"
|
||||||
#include "renderer.hxx"
|
#include "renderer.hxx"
|
||||||
|
|
|
@ -98,7 +98,7 @@ removeFromIndices(FGPositioned* aPos)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spatialFilterInBucket(const SGBucket& aBucket, const FGPositioned::Filter& aFilter, FGPositioned::List& aResult)
|
spatialFilterInBucket(const SGBucket& aBucket, FGPositioned::Filter* aFilter, FGPositioned::List& aResult)
|
||||||
{
|
{
|
||||||
SpatialPositionedIndex::const_iterator it;
|
SpatialPositionedIndex::const_iterator it;
|
||||||
it = global_spatialIndex.find(aBucket.gen_index());
|
it = global_spatialIndex.find(aBucket.gen_index());
|
||||||
|
@ -109,8 +109,13 @@ spatialFilterInBucket(const SGBucket& aBucket, const FGPositioned::Filter& aFilt
|
||||||
BucketEntry::const_iterator l = it->second.begin();
|
BucketEntry::const_iterator l = it->second.begin();
|
||||||
BucketEntry::const_iterator u = it->second.end();
|
BucketEntry::const_iterator u = it->second.end();
|
||||||
|
|
||||||
|
if (!aFilter) { // pass everything
|
||||||
|
aResult.insert(aResult.end(), l, u);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for ( ; l != u; ++l) {
|
for ( ; l != u; ++l) {
|
||||||
if (aFilter(*l)) {
|
if ((*aFilter)(*l)) {
|
||||||
aResult.push_back(*l);
|
aResult.push_back(*l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +123,7 @@ spatialFilterInBucket(const SGBucket& aBucket, const FGPositioned::Filter& aFilt
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spatialFind(const SGGeod& aPos, double aRange,
|
spatialFind(const SGGeod& aPos, double aRange,
|
||||||
const FGPositioned::Filter& aFilter, FGPositioned::List& aResult)
|
FGPositioned::Filter* aFilter, FGPositioned::List& aResult)
|
||||||
{
|
{
|
||||||
SGBucket buck(aPos);
|
SGBucket buck(aPos);
|
||||||
double lat = aPos.getLatitudeDeg(),
|
double lat = aPos.getLatitudeDeg(),
|
||||||
|
@ -135,6 +140,7 @@ spatialFind(const SGGeod& aPos, double aRange,
|
||||||
} // of i-iteration
|
} // of i-iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
class LowerLimitOfType
|
class LowerLimitOfType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -149,6 +155,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, FGPositioned::Type aUpper, FGPositioned::List& aResult)
|
spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, FGPositioned::Type aUpper, FGPositioned::List& aResult)
|
||||||
{
|
{
|
||||||
|
@ -180,6 +187,7 @@ spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, F
|
||||||
} // of j-iteration
|
} // of j-iteration
|
||||||
} // of i-iteration
|
} // of i-iteration
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
|
@ -238,8 +246,7 @@ sortByDistance(const SGGeod& aPos, FGPositioned::List& aResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
static FGPositionedRef
|
static FGPositionedRef
|
||||||
namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin,
|
namedFindClosest(const std::string& aIdent, const SGGeod& aOrigin, FGPositioned::Filter* aFilter)
|
||||||
FGPositioned::Type aLower, FGPositioned::Type aUpper)
|
|
||||||
{
|
{
|
||||||
NamedIndexRange range = global_namedIndex.equal_range(aIdent);
|
NamedIndexRange range = global_namedIndex.equal_range(aIdent);
|
||||||
if (range.first == range.second) {
|
if (range.first == range.second) {
|
||||||
|
@ -251,8 +258,7 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin,
|
||||||
NamedPositionedIndex::const_iterator check = range.first;
|
NamedPositionedIndex::const_iterator check = range.first;
|
||||||
if (++check == range.second) {
|
if (++check == range.second) {
|
||||||
// excellent, only one match in the range - all we care about is the type
|
// excellent, only one match in the range - all we care about is the type
|
||||||
FGPositioned::Type ty = range.first->second->type();
|
if (aFilter && !aFilter->pass(range.first->second)) {
|
||||||
if ((ty < aLower) || (ty > aUpper)) {
|
|
||||||
return NULL; // type check failed
|
return NULL; // type check failed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,7 +273,7 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin,
|
||||||
for (; it != range.second; ++it) {
|
for (; it != range.second; ++it) {
|
||||||
// filter by type
|
// filter by type
|
||||||
FGPositioned::Type ty = it->second->type();
|
FGPositioned::Type ty = it->second->type();
|
||||||
if ((ty < aLower) || (ty > aUpper)) {
|
if (aFilter && !aFilter->pass(range.first->second)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,7 +290,7 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin,
|
||||||
}
|
}
|
||||||
|
|
||||||
static FGPositioned::List
|
static FGPositioned::List
|
||||||
spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, const FGPositioned::Filter& aFilter)
|
spatialGetClosest(const SGGeod& aPos, unsigned int aN, double aCutoffNm, FGPositioned::Filter* aFilter)
|
||||||
{
|
{
|
||||||
FGPositioned::List result;
|
FGPositioned::List result;
|
||||||
int radius = 1; // start at 1, radius 0 is handled explicitly
|
int radius = 1; // start at 1, radius 0 is handled explicitly
|
||||||
|
@ -381,28 +387,13 @@ const char* FGPositioned::nameForType(Type aTy)
|
||||||
// search / query functions
|
// search / query functions
|
||||||
|
|
||||||
FGPositionedRef
|
FGPositionedRef
|
||||||
FGPositioned::findClosestWithIdent(const std::string& aIdent, double aLat, double aLon)
|
FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
|
||||||
{
|
{
|
||||||
return findClosestWithIdent(aIdent, SGGeod::fromDeg(aLon, aLat));
|
return namedFindClosest(aIdent, aPos, aFilter);
|
||||||
}
|
|
||||||
|
|
||||||
FGPositionedRef
|
|
||||||
FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos)
|
|
||||||
{
|
|
||||||
return namedFindClosestTyped(aIdent, aPos, INVALID, LAST_TYPE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FGPositioned::List
|
FGPositioned::List
|
||||||
FGPositioned::findWithinRangeByType(const SGGeod& aPos, double aRangeNm, Type aTy)
|
FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter)
|
||||||
{
|
|
||||||
List result;
|
|
||||||
spatialFindTyped(aPos, aRangeNm, aTy, aTy, result);
|
|
||||||
filterListByRange(aPos, aRangeNm, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
FGPositioned::List
|
|
||||||
FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, const Filter& aFilter)
|
|
||||||
{
|
{
|
||||||
List result;
|
List result;
|
||||||
spatialFind(aPos, aRangeNm, aFilter, result);
|
spatialFind(aPos, aRangeNm, aFilter, result);
|
||||||
|
@ -411,20 +402,60 @@ FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, const Filter&
|
||||||
}
|
}
|
||||||
|
|
||||||
FGPositioned::List
|
FGPositioned::List
|
||||||
FGPositioned::findAllWithIdent(const std::string& aIdent)
|
FGPositioned::findAllWithIdentSortedByRange(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
|
||||||
{
|
{
|
||||||
List result;
|
List result;
|
||||||
NamedIndexRange range = global_namedIndex.equal_range(aIdent);
|
NamedIndexRange range = global_namedIndex.equal_range(aIdent);
|
||||||
for (; range.first != range.second; ++range.first) {
|
for (; range.first != range.second; ++range.first) {
|
||||||
|
if (aFilter && !aFilter->pass(range.first->second)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
result.push_back(range.first->second);
|
result.push_back(range.first->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sortByDistance(aPos, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGPositionedRef
|
||||||
|
FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter)
|
||||||
|
{
|
||||||
|
FGPositioned::List l(spatialGetClosest(aPos, 1, aCutoffNm, aFilter));
|
||||||
|
if (l.empty()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(l.size() == 1);
|
||||||
|
return l.front();
|
||||||
|
}
|
||||||
|
|
||||||
FGPositioned::List
|
FGPositioned::List
|
||||||
FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, const Filter& aFilter)
|
FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter)
|
||||||
{
|
{
|
||||||
return spatialGetClosest(aPos, aN, aCutoffNm, aFilter);
|
return spatialGetClosest(aPos, aN, aCutoffNm, aFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FGPositionedRef
|
||||||
|
FGPositioned::findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter)
|
||||||
|
{
|
||||||
|
NamedIndexRange range = global_namedIndex.equal_range(aId);
|
||||||
|
for (; range.first != range.second; ++range.first) {
|
||||||
|
FGPositionedRef candidate = range.first->second;
|
||||||
|
if (aCur == candidate) {
|
||||||
|
aCur = NULL; // found our start point, next match will pass
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aFilter && !aFilter->pass(candidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aCur) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL; // fell out, no match in range
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,6 +71,14 @@ public:
|
||||||
const std::string& ident() const
|
const std::string& ident() const
|
||||||
{ return mIdent; }
|
{ return mIdent; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the name of this positioned. By default this is the same as the
|
||||||
|
* ident, but for many derived classes it's more meaningful - the aiport or
|
||||||
|
* navaid name, for example.
|
||||||
|
*/
|
||||||
|
virtual const std::string& name() const
|
||||||
|
{ return mIdent; }
|
||||||
|
|
||||||
const SGGeod& geod() const
|
const SGGeod& geod() const
|
||||||
{ return mPosition; }
|
{ return mPosition; }
|
||||||
|
|
||||||
|
@ -87,27 +95,64 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Predicate class to support custom filtering of FGPositioned queries
|
* Predicate class to support custom filtering of FGPositioned queries
|
||||||
|
* Default implementation of this passes any FGPositioned instance.
|
||||||
*/
|
*/
|
||||||
class Filter
|
class Filter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Filter() { ; }
|
virtual ~Filter() { ; }
|
||||||
|
|
||||||
virtual bool pass(FGPositioned* aPos) const = 0;
|
/**
|
||||||
|
* Over-rideable filter method. Default implementation returns true.
|
||||||
|
*/
|
||||||
|
virtual bool pass(FGPositioned* aPos) const
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
bool operator()(FGPositioned* aPos) const
|
bool operator()(FGPositioned* aPos) const
|
||||||
{ return pass(aPos); }
|
{ return pass(aPos); }
|
||||||
};
|
};
|
||||||
|
|
||||||
static List findWithinRange(const SGGeod& aPos, double aRangeNm, const Filter& aFilter);
|
class TypeFilter : public Filter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TypeFilter(Type aTy) : mType(aTy) { ; }
|
||||||
|
virtual bool pass(FGPositioned* aPos) const
|
||||||
|
{ return (mType == aPos->type()); }
|
||||||
|
private:
|
||||||
|
const Type mType;
|
||||||
|
};
|
||||||
|
|
||||||
static List findWithinRangeByType(const SGGeod& aPos, double aRangeNm, Type aTy);
|
static List findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter = NULL);
|
||||||
|
|
||||||
static FGPositionedRef findClosestWithIdent(const std::string& aIdent, double aLat, double aLon);
|
static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL);
|
||||||
|
|
||||||
static FGPositionedRef findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos);
|
/**
|
||||||
|
* Find the next item with the specified partial ID, after the 'current' item
|
||||||
|
* Note this function is not hyper-efficient, particular where the partial id
|
||||||
|
* spans a large number of candidates.
|
||||||
|
*
|
||||||
|
* @param aCur - Current item, or NULL to retrieve the first item with partial id
|
||||||
|
* @param aId - the (partial) id to lookup
|
||||||
|
*/
|
||||||
|
static FGPositionedRef findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter = NULL);
|
||||||
|
|
||||||
static List findAllWithIdent(const std::string& aIdent);
|
/**
|
||||||
|
* Find all items with the specified ident, and return then sorted by
|
||||||
|
* distance from a position
|
||||||
|
*
|
||||||
|
* @param aFilter - optional filter on items
|
||||||
|
*/
|
||||||
|
static List findAllWithIdentSortedByRange(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter = NULL);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the closest item to a position, which pass the specified filter
|
||||||
|
* A cutoff range in NM must be specified, to constrain the search acceptably.
|
||||||
|
* Very large cutoff values will make this slow.
|
||||||
|
*
|
||||||
|
* @result The closest item passing the filter, or NULL
|
||||||
|
* @param aCutoffNm - maximum distance to search within, in nautical miles
|
||||||
|
*/
|
||||||
|
static FGPositionedRef findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter = NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the closest N items to a position, which pass the specified filter
|
* Find the closest N items to a position, which pass the specified filter
|
||||||
|
@ -119,7 +164,9 @@ public:
|
||||||
* @param aN - number of matches to find
|
* @param aN - number of matches to find
|
||||||
* @param aCutoffNm - maximum distance to search within, in nautical miles
|
* @param aCutoffNm - maximum distance to search within, in nautical miles
|
||||||
*/
|
*/
|
||||||
static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, const Filter& aFilter);
|
static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter = NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Debug helper, map a type to a human-readable string
|
* Debug helper, map a type to a human-readable string
|
||||||
|
|
Loading…
Add table
Reference in a new issue