图形处理之抽取轮廓

等值面(线)

        抽取轮廓的操作对象是标量数据。其思想是:将数据集中标量值等于某一指定恒量值的部分提取出来。对于3D的数据集而言,产生的是一个等值面;对于2D的数据集而言,产生的是一个等值线。其典型的应用有气象图中的等温线、地形图中的等高线。对于医学数据而言,不同的标量值代表的是人体的不同部分,因而可以分别提取出人的皮肤或骨头。
  抽取轮廓的功能是由一个过滤器实现的,如vtkContourFilter 。vtkContourFilter 可以接受任意数据集类型作为输入,因而具有 一般性。使用vtkContourFilter 时,除了需要设置输入数据集外,还需要指定一个或多个用于抽取的标量值。可用如下两种方法进行设置。

  1. 使用方法SetValue()逐个设置抽取值。该方法有个两个参数:第一个参数是抽取值的索引号,表示第几个 抽取值。索引号从0开始计数;第二个参数就是指定的抽取值。
  2. 使用方法GenerateValues()自动产生一系列抽取值。该方法有三个参数:第一个参数是抽取值的个数,后面两个参数是抽取值的取值范围。例如:
vtkSmartPointer<vtkContourFilter> contours = vtkSmartPointer<vtkContourFilter>::New();
contours->GenerateValues(5.0, 0.0, 1.2);

最终产生的抽取值为0.0, 0.3, 0.6, 0.9和1.0,这是一个等差数列。

vtkContourFilter生成等值线示例

CMakeLists.txt文件代码如下:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(Contour)
FIND_PACKAGE(VTK REQUIRED)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(Contour	Contour.cpp)
TARGET_LINK_LIBRARIES(Contour ${VTK_LIBRARIES})

Contour.cpp文件代码如下:

#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkCellArray.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkLookupTable.h>
#include <vtkContourFilter.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkSmartPointer.h>

int main()
{
	int i;
	//定义网格的顶点坐标
	vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
	//第1行5个点
	points->InsertNextPoint(-2.0, 2.0, 0.0);
	points->InsertNextPoint(-1.0, 2.0, 0.0);
	points->InsertNextPoint(0.0, 2.0, 0.0);
	points->InsertNextPoint(1.0, 2.0, 0.0);
	points->InsertNextPoint(2.0, 2.0, 0.0);
	//第2行5个点
	points->InsertNextPoint(-2.0, 1.0, 0.0);
	points->InsertNextPoint(-1.0, 1.0, 0.0);
	points->InsertNextPoint(0.0, 1.0, 0.0);
	points->InsertNextPoint(1.0, 1.0, 0.0);
	points->InsertNextPoint(2.0, 1.0, 0.0);
	//第3行5个点
	points->InsertNextPoint(-2.0, 0.0, 0.0);
	points->InsertNextPoint(-1.0, 0.0, 0.0);
	points->InsertNextPoint(0.0, 0.0, 0.0);
	points->InsertNextPoint(1.0, 0.0, 0.0);
	points->InsertNextPoint(2.0, 0.0, 0.0);
	//第4行5个点
	points->InsertNextPoint(-2.0, -1.0, 0.0);
	points->InsertNextPoint(-1.0, -1.0, 0.0);
	points->InsertNextPoint(0.0, -1.0, 0.0);
	points->InsertNextPoint(1.0, -1.0, 0.0);
	points->InsertNextPoint(2.0, -1.0, 0.0);
	//第5行5个点
	points->InsertNextPoint(-2.0, -2.0, 0.0);
	points->InsertNextPoint(-1.0, -2.0, 0.0);
	points->InsertNextPoint(0.0, -2.0, 0.0);
	points->InsertNextPoint(1.0, -2.0, 0.0);
	points->InsertNextPoint(2.0, -2.0, 0.0);

	//定义单元,每个顶点建立一个四边形单元,共计个单元
	static vtkIdType pts[16][4] = { { 0, 5, 6, 1 }, { 1, 6, 7, 2 }, { 2, 7, 8, 3 },
	{ 3, 8, 9, 4 }, { 5, 10, 11, 6 }, { 6, 11, 12, 7 }, { 7, 12, 13, 8 }, { 8, 13, 14, 9 },
	{ 10, 15, 16, 11 }, { 11, 16, 17, 12 }, { 12, 17, 18, 13 }, { 13, 18, 19, 14 },
	{ 15, 20, 21, 16 }, { 16, 21, 22, 17 }, { 17, 22, 23, 18 }, { 18, 23, 24, 19 } };

	//创建对象
	vtkSmartPointer<vtkPolyData> pGrid = vtkSmartPointer<vtkPolyData>::New();
	vtkSmartPointer<vtkCellArray> polys = vtkSmartPointer<vtkCellArray>::New();
	for (i = 0; i < 16; i++)
	{
		polys->InsertNextCell(4, pts[i]);
	}
	vtkSmartPointer<vtkFloatArray> scalars = vtkSmartPointer<vtkFloatArray>::New();
	//第1行
	scalars->InsertTuple1(0, 0);
	scalars->InsertTuple1(1, 1);
	scalars->InsertTuple1(2, 1);
	scalars->InsertTuple1(3, 3);
	scalars->InsertTuple1(4, 2);
	//第2行
	scalars->InsertTuple1(5, 1);
	scalars->InsertTuple1(6, 3);
	scalars->InsertTuple1(7, 6);
	scalars->InsertTuple1(8, 6);
	scalars->InsertTuple1(9, 3);
	//第3行
	scalars->InsertTuple1(10, 3);
	scalars->InsertTuple1(11, 7);
	scalars->InsertTuple1(12, 9);
	scalars->InsertTuple1(13, 7);
	scalars->InsertTuple1(14, 3);
	//第4行
	scalars->InsertTuple1(15, 2);
	scalars->InsertTuple1(16, 7);
	scalars->InsertTuple1(17, 8);
	scalars->InsertTuple1(18, 6);
	scalars->InsertTuple1(19, 2);
	//第5行
	scalars->InsertTuple1(20, 1);
	scalars->InsertTuple1(21, 2);
	scalars->InsertTuple1(22, 3);
	scalars->InsertTuple1(23, 4);
	scalars->InsertTuple1(24, 3);

	pGrid->SetPoints(points);
	pGrid->SetPolys(polys);
	pGrid->GetPointData()->SetScalars(scalars);

	//定义颜色映射表
	vtkSmartPointer<vtkLookupTable> pColorTable = vtkSmartPointer<vtkLookupTable>::New();
	pColorTable->SetHueRange(0.667, 0.887);
	pColorTable->SetNumberOfColors(255);
	pColorTable->Build();

	vtkSmartPointer<vtkPolyDataMapper> cubeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	cubeMapper->SetInputData(pGrid);
	cubeMapper->SetScalarRange(0, 9);
	cubeMapper->SetLookupTable(pColorTable);
	vtkSmartPointer<vtkActor> cubeActor = vtkSmartPointer<vtkActor>::New();
	cubeActor->SetMapper(cubeMapper);

	//提取轮廓线
	vtkSmartPointer<vtkContourFilter> pContourFilter = vtkSmartPointer<vtkContourFilter>::New();
	pContourFilter->SetValue(0, 5.0);
	pContourFilter->SetInputData(pGrid);
	pContourFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> pContourMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	pContourMapper->SetInputData(pContourFilter->GetOutput());

	pContourMapper->ScalarVisibilityOff();
	vtkSmartPointer<vtkActor> pContourActor = vtkSmartPointer<vtkActor>::New();
	pContourActor->SetMapper(pContourMapper);
	pContourActor->GetProperty()->SetColor(1.0, 1.0, 0.0);
	pContourActor->GetProperty()->SetLineWidth(5.0);

	vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(pContourActor);
	renderer->AddActor(cubeActor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
	renWin->SetSize(300, 300);
	renWin->AddRenderer(renderer);
	renWin->SetWindowName("vtkContourFilter");

	vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renWin);

	interactor->Initialize();
	interactor->Start();
}

运行结果

这里写图片描述

示例原理

  1. 定义规则网格数据顶点的属性值,示例中设置标量值。
  2. 确定提取区域的属性值。
  3. 用提取区域的属性值和每个网格数据的每个单元进行比对,确定其是否在该单元内,如果在该单元内,要用插值的方法确定其和该单元边界的交点,然后继续比对下一个单元,如果不在该单元内,继续比对下一个单元。
  4. 将各个单元的交点相连成线,即为边界区域。
    ##原理示意图:
    这里写图片描述
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值