链接:
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);//20
surf->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;
}