diff --git a/src/Navaids/NavDataCache.cxx b/src/Navaids/NavDataCache.cxx
index ee7b90d95..aeb70cc30 100644
--- a/src/Navaids/NavDataCache.cxx
+++ b/src/Navaids/NavDataCache.cxx
@@ -573,6 +573,8 @@ public:
                            " VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)");
     runwayLengthFtQuery = prepare("SELECT length_ft FROM runway WHERE rowid=?1");
     
+    removePOIQuery = prepare("DELETE FROM positioned WHERE type=?1 AND ident=?2");
+    
   // query statement    
     findClosestWithIdent = prepare("SELECT rowid FROM positioned WHERE ident=?1 "
                                    AND_TYPED " ORDER BY distanceCartSqr(cart_x, cart_y, cart_z, ?4, ?5, ?6)");
@@ -921,6 +923,14 @@ public:
     
     deferredOctreeUpdates.clear();
   }
+    
+  void removePositionedWithIdent(FGPositioned::Type ty, const std::string& aIdent)
+  {
+    sqlite3_bind_int(removePOIQuery, 1, ty);
+    sqlite_bind_stdstring(removePOIQuery, 2, aIdent);
+    execUpdate(removePOIQuery);
+    reset(removePOIQuery);
+  }
   
   NavDataCache* outer;
   sqlite3* db;
@@ -952,6 +962,7 @@ public:
   insertCommStation, insertNavaid;
   sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS,
     setAirportPos, updateRunwayThreshold, updateILS;
+  sqlite3_stmt_ptr removePOIQuery;
   
   sqlite3_stmt_ptr findClosestWithIdent;
 // octree (spatial index) related queries
@@ -1056,8 +1067,11 @@ FGPositioned* NavDataCache::NavDataCachePrivate::loadById(sqlite3_int64 rowid)
       return new FGFix(rowid, ident, pos);
       
     case FGPositioned::WAYPOINT:
+    case FGPositioned::COUNTRY:
+    case FGPositioned::CITY:
+    case FGPositioned::TOWN:
     {
-      FGPositioned* wpt = new FGPositioned(rowid, FGPositioned::WAYPOINT, ident, pos);
+        FGPositioned* wpt = new FGPositioned(rowid, ty, ident, pos);
       return wpt;
     }
       
@@ -1629,11 +1643,17 @@ PositionedID NavDataCache::insertFix(const std::string& ident, const SGGeod& aPo
   return d->insertPositioned(FGPositioned::FIX, ident, string(), aPos, 0, true);
 }
 
-PositionedID NavDataCache::createUserWaypoint(const std::string& ident, const SGGeod& aPos)
+PositionedID NavDataCache::createPOI(FGPositioned::Type ty, const std::string& ident, const SGGeod& aPos)
 {
-  return d->insertPositioned(FGPositioned::WAYPOINT, ident, string(), aPos, 0,
+  return d->insertPositioned(ty, ident, string(), aPos, 0,
                              true /* spatial index */);
 }
+    
+void NavDataCache::removePOI(FGPositioned::Type ty, const std::string& aIdent)
+{
+  d->removePositionedWithIdent(ty, aIdent);
+  // should remove from the live cache too?
+}
   
 void NavDataCache::setAirportMetar(const string& icao, bool hasMetar)
 {
diff --git a/src/Navaids/NavDataCache.hxx b/src/Navaids/NavDataCache.hxx
index dc78d8be5..93ef318c7 100644
--- a/src/Navaids/NavDataCache.hxx
+++ b/src/Navaids/NavDataCache.hxx
@@ -116,8 +116,10 @@ public:
                                 PositionedID apt);
   PositionedID insertFix(const std::string& ident, const SGGeod& aPos);
   
-  PositionedID createUserWaypoint(const std::string& ident, const SGGeod& aPos);
+  PositionedID createPOI(FGPositioned::Type ty, const std::string& ident, const SGGeod& aPos);
   
+  void removePOI(FGPositioned::Type ty, const std::string& aIdent);
+    
   void dropGroundnetFor(PositionedID aAirport);
   
   PositionedID insertParking(const std::string& name, const SGGeod& aPos,
diff --git a/src/Navaids/positioned.cxx b/src/Navaids/positioned.cxx
index 92250b906..ee60aca80 100644
--- a/src/Navaids/positioned.cxx
+++ b/src/Navaids/positioned.cxx
@@ -73,10 +73,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);
+  FGPositioned::List 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);
 }
 
+void FGPositioned::deleteUserWaypoint(const std::string& aIdent)
+{
+  NavDataCache* cache = NavDataCache::instance();
+  cache->removePOI(WAYPOINT, aIdent);
+}
+
+
 const SGVec3d&
 FGPositioned::cart() const
 {
@@ -111,12 +126,19 @@ 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},
+      
   // aliases
     {"gnd", FREQ_GROUND},
     {"twr", FREQ_TOWER},
     {"waypoint", WAYPOINT},
     {"apt", AIRPORT},
     {"arpt", AIRPORT},
+    {"rwy", RUNWAY},
     {"any", INVALID},
     {"all", INVALID},
     
@@ -139,6 +161,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";
@@ -165,6 +188,9 @@ 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";
  default:
   return "unknown";
  }
diff --git a/src/Navaids/positioned.hxx b/src/Navaids/positioned.hxx
index 7aaaf22ad..aeaea6f12 100644
--- a/src/Navaids/positioned.hxx
+++ b/src/Navaids/positioned.hxx
@@ -81,6 +81,11 @@ public:
 // groundnet items
     PARKING,  ///< parking position - might be a gate, or stand
     TAXI_NODE,
+// POI items
+    COUNTRY,
+    CITY,
+    TOWN,
+      
     LAST_TYPE
   } Type;
 
@@ -230,6 +235,7 @@ public:
   static const char* nameForType(Type aTy);
   
   static FGPositioned* createUserWaypoint(const std::string& aIdent, const SGGeod& aPos);
+  static void deleteUserWaypoint(const std::string& aIdent);
 protected:
   friend class flightgear::NavDataCache;