其实,使用VTK可以使用很多种语言,比如java,python,和C++。那么为什么非要使用C++
呢?一个原因是觉得C++语言处理数据比较快,另一个原因是需要自己写算法。通过继承polyDataAlgorithm来写自己的算法,很有成就感。
比如我们写一个滤波算法,有一堆噪音的数据,然后我们想进行表面重建,显然重建后的表面不好看,因此我们先对数据进行平滑处理。数据的平滑处理有很多种方法,比如跟中模糊算法。这里我们想用一个球平均的算法,比如提取到一些数据点的坐标,然后我们采用波松方程的方法进行平均:
我们假设X和Y是直角坐标系平面上的点,x和y的间距相同。将平面上的一个点,于它四周的四个点进行平均,然后得到这个点的数值。
我们在点(0,0)附近对F函数进行泰勒展开:
假设,则我们可以得到
就用这个办法,我们取一个点的四周的四个点,将这四个点的坐标相加,然后取平均,给中间的点,成为中间这个点的坐标。
void myPolyDataMovingAverageFilter::CenterOfMass(vtkPoints *points, double center[3]){center[0]=0;center[1]=0;center[2]=0;for(vtkIdType i=0;i<points->GetNumberOfPoints();++i){double point[3];points->GetPoint(i,point);vtkMath::Add(center,point,center);}double numberOfPoints=static_cast<double>(points->GetNumberOfPoints());vtkMath::MultiplyScalar(center,1.0/numberOfPoints);
}
我们需要继承polydataalgorithm算法,然后重写requestdata方法
int myPolyDataMovingAverageFilter::RequestData(vtkInformation *request,vtkInformationVector **inputVector,vtkInformationVector *outputVector){// get inputvtkInformation *inInfo=inputVector[0]->GetInformationObject(0);vtkPolyData* input=vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));vtkInformation *outInfo=outputVector->GetInformationObject(0);vtkPolyData* output=vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));vtkSmartPointer<vtkPoints> newPoints=vtkSmartPointer<vtkPoints>::New();newPoints->SetNumberOfPoints(input->GetNumberOfPoints());vtkSmartPointer<vtkKdTreePointLocator> kdTree=vtkSmartPointer<vtkKdTreePointLocator>::New();kdTree->SetDataSet(input);kdTree->BuildLocator();for(vtkIdType pointId=0;pointId<input->GetNumberOfPoints();++pointId){vtkSmartPointer<vtkIdList> neighborIds=vtkSmartPointer<vtkIdList>::New();double p[3];input->GetPoint(pointId,p);kdTree->FindPointsWithinRadius(Radius,p,neighborIds);vtkSmartPointer<vtkPoints> neighbors=vtkSmartPointer<vtkPoints>::New();for(vtkIdType neighborId=0;neighborId<neighborIds->GetNumberOfIds();++neighborId){double neighbor[3];input->GetPoint(neighborIds->GetId(neighborId),neighbor);neighbors->InsertNextPoint(neighbor);}double center[3];CenterOfMass(neighbors,center);newPoints->SetPoint(pointId,center);}vtkSmartPointer<vtkPolyData> newPolyData=vtkSmartPointer<vtkPolyData>::New();newPolyData->SetPoints(newPoints);vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter=vtkSmartPointer<vtkVertexGlyphFilter>::New();glyphFilter->SetInputData(newPolyData);glyphFilter->Update();output->ShallowCopy(glyphFilter->GetOutput());return 1;
}
进行算法的测试,我们使用一个spheresource创建数据,再给它加上噪音。然后对数据进行平滑处理,我们看看这些球面上的点分布如何。
图1 运行结果
从运行结果上看,噪音被滤除掉了,小球变得圆滑起来。