]> git.mxchange.org Git - flightgear.git/blobdiff - src/Navaids/positioned.cxx
Synchronized with JSBSim/CVS
[flightgear.git] / src / Navaids / positioned.cxx
index bced11728b6064a703689c3fb499dbddb75c5e30..89d41475583e0a8e87a353e53dd592033b8bc836 100644 (file)
@@ -30,6 +30,7 @@
 #include <queue>
 #include <memory>
 
+#include <boost/foreach.hpp>
 #include <boost/algorithm/string/case_conv.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 
@@ -53,6 +54,16 @@ static void validateSGGeod(const SGGeod& geod)
   }
 }
 
+static bool validateFilter(FGPositioned::Filter* filter)
+{
+    if (filter->maxType() < filter->minType()) {
+        SG_LOG(SG_GENERAL, SG_WARN, "invalid positioned filter specified");
+        return false;
+    }
+    
+    return true;
+}
+
 
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -73,10 +84,25 @@ FGPositioned::~FGPositioned()
 FGPositioned*
 FGPositioned::createUserWaypoint(const std::string& aIdent, const SGGeod& aPos)
 {
-  PositionedID id = NavDataCache::instance()->createUserWaypoint(aIdent, aPos);
-  return NavDataCache::instance()->loadById(id);
+  NavDataCache* cache = NavDataCache::instance();
+  TypeFilter filter(WAYPOINT);
+  FGPositionedList existing = cache->findAllWithIdent(aIdent, &filter, true);
+  if (!existing.empty()) {
+    SG_LOG(SG_NAVAID, SG_WARN, "attempt to insert duplicate WAYPOINT:" << aIdent);
+    return existing.front().ptr();
+  }
+  
+  PositionedID id = cache->createPOI(WAYPOINT, aIdent, aPos);
+  return cache->loadById(id);
+}
+
+bool FGPositioned::deleteUserWaypoint(const std::string& aIdent)
+{
+  NavDataCache* cache = NavDataCache::instance();
+  return cache->removePOI(WAYPOINT, aIdent);
 }
 
+
 const SGVec3d&
 FGPositioned::cart() const
 {
@@ -111,12 +137,21 @@ FGPositioned::Type FGPositioned::typeFromName(const std::string& aName)
     {"ground", FREQ_GROUND},
     {"approach", FREQ_APP_DEP},
     {"departure", FREQ_APP_DEP},
+    {"runway", RUNWAY},
+    {"helipad", HELIPAD},
+    {"country", COUNTRY},
+    {"city", CITY},
+    {"town", TOWN},
+    {"village", VILLAGE},
+      
   // aliases
+    {"localizer", LOC},
     {"gnd", FREQ_GROUND},
     {"twr", FREQ_TOWER},
     {"waypoint", WAYPOINT},
     {"apt", AIRPORT},
     {"arpt", AIRPORT},
+    {"rwy", RUNWAY},
     {"any", INVALID},
     {"all", INVALID},
     
@@ -139,6 +174,7 @@ const char* FGPositioned::nameForType(Type aTy)
 {
  switch (aTy) {
  case RUNWAY: return "runway";
+ case HELIPAD: return "helipad";
  case TAXIWAY: return "taxiway";
  case PAVEMENT: return "pavement";
  case PARKING: return "parking stand";
@@ -146,7 +182,7 @@ const char* FGPositioned::nameForType(Type aTy)
  case VOR: return "VOR";
  case NDB: return "NDB";
  case ILS: return "ILS";
- case LOC: return "localiser";
+ case LOC: return "localizer";
  case GS: return "glideslope";
  case OM: return "outer-marker";
  case MM: return "middle-marker";
@@ -165,6 +201,10 @@ const char* FGPositioned::nameForType(Type aTy)
  case FREQ_UNICOM: return "unicom";
  case FREQ_APP_DEP: return "approach-departure";
  case TAXI_NODE: return "taxi-node";
+ case COUNTRY: return "country";
+ case CITY: return "city";
+ case TOWN: return "town";
+ case VILLAGE: return "village";
  default:
   return "unknown";
  }
@@ -187,7 +227,8 @@ FGPositioned::findFirstWithIdent(const std::string& aIdent, Filter* aFilter)
     return NULL;
   }
   
-  List r = NavDataCache::instance()->findAllWithIdent(aIdent, aFilter, true);
+  FGPositionedList r =
+    NavDataCache::instance()->findAllWithIdent(aIdent, aFilter, true);
   if (r.empty()) {
     return NULL;
   }
@@ -195,26 +236,55 @@ FGPositioned::findFirstWithIdent(const std::string& aIdent, Filter* aFilter)
   return r.front();
 }
 
-FGPositioned::List
+FGPositionedList
 FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter)
 {
   validateSGGeod(aPos);
 
-  List result;
+    if (!validateFilter(aFilter)) {
+        return FGPositionedList();
+    }
+    
+  FGPositionedList result;
   Octree::findAllWithinRange(SGVec3d::fromGeod(aPos), 
-    aRangeNm * SG_NM_TO_METER, aFilter, result);
+    aRangeNm * SG_NM_TO_METER, aFilter, result, 0xffffff);
+  return result;
+}
+
+FGPositionedList
+FGPositioned::findWithinRangePartial(const SGGeod& aPos, double aRangeNm, Filter* aFilter, bool& aPartial)
+{
+  validateSGGeod(aPos);
+  
+    if (!validateFilter(aFilter)) {
+        return FGPositionedList();
+    }
+    
+  int limitMsec = 32;
+  FGPositionedList result;
+  aPartial = Octree::findAllWithinRange(SGVec3d::fromGeod(aPos),
+                             aRangeNm * SG_NM_TO_METER, aFilter, result,
+                                        limitMsec);
   return result;
 }
 
-FGPositioned::List
+FGPositionedList
 FGPositioned::findAllWithIdent(const std::string& aIdent, Filter* aFilter, bool aExact)
 {
+    if (!validateFilter(aFilter)) {
+        return FGPositionedList();
+    }
+    
   return NavDataCache::instance()->findAllWithIdent(aIdent, aFilter, aExact);
 }
 
-FGPositioned::List
+FGPositionedList
 FGPositioned::findAllWithName(const std::string& aName, Filter* aFilter, bool aExact)
 {
+    if (!validateFilter(aFilter)) {
+        return FGPositionedList();
+    }
+    
   return NavDataCache::instance()->findAllWithName(aName, aFilter, aExact);
 }
 
@@ -223,7 +293,11 @@ FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter)
 {
   validateSGGeod(aPos);
   
-  List l(findClosestN(aPos, 1, aCutoffNm, aFilter));
+    if (!validateFilter(aFilter)) {
+        return NULL;
+    }
+    
+  FGPositionedList l(findClosestN(aPos, 1, aCutoffNm, aFilter));
   if (l.empty()) {
     return NULL;
   }
@@ -232,25 +306,38 @@ FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter)
   return l.front();
 }
 
-FGPositioned::List
+FGPositionedList
 FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter)
 {
   validateSGGeod(aPos);
   
-  List result;
-  Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result);
+  FGPositionedList result;
+  int limitMsec = 0xffff;
+  Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result, limitMsec);
   return result;
 }
+
+FGPositionedList
+FGPositioned::findClosestNPartial(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter, bool &aPartial)
+{
+    validateSGGeod(aPos);
+    
+    FGPositionedList result;
+    int limitMsec = 32;
+    aPartial = Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result,
+                        limitMsec);
+    return result;
+}
+
 void
-FGPositioned::sortByRange(List& aResult, const SGGeod& aPos)
+FGPositioned::sortByRange(FGPositionedList& aResult, const SGGeod& aPos)
 {
   validateSGGeod(aPos);
   
   SGVec3d cartPos(SGVec3d::fromGeod(aPos));
 // computer ordering values
   Octree::FindNearestResults r;
-  List::iterator it = aResult.begin(), lend = aResult.end();
+  FGPositionedList::iterator it = aResult.begin(), lend = aResult.end();
   for (; it != lend; ++it) {
     double d2 = distSqr((*it)->cart(), cartPos);
     r.push_back(Octree::OrderedPositioned(*it, d2));
@@ -272,9 +359,15 @@ void FGPositioned::modifyPosition(const SGGeod& newPos)
   const_cast<SGVec3d&>(mCart) = SGVec3d::fromGeod(newPos);
 }
 
+//------------------------------------------------------------------------------
+FGPositionedRef FGPositioned::loadByIdImpl(PositionedID id)
+{
+  return flightgear::NavDataCache::instance()->loadById(id);
+}
+
 FGPositioned::TypeFilter::TypeFilter(Type aTy) :
-  mMinType(aTy),
-  mMaxType(aTy)
+  mMinType(LAST_TYPE),
+  mMaxType(INVALID)
 {
   addType(aTy);
 }
@@ -290,6 +383,23 @@ void FGPositioned::TypeFilter::addType(Type aTy)
   mMaxType = std::max(mMaxType, aTy);
 }
 
+FGPositioned::TypeFilter
+FGPositioned::TypeFilter::fromString(const std::string& aFilterSpec)
+{
+  if (aFilterSpec.empty()) {
+    throw sg_format_exception("empty filter spec:", aFilterSpec);
+  }
+  
+  string_list parts = simgear::strutils::split(aFilterSpec, ",");
+  TypeFilter f;
+  
+  BOOST_FOREACH(std::string token, parts) {
+    f.addType(typeFromName(token));
+  }
+  
+  return f;
+}
+
 bool
 FGPositioned::TypeFilter::pass(FGPositioned* aPos) const
 {
@@ -300,7 +410,9 @@ FGPositioned::TypeFilter::pass(FGPositioned* aPos) const
     std::vector<Type>::const_iterator it = types.begin(),
         end = types.end();
     for (; it != end; ++it) {
-        return aPos->type() == *it;
+        if (aPos->type() == *it) {
+            return true;
+        }
     }
     
     return false;