VTK-Tessellator Subdivision

前言:本博文主要研究Tessellator 的Subdivision实现方式,并对涉及到vtk中的所有相关接口进行研究,以期找出网格Remesh的方法。希望此篇文章也能给其他小伙伴带来帮助!

目录

vtkTessellatorFilter

vtkEdgeSubdivisonCriterion

VTK示例

网格Remesh方法


vtkTessellatorFilter

位置:..\Filter\General

描述:对vtkUnstructuredGrid数据集进行简单的非线性近似为有限元分析单元。

该过滤器遍历输入vtkDataSet中的所有单元格。它对每个单元格进行细分,并使用vtkStreamingTessellator和vtkDataSetEdgeSubdivisionCriterion类来生成使用某种近似度量(编码在特定的vtkDataSetEdgeSubdivisionCriterion::EvaluateLocationAndFields实现中)近似非线性网格的简化。通过向三角测量器注册的回调例程AddATetrahedron、AddATriangle和AddALine,将简化放入过滤器的输出vtkDataSet对象中。

输出网格将具有几何图形和在输入网格的点数据中指定为属性的任何字段。属性的复制标志将被保留,除了法线。

实现过程:

过滤器的主要成员函数是RequestData()。这个函数首先调用SetupOutput(),它为原语回调分配数组和一些临时变量(分别由addattriangle和AddALine调用的OutputTriangle和OutputLine)。每个单元格都被赋予一个初始的镶嵌,这将导致一次或多次调用OutputTetrahedron、OutputTriangle或OutputLine来向OutputMesh添加元素。最后,调用Teardown()来释放过滤器的工作空间。

关联接口

vtkDataSetToUnstructuredGridFilter vtkDataSet vtkStreamingTessellator

vtkDataSetEdgeSubdivisionCriterion

vtkEdgeSubdivisonCriterion

描述:该接口用于判定一个线性近似的非线性几何或范围如何进行细分。该接口的所有子类用于决定分段线性近似(三角形,直线,…)对某些非线性几何应进行细分。这一决定可能基于绝对误差度量(和弦误差)或一些依赖于视图的度量(与设备分辨率相比的和弦误差)或一些抽象度量(颜色误差)。通过实现EvaluateLocationAndFields来完成。

VTK示例

位置:GeometricalObject中应用示例QuadraticTetra&QuadraticTetraDemo。

  

代码:

#include <vtkActor.h>
#include <vtkDataSetMapper.h>
#include <vtkGlyph3D.h>
#include <vtkMinimalStandardRandomSequence.h>
#include <vtkNamedColors.h>
#include <vtkPoints.h>
#include <vtkProperty.h>
#include <vtkQuadraticTetra.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTessellatorFilter.h>
#include <vtkUnstructuredGrid.h>

namespace
{
vtkSmartPointer<vtkUnstructuredGrid> MakeQuadraticTetra();
}

int main (int, char *[])
{
  vtkSmartPointer<vtkNamedColors> namedColors =
    vtkSmartPointer<vtkNamedColors>::New();

  vtkSmartPointer<vtkUnstructuredGrid> uGrid =
    MakeQuadraticTetra();

  vtkSmartPointer<vtkTessellatorFilter> tessellate =
    vtkSmartPointer<vtkTessellatorFilter>::New();
  tessellate->SetInputData(uGrid);

  vtkSmartPointer<vtkDataSetMapper> mapper = 
    vtkSmartPointer<vtkDataSetMapper>::New();
  mapper->SetInputConnection(tessellate->GetOutputPort());
  mapper->ScalarVisibilityOff();
 
  // Create an actor for the grid
  vtkSmartPointer<vtkActor> actor = 
    vtkSmartPointer<vtkActor>::New();
  actor->SetMapper(mapper);
  actor->GetProperty()->SetDiffuseColor(
    namedColors->GetColor3d("Tomato").GetData());
  actor->GetProperty()->SetEdgeColor(
    namedColors->GetColor3d("IvoryBlack").GetData());
  actor->GetProperty()->EdgeVisibilityOn();

  vtkSmartPointer<vtkSphereSource> sphereSource =
    vtkSmartPointer<vtkSphereSource>::New();
  sphereSource->SetRadius(0.02);

  vtkSmartPointer<vtkGlyph3D> glyph3D =
    vtkSmartPointer<vtkGlyph3D>::New();
  glyph3D->SetInputData(uGrid);
  glyph3D->SetSourceConnection(sphereSource->GetOutputPort());
  glyph3D->ScalingOff();
  glyph3D->Update();

  vtkSmartPointer<vtkDataSetMapper> glyph3DMapper =
    vtkSmartPointer<vtkDataSetMapper>::New();
  glyph3DMapper->SetInputConnection(glyph3D->GetOutputPort());
  glyph3DMapper->ScalarVisibilityOff();

  vtkSmartPointer<vtkActor> glyph3DActor =
    vtkSmartPointer<vtkActor>::New();
  glyph3DActor->SetMapper(glyph3DMapper);
  glyph3DActor->GetProperty()->SetColor(
    namedColors->GetColor3d("Banana").GetData());

  // Visualize
  vtkSmartPointer<vtkRenderer> renderer = 
    vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renderWindow = 
    vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->SetWindowName("Quadratic Tetra");
  renderWindow->AddRenderer(renderer);
  vtkSmartPointer<vtkRenderWindowInteractor> interactor = 
    vtkSmartPointer<vtkRenderWindowInteractor>::New();
  interactor->SetRenderWindow(renderWindow);
 
  renderer->AddActor(actor);
  renderer->AddActor(glyph3DActor);
  renderer->SetBackground(namedColors->GetColor3d("SlateGray").GetData());

  renderWindow->Render();
  interactor->Start();
 
  return EXIT_SUCCESS;
}

namespace
{
vtkSmartPointer<vtkUnstructuredGrid> MakeQuadraticTetra()
{
  vtkSmartPointer<vtkQuadraticTetra> aTetra =
    vtkSmartPointer<vtkQuadraticTetra>::New();
  vtkSmartPointer<vtkPoints> points =
    vtkSmartPointer<vtkPoints>::New();

  double *pcoords = aTetra->GetParametricCoords();
  vtkSmartPointer<vtkMinimalStandardRandomSequence> rng =
    vtkSmartPointer<vtkMinimalStandardRandomSequence>::New();
  points->SetNumberOfPoints(aTetra->GetNumberOfPoints());
  rng->SetSeed(5070); // for testing
  for (auto i = 0; i < aTetra->GetNumberOfPoints(); ++i)
  {
    double perturbation[3];
    for (auto j = 0; j < 3; ++j)
    {
      rng->Next();
      perturbation[j] = rng->GetRangeValue(-0.1, 0.1);
    }
    aTetra->GetPointIds()->SetId(i, i);
    points->SetPoint(i,
                     *(pcoords + 3 * i) + perturbation[0],
                     *(pcoords + 3 * i + 1) + perturbation[1],
                     *(pcoords + 3 * i + 2) + perturbation[2]);
  }

  // Add the points and tetra to an unstructured grid
  vtkSmartPointer<vtkUnstructuredGrid> uGrid =
    vtkSmartPointer<vtkUnstructuredGrid>::New();
  uGrid->SetPoints(points);
  uGrid->InsertNextCell(aTetra->GetCellType(), aTetra->GetPointIds());

  return uGrid;
}
}

结论:

1. vtkTessellatorFilter接口只针对近似线性的非线性几何进行划分。 因此才会出现MakeQuadraticTetra函数中对vtkQuadraticTetra的点进行随机偏移处理。若不进行该操作,不会对vtkQuadraticTetra数据进行Subdivision细分。

2. 细分的程度与参数ChordError相关,参数越小,细分次数越多,网格越细。其次细分次数不能超过MaxSubdivisionNumber。

      

        chordError: 0.035                            chordError: 0.01

网格Remesh方法

待更新

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

雪易

给我来点鼓励吧

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

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

打赏作者

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

抵扣说明:

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

余额充值