-1

How to get neighbour vertices of a mesh inside a given radius using, e.g., CGAL? A simple K-nearest search on vertices neglecting face and edge properties is not sufficient, because if meshes are close to each other, vertices of both will be found using a k-nearest approach.

An example: https://i.stack.imgur.com/oFasx.png

blue -> query point, blue circle -> search radius, green -> vertices to be found, red -> wrongly found vertices by knn search, black -> mesh

kenomo
  • 59
  • 6
  • This might work, define the distance from mesh center, consider both distances as a metric, then use KNN for example. – 4.Pi.n Feb 11 '21 at 22:40
  • But doesn't that only work as long as the mesh is almost flat? I have added an example [image](https://i.stack.imgur.com/oFasx.png). Could you clarify the approach using that image? Thanks. – kenomo Feb 12 '21 at 09:53
  • 1
    Is it good enough for your application to walk on the edges of the mesh, stopping at the vertices that are too far? – Marc Glisse Feb 12 '21 at 11:12
  • 1
    I don't know about `CGAL`, but I saw some graph related classes there. Maybe you can convert your mesh to graph, then find neighbours on it.. – Kao Feb 12 '21 at 11:31
  • Yes, that would be perfect. But I need an efficient mesh data structure. I do not really know which to chose of CGAL. Or if there is an implemented algorithm already. – kenomo Feb 12 '21 at 11:33
  • A graph-based approach is maybe fast. I give it a try. – kenomo Feb 12 '21 at 11:36
  • CGAL meshes can already be used as graphs, see the CGAL BGL package for instance. – Marc Glisse Feb 13 '21 at 12:46

1 Answers1

0

I solved the problem using the CGAL BGL package and the function CGAL::vertices_around_target.

A brief example:

typedef CGAL::Simple_cartesian<double> SCKernel;
typedef CGAL::Surface_mesh<SCKernel::Point_3> SurfaceMeshT;
typedef SurfaceMeshT::Vertex_index VertexIndex;

[...]

std::shared_ptr<SurfaceMeshT> mesh;

[...]

void getVerticesAroundTarget(std::vector<std::size_t>& indices, 
                             std::size_t ptx) {
    VertexIndex vti(ptx);
    for (auto& idx : CGAL::vertices_around_target(mesh->halfedge(vti), *mesh)){
        indices.push_back(idx.idx());
    }
}

void getNeighbourVertices(std::vector<std::size_t>& neighbourVertices, 
                          std::size_t ptx, 
                          std::size_t idx, 
                          double searchRadius) {
    std::vector<std::size_t> indices;
    getVerticesAroundTarget(indices, idx);

    for (auto& vIdx : indices) {
        if (std::find(neighbourVertices.begin(), neighbourVertices.end(), vIdx) == neighbourVertices.end()) { // Vertex has not yet been treated.
            if (squaredEuclideanDistance(ptx, vIdx) <= searchRadius * searchRadius) { // Vertex in search radius.
                neighbourVertices.push_back(vIdx);
                getNeighbourVertices(neighbourVertices, ptx, vIdx, searchRadius); // Get next neighbours around vIdx.
            }
        }
    }
}

Then

std::vector<size_t> neighbours;
double searchRadius = XXXX;
std::size_t ptx = XXXX;
getNeighbourVertices(neighbours, ptx, ptx, searchRadius);

launches the greedy search algorithm.

kenomo
  • 59
  • 6