]> git.mxchange.org Git - flightgear.git/commitdiff
- make FGAirport::search() more versatile, so that it can't only search
authormfranz <mfranz>
Fri, 5 Oct 2007 21:54:52 +0000 (21:54 +0000)
committermfranz <mfranz>
Fri, 5 Oct 2007 21:54:52 +0000 (21:54 +0000)
  the next airport or airport with METAR station, but about any type of
  airport
- as a side effect this change makes it also 30 to 50% faster  :-)

In the long run this linear search shall be replaced with a spatial
algorithm (like octree), which will be a much bigger performance gain.

src/Airports/simple.cxx
src/Airports/simple.hxx
src/Environment/environment_ctrl.cxx
src/Instrumentation/gps.cxx
src/Scripting/NasalSys.cxx

index 6efac4c0e25a853ee85d117a983184d65c0a34cd..e92b08fbd1c9e264392fc24c09db8e105429ca5b 100644 (file)
@@ -187,25 +187,35 @@ const FGAirport* FGAirportList::findFirstById( const string& id, bool exact )
 
 
 // search for the airport nearest the specified position
 
 
 // search for the airport nearest the specified position
-FGAirport* FGAirportList::search( double lon_deg, double lat_deg,
-                                  bool with_metar )
+FGAirport* FGAirportList::search(double lon_deg, double lat_deg)
+{
+    static FGAirportSearchFilter accept_any;
+    return search(lon_deg, lat_deg, accept_any);
+}
+
+
+// search for the airport nearest the specified position and
+// passing the filter
+FGAirport* FGAirportList::search(double lon_deg, double lat_deg,
+        FGAirportSearchFilter& search)
 {
 {
-    int closest = -1;
     double min_dist = 360.0;
     double min_dist = 360.0;
-    unsigned int i;
-    for ( i = 0; i < airports_array.size(); ++i ) {
+    airport_list_iterator it = airports_array.begin();
+    airport_list_iterator end = airports_array.end();
+    airport_list_iterator closest = end;
+    for (; it != end; ++it) {
+        if (!search.acceptable(*it))
+            continue;
+
         // crude manhatten distance based on lat/lon difference
         // crude manhatten distance based on lat/lon difference
-        double d = fabs(lon_deg - airports_array[i]->getLongitude())
-            + fabs(lat_deg - airports_array[i]->getLatitude());
-        if ( d < min_dist ) {
-            if ( !with_metar || (with_metar&&airports_array[i]->getMetar()) ) {
-                closest = i;
-                min_dist = d;
-            }
+        double d = fabs(lon_deg - (*it)->getLongitude())
+                + fabs(lat_deg - (*it)->getLatitude());
+        if (d < min_dist) {
+            closest = it;
+            min_dist = d;
         }
     }
         }
     }
-
-    return ( closest > -1 ? airports_array[closest] : NULL );
+    return closest != end ? *closest : 0;
 }
 
 
 }
 
 
index 9251ee423a7fa08d3a2f1585741a3e8a08ee9fcd..d1930730a019746756849a14703f4eab95432f82 100644 (file)
@@ -106,6 +106,12 @@ private:
 };
 
 
 };
 
 
+class FGAirportSearchFilter {
+public:
+    virtual ~FGAirportSearchFilter() {}
+    virtual bool acceptable(FGAirport*) { return true; }
+};
+
 
 typedef map < string, FGAirport* > airport_map;
 typedef airport_map::iterator airport_map_iterator;
 
 typedef map < string, FGAirport* > airport_map;
 typedef airport_map::iterator airport_map_iterator;
@@ -122,7 +128,6 @@ private:
 
     airport_map airports_by_id;
     airport_list airports_array;
 
     airport_map airports_by_id;
     airport_list airports_array;
-    //set < string > ai_dirs;
 
 public:
     // Constructor (new)
 
 public:
     // Constructor (new)
@@ -150,10 +155,10 @@ public:
 
     // search for the airport closest to the specified position
     // (currently a linear inefficient search so it's probably not
 
     // 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.
-    // 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 );
+    // best to use this at runtime.)  An FGAirportSearchFilter class
+    // can be used to restrict the possible choices to a subtype.
+    FGAirport* search( double lon_deg, double lat_deg );
+    FGAirport* search( double lon_deg, double lat_deg, FGAirportSearchFilter& );
 
     /**
      * Return the number of airports in the list.
 
     /**
      * Return the number of airports in the list.
index 82af0e02725cdb0a1d263db441ce7fe8b81d17da..5733ed67a3f3d3f21e103b17e80994cc27498956 100644 (file)
@@ -41,6 +41,9 @@
 
 SG_USING_STD(sort);
 
 
 SG_USING_STD(sort);
 
+class metar_filter : public FGAirportSearchFilter {
+    virtual bool acceptable(FGAirport *a) { return a->getMetar(); }
+} metar_only;
 
 \f
 ////////////////////////////////////////////////////////////////////////
 
 \f
 ////////////////////////////////////////////////////////////////////////
@@ -648,7 +651,7 @@ FGMetarEnvironmentCtrl::init ()
         const FGAirport* a = globals->get_airports()
                    ->search( longitude->getDoubleValue(),
                              latitude->getDoubleValue(),
         const FGAirport* a = globals->get_airports()
                    ->search( longitude->getDoubleValue(),
                              latitude->getDoubleValue(),
-                             true );
+                             metar_only );
         if ( a ) {  
             FGMetarResult result = fetch_data( a->getId() );
             if ( result.m != NULL ) {
         if ( a ) {  
             FGMetarResult result = fetch_data( a->getId() );
             if ( result.m != NULL ) {
@@ -711,7 +714,7 @@ FGMetarEnvironmentCtrl::update(double delta_time_sec)
         const FGAirport* a = globals->get_airports()
                    ->search( longitude->getDoubleValue(),
                              latitude->getDoubleValue(),
         const FGAirport* a = globals->get_airports()
                    ->search( longitude->getDoubleValue(),
                              latitude->getDoubleValue(),
-                             true );
+                             metar_only );
         if ( a ) {
             if ( !last_apt || last_apt->getId() != a->getId()
                  || fetch_elapsed > same_station_interval_sec )
         if ( a ) {
             if ( !last_apt || last_apt->getId() != a->getId()
                  || fetch_elapsed > same_station_interval_sec )
index ae0f3c8101829858f934199dc42ddcf53143482f..b466948c42d3a1bc08ff96283de84c1154f2b25f 100644 (file)
@@ -308,7 +308,7 @@ 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()) {
         // If the get-nearest-airport-node is true.
         // Get the nearest airport, and set it as waypoint 1.
         if (_get_nearest_airport_node->getBoolValue()) {
-            const FGAirport* a = globals->get_airports()->search(longitude_deg, latitude_deg, false);
+            const FGAirport* a = globals->get_airports()->search(longitude_deg, latitude_deg);
             if(a) {
                 _wp1_ID_node->setStringValue(a->getId().c_str());
                 wp1_longitude_deg = a->getLongitude();
             if(a) {
                 _wp1_ID_node->setStringValue(a->getId().c_str());
                 wp1_longitude_deg = a->getLongitude();
index 32dcb98e6256c311587ff4978fbb0da40063f999..423935d342eea93c8b9046d858f1bc492fa8c5ff 100644 (file)
@@ -496,11 +496,11 @@ static naRef f_airportinfo(naContext c, naRef me, int argc, naRef* args)
     FGAirportList *aptlst = globals->get_airports();
     FGAirport *apt;
     if(argc == 0)
     FGAirportList *aptlst = globals->get_airports();
     FGAirport *apt;
     if(argc == 0)
-        apt = aptlst->search(lon->getDoubleValue(), lat->getDoubleValue(), false);
+        apt = aptlst->search(lon->getDoubleValue(), lat->getDoubleValue());
     else if(argc == 1 && naIsString(args[0]))
         apt = aptlst->search(naStr_data(args[0]));
     else if(argc == 2 && naIsNum(args[0]) && naIsNum(args[1]))
     else if(argc == 1 && naIsString(args[0]))
         apt = aptlst->search(naStr_data(args[0]));
     else if(argc == 2 && naIsNum(args[0]) && naIsNum(args[1]))
-        apt = aptlst->search(args[1].num, args[0].num, false);
+        apt = aptlst->search(args[1].num, args[0].num);
     else {
         naRuntimeError(c, "airportinfo() with invalid function arguments");
         return naNil();
     else {
         naRuntimeError(c, "airportinfo() with invalid function arguments");
         return naNil();