10 #include <Eigen/Geometry>
17 #include <flann/flann.hpp>
28 typedef Eigen::Matrix<Index, Eigen::Dynamic, 1>
Vectori;
34 typedef Eigen::Matrix<Index, Eigen::Dynamic, Eigen::Dynamic>
Matrixi;
40 typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>
Matrixf;
41 typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>
Matrixd;
50 template <
typename Scalar>
55 template <
typename DerivedA,
typename DerivedB>
56 Scalar
operator()(
const Eigen::MatrixBase<DerivedA> &lhs,
57 const Eigen::MatrixBase<DerivedB> &rhs)
const {
58 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedA>::Scalar,
60 "distance scalar and input matrix A must have same type");
61 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedB>::Scalar,
63 "distance scalar and input matrix B must have same type");
65 return (lhs - rhs).cwiseAbs().sum();
71 Scalar
operator()(
const Scalar lhs,
const Scalar rhs)
const {
77 Scalar
operator()(
const Scalar val)
const {
return val; }
83 template <
typename Scalar>
88 template <
typename DerivedA,
typename DerivedB>
89 Scalar
operator()(
const Eigen::MatrixBase<DerivedA> &lhs,
90 const Eigen::MatrixBase<DerivedB> &rhs)
const {
91 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedA>::Scalar,
93 "distance scalar and input matrix A must have same type");
94 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedB>::Scalar,
96 "distance scalar and input matrix B must have same type");
98 return (lhs - rhs).cwiseAbs2().sum();
104 Scalar
operator()(
const Scalar lhs,
const Scalar rhs)
const {
105 Scalar diff = lhs - rhs;
111 Scalar
operator()(
const Scalar val)
const {
return std::sqrt(val); }
117 template <
typename Scalar,
int P>
122 for (
int i = 0; i < P; ++i)
result *= val;
130 template <
typename DerivedA,
typename DerivedB>
132 const Eigen::MatrixBase<DerivedB> &rhs)
const {
133 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedA>::Scalar,
135 "distance scalar and input matrix A must have same type");
136 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedB>::Scalar,
138 "distance scalar and input matrix B must have same type");
146 Scalar
operator()(
const Scalar lhs,
const Scalar rhs)
const {
147 return std::pow(
std::abs(lhs - rhs), P);
154 return std::pow(val, 1 /
static_cast<Scalar
>(P));
161 template <
typename Scalar>
166 template <
typename DerivedA,
typename DerivedB>
168 const Eigen::MatrixBase<DerivedB> &rhs)
const {
169 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedA>::Scalar,
171 "distance scalar and input matrix A must have same type");
172 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedB>::Scalar,
174 "distance scalar and input matrix B must have same type");
176 return (lhs - rhs).cwiseAbs().maxCoeff();
182 Scalar
operator()(
const Scalar lhs,
const Scalar rhs)
const {
196 template <
typename Scalar>
198 static_assert(std::is_integral<Scalar>::value,
199 "HammingDistance requires integral Scalar type");
202 Scalar
operator()(
const Scalar lhs,
const Scalar rhs)
const {
211 while (
copy !=
static_cast<Scalar
>(0)) {
223 template <
typename DerivedA,
typename DerivedB>
225 const Eigen::MatrixBase<DerivedB> &rhs)
const {
226 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedA>::Scalar,
228 "distance scalar and input matrix A must have same type");
229 static_assert(std::is_same<
typename Eigen::MatrixBase<DerivedB>::Scalar,
231 "distance scalar and input matrix B must have same type");
233 return lhs.binaryExpr(rhs,
XOR()).unaryExpr(
BitCount()).sum();
239 Scalar
operator()(
const Scalar lhs,
const Scalar rhs)
const {
242 return cnt(xOr(lhs, rhs));
247 Scalar
operator()(
const Scalar value)
const {
return value; }
251 template <
typename Scalar>
254 Index *indices_ =
nullptr;
255 Scalar *distances_ =
nullptr;
263 : indices_(indices), distances_(distances), maxSize_(maxSize) {}
275 indices_[
size_] = idx;
280 size_t k =
size_ - 1;
281 size_t tmp = (k - 1) / 2;
282 while (k > 0 && distances_[tmp] <
dist) {
283 distances_[k] = distances_[tmp];
284 indices_[k] = indices_[tmp];
288 distances_[k] =
dist;
299 distances_[0] = distances_[
size_];
300 indices_[0] = indices_[
size_];
305 Scalar
dist = distances_[0];
306 Index idx = indices_[0];
307 while (2 * k + 1 <
size_) {
309 if (j + 1 <
size_ && distances_[j + 1] > distances_[j]) ++j;
311 if (
dist >= distances_[j])
break;
312 distances_[k] = distances_[j];
313 indices_[k] = indices_[j];
316 distances_[k] =
dist;
323 return distances_[0];
347 for (
size_t i = 0; i < cnt; ++i) {
348 Index idx = indices_[0];
349 Scalar
dist = distances_[0];
351 indices_[cnt - i - 1] = idx;
352 distances_[cnt - i - 1] =
dist;
358 template <
typename Scalar,
typename Distance = Eucl
ideanDistance<Scalar>>
361 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
Matrix;
362 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1>
Vector;
368 const Matrix *data_ =
nullptr;
371 bool takeRoot_ =
true;
400 void setThreads(
const unsigned int threads) { threads_ = threads; }
425 template <
typename Derived>
426 void query(
const Eigen::MatrixBase<Derived> &queryPoints,
429 Matrix &distances)
const {
430 if (data_ ==
nullptr)
431 throw std::runtime_error(
"cannot query BruteForce: data not set");
432 if (data_->size() == 0)
433 throw std::runtime_error(
"cannot query BruteForce: data is empty");
435 throw std::runtime_error(
436 "cannot query BruteForce: data and query descriptors do "
437 "not have same dimension");
439 const Matrix &dataPoints = *data_;
441 indices.setConstant(knn, queryPoints.cols(), -1);
442 distances.setConstant(knn, queryPoints.cols(), -1);
444 #pragma omp parallel for num_threads(threads_)
445 for (
Index i = 0; i < queryPoints.cols(); ++i) {
446 Index *idxPoint = &indices.data()[i * knn];
447 Scalar *distPoint = &distances.data()[i * knn];
451 for (
Index j = 0; j < dataPoints.cols(); ++j) {
452 Scalar
dist = distance_(queryPoints.col(i), dataPoints.col(j));
455 bool isInRange = maxDist_ <= 0 ||
dist <= maxDist_;
458 if (isInRange && isImprovement) {
464 if (sorted_) heap.
sort();
467 for (
size_t j = 0; j < knn; ++j) {
468 if (idxPoint[j] < 0)
break;
469 distPoint[j] = distance_(distPoint[j]);
477 Index size()
const {
return data_ ==
nullptr ? 0 : data_->cols(); }
498 template <
typename _Scalar,
int _Dimension,
typename _Distance>
503 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
Matrix;
504 typedef Eigen::Matrix<Scalar, _Dimension, Eigen::Dynamic>
DataMatrix;
509 typedef Eigen::Matrix<Scalar, 2, 1> Bounds;
510 typedef Eigen::Matrix<Scalar, 2, _Dimension> BoundingBox;
524 Index splitaxis = -1;
539 Node(
const Index splitaxis,
545 splitaxis(splitaxis),
546 splitpoint(splitpoint) {}
548 bool isLeaf()
const {
return !hasLeft() && !hasRight(); }
550 bool isInner()
const {
return hasLeft() && hasRight(); }
552 bool hasLeft()
const {
return left >= 0; }
554 bool hasRight()
const {
return right >= 0; }
559 std::vector<Index> indices_ = std::vector<Index>();
560 std::vector<Node> nodes_ = std::vector<Node>();
562 Index bucketSize_ = 16;
564 bool compact_ =
false;
565 bool balanced_ =
false;
566 bool takeRoot_ =
true;
572 BoundingBox bbox_ = BoundingBox();
578 calculateBoundingBox(startIdx,
length, bbox);
579 return static_cast<Index>(nodes_.size() - 1);
588 void calculateBoundingBox(
const Index startIdx,
590 BoundingBox &bbox)
const {
592 assert(startIdx >= 0);
593 assert(
static_cast<size_t>(startIdx +
length) <= indices_.size());
594 assert(data_->rows() == bbox.cols());
599 Index first = indices_[startIdx];
600 for (
Index i = 0; i < bbox.cols(); ++i) {
601 bbox(0, i) = data(i, first);
602 bbox(1, i) = data(i, first);
608 Index col = indices_[startIdx + i];
609 assert(col >= 0 && col < data.cols());
612 for (
Index j = 0; j < data.rows(); ++j) {
613 bbox(0, j) =
std::min(bbox(0, j), data(j, col));
614 bbox(1, j) =
std::max(bbox(1, j), data(j, col));
621 void calculateBounds(
const Index startIdx,
624 Bounds &bounds)
const {
626 assert(startIdx >= 0);
627 assert(
static_cast<size_t>(startIdx +
length) <= indices_.size());
631 bounds(0) = data(dim, indices_[startIdx]);
632 bounds(1) = data(dim, indices_[startIdx]);
635 Index col = indices_[startIdx + i];
636 assert(col >= 0 && col < data.cols());
638 bounds(0) =
std::min(bounds(0), data(dim, col));
639 bounds(1) =
std::max(bounds(1), data(dim, col));
643 void calculateSplittingMidpoint(
const Index startIdx,
645 const BoundingBox &bbox,
648 Index &splitoffset) {
654 for (
Index i = 0; i < data.rows(); ++i) {
655 Scalar diff = bbox(1, i) - bbox(0, i);
656 if (diff > splitsize) {
665 calculateBounds(startIdx,
length, splitaxis, bounds);
666 splitsize = bounds(1) - bounds(0);
668 const Index origSplitaxis = splitaxis;
669 for (
Index i = 0; i < data.rows(); ++i) {
671 if (i == origSplitaxis)
continue;
672 Scalar diff = bbox(1, i) - bbox(0, i);
674 if (diff > splitsize) {
677 calculateBounds(startIdx,
length, splitaxis, newBounds);
678 diff = newBounds(1) - newBounds(0);
679 if (diff > splitsize) {
688 splitpoint = (bounds(0) + bounds(1)) /
static_cast<Scalar>(2);
690 Index leftIdx = startIdx;
694 while (leftIdx <= rightIdx) {
697 while (leftIdx <= rightIdx &&
698 data(splitaxis, indices_[leftIdx]) < splitpoint)
703 while (leftIdx <= rightIdx &&
704 data(splitaxis, indices_[rightIdx]) >= splitpoint)
707 if (leftIdx <= rightIdx) {
708 std::swap(indices_[leftIdx], indices_[rightIdx]);
715 const Index offset1 = leftIdx - startIdx;
717 rightIdx = startIdx +
length - 1;
719 while (leftIdx <= rightIdx) {
722 while (leftIdx <= rightIdx &&
723 data(splitaxis, indices_[leftIdx]) <= splitpoint)
728 while (leftIdx <= rightIdx &&
729 data(splitaxis, indices_[rightIdx]) > splitpoint)
732 if (leftIdx <= rightIdx) {
733 std::swap(indices_[leftIdx], indices_[rightIdx]);
740 const Index offset2 = leftIdx - startIdx;
747 if (offset1 > halfLength)
748 splitoffset = offset1;
749 else if (offset2 < halfLength)
750 splitoffset = offset2;
754 splitoffset = halfLength;
761 assert(startIdx >= 0);
762 assert(
static_cast<size_t>(startIdx +
length) <= indices_.size());
763 assert(data_->rows() == bbox.cols());
766 const Index nodeIdx = nodes_.size();
767 nodes_.push_back(
Node());
772 calculateSplittingMidpoint(startIdx,
length, bbox, splitaxis,
773 splitpoint, splitoffset);
775 nodes_[nodeIdx].splitaxis = splitaxis;
776 nodes_[nodeIdx].splitpoint = splitpoint;
778 const Index leftStart = startIdx;
779 const Index leftLength = splitoffset;
780 const Index rightStart = startIdx + splitoffset;
787 bboxLeft(1, splitaxis) = splitpoint;
788 Index left = buildR(leftStart, leftLength, bboxLeft);
789 nodes_[nodeIdx].left = left;
792 bboxRight(0, splitaxis) = splitpoint;
793 Index right = buildR(rightStart, rightLength, bboxRight);
794 nodes_[nodeIdx].right = right;
797 nodes_[nodeIdx].splitlower = bboxLeft(1, splitaxis);
798 nodes_[nodeIdx].splitupper = bboxRight(0, splitaxis);
801 for (
Index i = 0; i < bbox.cols(); ++i) {
802 bbox(0, i) =
std::min(bboxLeft(0, i), bboxRight(0, i));
803 bbox(1, i) =
std::max(bboxLeft(1, i), bboxRight(1, i));
811 if (
length <= bucketSize_)
812 return buildLeafNode(startIdx,
length, bbox);
814 return buildInnerNode(startIdx,
length, bbox);
817 bool isDistanceInRange(
const Scalar dist)
const {
818 return maxDist_ <= 0 ||
dist <= maxDist_;
822 const QueryHeap<Scalar> &dataHeap)
const {
823 return !dataHeap.full() ||
dist < dataHeap.front();
826 template <
typename Derived>
827 void queryLeafNode(
const Node &node,
828 const Eigen::MatrixBase<Derived> &queryPoint,
829 QueryHeap<Scalar> &dataHeap)
const {
830 assert(node.isLeaf());
835 for (
Index i = 0; i < node.length; ++i) {
836 const Index idx = node.startIdx + i;
837 assert(idx >= 0 && idx <
static_cast<Index>(indices_.size()));
840 const Index dataIdx = indices_[idx];
841 const Scalar dist = distance_(queryPoint, data.col(dataIdx));
845 if (isDistanceInRange(
dist) &&
846 isDistanceImprovement(
dist, dataHeap)) {
847 if (dataHeap.full()) dataHeap.pop();
848 dataHeap.push(dataIdx,
dist);
853 template <
typename Derived>
854 void queryInnerNode(
const Node &node,
855 const Eigen::MatrixBase<Derived> &queryPoint,
856 QueryHeap<Scalar> &dataHeap,
858 const Scalar mindist)
const {
859 assert(node.isInner());
861 const Index splitaxis = node.splitaxis;
862 const Scalar splitval = queryPoint(splitaxis, 0);
867 const bool visitLeft =
868 (splitval - node.splitlower + splitval - node.splitupper) < 0;
870 firstNode = node.left;
871 secondNode = node.right;
872 splitdist = distance_(splitval, node.splitupper);
874 firstNode = node.right;
875 secondNode = node.left;
876 splitdist = distance_(splitval, node.splitlower);
879 queryR(nodes_[firstNode], queryPoint, dataHeap, splitdists, mindist);
881 const Scalar mindistNew = mindist + splitdist - splitdists(splitaxis);
885 if (isDistanceInRange(mindistNew) &&
886 isDistanceImprovement(mindistNew, dataHeap)) {
887 const Scalar splitdistOld = splitdists(splitaxis);
888 splitdists(splitaxis) = splitdist;
889 queryR(nodes_[secondNode], queryPoint, dataHeap, splitdists,
891 splitdists(splitaxis) = splitdistOld;
895 template <
typename Derived>
896 void queryR(
const Node &node,
897 const Eigen::MatrixBase<Derived> &queryPoint,
898 QueryHeap<Scalar> &dataHeap,
900 const Scalar mindist)
const {
902 queryLeafNode(node, queryPoint, dataHeap);
904 queryInnerNode(node, queryPoint, dataHeap, splitdists, mindist);
912 Index left = depthR(nodes_[node.left]);
913 Index right = depthR(nodes_[node.right]);
962 void setThreads(
const unsigned int threads) { threads_ = threads; }
989 if (data_ ==
nullptr)
990 throw std::runtime_error(
"cannot build KDTree; data not set");
992 if (data_->size() == 0)
993 throw std::runtime_error(
"cannot build KDTree; data is empty");
996 nodes_.reserve((data_->cols() / bucketSize_) + 1);
999 indices_.resize(data_->cols());
1000 for (
size_t i = 0; i < indices_.size(); ++i) indices_[i] = i;
1002 bbox_.resize(2, data_->rows());
1006 calculateBoundingBox(startIdx,
length, bbox_);
1008 buildR(startIdx,
length, bbox_);
1028 template <
typename Derived>
1029 void query(
const Eigen::MatrixBase<Derived> &queryPoints,
1032 Matrix &distances)
const {
1033 if (nodes_.size() == 0)
1034 throw std::runtime_error(
"cannot query KDTree; not built yet");
1037 throw std::runtime_error(
1038 "cannot query KDTree; data and query points do not have "
1041 distances.setConstant(knn, queryPoints.cols(), -1);
1042 indices.setConstant(knn, queryPoints.cols(), -1);
1044 Index *indicesRaw = indices.data();
1045 Scalar *distsRaw = distances.data();
1047 #pragma omp parallel for num_threads(threads_)
1048 for (
Index i = 0; i < queryPoints.cols(); ++i) {
1049 Scalar *distPoint = &distsRaw[i * knn];
1050 Index *idxPoint = &indicesRaw[i * knn];
1058 for (
Index j = 0; j < splitdists.rows(); ++j) {
1059 const Scalar value = queryPoints(j, i);
1060 const Scalar lower = bbox_(0, j);
1061 const Scalar upper = bbox_(1, j);
1062 if (value < lower) {
1063 splitdists(j) = distance_(value, lower);
1064 }
else if (value > upper) {
1065 splitdists(j) = distance_(value, upper);
1067 splitdists(j) =
static_cast<Scalar>(0);
1070 mindist += splitdists(j);
1073 queryR(nodes_[0], queryPoints.col(i), dataHeap, splitdists,
1076 if (sorted_) dataHeap.
sort();
1079 for (
size_t j = 0; j < knn; ++j) {
1080 if (distPoint[j] < 0)
break;
1081 distPoint[j] = distance_(distPoint[j]);
1092 Index size()
const {
return data_ ==
nullptr ? 0 : data_->cols(); }
1101 return nodes_.size() == 0 ? 0 : depthR(nodes_.front());
1105 template <
typename _Scalar,
typename _Distance = Eucl
ideanDistance<_Scalar>>
1107 template <
typename _Scalar,
typename _Distance = Eucl
ideanDistance<_Scalar>>
1109 template <
typename _Scalar,
typename _Distance = Eucl
ideanDistance<_Scalar>>
1111 template <
typename _Scalar,
typename _Distance = Eucl
ideanDistance<_Scalar>>
1113 template <
typename _Scalar,
typename _Distance = Eucl
ideanDistance<_Scalar>>
1117 template <
typename Scalar>
1120 static_assert(std::is_integral<Scalar>::value,
1121 "MultiIndexHashing Scalar has to be integral");
1123 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
Matrix;
1124 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1>
Vector;
1137 std::vector<std::map<Scalar, std::vector<Index>>> buckets_;
1139 template <
typename Derived>
1140 Scalar extractCode(
const Eigen::MatrixBase<Derived> &data,
1143 Index leftShift = std::max<Index>(
1144 0,
static_cast<Index>(
sizeof(Scalar)) -
offset - substrLen_);
1147 Scalar code = (data(idx, 0) << (leftShift * 8)) >> (rightShift * 8);
1149 if (
static_cast<Index>(
sizeof(Scalar)) -
offset < substrLen_ &&
1150 idx + 1 < data.rows()) {
1151 Index shift = 2 *
static_cast<Index>(
sizeof(Scalar)) - substrLen_ -
1153 code |= data(idx + 1, 0) << (shift * 8);
1193 void setThreads(
const unsigned int threads) { threads_ = threads; }
1213 if (data_ ==
nullptr)
1214 throw std::runtime_error(
1215 "cannot build MultiIndexHashing; data not set");
1216 if (data_->size() == 0)
1217 throw std::runtime_error(
1218 "cannot build MultiIndexHashing; data is empty");
1220 const Matrix &data = *data_;
1221 const Index bytesPerVec =
1222 data.rows() *
static_cast<Index>(
sizeof(Scalar));
1223 if (bytesPerVec % substrLen_ != 0)
1224 throw std::runtime_error(
1225 "cannot build MultiIndexHashing; cannot divide byte count "
1226 "per vector by substring length without remainings");
1229 buckets_.resize(bytesPerVec / substrLen_);
1231 for (
size_t i = 0; i < buckets_.size(); ++i) {
1232 Index start =
static_cast<Index>(i) * substrLen_;
1233 Index idx = start /
static_cast<Index>(
sizeof(Scalar));
1235 std::map<Scalar, std::vector<Index>> &map = buckets_[i];
1237 for (
Index c = 0; c < data.cols(); ++c) {
1238 Scalar code = extractCode(data.col(c), idx,
offset);
1239 if (map.find(code) == map.end())
1240 map[code] = std::vector<Index>();
1241 map[code].push_back(c);
1246 template <
typename Derived>
1247 void query(
const Eigen::MatrixBase<Derived> &queryPoints,
1250 Matrix &distances)
const {
1251 if (buckets_.size() == 0)
1252 throw std::runtime_error(
1253 "cannot query MultiIndexHashing; not built yet");
1255 throw std::runtime_error(
1256 "cannot query MultiIndexHashing; data and query points do "
1257 "not have same dimension");
1259 const Matrix &data = *data_;
1261 indices.setConstant(knn, queryPoints.cols(), -1);
1262 distances.setConstant(knn, queryPoints.cols(), -1);
1264 Index *indicesRaw = indices.data();
1265 Scalar *distsRaw = distances.data();
1267 Scalar maxDistPart = maxDist_ / buckets_.size();
1269 #pragma omp parallel for num_threads(threads_)
1270 for (
Index c = 0; c < queryPoints.cols(); ++c) {
1271 std::set<Index> candidates;
1272 for (
size_t i = 0; i < buckets_.size(); ++i) {
1273 Index start =
static_cast<Index>(i) * substrLen_;
1274 Index idx = start /
static_cast<Index>(
sizeof(Scalar));
1276 const std::map<Scalar, std::vector<Index>> &map = buckets_[i];
1278 Scalar code = extractCode(queryPoints.col(c), idx,
offset);
1279 for (
const auto &x : map) {
1280 Scalar
dist = distance_(x.first, code);
1281 if (maxDistPart <= 0 ||
dist <= maxDistPart) {
1282 for (
size_t j = 0; j < x.second.size(); ++j)
1283 candidates.insert(x.second[j]);
1288 Scalar *distPoint = &distsRaw[c * knn];
1289 Index *idxPoint = &indicesRaw[c * knn];
1293 for (
Index idx : candidates) {
1294 Scalar
dist = distance_(data.col(idx), queryPoints.col(c));
1296 bool isInRange = maxDist_ <= 0 ||
dist <= maxDist_;
1297 bool isImprovement =
1299 if (isInRange && isImprovement) {
1300 if (dataHeap.
full()) dataHeap.
pop();
1305 if (sorted_) dataHeap.
sort();
1311 Index size()
const {
return data_ ==
nullptr ? 0 : data_->cols(); }
1319 dataCopy_.resize(0, 0);
1327 template <
typename Scalar,
typename Distance = flann::L2_Simple<Scalar>>
1330 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
1331 typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vector;
1332 typedef Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>
Matrixi;
1338 Matrix *dataPoints_;
1348 dataPoints_(nullptr),
1350 searchParams_(32, 0, false),
1351 indexParams_(
flann::KDTreeSingleIndexParams(15)),
1354 KDTreeFlann(Matrix &data,
const bool copy =
false) : KDTreeFlann() {
1355 setData(data,
copy);
1358 ~KDTreeFlann() { clear(); }
1364 void setChecks(
const int checks) { searchParams_.
checks = checks; }
1366 void setSorted(
const bool sorted) { searchParams_.
sorted = sorted; }
1368 void setThreads(
const int threads) { searchParams_.
cores = threads; }
1370 void setEpsilon(
const float eps) { searchParams_.
eps = eps; }
1372 void setMaxDistance(
const Scalar
dist) { maxDist_ =
dist; }
1374 void setData(Matrix &data,
const bool copy =
false) {
1377 dataPoints_ = &dataCopy_;
1379 dataPoints_ = &data;
1386 if (dataPoints_ ==
nullptr)
1387 throw std::runtime_error(
"cannot build KDTree; data not set");
1388 if (dataPoints_->size() == 0)
1389 throw std::runtime_error(
"cannot build KDTree; data is empty");
1391 if (index_ !=
nullptr)
delete index_;
1394 dataPoints_->rows());
1396 index_ =
new FlannIndex(dataPts, indexParams_);
1397 index_->buildIndex();
1400 void query(Matrix &queryPoints,
1403 Matrix &distances)
const {
1404 if (index_ ==
nullptr)
1405 throw std::runtime_error(
"cannot query KDTree; not built yet");
1406 if (dataPoints_->rows() != queryPoints.rows())
1407 throw std::runtime_error(
1408 "cannot query KDTree; KDTree has different dimension than "
1412 distances.resize(knn, queryPoints.cols());
1413 indices.resize(knn, queryPoints.cols());
1417 queryPoints.rows());
1425 index_->radiusSearch(queryPts, indicesF, distancesF, maxDist_,
1428 index_->knnSearch(queryPts, indicesF, distancesF, knn,
1432 #pragma omp parallel for num_threads(searchParams_.cores)
1433 for (
Index i = 0; i < indices.cols(); ++i) {
1435 for (
Index j = 0; j < indices.rows(); ++j) {
1436 if (indices(j, i) == -1) found =
true;
1440 distances(j, i) = -1;
1447 return dataPoints_ ==
nullptr ? 0 : dataPoints_->cols();
1450 Index dimension()
const {
1451 return dataPoints_ ==
nullptr ? 0 : dataPoints_->rows();
1455 if (index_ !=
nullptr) {
1461 FlannIndex &flannIndex() {
return index_; }
1464 typedef KDTreeFlann<double> KDTreeFlannd;
1465 typedef KDTreeFlann<float> KDTreeFlannf;
double Distance(const Point3D< Real > &p1, const Point3D< Real > &p2)
cmdLineReadable * params[]
Generic handle to any of the 8 types of E57 element objects.
void setDistance(const Distance &distance)
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > Matrix
void setSorted(const bool sorted)
BruteForce(const Matrix &data, const bool copy=false)
void setThreads(const unsigned int threads)
void setData(const Matrix &data, const bool copy=false)
void setMaxDistance(const Scalar maxDist)
void query(const Eigen::MatrixBase< Derived > &queryPoints, const size_t knn, Matrixi &indices, Matrix &distances) const
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
void setTakeRoot(const bool takeRoot)
void setDistance(const Distance &distance)
void query(const Eigen::MatrixBase< Derived > &queryPoints, const size_t knn, Matrixi &indices, Matrix &distances) const
KDTreeMinkowski(const DataMatrix &data, const bool copy=false)
void setThreads(const unsigned int threads)
void setData(const DataMatrix &data, const bool copy=false)
void setBucketSize(const Index bucketSize)
void setTakeRoot(const bool takeRoot)
void setBalanced(const bool balanced)
Eigen::Matrix< Scalar, _Dimension, 1 > DataVector
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > Matrix
void setMaxDistance(const Scalar maxDist)
void setCompact(const bool compact)
void setSorted(const bool sorted)
Eigen::Matrix< Scalar, _Dimension, Eigen::Dynamic > DataMatrix
void query(const Eigen::MatrixBase< Derived > &queryPoints, const size_t knn, Matrixi &indices, Matrix &distances) const
MultiIndexHashing(const Matrix &data, const bool copy=false)
void setThreads(const unsigned int threads)
void setMaxDistance(const Scalar maxDist)
Eigen::Matrix< Scalar, Eigen::Dynamic, 1 > Vector
Eigen::Matrix< Scalar, Eigen::Dynamic, Eigen::Dynamic > Matrix
void setData(const Matrix &data, const bool copy=false)
void setSorted(const bool sorted)
void setSubstringLength(const Index len)
void push(const Index idx, const Scalar dist)
QueryHeap(Index *indices, Scalar *distances, const size_t maxSize)
__host__ __device__ float length(float2 v)
__host__ __device__ int2 abs(int2 v)
static double dist(double x1, double y1, double x2, double y2)
BoundingBoxTpl< PointCoordinateType > BoundingBox
Default bounding-box type.
std::map< std::string, any > IndexParams
Eigen::Matrix< Index, 3, 1 > Vector3i
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > Matrixd
Eigen::Matrix< Index, 5, 1 > Vector5i
Eigen::Matrix< Index, 4, 4 > Matrix4i
Eigen::Matrix< Index, 4, 1 > Vector4i
Eigen::Matrix< float, Eigen::Dynamic, Eigen::Dynamic > Matrixf
Eigen::Matrix< Index, 2, 1 > Vector2i
Eigen::Matrix< Index, 3, 3 > Matrix3i
Eigen::MatrixXd::Index Index
Eigen::Matrix< Index, 2, 2 > Matrix2i
Eigen::Matrix< Index, Eigen::Dynamic, Eigen::Dynamic > Matrixi
Eigen::Matrix< Index, Eigen::Dynamic, 1 > Vectori
Eigen::Matrix< Index, 5, 5 > Matrix5i
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Scalar operator()(const Eigen::MatrixBase< DerivedA > &lhs, const Eigen::MatrixBase< DerivedB > &rhs) const
Scalar operator()(const Scalar lhs, const Scalar rhs) const
Scalar operator()(const Scalar val) const
Scalar operator()(const Scalar lhs, const Scalar rhs) const
Scalar operator()(const Eigen::MatrixBase< DerivedA > &lhs, const Eigen::MatrixBase< DerivedB > &rhs) const
Scalar operator()(const Scalar val) const
Scalar operator()(const Scalar lhs) const
Scalar operator()(const Scalar lhs, const Scalar rhs) const
Scalar operator()(const Scalar value) const
Scalar operator()(const Eigen::MatrixBase< DerivedA > &lhs, const Eigen::MatrixBase< DerivedB > &rhs) const
Scalar operator()(const Scalar lhs, const Scalar rhs) const
Scalar operator()(const Scalar val) const
Scalar operator()(const Eigen::MatrixBase< DerivedA > &lhs, const Eigen::MatrixBase< DerivedB > &rhs) const
Scalar operator()(const Scalar lhs, const Scalar rhs) const
Scalar operator()(const Scalar val) const
Scalar operator()(const Eigen::MatrixBase< DerivedA > &lhs, const Eigen::MatrixBase< DerivedB > &rhs) const
Scalar operator()(const Scalar val) const
Scalar operator()(const Scalar lhs, const Scalar rhs) const