" 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)");
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;
insertCommStation, insertNavaid;
sqlite3_stmt_ptr setAirportMetar, setRunwayReciprocal, setRunwayILS,
setAirportPos, updateRunwayThreshold, updateILS;
+ sqlite3_stmt_ptr removePOIQuery;
sqlite3_stmt_ptr findClosestWithIdent;
// octree (spatial index) related queries
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;
}
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)
{
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
{
{"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},
{
switch (aTy) {
case RUNWAY: return "runway";
+ case HELIPAD: return "helipad";
case TAXIWAY: return "taxiway";
case PAVEMENT: return "pavement";
case PARKING: return "parking stand";
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";
}