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、開放均勻的節點向量
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章