VTK修炼之道82:VTK管线机制_信息对象类VTKInformation
生活随笔
收集整理的這篇文章主要介紹了
VTK修炼之道82:VTK管线机制_信息对象类VTKInformation
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.VTK管線機制
VTK中通過管線機制來實現組合各種算法處理數據。每一種算法是一個Filter,多個Filter連接在一起形成VTK管線。每個Filter可以分為兩個組成部分:一個是算法對象,繼承自vtkAlgrithm,主要負責處理輸入的數據和信息;另一個是執行對象,繼承自vtkExecute(),負責通知算法對象何時運行以及傳遞需要處理的數據和信息。Filter類繼承自vtkAlgrithm及其子類,實例化時,內部會生成一個默認的Executive()對象,用于管理執行管線。 數據和信息通過端口在Filter中傳遞,根據數據流的方向,分為輸入端口和輸出端口,如下圖所示:Filter的輸入數據與信息存儲在輸入端口中。一個Filter可能有0個輸入端口(例如Reader對象);也可能有一個或多個輸入端口(例如,vtkGlyph3D類需要兩個輸入端口,每個輸入端口可以建立多個連接)。 一個Filter可能有1個或多個輸出端口,每個輸出端口對應一個邏輯輸出。例如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之間建立連接的示意圖: 在一個連接中,上游Filter(也稱為Producer)的輸出端口與下游Filter(也稱為Consumer)的輸出端口建立連接。上游Filter為下游Filter提供數據和信息以待處理。
2.完整的VTK管線
一個完整的VTK管線通常包含Source對象、Filter對象和Mapper對象。- Source對象時一個管線的起點,主要負責讀取文件或者根據參數生成管線處理的數據,例如,vtkBMPReader、vtkSphereSource等。讀取文件的Source通常稱為Reader。
- Filter對象是處理數據的算法類,需要一個或者多個輸入類生成一個或者多個輸出,例如,vtkImageCast、vtkCurvatures等。
- Mapper對象負責將數據轉換為圖元,但也可能將數據寫入文件或者其他軟件系統,寫文件的Mapper通常稱為Writer。
2.1 執行管線的連接和控制是如何實現的?
一般情況下,Source對象、Filter對象、Mapper對象都統稱為Filter。VTK中存在多種數據結構,如果每種數據類型都要定義一種Filter,那么將會產生非常龐大的Filter群,不利于定義一種通用的VTK執行管線。 管線的接口是通過邏輯端口(Logical Port)而不是數據流實現的,因此在形成連接的過程中不需要知道實際的數據類型,而是在執行時進行數據類型檢查,以決定管線是否執行。 vtk定義了一個vtkInfomation類,用于存儲和傳遞管線執行過程中的信息、請求和數據,實現執行管線的連接和控制。3.信息對象類vtkInformation
vtkInformation是實現VTK執行管線的一個非常重要的類。此類實際上是一個Map容器,采用Key-Value的映射方式,通過索引(Key)的類型來決定其對應的數據,用于存儲管線中的各種信息和數據。 使用vtkInformation類較好地增強了VTK執行管線的靈活性,對于管線接口而言,不需要知道數據和信息的實際類型,從而在不改變VTK執行管線類接口的情況下,方便地為Filter的端口添加新的數據。 vtkInformation類中索引Key的類型為vtkInformationKey的子類,VTK定義了大量的索引類型,這些類都繼承自vtkInformationKey。比如:vtkObjectData類中定義的靜態函數: static vtkInformationDataObjectKey* ?DDATA_OBJECT(); 用于獲取一個映射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的約束
3.1 管線信息對象
管線信息對象用于存儲執行管線的執行信息,存儲在Filter的執行對象中。每個輸出端口對應一個管線信息對象,通過vtkExecutive::GetOutputInformation()函數獲取。輸出端口的管線信息對象中包含了輸出端口的vtkDataObject數據,可以通過相應的索引Key值來獲取;與此同時,每個輸出端口的vtkDataObject數據中也存儲了對應端口的管線信息對象指針,通過vtkDataObject::GetPipelineInformation()來訪問。另外,每個輸出端口連接也對應一個管線對象,通過vtkExecutive::GetInputInformation()函數獲取。輸入端口連接對應的管線對象實際上為該鏈接對應的上游Filter的輸出端口管線對象。 SetInputConnection(int potr, vtkAlgrithmOutput* input)用于建立連接,其中input是一個vtkAlgrithmObject類型參數,定義了一個端口Index和算法對象Producer,通過函數GetIndex()和GetProducer()可以直接獲取。因此在SetInputConnection()函數中,可以通過如下代碼獲取上游Filter(producer)的端口信息對象來建立連接。 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 oneif( !this->AlgrithmInternal->Outputs[port] ){this->AlgrithmInternal[port] =vtkSmartPoint<vtkAlgorithmOutput>::New();this->AlgorithmInternal[port]->SetProducer(this);this->AlgorithmInternal[port]->SetIndex[port];}//return the proxy pbject instancereturn this->AlgorithmInternal->Outputs[port]; }一個Filter可能會有多個輸出端口,這就對應著多個管線信息對象,VTK中使用VTKInformationVector類表示信息對象的集合。在vtkExecutive中即使用該類來定義管線信息對象集合。使用該類可以方便地對信息對象進行操作,例如GetNumberOfInformationObjects()/SetNumberOfInformationObjects()用于獲取或者設置信息對象數目;SetInformationObject()/GetInformationObject()用于設置或獲取某個信息對象;Append()/Remove()用于追加或者刪除信息對象。在vtkAlgrithm中,也是該類來定義端口信息對象集合。3.2 端口信息對象
端口信息對象存儲在vtkAlgrithm類中,每個輸入端口和每個輸出端口都對應一個端口信息對象。端口信息對象的作用是指定輸入/輸出數據的類型,管線執行時需要根據輸入/輸出數據類型來判斷和生成相應的數據。vtkAlgoorithm::GetInputPortInformation()用于獲取輸入端口信息對象。在vtkAlgrithm中,使用PORT_REQUIREMENTS_FILLED索引來標識是否設置端口的需求信息。因此,在GetInputPortInformation()中需要判斷是否設置輸入端口的需求信息。如果還未設置,則調用vtkAlgrithm::fillInputInformation()函數來設置輸入端口需求信息。vtkAlgrithm也是一個很基本的基類。所以vtkAlgorithm::FillInputPortInformation()僅實現了一個空的虛函數。在vtkAlgrithum子類中需要對該虛函數進行覆蓋。例如vtkPolyDataAlgorithm中需要輸入端口的數據類型為vtkPolyData,那么相應的FillInputPortInformation()實現如下: int vtkPolyDataAlgrithm::FillInputPortInformation(int vtkNotUsed(port),vtkInformation* info) {info->Set( vtkAlgrithm::INPUT_REQUIRED_DATA_TYPE(), "vtkPolyData");return 1; }上面的代碼就是使用了INPUT_REQUIRED_DATA_TYPE索引來設置輸入數據類型的值。
3.3 算法信息對象
在vtkAlgrithm算法對象中,逼近定義了端口信息對象,還定義了一個算法信息對象。算法信息對象存儲了關于算法對象的相關信息,可以通過vtkAlgrithm::GetInformation()獲取。 例如: vtkShirinkFilter::vtkShrinkFilter() {this->ShrinkFactor = 0.5;this->GetInformation()->Set( vtkAlgorithm::PRESERVES_RANGES(), 1);this->GetInformation()->Set( vtkAlgorithm::PRESERVES_BOUNDS(), 1); }3.4 請求信息對象
VTK管線是通過一系列的請求完成的。請求被封裝為vtkInformation對象在管線中傳遞。例如在vtkDemandDrivenPipeline::UpdateData()中定義請求如下: 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用于表示一個索引請求。3.5 數據信息對象
每個vtkDataObject數據對象中都保持了一個vtkInformation信息對象,用于存儲當前數據對象中的逐句類型,可以通過函數vtkDataObject::GetInformation()來獲取。4.參看資料
1.《C++ primer》2.《The VTK User’s Guide – 11thEdition》
3. ?張曉東, 羅火靈. VTK圖形圖像開發進階[M]. 機械工業出版社, 2015.
總結
以上是生活随笔為你收集整理的VTK修炼之道82:VTK管线机制_信息对象类VTKInformation的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 历史重现,德国海关突袭IFA大展
- 下一篇: [图]运动鞋用“囧”字做图案卖断货