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); }

本方法效率不高,但是能夠滿足刪除點的要求,目前沒有其他更有效的方法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM