vtk [vtkPolyData, vtkCell, vtkPoints]

Article directory

  • 1. vtkPolyData, cell, point
    • 1) Example
    • 2) vtkPolyData, vtkCell, vtkPoints
  • 2. The difference between vtkNew<> and vtkSmartPointer<>:
  • 3. Supplement
  • 4. A simple method to determine whether the topological structures of the two are consistent

1. vtkPolyData, cell, point

1) Example

 /**
  * vtkNew is a class template
  * vtkNew<> is a simple RAII (Resource Acquisition Is Initialization) class template that is used to create objects on the heap and is responsible for the destruction of objects. Objects created using vtkNew<> are automatically destroyed when the scope ends, without the need to manually call delete.
  *
  * Do you know what a class template is and what a template class is?
  * Literally, a class template is a template, that is, class template; a template class is a class, that is, template class.
  * To put it simply: a class template is a definition and cannot be used directly. It also needs to be instantiated. Then the template class is an instantiation of the class template, and the parameters in the class are replaced by the actual types; (To put it simply: A class template that is not instantiated is called a class template, and a class template that is instantiated is a template class)
  * That is: vtkNew is a class template, and then vtkNew<vtkNameColors> is a template class
  ◆ vtkColor3d GetColor3d(const vtkStdString & name): Get the color by name.
The name is considered case-insensitive. Color is returned as vtkColor3d class. If the color is not found, black is returned.
  */
  vtkNew<vtkNamedColors> colors;

  /***
  * vtkPoints: vtkPoints represents 3D points. The data model for vtkPoints is an array of vx-vy-vz triples, accessible by (point or cell) id.
  ◆ vtkIdType vtkPoints::InsertNextPoint (double x,
     double y,
     double z
    )
    In fact, they all have float methods, but in cpp, if you don’t specify it, decimals are all double types.
    
    Source code:
    inline vtkIdType vtkPoints::InsertNextPoint(double x, double y, double z)
     {
       double p[3] = { x, y, z };
       return this->Data->InsertNextTuple(p);
     }
     //vtkDataArray* Data; // Array which represents data
     //Definition of InsertNextTuple:
vtkIdType vtkDataArray::InsertNextTuple ( vtkIdType srcTupleIdx,
vtkAbstractArray * source
)
Then this method inherits from the vtkAbstractArray class
virtual vtkIdType vtkAbstractArray::InsertNextTuple ( vtkIdType srcTupleIdx,
vtkAbstractArray * source
)
Insert the tuple from srcTupleIdx to the end of the source array.
Note that memory allocation is performed as needed to maintain data. Returns the tuple index of the inserted data.
  ****/
  vtkNew<vtkPoints> points;//Four points that make up the graphic
  points->InsertNextPoint(0.0, 0.0, 0.0);
  points->InsertNextPoint(1.0, 0.0, 0.0);
  points->InsertNextPoint(1.0, 1.0, 0.0);
  points->InsertNextPoint(0.0, 1.0, 0.0);

  // Create the polygon
/**
*vtkPolygon: represents the pixel of an n-sided polygon
vtkPolygon is a specific implementation of vtkCell, used to represent 2D n-sided polygons. Polygons cannot have any internal holes, nor can they intersect themselves. Define a polygon with n points arranged counterclockwise; do not repeat the last point.
* The GetPointIds function inherits from the vtkCell class: vtkIdList* vtkCell::GetPointIds ()
Returns a list of point IDs that define the cell.
vtkIdList* GetPointIds() { return this->PointIds; }

void vtkIdList::SetNumberOfIds ( vtkIdType number )
: Specify the number of IDs to be saved for this object.


void vtkIdList::SetId ( vtkIdType i,
vtkIdType vtkid )
: Set id at position i.
Doesn't do range checking, so it's a little faster than InsertId. Make sure to allocate memory using SetNumberOfIds() before using SetId().
 typedef long long vtkIdType;
 typedef long vtkIdType;
 typedef int vtkIdType;
void SetId(vtkIdType i, vtkIdType vtkid) VTK_EXPECTS(0 <= i & amp; & amp; i < GetNumberOfIds())
{
this->Ids[i] = vtkid;
}//Explanation: VTK_EXPECTS(0 <= i & amp; & amp; i < GetNumberOfIds()): This is an assertion macro used to check whether conditions are met at runtime. Here, the assertion ensures that the index value i passed in is greater than or equal to 0 and less than the size of the polygon point index array.
**/
  vtkNew<vtkPolygon> polygon;
  polygon->GetPointIds()->SetNumberOfIds(4); // make a quad
  polygon->GetPointIds()->SetId(0, 0);
  polygon->GetPointIds()->SetId(1, 1);
  polygon->GetPointIds()->SetId(2, 2);
  polygon->GetPointIds()->SetId(3, 3);//If you have questions about this: You can take a look at Figure 1 and Figure 2 below

  /****************
  *vtkCellArray: object to represent cell connectivity
tkCellArray is used to represent the topology of a data set. It stores the identity of the points contained in each cell through an explicit connection table.

Internally, the connection table is represented by two arrays: Offsets and Connectivity.

Offsets is an array of length [numCells + 1], representing the starting index position of each cell's point in the Connectivity array. The last value is always the length of the Connectivity array.

The Connectivity array stores a list of point identifiers for each cell.

So, for a dataset containing 2 triangles, a quad, and a line, the inner array would look like this:

I don’t quite understand what the following topology and current state of vtkCellArray mean?

Topology:
Unit 0: Triangle | Point ID: {0, 1, 2}
Unit 1: Triangle | Point ID: {5, 7, 2}
Unit 2: Quadrilateral | Point IDs: {3, 4, 6, 7}
Unit 3: Line | Point ID: {5, 8}

vtkCellArray (current state):
Offsets: {0, 3, 6, 10, 12}
Connectivity: {0, 1, 2, 5, 7, 2, 3, 4, 6, 7, 5, 8}



vtkIdType vtkCellArray::InsertNextCell ( vtkCell * cell )
Function:Insert a cell object.
Return the cell id of the cell.
Source code:
inline vtkIdType vtkCellArray::InsertNextCell(vtkCell* cell)
 {
   vtkIdList* pts = cell->GetPointIds();
   return this->Visit(
     vtkCellArray_detail::InsertNextCellImpl{}, pts->GetNumberOfIds(), pts->GetPointer(0));
 }
  ******************/
  vtkNew<vtkCellArray> polygons;
  polygons->InsertNextCell(polygon);//vtkNew<vtkPolygon> polygon; polygon is vtkNew<vtkPolygon>, but can be used as a parameter of vtkCell* type (because vtkPolygon is a subclass of vtkCell)
//To summarize: the function of these two lines of code is to store the topology of the data collection, that is, the connection relationship between cells. Polygon is the topology we wrote.

  //Create a PolyData
  vtkNew<vtkPolyData> polygonPolyData;
  polygonPolyData->SetPoints(points);//Give coordinate points to Polydata
  polygonPolyData->SetPolys(polygons);//Then give the topology of these coordinates to Polydata (what I understand is the connection order of the coordinates)
 //Now that we know the coordinates and how to connect them, the Polydata package is complete.

  //Then: get the renderable primitive data through mapper, then get the renderable primitive data through actor, and finally add the actor to the renderer
  // Create a mapper and actor
  vtkNew<vtkPolyDataMapper> mapper;
  mapper->SetInputData(polygonPolyData);

  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetColor(colors->GetColor3d("Silver").GetData());

  // Visualize
  vtkNew<vtkRenderer> renderer;
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->SetWindowName("Polygon");
  renderWindow->AddRenderer(renderer);
  vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
  renderWindowInteractor->SetRenderWindow(renderWindow);

  renderer->AddActor(actor);
  renderer->SetBackground(colors->GetColor3d("Salmon").GetData());//Set the background color

  renderWindow->Render();
  renderWindowInteractor->Start();

Figure 1.png

Figure 2.png

2) vtkPolyData, vtkCell, vtkPoints

https://vtk.org/doc/nightly/html/classvtkPolyData.html

https://vtk.org/doc/nightly/html/classvtkCell.html

https://vtk.org/doc/nightly/html/classvtkPoints.html

2. The difference between vtkNew<> and vtkSmartPointer<>:

For example: the same construction of window interactor

How to write

vtkSmartPointer<>:
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();

How to write vtkNew<vtkRenderWindowInteractor>:
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;

To put it simply, vtkNew has no reference counting, while vtkSmartPointer has a reference counting mechanism

Both vtkNew and vtkSmartPointer are used for the creation and management of objects in VTK (Visualization Toolkit). However, there do exist some major differences between the two:

  • vtkNew is used to create a new VTK object on the heap and maintain ownership of it. When a vtkNew object goes out of scope, it deletes its associated VTK object. Note, however, that vtkNew does not support reference counting.

  • In contrast, vtkSmartPointer is a smart pointer that maintains a reference count of VTK objects. When a vtkSmartPointer points to a VTK object, the object’s reference count is incremented by one. When a vtkSmartPointer goes out of scope or is reallocated to another object, the reference count of the original VTK object is decreased by one. If the reference count of a VTK object becomes 0, the object will be deleted.

Therefore, when we need to use the reference counting mechanism for memory management, we usually choose to use vtkSmartPointer instead of vtkNew.

Then, the author of vtk supports the use of vtkSmartPointer<>

for

V

T

K

Object management in the library, recommended

v

t

k

S

m

a

r

t

P

o

i

n

t

e

r

< >

To avoid problems such as memory leaks and dangling pointers.

For object management in the VTK library, it is recommended to use vtkSmartPointer<> to avoid problems such as memory leaks and dangling pointers.

For object management in the VTK library, it is recommended to use vtkSmartPointer<> to avoid problems such as memory leaks and dangling pointers. “

3. Supplement

Here is another article by a big guy: Once you understand the above one, the grid segmentation example written by the big guy below will not be so difficult to understand.

https://blog.csdn.net/liushao1031177/article/details/118151714#comments_29088179

4. A simple method to determine whether the topological structures of the two are consistent

For three-dimensional objects, such as a sphere and a donut, the main thing we can use to distinguish the two is the number of holes they have.
If one object has more holes than another object, the two are topologically different. This is because they violate the rules we established earlier for stretching plasticine. To create a hole, we either tear a hole in the play dough or stretch the play dough into a donut shape and bring the two ends together.