实验四 自由曲线绘制算法
1. 实验目的:
掌握曲线的表示形式、曲线的连续性条件、拟合和逼近的基本概念
掌握 Bezier 曲线的性质
编程实现 Bezier 曲线生成算法
2. 实验描述:
绘制三次 Bezier 曲线,可以采用公式法或德卡斯特里奥(De Casteliau)算法绘制
3. 算法设计:
在空间给定 1n 个点 0
P P P
2
,
,
1
,
,
P ,称下列参数曲线为 n 次 Bezier 曲线:
n
( )
P t
n
i
0
PB t
i
,
i n
( ) , 0
t
1
其中 , ( )
i nB t 是 Bernstein 基函数,其表达式为:
( )
B t
,
i n
!
n
!(
i n i
)!
t
i
(1
t
)
n i
,接着我们讨论 3 次 Bezier 曲线,我们也采用将
表达式改写为矩阵形式的方法,我们得到:
( )
P t
3
i
0
P
i
3!
!(3
i
i
)!
i
t
(1
t
)
3
i
(1
3
)
t P
0
3 (1
t
2
)
t P
1
2
3 (1
t
)
t P t P
3
2
3
3
t
2
3
t
3 1, 3
t
t
3
2
6
t
3 , 3
t
t
3
2
3 ,
t
t
3
P
0
P
1
P
2
P
3
4. 源程序:
//1)TestView.h
class CTestView : public CView
{
…….
protected:
bool Flag;//标志
CPoint *pt;//顶点
int CtrlPoint;//控制多边形顶点
……..
}
2) //TestView.cpp
#include "math.h"//数学头文件
#define N_MAX_POINT 10//控制多边形的最大顶点数
#define ROUND(a) int(a+0.5) //四舍五入
。。。。。。
CTestView::CTestView()
{
Flag=false;
}
void CTestView::OnMENUBezierCurve()
{
// TODO: Add your command handler code here
RedrawWindow();
AfxGetMainWnd()->SetWindowText("三次 Bezier 曲线");//显示标题
MessageBox("单击左键绘制控制多边形,单击右键绘制曲线","提示",MB_OK);
pt=new CPoint[N_MAX_POINT];
Flag=true;CtrlPoint=0;
}
void CTestView::DrawBezier()//绘制 Bezier 曲线
{
CClientDC dc(this);
double x,y;
int rate=800,n;
n=CtrlPoint-1;
for(double t=0;t<=1;t+=1.0/rate)
{
x=0;y=0;
for(int i=0;i<=n;i++)
{
x+=pt[i].x*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);
y+=pt[i].y*Cnk(n,i)*pow(t,i)*pow(1-t,n-i);
}
dc.SetPixel(ROUND(x),ROUND(y),RGB(255,0,255));//曲线颜色
}
}
double CTestView::Cnk(const int &n, const int &i)//Bernstein 第一项
{
return double(Factorial(n)/(Factorial(i)*Factorial(n-i)));
}
int CTestView::Factorial(int m)//阶乘函数
{
int f=1;
for(int i=1;i<=m;i++)
f*=i;
return f;
}
void CTestView::DrawCharPolygon()//绘制控制多边形
{
CClientDC dc(this);
CPen MyPen,*pOldPen;
MyPen.CreatePen(PS_SOLID,3,RGB(0,255,0));//控制多边形
pOldPen=dc.SelectObject(&MyPen);
for(int i=0;i
void CTestView::OnRButtonDown(UINT nFlags, CPoint point)//调用绘制函数
{
// TODO: Add your message handler code here and/or call default
Flag=false;
DrawBezier();
CView::OnRButtonDown(nFlags, point);
}
5.运行结果:(屏幕截图)