Basic infrastructure to expose type ranges from filters, and hence reduce
how many candidates need to be submitted to the pass() hook.
This commit is contained in:
parent
8ad7f4eb70
commit
2d852024c6
2 changed files with 78 additions and 57 deletions
|
@ -37,6 +37,9 @@
|
||||||
typedef std::multimap<std::string, FGPositioned*> NamedPositionedIndex;
|
typedef std::multimap<std::string, FGPositioned*> NamedPositionedIndex;
|
||||||
typedef std::pair<NamedPositionedIndex::const_iterator, NamedPositionedIndex::const_iterator> NamedIndexRange;
|
typedef std::pair<NamedPositionedIndex::const_iterator, NamedPositionedIndex::const_iterator> NamedIndexRange;
|
||||||
|
|
||||||
|
using std::lower_bound;
|
||||||
|
using std::upper_bound;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Order positioned elements by type, then pointer address. This allows us to
|
* Order positioned elements by type, then pointer address. This allows us to
|
||||||
* use range searches (lower_ and upper_bound) to grab items of a particular
|
* use range searches (lower_ and upper_bound) to grab items of a particular
|
||||||
|
@ -52,6 +55,21 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LowerLimitOfType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool operator()(const FGPositioned* a, const FGPositioned::Type b) const
|
||||||
|
{
|
||||||
|
return a->type() < b;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const FGPositioned::Type a, const FGPositioned* b) const
|
||||||
|
{
|
||||||
|
return a < b->type();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef std::set<FGPositioned*, OrderByType> BucketEntry;
|
typedef std::set<FGPositioned*, OrderByType> BucketEntry;
|
||||||
typedef std::map<long int, BucketEntry> SpatialPositionedIndex;
|
typedef std::map<long int, BucketEntry> SpatialPositionedIndex;
|
||||||
|
|
||||||
|
@ -122,6 +140,12 @@ spatialFilterInBucket(const SGBucket& aBucket, FGPositioned::Filter* aFilter, FG
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aFilter->hasTypeRange()) {
|
||||||
|
// avoid many calls to the filter hook
|
||||||
|
l = lower_bound(it->second.begin(), it->second.end(), aFilter->minType(), LowerLimitOfType());
|
||||||
|
u = upper_bound(l, it->second.end(), aFilter->maxType(), LowerLimitOfType());
|
||||||
|
}
|
||||||
|
|
||||||
for ( ; l != u; ++l) {
|
for ( ; l != u; ++l) {
|
||||||
if ((*aFilter)(*l)) {
|
if ((*aFilter)(*l)) {
|
||||||
aResult.push_back(*l);
|
aResult.push_back(*l);
|
||||||
|
@ -148,55 +172,6 @@ spatialFind(const SGGeod& aPos, double aRange,
|
||||||
} // of i-iteration
|
} // of i-iteration
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
class LowerLimitOfType
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
bool operator()(const FGPositioned* a, const FGPositioned::Type b) const
|
|
||||||
{
|
|
||||||
return a->type() < b;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const FGPositioned::Type a, const FGPositioned* b) const
|
|
||||||
{
|
|
||||||
return a < b->type();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
spatialFindTyped(const SGGeod& aPos, double aRange, FGPositioned::Type aLower, FGPositioned::Type aUpper, FGPositioned::List& aResult)
|
|
||||||
{
|
|
||||||
SGBucket buck(aPos);
|
|
||||||
double lat = aPos.getLatitudeDeg(),
|
|
||||||
lon = aPos.getLongitudeDeg();
|
|
||||||
|
|
||||||
int bx = (int)( aRange*SG_NM_TO_METER / buck.get_width_m() / 2);
|
|
||||||
int by = (int)( aRange*SG_NM_TO_METER / buck.get_height_m() / 2 );
|
|
||||||
|
|
||||||
// loop over bucket range
|
|
||||||
for ( int i=-bx; i<=bx; i++) {
|
|
||||||
for ( int j=-by; j<=by; j++) {
|
|
||||||
buck = sgBucketOffset(lon, lat, i, j);
|
|
||||||
|
|
||||||
SpatialPositionedIndex::const_iterator it;
|
|
||||||
it = global_spatialIndex.find(buck.gen_index());
|
|
||||||
if (it == global_spatialIndex.end()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
BucketEntry::const_iterator l = std::lower_bound(it->second.begin(), it->second.end(), aLower, LowerLimitOfType());
|
|
||||||
BucketEntry::const_iterator u = std::upper_bound(l, it->second.end(), aUpper, LowerLimitOfType());
|
|
||||||
|
|
||||||
for ( ; l != u; ++l) {
|
|
||||||
aResult.push_back(*l);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // of j-iteration
|
|
||||||
} // of i-iteration
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
class RangePredictate
|
class RangePredictate
|
||||||
|
@ -263,12 +238,19 @@ namedFindClosest(const std::string& aIdent, const SGGeod& aOrigin, FGPositioned:
|
||||||
// sequential iterators, not random-access ones
|
// sequential iterators, not random-access ones
|
||||||
NamedPositionedIndex::const_iterator check = range.first;
|
NamedPositionedIndex::const_iterator check = range.first;
|
||||||
if (++check == range.second) {
|
if (++check == range.second) {
|
||||||
// excellent, only one match in the range - all we care about is the type
|
// excellent, only one match in the range
|
||||||
if (aFilter && !aFilter->pass(range.first->second)) {
|
FGPositioned* r = range.first->second;
|
||||||
return NULL; // type check failed
|
if (aFilter) {
|
||||||
}
|
if (aFilter->hasTypeRange() && !aFilter->passType(r->type())) {
|
||||||
|
return NULL;
|
||||||
return range.first->second;
|
}
|
||||||
|
|
||||||
|
if (!aFilter->pass(r)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} // of have a filter
|
||||||
|
|
||||||
|
return r;
|
||||||
} // of short-circuit logic for single-element range
|
} // of short-circuit logic for single-element range
|
||||||
|
|
||||||
// multiple matches, we need to actually check the distance to each one
|
// multiple matches, we need to actually check the distance to each one
|
||||||
|
@ -278,8 +260,15 @@ namedFindClosest(const std::string& aIdent, const SGGeod& aOrigin, FGPositioned:
|
||||||
SGVec3d cartOrigin(SGVec3d::fromGeod(aOrigin));
|
SGVec3d cartOrigin(SGVec3d::fromGeod(aOrigin));
|
||||||
|
|
||||||
for (; it != range.second; ++it) {
|
for (; it != range.second; ++it) {
|
||||||
if (aFilter && !aFilter->pass(range.first->second)) {
|
FGPositioned::Type ty = range.first->second->type();
|
||||||
continue;
|
if (aFilter) {
|
||||||
|
if (aFilter->hasTypeRange() && !aFilter->passType(ty)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aFilter->pass(range.first->second)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// find distance
|
// find distance
|
||||||
|
@ -428,6 +417,22 @@ char** searchAirportNamesAndIdents(const std::string& aFilter)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGPositioned::Filter::hasTypeRange() const
|
||||||
|
{
|
||||||
|
assert(minType() <= maxType());
|
||||||
|
return (minType() != INVALID) && (maxType() != INVALID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
FGPositioned::Filter::passType(Type aTy) const
|
||||||
|
{
|
||||||
|
assert(hasTypeRange());
|
||||||
|
return (minType() <= aTy) && (maxType() >= aTy);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos, bool aIndexed) :
|
FGPositioned::FGPositioned(Type ty, const std::string& aIdent, const SGGeod& aPos, bool aIndexed) :
|
||||||
mType(ty),
|
mType(ty),
|
||||||
mPosition(aPos),
|
mPosition(aPos),
|
||||||
|
|
|
@ -113,6 +113,22 @@ public:
|
||||||
virtual bool pass(FGPositioned* aPos) const
|
virtual bool pass(FGPositioned* aPos) const
|
||||||
{ return true; }
|
{ return true; }
|
||||||
|
|
||||||
|
virtual Type minType() const
|
||||||
|
{ return INVALID; }
|
||||||
|
|
||||||
|
virtual Type maxType() const
|
||||||
|
{ return INVALID; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if this filter has a non-empty type range
|
||||||
|
*/
|
||||||
|
bool hasTypeRange() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assuming hasTypeRange is true, test if a given type passes the range
|
||||||
|
*/
|
||||||
|
bool passType(Type aTy) const;
|
||||||
|
|
||||||
bool operator()(FGPositioned* aPos) const
|
bool operator()(FGPositioned* aPos) const
|
||||||
{ return pass(aPos); }
|
{ return pass(aPos); }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue