写一段将ply点云文件中的各个点按kruskal最小生成树的顺序连成可视化线段的C++代码
以下是将ply点云文件中的各个点按kruskal最小生成树的顺序连成可视化线段的C++代码:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <pcl/point_types.h>
#include <pcl/io/ply_io.h>
#include <pcl/visualization/pcl_visualizer.h>
struct Edge {
int src;
int dst;
double weight;
};
bool cmp(const Edge& e1, const Edge& e2) {
return e1.weight < e2.weight;
}
int find(int x, std::vector<int>& parent) {
if (parent[x] == x) {
return x;
}
return parent[x] = find(parent[x], parent);
}
void Union(int x, int y, std::vector<int>& parent) {
int px = find(x, parent);
int py = find(y, parent);
parent[py] = px;
}
std::vector<Edge> kruskal(std::vector<Edge>& edges, int n) {
std::vector<int> parent(n);
for (int i = 0; i < n; ++i) {
parent[i] = i;
}
std::sort(edges.begin(), edges.end(), cmp);
std::vector<Edge> mst;
for (int i = 0; i < edges.size(); ++i) {
int src = edges[i].src;
int dst = edges[i].dst;
if (find(src, parent) != find(dst, parent)) {
Union(src, dst, parent);
mst.push_back(edges[i]);
}
}
return mst;
}
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Please provide input file." << std::endl;
return -1;
}
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::io::loadPLYFile(argv[1], *cloud);
int n = cloud->size();
std::vector<Edge> edges(n * (n - 1) / 2);
int idx = 0;
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
double dist = std::sqrt(std::pow(cloud->points[i].x - cloud->points[j].x, 2) +
std::pow(cloud->points[i].y - cloud->points[j].y, 2) +
std::pow(cloud->points[i].z - cloud->points[j].z, 2));
edges[idx++] = {i, j, dist};
}
}
std::vector<Edge> mst = kruskal(edges, n);
pcl::visualization::PCLVisualizer viewer("Minimum Spanning Tree");
viewer.setBackgroundColor(0, 0, 0);
viewer.addPointCloud<pcl::PointXYZ>(cloud, "cloud");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
for (int i = 0; i < mst.size(); ++i) {
pcl::PointXYZ p1 = cloud->points[mst[i].src];
pcl::PointXYZ p2 = cloud->points[mst[i].dst];
std::string line_id = "line_" + std::to_string(i);
viewer.addLine(p1, p2, 1.0, 0.0, 0.0, line_id);
}
viewer.spin();
return 0;
}
该程序的实现步骤为:
- 读取ply点云文件;
- 计算任意两个点之间的距离,构建完全图,即所有点之间都有一条边;
- 对边按权值从小到大排序;
- 依次取最小的边,如果这条边的两个顶点不在同一个连通块中,则将这条边加入最小生成树中,并将这两个顶点合并到同一个连通块中;
- 将最小生成树的边可视化为线段并显示在窗口中。
注:该程序使用了PCL库进行读取ply文件和可视化,因此需要安装PCL库
原文地址: https://www.cveoy.top/t/topic/eCDE 著作权归作者所有。请勿转载和采集!