31 #ifndef FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
32 #define FLANN_HIERARCHICAL_CLUSTERING_INDEX_H_
42 #define SIZE_MAX ((size_t) -1)
63 int trees = 4,
int leaf_max_size = 100)
67 (*this)[
"branching"] = branching;
69 (*this)[
"centers_init"] = centers_init;
71 (*this)[
"trees"] = trees;
73 (*this)[
"leaf_max_size"] = leaf_max_size;
85 template <
typename Distance>
136 chooseCenters_->setDataSize(
veclen_);
141 memoryCounter_(other.memoryCounter_),
142 branching_(other.branching_),
143 trees_(other.trees_),
144 centers_init_(other.centers_init_),
145 leaf_max_size_(other.leaf_max_size_)
149 tree_roots_.resize(other.tree_roots_.size());
150 for (
size_t i=0;i<tree_roots_.size();++i) {
151 copyTree(tree_roots_[i], other.tree_roots_[i]);
164 switch(centers_init_) {
178 throw FLANNException(
"Unknown algorithm for choosing initial centers.");
189 delete chooseCenters_;
212 size_t old_size =
size_;
220 for (
size_t i=0;i<
points.rows;++i) {
221 for (
int j = 0; j < trees_; j++) {
222 addPointToTree(tree_roots_[j], old_size + i);
235 template<
typename Archive>
247 if (Archive::is_loading::value) {
248 tree_roots_.resize(trees_);
250 for (
size_t i=0;i<tree_roots_.size();++i) {
251 if (Archive::is_loading::value) {
252 tree_roots_[i] =
new(pool_) Node();
254 ar & *tree_roots_[i];
257 if (Archive::is_loading::value) {
293 findNeighborsWithRemoved<true>(
result, vec, searchParams);
296 findNeighborsWithRemoved<false>(
result, vec, searchParams);
307 chooseCenters_->setDataSize(
veclen_);
312 tree_roots_.resize(trees_);
313 std::vector<int> indices(
size_);
314 for (
int i=0; i<trees_; ++i) {
315 for (
size_t j=0; j<
size_; ++j) {
318 tree_roots_[i] =
new(pool_) Node();
319 computeClustering(tree_roots_[i], &indices[0],
size_);
333 template<
typename Archive>
337 Index* obj =
static_cast<Index*
>(ar.getObject());
342 if (Archive::is_loading::value) {
343 point = obj->points_[index];
346 friend struct serialization::access;
362 std::vector<Node*> childs;
366 std::vector<PointInfo>
points;
378 for(
size_t i=0; i<childs.size(); i++){
386 template<
typename Archive>
389 typedef HierarchicalClusteringIndex<Distance>
Index;
390 Index* obj =
static_cast<Index*
>(ar.getObject());
392 if (Archive::is_loading::value) {
394 pivot = obj->points_[pivot_index];
399 if (Archive::is_saving::value) {
400 childs_size = childs.size();
404 if (childs_size==0) {
408 if (Archive::is_loading::value) {
409 childs.resize(childs_size);
411 for (
size_t i=0;i<childs_size;++i) {
412 if (Archive::is_loading::value) {
413 childs[i] =
new(obj->pool_)
Node();
420 friend struct serialization::access;
422 typedef Node* NodePtr;
429 typedef BranchStruct<NodePtr, DistanceType> BranchSt;
437 for (
size_t i=0; i<tree_roots_.size(); ++i) {
438 tree_roots_[i]->~Node();
443 void copyTree(NodePtr& dst,
const NodePtr& src)
445 dst =
new(pool_)
Node();
446 dst->pivot_index = src->pivot_index;
447 dst->pivot =
points_[dst->pivot_index];
449 if (src->childs.size()==0) {
450 dst->points = src->points;
453 dst->childs.resize(src->childs.size());
454 for (
size_t i=0;i<src->childs.size();++i) {
455 copyTree(dst->childs[i], src->childs[i]);
462 void computeLabels(
int* indices,
int indices_length,
int* centers,
int centers_length,
int* labels,
DistanceType& cost)
465 for (
int i=0; i<indices_length; ++i) {
469 for (
int j=1; j<centers_length; ++j) {
490 void computeClustering(NodePtr node,
int* indices,
int indices_length)
492 if (indices_length < leaf_max_size_) {
493 node->points.resize(indices_length);
494 for (
int i=0;i<indices_length;++i) {
495 node->points[i].index = indices[i];
496 node->points[i].point =
points_[indices[i]];
498 node->childs.clear();
502 std::vector<int> centers(branching_);
503 std::vector<int> labels(indices_length);
506 (*chooseCenters_)(branching_, indices, indices_length, ¢ers[0], centers_length);
508 if (centers_length<branching_) {
509 node->points.resize(indices_length);
510 for (
int i=0;i<indices_length;++i) {
511 node->points[i].index = indices[i];
512 node->points[i].point =
points_[indices[i]];
514 node->childs.clear();
521 computeLabels(indices, indices_length, ¢ers[0], centers_length, &labels[0], cost);
523 node->childs.resize(branching_);
526 for (
int i=0; i<branching_; ++i) {
527 for (
int j=0; j<indices_length; ++j) {
535 node->childs[i] =
new(pool_)
Node();
536 node->childs[i]->pivot_index = centers[i];
537 node->childs[i]->pivot =
points_[centers[i]];
538 node->childs[i]->points.clear();
539 computeClustering(node->childs[i],indices+start, end-start);
545 template<
bool with_removed>
546 void findNeighborsWithRemoved(ResultSet<DistanceType>&
result,
const ElementType* vec,
const SearchParams& searchParams)
const
548 int maxChecks = searchParams.checks;
551 Heap<BranchSt>* heap =
new Heap<BranchSt>(
size_);
553 DynamicBitset checked(
size_);
555 for (
int i=0; i<trees_; ++i) {
556 findNN<with_removed>(tree_roots_[i],
result, vec, checks, maxChecks, heap, checked);
560 while (heap->popMin(branch) && (checks<maxChecks || !
result.full())) {
561 NodePtr node = branch.node;
562 findNN<with_removed>(node,
result, vec, checks, maxChecks, heap, checked);
581 template<
bool with_removed>
582 void findNN(NodePtr node, ResultSet<DistanceType>&
result,
const ElementType* vec,
int& checks,
int maxChecks,
583 Heap<BranchSt>* heap, DynamicBitset& checked)
const
585 if (node->childs.empty()) {
586 if (checks>=maxChecks) {
587 if (
result.full())
return;
590 for (
size_t i=0; i<node->points.size(); ++i) {
591 PointInfo& pointInfo = node->points[i];
595 if (checked.test(pointInfo.index))
continue;
598 checked.set(pointInfo.index);
605 domain_distances[best_index] =
distance_(vec, node->childs[best_index]->pivot,
veclen_);
606 for (
int i=1; i<branching_; ++i) {
608 if (domain_distances[i]<domain_distances[best_index]) {
612 for (
int i=0; i<branching_; ++i) {
614 heap->insert(BranchSt(node->childs[i],domain_distances[i]));
617 delete[] domain_distances;
618 findNN<with_removed>(node->childs[best_index],
result,vec, checks, maxChecks, heap, checked);
622 void addPointToTree(NodePtr node,
size_t index)
626 if (node->childs.empty()) {
628 pointInfo.point =
point;
629 pointInfo.index = index;
630 node->points.push_back(pointInfo);
632 if (node->points.size()>=
size_t(branching_)) {
633 std::vector<int> indices(node->points.size());
635 for (
size_t i=0;i<node->points.size();++i) {
636 indices[i] = node->points[i].index;
638 computeClustering(node, &indices[0], indices.size());
644 ElementType* center = node->childs[closest]->pivot;
646 for (
size_t i=1;i<size_t(branching_);++i) {
647 center = node->childs[i]->pivot;
654 addPointToTree(node->childs[closest], index);
662 std::swap(tree_roots_, other.tree_roots_);
664 std::swap(memoryCounter_, other.memoryCounter_);
667 std::swap(centers_init_, other.centers_init_);
668 std::swap(leaf_max_size_, other.leaf_max_size_);
669 std::swap(chooseCenters_, other.chooseCenters_);
677 std::vector<Node*> tree_roots_;
686 PooledAllocator pool_;
717 CenterChooser<Distance>* chooseCenters_;
double Distance(const Point3D< Real > &p1, const Point3D< Real > &p2)
Generic handle to any of the 8 types of E57 element objects.
bool test(size_t index) const
BaseClass * clone() const
NNIndex< Distance > BaseClass
HierarchicalClusteringIndex & operator=(HierarchicalClusteringIndex other)
void serialize(Archive &ar)
Distance::ResultType DistanceType
HierarchicalClusteringIndex(const Matrix< ElementType > &inputData, const IndexParams &index_params=HierarchicalClusteringIndexParams(), Distance d=Distance())
void saveIndex(FILE *stream)
flann_algorithm_t getType() const
HierarchicalClusteringIndex(const IndexParams &index_params=HierarchicalClusteringIndexParams(), Distance d=Distance())
virtual ~HierarchicalClusteringIndex()
void addPoints(const Matrix< ElementType > &points, float rebuild_threshold=2)
Incrementally add points to the index.
void findNeighbors(ResultSet< DistanceType > &result, const ElementType *vec, const SearchParams &searchParams) const
virtual void buildIndex()
Distance::ElementType ElementType
void loadIndex(FILE *stream)
HierarchicalClusteringIndex(const HierarchicalClusteringIndex &other)
std::vector< ElementType * > points_
void swap(NNIndex &other)
DynamicBitset removed_points_
void setDataset(const Matrix< ElementType > &dataset)
virtual void buildIndex()
void extendDataset(const Matrix< ElementType > &new_points)
IndexParams index_params_
@ FLANN_INDEX_HIERARCHICAL
@ FLANN_CENTERS_GROUPWISE
static double dist(double x1, double y1, double x2, double y2)
void swap(optional< T > &x, optional< T > &y) noexcept(noexcept(x.swap(y)))
T get_param(const IndexParams ¶ms, std::string name, const T &default_value)
std::map< std::string, any > IndexParams
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
#define USING_BASECLASS_SYMBOLS
HierarchicalClusteringIndexParams(int branching=32, flann_centers_init_t centers_init=FLANN_CENTERS_RANDOM, int trees=4, int leaf_max_size=100)