RSMesh 1.0.0
一个曲面重构的系统,输入为点云,输出为obj,stl等主流格式的网格文件,使用的方法为径向基函数插值,采取了并行优化、Intel-MKL等优化措施,支持百万级别的点云
载入中...
搜索中...
未找到
kdtree.cpp
1//
2// Created by RainSure on 2023/10/27.
3//
4
5#include "point_cloud/kdtree.h"
6#include "common/macros.h"
7#include <cmath>
8#include <stdexcept>
9
10#include "flann/flann.hpp"
11
12namespace rsmesh {
13 namespace point_cloud {
15 using FlannIndex = flann::Index<flann::L2<double>>;
16 public:
17 using indices_and_distaces = std::pair<std::vector<index_t>, std::vector<double>>;
18
19 impl(const geometry::points3d& points, bool use_exact_search) {
20 flann::Matrix<double> points_mat(const_cast<double *>(points.data()), points.rows(), 3);
21
22 flann_index_ = std::make_unique<FlannIndex>(points_mat, flann::KDTreeSingleIndexParams());
23 flann_index_->buildIndex();
24
25 if(use_exact_search) {
26 params_knn_.checks = flann::FLANN_CHECKS_UNLIMITED;
27 params_radius_.checks = flann::FLANN_CHECKS_UNLIMITED;
28 }
29 }
30
31 [[nodiscard]]indices_and_distaces knn_search(const geometry::point3d& point, index_t k) const {
32 flann::Matrix<double> point_mat(const_cast<double *>(point.data()), 1, 3);
33 std::vector<std::vector<size_t>> indices_v;
34 std::vector<std::vector<double>> distaces_v;
35
36 (void)flann_index_->knnSearch(point_mat, indices_v, distaces_v, k, params_knn_);
37
38 std::vector<index_t> indices;
39 indices.reserve(indices_v[0].size());
40
41 for(auto i : indices_v[0]) {
42 indices.push_back(static_cast<index_t>(i));
43 }
44
45 for(auto &d : distaces_v[0]) {
46 d = std::sqrt(d);
47 }
48
49 RSMESH_ASSERT(indices.size() == distaces_v[0].size() and indices.size() == k);
50
51 return {std::move(indices), std::move(distaces_v[0])};
52 }
53
54 [[nodiscard]] indices_and_distaces radius_search(const geometry::points3d& point, double radius) const {
55 flann::Matrix<double> point_mat(const_cast<double *>(point.data()), 1, 3);
56 std::vector<std::vector<size_t>> indices_v;
57 std::vector<std::vector<double>> distances_v;
58
59 auto radius_sq = static_cast<float>(radius * radius);
60 (void)flann_index_->radiusSearch(point_mat, indices_v, distances_v, radius_sq, params_radius_);
61
62 std::vector<index_t> indices;
63 indices.reserve(indices_v[0].size());
64
65 for(auto i : indices_v[0]) {
66 indices.push_back(static_cast<index_t>(i));
67 }
68
69 for(auto &d : distances_v[0]) {
70 d = std::sqrt(d);
71 }
72
73 return {std::move(indices), std::move(distances_v[0])};
74 }
75
76 private:
77 flann::SearchParams params_knn_;
78 flann::SearchParams params_radius_;
79 std::unique_ptr<FlannIndex> flann_index_;
80 };
81
82 kdtree::kdtree(const geometry::points3d &points, bool use_exact_search) :
83 impl_(points.rows() == 0 ? nullptr : std::make_unique<impl>(points, use_exact_search)) {}
84
85 kdtree::~kdtree() = default;
86
87 kdtree::indices_and_distaces kdtree::knn_search(const geometry::point3d &point, rsmesh::index_t k) const {
88 if (k <= 0) {
89 throw std::invalid_argument("k must be greater than 0");
90 }
91 if(impl_ == nullptr) {
92 return {};
93 }
94
95 return impl_->knn_search(point, k);
96 }
97
98 kdtree::indices_and_distaces kdtree::radius_search(const geometry::point3d &point, double radius) const {
99 if(radius <= 0.0) {
100 throw std::invalid_argument("radius must be greater than 0.0");
101 }
102
103 if(impl_ == nullptr) {
104 return {};
105 }
106 return impl_->radius_search(point, radius);
107 }
108 } // rsmesh
109} // point_cloud
indices_and_distaces knn_search(const geometry::point3d &point, index_t k) const
搜索距离某个点最近的k个点
Definition kdtree.cpp:87
indices_and_distaces radius_search(const geometry::point3d &point, double radius) const
搜索出距离某个点距离小于等于radius的全部点
Definition kdtree.cpp:98
kdtree(const geometry::points3d &points, bool use_exact_search)
构造函数
Definition kdtree.cpp:82
vectors3d points3d
3维点的集合
Definition point3d.h:48
vector3d point3d
3维点
Definition point3d.h:39
本系统的主命名空间,包含了common, examples, fmm, geometry, numeric, point_cloud等子命名空间