Compute nearest neighbor graph.
Connects each point to its single nearest neighbor. Directed graph: point i connects to nearest neighbor j, but j may connect to a different point k.
458{
459 const auto n =
static_cast<size_t>(
points.cols());
460 if (n < 2) {
461 return {};
462 }
463
464 const auto dim =
static_cast<size_t>(
points.rows());
465 const double* base =
points.data();
466
467 std::vector<size_t> nearest(n);
468
469 P::for_each(P::par_unseq,
470 std::views::iota(size_t { 0 }, n).begin(),
471 std::views::iota(size_t { 0 }, n).end(),
472 [&](size_t i) {
473 double min_dist_sq = std::numeric_limits<double>::max();
474 size_t best = i;
475
476 const double* pi = base + i * dim;
477 for (size_t j = 0; j < n; ++j) {
478 if (i == j) {
479 continue;
480 }
481 const double d = dist_sq(pi, base + j * dim, dim);
482 if (d < min_dist_sq) {
483 min_dist_sq = d;
484 best = j;
485 }
486 }
487
488 nearest[i] = best;
489 });
490
492 edges.reserve(n);
493
494 for (size_t i = 0; i < n; ++i) {
495 if (nearest[i] != i) {
496 edges.emplace_back(i, nearest[i]);
497 }
498 }
499
500 MF_DEBUG(Journal::Component::Kinesis, Journal::Context::Runtime,
501 "nearest_neighbor_graph: {} points, generated {} edges", n, edges.size());
502
503 return edges;
504}
#define MF_DEBUG(comp, ctx,...)
std::vector< glm::vec2 > * points
std::vector< std::pair< size_t, size_t > > EdgeList