VTK删除vtkPolyData中的顶点和面片

  应用VTK处理网格数据,基本都要用到vtkPolyData,包括点数据信息和拓扑结构进行。点信息数据存储在vtkPoints数据结构中,拓扑结构信息可以包括顶点(verts),线(lines),多边形(polys)和三角面片(strips)。拓扑结构信息的数据类型是vtkCharArray,只存储顶点信息的索引值,本文以polys为例。

  vtkPolyData提供便利数据添加功能,添加point和添加polys示例如下:

// 添加点
double p0[3] = {1.0,0.0,0.0};
double p1[3] = {0.0,1.0,0.0};
double p2[3] = {0.0,0.0,1.0};
vtkPoints *pPoint = vtkPoints::New();
pPoint->InsertNextPoint(p0);
pPoint->InsertNextPoint(p1);
pPoint->InsertNextPoint(p2);

//添加多边形
vtkIdType pIds[3] = {0,1,2};
vtkCellArray *pPolys = vtkCellArray::New();
pPolys->InsertNextCell(pIds);

vtkPolyData *pData = vtkPolyData::New();
pData->SetPoints(pPoint);
pData->SetPolys(pPolys);

  但是,vtkPolyData删除点或者拓扑信息就没有这么简单了,应为拓扑结构中存储的是点的索引信息,删除点必然会影响点的索引值,这时就要特别注意。

  最近查了一些资料,总结了一下安全删除vtkPolyData数据中点和拓扑信息

  (1)vtkPolyData提供一个DeletePoint()的接口,可以使用这个接口删除点,但是不能真正的删除点数据。因为DeletePoint()实际操作的是vtkPolyData内部定义的数据vtkCellLinks,这个数据结构是一个辅助类,使用前必须要调用BuildLinks()函数,如果只是可视化使用,这个函数是可以用的。但是如果要删除vtkPoints里面的数据,就没有这么简单了。

  (2)vtkPolyData删除拓扑结构信息比较简单,因为拓扑信息只包括点的索引值,删除后不会影响其他数据,可以使用DeleteCell()方法。

  本文将将给出三个实例来表示vtkPolyData中数据的删除操作,其中包括一个删除拓扑信息的实例,两个删除点的实例。

实例1:删除拓扑结构

vtkIdType cellId = 200;// 要删除的面片的索引值

pData->BuildCells();
pData->DeleteCell(cellId);  // 标记要删除的cell结构,不会真正的删除
pData->RemoveDeleteCells(); // 实际删除cell结构

pData->Modified();

实例2:删除点数据,不能真正的删除点

vtkIdType pId = 100; // 要删除的顶点的索引值
pData->BuildLinks();
pData->DeletePoint(pId);
pData->DeleteLinks();
pData->Modified();

实例3:真正的删除点数据,同时恢复拓扑结构中点的索引值

// 辅助类
struct Vertex
{
  double p[3];

  inline bool operator==(const Vertex &v ) const
 {
   return (p[0] == v.p[0])&&( p[1] == v.p[1])&&(p[2] == v.p[2]);
 }

 inline bool operator != (const Vertex &v) const
 {
   return (p[0] != v.p[0])&&( p[1] != v.p[1])&&(p[2] != v.p[2]);
 }      
}
/*
* pData 要处理的网格数据
* delPIds 要删除的点的索引值,可以是多个点,用vector表示
*/
void RealDeletePoint(vtkPolyData *pData, std::vector<int> delPIds)
{
  vtkPoints
*pPoints = vtkPoints::New();   vtkCellArray *PCell = vtkCellArray::New();   vtkIdType *newIds = nullptr;   vtkIdType *pIds;   vtkIdType nId;   std::map<Vertex, int> pointMap;   for(int i = 0; i < pData->GetNumberOfCells(); i++)   {     pData->GetCellPoints(i,nId,pIds);     newIds = new vtkIdType[nId];     for(int j = 0; j < nId; j++)     {       double *p = pData->GetPoint(pIds[j]);       Vertex tmpv;       tmpv[0] = p[0];       tmpv[1] = p[1];       tmpv[2] = p[2];       auto it = pointMap.find(tmpv);       if(it != pointMap.end())       {         newIds[j] = it->second;       }       else       {         pPoints->InsertNextPoint(p);         newIds[j] = pPoints->GetNumberOfPoints()-1;       }     }     pCell->InsertNextCell(nId, newIds);     delete []newIds;     newIds = nullptr;   }   pData->SetPoints(pPoints);   pData->SetPolys(pCell); }

本方法效率不高,但是能够满足删除点的要求,目前没有其他更有效的方法。

原文地址:https://www.cnblogs.com/xuhui24/p/6555685.html