#include <boost/algorithm/string/case_conv.hpp>
#include <boost/algorithm/string/predicate.hpp>
+#include <osg/Math> // for osg::isNaN
+
#include <simgear/timing/timestamp.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
return result;
}
+static void validateSGGeod(const SGGeod& geod)
+{
+ if (osg::isNaN(geod.getLatitudeDeg()) ||
+ osg::isNaN(geod.getLongitudeDeg()))
+ {
+ throw sg_range_exception("position is invalid, NaNs");
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
bool
static FGPositioned::List
findAll(const NamedPositionedIndex& aIndex,
- const std::string& aName, FGPositioned::Filter* aFilter)
+ const std::string& aName,
+ FGPositioned::Filter* aFilter,
+ bool aExact)
{
FGPositioned::List result;
if (aName.empty()) {
}
std::string name = boost::to_upper_copy(aName);
- std::string upperBoundId = name;
- upperBoundId[upperBoundId.size()-1]++;
- NamedPositionedIndex::const_iterator upperBound = aIndex.lower_bound(upperBoundId);
+ NamedPositionedIndex::const_iterator upperBound;
+
+ if (aExact) {
+ upperBound = aIndex.upper_bound(name);
+ } else {
+ std::string upperBoundId = name;
+ upperBoundId[upperBoundId.size()-1]++;
+ upperBound = aIndex.lower_bound(upperBoundId);
+ }
+
NamedPositionedIndex::const_iterator it = aIndex.lower_bound(name);
for (; it != upperBound; ++it) {
FGPositionedRef
FGPositioned::findClosestWithIdent(const std::string& aIdent, const SGGeod& aPos, Filter* aFilter)
{
- FGPositioned::List r(findAll(global_identIndex, aIdent, aFilter));
+ validateSGGeod(aPos);
+
+ FGPositioned::List r(findAll(global_identIndex, aIdent, aFilter, true));
if (r.empty()) {
return FGPositionedRef();
}
FGPositioned::List
FGPositioned::findWithinRange(const SGGeod& aPos, double aRangeNm, Filter* aFilter)
{
+ validateSGGeod(aPos);
+
List result;
Octree::findAllWithinRange(SGVec3d::fromGeod(aPos),
aRangeNm * SG_NM_TO_METER, aFilter, result);
}
FGPositioned::List
-FGPositioned::findAllWithIdent(const std::string& aIdent, Filter* aFilter)
+FGPositioned::findAllWithIdent(const std::string& aIdent, Filter* aFilter, bool aExact)
{
- return findAll(global_identIndex, aIdent, aFilter);
+ return findAll(global_identIndex, aIdent, aFilter, aExact);
}
FGPositioned::List
-FGPositioned::findAllWithName(const std::string& aName, Filter* aFilter)
+FGPositioned::findAllWithName(const std::string& aName, Filter* aFilter, bool aExact)
{
- return findAll(global_nameIndex, aName, aFilter);
+ return findAll(global_nameIndex, aName, aFilter, aExact);
}
FGPositionedRef
FGPositioned::findClosest(const SGGeod& aPos, double aCutoffNm, Filter* aFilter)
{
- List l(findClosestN(aPos, 1, aCutoffNm, aFilter));
- if (l.empty()) {
- return NULL;
- }
-
- assert(l.size() == 1);
- return l.front();
+ validateSGGeod(aPos);
+
+ List l(findClosestN(aPos, 1, aCutoffNm, aFilter));
+ if (l.empty()) {
+ return NULL;
+ }
+
+ assert(l.size() == 1);
+ return l.front();
}
FGPositioned::List
FGPositioned::findClosestN(const SGGeod& aPos, unsigned int aN, double aCutoffNm, Filter* aFilter)
{
+ validateSGGeod(aPos);
+
List result;
Octree::findNearestN(SGVec3d::fromGeod(aPos), aN, aCutoffNm * SG_NM_TO_METER, aFilter, result);
return result;
void
FGPositioned::sortByRange(List& aResult, const SGGeod& aPos)
{
+ validateSGGeod(aPos);
+
SGVec3d cartPos(SGVec3d::fromGeod(aPos));
// computer ordering values
Octree::FindNearestResults r;