目录
1.概述
Itk::PointSet
是一种在n 维空间中以点集的形式来表示几何图形的基类。它是为itk::Mesh
提供操作点集的必要方法的基类。点具有和它们相关的值,这些值的类型是由itk::PointSet
类(例如TPixelType
)的模板参数来定义的。在ITK
中存在两种PointSets
的基本交互方式,分别是静态的和动态的。使用静态方式的条件是:集合中点的数目预先知道,并且后继对点集的操作不会改变点的数目。另一方面,使用动态方式可以支持高效地对点进行插值和删除。这两种方式的区别就意味着,在性能优化和内存管理时可以方便地对点集PointSet
的行为进行精细调整。
2.过程
为了使用点集PointSet
类,必须包含它的头文件。#include "itkPointSet.h"
然后我们必须确定与点相关的数据类型。为了跟itk::Image
的术语保持一致,通常称这个数据类型为PixelType
。点集PointSet
也在空间的维数上进行模板化,点将在空间中被表达。下面的声明阐述了点集PointSet
类的一个典型实例。typedef itk::PointSet< unsigned short, 3 > PointSetType;
点集PointSet
对象是通过在它的类型上调用New( )
方法来创建的。该对象必须分配给一个智能指针。然后将点集PointSet
引用计数并多个对象共享。当引用对象的计数减少到零时,分配给点集PointSet
的内存就会被释放。这就意味着对这种类不需要再调用Delete( )
方法。事实上,对ITK
中所有引用计数的类都永远不要直接调用Delete( )
方法。PointSetType::Pointer pointsSet = PointSetType::New();
遵循泛型编程的基本原则,点集PointSet
有一系列相关的定义类型可以确保声明兼容类型的交互对象。这些类型定义以一系列特性而为我们所熟知。PointSet
类的特性之一PointType
,可以被点集用来表示空间中的点。下面的声明就是使用了点集PointSet
特征PointType
,并重命名以便于在全局命名空间中使用。typedef PointSetType::PointType PointType;
现在可以用PointType
来声明插入到点集PointSet
中点对象。点是相对较小的对象,因此不便于使用引用计数和智能指针来进行管理。它们同典型的C++类一样可以被简单地实例化,点类从itk::Array
继承了[]
操作符,这就使得可以使用索引符号来访问它的元素。出于效率考虑,不执行边界检查,由用户确保i
索引值位于{0,Dimension−1}
范围内。点中的每个元素都和空间坐标相关联。
下面的代码阐述了如何对一个点进行实例化并对它的元素进行初始化。
PointType p0;
p0[0] = -1.0; // x coordinate
p0[1] = -1.0; // y coordinate
p0[2] = 0.0; // z coordinate
使用SetPoint( )
方法来将点插入点集PointSet
中。这种方法要求用户提供点的唯一标识符。这个标识符通常是一个无符号整数,在将点插入点集时用标识符枚举所有点。下面的代码展示了如何将三个点插入到点集:
pointsSet->SetPoint( 0, p0 );
pointsSet->SetPoint( 1, p1 );
pointsSet->SetPoint( 2, p2 );
可以通过查询点集PointSet
来确定已经插入点集PointSet
中点的数目。使用GetNumberOfPoints( )
方法的代码阐述如下。
const unsigned int numberOfPoints = pointsSet->GetNumberOfPoints();
std::cout << numberOfPoints << std::endl;
可以通过使用GetPoint( )
方法和整数标识符从点集PointSet
中读取点。点储存在用户提供的一个指针中。如果提供的标识符和已存在的点不匹配,这个方法将返回false
,同时点中的内容无效。
PointType pp;
bool pointExists = pointsSet->GetPoint( 1, & pp );
if( pointExists )
{
std::cout << "Point is = " << pp << std::endl;
}
GetPoint( )
和SetPoint( )
并不是访问点集PointSet
中的点的最有效方式。直接访问由特性定义的内部点容器,并使用迭代器来顺序访问点的列表将更直接、更有效。
3.代码
// 为了使用PointSet类,应该包含它的头文件。
#include "itkPointSet.h"
int main(int, char *[])
{
// 然后我们必须决定与点相关联的值是什么类型。这通常被称为PixelType,以使术语与itk::Image一致。PointSet也在表示点的空间维度上被模板化。
// 下面的声明说明了PointSet类的典型实例化。
using PointSetType = itk::PointSet<unsigned short, 3>;
//通过调用其类型的New()方法,可以创建PointSet对象。生成的对象必须赋值给SmartPointer。
//然后,PointSet被引用计数,可以被多个对象共享。当对对象的引用减少到零时,为PointSet分配的内存将被释放。
//这仅仅意味着用户不需要关心调用这个类上的Delete()方法。事实上,在任何引用计数的ITK类中,都不应该直接调用Delete()方法。
//
PointSetType::Pointer pointsSet = PointSetType::New();
// Software Guide : EndCodeSnippet
// 遵循泛型编程的基本原则,点集`PointSet` 有一系列相关的定义类型可以确保声明兼容类型的交互对象。
// 这些类型定义以一系列特性而为我们所熟知。`PointSet`类的特性之一`PointType`,可以被点集用来表示空间中的点。
// 下面的声明就是使用了点集`PointSet`特征`PointType`,并重命名以便于在全局命名空间中使用。`typedef PointSetType::PointType PointType;`
//
using PointType = PointSetType::PointType;
// 现在可以用`PointType` 来声明插入到点集`PointSet` 中点对象。点是相对较小的对象,因此不便于使用引用计数和智能指针来进行管理。
// 它们同典型的C++类一样可以被简单地实例化,点类从`itk::Array` 继承了`[]`操作符,这就使得可以使用索引符号来访问它的元素。
// 出于效率考虑,不执行边界检查,由用户确保`i`索引值位于`{0,Dimension−1}`范围内。点中的每个元素都和空间坐标相关联。
PointType p0;
p0[0] = -1.0; // x coordinate
p0[1] = -1.0; // y coordinate
p0[2] = 0.0; // z coordinate
PointType p1;
p1[0] = 1.0; // Point 1 = { 1,-1,0 }
p1[1] = -1.0;
p1[2] = 0.0;
PointType p2; // Point 2 = { 1,1,0 }
p2[0] = 1.0;
p2[1] = 1.0;
p2[2] = 0.0;
// 使用`SetPoint( )`方法来将点插入点集`PointSet` 中。这种方法要求用户提供点的唯一标识符。
// 这个标识符通常是一个无符号整数,在将点插入点集时用标识符枚举所有点。下面的代码展示了如何将三个点插入到点集:
pointsSet->SetPoint(0, p0);
pointsSet->SetPoint(1, p1);
pointsSet->SetPoint(2, p2);
// Software Guide : EndCodeSnippet
// 可以通过使用`GetNumberOfPoints( )` 方法查询已经插入点集`PointSet` 中点的数目。
const unsigned int numberOfPoints = pointsSet->GetNumberOfPoints();
std::cout << numberOfPoints << std::endl;
// 可以通过使用`GetPoint( )`方法和整数标识符从点集`PointSet` 中读取点。点储存在用户提供的一个指针中。
// 如果提供的标识符和已存在的点不匹配,这个方法将返回`false`,同时点中的内容无效。
PointType pp;
bool pointExists = pointsSet->GetPoint(1, &pp);
if (pointExists)
{
std::cout << "Point is = " << pp << std::endl;
}
// `GetPoint( )`和`SetPoint( )`并不是访问点集`PointSet` 中的点的最有效方式。
// 直接访问由特性定义的内部点容器,并使用迭代器来顺序访问点的列表将更直接、更有效。
return EXIT_SUCCESS;
}