-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));
-
- 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.
-}
-
-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));
-
- // 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;
-}
-
-FGNavRecord* DCLGPS::FindClosestVor(double lat_rad, double lon_rad) {
- return(globals->get_navlist()->findClosest(lon_rad, lat_rad, 0.0, FG_NAV_VOR));
+FGPositioned* DCLGPS::FindTypedFirstById(const string& id, FGPositioned::Type ty, bool &multi, bool exact)
+{
+ multi = false;
+ FGPositioned::TypeFilter filter(ty);
+
+ if (exact) {
+ FGPositioned::List matches =
+ FGPositioned::findAllWithIdentSortedByRange(id, SGGeod::fromRad(_lon, _lat), &filter);
+ multi = (matches.size() > 1);
+ return matches.empty() ? NULL : matches.front().ptr();
+ }
+
+ return FGPositioned::findNextWithPartialId(NULL, id, &filter);
+}
+
+FGNavRecord* DCLGPS::FindFirstVorById(const string& id, bool &multi, bool exact)
+{
+ return dynamic_cast<FGNavRecord*>(FindTypedFirstById(id, FGPositioned::VOR, multi, exact));
+}
+
+FGNavRecord* DCLGPS::FindFirstNDBById(const string& id, bool &multi, bool exact)
+{
+ 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) {
+ 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());