写一段将ply点云文件中的各个点按最小生成树的顺序连成线段的C++代码
以下是将Ply点云文件中的各个点按最小生成树的顺序连成线段的C++代码:
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
struct Point {
float x, y, z;
};
struct Edge {
int src, dst;
float weight;
};
struct Graph {
vector<Point> points;
vector<Edge> edges;
};
bool compareEdge(Edge e1, Edge e2) {
return e1.weight < e2.weight;
}
Graph readPlyFile(string filename) {
Graph graph;
ifstream plyFile(filename);
string line;
// skip header
while (getline(plyFile, line)) {
if (line == "end_header") {
break;
}
}
// read vertices
int numVertices;
plyFile >> line >> numVertices;
for (int i = 0; i < numVertices; i++) {
Point p;
plyFile >> p.x >> p.y >> p.z;
graph.points.push_back(p);
}
// read faces
int numFaces;
plyFile >> line >> numFaces;
for (int i = 0; i < numFaces; i++) {
int numIndices;
plyFile >> numIndices;
vector<int> indices(numIndices);
for (int j = 0; j < numIndices; j++) {
plyFile >> indices[j];
}
for (int j = 0; j < numIndices - 1; j++) {
Edge e;
e.src = indices[j];
e.dst = indices[j+1];
e.weight = sqrt(pow(graph.points[indices[j]].x - graph.points[indices[j+1]].x, 2) +
pow(graph.points[indices[j]].y - graph.points[indices[j+1]].y, 2) +
pow(graph.points[indices[j]].z - graph.points[indices[j+1]].z, 2));
graph.edges.push_back(e);
}
Edge e;
e.src = indices[numIndices-1];
e.dst = indices[0];
e.weight = sqrt(pow(graph.points[indices[numIndices-1]].x - graph.points[indices[0]].x, 2) +
pow(graph.points[indices[numIndices-1]].y - graph.points[indices[0]].y, 2) +
pow(graph.points[indices[numIndices-1]].z - graph.points[indices[0]].z, 2));
graph.edges.push_back(e);
}
plyFile.close();
return graph;
}
vector<int> prim(Graph graph) {
vector<int> mst;
vector<bool> visited(graph.points.size(), false);
priority_queue<pair<float, int>, vector<pair<float, int>>, greater<pair<float, int>>> pq;
// start from first point
visited[0] = true;
for (Edge e : graph.edges) {
if (e.src == 0) {
pq.push(make_pair(e.weight, e.dst));
}
if (e.dst == 0) {
pq.push(make_pair(e.weight, e.src));
}
}
while (!pq.empty()) {
pair<float, int> p = pq.top();
pq.pop();
if (visited[p.second]) {
continue;
}
visited[p.second] = true;
mst.push_back(p.second);
for (Edge e : graph.edges) {
if ((e.src == p.second && !visited[e.dst]) ||
(e.dst == p.second && !visited[e.src])) {
pq.push(make_pair(e.weight, (e.src == p.second) ? e.dst : e.src));
}
}
}
return mst;
}
int main() {
Graph graph = readPlyFile("input.ply");
vector<int> mst = prim(graph);
ofstream outputFile("output.ply");
outputFile << "ply" << endl
<< "format ascii 1.0" << endl
<< "element vertex " << mst.size() << endl
<< "property float x" << endl
<< "property float y" << endl
<< "property float z" << endl
<< "element edge " << mst.size()-1 << endl
<< "property int vertex1" << endl
<< "property int vertex2" << endl
<< "end_header" << endl;
for (int i : mst) {
outputFile << graph.points[i].x << " " << graph.points[i].y << " " << graph.points[i].z << endl;
}
sort(mst.begin(), mst.end());
for (int i = 0; i < mst.size()-1; i++) {
outputFile << i << " " << i+1 << endl;
}
outputFile.close();
return 0;
}
该代码先通过readPlyFile函数读取Ply点云文件中的信息,将点存储在points中,将每个面中相邻的点的信息转换成边存储在edges中,并计算每条边的权值。然后通过prim函数求出最小生成树,并将最小生成树中的点和边按Ply文件格式输出到文件中
原文地址: https://www.cveoy.top/t/topic/eCuz 著作权归作者所有。请勿转载和采集!