-void findNearestN(const SGVec3d& aPos, unsigned int aN, double aCutoffM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults)
-{
- aResults.clear();
- FindNearestPQueue pq;
- FindNearestResults results;
- pq.push(Ordered<Node*>(global_spatialOctree, 0));
- double cut = aCutoffM * aCutoffM;
-
- while (!pq.empty()) {
- if (!results.empty()) {
- // terminate the search if we have sufficent results, and we are
- // sure no node still on the queue contains a closer match
- double furthestResultOrder = results.back().order();
- if ((results.size() >= aN) && (furthestResultOrder < pq.top().order())) {
- break;
- }
- }
-
- Node* nd = pq.top().get();
- pq.pop();
-
- nd->visit(aPos, cut, aFilter, results, pq);
- } // of queue iteration
-
- // depending on leaf population, we may have (slighty) more results
- // than requested
- unsigned int numResults = std::min((unsigned int) results.size(), aN);
- // copy results out
- aResults.resize(numResults);
- for (unsigned int r=0; r<numResults; ++r) {
- aResults[r] = results[r].get();
- }
-}
-
-void findAllWithinRange(const SGVec3d& aPos, double aRangeM, FGPositioned::Filter* aFilter, FGPositioned::List& aResults)
-{
- aResults.clear();
- FindNearestPQueue pq;
- FindNearestResults results;
- pq.push(Ordered<Node*>(global_spatialOctree, 0));
- double rng = aRangeM * aRangeM;
-
- while (!pq.empty()) {
- Node* nd = pq.top().get();
- pq.pop();
-
- nd->visit(aPos, rng, aFilter, results, pq);
- } // of queue iteration
-
- unsigned int numResults = results.size();
- // copy results out
- aResults.resize(numResults);
- for (unsigned int r=0; r<numResults; ++r) {
- aResults[r] = results[r].get();
- }
-}
-
-} // of namespace Octree
-
-//////////////////////////////////////////////////////////////////////////////
-
-static void
-addToIndices(FGPositioned* aPos)
-{
- assert(aPos);
- if (!aPos->ident().empty()) {
- std::string u(boost::to_upper_copy(aPos->ident()));
-
- global_identIndex.insert(global_identIndex.begin(),
- std::make_pair(u, aPos));
- }
-
- if (!aPos->name().empty()) {
- std::string u(boost::to_upper_copy(aPos->name()));
-
- global_nameIndex.insert(global_nameIndex.begin(),
- std::make_pair(u, aPos));
- }
-
- if (!Octree::global_spatialOctree) {
- double RADIUS_EARTH_M = 7000 * 1000.0; // 7000km is plenty
- SGVec3d earthExtent(RADIUS_EARTH_M, RADIUS_EARTH_M, RADIUS_EARTH_M);
- Octree::global_spatialOctree = new Octree::Branch(SGBox<double>(-earthExtent, earthExtent));
- }
- Octree::global_spatialOctree->insert(aPos);
-}
-
-static void
-removeFromIndices(FGPositioned* aPos)
-{
- assert(aPos);
-
- if (!aPos->ident().empty()) {
- std::string u(boost::to_upper_copy(aPos->ident()));
- NamedPositionedIndex::iterator it = global_identIndex.find(u);
- while (it != global_identIndex.end() && (it->first == u)) {
- if (it->second == aPos) {
- global_identIndex.erase(it);
- break;
- }
-
- ++it;
- } // of multimap walk
- }
-
- if (!aPos->name().empty()) {
- std::string u(boost::to_upper_copy(aPos->name()));
- NamedPositionedIndex::iterator it = global_nameIndex.find(u);
- while (it != global_nameIndex.end() && (it->first == u)) {
- if (it->second == aPos) {
- global_nameIndex.erase(it);
- break;
- }
-
- ++it;
- } // of multimap walk
- }
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-class OrderByName
-{
-public:
- bool operator()(FGPositioned* a, FGPositioned* b) const
- {
- return a->name() < b->name();
- }
-};
-
-void findInIndex(NamedPositionedIndex& aIndex, const std::string& aFind, std::vector<FGPositioned*>& aResult)
-{
- NamedPositionedIndex::const_iterator it = aIndex.begin();
- NamedPositionedIndex::const_iterator end = aIndex.end();
-
- bool haveFilter = !aFind.empty();
-
- for (; it != end; ++it) {
- FGPositioned::Type ty = it->second->type();
- if ((ty < FGPositioned::AIRPORT) || (ty > FGPositioned::SEAPORT)) {
- continue;
- }
-
- if (haveFilter && it->first.find(aFind) == std::string::npos) {
- continue;
- }
-
- aResult.push_back(it->second);
- } // of index iteration
-}
-
-/**
- * A special purpose helper (imported by FGAirport::searchNamesAndIdents) to
- * implement the AirportList dialog. It's unfortunate that it needs to reside
- * here, but for now it's least ugly solution.
- */
-char** searchAirportNamesAndIdents(const std::string& aFilter)
-{
-// note this is a vector of raw pointers, not smart pointers, because it
-// may get very large and smart-pointer-atomicity-locking then becomes a
-// bottleneck for this case.
- std::vector<FGPositioned*> matches;
- if (!aFilter.empty()) {
- std::string filter = boost::to_upper_copy(aFilter);
- findInIndex(global_identIndex, filter, matches);
- findInIndex(global_nameIndex, filter, matches);
- } else {
-
- findInIndex(global_identIndex, std::string(), matches);
- }
-
-// sort alphabetically on name
- std::sort(matches.begin(), matches.end(), OrderByName());
-
-// convert results to format comptible with puaList
- unsigned int numMatches = matches.size();
- char** result = new char*[numMatches + 1];
- result[numMatches] = NULL; // end-of-list marker
-
- // nasty code to avoid excessive string copying and allocations.
- // We format results as follows (note whitespace!):
- // ' name-of-airport-chars (ident)'
- // so the total length is:
- // 1 + strlen(name) + 4 + strlen(icao) + 1 + 1 (for the null)
- // which gives a grand total of 7 + name-length + icao-length.
- // note the ident can be three letters (non-ICAO local strip), four
- // (default ICAO) or more (extended format ICAO)
- for (unsigned int i=0; i<numMatches; ++i) {
- int nameLength = matches[i]->name().size();
- int icaoLength = matches[i]->ident().size();
- char* entry = new char[7 + nameLength + icaoLength];
- char* dst = entry;
- *dst++ = ' ';
- memcpy(dst, matches[i]->name().c_str(), nameLength);
- dst += nameLength;
- *dst++ = ' ';
- *dst++ = ' ';
- *dst++ = ' ';
- *dst++ = '(';
- memcpy(dst, matches[i]->ident().c_str(), icaoLength);
- dst += icaoLength;
- *dst++ = ')';
- *dst++ = 0;
- result[i] = entry;
- }
-
- return result;
-}