Returns exactly (n-1) edges forming tree of minimum total length that connects all points. Undirected acyclic graph.
363{
364 const auto n =
static_cast<size_t>(
points.cols());
365 if (n < 2) {
366 return {};
367 }
368
369 const auto dim =
static_cast<size_t>(
points.rows());
370 const double* base =
points.data();
371
372 EdgeList mst_edges;
373 mst_edges.reserve(n - 1);
374
375 std::vector<bool> in_mst(n, false);
376 std::priority_queue<Edge, std::vector<Edge>, std::greater<>> pq;
377
378 in_mst[0] = true;
379
380 for (size_t j = 1; j < n; ++j) {
381 pq.push({ .a = 0, .b = j, .weight = std::sqrt(dist_sq(base, base + j * dim, dim)) });
382 }
383
384 while (!pq.empty() && mst_edges.size() < n - 1) {
385 const Edge e = pq.top();
386 pq.pop();
387
388 if (in_mst[e.b]) {
389 continue;
390 }
391
392 mst_edges.emplace_back(e.a, e.b);
393 in_mst[e.b] = true;
394
395 const double* pb = base + e.b * dim;
396 for (size_t j = 0; j < n; ++j) {
397 if (!in_mst[j]) {
398 pq.push({ .a = e.b, .b = j, .weight = std::sqrt(dist_sq(pb, base + j * dim, dim)) });
399 }
400 }
401 }
402
403 MF_DEBUG(Journal::Component::Kinesis, Journal::Context::Runtime,
404 "minimum_spanning_tree: {} points, generated {} edges",
405 n, mst_edges.size());
406
407 return mst_edges;
408}
#define MF_DEBUG(comp, ctx,...)
std::vector< glm::vec2 > * points