Skip to content

Commit 7ca6f18

Browse files
committed
feat: get the first closest point
1 parent 86ac76b commit 7ca6f18

File tree

3 files changed

+87
-39
lines changed

3 files changed

+87
-39
lines changed

src/core/closest_point_query.cpp

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
#include "math.h"
44

5+
#include <glm/gtc/type_ptr.hpp>
6+
57
#include <chrono>
68
#include <cstddef>
7-
#include <inttypes.h>
89
#include <iostream>
910
#include <limits>
1011
#include <vector>
@@ -14,14 +15,20 @@ namespace core
1415

1516
ClosestPointQuery::ClosestPointQuery(const MeshPointCloud& mesh_point_cloud)
1617
: m_mesh_point_cloud(mesh_point_cloud)
18+
, m_tree_index(
19+
3,
20+
mesh_point_cloud,
21+
nanoflann::KDTreeSingleIndexAdaptorParams(10 /* tree leaf max size */))
1722
{
1823
// Start a timer to know how long it takes to build the query object.
1924
auto timer_start = std::chrono::high_resolution_clock::now();
2025

26+
m_tree_index.buildIndex();
27+
2128
auto timer_stop = std::chrono::high_resolution_clock::now();
2229
auto process_time = std::chrono::duration_cast<std::chrono::milliseconds>(timer_stop - timer_start).count();
2330

24-
std::printf("Generated mesh query tree in %" PRId64 "ms.", process_time);
31+
std::cout << "Generated mesh query tree in " << process_time << "ms.\n";
2532
}
2633

2734
bool ClosestPointQuery::get_closest_point(
@@ -31,43 +38,38 @@ bool ClosestPointQuery::get_closest_point(
3138
{
3239
assert(max_distance > 0.0f);
3340

34-
const std::size_t triangle_count = m_mesh_point_cloud.kdtree_get_point_count() / 3;
35-
36-
//=> Naive implementation.
37-
// 1. Go through each triangle
38-
// 2. Compute the closest point on a particular mesh
39-
// 3. Keep the closest
40-
float closest_distance2 = std::numeric_limits<float>::max();
41-
result = { 0, 0, 0 };
42-
bool found = false;
43-
44-
for (std::size_t triangle_index = 0; triangle_index < triangle_count; ++triangle_index)
45-
{
46-
const glm::vec3& v1 = m_mesh_point_cloud.kdtree_get_pt(triangle_index * 3);
47-
const glm::vec3& v2 = m_mesh_point_cloud.kdtree_get_pt(triangle_index * 3 + 1);
48-
const glm::vec3& v3 = m_mesh_point_cloud.kdtree_get_pt(triangle_index * 3 + 2);
49-
50-
bool success = false;
51-
const glm::vec3 p = closest_point_in_triangle(
52-
query_point,
53-
v1,
54-
v2,
55-
v3);
56-
57-
const float distance2_to_triangle = distance2(p, query_point);
58-
59-
if (distance2_to_triangle > max_distance)
60-
continue;
61-
62-
if (distance2_to_triangle < closest_distance2)
63-
{
64-
closest_distance2 = distance2_to_triangle;
65-
result = p;
66-
found = true;
67-
}
68-
}
69-
70-
return found;
41+
static nanoflann::SearchParams search_params(
42+
32, // ignored param
43+
0.0f, // epsilon
44+
true); // true means we want results to be sorted by squared dist
45+
46+
std::vector<std::size_t> ret_index(1);
47+
std::vector<float> out_dist_sqr(1);
48+
const std::size_t num_results =
49+
m_tree_index.knnSearch(
50+
glm::value_ptr(query_point),
51+
1, // We only want 1 result, the closest one.
52+
&ret_index[0],
53+
&out_dist_sqr[0]);
54+
55+
if (num_results == 0)
56+
return false;
57+
58+
glm::vec3 v1, v2, v3;
59+
m_mesh_point_cloud.get_triangle(ret_index[0], v1, v2, v3);
60+
61+
result = closest_point_in_triangle(
62+
query_point,
63+
v1,
64+
v2,
65+
v3);
66+
67+
const float distance2_to_triangle = distance2(result, query_point);
68+
69+
if (distance2_to_triangle > max_distance)
70+
return false;;
71+
72+
return true;
7173
}
7274

7375
} // namespace core

src/core/closest_point_query.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ class ClosestPointQuery
3434

3535
private:
3636
const MeshPointCloud& m_mesh_point_cloud;
37+
38+
// nanoflann kdtree. Will be used to speed up look up time.
39+
typedef nanoflann::KDTreeSingleIndexAdaptor<
40+
nanoflann::L2_Simple_Adaptor<float, MeshPointCloud>,
41+
MeshPointCloud,
42+
3, /* Go 3D! */
43+
size_t> TreeIndex;
44+
TreeIndex m_tree_index;
45+
46+
typedef std::vector<std::pair<std::size_t, float>> TreeSearchVectorResult;
3747
};
3848

3949
} // namespace core

src/core/mesh_point_cloud.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,42 @@ class MeshPointCloud
2121
public:
2222
MeshPointCloud(const Mesh& mesh);
2323

24+
inline void get_triangle(
25+
const std::size_t idx,
26+
glm::vec3& v1,
27+
glm::vec3& v2,
28+
glm::vec3& v3) const
29+
{
30+
// The index we receive is a vertex index.
31+
// Since each triangle is made of 3 vertex
32+
// and we don't share vertices in the point cloud,
33+
// we can deduce the v1, v2 and v3 easily.
34+
// TODO: once more points are added in the cloud
35+
// other than the vertices, this won't work anymore.
36+
if (idx % 3 == 0)
37+
{
38+
v1 = m_points[idx];
39+
v2 = m_points[idx + 1];
40+
v3 = m_points[idx + 2];
41+
}
42+
else if ((idx - 1) % 3 == 0)
43+
{
44+
v1 = m_points[idx - 1];
45+
v2 = m_points[idx];
46+
v3 = m_points[idx + 1];
47+
}
48+
else if ((idx - 2) % 3 == 0)
49+
{
50+
v1 = m_points[idx - 2];
51+
v2 = m_points[idx - 1];
52+
v3 = m_points[idx];
53+
}
54+
else
55+
{
56+
assert(false);
57+
}
58+
}
59+
2460
// nanoflann compatibility implementaiton.
2561
inline std::size_t kdtree_get_point_count() const
2662
{

0 commit comments

Comments
 (0)