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;