Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I modify a point in a cell in a vtkPolydata?

Tags:

c++

vtk

I'm trying to edit a point inside a vtkPolyData.

I tried two methods:

  • Modifying the point directly by using GetPoint and SetPoint methods (this works)
  • Accessing a cell with GetCell, then the points with GetPoint and modifying it with SetPoint (this does not work as expected)

Here is a sample code:

#include <iostream>
#include <vtkCell.h>
#include <vtkCellArray.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolygon.h>
#include <vtkSmartPointer.h>

using std::cout;
using std::endl;

int main(int, char *[])
{
  // Points
  static float x[8][3] = { {0, 0, 0}, {1, 0, 0}, {1, 1, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 1, 1}};
  // Faces
  static vtkIdType pts[6][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {0, 1, 5, 4}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 0, 4, 7}};

  // We'll create the building blocks of polydata including data attributes.
  vtkPolyData *cube = vtkPolyData::New();
  vtkPoints *points = vtkPoints::New();
  vtkCellArray *polys = vtkCellArray::New();

  // Load the point, cell, and data attributes.
  for (int i = 0; i < 8; i++)
    points->InsertPoint(i, x[i]);
  for (int i = 0; i < 6; i++)
    polys->InsertNextCell(4, pts[i]);

  // We now assign the pieces to the vtkPolyData.
  cube->SetPoints(points);
  points->Delete();
  cube->SetPolys(polys);
  polys->Delete();

  double db[3] = {0, 0, 0};

  vtkSmartPointer<vtkPoints> cube_pts_1 = vtkSmartPointer<vtkPoints>::New();
  cube_pts_1 = cube->GetPoints();
  cout << "cube_pts_1 number of points = " << cube_pts_1->GetNumberOfPoints() << endl;

  // Access and modify third point in the polydata
  vtkIdType id_1(3);
  cube->GetPoint(id_1, db);
  cout << "Point (ID = " << id_1 << ") = " << db[0] << " " << db[1] << " " << db[2] << endl;

  // Modify third point in the polydata
  db[0] = 0;
  db[1] = 2;
  db[2] = 0;
  cube_pts_1->SetPoint(id_1, db);
  cout << "Point (ID = " << id_1 << ") = " << cube_pts_1->GetPoint(id_1)[0] << " " << cube_pts_1->GetPoint(id_1)[1]
      << " " << cube_pts_1->GetPoint(id_1)[2] << endl;

  // Access face 0 of polydata
  vtkSmartPointer<vtkPoints> cube_pts_2 = vtkSmartPointer<vtkPoints>::New();
  cube_pts_2 = cube->GetCell(0)->GetPoints();
  cout << "cube_pts_2 (cell 0) number of points = " << cube_pts_2->GetNumberOfPoints() << endl;

  // Access point 3 of face 0 in polydata (= point 3 in the polydata)
  vtkIdType id_2(3);
  cube->GetCell(0)->GetPoints()->GetPoint(id_2, db);
  cout << "Point (ID = " << id_2 << ") = " << db[0] << " " << db[1] << " " << db[2] << endl;

  // Modify point 3 of face 0 in polydata
  db[0] = 0;
  db[1] = 3;
  db[2] = 0;
  cube_pts_2->SetPoint(cube->GetCell(0)->GetPointId(id_2), db);

  cout << "Point (ID = " << id_2 << ") = " << cube->GetCell(0)->GetPoints()->GetPoint(id_2)[0] << " "
      << cube->GetCell(0)->GetPoints()->GetPoint(id_2)[1] << " " << cube->GetCell(0)->GetPoints()->GetPoint(id_2)[2]
      << endl;

  return EXIT_SUCCESS;
}

How do I modify a point in a vtkPolyData when accessing the cell?

like image 405
Romain Hernandez Avatar asked Mar 26 '18 12:03

Romain Hernandez


1 Answers

The Points array of a cell is separate from the one of the polydata - it contains copies of only the points that are in the cell and is in no way linked to the polydata's array - modifying it doesn't do anything helpful most of the time. I believe the original intent was to be able to have cells that are not part of any mesh, but when they are, the Points array should not be used, only the PointsIds should, which for a given point within the cell contains its index in the parent mesh's (e.g. vtkPolyData) points.

You will almost always want to modify the polydata's points, since that is what is used by all filters, the rendering pipeline etc. That would be in your code done as:

cube_pts_1->SetPoint(cube->GetCell(0)->GetPointId(id_2), db);

Note that what you wrote instead (cube_pts_2->...) would actually cause a crash in most situations - it works in your case because you are testing on cell 0, which has the cell ids 0, 1, 2, 3, but if you use for example cell 1, the ...GetCell(1)->GetPointId(id_2) call will return 6 (ID of the third point of the second cell), which will be over the bounds of the size of the cube_pts_2 array (== 4).

like image 192
tomj Avatar answered Oct 30 '22 14:10

tomj