VTK修炼之道54:图形基本操作进阶_表面重建技术(三角剖分)
生活随笔
收集整理的這篇文章主要介紹了
VTK修炼之道54:图形基本操作进阶_表面重建技术(三角剖分)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.表面重建
通過(guò)三維掃描儀所獲取的實(shí)際物體的空間點(diǎn)云數(shù)據(jù)僅僅表示物體的幾何形狀,而無(wú)法表達(dá)其內(nèi)部的拓?fù)浣Y(jié)構(gòu)。拓?fù)浣Y(jié)構(gòu)對(duì)于實(shí)際圖形處理以及可視化具有更重要的意義。因此,這就需要利用表面重建技術(shù)獎(jiǎng)點(diǎn)云數(shù)據(jù)轉(zhuǎn)換成面模型,通常為三角網(wǎng)格模型。除此之外,基于圖像數(shù)據(jù)的面繪制技術(shù)也是一種應(yīng)用非常廣泛的表面重建技術(shù)。2.VTK中實(shí)現(xiàn)三角剖分技術(shù)
三角剖分技術(shù)是一種應(yīng)用非常廣泛的面重建技術(shù)。三角剖分將一些散亂的點(diǎn)云數(shù)據(jù)剖分為一系列的三角形網(wǎng)格。最常用的三角剖分技術(shù)為Delaunay三角剖分。Delaunay三角剖分具有許多優(yōu)良的性質(zhì),如最大化最小角特性,即在所有可能的三角剖分中,其所生成的的三角形的最小角的角度最大。所以,Delaunay三角剖分無(wú)論從哪個(gè)區(qū)域開(kāi)始構(gòu)建,最終生成的三角網(wǎng)格還是唯一的。 VTK的vtkDelaunay2D類實(shí)現(xiàn)了二維三角剖分。該類的輸入數(shù)據(jù)為一個(gè)vtkPointSet或其子類表示的三維空間點(diǎn)集,其輸出為一個(gè)三角網(wǎng)格vtkPolyData數(shù)據(jù)。雖然輸入的是三維數(shù)據(jù),但是算法僅適用XY平面數(shù)據(jù)進(jìn)行平面三角剖分,而忽略Z方向數(shù)據(jù)。當(dāng)然,也可以為vtkDelaunay2D設(shè)置一個(gè)投影變換從而在新的投影平面上進(jìn)行三角剖分。需要注意的是,再不添加任何限制條件下,該類生成的平面三角網(wǎng)格為一個(gè)凸包。 下例演示如何使用vtkDelaunay2D,將其生成的數(shù)據(jù)用于模型地形數(shù)據(jù): #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); VTK_MODULE_INIT(vtkRenderingFreeType); VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h> #include <vtkPoints.h> #include <vtkPolyData.h> #include <vtkPointData.h> #include <vtkDelaunay2D.h> #include <vtkMath.h> #include <vtkVertexGlyphFilter.h> #include <vtkPolyDataMapper.h> #include <vtkProperty.h> #include <vtkActor.h> #include <vtkRenderWindow.h> #include <vtkRenderer.h> #include <vtkRenderWindowInteractor.h>int main() {unsigned int gridSize = 10;vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();for (unsigned int x = 0; x < gridSize; x++){for (unsigned int y = 0; y < gridSize; y++){points->InsertNextPoint(x, y, vtkMath::Random(0.0, 3.0));}}vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();polydata->SetPoints(points);vtkSmartPointer<vtkDelaunay2D> delaunay =vtkSmartPointer<vtkDelaunay2D>::New();delaunay->SetInputData(polydata);delaunay->Update();vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();glyphFilter->SetInputData(polydata);glyphFilter->Update();vtkSmartPointer<vtkPolyDataMapper> pointsMapper =vtkSmartPointer<vtkPolyDataMapper>::New();pointsMapper->SetInputData(glyphFilter->GetOutput());vtkSmartPointer<vtkActor> pointsActor =vtkSmartPointer<vtkActor>::New();pointsActor->SetMapper(pointsMapper);pointsActor->GetProperty()->SetPointSize(3);pointsActor->GetProperty()->SetColor(1, 0, 0);vtkSmartPointer<vtkPolyDataMapper> triangulatedMapper =vtkSmartPointer<vtkPolyDataMapper>::New();triangulatedMapper->SetInputData(delaunay->GetOutput());vtkSmartPointer<vtkActor> triangulatedActor =vtkSmartPointer<vtkActor>::New();triangulatedActor->SetMapper(triangulatedMapper);vtkSmartPointer<vtkRenderer> renderer =vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(pointsActor);renderer->AddActor(triangulatedActor);renderer->SetBackground(0, 0, 0);vtkSmartPointer<vtkRenderWindow> renderWindow =vtkSmartPointer<vtkRenderWindow>::New();renderWindow->AddRenderer(renderer);renderWindow->SetSize(640, 640);renderWindow->Render();renderWindow->SetWindowName("PolyData Delaunay2D");vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =vtkSmartPointer<vtkRenderWindowInteractor>::New();renderWindowInteractor->SetRenderWindow(renderWindow);renderWindowInteractor->Start();return 0; }該例先定義了一個(gè)vtkPolyData數(shù)據(jù),并為其生成一個(gè)10*10的地面網(wǎng)格點(diǎn)集points以及每個(gè)點(diǎn)生成了一個(gè)隨機(jī)數(shù),表示每個(gè)點(diǎn)的海拔值;然后將該數(shù)據(jù)做為vtkDelaunay2D對(duì)象的輸入實(shí)現(xiàn)三角剖分,即可得到一個(gè)地面的網(wǎng)格數(shù)據(jù)。 輸出結(jié)果如下所示:
3.局部數(shù)據(jù)三角剖分(帶約束的三角平分)
vtkDelaunay2D還支持加入邊界限制。用戶需要設(shè)置另外一個(gè)vtkPolyData數(shù)據(jù),其內(nèi)部的線段、閉合或者非閉合的線段集合將作為邊界條件控制三角剖分的過(guò)程。其中,組成這些邊界的點(diǎn)的索引必須與原始點(diǎn)集數(shù)據(jù)一致。加入邊界條件后,最后的剖分結(jié)果可能不在滿足Delaunay準(zhǔn)則。 下面的例子,是在上例的基礎(chǔ)上,加入一個(gè)多變形邊界來(lái)限制三角剖分: #include <vtkAutoInit.h> VTK_MODULE_INIT(vtkRenderingOpenGL); VTK_MODULE_INIT(vtkRenderingFreeType); VTK_MODULE_INIT(vtkInteractionStyle);#include <vtkSmartPointer.h> #include <vtkPoints.h> #include <vtkMath.h> #include <vtkPointData.h> #include <vtkPolyData.h> #include <vtkVertexGlyphFilter.h> #include <vtkProperty.h> #include <vtkPolygon.h> #include <vtkCellArray.h> #include <vtkDelaunay2D.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h>int main() {vtkSmartPointer<vtkPoints> points =vtkSmartPointer<vtkPoints>::New();unsigned int gridSize = 10;for (unsigned int x = 0; x < gridSize; x++){for (unsigned int y = 0; y < gridSize; y++){points->InsertNextPoint(x, y, vtkMath::Random(0.0, 3.0));}}vtkSmartPointer<vtkPolyData> polydata =vtkSmartPointer<vtkPolyData>::New();polydata->SetPoints(points);//多邊形vtkSmartPointer<vtkPolygon> poly =vtkSmartPointer<vtkPolygon>::New();poly->GetPointIds()->InsertNextId(32);poly->GetPointIds()->InsertNextId(42);poly->GetPointIds()->InsertNextId(43);poly->GetPointIds()->InsertNextId(44);poly->GetPointIds()->InsertNextId(45);poly->GetPointIds()->InsertNextId(35);poly->GetPointIds()->InsertNextId(25);poly->GetPointIds()->InsertNextId(24);poly->GetPointIds()->InsertNextId(23);poly->GetPointIds()->InsertNextId(22);vtkSmartPointer<vtkCellArray> cell =vtkSmartPointer<vtkCellArray>::New();cell->InsertNextCell(poly); //設(shè)計(jì)拓?fù)浣Y(jié)構(gòu)//邊界約束vtkSmartPointer<vtkPolyData> boundary =vtkSmartPointer<vtkPolyData>::New();boundary->SetPoints(points);boundary->SetPolys(cell); //只顯示具有拓?fù)浣Y(jié)構(gòu)部分vtkSmartPointer<vtkDelaunay2D> delaunay =vtkSmartPointer<vtkDelaunay2D>::New();delaunay->SetInputData(polydata);delaunay->SetSourceData(boundary); //約束源delaunay->Update(); ///vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =vtkSmartPointer<vtkVertexGlyphFilter>::New();glyphFilter->SetInputData(polydata);glyphFilter->Update();vtkSmartPointer<vtkPolyDataMapper> pointsMapper =vtkSmartPointer<vtkPolyDataMapper>::New();pointsMapper->SetInputData(glyphFilter->GetOutput());vtkSmartPointer<vtkActor> pointsActor =vtkSmartPointer<vtkActor>::New();pointsActor->SetMapper(pointsMapper);pointsActor->GetProperty()->SetPointSize(8);pointsActor->GetProperty()->SetColor(1, 0, 0);vtkSmartPointer<vtkPolyDataMapper> triangulatedMapper =vtkSmartPointer<vtkPolyDataMapper>::New();triangulatedMapper->SetInputData(delaunay->GetOutput());vtkSmartPointer<vtkActor> triangulatedActor =vtkSmartPointer<vtkActor>::New();triangulatedActor->SetMapper(triangulatedMapper); //vtkSmartPointer<vtkRenderer> renderer =vtkSmartPointer<vtkRenderer>::New();renderer->AddActor(pointsActor);renderer->AddActor(triangulatedActor);renderer->SetBackground(0, 0, 0);vtkSmartPointer<vtkRenderWindow> rw =vtkSmartPointer<vtkRenderWindow>::New();rw->AddRenderer(renderer);rw->SetSize(640, 480);rw->SetWindowName("PolyData By ConstrainedDelaunay2D");vtkSmartPointer<vtkRenderWindowInteractor> rwi =vtkSmartPointer<vtkRenderWindowInteractor>::New();rwi->SetRenderWindow(rw);rwi->Start();return 0; }這里定義一個(gè)vtkPolyData類型的數(shù)據(jù)boundary,其點(diǎn)數(shù)據(jù)與上例中的points一致。其單元數(shù)據(jù)為一個(gè)多邊形。通過(guò)vtkDelaunay2D的SetSourceData()函數(shù)設(shè)置邊界數(shù)據(jù),運(yùn)行結(jié)果如下所示:該邊界多邊形內(nèi)部的數(shù)據(jù)并未進(jìn)行三角剖分。對(duì)于邊界多邊形限制數(shù)據(jù)的內(nèi)部或者外部,與多邊形點(diǎn)的順序有關(guān)。這里采用右手坐標(biāo)系,從Z軸向下看去,如果多邊形的點(diǎn)順序?yàn)槟鏁r(shí)針,則僅對(duì)多邊形內(nèi)部數(shù)據(jù)進(jìn)行剖分;而如果為順時(shí)針?lè)较?#xff0c;則對(duì)多邊形外部數(shù)據(jù)進(jìn)行剖分,此時(shí)該邊界多邊形可以看成一個(gè)孔洞。
4.vtkelaunay3D實(shí)現(xiàn)三維三角剖分
VTK的vtkDelaunay3D類可實(shí)現(xiàn)三維三角剖分。該類的使用方法與vtkDelaunay2D基本一致,不同的是,三維三角剖分得到的結(jié)果并非三角網(wǎng)格,而是四面體網(wǎng)絡(luò)。因此,其輸出數(shù)據(jù)的類型為vtkUnstructuredGrid,在未加入邊界條件下的三維三角剖分通常也為一個(gè)凸包。5.簡(jiǎn)述類vtkVertexGlyphFilter
This filter throws away all of the cells in the input and replaces them with?a vertex on each point. ?The intended use of this filter is roughly?equivalent to the vtkGlyph3D filter, except this filter is specifically fordata that has many vertices, making the rendered result faster and less?cluttered than the glyph filter. This filter may take a graph or point set?as input.
6.參看資料
1.《C++ primer》2.《The VTK User’s Guide – 11thEdition》
3. ?張曉東, 羅火靈. VTK圖形圖像開(kāi)發(fā)進(jìn)階[M]. 機(jī)械工業(yè)出版社, 2015.
總結(jié)
以上是生活随笔為你收集整理的VTK修炼之道54:图形基本操作进阶_表面重建技术(三角剖分)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 三角剖分算法的数学理解
- 下一篇: 每个人对工作都会有自己的想法