VTK笔记-使用vtkHull类获取多边形数据的凸包

1.vtkHull类

  vtkHull是一个过滤器,它将在给定一组n个平面的情况下生成一个n边凸包。(凸面外壳限制输入多边形数据。)外壳是通过向输入vtkPolyData挤压平面生成的,直到平面刚好接触vtkPolyData。然后,生成的平面用于生成由三角形表示的多面体(即外壳)。
  n个平面可通过多种方式定义,包括
    1)手动指定每个平面;
    2)选择输入边界框的六个面平面;
    3)选择输入边界框的八个顶点平面;
    4)选择输入边界框的12个边平面;和/或5)使用递归细分的八面体。
请注意,指定平面时,平面法线应指向凸面区域之外。
此过滤器的输出可与vtkLODActor结合使用,以表示LOD层次结构中的详细级别。此类的另一个用途是手动指定平面,然后从平面生成多面体(不向输入方向挤压平面)。方法GenerateHull()用于执行此操作。

1.1对外接口

1.1.1指定平面

void RemoveAllPlanes(void);  

从当前平面集中删除所有平面。

int AddPlane(double A, double B, double C);
int AddPlane(double plane[3]);

函数功能:将平面添加到当前平面集。
它将被添加到列表的末尾,并返回一个稍后可用于设置此平面法线的索引。值A、B、C来自平面方程Ax+By+Cz+D=0。此向量不必具有单位长度(但必须具有非零长度!)。如果返回值0>i>=-NumberOfPlanes,则该平面与先前插入的平面平行,|-i-1|是先前插入的平面的索引。如果返回值i<-NumberOfPlanes,则平面法线长度为零。

void SetPlane(int i, double A, double B, double C);
void SetPlane(int i, double plane[3]);

设置平面i对应的法线值。
这是一个已使用AddPlane()添加到当前平面集的平面,现在正在修改。值A、B、C来自平面方程Ax+By+Cz+D=0。该向量不必具有单位长度。请注意,D被设置为零,但采用vtkPlanes*参数的方法除外,其中D被设置为此处定义的D值。

int AddPlane(double A, double B, double C, double D);
int AddPlane(double plane[3], double D);
void SetPlane(int i, double A, double B, double C, double D);
void SetPlane(int i, double plane[3], double D);

允许设置D的AddPlane()/SetPlane()的变体(函数重载)。
使用GenerateHull()时使用这些方法。

void SetPlanes(vtkPlanes* planes);

使用vtkPlanes隐式函数一次设置所有平面。
这还设置了D值,因此可以与GenerateHull()一起使用。

vtkGetMacro(NumberOfPlanes, int); 

获取当前平面集的平面个数;

void AddCubeVertexPlanes();  

添加表示立方体顶点的8个平面-连接到顶点的三个面平面的组合
(1,1,1), (1,1,-1), (1,-1,1), (1,-1,1),
(-1,1,1), (-1,1,-1), (-1,-1,1), (-1,-1-1)
从对角顶点的连线作为平面的法线,一根对角线从两个方向产生两个平面,法线方向相反;
在这里插入图片描述

void AddCubeEdgePlanes();  

添加表示立方体边的12个平面-位于两个连接面平面的中间
(1,1,0), (-1,-1,0), (-1,1,0), (1,-1,0),
(0,1,1), (0,-1,-1), (0,1,-1), (0,-1,1),
(1,0,1), (-1,0,-1), (1,0,-1), (-1,0,1)
每个平面上的对角线作为法线,6个平面,会有6个不相同的对角连线(其中有6个对角连线是和其他相同的对角连线),6根直线可以确定12个不同方向的向量,从而构成12个平面;
在这里插入图片描述

void AddCubeFacePlanes();  

添加构成立方体面的六个平面;
(1,0,0), (-1, 0, 0), (0,1,0),
(0,-1,0), (0,0,1), (0,0,-1)
与立方体6个平面平行的6个面,可以从12条边中,找到向量不相同的6个向量作为平面法向量;
在这里插入图片描述

void AddRecursiveSpherePlanes(int level);    

添加表示通过在八面体中递归细分三角形而形成的多边形球体顶点法线的平面。
在这里插入图片描述在这里插入图片描述

每个三角形通过连接边的中点进行细分,从而形成4个较小的三角形。
级别表示进行了多少次细分;
级别0表示用于从原始八面体添加6个平面,即从八面体进行一次细化,每条边上的中点与平面上相邻边上的中点相连接;一个顶点变成了4个顶点,则从之前的6个顶点变为24个顶点;
在这里插入图片描述

级别1将添加18个平面,从十四面体再进行一次细化;依此类推。
在这里插入图片描述

void GenerateHull(vtkPolyData* pd, double* bounds);  
void GenerateHull(
      vtkPolyData* pd,
double xmin, double xmax,
double ymin, double ymax, 
double zmin, double zmax);

一种特殊方法,用于直接从一组n个平面生成多面体。
用户提供的平面不会挤压到输入数据(实际上用户不需要指定输入)。若要使用此方法,必须提供vtkPolyData的实例,定义多面体的点和单元将放置在该实例中。您还必须提供一个边界框,期望生成的多面体位于该边界框中。这可能是一个非常慷慨的配合,它只用于创建最终剪裁的初始多边形。

1.2示例代码

#include <vtkActor.h>
#include <vtkDataSetMapper.h>
#include <vtkHull.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPoints.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkXMLPolyDataReader.h>

int main(int argc, char* argv[]){
  // Parse command line arguments
  if (argc != 2)  {
    std::cout << "Required arguments: Filename e.g. cowHead.vtp" << std::endl;
    return EXIT_FAILURE;
  }

  vtkNew<vtkNamedColors> namedColors;

  vtkNew<vtkXMLPolyDataReader> reader;
  reader->SetFileName(argv[1]);

  vtkNew<vtkHull> hullFilter;
  hullFilter->SetInputConnection(reader->GetOutputPort());
  hullFilter->AddCubeFacePlanes();
  hullFilter->AddRecursiveSpherePlanes(5);

  vtkNew<vtkDataSetMapper> originalMapper;
  originalMapper->SetInputConnection(reader->GetOutputPort());
  originalMapper->ScalarVisibilityOff();

  // Create an actor for the surface
  vtkNew<vtkActor> originalActor;
  originalActor->SetMapper(originalMapper);
  originalActor->GetProperty()->SetDiffuseColor(namedColors->GetColor3d("Banana").GetData());

  vtkNew<vtkDataSetMapper> mapper;
  mapper->SetInputConnection(hullFilter->GetOutputPort());
  mapper->ScalarVisibilityOff();

  // Create an actor for the surface
  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetDiffuseColor(namedColors->GetColor3d("Tomato").GetData());
  actor->GetProperty()->SetEdgeColor(namedColors->GetColor3d("IvoryBlack").GetData());
  actor->GetProperty()->SetOpacity(0.5);
  actor->GetProperty()->EdgeVisibilityOff();

  vtkNew<vtkRenderer> renderer;
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->AddRenderer(renderer);
  renderWindow->SetWindowName("ConvexHull");

  vtkNew<vtkRenderWindowInteractor> interactor;
  interactor->SetRenderWindow(renderWindow);

  renderer->AddActor(originalActor);
  renderer->AddActor(actor);
  renderer->SetBackground(namedColors->GetColor3d("SlateGray").GetData());

  renderWindow->Render();
  interactor->Start();

  return EXIT_SUCCESS;
}

计算结果,如下:

在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

黑山老妖的笔记本

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

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

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

打赏作者

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

抵扣说明:

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

余额充值