链接:
1.https://blog.csdn.net/hw140701/article/details/52796290
2.https://blog.csdn.net/HopefulLight/article/details/79157144?utm_source=blogxgwz6
经典的Signed Distance Function重建算法主要流程如下:
1、对每个数据点,搜索其邻域数据点,使用特征向量方法计算法线和法平面
2、由于法线的方向可有正负两个不确定,故对全局使用最小生成树近似计算法线朝向
3、以立方体素(voxel)为单位,沿着曲面滑动延展,计算每个格顶点到法平面的距离
4、使用Marching Cube算法从立方体素中(插值地)提取三角面
VTK库提供的vtkSurfaceReconstructionFilter类实现了该算法。
vtkSurfaceReconstructionFilter实现了一种隐式曲面重建的方法,即将曲面看作一个符号距离函数的等值面,曲面内外的距离值得符号函数相反,则零等值面即为所求的曲面。该方法需要对点云数据进行网格划分,然后估算每个点的切平面和方向,并以每个点与最近的切平面距离来近似表面距离。这样既可得到一个符号距离的体数据,使用vtkContourFilter来提取零等值面即可得到相应的网格。
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkSmartPointer.h"
#include "vtkProperty.h"
#include "vtkCamera.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkSurfaceReconstructionFilter.h"
#include "vtkContourFilter.h"
#include "vtkSTLWriter.h"
int main() {vtkSmartPointer<vtkRenderer>ren = vtkSmartPointer<vtkRenderer>::New(); //设置绘制者(绘制对象指针)vtkSmartPointer<vtkRenderWindow>renWin = vtkSmartPointer<vtkRenderWindow>::New(); //设置绘制窗口vtkSmartPointer<vtkRenderWindowInteractor>iren = vtkSmartPointer<vtkRenderWindowInteractor>::New(); //设置绘制交互操作窗口的vtkSmartPointer<vtkPoints>m_Points = vtkSmartPointer<vtkPoints>::New();vtkSmartPointer<vtkCellArray>vertices = vtkSmartPointer<vtkCellArray>::New();//_读进点云数据信息FILE *fp = NULL;fp = fopen("../points.txt", "r"); //读取TXT中的XYZ坐标if (!fp) {printf("打开文件失败!!\n");exit(0);}double x = 0, y = 0, z = 0;int i = 0;while (!feof(fp)) {fscanf(fp, "%lf %lf %lf", &x, &y, &z);m_Points->InsertPoint(i, x, y, z); vertices->InsertNextCell(1); vertices->InsertCellPoint(i);i ++;}fclose(fp);vtkSmartPointer<vtkPolyData>points = vtkSmartPointer<vtkPolyData>::New();points->SetPoints(m_Points);vtkSmartPointer<vtkSurfaceReconstructionFilter>surf = vtkSmartPointer<vtkSurfaceReconstructionFilter>::New();surf->SetInputData(points);surf->SetNeighborhoodSize(20);//20surf->SetSampleSpacing(0.5);//用于设置划分网格的网格间距,间距与小,网格越密集,一般采用默认值0.05.surf->Update();vtkSmartPointer<vtkContourFilter>contour = vtkSmartPointer<vtkContourFilter>::New();contour->SetInputConnection(surf->GetOutputPort());contour->SetValue(0, 0.0);contour->Update();vtkNew<vtkSTLWriter> stlWriter ;stlWriter->SetFileName("../save/tmp.stl");stlWriter->SetInputConnection(contour->GetOutputPort());stlWriter->Write();stlWriter->Update();cout << "写入模型成功" << endl;vtkSmartPointer<vtkPolyDataMapper>pointMapper = vtkSmartPointer<vtkPolyDataMapper>::New();pointMapper->SetInputData(contour->GetOutput());pointMapper->ScalarVisibilityOff();//为了改actor颜色vtkSmartPointer<vtkActor>actor = vtkSmartPointer<vtkActor>::New();actor->SetMapper(pointMapper);actor->GetProperty()->SetColor(1.0, 1.0, 1.0);ren->AddActor(actor);renWin->AddRenderer(ren);renWin->SetSize(800, 800);iren->SetRenderWindow(renWin);renWin->Render();renWin->SetWindowName("SurfaceReconstructionFilter");iren->Start();return 0;
}