MFC有理二次Bezier曲线绘制
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7ec0da5220725b36e3c05cc61093902d.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c7a2380dddae52047c204427385e18e9.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/eac9acd17119fd1a05ff4a85fc3b7290.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/61f35664aa0567b8ce94d3943dc6cc2f.png)
非有理Bezier曲线曲线无法精确表示所有的二次曲线和二次曲面,引入了有理Bezier曲线曲面,来精确表示。如图,通过控制权重,可以获取不同的二次有理Bezier曲线(蓝色线条),虚线为非有理Bezier曲线,作为对照。
理论与算法参考《计算几何算法与实现》–孔令德
代码实现如下:
#pragma once
#include"P2.h"
#include"math.h"
#define ROUND(h) int(h+0.5)
class RationalQuadraticBezier
{
public:
RationalQuadraticBezier(void);
~RationalQuadraticBezier(void);
void ReadPoint(void);//赋值控制点
CP2 point[3];//控制点数组
void DrawCurve(CDC*pDC);//绘制曲线
void DrawControlPoint(CDC*pDC);//绘制控制点
void RationalCurve(CDC*pDC);
};
#include "StdAfx.h"
#include "RationalQuadraticBezier.h"
RationalQuadraticBezier::RationalQuadraticBezier(void)
{
ReadPoint();
}
RationalQuadraticBezier::~RationalQuadraticBezier(void)
{
}
void RationalQuadraticBezier::ReadPoint(void)
{
point[0].x=-200,point[0].y=-100;
point[1].x=0,point[1].y=100;
point[2].x=200,point[2].y=-100;
}
void RationalQuadraticBezier::DrawCurve(CDC*pDC)
{
DrawControlPoint(pDC);//绘制控制点
RationalCurve(pDC);//绘制有理二次Bezier样条
}
void RationalQuadraticBezier::DrawControlPoint(CDC*pDC)
{
CPen NewPen,*pOldPen;//画笔
NewPen.CreatePen(PS_SOLID,3,RGB(0,0,0));
pOldPen=pDC->SelectObject(&NewPen);
CBrush NewBrush,*pOldBrush;
pOldBrush=(CBrush*)pDC->SelectStockObject(BLACK_BRUSH);//画刷
pDC->MoveTo(ROUND(point[0].x),ROUND(point[0].y));
for(int i=0;i<3;i++)
{
pDC->LineTo(ROUND(point[i].x),ROUND(point[i].y));
pDC->Ellipse(ROUND(point[i].x)-5,ROUND(point[i].y)-5,ROUND(point[i].x)+5,ROUND(point[i].y)+5);
}
pDC->SelectObject(pOldBrush);
pDC->SelectObject(pOldPen);
}
void RationalQuadraticBezier::RationalCurve(CDC*pDC)
{
CPen NewPen,*pOldPen;
NewPen.CreatePen(PS_SOLID,1,RGB(0,0,255));
pOldPen=pDC->SelectObject(&NewPen);
double Bern02,Bern12,Bern22;//定义伯恩斯坦基函数
double weight0=1.0,weight2=1.0,weight1=-0.5;//权因子赋值
double tStep=0.01;//绘制步长
pDC->MoveTo(ROUND(point[0].x),ROUND(point[0].y));
for(double t=0;t<=1.0;t=t+tStep)
{
Bern02=(1-t)*(1-t);//伯恩斯坦基函数值
Bern12=2*t*(1-t);
Bern22=t*t;
CP2 tempPoint(0,0);//计算插值点
double denominator=Bern02*weight0+Bern12*weight1+Bern22*weight2;//分母
tempPoint.x=(Bern02*weight0*point[0].x+Bern12*weight1*point[1].x+Bern22*weight2*point[2].x)/denominator;//分子/分母
tempPoint.y=(Bern02*weight0*point[0].y+Bern12*weight1*point[1].y+Bern22*weight2*point[2].y)/denominator;
pDC->LineTo(ROUND(tempPoint.x),ROUND(tempPoint.y));
}
pDC->SelectObject(pOldPen);
}