主要的测量方法Dijkstra和Floyd ,geonet。Fast Marching等等
之前还查到热测量
还在苦苦烦恼的我,突然发现vtk官网有类似的实现
https://kitware.github.io/vtk-examples/site/Cxx/PolyData/DijkstraGraphGeodesicPath/
代码一:只能演示(需要自己改动)
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkDijkstraGraphGeodesicPath.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
int main()
{
vtkNew<vtkNamedColors> colors;
vtkNew<vtkSphereSource> sphereSource;
sphereSource->Update();
vtkNew<vtkDijkstraGraphGeodesicPath> dijkstra;
dijkstra->SetInputConnection(sphereSource->GetOutputPort());
dijkstra->SetStartVertex(0); //点云开始下标
dijkstra->SetEndVertex(7);//点云结束下标
dijkstra->Update();
vtkNew<vtkPolyDataMapper> pathMapper;
pathMapper->SetInputConnection(dijkstra->GetOutputPort());
vtkNew<vtkActor> pathActor;
pathActor->SetMapper(pathMapper);
pathActor->GetProperty()->SetColor(colors->GetColor3d("HotPink").GetData());
pathActor->GetProperty()->SetLineWidth(4);
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(sphereSource->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(colors->GetColor3d("MistyRose").GetData());
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("DijkstraGraphGeodesicPath");
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->AddActor(pathActor);
renderer->SetBackground(colors->GetColor3d("MidnightBlue").GetData());
auto camera = renderer->GetActiveCamera();
camera->SetPosition(2.9, -1.6, 0.3);
camera->SetFocalPoint(0, 0, 0);
camera->SetViewUp(0, 0, 1);
camera->SetDistance(3);
camera->Zoom(1.5);
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
代码二:可以实现自己的选点
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkDijkstraGraphGeodesicPath.h>
#include <vtkCellPicker.h>
#include <vtkIdList.h>
#include <vtkPoints.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>
#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDijkstraGraphGeodesicPath.h>
#include <vtkSTLReader.h>
#include <vtkIncrementalOctreePointLocator.h>
class MyInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
static MyInteractorStyle* New();
vtkTypeMacro(MyInteractorStyle, vtkInteractorStyleTrackballCamera);
MyInteractorStyle()
{
this->Mesh = nullptr;
this->Picker = nullptr;
this->PreId = -1;
this->CurId = -1;
}
~MyInteractorStyle()
{
this->Mesh = nullptr;
this->Picker = nullptr;
this->PreId = -1;
this->CurId = -1;
}
void OnRightButtonUp()
{
auto ren = this->GetDefaultRenderer();
auto interactor = this->GetInteractor();
int* clickPos = interactor->GetEventPosition();
double pos[3];
this->Picker->Pick(clickPos[0], clickPos[1], 0, ren);
vtkIdType cellId = this->Picker->GetCellId();
if (cellId != -1)
{
vtkIdType pointId = this->Picker->GetPointId();
this->CurId = pointId;
DrawPoint();
if (this->PreId != -1)
{
DrawLine();
}
this->PreId = pointId;
}
vtkInteractorStyleTrackballCamera::OnRightButtonUp();
}
vtkPolyData* Mesh;
vtkCellPicker* Picker;
private:
void DrawPoint()
{
auto ren = this->GetDefaultRenderer();
double* pos = this->Mesh->GetPoint(this->CurId);
auto sphere = vtkSmartPointer<vtkSphereSource>::New();
sphere->SetRadius(0.01);
sphere->SetCenter(pos);
auto pointMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
pointMapper->SetInputConnection(sphere->GetOutputPort());
auto pointActor = vtkSmartPointer<vtkActor>::New();
pointActor->SetMapper(pointMapper);
pointActor->GetProperty()->SetColor(1, 0, 0); // Red
ren->AddActor(pointActor);
ren->Render();
}
void DrawLine()
{
auto dijkstra = vtkSmartPointer<vtkDijkstraGraphGeodesicPath>::New();
dijkstra->SetInputData(this->Mesh);
dijkstra->SetStartVertex(this->PreId);
dijkstra->SetEndVertex(this->CurId);
dijkstra->Update();
vtkIdList* idList = dijkstra->GetIdList();
auto points = vtkSmartPointer<vtkPoints>::New();
for (vtkIdType i = 0; i < idList->GetNumberOfIds(); i++)
{
vtkIdType id = idList->GetId(i);
points->InsertNextPoint(this->Mesh->GetPoint(id));
}
auto polyLine = vtkSmartPointer<vtkPolyLine>::New();
polyLine->GetPointIds()->SetNumberOfIds(points->GetNumberOfPoints());
for (vtkIdType i = 0; i < points->GetNumberOfPoints(); i++)
{
polyLine->GetPointIds()->SetId(i, i);
}
auto cells = vtkSmartPointer<vtkCellArray>::New();
cells->InsertNextCell(polyLine);
auto polyData = vtkSmartPointer<vtkPolyData>::New();
polyData->SetPoints(points);
polyData->SetLines(cells);
auto ren = this->GetDefaultRenderer();
auto lineMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
lineMapper->SetInputData(polyData);
//lineMapper->SetInputConnection(dijkstra->GetOutputPort());
auto lineActor = vtkSmartPointer<vtkActor>::New();
lineActor->SetMapper(lineMapper);
lineActor->GetProperty()->SetColor(0, 1, 0); // Green
lineActor->GetProperty()->SetLineWidth(3);
ren->AddActor(lineActor);
ren->Render();
}
vtkIdType PreId;
vtkIdType CurId;
};
vtkStandardNewMacro(MyInteractorStyle);
int main(int argc, char* argv[])
{
//auto sphereSource = vtkSmartPointer<vtkSphereSource>::New();
//sphereSource->Update();
vtkSmartPointer<vtkSTLReader> sphereSource = vtkSmartPointer<vtkSTLReader>::New();
sphereSource->SetFileName("./Mesh.stl");
//切换自己的stl网格数据,转换我用的软件是CloudCompare
sphereSource->Update();
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(sphereSource->GetOutputPort());
auto actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
actor->GetProperty()->EdgeVisibilityOn();
auto picker = vtkSmartPointer<vtkCellPicker>::New();
picker->AddPickList(actor);
auto renderer = vtkSmartPointer<vtkRenderer>::New();
auto renderWin = vtkSmartPointer<vtkRenderWindow>::New();
renderWin->SetSize(600, 600);
renderWin->AddRenderer(renderer);
auto style = vtkSmartPointer<MyInteractorStyle>::New();
style->SetDefaultRenderer(renderer);
style->Mesh = sphereSource->GetOutput();
style->Picker = picker;
auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWin);
interactor->SetInteractorStyle(style);
renderer->AddActor(actor);
renderer->SetBackground(1, 1, 1);
interactor->Start();
return EXIT_SUCCESS;
}
代码三:
主要实现 : 手动输入开始坐标和结束坐标, 并且打印点云坐标,计算距离
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkSphereSource.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkDijkstraGraphGeodesicPath.h>
#include <vtkSTLReader.h>
#include <vtkIncrementalOctreePointLocator.h>
int main(int, char* [])
{
// Read a stl file.
vtkSmartPointer<vtkPolyData> input1 = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkSTLReader> reader1 = vtkSmartPointer<vtkSTLReader>::New();
reader1->SetFileName("./Mesh.stl");
reader1->Update();
input1->DeepCopy(reader1->GetOutput());
input1->DeepCopy(reader1->GetOutput());
vtkSmartPointer<vtkIncrementalOctreePointLocator> kDTree1 = vtkSmartPointer<vtkIncrementalOctreePointLocator>::New();
kDTree1->SetDataSet(input1);
kDTree1->BuildLocator();
double startPos[3] = { 0.040644, -0.232344, 1.753312 };//开始
double endPos[3] = { 0.253736, -0.2223910, 1.695677 };//结束
//还是用cc 标注的点
int startId = kDTree1->FindClosestPoint(startPos);
int endId = kDTree1->FindClosestPoint(endPos);
vtkSmartPointer<vtkDijkstraGraphGeodesicPath> dijkstra =
vtkSmartPointer<vtkDijkstraGraphGeodesicPath>::New();
dijkstra->SetInputData(reader1->GetOutput());
dijkstra->SetStartVertex(startId);
dijkstra->SetEndVertex(endId);
dijkstra->Update();
vtkSmartPointer<vtkPolyDataMapper> pathMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
pathMapper->SetInputData(dijkstra->GetOutput());
vtkSmartPointer<vtkActor> pathActor = vtkSmartPointer<vtkActor>::New();
pathActor->SetMapper(pathMapper);
pathActor->GetProperty()->SetColor(1, 0, 0);
pathActor->GetProperty()->SetLineWidth(4);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(reader1->GetOutput());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->AddActor(pathActor);
renderer->SetBackground(1.0, 1.0, 1.0);
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(640, 480);
renderWindow->Render();
renderWindow->SetWindowName("PolyDataGeodesic");
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
renderWindow->Render();
renderWindowInteractor->Start();
vtkSmartPointer<vtkIdList> IdList = vtkSmartPointer<vtkIdList>::New();
IdList = dijkstra->GetIdList();
int a[100];
int b = 0;
for (int i = 0; i < IdList->GetNumberOfIds(); i++)
{
cout << IdList->GetId(i) << endl;
//cout << IdList[7879];
a[i] = IdList->GetId(i);
b += 1;
}
vtkPolyData* polydata = reader1->GetOutput();
double chic = 0;
for (int i = 0; i < b - 1; i++)
{
double p[3];
cout << a[i];
polydata->GetPoint(a[i], p);
std::cout << "Point " << i << " : (" << p[0] << " " << p[1] << " " << p[2]
<< ")" << std::endl;
double p1[3];
polydata->GetPoint(a[i + 1], p1);
std::cout << "Point " << i << " : (" << p1[0] << " " << p1[1] << " " << p1[2]
<< ")" << std::endl;
double squaredDistance = vtkMath::Distance2BetweenPoints(p, p1);
double distance = std::sqrt(squaredDistance);
chic += distance;
std::cout << "Distance = " << distance << std::endl;
}
std::cout << "最后 = " << chic << std::endl;
return EXIT_SUCCESS;
}
打印下标id
打印点云坐标
计算距离长度(m)
最后把网格的程序拿出来
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/pcd_io.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d_omp.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/surface/poisson.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
int main()
{
// Load input file into a PointCloud<T> with an appropriate type
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::PCLPointCloud2 cloud_blob;
pcl::io::loadPCDFile(".//43.pcd", cloud_blob);
pcl::fromPCLPointCloud2(cloud_blob, *cloud);
pcl::VoxelGrid<pcl::PointXYZ> filter;
filter.setInputCloud(cloud);
// 设置体素栅格的大小为 1x1x1cm
filter.setLeafSize(0.01f, 0.01f, 0.01f);
filter.filter(*cloud);
//* the data should be available in cloud
// Normal estimation*
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
tree->setInputCloud(cloud);
n.setInputCloud(cloud);
n.setSearchMethod(tree);
n.setKSearch(20);
n.compute(*normals);
//* normals should not contain the point normals + surface curvatures
// Concatenate the XYZ and normal fields*
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);
//* cloud_with_normals = cloud + normals
// Create search tree*
pcl::search::KdTree<pcl::PointNormal>::Ptr tree2(new pcl::search::KdTree<pcl::PointNormal>);
tree2->setInputCloud(cloud_with_normals);
// Initialize objects
pcl::GreedyProjectionTriangulation<pcl::PointNormal> gp3;
pcl::PolygonMesh triangles;
// Set the maximum distance between connected points (maximum edge length)
gp3.setSearchRadius(0.025);
// Set typical values for the parameters
gp3.setMu(2.5);
gp3.setMaximumNearestNeighbors(100);
gp3.setMaximumSurfaceAngle(M_PI / 4); // 45 degrees
gp3.setMinimumAngle(M_PI / 18); // 10 degrees
gp3.setMaximumAngle(2 * M_PI / 3); // 120 degrees
gp3.setNormalConsistency(false);
// Get result
gp3.setInputCloud(cloud_with_normals);
gp3.setSearchMethod(tree2);
gp3.reconstruct(triangles);
// Additional vertex information
std::vector<int> parts = gp3.getPartIDs();
std::vector<int> states = gp3.getPointStates();
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
viewer->setBackgroundColor(0, 0, 0);
//1的效果
viewer->addPolygonMesh(triangles, "my");
//2的效果
viewer->addPolylineFromPolygonMesh(triangles);
pcl::io::savePLYFile("result.ply", triangles);
viewer->addCoordinateSystem(1.0);
viewer->initCameraParameters();
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
}
// Finish
return (0);
}
2的效果
1的效果
一起的效果