Bezier曲线的拼接

Bezier曲线的拼接


在这里插入图片描述
使用四条三次Bezier曲线段逼近圆:
1、新建MFC项目;
2、添加二维点类CP2

#pragma once
//为了避免按照x和y方向进行重复运算,重载运算对象
class CP2
{
public:
	CP2(void);
	~CP2(void);
	CP2(double x,double y);
	friend CP2 operator+(const CP2&p0,const CP2&p1);//运算符重载
	friend CP2 operator-(const CP2&p0,const CP2&p1);
	friend CP2 operator-(double scalar,const CP2&p);
	friend CP2 operator-(const CP2&p,double scalar);
	friend CP2 operator*(const CP2&p,double scalar);
	friend CP2 operator*(double scalar,const CP2&p);
	friend CP2 operator/(const CP2&p0,const CP2&p1);
	friend CP2 operator/(const CP2&p,double scalar);

public:
	double x;
	double y;
};

#include "StdAfx.h"
#include "P2.h"
#include"math.h"

CP2::CP2(void)
{
}


CP2::~CP2(void)
{
}

CP2::CP2(double x,double y)
{
	this->x=x;
	this->y=y;
}

 CP2 operator+(const CP2&p0,const CP2&p1)//运算符重载
 {
	 CP2 result;
	 result.x=p0.x+p1.x;
	 result.y=p0.y+p1.y;
	 return result;
 }
 CP2 operator-(const CP2&p0,const CP2&p1)
 {
	 CP2 result;
	 result.x=p0.x-p1.x;
	 result.y=p0.y-p1.y;
	 return result;
 }
 CP2 operator-(double scalar,const CP2&p)
 {
	 CP2 result;
	 result.x=scalar-p.x;
	 result.y=scalar-p.y;
	 return result;
 }
 CP2 operator-(const CP2&p,double scalar)
 {
	 CP2 result;
	 result.x=p.x-scalar;
	 result.y=p.y-scalar;
	 return result;
 }
 CP2 operator*(const CP2&p,double scalar)
 {
	 return CP2(p.x*scalar,p.y*scalar);
 }
 CP2 operator*(double scalar,const CP2&p)
 {
	 return CP2(p.x*scalar,p.y*scalar);
 }
 CP2 operator/(const CP2&p0, CP2&p1)
 {
	 if(fabs(p1.x)<1e-6)
	 {
		 p1.x=1.0;
	 }
	 if(fabs(p1.y)<1e-6)
	 {
		 p1.y=1.0;
	 }
	 CP2 result;
	 result.x=p0.x/p1.x;
	 result.y=p0.y/p1.y;
	 return result;
 }
 CP2 operator/(const CP2&p,double scalar)
 {
	 if(fabs(scalar)<1e-6)
	 {
		 scalar=1.0;
	 }
	 if(fabs(scalar)<1e-6)
	 {
		 scalar=1.0;
	 }
	 CP2 result;
	 result.x=p.x/scalar;
	 result.y=p.y/scalar;
	 return result;
 }

3、添加Bezier曲线绘制类

#pragma once
#include"P2.h"
#include"math.h"
#define ROUND(h) int((h)+0.5)//定义四舍五入

class DrawBezierCurve
{
public:
	DrawBezierCurve(void);
	DrawBezierCurve(CP2 *P,int ptNum);
	~DrawBezierCurve(void);

	void Draw(CDC*pDC);
	void DrawControlPolygon(CDC*pDC);
private:
	double Cni(const int&n,const int&i);
	int Factorial(int n);
private:
	CP2 P[4];
	int n;
	CPoint ctrP[4];
};
#include "StdAfx.h"
#include "DrawBezierCurve.h"


DrawBezierCurve::DrawBezierCurve(void)
{
}


DrawBezierCurve::~DrawBezierCurve(void)
{
}

DrawBezierCurve::DrawBezierCurve(CP2 *P,int ptNum)
{
	for(int i=0;i<ptNum;i++)
	{
		this->P[i]=P[i];
	}
	n=ptNum-1;
}

void DrawBezierCurve::Draw(CDC*pDC)
{
	CPen NewPen,*pOldPen;
	NewPen.CreatePen(PS_SOLID,1,RGB(0,0,255));
	pOldPen=pDC->SelectObject(&NewPen);
	pDC->MoveTo(ROUND(P[0].x),ROUND(P[0].y));
	double tStep=0.01;
	for(double t=0.0;t<=1.0;t=t+tStep)
	{
		double x=0.0,y=0.0;
			for(int i=0;i<=n;i++)
			{
				x+=P[i].x*Cni(n,i)*pow(t,i)*pow(1-t,n-i);
				y+=P[i].y*Cni(n,i)*pow(t,i)*pow(1-t,n-i);
			}
			pDC->LineTo(ROUND(x),ROUND(y));
	}
	pDC->SelectObject(pOldPen);
	NewPen.DeleteObject();
}

double DrawBezierCurve::Cni(const int&n,const int&i)
{
	return(Factorial(n)/(Factorial(i)*Factorial(n-i)));
}

int DrawBezierCurve::Factorial(int n)
{
	int factorial;
	if(n==0||n==1)
	{
		factorial=1;
	}
	else
		factorial=n*Factorial(n-1);
	return factorial;
}

void DrawBezierCurve::DrawControlPolygon(CDC*pDC)
{
	CBrush NewBrush,*pOldBrush;
	pOldBrush=(CBrush*)pDC->SelectStockObject(BLACK_BRUSH);
	pDC->MoveTo(ROUND(P[0].x),ROUND(P[0].y));
	for(int i=0;i<=n;i++)
	{
		pDC->LineTo(ROUND(P[i].x),ROUND(P[i].y));
		pDC->Ellipse(ROUND(P[i].x)-5,ROUND(P[i].y)-5,ROUND(P[i].x)+5,ROUND(P[i].y)+5);
	}
	pDC->SelectObject(pOldBrush);
}

4、在View类中添加头

#include"P2.h"
#include"DrawBezierCurve.h"

添加成员属性

public:
	void ReadPoint(void);
	CP2 P[12];
	CP2 P1[4];
	CP2 P2[4];
	CP2 P3[4];
	CP2 P4[4];
void CDrawSewBezierView::ReadPoint(void)
{
	double m=0.5523;
	double r=300;
	P[0].x=r,P[0].y=0;
	P[1].x=r,P[1].y=m*r;
	P[2].x=m*r,P[2].y=r;
	P[3].x=0,P[3].y=r;
	P[4].x=-m*r,P[4].y=r;
	P[5].x=-r,P[5].y=m*r;
	P[6].x=-r,P[6].y=0;
	P[7].x=-r,P[7].y=-m*r;
	P[8].x=-m*r,P[8].y=-r;

	P[9].x=0,P[9].y=-r;
	P[10].x=r*m,P[10].y=-r;
	P[11].x=r,P[11].y=-m*r;
}

OnDraw中进行绘制:

// TODO: 在此处为本机数据添加绘制代码
	CRect rect;//定义客户区矩形
	GetClientRect(&rect);//获得客户区矩形的信息
	pDC->SetMapMode(MM_ANISOTROPIC);//自定义二维坐标系
	pDC->SetWindowExt(rect.Width(), rect.Height());//设置窗口范围
	pDC->SetViewportExt(rect.Width(), -rect.Height());//设置视区范围,且x轴水平向右为正,y轴垂直向上为正
	pDC->SetViewportOrg(rect.Width() / 2, rect.Height() / 2);//设置客户区中心为二维坐标系原点
	rect.OffsetRect(-rect.Width() / 2, -rect.Height() / 2);//rect矩形与客户区重合

	ReadPoint();

	P1[0]=P[0],P1[1]=P[1],P1[2]=P[2],P1[3]=P[3];
	P2[0]=P[3],P2[1]=P[4],P2[2]=P[5],P2[3]=P[6];
	P3[0]=P[6],P3[1]=P[7],P3[2]=P[8],P3[3]=P[9];
	P4[0]=P[9],P4[1]=P[10],P4[2]=P[11],P4[3]=P[0];

	DrawBezierCurve Bezier1(P1,4);
	Bezier1.Draw(pDC);
	Bezier1.DrawControlPolygon(pDC);

	DrawBezierCurve Bezier2(P2,4);
	Bezier2.Draw(pDC);
	Bezier2.DrawControlPolygon(pDC);

	DrawBezierCurve Bezier3(P3,4);
	Bezier3.Draw(pDC);
	Bezier3.DrawControlPolygon(pDC);

	DrawBezierCurve Bezier4(P4,4);
	Bezier4.Draw(pDC);
	Bezier4.DrawControlPolygon(pDC);

参考《计算几何算法与实现》–孔令德

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值