文章目录
- 一,vtkPolyData、cell、point
- 1) 例子
- 2) vtkPolyData、vtkCell、vtkPoints
- 二,vtkNew<>与vtkSmartPointer<>的区别:
- 三,补充
一,vtkPolyData、cell、point
1) 例子
/**
* vtkNew 是一个类模板
* vtkNew<> 是一个简单的 RAII(Resource Acquisition Is Initialization)(资源获取即初始化)类模板,用于在堆上创建对象,并负责对象的销毁。使用 vtkNew<> 创建的对象会自动在作用域结束时被销毁,无需手动调用 delete。
*
* 你知道什么是类模板,什么是模板类吗?
* 从字面意思看,类模板是一个模板,即class template;模板类是一个类,即 template class。
* 简单的来讲:类模板就是一个定义,不能直接拿来用,还需要进行实例化,然后模板类就是类模板的实例化,类中的参数被实际类型所替代;(再简单来讲:没是实例化的叫类模板,实例化后的类模板是模板类)
* 即:vtkNew是一个类模板,然后vtkNew<vtkNameColors>是模板类
◆ vtkColor3d GetColor3d(const vtkStdString & name ):按名称获取颜色。
该名称被视为不区分大小写。颜色作为vtkColor3d类返回。如果找不到颜色,则返回黑色。
*/
vtkNew<vtkNamedColors> colors;
/***
* vtkPoints:vtkPoints表示3D点。vtkPoints的数据模型是一个vx-vy-vz三元组数组,可通过(点或单元)id访问。
◆ vtkIdType vtkPoints::InsertNextPoint ( double x,
double y,
double z
)
其实还都float的方法,但是cpp在你不指定的情况下,小数都是double类型
源码:
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
//InsertNextTuple的定义:
vtkIdType vtkDataArray::InsertNextTuple ( vtkIdType srcTupleIdx,
vtkAbstractArray * source
)
然后这个方法继承自vtkAbstractArray类
virtual vtkIdType vtkAbstractArray::InsertNextTuple ( vtkIdType srcTupleIdx,
vtkAbstractArray * source
)
将srcTupleIdx中的元组插入到源数组的末尾。
注意,根据需要执行存储器分配以保持数据。返回插入数据的元组索引。
****/
vtkNew<vtkPoints> points;//构成图形的四个点
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:表示n边多边形的像元
vtkPolygon是vtkCell的具体实现,用于表示2D n边多边形。多边形不能有任何内部孔,也不能自相交。定义n个点按逆时针方向排列的多边形;不要重复最后一点。
* GetPointIds函数继承自vtkCell类:vtkIdList* vtkCell::GetPointIds ( )
返回定义单元格的点ID列表。
vtkIdList* GetPointIds() { return this->PointIds; }
void vtkIdList::SetNumberOfIds ( vtkIdType number )
:指定此对象要保存的id数。
void vtkIdList::SetId ( vtkIdType i,
vtkIdType vtkid )
:在位置i设置id。
不做范围检查,所以它比InsertId快一点。确保在使用SetId()之前使用SetNumberOfIds()分配内存。
typedef long long vtkIdType;
typedef long vtkIdType;
typedef int vtkIdType;
void SetId(vtkIdType i, vtkIdType vtkid) VTK_EXPECTS(0 <= i && i < GetNumberOfIds())
{
this->Ids[i] = vtkid;
}//解释:VTK_EXPECTS(0 <= i && i < GetNumberOfIds()): 这是一个断言宏,用于在运行时检查条件是否满足。在这里,断言确保传入的索引值 i 大于等于 0 并且小于多边形点索引数组的大小。
**/
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);//如果你对这里有疑问:可以看一下下面的图1与图2
/*************
*vtkCellArray : 对象来表示像元连通性
tkCellArray 用于表示数据集的拓扑结构,它通过一个显式的连接表来存储每个单元所包含的点的标识。
在内部,连接表由两个数组表示:Offsets 和 Connectivity。
Offsets 是一个长度为 [numCells+1] 的数组,表示每个单元的点在 Connectivity 数组中的起始索引位置。最后一个值始终是 Connectivity 数组的长度。
Connectivity 数组存储每个单元的点标识列表。
因此,对于包含 2 个三角形、一个四边形和一条线的数据集,内部数组将如下所示:
我不太理解下面这个拓扑结构和当前状态的vtkCellArray是什么意思??????????????????????????????????
拓扑结构:
单元 0: 三角形 | 点标识:{0, 1, 2}
单元 1: 三角形 | 点标识:{5, 7, 2}
单元 2: 四边形 | 点标识:{3, 4, 6, 7}
单元 3: 线 | 点标识:{5, 8}
vtkCellArray(当前状态):
Offsets: {0, 3, 6, 10, 12}
Connectivity: {0, 1, 2, 5, 7, 2, 3, 4, 6, 7, 5, 8}
vtkIdType vtkCellArray::InsertNextCell ( vtkCell * cell )
作用:Insert a cell object.
Return the cell id of the cell.
源码:
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是vtkNew<vtkPolygon>,但是可以作为vtkCell*类型的参数(因为vtkPolygon是vtkCell的子类)
//总结一下:这两行代码的作用是存储数据集合的拓扑结构,即单元(cell)的连接关系,polygon就是我们写好的拓扑结构
// Create a PolyData
vtkNew<vtkPolyData> polygonPolyData;
polygonPolyData->SetPoints(points);//将坐标点给到Polydata
polygonPolyData->SetPolys(polygons);//再将这些坐标的拓扑结构给到Polydata(我理解的是坐标的连接顺序)
//既然知道了坐标,也知道了坐标怎么连接,那么这个Polydata就算封装完成了
//然后就是:通过mapper得到可渲染的图元数据,再通过actor得到可渲染的图元,最后将actor加入到渲染器
// 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());//设置背景颜色
renderWindow->Render();
renderWindowInteractor->Start();
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
二,vtkNew<>与vtkSmartPointer<>的区别:
举个例子:同样是构造窗口交互器
vtkSmartPointer<>的写法:
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkNew<vtkRenderWindowInteractor>的写法:
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
简单的来说 , vtkNew没有引用计数,而vtkSmartPointer有引用计数的机制
vtkNew和vtkSmartPointer都用于VTK(可视化工具包)中对象的创建和管理。但是,两者之间确实存在着一些主要的区别 :
-
vtkNew 用于在堆上创建一个新的 VTK 对象并保持其所有权。当 vtkNew 对象超出范围时,它将删除其相关联的 VTK 对象。但请注意,vtkNew 不支持引用计数。
-
相反,vtkSmartPointer 是一个智能指针,用于维护VTK对象的引用计数。当一个 vtkSmartPointer 指向一个 VTK 对象时,该对象的引用计数增加1。当 vtkSmartPointer 在超出范围或被重新分配到另一个对象时,原来的VTK对象的引用计数减少1。如果VTK对象的引用计数变为0,那么这个对象就会被删除。
所以,在需要使用引用计数机制进行内存管理的情况下,我们通常会选择使用 vtkSmartPointer 而不是 vtkNew。
然后 , vtk的作者 更加支持使用vtkSmartPointer<>
“
对于
V
T
K
库中的对象管理,推荐使用
v
t
k
S
m
a
r
t
P
o
i
n
t
e
r
<
>
来避免内存泄漏和悬挂指针等问题。
对于VTK库中的对象管理,推荐使用vtkSmartPointer<>来避免内存泄漏和悬挂指针等问题。
对于VTK库中的对象管理,推荐使用vtkSmartPointer<>来避免内存泄漏和悬挂指针等问题。”
三,补充
这里还有一篇大佬的文章:把上面的那个搞懂了,下面这个大佬写的网格分割的例子就不那么难理解了
https://blog.csdn.net/liushao1031177/article/details/118151714#comments_29088179