#c #kdtree #flann
#c #kdtree ( кдтри ) #фланн
Вопрос:
#include <vector>
#include <iostream>
#include <nanoflann.hpp>
#include <eigen3/Eigen/Dense>
using Eigen::MatrixX3d;
using Eigen::Vector3d;
using nanoflann::KNNResultSet;
using nanoflann::SearchParams;
using kdt = nanoflann::KDTreeEigenMatrixAdaptor<MatrixX3d, 3, nanoflann::metric_L2>;
int main()
{
// Create simple matrix
MatrixX3d matrix(10, 3);
for(unsigned int i = 0; i < 10; i )
{
double f_i = static_cast<double>(i);
matrix.row(i) = Vector3d(f_i, 0, 0);
}
// Create test points
std::vector<Vector3d> test_vecs;
for(unsigned int i = 0; i < 10; i )
{
double f_i = static_cast<double>(i);
test_vecs.push_back(Vector3d(f_i, f_i, f_i));
}
// Result buffer
double distance;
size_t index;
KNNResultSet<double> result_set(1);
result_set.init(amp;index, amp;distance);
SearchParams sp;
// KDTree
kdt matrix_index(3, std::ref(matrix), 10);
matrix_index.index->buildIndex();
//Query points backwards
for(int i = 9; i >= 0; i--)
{
Vector3d curr_vec = test_vecs.at(i);
matrix_index.index->findNeighbors(result_set, amp;curr_vec[0], sp);
std::cout << i << std::endl;
std::cout << index << " " << distance << std::endl << std::endl;
}
// Query points forwards
for(unsigned int i = 0; i < 10; i )
{
Vector3d curr_vec = test_vecs.at(i);
matrix_index.index->findNeighbors(result_set, amp;curr_vec[0], sp);
std::cout << i << std::endl;
std::cout << index << " " << distance << std::endl << std::endl;
}
}
Обратный запрос ( BQ
) возвращает ожидаемые результаты. Однако прямой запрос ( FQ
) выдает только нули (как индекс, так и расстояние). FQ
также, похоже, полностью разрушает KDTree. Если вы измените порядок двух запросов (последние два цикла for), так что FQ
это выполняется до BQ
того, как оба теперь будут выдавать только нули.
Почему возникает такое поведение и как его обойти?
Ответ №1:
5 50
для каждой итерации
Повторно инициализируйте результирующий набор на каждой итерации, и вы получите желаемое поведение:
result_set.init(amp;index, amp;distance);
matrix_index.index->findNeighbors(result_set, amp;curr_vec[0], sp);
Демонстрация: https://godbolt.org/z/s5f1jq
Комментарии:
1. Это решает проблемы, с которыми я сталкиваюсь, однако я хотел бы понять, почему эта ошибка возникла в первую очередь. Я вижу, что функция
init
-function сбрасывает некоторуюcounter
переменнуюKNNResultSet
, но для меня все еще немного загадочно, что этот счетчик делает в первую очередь и почему ошибка кажется такой «случайной».2. Используется только место
count
inaddPoint
, которое, по-видимому, поддерживает список из N точек с наименьшим расстоянием (смещая точку только в том случае, если она ниже). Если первое местоположение, которое вы просматриваете, имеет расстояние 0, оно никогда не сместит его, поэтому все это были нули.