您现在的位置是:首页 >技术杂谈 >C++ OpenMesh拉普拉斯光顺平滑网格模型网站首页技术杂谈

C++ OpenMesh拉普拉斯光顺平滑网格模型

alicema1111 2024-06-17 10:19:19
简介C++ OpenMesh拉普拉斯光顺平滑网格模型

程序示例精选

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++,网页领域博主

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。