图形处理之计算法向量vtkPolyDataNormals

法向量计算

        三维平面的法向量是指垂直于该平面的三维向量。曲面在某点P处的法向量为垂直于该点切平面的向量。对于一个网格模型,每个点和单元cell都可以计算一个法向量,在三维计算机图形学中法向量一个重要的应用是光照和阴影计算。在计算网格模型法向量时,单元cell法向量计算比较简单,可以通过组成每个单元cell的任意两条边的叉乘向量并归一化来表示。而对于点的法向量,则是由所有使用该点的单元法向量的平均值来表示。
        VTK中计算法向量的Filter为vtkPolyDataNormals。该类针对单元为三角形或者多边形类型的vtkPolyData数据进行计算。由于法向量分为点法向量和单元法向量,可以通过函数SetComputeCellNormals和SetComputePointNormals来设置需要计算的法向量类型。默认情况下计算点法向量,关闭单元法向量计算。另外默认开始对锐边缘(sharp Edge)的处理。如果检测到存在锐边缘,则会将其分裂,因此模型的数据可能发生变化。可以通过SetSplitting函数关闭该功能。

示例演示

        我们对比计算法向量前后模型显示 并符号化显示法向量。

/**********************************************************************

Copyright (c) Mr.Bin. All rights reserved.
For more information visit: http://blog.csdn.net/webzhuce

**********************************************************************/
#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkPolyDataReader.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkPolyDataNormals.h>
#include <vtkGlyph3D.h>
#include <vtkArrowSource.h>
#include <vtkMaskPoints.h>
#include <vtkProperty.h>

//test data : ../data/fran_cut.vtk
int main(int argc, char *argv[])
{
	vtkNew<vtkPolyDataReader> reader;
	reader->SetFileName("E:/github/Study-VTK/data/fran_cut.vtk");
	reader->Update();

	vtkNew<vtkPolyDataNormals> normfilter;
	normfilter->SetInputData(reader->GetOutput());
	normfilter->SetComputePointNormals(1);
	normfilter->SetComputeCellNormals(0);
	normfilter->SetAutoOrientNormals(1);
	normfilter->SetSplitting(0);
	normfilter->Update();

	vtkNew<vtkMaskPoints> mask;
	mask->SetInputData(normfilter->GetOutput());
	mask->SetMaximumNumberOfPoints(300);
	mask->RandomModeOn();
	mask->Update();

	vtkNew<vtkArrowSource> arrow;
	arrow->Update();
	vtkNew<vtkGlyph3D> glyph;
	glyph->SetInputData(mask->GetOutput());
	glyph->SetSourceData(arrow->GetOutput()); 
	glyph->SetVectorModeToUseNormal();
	glyph->SetScaleFactor(0.01);
	glyph->Update();

	vtkNew<vtkPolyDataMapper> originmapper;
	originmapper->SetInputData(reader->GetOutput());
	vtkNew<vtkActor> originactor;
	originactor->SetMapper(originmapper);

	vtkNew<vtkPolyDataMapper> normedmapper;
	normedmapper->SetInputData(normfilter->GetOutput());
	vtkNew<vtkActor> normedactor;
	normedactor->SetMapper(normedmapper);

	vtkNew<vtkPolyDataMapper> glyphmapper;
	glyphmapper->SetInputData(glyph->GetOutput());

	vtkNew<vtkActor> glyphactor;
	glyphactor->SetMapper(glyphmapper);
	glyphactor->GetProperty()->SetColor(1., 0.,0.);

	double originalviewport[4] = {0.0, 0.0, 0.33, 1.0};
	double normviewport[4] = {0.33, 0.0, 0.66, 1.0};
	double glphviewport[4] = {0.66, 0.0, 1.0, 1.0};

	vtkNew<vtkRenderer> originalrenderer;
	originalrenderer->SetViewport(originalviewport);
	originalrenderer->AddActor(originactor);
	originalrenderer->ResetCamera();
	originalrenderer->SetBackground(1.0, 1.0, 1.0);

	vtkNew<vtkRenderer> normedrenderer;
	normedrenderer->SetViewport(normviewport);
	normedrenderer->AddActor(normedactor);
	normedrenderer->ResetCamera();
	normedrenderer->SetBackground(1.0, 1.0, 1.0);

	vtkNew<vtkRenderer> glyphRenderer;
	glyphRenderer->SetViewport(glphviewport);
	glyphRenderer->AddActor(glyphactor);
	glyphRenderer->AddActor(normedactor);
	glyphRenderer->ResetCamera();
	glyphRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkNew<vtkRenderWindow> renderwindow;
	renderwindow->AddRenderer(originalrenderer);
	renderwindow->AddRenderer(normedrenderer);
	renderwindow->AddRenderer(glyphRenderer);
	renderwindow->SetSize(640, 320);
	renderwindow->Render();
	renderwindow->SetWindowName("PolyDataNormal");

	vtkNew<vtkRenderWindowInteractor> renderwindowinteractor;
	renderwindowinteractor->SetRenderWindow(renderwindow);
	renderwindowinteractor->Initialize();
	renderwindowinteractor->Start();

	return EXIT_SUCCESS;
}

运行结果

        左图1为原始图,左图2为计算法向量后。如图所示,加入法向量后,模型显示得更加平滑。
在这里插入图片描述

参考资料

  • VTK图形图像开发进阶[M]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值