3.样条曲线之B样条曲线

B样条曲线

        B样条是使用更广泛的逼近样条类。B样条有两个贝塞尔样条所不具备的优点:1、B样条多项式次数可独立于控制点数目(有一定限制);2、B样条允许局部控制曲线或曲面。缺点是B样条比贝塞尔样条更复杂。我们可以把沿B样条曲线的坐标位置的计算表示写成混合函数公式的表达式:
在这里插入图片描述
        B样条的局部控制可以由定义在u取值范围中子区间上的混合函数来实现。B样条曲线的混合函数由Cox-deBoor递归公式定义为
在这里插入图片描述
所选的一组子区间端点Uj称为节点(kont),而选定的一组之区间的端点整体称为节点向量(kont vector)。可以选择满足Uj=<Uj+1的任意值作为子区间端点。Umin和Umax的值取决于所选的控制点个数、参数d的取值、如何建立子区间(节点向量)。除了局部控制,B样条曲线允许通过改变控制点的个数来设计一条曲线,而不需要改变多项式的次数。也可以增加或修改控制点的数目来控制曲线形状。类似地,可以增加节点向量的值从而辅助曲线的设计。 B样条曲线具有以下性质:

  • 在u取值范围内,多项式曲线的次数为d-1,并且具有C^d-2连续性。
  • 对于n+1个控制点,曲线由n+1个混合函数进行描述。
  • 每个混合函数Bk,d定义在u取值范围的d子区间上,以节点向量之Uk为起点。
  • 参数u的取值范围由n+d+1个节点向量中指定的值分成n+d个子区间。
  • 节点值记为{U0,U1,…,Un+d},所生成的B样条曲线仅定义在从节点值Ud-1到节点值Un+1的区间上。
  • 每个样条曲线段(在两个相邻节点值间)受d个控制点影响。
  • 任意一个控制点可以影响最多d条曲线段的形状。
  • 对于从节点值Ud-1到Un+1区间上的任意值u,所有的基本函数之和为1:B0,d(u)+B1,d(u)+…+Bn,d(u) = 1。

给出控制点位置和参数d的值,则需要执行节点值,并使用Cox-deBoor递归关系来获得混合函数。节点向量有三种分类:均匀的、开放均匀的和非均匀的。

示例演示

        按照《计算机图形学(第四版)》的公式,写出了程序在均匀的 节点向量情况下总是不对。所以做点小改动。首先Cox-deBoor递归公式改为如下:
在这里插入图片描述
然后,u等于节点值Un+1时减去一个很小的值。

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

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

**********************************************************************/
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkActor.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkSphereSource.h>
#include <vtkGlyph3DMapper.h>
#include "vtkBSplineSource.h"

int main()
{
	double p0[3] = { -40.0, -40.0, 0.0 };
	double p1[3] = { -20.0, 200.0, 0.0 };
	double p2[3] = { 20.0, 200.0, 0.0 };
	double p3[3] = { 40.0, -40.0, 0.0 };

	vtkNew<vtkPoints> points;
	points->InsertNextPoint(p0);
	points->InsertNextPoint(p1);
	points->InsertNextPoint(p2);
	points->InsertNextPoint(p3);

	// spline points
	vtkNew<vtkSphereSource> spheresource;
	spheresource->SetPhiResolution(20);
	spheresource->SetThetaResolution(20);
	spheresource->SetRadius(10);
	spheresource->Update();
	vtkNew<vtkPolyData> ctrlpointsdata;
	ctrlpointsdata->SetPoints(points);
	vtkNew<vtkGlyph3DMapper> ctrlpointsmapper;
	ctrlpointsmapper->SetInputData(ctrlpointsdata);
	ctrlpointsmapper->SetSourceConnection(spheresource->GetOutputPort());
	ctrlpointsmapper->Update();
	vtkNew<vtkActor> ctrlpointsactor;
	ctrlpointsactor->SetMapper(ctrlpointsmapper);
	ctrlpointsactor->GetProperty()->SetColor(1.0, 0.0, 0.0);

	//spline
	vtkNew<vtkBSplineSource> spline;
	//open uniform
	int d = 4;
	std::vector<float> knots = { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f,1.0f };
	
	open uniform
	//int d = 3;  
	//std::vector<float> knots = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f};
	spline->SetParameters(points, d, knots);
	vtkNew<vtkPolyDataMapper> splinemapper;
	splinemapper->SetInputConnection(spline->GetOutputPort());
	vtkNew<vtkActor> splineactor;
	splineactor->SetMapper(splinemapper);
	splineactor->GetProperty()->SetColor(1.0, 0.0, 0.0);
	
	
	//render
	vtkNew<vtkRenderer> renderer;
	renderer->AddActor(ctrlpointsactor);
	renderer->AddActor(splineactor);
	renderer->SetBackground(1.0, 1.0, 1.0);
	vtkNew<vtkRenderWindow> renderwindow;
	renderwindow->SetSize(400, 200);
	renderwindow->AddRenderer(renderer);
	vtkNew<vtkRenderWindowInteractor> interactor;
	interactor->SetRenderWindow(renderwindow);
	vtkNew<vtkInteractorStyleTrackballCamera> style;
	interactor->SetInteractorStyle(style);
	interactor->Initialize();
	interactor->Start();

	return EXIT_SUCCESS;

}

运行结果

1、均匀的节点向量
在这里插入图片描述
2、开放均匀的节点向量
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/webzhuce/article/details/104167805
今日推荐