VTK:VTK管线机制——信息对象类VTKInformation

1.VTK管线机制

VTK中通过管线机制来实现组合各种算法处理数据。每一种算法是一个人Filter,多个Filter连接在一起形成VTK管线。每一个Filter可以分为两个部分:一个是算法对象,继承自vtkAlgrithm,主要负责处理输入的数据和信息;另一个是执行对象,继承自vtkExecute(),负责通知算法对象何时运行以及需要处理的数据和信息。Filter类继承自vtkAlgrithm及其子类,实例化时,内部会生成一个默认的Executive()对象,用于管理执行管线。数据和信息通过端口在Filter中传递,根据数据流的方向,分为输入端口和输出端口,如下图所示:
在这里插入图片描述
Filter的输入数据与信息存储在输入端中。一个Filter可能有0个输入端口(例如Reader对象);也可能有一个或多个输入端口(例如,vtkGlyph3D类需要两个输入端口,每一个输入端口可以建立多个连接)。
一个Filter可能有一个或多个输出端口,每个输出端口对应一个逻辑输出。例如,vtkExtractvectorComponents类,从一个三维向量数据中提取每个分量数据,该Filter需要一个输入端口接受向量数据,三个输出端口用于输出三个分量数据,端口号分别为0,1,2.
Filter之间通过(Port)建立连接(Connection)。例如一个标准的联机代码如下:Filter2->SetInputConnection(Filter1->GetOutputPort());
该句代码将Filter1的输出端口与Filter2的输入端口建立连接,连接中只涉及一个输入端口和一个输出端口。而VTK中还有许多Filter可能需要多个输入,例如vtkGlyph3D,该类需要两个输入数据并生成一盒输出数据。因此这里需要建立两个连接,相应的函数分别为SetInputConnection()和SetSourceConnection(),其中,SetInputConnection()输出的是几何点集数据,对应输入端口为0,SetSourceConnection()输入的Glyph图形数据,对应输入端1.vtkGlyph3D中输入的两个数据具有不同的意义,因此建立两个不同的输入端口。另外对一个Filter的多个输入数据具有相同意义时,则只需要建立一个输入端口,并使用AddInputConnection()来添加新的连接。例如vtkAppendFilter类实现数据的合并,其多个输入数据具有相同的意义,而不行vtkGlyph3D的两个输入表示不同的对象,因此其连接建立如下:
apeend = vtkAppendFilter::New(); append->AddInputConnection( foo->GetOutputPort ); append->AddInputConnection( bar->GetOutputPort );
下图显示了Filter之间建立连接的示意图:
在这里插入图片描述

2.完整的VTK管线

一个完整的VTK管线通常包含Source对象,Filter对象和Mapper对象。
1.Source对象时一个管线的起点,主要负责读取文件或者根据参数生成管线处理的数据,例如,vtkBMPReader、vtkSphereSource等。读取文件的source通常称为Reader。
2.Filter对象是处理数据的算法类,需要一个或者多个输入类生成一个或者多个输出,例如,vtkImageCast、vtkCurvarures等。
3.Mapper对象负责将数据转换为图元,但也可能将数据写入文件或者其他软件系统,写文件的Mapper通常称为Write。

执行管线连接和控制的实现
一般情况下,Source对象、Filter对象、Mapper对象统称为Filter。VTK中存在多种数据结构,如果每种数据类型都要定义一种Filter,那么将会产生非常大的Filter群,不利于定义一种通用的VTK执行管线。
管线的接口是通过逻辑端口(Logical Port)而不是数据流实现的,因此在形成连接的过程中不需要知道实际的数据类型,而是在执行时进行数据类型检查,以决定管线是否执行。
vtk定义了一个vtkInfomation类,用于存储和传递管线执行过程中的信息、请求和数据,实现执行管线的连接和控制。

3.信息对象类vtkInformation

vtkInformation是实现VTK实现VTK执行管线的一个非常重要的类。此类实际上是一个Mapper容器,采用Key-Value的映射方式,通过索引(Key)的类型来决定其对应的数据,用于存储管线中各种信息和数据。
使用vtkInformation类较好地增加了VTK执行管线二等灵活性,对于管线而言,不需要知道数据和信息的实际类型,从而不改变VTK执行管线类的接口的情况下,方便地为Filter的端口添加新的数据。
vtkInformation类中索引Key的类型为vtkInformationKey的子类,VTK定义了大量的索引类型,这些类都继承自vtkinformationKey。比如:vtkObjectData类中国蒂尼的静态函数;static vtkInformationDataObjectKey* DDATA_OBJECT();用于获取一个映射vtkDataObject类型的数据的vtkInformationDataObjectKey类型索引对于获取一个映射vtkDataObject类型数据的vtkInformationDataObjectKey类型索引对象,可以方便的保存和获取一个vtkDataObject数据,该函数在CPP文件中实现如下:vtkInformationKeyMacro( vtkDataObject, DATA_OBJECT, DataObject);vtkInformationKeyMacro是一个宏,其代码如下:

#define vtkInformationKeyMacro(CLASS, NAME, Type);
{
  static vtkInformation##type##Key*  CLASS##_##NAME =
	new vtkInformation##type##Key(#NAME, #CLASS);
  return CLASS##_##NAME;
}

从该宏的定义可知,需要三个参数:一个是调用宏的类名CLASS,一个是函数名字NAME,另外一个是索引类型Type。CLASS与NAME仅在内部使用,而type决定了返回的Key的类型,如以上的vtkInformationDataObjectKey传入的type为DataObject。所以一个Key类型结构为vtkInformation##type##Key,输入不同的type,即可得到不同的Key。
Key的约束
当一个Key类型的构造函数需要额外的信息来限制Key时,需要使用vtkInformationKeyRestrictedMacro宏:
#define vtkInformationKeyRestrictedMacro( CLASS, NAME, type, required) \ { static vtkInformation##type##Key* CLASS##_##NAME = new vtkInformation##type##Key( #NAME, #CLASS, required); return CLASS##_##NAME; }
例如,vtkDataObject中静态函数ORIGIN()用于返回映射三维向量的索引Key:static vtkInformationDoubleVectorKey* ORIGIN();
其实现如下:
vtkInformationKeyRestrictedMacro( vtkDataObject, ORIGIN, Double Vector, 3);
以上返回的是一个vtkInformationDoublevectorVectorKey类型,由于使用需要限定维数大小,因此使用vtkInformationKeyRestrictedMacro,并将为数作为第四个参数传入来限定向量的大小,其类型参数为DoubleVector。使用上述方法可以方便地自定义Key类型和访问函数。

管线信息对象
管线信息对象用于存储执行管线的执行信息,存储在Filter的执行对象中。每个输出端口对应一个管线对象,通过vtkExecutive::GetOutputInformation()函数获取。输出端口的管线信息对象中包含了输出端口的vtkDataObject数据,可以通过相应的索引Key值来获取;与此同时,每一个人输出端口vtkDataObject::GetPipelineInformation()来访问。另外,每一个输出端口
连接也对应一个管线对象,通过vtkExecutive::GetInputInformation()函数获取。输入端口连接对应的管线对象实际上为该链接对应的上游Filter的输出端口管线对象。
SetInputConnection(int potr,vtkAlgrithmOutput* intput)用于建立连接,其中input是一个vtkAlgrithmObject类型参数,定义一个端口index和算法对象Producer,通过函数GetIndex()和GetProducer()可以直接获取。因此在SetInputConnection()函数中,可以通过如下代码获取上游Filter的端口信息对象来建立连接。

vtkExecutive* producer =
	( input && input->GetProducer() ) ?  input->GetProducer()->GetExecutive():0;
int producerPort = producer?  intput->GetIndex():0;
vtkInformation*  newInfo =
	producer ? producer->GetOutputInformation(producerPort):0;

GetOutputPort()函数用于获取上游Filter的输入端口信息,即SetInputConnection()中的input对象。
GetOutputPort()函数代码如下:

vtkAlgrithmOutput* vtkAlgrithm::GetOutputPort(int port)
{
    if( !this->OutputPortIndexInRange(port, "get") )
	{
	    return 0;
	}
    //Create the vtkAlgrithmOutput proxy object if there is not one
    if( !this->AlgrithmInternal->Outputs[port] )
	{
	    this->AlgrithmInternal[port] =
		vtkSmartPoint<vtkAlgorithmOutput>::New();
	    this->AlgorithmInternal[port]->SetProducer(this);
	    this->AlgorithmInternal[port]->SetIndex[port];
	}
    //return the proxy pbject instance
    return this->AlgorithmInternal->Outputs[port];
}

一个Filter可能会有多个输出端口,这就对应着多个管线信息对象,VTK中使用VTKInformationVector类表示信息对象的集合。在vtkExecutive中即使用该类来定义管线信息对象集合。使用该类可以方便地对信息对象进行操作,例如,GetNumberOfInformationObjects()/SetNumberOfInformationObjects()用于获取或设置信息对象数目;SetInformationObject()/GetinformationObject()用于设置或获取某个信息对象;Append()/Remove()用于追加或删除信息对象。在vtkAlgrithm中,也是该类来定义端口信息对象的集合。

端口信息对象

端口信息对象存储在vtkAlgrithm类中,每个输入端口和每个输出端口都对应一个端口信息对象。端口信息对象的作用是值输入/输出的类型,管线执行时需要根据输入/输出数据类型来判断和生成相应的数据。vtkAlgrithm::GetInputPortInformation()用于获取输入端口信息对象。在vtkAlgrithm,使用PORT_REQUIREMENTS_FILLED索引来标识是否设置端口的需求信息。因此,在GetInputInformation()中需要判断是否设置输入短偶需求信息。如果还为设置,则调用vtkAlgrithm::fillInformation()函数来设置输入端口需求信息。vtkAlgrithm也是一个很基本的基类。所以vtkAlgrithm::FillInputPortInformation()仅实现了一个空虚函数。在vtkAlgrithm子类中需要对该虚函数进行覆盖。例如vtkPolyDataAlgrithm中需要输入端口的数据类型为vtkPolyData,那么相应的FillInputPortInformation()实现如下:int vtkPolyDataAlgrithm::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info) { info->Set( vtkAlgrithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData"); return 1; }
上面的代码就是使用了INPUT_REQUIRED_DATA_TYPE索引来设置输入数据类型的值。

算法信息对象

在vtkAlgrithm算法对象中,定义了端口信息对象,还定义一个算法信息对象。算法信息对象存储了关于算法对象的相关信息。可以通过vtkAlgrithm::GetInformation()获取。
vtkShirinkFilter::vtkShrinkFilter() { this->ShrinkFactor = 0.5; this->GetInformation()->Set( vtkAlgorithm::PRESERVES_RANGES(), 1); this->GetInformation()->Set( vtkAlgorithm::PRESERVES_BOUNDS(), 1); }

请求信息对象

VTK管线是通过一系列的请求完成的。请求被封装为vtkInformation对象在管线中传递。例如在vtkDemandDriven::Update()中定义请求如下:
this->DataRequest = vtkInformation::New(); this->DataRequest->Set(REQUEST_DATA()); //the request is forwarded upstream through the pipeline this->DataRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream); //Algorithms process this request after it is forwarded. this->DataRequest->Set( vtkExecutive::ALGORITHM_AFTER_FORWARDED, 1);
DataRequest是一个vtkInformation对象,通过vtkInformation::New()定义。REQUEST_DATA是一个重要的请求类型。REQUEST_DATA()函数返回一个VTKInformationRequestKey索引对象,其中报损了请求的名字为REQUEST_DATA。vtkInformationRequestKey用于表示一个索引请求。

数据信息对象

每个vtkDataObject数据对象中都保持了一个vtkInformation信息对象,用于存储当前数据对象中的逐句类型,可以通过函数vtkDataObject::GetInformation()来获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

简 。单

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值