程序示例精选
C++ OpenMesh拉普拉斯光顺平滑网格模型
如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助!
前言
这篇博客针对<<C++ OpenMesh拉普拉斯光顺平滑网格模型>>编写代码,代码整洁,规则,易读。 学习与应用推荐首选。
文章目录
一、所需工具软件
二、使用步骤
1. 引入库
2. 代码实现
3. 运行结果
三、在线协助
一、所需工具软件
1. VS,Qt
2. OpenMesh
二、使用步骤
1.引入库
#include <iostream>
#include <OpenMesh/Core/IO/MeshIO.hh>
#include <OpenMesh/Core/Mesh/PolyMesh_ArrayKernelT.hh>
typedef OpenMesh::PolyMesh_ArrayKernelT<> Mesh;
2. 代码实现
代码如下:
vtkSmartPointer<vtkPolyData> polyDataOut = vtkSmartPointer<vtkPolyData>::New();
namespace {
class MyCallback : public vtkCommand
{
public:
static MyCallback* New()
{
return new MyCallback;
}
MyCallback()
{
}
vtkNew<vtkPolyData> data;
virtual void Execute(vtkObject* caller, unsigned long, void*)
{
vtkContourWidget* contourWidget = reinterpret_cast<vtkContourWidget*>(caller);
vtkContourRepresentation* rep = static_cast<vtkContourRepresentation*>(contourWidget->GetRepresentation());
vtkContourRepresentationNode* node = rep->GetNthNode(rep->GetNumberOfNodes() - 1);
std::cout << "There are " << rep->GetNumberOfNodes() << " nodes." << std::endl;
int saveFile = rep->GetNumberOfNodes();
std::cout << "saveFile: " << saveFile << std::endl;
std::cout << "most recent node is " << std::to_string(node->WorldPosition[0]) << " " << std::to_string(node->WorldPosition[1]) << " " << std::to_string(node->WorldPosition[2]) << std::endl;
std::string valueData1 = std::to_string(node->WorldPosition[0]);
std::string valueData2 = std::to_string(node->WorldPosition[1]);
std::string valueData3 = std::to_string(node->WorldPosition[2]);
//QFile filetxt(QString::fromStdString("nodes"+saveFile.toStdString()+".txt"));
QFile filetxt(QString::fromStdString("nodes") + QString("%1").arg(saveFile) + QString::fromStdString((".txt")));
if (filetxt.open(QIODevice::WriteOnly))
{
QTextStream out(&filetxt);
//out << QString::fromStdString(valueData1)<<"," << QString::fromStdString(valueData2)<< "," << QString::fromStdString(valueData3);
out << QString::fromStdString(valueData1) << endl;
out << QString::fromStdString(valueData2) << endl;
out << QString::fromStdString(valueData3) << endl;
out.setCodec("UTF-8");
out.flush();
}
filetxt.close();
//save to nodesPointAll.txt
QFile filetxt2(QString::fromStdString("nodesPointAll.txt"));
if (filetxt2.open(QIODevice::WriteOnly | QIODevice::Append))
{
QTextStream out(&filetxt2);
//out << QString::fromStdString(valueData1)<<"," << QString::fromStdString(valueData2)<< "," << QString::fromStdString(valueData3);
out << QString::fromStdString(valueData1) << ", " << QString::fromStdString(valueData2) << ", " << QString::fromStdString(valueData3) << endl;
out.setCodec("UTF-8");
out.flush();
}
filetxt2.close();
rep->GetNodePolyData(data);
}
void SetSphereSource(vtkSmartPointer<vtkSphereSource> sphere)
{
this->SphereSource = sphere;
}
private:
vtkSmartPointer<vtkSphereSource> SphereSource;
};
class myInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
static myInteractorStyle* New();
vtkTypeMacro(myInteractorStyle, vtkInteractorStyleTrackballCamera);
int pointNum = 0;
bool contourwidgetenabled = false;
vtkContourWidget* widget;
MyCallback* callback;
virtual void OnRightButtonDown() override
{
vtkInteractorStyleTrackballCamera::OnRightButtonDown();
}
void OnMiddleButtonDown() override {
if (contourwidgetenabled == false)
{
this->widget->EnabledOn();
contourwidgetenabled = true;
}
else
{
this->widget->EnabledOff();
contourwidgetenabled = false;
}
vtkInteractorStyleTrackballCamera::OnMiddleButtonDown();
}
void setContourWidget(vtkContourWidget* widget)
{
this->widget = widget;
}
void setPolyCallback(MyCallback* callback)
{
this->callback = callback;
}
};
vtkStandardNewMacro(myInteractorStyle);
} // namespace
//多格式文件打开定义
namespace {
vtkSmartPointer<vtkPolyData> ReadPolyData(const char* fileName)
{
vtkSmartPointer<vtkPolyData> polyData;
std::string extension =
vtksys::SystemTools::GetFilenameLastExtension(std::string(fileName));
// Drop the case of the extension
std::transform(extension.begin(), extension.end(), extension.begin(),
::tolower);
if (extension == ".ply")
{
vtkNew<vtkPLYReader> reader;
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".vtp")
{
vtkNew<vtkXMLPolyDataReader> reader;
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".obj")
{
vtkNew<vtkOBJReader> reader;
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".stl")
{
vtkNew<vtkSTLReader> reader;
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else if (extension == ".vtk")
{
vtkNew<vtkPolyDataReader> reader;
reader->SetFileName(fileName);
reader->Update();
polyData = reader->GetOutput();
}
else
{
vtkNew<vtkSphereSource> source;
source->Update();
polyData = source->GetOutput();
}
return polyData;
}
}
vtkviewer2::vtkviewer2(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QObject::connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(OnOpenFile()));
QObject::connect(ui.pushButton_2, SIGNAL(clicked()), this, SLOT(smooth()));
}
void vtkviewer2::IntialWindow()
{
//初始化窗口第一次打开时的颜色
vtkNew<vtkNamedColors> colors;
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderer->SetBackground(colors->GetColor3d("CadetBlue").GetData());
ui.qvtkWidget->SetRenderWindow(renderWindow);
ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
//初始化窗口第一次打开时的颜色_END
}
void vtkviewer2::OnOpenFile()
{
IntialWindow();
QString fileNamePath = QFileDialog::getOpenFileName(this, QString::fromLocal8Bit("打开文件"), "./model/", tr(" All_files(*.*)"));
QFileInfo fi = QFileInfo(fileNamePath);
QString fileName = fi.fileName();
QString fileSuffix = fi.suffix();
QString fileAbsolutePath = fi.absolutePath();
QString title = fileName.remove(".stl");
std::cout << "fileNamePath: " << fileNamePath.toStdString() << std::endl;
std::cout << "fileName: " << fileName.toStdString() << std::endl;
std::cout << "title: " << title.toStdString() << std::endl;
std::cout << "fileSuffix: " << fileSuffix.toStdString() << std::endl;
std::cout << "fileAbsolutePath: " << fileAbsolutePath.toStdString() << std::endl;
int controlPointsX = 5;
int controlPointsY = 5;
vtkNew<vtkNamedColors> colors;
vtkNew<vtkRenderWindowInteractor> contourWidgetinteractor;
vtkSmartPointer<vtkPolyDataMapper> bezierSurfacemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
auto polyData = ReadPolyData(fileNamePath.toStdString().c_str());
polyDataOut->DeepCopy(polyData);
//vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
//reader->SetFileName(fileNamePath.toStdString().c_str());
//reader->Update();
//vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
//polyData->SetPoints(reader->GetOutput()->GetPoints());
//std::string saveFileName = "model/"+title.toStdString() +"Save.stl";
vtkSmartPointer<vtkPLYWriter> stlWriter = vtkSmartPointer<vtkPLYWriter>::New();
//stlWriter->SetFileName(saveFileName.c_str());
stlWriter->SetInputData(polyData);
stlWriter->SetFileName("temp/temp.ply");
//stlWriter->SetInputConnection(reader->GetOutputPort());
stlWriter->Write();
std::cout << "stlWriter sucessful " << std::endl;
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(polyData);
//mapper->SetInputConnection(reader->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(colors->GetColor3d("MistyRose").GetData());
actor->GetProperty()->SetOpacity(1);
// Create the RenderWindow, Renderer
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("PolygonalSurfacePointPlacer");
contourWidgetinteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->SetBackground(colors->GetColor3d("CadetBlue").GetData());
//display
ui.qvtkWidget->SetRenderWindow(renderWindow);
ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
//display-end
//mouse rotation
vtkNew<vtkContourWidget> contourWidget;
contourWidget->SetInteractor(contourWidgetinteractor);
//class defination
vtkNew<myInteractorStyle> contourWidgetinteractorstyle;
contourWidgetinteractorstyle->setContourWidget(contourWidget);
contourWidgetinteractor->SetInteractorStyle(contourWidgetinteractorstyle);
contourWidget->EnabledOff();
renderer->ResetCamera();
renderWindow->Render();
contourWidgetinteractor->Initialize();
contourWidgetinteractor->Start();
//mouse rotation-end
}
void smooth_mesh(Mesh& mesh, const int iterations)
{
for (int i = 0; i < iterations; ++i) // 迭代指定次数
{
Mesh::VertexIter v_it, v_end = mesh.vertices_end();
for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it)
{
float n = 0.0f;
for (Mesh::VertexVertexIter vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it)
{
p += mesh.point(*vit);
++n;
}
p /= n;
mesh.set_point(*v_it);
}
}
}
void vtkviewer2::smooth()
{
// Load mesh from file
std::string input_path = "temp/temp.ply";
Mesh mesh;
if (!OpenMesh::IO::read_mesh(mesh, input_path))
{
std::cerr << "Error: Cannot read mesh from " << input_path << std::endl;
return ;
}
// Smooth mesh
const int iterations = 10; // 光顺程度参数
smooth_mesh(mesh, iterations);
// Save smoothed mesh to file
std::string output_path = "temp/tempSmooth.ply";
if (!OpenMesh::IO::write_mesh(mesh, output_path))
{
std::cerr << "Error: Cannot write mesh to " << output_path << std::endl;
return ;
}
//显示
IntialWindow();
int controlPointsX = 5;
int controlPointsY = 5;
vtkNew<vtkNamedColors> colors;
vtkNew<vtkRenderWindowInteractor> contourWidgetinteractor;
vtkSmartPointer<vtkPolyDataMapper> bezierSurfacemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
auto polyData = ReadPolyData("temp/tempSmooth.ply");
polyDataOut->DeepCopy(polyData);
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(polyData);
//mapper->SetInputConnection(reader->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(colors->GetColor3d("MistyRose").GetData());
actor->GetProperty()->SetOpacity(1);
// Create the RenderWindow, Renderer
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("PolygonalSurfacePointPlacer");
contourWidgetinteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->SetBackground(colors->GetColor3d("CadetBlue").GetData());
//display
ui.qvtkWidget->SetRenderWindow(renderWindow);
ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
//display-end
//mouse rotation
vtkNew<vtkContourWidget> contourWidget;
contourWidget->SetInteractor(contourWidgetinteractor);
//class defination
vtkNew<myInteractorStyle> contourWidgetinteractorstyle;
contourWidgetinteractorstyle->setContourWidget(contourWidget);
contourWidgetinteractor->SetInteractorStyle(contourWidgetinteractorstyle);
contourWidget->EnabledOff();
renderer->ResetCamera();
renderWindow->Render();
contourWidgetinteractor->Initialize();
contourWidgetinteractor->Start();
}
3. 运行结果
三、在线协助:
如需安装运行环境或远程调试,见文章底部个人 QQ 名片,由专业技术人员远程协助!
1)远程安装运行环境,代码调试
2)Qt, C++, Python入门指导
3)界面美化
4)软件制作
博主推荐文章:python人脸识别统计人数qt窗体-CSDN博客
博主推荐文章:Python Yolov5火焰烟雾识别源码分享-CSDN博客
Python OpenCV识别行人入口进出人数统计_python识别人数-CSDN博客
个人博客主页:alicema1111的博客_CSDN博客-Python,C++,网页领域博主
博主所有文章点这里:alicema1111的博客_CSDN博客-Python,C++,网页领域博主