原文鏈接:http://www.aosabook.org/en/vtk.html
作者:Berk Geveci 與 Will Schroeder
可視化工具箱(Visualization Toolkit, VTK)是一種廣泛使用的數(shù)據(jù)處理與可視化軟件系統(tǒng)。它應(yīng)用于科學(xué)計(jì)算、醫(yī)學(xué)影像分析、計(jì)算幾何、渲染、圖像處理以及信息學(xué)等領(lǐng)域。本章,我們展示一個(gè)VTK的簡(jiǎn)要概覽,包括一些使之成為一個(gè)成功系統(tǒng)的基本設(shè)計(jì)模式。
要真正理解一個(gè)軟件系統(tǒng),關(guān)鍵之處不僅要理解它能夠解決什么問(wèn)題,而且還要了解它出現(xiàn)時(shí)的特定文化環(huán)境。在VTK的案例中,系統(tǒng)表面看起來(lái)要設(shè)計(jì)成用于科學(xué)數(shù)據(jù)的三維可視化系統(tǒng)。但VTK出現(xiàn)時(shí)的文化語(yǔ)境為奮斗者們添上了一個(gè)意義深遠(yuǎn)的背后故事,這有助于解釋軟件為什么是這樣設(shè)計(jì)和部署的。
在VTK創(chuàng)生和開(kāi)始編寫(xiě)之時(shí),它的初始作者(Will Schroeder、Ken Martin、Bill Lorensen)還是GE研發(fā)部門(mén)的科研人員。我們向一個(gè)名為L(zhǎng)YMB的先驅(qū)性系統(tǒng)投入了大量精力,該系統(tǒng)是一種以C實(shí)現(xiàn)的、類(lèi)似Smalltalk的開(kāi)發(fā)環(huán)境。在那個(gè)時(shí)代,它是一個(gè)偉大的系統(tǒng),我們作為科研人員一再地被阻止在兩大障礙上:1)IP問(wèn)題(此處意指知識(shí)產(chǎn)權(quán)(Intellectual Property, IP)——譯注。)和2)非標(biāo)準(zhǔn)的、有所有權(quán)的軟件。IP問(wèn)題之所以是個(gè)問(wèn)題,是因?yàn)橐坏〨E公司的律師介入,那么嘗試將軟件向公司外部公布軟件就幾乎不可能了。第二,即使我們?cè)贕E公司內(nèi)部部署軟件,許多我們的用戶(hù)也會(huì)受制于學(xué)習(xí)一個(gè)有所有權(quán)的、非標(biāo)準(zhǔn)系統(tǒng),因?yàn)闉榱苏莆账鞒龅呐Σ荒茉谒x開(kāi)公司后轉(zhuǎn)移到新的雇主那里;并且,這種軟件沒(méi)有標(biāo)準(zhǔn)工具集所提供的廣泛支持。于是,VTK的原始動(dòng)機(jī)就是開(kāi)發(fā)一個(gè)開(kāi)放標(biāo)準(zhǔn),或曰“協(xié)作平臺(tái)”,通過(guò)它,我們能夠很容易地將技術(shù)傳授給我們的用戶(hù)。因此,為VTK選擇一個(gè)開(kāi)源許可證或許是我們所做出的最重要的設(shè)計(jì)決策。
最終選擇了非互利的、自由的許可證(比如:選BSD(即BSD許可證(Berkeley Software Distribution License,BSD)?!g注。)而不選GPL(即GPL許可證(GNU General Public License)?!g注。))在事后證明是一個(gè)值得效仿的決策,因?yàn)樗罱K使基于商業(yè)的服務(wù)和咨詢(xún)成為可能,而這正成就了Kitware。在我們做出這個(gè)決定的時(shí)候,我們最感興趣的是降低與學(xué)術(shù)界、研究機(jī)構(gòu)以及商務(wù)實(shí)體之間合作的壁壘。我們從那時(shí)也發(fā)現(xiàn),許多組織都避免使用互利性許可證,由于它們可能造成的嚴(yán)重問(wèn)題。事實(shí)上,我們可能會(huì)爭(zhēng)論互利性許可證在延緩開(kāi)源軟件的接收上有很大作用,但這另當(dāng)別論。這里的要點(diǎn)是:與任何軟件系統(tǒng)相關(guān)的重要設(shè)計(jì)決策之一就是著作權(quán)許可證的選擇。重新審視項(xiàng)目的目標(biāo),然后再恰當(dāng)?shù)亟鉀QIP問(wèn)題是很重要的。
VTK最初是以一個(gè)科學(xué)數(shù)據(jù)可視化系統(tǒng)出現(xiàn)的??梢暬I(lǐng)域之外的許多人都天真地把它當(dāng)成一種特殊的幾何渲染:查看虛擬物體并與之交互。盡管這些確實(shí)是可視化的一部分,但是通常的數(shù)據(jù)可視化還包括把數(shù)據(jù)轉(zhuǎn)換成感知性輸入的整個(gè)過(guò)程,典型的數(shù)據(jù)是圖像,此外還包括觸覺(jué)、聽(tīng)覺(jué)等其他形式。數(shù)據(jù)形式不僅由幾何拓?fù)浣Y(jié)構(gòu)組成——比如像網(wǎng)格或者復(fù)雜空間分解等抽象形式,還有核心結(jié)構(gòu)的屬性,諸如標(biāo)量(如:溫度或壓強(qiáng)),矢量(如:速度),張量(如:應(yīng)力與張力),以及渲染屬性,諸如表面法線(xiàn)和紋理坐標(biāo)等。
注意,通常情況下,表示時(shí)空信息的數(shù)據(jù)被看做是科學(xué)可視化的一部分。然而,還有更抽象數(shù)據(jù)形式,比如市場(chǎng)統(tǒng)計(jì)資料、網(wǎng)頁(yè)、文檔以及其它信息,它們只能通過(guò)諸如非結(jié)構(gòu)文檔、表格、圖和樹(shù)等抽象(即:非時(shí)空)關(guān)系來(lái)表示。這些抽象數(shù)據(jù)一般通過(guò)信息可視化的方法來(lái)處理。在社區(qū)的幫助下,VTK現(xiàn)在能夠完成科學(xué)可視化和信息可視化方面的工作。
作為一種可視化系統(tǒng),VTK的角色是以這些形式獲取數(shù)據(jù),并最終將它們轉(zhuǎn)換成利于人類(lèi)感官理解的形式。因此,VTK的核心需求之一就是創(chuàng)建數(shù)據(jù)流管線(xiàn)的能力,這種管線(xiàn)能夠讀入、處理、表示并最終渲染數(shù)據(jù)。這樣,工具箱就必須構(gòu)建成一個(gè)靈活的系統(tǒng),它的設(shè)計(jì)在許多層面上反映了這一點(diǎn)。例如,我們有目的地將VTK設(shè)計(jì)成這樣一種工具箱,它具有許多可互換的組件,這些組件可以組合起來(lái)用于處理多種數(shù)據(jù)。
在深入介紹VTK特殊的架構(gòu)特性之前,先介紹頂層的概念,它們系統(tǒng)的開(kāi)發(fā)和使用都產(chǎn)生了深遠(yuǎn)的影響。其中之一就是VTK的混合包裝設(shè)施。該設(shè)施從VTK的C++實(shí)現(xiàn)自動(dòng)生成Python,Java,和Tcl等的語(yǔ)言綁定(還可綁定更多的語(yǔ)言,并且有些已經(jīng)實(shí)現(xiàn)了——譯注)。最具實(shí)力的開(kāi)發(fā)者將使用C++進(jìn)行工作。使用者和應(yīng)用程序開(kāi)發(fā)者也可以使用C++,但是通常情況下,上文提到的解釋性語(yǔ)言更加適合這兩個(gè)群體?;旌系木幾g性/解釋性環(huán)境將這兩個(gè)領(lǐng)域的優(yōu)勢(shì)結(jié)合在了一起:計(jì)算密集型算法的高性能和樣機(jī)或開(kāi)發(fā)的靈活性。事實(shí)上,這種多語(yǔ)言計(jì)算的方法在許多科學(xué)計(jì)算社區(qū)中得到廣泛應(yīng)用,并且許多團(tuán)隊(duì)將VTK作為他們自己軟件的一個(gè)范本。
就軟件過(guò)程而言,VTK采用CMake來(lái)控制構(gòu)建過(guò)程;CDash/CTest用于測(cè)試;然后CPack用于跨平臺(tái)部署。VTK確實(shí)可以在幾乎任何計(jì)算機(jī)上進(jìn)行編譯,包括因其簡(jiǎn)陋的開(kāi)發(fā)環(huán)境而聲名狼藉的超級(jí)計(jì)算機(jī)。此外,開(kāi)發(fā)工具外圍還包括網(wǎng)頁(yè)、wiki、郵件列表(用戶(hù)區(qū)和開(kāi)發(fā)者區(qū)),文檔生成設(shè)施(即:Doxygen)和bug追蹤系統(tǒng)(Mantis)。
由于VTK是面向?qū)ο笙到y(tǒng),在其內(nèi)部,對(duì)類(lèi)的訪(fǎng)問(wèn)和數(shù)據(jù)成員的實(shí)例化都被小心地管理起來(lái)。通常情況下,所有的數(shù)據(jù)成員的訪(fǎng)問(wèn)權(quán)限均為protected或private。通過(guò)Set
和Get
方法來(lái)訪(fǎng)問(wèn)這些數(shù)據(jù)成員,這兩種方法具有各種類(lèi)型的形參,例如:布爾型數(shù)據(jù)、模態(tài)數(shù)據(jù)、字符串、以及向量。這些方法中的多數(shù)的創(chuàng)建是通過(guò)向類(lèi)的頭文件中插入宏來(lái)實(shí)現(xiàn)的。例如:
vtkSetMacro(Tolerance, double);
vtkGetMacro(Tolerance, double);
可以展開(kāi)為如下形式:
virtual void SetTolerance(double);
virtual double GetTolerance();
使用這些宏的原因已經(jīng)超出了僅僅使代碼清晰。VTK中有重要的數(shù)據(jù)成員控制調(diào)試、更新對(duì)象的修改時(shí)間(MTime)、并恰當(dāng)?shù)毓芾硪糜?jì)數(shù)。這些宏正確地操作這些數(shù)據(jù),因而強(qiáng)烈推薦使用它們。例如,當(dāng)一個(gè)對(duì)象的修改時(shí)間沒(méi)有得到恰當(dāng)?shù)墓芾頃r(shí),VTK中就會(huì)出現(xiàn)一個(gè)尤其嚴(yán)重的bug。在這種情況下,代碼就不會(huì)按其應(yīng)該運(yùn)行的方式運(yùn)行,或者還會(huì)執(zhí)行多次。
VTK的優(yōu)勢(shì)之一就是其相對(duì)簡(jiǎn)單的用于表示和管理數(shù)據(jù)的方法。典型的情況下,各種特殊數(shù)據(jù)(例如:vtkFloatArray
)的數(shù)組用于表示信息的連續(xù)片段。例如:一個(gè)裝載有三個(gè)三維坐標(biāo)點(diǎn)的表可以用具有9個(gè)元素的vtkFloatArray
來(lái)表示。這些數(shù)組有一種元組的記法,故有一個(gè)三維坐標(biāo)點(diǎn)即一個(gè)3元組,而一個(gè)對(duì)稱(chēng)的3×3張量矩陣可以由一個(gè)6元組表示()。專(zhuān)門(mén)采用這種設(shè)計(jì)是因?yàn)樵诳茖W(xué)計(jì)算中,與操作數(shù)組的系統(tǒng)(例如:Fortran)接口是很常見(jiàn)的,并且這樣還能使對(duì)大塊連續(xù)數(shù)據(jù)的內(nèi)存分配與回收變得更加高效。再者,連續(xù)數(shù)據(jù)的通信、串行、以及IO操作通常更有效率。這些(可以加載各種類(lèi)型數(shù)據(jù)的)核心數(shù)據(jù)數(shù)組表示了VTK中的大部分?jǐn)?shù)據(jù),且具有多種方便的方法,以進(jìn)行信息的插入和訪(fǎng)問(wèn),包括用于快速訪(fǎng)問(wèn)的方法、以及在添加更多數(shù)據(jù)時(shí)所需要的自動(dòng)分配內(nèi)存的方法。數(shù)據(jù)數(shù)組是抽象類(lèi)vtkDataArray
的子類(lèi),該抽象類(lèi)的意義在于:通用的虛方法可用于簡(jiǎn)化編碼。但是,為了實(shí)現(xiàn)更高的性能,靜態(tài)的、模版化的函數(shù)被引入,這樣就可以根據(jù)不同的參數(shù)類(lèi)型進(jìn)行切換,并實(shí)現(xiàn)隨后對(duì)連續(xù)數(shù)據(jù)數(shù)組的直接訪(fǎng)問(wèn)。
即使由于性能方面的原因,模板被廣泛地使用,C++模板通常在公有類(lèi)的API中也是不可見(jiàn)的。這點(diǎn)在STL中也是如此:我們采用了PIMPL設(shè)計(jì)模式來(lái)隱藏模版實(shí)現(xiàn)的復(fù)雜細(xì)節(jié)。這種模式為我們提供了很大幫助,尤其是在以前文所述將代碼包裝為解釋性代碼的時(shí)候。避免公有API中模板的復(fù)雜性意思是:在應(yīng)用程序開(kāi)發(fā)者看來(lái),VTK實(shí)現(xiàn)大部分是無(wú)需考慮數(shù)據(jù)類(lèi)型的選擇的。當(dāng)然,在其外殼之下,代碼的執(zhí)行是由數(shù)據(jù)類(lèi)型來(lái)驅(qū)動(dòng)的,而該數(shù)據(jù)類(lèi)型則一般是運(yùn)行時(shí)訪(fǎng)問(wèn)數(shù)據(jù)時(shí)確定的。
一些用戶(hù)很想知道為什么VTK使用引用計(jì)數(shù)來(lái)管理內(nèi)存而不是垃圾回收這一對(duì)用戶(hù)來(lái)說(shuō)更為友好的方式。基本的答案是當(dāng)數(shù)據(jù)被刪除的時(shí)候,VTK需要對(duì)其完全控制,因?yàn)橐幚淼臄?shù)據(jù)量可能十分巨大。例如,一組1000×1000×1000字節(jié)的體數(shù)據(jù)的數(shù)據(jù)量是1G字節(jié)。把這么大的數(shù)據(jù)留在內(nèi)存中等待垃圾回收器來(lái)決定是否應(yīng)該釋放它們,確實(shí)不是一個(gè)好主意。在VTK中,大部分類(lèi)(vtkObject
的子類(lèi))具有內(nèi)建的引用計(jì)數(shù)能力。每個(gè)對(duì)象都包含有一個(gè)引用計(jì)數(shù),它在該對(duì)象實(shí)例化時(shí)被初始化為1。每次使用該對(duì)象都會(huì)進(jìn)行注冊(cè),然后引用計(jì)數(shù)就加1。類(lèi)似地,當(dāng)使用該對(duì)象進(jìn)行了反注冊(cè)(或者等效地認(rèn)為該對(duì)象被刪除),那么引用計(jì)數(shù)就會(huì)減1。最終的對(duì)象引用計(jì)數(shù)減至0,此時(shí)該對(duì)象自毀。下面列舉一個(gè)典型的例子:
vtkCamera *camera = vtkCamera::New(); // reference count is 1
camera->Register(this); // reference count is 2
camera->Unregister(this); // reference count is 1
renderer->SetActiveCamera(camera); // reference count is 2
renderer->Delete(); // ref count is 1 when renderer is deleted
camera->Delete(); // camera self destructs
這里還有另外一個(gè)關(guān)于為什么引用計(jì)數(shù)對(duì)于VTK很重要的原因——它提供了有效復(fù)制數(shù)據(jù)的能力。例如:想象有一個(gè)數(shù)據(jù)對(duì)象D1,它由許多數(shù)據(jù)數(shù)組組成:點(diǎn)、多邊形、顏色、標(biāo)量、以及紋理坐標(biāo)等?,F(xiàn)在假設(shè)處理該數(shù)據(jù)來(lái)生成一個(gè)新的數(shù)據(jù)對(duì)象D2,此對(duì)象與第一個(gè)對(duì)象相同,還外加了向量數(shù)據(jù)(用于定位點(diǎn))。一種浪費(fèi)資源的方式是完全復(fù)制(深拷貝)D1來(lái)創(chuàng)建D2,然后向其中加入新的向量數(shù)據(jù)數(shù)組。另有一種方法,我們創(chuàng)建一個(gè)空的D2,然后將D1中的數(shù)組傳給D2(淺拷貝),使用引用計(jì)數(shù)來(lái)追蹤數(shù)據(jù)所有權(quán),最終向添加新的向量數(shù)組。后者方法避免了復(fù)制數(shù)據(jù),這正如前文所述,對(duì)一個(gè)優(yōu)秀可視化系統(tǒng)是必不可少的。我們?cè)诒菊碌纳院髢?nèi)容中可以看到,數(shù)據(jù)處理的管線(xiàn)例行公事式地實(shí)現(xiàn)了這種運(yùn)行機(jī)制,即:將數(shù)據(jù)從算法的數(shù)據(jù)復(fù)制至輸出,此時(shí)引用計(jì)數(shù)對(duì)于VTK是必不可少的。
當(dāng)然,引用計(jì)數(shù)也有一些臭名昭著的問(wèn)題。偶爾會(huì)存在引用周期,這時(shí)循環(huán)中的對(duì)象以一種相互支持的配置來(lái)引用彼此。這種情況下,就需要明智的介入,或者在VTK中,一種在vtkGarbageCollector
中實(shí)現(xiàn)的特殊設(shè)施就可以用來(lái)管理牽涉與上述循環(huán)中的對(duì)象。當(dāng)這樣的類(lèi)被鑒別到的時(shí)候(這被期望發(fā)生在開(kāi)發(fā)過(guò)程中),該類(lèi)就會(huì)將其自身注冊(cè)至垃圾回收器,并管理其自己的Register
和Unregister
方法的開(kāi)銷(xiāo)。然后緊接著的對(duì)象銷(xiāo)毀(或者反注冊(cè))方法對(duì)局部的引用計(jì)數(shù)網(wǎng)絡(luò)進(jìn)行拓?fù)浞治觯阉饕呀?jīng)分離了的相互引用的對(duì)象群。這些都將被垃圾回收器予以刪除。
VTK中的多數(shù)實(shí)例化過(guò)程是通過(guò)一種以靜態(tài)類(lèi)成員實(shí)現(xiàn)的對(duì)象工廠運(yùn)行。典型的語(yǔ)義表達(dá)如下:
vtkLight *a = vtkLight::New();
這里要認(rèn)識(shí)到的重要之處是:這里實(shí)際被實(shí)例化的可能不是vtkLight
,可能是vtkLight
的子類(lèi)(例如:vtkOpenGLLight
)。采用對(duì)象工廠的動(dòng)機(jī)多種多樣,最為重要的是應(yīng)用的可移植性和設(shè)備不相關(guān)性。例如,前文中我們?cè)谝粋€(gè)渲染場(chǎng)景中創(chuàng)建了一個(gè)光源。在一個(gè)運(yùn)行于特定平臺(tái)上的特定的應(yīng)用程序中,vtkLight::New
可能會(huì)生成一個(gè)OpenGL光源,然而在不同的平臺(tái)上,存在著圖形系統(tǒng)中其他渲染庫(kù)或方法來(lái)創(chuàng)建光源的可能性。到底實(shí)例化什么樣的派生類(lèi)是一種運(yùn)行時(shí)系統(tǒng)信息的功能。在早期的VTK中,可以有包括gl、PHIGS、Starbase、XGL、以及OpenGL等多種選擇。然而這些圖形庫(kù)中的多數(shù)現(xiàn)在已經(jīng)消失了,出現(xiàn)了包括DirectX和基于GPU方法在內(nèi)的新方法。隨著時(shí)間的推移,一個(gè)利用VTK寫(xiě)成的應(yīng)用程序沒(méi)必要進(jìn)行修改,因?yàn)殚_(kāi)發(fā)者已經(jīng)派生出了特定的對(duì)應(yīng)于新設(shè)備的vtkLight
的子類(lèi)和其他渲染類(lèi)來(lái)支持不斷發(fā)展的技術(shù)。另外一個(gè)對(duì)象工廠的重要用處是使性能增強(qiáng)變動(dòng)的運(yùn)行時(shí)替換成為可能。例如,一個(gè)vtkImageFFT
可能取代一個(gè)訪(fǎng)問(wèn)特種用途硬件或數(shù)值計(jì)算庫(kù)的類(lèi)。
VTK的一個(gè)優(yōu)點(diǎn)就是其表示數(shù)據(jù)復(fù)雜形式的能力。這些數(shù)據(jù)形式包括從簡(jiǎn)單表格到有限元網(wǎng)格之類(lèi)的復(fù)雜結(jié)構(gòu)。所有這些數(shù)據(jù)形式都是vtkDataObject
的子類(lèi),如圖24.1所示(注意這是數(shù)據(jù)對(duì)象類(lèi)的繼承圖的一部分)。
圖24.2:數(shù)據(jù)集類(lèi)
VTK由若干主干子系統(tǒng)組成。與可視化包關(guān)聯(lián)最緊密的子系統(tǒng)或許應(yīng)該是數(shù)據(jù)流/管線(xiàn)架構(gòu)了。從概念上講,管線(xiàn)架構(gòu)由三類(lèi)基本對(duì)象組成:表示數(shù)據(jù)的對(duì)象(上文中的vtkDataObject
),將數(shù)據(jù)從一種形式處理、變換、濾波或者映射成另外一種形式的對(duì)象(vtkAlgorithm
),以及執(zhí)行管線(xiàn)的對(duì)象(vtkExecutive
)——此管線(xiàn)控制著一個(gè)由交錯(cuò)數(shù)據(jù)(?)和過(guò)程對(duì)象(即:管線(xiàn))組成的連通圖。圖24.3展示了一個(gè)典型的管線(xiàn)。
盡管這是交互的一種原始形式,它也是許多使用VTK的應(yīng)用程序的基本要素。例如:上述的簡(jiǎn)短代碼可以很容易地轉(zhuǎn)換、用于顯示并管理圖形界面中的進(jìn)度條。這一命令/觀察者子系統(tǒng)也是VTK中三維掛件的核心,這些掛件是用于數(shù)據(jù)的請(qǐng)求、操縱以及編輯的復(fù)雜的交互性對(duì)象,下文將予以描述。
提到上面的例子,很重要的一點(diǎn)是,VTK中的事件都是預(yù)定義的,但是這里也為自定義事件開(kāi)了后門(mén)。vtkCommand
類(lèi)定義了一組枚舉型事件(例如:上面例子中的vtkCommand::ProgressEvent
)以及一個(gè)用戶(hù)事件。UserEvent
只是一個(gè)整形數(shù)值,一般用作一組應(yīng)用程序中自定義事件的起始抵消值。于是,vtkCommand::UserEvent+100
可能是指一個(gè)VTK預(yù)定義的事件之外的某個(gè)事件。
從用戶(hù)的角度來(lái)看,一個(gè)VTK掛件可以看作是場(chǎng)景中的一個(gè)演員,只是用戶(hù)可以通過(guò)操縱句柄或者其它幾何特性(句柄操縱與幾何特性操縱均是基于前文所述之抓取功能——原文:picking functionality,即24.2.4一節(jié)中最后一段所述——的)來(lái)與之交互。與掛件的交互是很直觀的:用戶(hù)抓住球面句柄并將其移動(dòng),或者抓住一條直線(xiàn)并將其移動(dòng)。然而,在場(chǎng)景的背后,事件被發(fā)送出去(例如:InteractionEvent
),而一個(gè)編寫(xiě)合理的應(yīng)用程序就能夠觀察到這些事件,并采取恰當(dāng)?shù)男袆?dòng)。例如,它們通常由下面所給出的vtkCommand::InteractorEvent
所觸發(fā):
vtkLW2Callback *myCallback = vtkLW2Callback::New();
myCallback->PolyData = seeds; // streamlines seed points, updated on interaction
myCallback->Actor = streamline; // streamline actor, made visible on interaction
vtkLineWidget2 *lineWidget = vtkLineWidget::New();
lineWidget->SetInteractor(iren);
lineWidget->SetRepresentation(rep);
lineWidget->AddObserver(vtkCommand::InteractionEvent, myCallback);
實(shí)際上,VTK掛件由兩個(gè)對(duì)象構(gòu)建而成:一個(gè)是vtkInteractorObserver
的子類(lèi),另一個(gè)是vtkProp
的子類(lèi)。vtkInteractorObserver
只是觀察渲染窗中的用戶(hù)交互(例如:鼠標(biāo)事件和鍵盤(pán)事件)并處理之。這些操縱通常由突出顯示句柄,改變鼠標(biāo)指針的外觀,以及變換數(shù)據(jù)等所組成,它們都會(huì)修改vtkProp
的幾何特征。當(dāng)然,這些掛件的特殊細(xì)節(jié)要求編寫(xiě)子類(lèi)來(lái)控制其行為的細(xì)微差別,目前系統(tǒng)中擁有50多個(gè)不同的掛件。
VTK是一個(gè)大型軟件工具箱。目前,系統(tǒng)由大約1500萬(wàn)行代碼(包括注釋?zhuān)遣话ㄗ詣?dòng)生成的包裹層軟件),約1000個(gè)C++類(lèi)組成。為了管理系統(tǒng)的復(fù)雜度并減少構(gòu)建和鏈接的時(shí)間,系統(tǒng)被分割放置在十幾個(gè)子路徑中。表24.1列出了這些子路徑,并簡(jiǎn)要總結(jié)了這些庫(kù)所提供的功能。
| Common
| VTK核心類(lèi) |
| Filtering
| 用于管理管線(xiàn)數(shù)據(jù)流的類(lèi) |
| Rendering
| 渲染,抓取,查看圖像,以及交互 |
| VolumeRendering
| 體繪制技術(shù) |
| Graphics
| 三維幾何處理 |
| GenericFiltering
| 非線(xiàn)性三維幾何處理 |
| Imaging
| 圖像處理管線(xiàn) |
| Hybrid
| 同時(shí)要求使用圖形學(xué)和圖像處理功能的類(lèi) |
| Widgets
| 復(fù)雜的交互 |
| IO
| VTK的輸入和輸出 |
| Infovis
| 信息可視化 |
| Parallel
| 并行處理(控制器和通信器) |
| Wrapping
| 對(duì)Tcl,Python以及Java的包裹的支持 |
| Examples
| 內(nèi)容廣泛、文檔良好的示例 |
表24.1:VTK的子路徑
VTK一直是一個(gè)非常成功的系統(tǒng)。雖然第一行代碼于1993年寫(xiě)出,但是目前,VTK仍然在不斷成長(zhǎng)壯大、其開(kāi)發(fā)速度也在不斷加快2。本節(jié),我們將談?wù)勔恍┙?jīng)驗(yàn)和將來(lái)的挑戰(zhàn)。
VTK發(fā)展歷程中,最令人驚嘆的方面之一就是項(xiàng)目的壽命。開(kāi)發(fā)的速度歸因于若干主要原因:
雖然成長(zhǎng)是令人興奮的,確證軟件系統(tǒng)的建立,預(yù)測(cè)VTK的未來(lái),但妥善的管理卻是極其困難的。因此,近期VTK將更多地專(zhuān)注于管理社區(qū)以及軟件的成長(zhǎng)。為此,已經(jīng)采取了若干措施。
首先,創(chuàng)立了正式的管理架構(gòu)。創(chuàng)建了架構(gòu)審查委員會(huì)(Architectural Review Board),來(lái)指導(dǎo)社區(qū)和技術(shù)的發(fā)展,專(zhuān)注于高層次的、戰(zhàn)略性的議題。VTK社區(qū)也正在組建一個(gè)由意見(jiàn)領(lǐng)袖組成的公認(rèn)的團(tuán)隊(duì),來(lái)指導(dǎo)某些VTK子系統(tǒng)的技術(shù)開(kāi)發(fā)。
其次,制定了關(guān)于更進(jìn)一步使工具箱模塊化的計(jì)劃,尤其是應(yīng)對(duì)由git引入的工作流功能,還認(rèn)識(shí)到使用者和開(kāi)發(fā)者一般都想在工作中使用工具箱中小的子系統(tǒng),并且不想構(gòu)建并鏈接整個(gè)包。此外,為了支持不斷成長(zhǎng)的社區(qū),對(duì)新的功能和子系統(tǒng)的支持是很重要的,即使它們并不一定是工具箱的核心部分。通過(guò)創(chuàng)建松散的、模塊化的一群模塊,在維持核心的穩(wěn)定性的同時(shí),適應(yīng)外圍的大量代碼貢獻(xiàn)是可能的。
除了軟件過(guò)程之外,在開(kāi)發(fā)管線(xiàn)當(dāng)中還有許多技術(shù)創(chuàng)新。
最后,Kitware和更加廣泛的VTK社區(qū)決定加入Open Science。從務(wù)實(shí)的角度講,它一個(gè)這樣的方式,我們將傳播公開(kāi)的數(shù)據(jù)、公開(kāi)的發(fā)表、以及公開(kāi)的源代碼——這是確保我們正在創(chuàng)建可重現(xiàn)的科學(xué)系統(tǒng)所必需的特征。雖然VTK一直以來(lái)都以開(kāi)源和公開(kāi)數(shù)據(jù)的系統(tǒng)的形式傳播,但是文檔過(guò)程卻一直缺乏。在擁有正式書(shū)籍[Kit10,SML06]的同時(shí),還一直有各種非正式的方法來(lái)收集包括新的源碼在內(nèi)的技術(shù)發(fā)表物。我們正在通過(guò)開(kāi)發(fā)像是VTK Journal3的新的發(fā)表機(jī)制來(lái)改善這種狀況,該期刊可以發(fā)表由文檔、源代碼、數(shù)據(jù)、以及有效的測(cè)試圖像組成的文章。它還實(shí)現(xiàn)了自動(dòng)化的代碼審查(利用VTK的高質(zhì)量的軟件測(cè)試過(guò)程)以及人對(duì)遞交文章的審查。
雖然VTK很成功,但是還有許多事情我們沒(méi)有處理好:
vtkImageClass
,它內(nèi)部處理像素?cái)?shù)據(jù)組成的數(shù)組。然而,在某些情況下,我們不得不將之重構(gòu)為小的片段,并繼續(xù)這一過(guò)程。一個(gè)基本的例子就是數(shù)據(jù)處理管線(xiàn)。最初,數(shù)據(jù)管線(xiàn)是通過(guò)數(shù)據(jù)和算法對(duì)象的交互而隱式實(shí)現(xiàn)的。我們最終認(rèn)識(shí)到我們得創(chuàng)建一種顯式的管線(xiàn)執(zhí)行對(duì)象來(lái)協(xié)調(diào)數(shù)據(jù)與算法之間的交互,并且用于實(shí)現(xiàn)不同的數(shù)據(jù)處理策略。像VTK這樣的開(kāi)源系統(tǒng)的好處之一是許多這些錯(cuò)誤能夠并且將會(huì)隨著時(shí)間而得以糾正。我們擁有一個(gè)積極的、有能力的開(kāi)發(fā)社區(qū),他們每天都在改進(jìn)著這個(gè)系統(tǒng),并且我們希望在可預(yù)見(jiàn)的將來(lái),這一狀態(tài)能夠維持下去。
腳注
1.?http://en.wikipedia.org/wiki/Opaque_pointer.
2. See the latest VTK code analysis at?http://www.ohloh.net/p/vtk/analyses/latest.
3.?http://www.midasjournal.org/?journal=35.
更多建議: