]> git.mxchange.org Git - flightgear.git/commitdiff
James Turner:
authorfredb <fredb>
Wed, 3 Dec 2008 20:03:46 +0000 (20:03 +0000)
committerfredb <fredb>
Wed, 3 Dec 2008 20:03:46 +0000 (20:03 +0000)
Attached patch updates the route-manager to use FGPositioned to search
for waypoints, instead of a manual airport / fix / navaid search. This
is good because it's now using the 'strictly closest' match, rather
than arbitrarily picking a distant fix over a nearby navaid. In my
case, the TLA VOR is significant to several EGPH procedures, but also
happens to be the ident of a fix a long, long way away.

Also updates the FGPositioned class to stop using Point3D, partly
because it's deprecated and partly because I had misunderstood the
interface and was using it wrong. For now, all FGPositioned distance
checks use SGGeodesy::inverse, which is accurate but inefficient. Once
FGPositioned queries are used for something on a hot path, I'll
probably store the cartesian position as well as the geodetic, to make
these checks fast.

src/Autopilot/route_mgr.cxx
src/Autopilot/route_mgr.hxx
src/Navaids/positioned.cxx

index e657f2d634be58fd1a77f715904a4b1933fb03ea..b52fa4fe88ce694650779d8b2a9113d5046e35fe 100644 (file)
@@ -281,24 +281,24 @@ bool FGRouteMgr::build() {
 }
 
 
-int FGRouteMgr::new_waypoint( const string& target, int n ) {
-    SGWayPoint *wp = 0;
-    int type = make_waypoint( &wp, target );
-
-    if (wp) {
-        add_waypoint( *wp, n );
-        delete wp;
+void FGRouteMgr::new_waypoint( const string& target, int n ) {
+    SGWayPoint* wp = make_waypoint( target );
+    if (!wp) {
+        return;
+    }
+    
+    add_waypoint( *wp, n );
+    delete wp;
 
-        if ( !near_ground() )
-            fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
+    if ( !near_ground() ) {
+        fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
     }
-    return type;
 }
 
 
-int FGRouteMgr::make_waypoint( SGWayPoint **wp, const string& tgt ) {
+SGWayPoint* FGRouteMgr::make_waypoint(const string& tgt ) {
     string target = tgt;
-
+    
     // make upper case
     for (unsigned int i = 0; i < target.size(); i++)
         if (target[i] >= 'a' && target[i] <= 'z')
@@ -321,57 +321,28 @@ int FGRouteMgr::make_waypoint( SGWayPoint **wp, const string& tgt ) {
         double lat = atof( target.c_str() + pos + 1);
 
         SG_LOG( SG_GENERAL, SG_INFO, "Adding waypoint lon = " << lon << ", lat = " << lat );
-        *wp = new SGWayPoint( lon, lat, alt, SGWayPoint::WGS84, target );
-        return 1;
-    }
-
-    // check for airport id
-    const FGAirport *apt = fgFindAirportID( target );
-    if (apt) {
-        SG_LOG( SG_GENERAL, SG_INFO, "Adding waypoint (airport) = " << target );
-        *wp = new SGWayPoint( apt->getLongitude(), apt->getLatitude(), alt, SGWayPoint::WGS84, target );
-        return 2;
-    }
+        return new SGWayPoint( lon, lat, alt, SGWayPoint::WGS84, target );
+    }    
 
-    double lat, lon;
-    // The base lon/lat are determined by the last WP,
-    // or the current pos if the WP list is empty.
-    const int wps = this->size();
-
-    if (wps > 0) {
-        SGWayPoint wp = get_waypoint(wps-1);
-        lat = wp.get_target_lat();
-        lon = wp.get_target_lon();
+    SGGeod basePosition;
+    if (route->size() > 0) {
+        SGWayPoint wp = get_waypoint(route->size()-1);
+        basePosition = SGGeod::fromDeg(wp.get_target_lon(), wp.get_target_lat());
     } else {
-        lat = fgGetNode("/position/latitude-deg")->getDoubleValue();
-        lon = fgGetNode("/position/longitude-deg")->getDoubleValue();
-    }
-
-    // check for fix id
-    FGFix* f;
-    double heading;
-    double dist;
-
-    if ( globals->get_fixlist()->query_and_offset( target, lon, lat, 0, f, &heading, &dist ) ) {
-        SG_LOG( SG_GENERAL, SG_INFO, "Adding waypoint (fix) = " << target );
-        *wp = new SGWayPoint( f->get_lon(), f->get_lat(), alt, SGWayPoint::WGS84, target );
-        return 3;
+        // route is empty, use current position
+        basePosition = SGGeod::fromDeg(
+            fgGetNode("/position/longitude-deg")->getDoubleValue(), 
+            fgGetNode("/position/latitude-deg")->getDoubleValue());
     }
 
-    // Try finding a nav matching the ID
-    lat *= SGD_DEGREES_TO_RADIANS;
-    lon *= SGD_DEGREES_TO_RADIANS;
-
-    SG_LOG( SG_GENERAL, SG_INFO, "Looking for nav " << target << " at " << lon << " " << lat);
 
-    if (FGNavRecord* nav = globals->get_navlist()->findByIdent(target.c_str(), lon, lat)) {
-        SG_LOG( SG_GENERAL, SG_INFO, "Adding waypoint (nav) = " << target );
-        *wp = new SGWayPoint( nav->get_lon(), nav->get_lat(), alt, SGWayPoint::WGS84, target );
-        return 4;
+    FGPositionedRef p = FGPositioned::findClosestWithIdent(target, basePosition);
+    if (!p) {
+        SG_LOG( SG_GENERAL, SG_INFO, "Unable to find FGPositioned with ident:" << target);
+        return NULL;
     }
-
-    // unknown target
-    return 0;
+    
+    return new SGWayPoint(p->longitude(), p->latitude(), p->elevation(), SGWayPoint::WGS84, target);
 }
 
 
index 67a27d7c8b9636c811b3f593fde6c08152f1ef58..f409a8c4e3ab5a0186fab5a4a14bea9c03ce6009 100644 (file)
@@ -93,7 +93,7 @@ private:
     SGPropertyNode_ptr mirror;
     bool altitude_set;
 
-    int make_waypoint( SGWayPoint **wp, const string& target );
+    SGWayPoint* make_waypoint(const string& target);
     void update_mirror();
     bool near_ground();
 
@@ -110,7 +110,7 @@ public:
 
     bool build ();
 
-    int new_waypoint( const string& tgt_alt, int n = -1 );
+    void new_waypoint( const string& tgt_alt, int n = -1 );
     void add_waypoint( const SGWayPoint& wp, int n = -1 );
     SGWayPoint pop_waypoint( int i = 0 );
 
index e2a5b8d1dfaf59a4f993b0fdcd1cfb3c72354033..a89d28f2902a560a2a54bb15f9ea1e266e49e776 100644 (file)
@@ -182,38 +182,31 @@ spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, F
 }
 
 /**
- * Cartesian range predicate. Note that for really long ranges, might need to
- * to use geodetic / geocentric distance instead
  */
 class RangePredictate
 {
 public:
-  RangePredictate(const Point3D& aOrigin, double aRange) :
+  RangePredictate(const SGGeod& aOrigin, double aRange) :
     mOrigin(aOrigin),
-    mRangeSquared(aRange * aRange)
+    mRange(aRange)
   { ; }
   
   bool operator()(const FGPositionedRef& aPos)
   {
-    Point3D p(Point3D::fromSGGeod(aPos->geod()));
-    bool ok = (mOrigin.distance3Dsquared(p) > mRangeSquared);
-    if (ok) {
-      double x = sqrt(mOrigin.distance3Dsquared(p) - mRangeSquared);
-      x *= SG_METER_TO_NM;
-      //std::cout << "pos:" << aPos->ident() << " failed range check by " << x << std::endl;
-    }
-    return ok;
+    double d, az1, az2;
+    SGGeodesy::inverse(aPos->geod(), mOrigin, az1, az2, d);
+    return (d > mRange);
   }
   
 private:
-  Point3D mOrigin;
-  double mRangeSquared;
+  SGGeod mOrigin;
+  double mRange;
 };
 
 static void
 filterListByRange(const SGGeod& aPos, double aRange, FGPositioned::List& aResult)
 {
-  RangePredictate pred(Point3D::fromSGGeod(aPos), aRange * SG_NM_TO_METER);
+  RangePredictate pred(aPos, aRange * SG_NM_TO_METER);
   FGPositioned::List::iterator newEnd; 
   newEnd = std::remove_if(aResult.begin(), aResult.end(), pred);
   aResult.erase(newEnd, aResult.end());
@@ -223,17 +216,19 @@ class DistanceOrdering
 {
 public:
   DistanceOrdering(const SGGeod& aPos) :
-    mPos(Point3D::fromSGGeod(aPos))
+    mPos(aPos)
   { }
   
   bool operator()(const FGPositionedRef& a, const FGPositionedRef& b) const
   {
-    return mPos.distance3Dsquared(Point3D::fromSGGeod(a->geod())) < 
-      mPos.distance3Dsquared(Point3D::fromSGGeod(b->geod()));
+    double dA, dB, az1, az2;
+    SGGeodesy::inverse(mPos, a->geod(), az1, az2, dA);
+    SGGeodesy::inverse(mPos, b->geod(), az1, az2, dB);
+    return dA < dB;
   }
 
 private:
-  Point3D mPos;
+  SGGeod mPos;
 };
 
 static void
@@ -247,7 +242,9 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin,
   FGPositioned::Type aLower, FGPositioned::Type aUpper)
 {
   NamedIndexRange range = global_namedIndex.equal_range(aIdent);
-  if (range.first == range.second) return NULL;
+  if (range.first == range.second) {
+    return NULL;
+  }
   
 // common case, only one result. looks a bit ugly because these are
 // sequential iterators, not random-access ones
@@ -265,21 +262,21 @@ namedFindClosestTyped(const std::string& aIdent, const SGGeod& aOrigin,
 // multiple matches, we need to actually check the distance to each one
   double minDist = HUGE_VAL;
   FGPositionedRef result;
-  Point3D origin(Point3D::fromSGGeod(aOrigin));
-  
-  for (; range.first != range.second; ++range.first) {
+  NamedPositionedIndex::const_iterator it = range.first;
+    
+  for (; it != range.second; ++it) {
   // filter by type
-    FGPositioned::Type ty = range.first->second->type();
+    FGPositioned::Type ty = it->second->type();
     if ((ty < aLower) || (ty > aUpper)) {
       continue;
     }
     
   // find distance
-    Point3D p(Point3D::fromSGGeod(range.first->second->geod()));
-    double ds = origin.distance3Dsquared(p);
-    if (ds < minDist) {
-      minDist = ds;
-      result = range.first->second;
+    double d, az1, az2;
+    SGGeodesy::inverse(aOrigin, it->second->geod(), az2, az2, d);
+    if (d < minDist) {
+      minDist = d;
+      result = it->second;
     }
   }
   
@@ -340,26 +337,25 @@ FGPositioned::FGPositioned() :
 
 FGPositioned::FGPositioned(Type ty, const std::string& aIdent, double aLat, double aLon, double aElev) :
   mType(ty),
-  mIdent(aIdent),
-  mPosition(SGGeod::fromDegFt(aLon, aLat, aElev))
+  mPosition(SGGeod::fromDegFt(aLon, aLat, aElev)),
+  mIdent(aIdent)
 {
-  //addToIndices(this);
-  //SGReferenced::get(this); // hold an owning ref, for the moment
+  addToIndices(this);
+  SGReferenced::get(this); // hold an owning ref, for the moment
 }
 
 FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos) :
   mType(ty),
-  mIdent(aIdent),
-  mPosition(aPos)
+  mPosition(aPos),
+  mIdent(aIdent)
 {
-  //addToIndices(this);
-  //SGReferenced::get(this); // hold an owning ref, for the moment
+  addToIndices(this);
+  SGReferenced::get(this); // hold an owning ref, for the moment
 }
 
 FGPositioned::~FGPositioned()
 {
-  //std::cout << "~FGPositioned:" << mIdent << std::endl;
-  //removeFromIndices(this);
+  removeFromIndices(this);
 }
 
 SGBucket