【功能】
输入点的二维 Delaunay 三角化
该类是一个过滤器,
输入: vtkPointSet 和他的子类
输出: 多边形数据集。
一般来说,输出是一个三角化的面;
但是如果指定一个非0的埃尔法值 alpha 距离值,只有在该alpha半径内的所有的三角形、边、顶点才会被输出。
换句话说,非0 alpha值可能产生一个三角、线、点的任意组合。
此外,该类也可以进行约束delaunay三角网。约束三角剖分是指边、环(多边形)可以被指定。
Delaunay三角化通常应用于为无结构的点集建立拓扑结构。点集是三维的,三角剖分是二维的,所以三角剖分是在x-y面上进行的,Z轴被忽略。
如果想在指定面上进行三角剖分,可以用vtkTransformFilter将点集所在的面变换到 x-y 面上,或者直接给vtkDelaunay2D 指定一个平移矩阵。
变换矩阵可以是 rigid, non-rigid, non-invertible, etc
为了生成一个约束性面,对于输入必须定义一个附加值。
输入是一个包含边、折线或者多边形(包含 edges and loops)信息的 vtkPolyData 实例。
只有第二个输入的拓扑结构(线、多边形)会被使用。拓扑结构默认对应点集为会被三角化的点集。也就是说,线、多边形用到的点ID都是第一个输入的点集。输入中的线、线集信息会映射到输出面中的边。
多边形定义一个环 loop 分为内部区域、外部区域;多边形的内部区域默认为右手定理,也就是说沿着Z轴方向,多边形应该按照逆时针的顺序定义。
多边形中的洞应该定义为顺时针方向。
如果想要创建一个约束三角剖分,最终的面可能不满足Delaunay标准。
注意: 投影到二维面时,线、多边形的边一定不能相交。三角化的过程中可能由于没有足够的点来恢复所有的边,定义的边可能出现过长或者重合的情况。线和多边形是点ID的列表,对应的点是输入的点ID。
如果输入变换矩阵,约束条件就是定义转换的空间。所以当右手定力应用于多边形约束时,三角化应用于转换后的点集。所以变换可以是任何形式的变换。
【示例】
#include<vtkVersion.h>
#include<vtkCellArray.h>
#include<vtkProperty.h>
#include<vtkPolyDataMapper.h>
#include<vtkActor.h>
#include<vtkPoints.h>
#include<vtkPolyData.h>
#include<vtkPolygon.h>
#include<vtkSmartPointer.h>
#include<vtkDelaunay2D.h>
#include<vtkMath.h>
#include<vtkRenderer.h>
#include<vtkRenderWindow.h>
#include<vtkRenderWindowInteractor.h>
intmain(int,char*[])
{
// Generate a 10 x 10 grid of points
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
for(unsignedintx = 0; x < 10; x++)
{
for(unsignedinty = 0; y < 10; y++)
{
points->InsertNextPoint(x + vtkMath::Random(-.25, .25),
y + vtkMath::Random(-.25,.25),
0);
}
}
vtkSmartPointer<vtkPolyData> aPolyData = vtkSmartPointer<vtkPolyData>::New();
aPolyData->SetPoints(points);
// Create a cell array to store the polygon in
vtkSmartPointer<vtkCellArray> aCellArray = vtkSmartPointer<vtkCellArray>::New();
// Define a polygonal hole with a clockwise polygon
vtkSmartPointer<vtkPolygon> aPolygon = vtkSmartPointer<vtkPolygon>::New();
/* 设置不同的ID顺序 */
·······
aCellArray->InsertNextCell(aPolygon);
// Create a polydata to store the boundary. The points must be the
// same as the points we will triangulate.
vtkSmartPointer<vtkPolyData> boundary = vtkSmartPointer<vtkPolyData>::New();
boundary->SetPoints(aPolyData->GetPoints());
boundary->SetPolys(aCellArray);
// Triangulate the grid points
vtkSmartPointer<vtkDelaunay2D> delaunay = vtkSmartPointer<vtkDelaunay2D>::New();
delaunay->SetInputData(aPolyData); // 第一个输入
delaunay->SetSourceData(boundary); // 第二个输入
delaunay->Update();
// Visualize
vtkSmartPointer<vtkPolyDataMapper> meshMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
meshMapper->SetInputConnection(delaunay->GetOutputPort());
vtkSmartPointer<vtkActor> meshActor = vtkSmartPointer<vtkActor>::New();
meshActor->SetMapper(meshMapper);
meshActor->GetProperty()->SetRepresentationToWireframe();
vtkSmartPointer<vtkPolyDataMapper> boundaryMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
boundaryMapper->SetInputData(boundary);
vtkSmartPointer<vtkActor> boundaryActor = vtkSmartPointer<vtkActor>::New();
boundaryActor->SetMapper(boundaryMapper);
boundaryActor->GetProperty()->SetColor(1,0,0);
// Create a renderer, render window, and interactor
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
// Add the actor to the scene
renderer->AddActor(meshActor);
renderer->AddActor(boundaryActor);
renderer->SetBackground(.3, .6, .3);// Background color green
// Render and interact
renderWindow->Render();
renderWindowInteractor->Start();
returnEXIT_SUCCESS;
}
① 洞
aPolygon->GetPointIds()->InsertNextId(22);
aPolygon->GetPointIds()->InsertNextId(23);
aPolygon->GetPointIds()->InsertNextId(24);
aPolygon->GetPointIds()->InsertNextId(25);
aPolygon->GetPointIds()->InsertNextId(35);
aPolygon->GetPointIds()->InsertNextId(45);
aPolygon->GetPointIds()->InsertNextId(44);
aPolygon->GetPointIds()->InsertNextId(43);
aPolygon->GetPointIds()->InsertNextId(42);
aPolygon->GetPointIds()->InsertNextId(32);
②
// 只有边界 逆时针
aPolygon->GetPointIds()->InsertNextId(0);
aPolygon->GetPointIds()->InsertNextId(10);
aPolygon->GetPointIds()->InsertNextId(20);
aPolygon->GetPointIds()->InsertNextId(30);
aPolygon->GetPointIds()->InsertNextId(40);
aPolygon->GetPointIds()->InsertNextId(50);
aPolygon->GetPointIds()->InsertNextId(60);
aPolygon->GetPointIds()->InsertNextId(70);
aPolygon->GetPointIds()->InsertNextId(80);
aPolygon->GetPointIds()->InsertNextId(90);
aPolygon->GetPointIds()->InsertNextId(91);
aPolygon->GetPointIds()->InsertNextId(92);
aPolygon->GetPointIds()->InsertNextId(93);
aPolygon->GetPointIds()->InsertNextId(94);
aPolygon->GetPointIds()->InsertNextId(95);
aPolygon->GetPointIds()->InsertNextId(96);
aPolygon->GetPointIds()->InsertNextId(97);
aPolygon->GetPointIds()->InsertNextId(98);
aPolygon->GetPointIds()->InsertNextId(99);
aPolygon->GetPointIds()->InsertNextId(89);
aPolygon->GetPointIds()->InsertNextId(79);
aPolygon->GetPointIds()->InsertNextId(69);
aPolygon->GetPointIds()->InsertNextId(59);
aPolygon->GetPointIds()->InsertNextId(49);
aPolygon->GetPointIds()->InsertNextId(39);
aPolygon->GetPointIds()->InsertNextId(29);
aPolygon->GetPointIds()->InsertNextId(19);
aPolygon->GetPointIds()->InsertNextId(9);
aPolygon->GetPointIds()->InsertNextId(8);
aPolygon->GetPointIds()->InsertNextId(7);
aPolygon->GetPointIds()->InsertNextId(6);
aPolygon->GetPointIds()->InsertNextId(5);
aPolygon->GetPointIds()->InsertNextId(4);
aPolygon->GetPointIds()->InsertNextId(3);
aPolygon->GetPointIds()->InsertNextId(2);
aPolygon->GetPointIds()->InsertNextId(1);
③
// 只有边界 顺时针
aPolygon->GetPointIds()->InsertNextId(0);
aPolygon->GetPointIds()->InsertNextId(1);
aPolygon->GetPointIds()->InsertNextId(2);
aPolygon->GetPointIds()->InsertNextId(3);
aPolygon->GetPointIds()->InsertNextId(4);
aPolygon->GetPointIds()->InsertNextId(5);
aPolygon->GetPointIds()->InsertNextId(6);
aPolygon->GetPointIds()->InsertNextId(7);
aPolygon->GetPointIds()->InsertNextId(8);
aPolygon->GetPointIds()->InsertNextId(9);
aPolygon->GetPointIds()->InsertNextId(19);
aPolygon->GetPointIds()->InsertNextId(29);
aPolygon->GetPointIds()->InsertNextId(39);
aPolygon->GetPointIds()->InsertNextId(49);
aPolygon->GetPointIds()->InsertNextId(59);
aPolygon->GetPointIds()->InsertNextId(69);
aPolygon->GetPointIds()->InsertNextId(79);
aPolygon->GetPointIds()->InsertNextId(89);
aPolygon->GetPointIds()->InsertNextId(99);
aPolygon->GetPointIds()->InsertNextId(98);
aPolygon->GetPointIds()->InsertNextId(97);
aPolygon->GetPointIds()->InsertNextId(96);
aPolygon->GetPointIds()->InsertNextId(95);
aPolygon->GetPointIds()->InsertNextId(94);
aPolygon->GetPointIds()->InsertNextId(93);
aPolygon->GetPointIds()->InsertNextId(92);
aPolygon->GetPointIds()->InsertNextId(91);
aPolygon->GetPointIds()->InsertNextId(90);
aPolygon->GetPointIds()->InsertNextId(80);
aPolygon->GetPointIds()->InsertNextId(70);
aPolygon->GetPointIds()->InsertNextId(60);
aPolygon->GetPointIds()->InsertNextId(50);
aPolygon->GetPointIds()->InsertNextId(40);
aPolygon->GetPointIds()->InsertNextId(30);
aPolygon->GetPointIds()->InsertNextId(20);
aPolygon->GetPointIds()->InsertNextId(10);