【VTK】基于VTK的扩展ACVD实现网格重新划分网格Remeshing
很高兴在雪易的CSDN遇见你
VTK技术爱好者 QQ:870202403 公众号:VTK忠粉
前言
本文分享基于VTK的扩展ACVD实现网格重新划分网格Remeshing,希望对各位小伙伴有所帮助!
感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步!
你的点赞就是我的动力(^U^)ノ~YO
目录
前言
1. 重新划分网格Remeshing的效果
2. 基于VTK实现的ACVD
3. Remeshing源码分享
结论:
1. 重新划分网格Remeshing的效果
在3D图形处理时,通常需要进行网格的重新划分。医学图形处理时通常使用VTK作为图形处理和渲染显示的库。
分享过关于CGAL实现Remeshing的方法,详情见:
【CGAL系列】Remesh—1 Isotropic_remeshing_example_cgal remeshing-CSDN博客
这里,我们分享基于VTK如何进行网格重新划分Remeshing。
2. 基于VTK实现的ACVD
网站链接:ACVD | Sébastien Valette (insa-lyon.fr)
源码:ACVD
ACVD库基于VTK进行扩展,为三角形网格提供一种快速高效的网格简化/重采样方法。可以应用于非常复杂的网格(数百万个顶点)。这种方法基于变分框架内的输入网格单元的聚类。这种聚类方法类似于质心的分区Voronoi区域,其中每个区域具有相同的大小,因此表面的采样非常均匀,并且对生成的三角进行测量具有良好的纵横比。
这种方法对于重新划分网格程序也很有用。
基于斯坦福兔子的聚类方法
3. Remeshing源码分享
.h文件
#pragma once #include #include class zxExampleRemeshing : public QObject { public: zxExampleRemeshing(QWidget* parent = nullptr); bool ValidateSurface(vtkPolyData* surface); vtkPolyData* Remesh(vtkPolyData* surface, int numVertices, double gradation, int subsampling, double edgeSplitting, int optimizationLevel, bool forceManifold, bool boundaryFixing); void Remeshing(); };
.cpp文件
#include "zxExampleRemeshing.h" #include "vtkSTLReader.h" #include "vtkSTLWriter.h" #include "vtkTriangleFilter.h" #include "vtkCellData.h" #include "vtkPointData.h" #include #include #include #include #include #include "vtkSurface.h" #include "vtkIsotropicDiscreteRemeshing.h" #include "vtkIsotropicMetricForClustering.h" #include "vtkQuadricTools.h" struct ClustersQuadrics final { explicit ClustersQuadrics(size_t size) : Elements(size), Size(size) { for (auto& array : Elements) array.fill(0.0); } ~ClustersQuadrics() = default; ClustersQuadrics(const ClustersQuadrics&) = delete; ClustersQuadrics& operator=(const ClustersQuadrics&) = delete; std::vector Elements; size_t Size; }; zxExampleRemeshing::zxExampleRemeshing(QWidget* parent) { } bool zxExampleRemeshing::ValidateSurface(vtkPolyData* surface) { if (nullptr == surface) return false; if (surface->GetNumberOfPoints() SetInputData(surface); tri->Update(); surface->DeepCopy(tri->GetOutput()); if (surface->GetNumberOfPolys() GetNumberOfPoints(); } if (edgeSplitting != 0.0) mesh->SplitLongEdges(edgeSplitting); std::cout SetGradation(gradation); remesher->SetBoundaryFixing(boundaryFixing); remesher->SetConsoleOutput(1); remesher->SetForceManifold(forceManifold); remesher->SetInput(mesh); remesher->SetNumberOfClusters(numVertices); remesher->SetSubsamplingThreshold(subsampling); remesher->Remesh(); std::cout GetInput(); int clusteringType = remesher->GetClusteringType(); int numItems = remesher->GetNumberOfItems(); int numMisclassifiedItems = 0; for (int i = 0; i GetValue(i); if (cluster >= 0 && cluster GetVertexNeighbourFaces(i, faceList); int numIds = static_cast(faceList->GetNumberOfIds()); for (int j = 0; j GetId(j), false); } else { vtkQuadricTools::AddTriangleQuadric(clustersQuadrics.Elements[cluster].data(), remesherInput, i, false); } } else { ++numMisclassifiedItems; } } std::cout ComputePointNormalsOn(); normals->ConsistencyOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); normals->SplittingOff(); normals->Update(); auto remeshedSurface = vtkPolyData::New(); remeshedSurface->DeepCopy(normals->GetOutput()); std::cout reader; reader->SetFileName("D:\\Data\\Remeshing\\implant.stl"); reader->Update(); vtkPolyData* polyData = vtkPolyData::New(); polyData->DeepCopy(reader->GetOutput()); std::cout GetCellData()->Initialize(); mesh->GetPointData()->Initialize(); mesh->DisplayMeshProperties(); int density = 50; int numVertices = std::max(100, static_cast(polyData->GetNumberOfPoints() * density * 0.01)); QString remeshingType = "Adaptive"; // Adaptive or Regular double gradation = remeshingType == QStringLiteral("Adaptive") ? 1.0 : 0.0; const QString quality = "Medium (fast)"; int subsampling; if (QStringLiteral("High (slow)") == quality) { subsampling = 50; } else if (QStringLiteral("Maximum (very slow)") == quality) { subsampling = 500; } else // The default is "Medium (fast)". { subsampling = 10; } bool boundingFixing = true; double edgeSplitting = 0.; double optimizationLevel = 1.0; if (numVertices == 0) { numVertices = polyData->GetNumberOfPoints(); } if (edgeSplitting != 0.0) mesh->SplitLongEdges(edgeSplitting); std::cout SetGradation(gradation); remesher->SetBoundaryFixing(boundingFixing); remesher->SetConsoleOutput(1); remesher->SetForceManifold(false); remesher->SetInput(mesh); remesher->SetNumberOfClusters(numVertices); remesher->SetSubsamplingThreshold(subsampling); remesher->Remesh(); std::cout GetInput(); int clusteringType = remesher->GetClusteringType(); int numItems = remesher->GetNumberOfItems(); int numMisclassifiedItems = 0; for (int i = 0; i GetValue(i); if (cluster >= 0 && cluster GetVertexNeighbourFaces(i, faceList); int numIds = static_cast(faceList->GetNumberOfIds()); for (int j = 0; j GetId(j), false); } else { vtkQuadricTools::AddTriangleQuadric(clustersQuadrics.Elements[cluster].data(), remesherInput, i, false); } } else { ++numMisclassifiedItems; } } std::cout ComputePointNormalsOn(); normals->ConsistencyOff(); normals->FlipNormalsOff(); normals->NonManifoldTraversalOff(); normals->SplittingOff(); normals->Update(); auto remeshedSurface = vtkPolyData::New(); remeshedSurface->DeepCopy(normals->GetOutput()); std::cout
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。