1
0
Fork 0

Further extensions to FGPositioned to support ongoing GPS work.

This commit is contained in:
jmt 2009-09-27 23:12:58 +00:00 committed by Tim Moore
parent 04b30f322d
commit 5755b7ae0e
2 changed files with 100 additions and 32 deletions

View file

@ -474,6 +474,10 @@ FGPositioned::cart() const
FGPositioned::Type FGPositioned::typeFromName(const std::string& aName)
{
if (aName.empty() || (aName == "")) {
return INVALID;
}
typedef struct {
const char* _name;
Type _ty;
@ -489,6 +493,7 @@ FGPositioned::Type FGPositioned::typeFromName(const std::string& aName)
{"dme", DME},
// aliases
{"waypoint", WAYPOINT},
{"apt", AIRPORT},
{NULL, INVALID}
};
@ -585,36 +590,6 @@ FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm
return spatialGetClosest(aPos, aN, aCutoffNm, aFilter);
}
/*
FGPositionedRef
FGPositioned::findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter)
{
NamedIndexRange range = global_namedIndex.equal_range(aId);
for (; range.first != range.second; ++range.first) {
FGPositionedRef candidate = range.first->second;
if (aCur == candidate) {
aCur = NULL; // found our start point, next match will pass
continue;
}
if (aFilter) {
if (aFilter->hasTypeRange() && !aFilter->passType(candidate->type())) {
continue;
}
if(!aFilter->pass(candidate)) {
continue;
}
}
if (!aCur) {
return candidate;
}
}
return NULL; // fell out, no match in range
}*/
FGPositionedRef
FGPositioned::findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter)
{
@ -656,4 +631,86 @@ FGPositioned::findNextWithPartialId(FGPositionedRef aCur, const std::string& aId
return NULL; // Reached the end of the valid sequence with no match.
}
FGPositionedRef
FGPositioned::findWithPartialId(const std::string& aId, Filter* aFilter, int aOffset)
{
// see comment in findNextWithPartialId concerning upperBoundId
std::string upperBoundId = aId;
upperBoundId[upperBoundId.size()-1]++;
NamedPositionedIndex::const_iterator upperBound = global_namedIndex.lower_bound(upperBoundId);
NamedIndexRange range = global_namedIndex.equal_range(aId);
while (range.first != upperBound) {
for (; range.first != range.second; ++range.first) {
FGPositionedRef candidate = range.first->second;
if (aFilter) {
if (aFilter->hasTypeRange() && !aFilter->passType(candidate->type())) {
continue;
}
if (!aFilter->pass(candidate)) {
continue;
}
}
if (aOffset == 0) {
return candidate;
} else {
--aOffset; // seen one more valid result, decrement the count
}
}
// Unable to match the filter with this range - try the next range.
range = global_namedIndex.equal_range(range.second->first);
}
return NULL; // Reached the end of the valid sequence with no match.
}
/**
* Wrapper filter which proxies to an inner filter, but also ensures the
* ident starts with supplied partial ident.
*/
class PartialIdentFilter : public FGPositioned::Filter
{
public:
PartialIdentFilter(const std::string& ident, FGPositioned::Filter* filter) :
_ident(ident),
_inner(filter)
{ ; }
virtual bool pass(FGPositioned* aPos) const
{
if (!_inner->pass(aPos)) {
return false;
}
return (::strncmp(aPos->ident().c_str(), _ident.c_str(), _ident.size()) == 0);
}
virtual FGPositioned::Type minType() const
{ return _inner->minType(); }
virtual FGPositioned::Type maxType() const
{ return _inner->maxType(); }
private:
std::string _ident;
FGPositioned::Filter* _inner;
};
FGPositionedRef
FGPositioned::findClosestWithPartialId(const SGGeod& aPos, const std::string& aId, Filter* aFilter, int aOffset)
{
PartialIdentFilter pf(aId, aFilter);
List matches = spatialGetClosest(aPos, aOffset + 1, 1000.0, &pf);
if ((int) matches.size() <= aOffset) {
SG_LOG(SG_GENERAL, SG_INFO, "FGPositioned::findClosestWithPartialId, couldn't match enough with prefix:" << aId);
return NULL; // couldn't find a match within the cutoff distance
}
return matches[aOffset];
}

View file

@ -158,6 +158,11 @@ public:
*/
static FGPositionedRef findNextWithPartialId(FGPositionedRef aCur, const std::string& aId, Filter* aFilter = NULL);
/**
* As above, but searches using an offset index
*/
static FGPositionedRef findWithPartialId(const std::string& aId, Filter* aFilter, int aOffset);
/**
* Find all items with the specified ident, and return then sorted by
* distance from a position
@ -182,12 +187,18 @@ public:
* Very large cutoff values will make this slow.
*
* @result The matches (possibly less than N, depending on the filter and cutoff),
* sorted by distance from the search pos
* sorted by distance from the search pos
* @param aN - number of matches to find
* @param aCutoffNm - maximum distance to search within, in nautical miles
*/
static List findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter = NULL);
/**
* Find the closest match based on partial id (with an offset to allow selecting the n-th closest).
* Cutoff distance is limited internally, to avoid making this very slow.
*/
static FGPositionedRef findClosestWithPartialId(const SGGeod& aPos, const std::string& aId, Filter* aFilter, int aOffset);
/**
* Map a candidate type string to a real type. Returns INVALID if the string
* does not correspond to a defined type.