| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef FLANN_RESULTSET_H |
| | #define FLANN_RESULTSET_H |
| |
|
| | #include <algorithm> |
| | #include <cstring> |
| | #include <iostream> |
| | #include <limits> |
| | #include <set> |
| | #include <vector> |
| |
|
| | namespace flann |
| | { |
| |
|
| | |
| | |
| | |
| | |
| |
|
| | template <typename T, typename DistanceType> |
| | struct BranchStruct |
| | { |
| | T node; |
| | DistanceType mindist; |
| |
|
| | BranchStruct() {} |
| | BranchStruct(const T& aNode, DistanceType dist) : node(aNode), mindist(dist) {} |
| |
|
| | bool operator<(const BranchStruct<T, DistanceType>& rhs) const |
| | { |
| | return mindist<rhs.mindist; |
| | } |
| | }; |
| |
|
| |
|
| | template <typename DistanceType> |
| | struct DistanceIndex |
| | { |
| | DistanceIndex(DistanceType dist, size_t index) : |
| | dist_(dist), index_(index) |
| | { |
| | } |
| | bool operator<(const DistanceIndex& dist_index) const |
| | { |
| | return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_); |
| | } |
| | DistanceType dist_; |
| | size_t index_; |
| | }; |
| |
|
| |
|
| | template <typename DistanceType> |
| | class ResultSet |
| | { |
| | public: |
| | virtual ~ResultSet() {} |
| |
|
| | virtual bool full() const = 0; |
| |
|
| | virtual void addPoint(DistanceType dist, size_t index) = 0; |
| |
|
| | virtual DistanceType worstDist() const = 0; |
| |
|
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | template <typename DistanceType> |
| | class KNNSimpleResultSet : public ResultSet<DistanceType> |
| | { |
| | public: |
| | typedef DistanceIndex<DistanceType> DistIndex; |
| |
|
| | KNNSimpleResultSet(size_t capacity_) : |
| | capacity_(capacity_) |
| | { |
| | |
| | dist_index_.resize(capacity_, DistIndex(std::numeric_limits<DistanceType>::max(),-1)); |
| | clear(); |
| | } |
| |
|
| | ~KNNSimpleResultSet() |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | void clear() |
| | { |
| | worst_distance_ = std::numeric_limits<DistanceType>::max(); |
| | dist_index_[capacity_-1].dist_ = worst_distance_; |
| | count_ = 0; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | size_t size() const |
| | { |
| | return count_; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | bool full() const |
| | { |
| | return count_==capacity_; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist>=worst_distance_) return; |
| |
|
| | if (count_ < capacity_) ++count_; |
| | size_t i; |
| | for (i=count_-1; i>0; --i) { |
| | #ifdef FLANN_FIRST_MATCH |
| | if ( (dist_index_[i-1].dist_>dist) || ((dist==dist_index_[i-1].dist_)&&(dist_index_[i-1].index_>index)) ) |
| | #else |
| | if (dist_index_[i-1].dist_>dist) |
| | #endif |
| | { |
| | dist_index_[i] = dist_index_[i-1]; |
| | } |
| | else break; |
| | } |
| | dist_index_[i].dist_ = dist; |
| | dist_index_[i].index_ = index; |
| | worst_distance_ = dist_index_[capacity_-1].dist_; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true) |
| | { |
| | size_t n = std::min(count_, num_elements); |
| | for (size_t i=0; i<n; ++i) { |
| | *indices++ = dist_index_[i].index_; |
| | *dists++ = dist_index_[i].dist_; |
| | } |
| | } |
| |
|
| | DistanceType worstDist() const |
| | { |
| | return worst_distance_; |
| | } |
| |
|
| | private: |
| | size_t capacity_; |
| | size_t count_; |
| | DistanceType worst_distance_; |
| | std::vector<DistIndex> dist_index_; |
| | }; |
| |
|
| | |
| | |
| | |
| | template <typename DistanceType> |
| | class KNNResultSet : public ResultSet<DistanceType> |
| | { |
| | public: |
| | typedef DistanceIndex<DistanceType> DistIndex; |
| |
|
| | KNNResultSet(int capacity) : capacity_(capacity) |
| | { |
| | |
| | dist_index_.resize(capacity_, DistIndex(std::numeric_limits<DistanceType>::max(),-1)); |
| | clear(); |
| | } |
| |
|
| | ~KNNResultSet() |
| | { |
| |
|
| | } |
| |
|
| | |
| | |
| | |
| | void clear() |
| | { |
| | worst_distance_ = std::numeric_limits<DistanceType>::max(); |
| | dist_index_[capacity_-1].dist_ = worst_distance_; |
| | count_ = 0; |
| | } |
| |
|
| | size_t size() const |
| | { |
| | return count_; |
| | } |
| |
|
| | bool full() const |
| | { |
| | return count_ == capacity_; |
| | } |
| |
|
| |
|
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist >= worst_distance_) return; |
| | size_t i; |
| | for (i = count_; i > 0; --i) { |
| | #ifdef FLANN_FIRST_MATCH |
| | if ( (dist_index_[i-1].dist_<=dist) && ((dist!=dist_index_[i-1].dist_)||(dist_index_[i-1].index_<=index)) ) |
| | #else |
| | if (dist_index_[i-1].dist_<=dist) |
| | #endif |
| | { |
| | |
| | for (size_t j = i - 1; dist_index_[j].dist_ == dist && j--;) { |
| | if (dist_index_[j].index_ == index) { |
| | return; |
| | } |
| | } |
| | break; |
| | } |
| | } |
| | if (count_ < capacity_) ++count_; |
| | for (size_t j = count_-1; j > i; --j) { |
| | dist_index_[j] = dist_index_[j-1]; |
| | } |
| | dist_index_[i].dist_ = dist; |
| | dist_index_[i].index_ = index; |
| | worst_distance_ = dist_index_[capacity_-1].dist_; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true) |
| | { |
| | size_t n = std::min(count_, num_elements); |
| | for (size_t i=0; i<n; ++i) { |
| | *indices++ = dist_index_[i].index_; |
| | *dists++ = dist_index_[i].dist_; |
| | } |
| | } |
| |
|
| | DistanceType worstDist() const |
| | { |
| | return worst_distance_; |
| | } |
| |
|
| | private: |
| | size_t capacity_; |
| | size_t count_; |
| | DistanceType worst_distance_; |
| | std::vector<DistIndex> dist_index_; |
| |
|
| | }; |
| |
|
| |
|
| |
|
| | template <typename DistanceType> |
| | class KNNResultSet2 : public ResultSet<DistanceType> |
| | { |
| | public: |
| | typedef DistanceIndex<DistanceType> DistIndex; |
| |
|
| | KNNResultSet2(size_t capacity_) : |
| | capacity_(capacity_) |
| | { |
| | |
| | dist_index_.reserve(capacity_); |
| | clear(); |
| | } |
| |
|
| | ~KNNResultSet2() |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | void clear() |
| | { |
| | dist_index_.clear(); |
| | worst_dist_ = std::numeric_limits<DistanceType>::max(); |
| | is_full_ = false; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | size_t size() const |
| | { |
| | return dist_index_.size(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | bool full() const |
| | { |
| | return is_full_; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist>=worst_dist_) return; |
| |
|
| | if (dist_index_.size()==capacity_) { |
| | |
| | std::pop_heap(dist_index_.begin(), dist_index_.end()); |
| | dist_index_.pop_back(); |
| | } |
| |
|
| | |
| | dist_index_.push_back(DistIndex(dist,index)); |
| | if (is_full_) { |
| | std::push_heap(dist_index_.begin(), dist_index_.end()); |
| | } |
| |
|
| | if (dist_index_.size()==capacity_) { |
| | if (!is_full_) { |
| | std::make_heap(dist_index_.begin(), dist_index_.end()); |
| | is_full_ = true; |
| | } |
| | |
| | worst_dist_ = dist_index_[0].dist_; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true) |
| | { |
| | if (sorted) { |
| | |
| | |
| | std::sort(dist_index_.begin(), dist_index_.end()); |
| | } |
| | else { |
| | if (num_elements<size()) { |
| | std::nth_element(dist_index_.begin(), dist_index_.begin()+num_elements, dist_index_.end()); |
| | } |
| | } |
| |
|
| | size_t n = std::min(dist_index_.size(), num_elements); |
| | for (size_t i=0; i<n; ++i) { |
| | *indices++ = dist_index_[i].index_; |
| | *dists++ = dist_index_[i].dist_; |
| | } |
| | } |
| |
|
| | DistanceType worstDist() const |
| | { |
| | return worst_dist_; |
| | } |
| |
|
| | private: |
| | size_t capacity_; |
| | DistanceType worst_dist_; |
| | std::vector<DistIndex> dist_index_; |
| | bool is_full_; |
| | }; |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | template <typename DistanceType> |
| | class RadiusResultSet : public ResultSet<DistanceType> |
| | { |
| | public: |
| | typedef DistanceIndex<DistanceType> DistIndex; |
| |
|
| | RadiusResultSet(DistanceType radius_) : |
| | radius_(radius_) |
| | { |
| | |
| | dist_index_.reserve(1024); |
| | clear(); |
| | } |
| |
|
| | ~RadiusResultSet() |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | void clear() |
| | { |
| | dist_index_.clear(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | size_t size() const |
| | { |
| | return dist_index_.size(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | bool full() const |
| | { |
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist<radius_) { |
| | |
| | dist_index_.push_back(DistIndex(dist,index)); |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true) |
| | { |
| | if (sorted) { |
| | |
| | |
| | std::sort(dist_index_.begin(), dist_index_.end()); |
| | } |
| | else { |
| | if (num_elements<size()) { |
| | std::nth_element(dist_index_.begin(), dist_index_.begin()+num_elements, dist_index_.end()); |
| | } |
| | } |
| |
|
| | size_t n = std::min(dist_index_.size(), num_elements); |
| | for (size_t i=0; i<n; ++i) { |
| | *indices++ = dist_index_[i].index_; |
| | *dists++ = dist_index_[i].dist_; |
| | } |
| | } |
| |
|
| | DistanceType worstDist() const |
| | { |
| | return radius_; |
| | } |
| |
|
| | private: |
| | DistanceType radius_; |
| | std::vector<DistIndex> dist_index_; |
| | }; |
| |
|
| |
|
| |
|
| | |
| | |
| | |
| | |
| | template <typename DistanceType> |
| | class KNNRadiusResultSet : public ResultSet<DistanceType> |
| | { |
| | public: |
| | typedef DistanceIndex<DistanceType> DistIndex; |
| |
|
| | KNNRadiusResultSet(DistanceType radius_, size_t capacity_) : |
| | radius_(radius_), capacity_(capacity_) |
| | { |
| | |
| | dist_index_.reserve(capacity_); |
| | clear(); |
| | } |
| |
|
| | ~KNNRadiusResultSet() |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | void clear() |
| | { |
| | dist_index_.clear(); |
| | worst_dist_ = radius_; |
| | is_heap_ = false; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | size_t size() const |
| | { |
| | return dist_index_.size(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | bool full() const |
| | { |
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist>=worst_dist_) return; |
| |
|
| | if (dist_index_.size()==capacity_) { |
| | |
| | std::pop_heap(dist_index_.begin(), dist_index_.end()); |
| | dist_index_.pop_back(); |
| | } |
| |
|
| | |
| | dist_index_.push_back(DistIndex(dist,index)); |
| | if (is_heap_) { |
| | std::push_heap(dist_index_.begin(), dist_index_.end()); |
| | } |
| |
|
| | if (dist_index_.size()==capacity_) { |
| | |
| | if (!is_heap_) { |
| | std::make_heap(dist_index_.begin(), dist_index_.end()); |
| | is_heap_ = true; |
| | } |
| | |
| | worst_dist_ = dist_index_[0].dist_; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | void copy(size_t* indices, DistanceType* dists, size_t num_elements, bool sorted = true) |
| | { |
| | if (sorted) { |
| | |
| | |
| | std::sort(dist_index_.begin(), dist_index_.end()); |
| | } |
| | else { |
| | if (num_elements<size()) { |
| | std::nth_element(dist_index_.begin(), dist_index_.begin()+num_elements, dist_index_.end()); |
| | } |
| | } |
| |
|
| | size_t n = std::min(dist_index_.size(), num_elements); |
| | for (size_t i=0; i<n; ++i) { |
| | *indices++ = dist_index_[i].index_; |
| | *dists++ = dist_index_[i].dist_; |
| | } |
| | } |
| |
|
| | DistanceType worstDist() const |
| | { |
| | return worst_dist_; |
| | } |
| |
|
| | private: |
| | bool is_heap_; |
| | DistanceType radius_; |
| | size_t capacity_; |
| | DistanceType worst_dist_; |
| | std::vector<DistIndex> dist_index_; |
| | }; |
| |
|
| |
|
| | |
| | |
| | |
| | |
| |
|
| | template <typename DistanceType> |
| | class CountRadiusResultSet : public ResultSet<DistanceType> |
| | { |
| | DistanceType radius; |
| | size_t count; |
| |
|
| | public: |
| | CountRadiusResultSet(DistanceType radius_ ) : |
| | radius(radius_) |
| | { |
| | clear(); |
| | } |
| |
|
| | ~CountRadiusResultSet() |
| | { |
| | } |
| |
|
| | void clear() |
| | { |
| | count = 0; |
| | } |
| |
|
| | size_t size() const |
| | { |
| | return count; |
| | } |
| |
|
| | bool full() const |
| | { |
| | return true; |
| | } |
| |
|
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist<radius) { |
| | count++; |
| | } |
| | } |
| |
|
| | DistanceType worstDist() const |
| | { |
| | return radius; |
| | } |
| |
|
| | }; |
| |
|
| |
|
| |
|
| | |
| |
|
| | |
| | |
| | template<typename DistanceType> |
| | class UniqueResultSet : public ResultSet<DistanceType> |
| | { |
| | public: |
| | struct DistIndex |
| | { |
| | DistIndex(DistanceType dist, unsigned int index) : |
| | dist_(dist), index_(index) |
| | { |
| | } |
| | bool operator<(const DistIndex dist_index) const |
| | { |
| | return (dist_ < dist_index.dist_) || ((dist_ == dist_index.dist_) && index_ < dist_index.index_); |
| | } |
| | DistanceType dist_; |
| | unsigned int index_; |
| | }; |
| |
|
| | |
| | UniqueResultSet() : |
| | worst_distance_(std::numeric_limits<DistanceType>::max()) |
| | { |
| | } |
| |
|
| | |
| | |
| | |
| | inline bool full() const |
| | { |
| | return is_full_; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | void copy(size_t* indices, DistanceType* dist, int n_neighbors, bool sorted = true) |
| | { |
| | if (n_neighbors<0) n_neighbors = dist_indices_.size(); |
| | int i = 0; |
| | typedef typename std::set<DistIndex>::const_iterator Iterator; |
| | for (Iterator dist_index = dist_indices_.begin(), dist_index_end = |
| | dist_indices_.end(); (dist_index != dist_index_end) && (i < n_neighbors); ++dist_index, ++indices, ++dist, ++i) { |
| | *indices = dist_index->index_; |
| | *dist = dist_index->dist_; |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | size_t size() const |
| | { |
| | return dist_indices_.size(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | inline DistanceType worstDist() const |
| | { |
| | return worst_distance_; |
| | } |
| | protected: |
| | |
| | bool is_full_; |
| |
|
| | |
| | DistanceType worst_distance_; |
| |
|
| | |
| | std::set<DistIndex> dist_indices_; |
| | }; |
| |
|
| | |
| |
|
| | |
| | |
| | |
| | template<typename DistanceType> |
| | class KNNUniqueResultSet : public UniqueResultSet<DistanceType> |
| | { |
| | public: |
| | |
| | |
| | |
| | KNNUniqueResultSet(unsigned int capacity) : capacity_(capacity) |
| | { |
| | this->is_full_ = false; |
| | this->clear(); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | inline void addPoint(DistanceType dist, size_t index) |
| | { |
| | |
| | if (dist >= worst_distance_) return; |
| | dist_indices_.insert(DistIndex(dist, index)); |
| |
|
| | if (is_full_) { |
| | if (dist_indices_.size() > capacity_) { |
| | dist_indices_.erase(*dist_indices_.rbegin()); |
| | worst_distance_ = dist_indices_.rbegin()->dist_; |
| | } |
| | } |
| | else if (dist_indices_.size() == capacity_) { |
| | is_full_ = true; |
| | worst_distance_ = dist_indices_.rbegin()->dist_; |
| | } |
| | } |
| |
|
| | |
| | |
| | void clear() |
| | { |
| | dist_indices_.clear(); |
| | worst_distance_ = std::numeric_limits<DistanceType>::max(); |
| | is_full_ = false; |
| | } |
| |
|
| | protected: |
| | typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex; |
| | using UniqueResultSet<DistanceType>::is_full_; |
| | using UniqueResultSet<DistanceType>::worst_distance_; |
| | using UniqueResultSet<DistanceType>::dist_indices_; |
| |
|
| | |
| | unsigned int capacity_; |
| | }; |
| |
|
| | |
| |
|
| | |
| | |
| | |
| | template<typename DistanceType> |
| | class RadiusUniqueResultSet : public UniqueResultSet<DistanceType> |
| | { |
| | public: |
| | |
| | |
| | |
| | RadiusUniqueResultSet(DistanceType radius) : |
| | radius_(radius) |
| | { |
| | is_full_ = true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | void addPoint(DistanceType dist, size_t index) |
| | { |
| | if (dist < radius_) dist_indices_.insert(DistIndex(dist, index)); |
| | } |
| |
|
| | |
| | |
| | inline void clear() |
| | { |
| | dist_indices_.clear(); |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | inline bool full() const |
| | { |
| | return true; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | inline DistanceType worstDist() const |
| | { |
| | return radius_; |
| | } |
| | private: |
| | typedef typename UniqueResultSet<DistanceType>::DistIndex DistIndex; |
| | using UniqueResultSet<DistanceType>::dist_indices_; |
| | using UniqueResultSet<DistanceType>::is_full_; |
| |
|
| | |
| | DistanceType radius_; |
| | }; |
| |
|
| | |
| |
|
| | |
| | |
| | template<typename DistanceType> |
| | class KNNRadiusUniqueResultSet : public KNNUniqueResultSet<DistanceType> |
| | { |
| | public: |
| | |
| | |
| | |
| | KNNRadiusUniqueResultSet(DistanceType radius, size_t capacity) : KNNUniqueResultSet<DistanceType>(capacity) |
| | { |
| | this->radius_ = radius; |
| | this->clear(); |
| | } |
| |
|
| | |
| | |
| | void clear() |
| | { |
| | dist_indices_.clear(); |
| | worst_distance_ = radius_; |
| | is_full_ = true; |
| | } |
| | private: |
| | using KNNUniqueResultSet<DistanceType>::dist_indices_; |
| | using KNNUniqueResultSet<DistanceType>::is_full_; |
| | using KNNUniqueResultSet<DistanceType>::worst_distance_; |
| |
|
| | |
| | DistanceType radius_; |
| | }; |
| | } |
| |
|
| | #endif |
| |
|
| |
|