}
-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')
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);
}
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();
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 );
}
/**
- * 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());
{
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
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
// 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;
}
}
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