前言:本博文主要记录vtkSelectPolyDataFilter接口的应用,实现原理,以及与其近似的vtkClipPolyData&vtkImplicitSelectionLoop的应用相比较,帮助小伙伴理解vtkSelectPolyDataFilter接口的实现原理,并且与其它接口进行区分。
结果展示
SelectPolyData ImplicitSelectionLoop
vtkSelectPolyDataFilter
描述:vtkSelectPolyData是一个过滤器,它根据定义“循环”并指示循环内的区域来选择多边形数据。循环内的网格由完整的细胞组成(细胞没有被切割)。或者,此过滤器可用于生成标量。这些标量值是到循环的距离测量,可用于剪辑、等高线。或者提取数据(即隐式函数可以做的任何事情)。
循环由x-y-z点坐标数组定义。(坐标应与输入多边形数据在同一坐标空间中。)环可以是凹的,非平面的,但不能自相交。过滤器的输入是一个多边形网格(仅限曲面原语,如三角形条和多边形);输出是a)在选择循环GenerateSelectionScalarsOff内的原始网格铺设的一部分;或b)添加标量值的相同多边形网格(GenerateSelectionScalarsOn)。
算法工作原理如下:对于循环中的每个点坐标,网格中最近的点被找到。结果是一个由距离网格最近的点id组成的循环。然后,在网格中找到连接最近点的边缘(并沿着形成环路的线铺设)。贪心边跟踪过程如下所示。在当前点,选择方向为且端点离直线最近的网格边。沿着边缘走到新的终点,然后重复这个过程。这个过程一直持续到整个循环创建完成。
要确定网格的哪一部分在循环内部和外部,有三种可能的选择。1)最小连通区域,2)最大连通区域,3)最接近用户指定点的连通区域。(设置ivar SelectionMode)
一旦像上面那样计算循环,GenerateSelectionScalars将控制过滤器的输出。如果为on,则基于到环线的距离生成标量值。否则,将输出位于选择循环内的单元格。默认情况下,环路内的网格铺设为输出;然而,如果InsideOut打开了,那么在环路外的网格部分被输出。
过滤器可以配置为通过设置GenerateUnselectedOutput来生成网格的未选择部分作为输出。使用方法GetUnselectedOutput来访问此输出。(注意:这个标志只在enerateSelectionScalars关闭时才相关。)
实例TestSelectPolyData
#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkSelectPolyData.h>
#include <vtkSphereSource.h>
#include <vtkClipPolyData.h>
#include <vtkProperty.h>
#include <vtkPolyDataMapper.h>
#include <vtkLODActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkNamedColors.h>
int main(int, char *[])
{
vtkSmartPointer<vtkNamedColors> colors =
vtkSmartPointer<vtkNamedColors>::New();
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetPhiResolution(50);
sphereSource->SetThetaResolution(100);
sphereSource->Update();
vtkSmartPointer<vtkPoints> selectionPoints =
vtkSmartPointer<vtkPoints>::New();
selectionPoints->InsertPoint( 0, -0.16553, 0.135971, 0.451972 );
selectionPoints->InsertPoint( 1, -0.0880123, -0.134952, 0.4747);
selectionPoints->InsertPoint( 2, 0.00292618, -0.134604, 0.482459 );
selectionPoints->InsertPoint( 3, 0.0641941, 0.067112, 0.490947);
selectionPoints->InsertPoint( 4, 0.15577, 0.0734765, 0.469245);
selectionPoints->InsertPoint( 5, 0.166667, -0.129217, 0.454622 );
selectionPoints->InsertPoint( 6, 0.241259, -0.123363, 0.420581);
selectionPoints->InsertPoint( 7, 0.240334, 0.0727106, 0.432555);
selectionPoints->InsertPoint( 8, 0.308529, 0.0844311, 0.384357 );
selectionPoints->InsertPoint( 9, 0.32672, -0.121674, 0.359187);
selectionPoints-> InsertPoint( 10, 0.380721, -0.117342, 0.302527);
selectionPoints ->InsertPoint( 11, 0.387804, 0.0455074, 0.312375 );
selectionPoints ->InsertPoint( 12, 0.43943, -0.111673, 0.211707);
selectionPoints ->InsertPoint( 13, 0.470984, -0.0801913, 0.147919);
selectionPoints ->InsertPoint( 14, 0.436777, 0.0688872, 0.233021 );
selectionPoints ->InsertPoint( 15, 0.44874, 0.188852, 0.109882);
selectionPoints ->InsertPoint( 16, 0.391352, 0.254285, 0.176943);
selectionPoints ->InsertPoint( 17, 0.373274, 0.154162, 0.294296 );
selectionPoints ->InsertPoint( 18, 0.274659, 0.311654, 0.276609);
selectionPoints ->InsertPoint( 19, 0.206068, 0.31396, 0.329702);
selectionPoints ->InsertPoint( 20, 0.263789, 0.174982, 0.387308 );
selectionPoints ->InsertPoint( 21, 0.213034, 0.175485, 0.417142);
selectionPoints ->InsertPoint( 22, 0.169113, 0.261974, 0.390286);
selectionPoints ->InsertPoint( 23, 0.102552, 0.25997, 0.414814 );
selectionPoints ->InsertPoint( 24, 0.131512, 0.161254, 0.454705);
selectionPoints ->InsertPoint( 25, 0.000192443, 0.156264, 0.475307);
selectionPoints ->InsertPoint( 26, -0.0392091, 0.000251724, 0.499943);
selectionPoints ->InsertPoint( 27, -0.096161, 0.159646, 0.46438 );
vtkSmartPointer<vtkSelectPolyData> loop =
vtkSmartPointer<vtkSelectPolyData>::New();
loop->SetInputConnection(sphereSource->GetOutputPort());
loop->SetLoop(selectionPoints);
loop->GenerateSelectionScalarsOn();
loop->SetSelectionModeToSmallestRegion(); //negative scalars inside
vtkSmartPointer<vtkClipPolyData> clip = //clips out positive region
vtkSmartPointer<vtkClipPolyData>::New();
clip->SetInputConnection(loop->GetOutputPort());
vtkSmartPointer<vtkPolyDataMapper> clipMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
clipMapper->SetInputConnection(clip->GetOutputPort());
clipMapper->ScalarVisibilityOff();
vtkSmartPointer<vtkProperty> backProp =
vtkSmartPointer<vtkProperty>::New();
backProp->SetColor(colors->GetColor3d("tomato").GetData());
vtkSmartPointer<vtkLODActor> clipActor =
vtkSmartPointer<vtkLODActor>::New();
clipActor->SetMapper(clipMapper);
clipActor->SetBackfaceProperty(backProp);
clipActor->GetProperty()->SetColor(colors->GetColor3d("banana").GetData());
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> interactor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
// Add the actors to the renderer, set the background and size
renderer->AddActor (clipActor);
renderer->SetBackground (colors->GetColor3d("slate_grey").GetData());
renderWindow->SetSize (500, 500);
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}
实例2 ImplicitSelectionLoop
原理:采用vtkImplicitSelectionLoop作为vtkImplicitFunction,实现vtkClipPolyData分割,结果如上图ImplicitSelectionLoop所示。
#include <vtkClipPolyData.h>
#include <vtkImplicitSelectionLoop.h>
#include <vtkLODActor.h>
#include <vtkNamedColors.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
int main(int, char*[])
{
auto colors = vtkSmartPointer<vtkNamedColors>::New();
auto sphereSource = vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetPhiResolution(100);
sphereSource->SetThetaResolution(100);
sphereSource->Update();
auto selectionPoints = vtkSmartPointer<vtkPoints>::New();
selectionPoints->InsertPoint(0, -0.16553, 0.135971, 0.451972);
selectionPoints->InsertPoint(1, -0.0880123, -0.134952, 0.4747);
selectionPoints->InsertPoint(2, 0.00292618, -0.134604, 0.482459);
selectionPoints->InsertPoint(3, 0.0641941, 0.067112, 0.490947);
selectionPoints->InsertPoint(4, 0.15577, 0.0734765, 0.469245);
selectionPoints->InsertPoint(5, 0.166667, -0.129217, 0.454622);
selectionPoints->InsertPoint(6, 0.241259, -0.123363, 0.420581);
selectionPoints->InsertPoint(7, 0.240334, 0.0727106, 0.432555);
selectionPoints->InsertPoint(8, 0.308529, 0.0844311, 0.384357);
selectionPoints->InsertPoint(9, 0.32672, -0.121674, 0.359187);
selectionPoints->InsertPoint(10, 0.380721, -0.117342, 0.302527);
selectionPoints->InsertPoint(11, 0.387804, 0.0455074, 0.312375);
selectionPoints->InsertPoint(12, 0.43943, -0.111673, 0.211707);
selectionPoints->InsertPoint(13, 0.470984, -0.0801913, 0.147919);
selectionPoints->InsertPoint(14, 0.436777, 0.0688872, 0.233021);
selectionPoints->InsertPoint(15, 0.44874, 0.188852, 0.109882);
selectionPoints->InsertPoint(16, 0.391352, 0.254285, 0.176943);
selectionPoints->InsertPoint(17, 0.373274, 0.154162, 0.294296);
selectionPoints->InsertPoint(18, 0.274659, 0.311654, 0.276609);
selectionPoints->InsertPoint(19, 0.206068, 0.31396, 0.329702);
selectionPoints->InsertPoint(20, 0.263789, 0.174982, 0.387308);
selectionPoints->InsertPoint(21, 0.213034, 0.175485, 0.417142);
selectionPoints->InsertPoint(22, 0.169113, 0.261974, 0.390286);
selectionPoints->InsertPoint(23, 0.102552, 0.25997, 0.414814);
selectionPoints->InsertPoint(24, 0.131512, 0.161254, 0.454705);
selectionPoints->InsertPoint(25, 0.000192443, 0.156264, 0.475307);
selectionPoints->InsertPoint(26, -0.0392091, 0.000251724, 0.499943);
selectionPoints->InsertPoint(27, -0.096161, 0.159646, 0.46438);
auto loop = vtkSmartPointer<vtkImplicitSelectionLoop>::New();
loop->SetLoop(selectionPoints);
auto clip = // clips out positive region
vtkSmartPointer<vtkClipPolyData>::New();
clip->SetInputConnection(sphereSource->GetOutputPort());
clip->SetClipFunction(loop);
clip->SetValue(0.0);
auto clipMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
clipMapper->SetInputConnection(clip->GetOutputPort());
clipMapper->ScalarVisibilityOff();
auto backProp = vtkSmartPointer<vtkProperty>::New();
backProp->SetColor(colors->GetColor3d("tomato").GetData());
auto clipActor = vtkSmartPointer<vtkLODActor>::New();
clipActor->SetMapper(clipMapper);
clipActor->SetBackfaceProperty(backProp);
clipActor->GetProperty()->SetColor(colors->GetColor3d("banana").GetData());
auto renderer = vtkSmartPointer<vtkRenderer>::New();
auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
interactor->SetRenderWindow(renderWindow);
// Add the actors to the renderer, set the background and size
renderer->AddActor(clipActor);
renderer->SetBackground(colors->GetColor3d("slate_grey").GetData());
renderWindow->SetSize(500, 500);
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}