# 绘制贝塞尔Bezier曲线

// TrainingTools.cpp : 定义控制台应用程序的入口点。
//
#include <iostream>
#include <string.h>
#include <cxcore.h>
#include <cv.h>
#include <highgui.h>
#include <fstream>

using namespace std;

const int WW_MAX_MARK_COUNT = 40; //最大40个控制点
int mark_count =4;
int conner_pt_index =-1;
CvPoint3D32f Control_pts[WW_MAX_MARK_COUNT];
IplImage *image = 0 ; //原始图像
bool is_showControlLines = true;

// 两个向量相加，p=p+q
{
p.x += q.x; p.y += q.y; p.z += q.z;
return p;
}

// 向量和标量相乘p=c*p
CvPoint3D32f pointTimes(float c, CvPoint3D32f p)
{
p.x *= c; p.y *= c; p.z *= c;
return p;
}

// 计算贝塞尔方程的值
// 变量u的范围在0-1之间
//P1*t^3 + P2*3*t^2*(1-t) + P3*3*t*(1-t)^2 + P4*(1-t)^3 = Pnew
CvPoint3D32f Bernstein(float u, CvPoint3D32f *p)
{
CvPoint3D32f a, b, c, d, r;

a = pointTimes(pow(u,3), p[0]);
b = pointTimes(3*pow(u,2)*(1-u), p[1]);
c = pointTimes(3*u*pow((1-u),2), p[2]);
d = pointTimes(pow((1-u),3), p[3]);

return r;
}

//画控制线
void DrawControlLine(CvPoint3D32f *p)
{
CvPoint pc[4];
for(int i=0;i<4;i++)
{
pc[i].x = (int)p[i].x;
pc[i].y = (int)p[i].y;
}

cvLine(image,pc[0],pc[1],CV_RGB(0,0,255),1,CV_AA,0);
cvLine(image,pc[2],pc[3],CV_RGB(0,0,255),1,CV_AA,0);
}

//得到最近Control_pts的index
int getNearPointIndex(CvPoint mouse_pt)
{
CvPoint pt;
for(int i =0; i<mark_count;i++)
{
pt.x= mouse_pt.x - (int)Control_pts[i].x;
pt.y= mouse_pt.y - (int)Control_pts[i].y;
float distance = sqrt ((float)( pt.x*pt.x + pt.y*pt.y ));
if(distance<10)

return i;

}
return -1;
}

void on_mouse( int event, int x, int y, int flags, void *param )
{
if( event == CV_EVENT_LBUTTONDOWN )
{
CvPoint pt = cvPoint(x,y);
//cout<<x<<","<<y<<endl;

if(conner_pt_index >-1)
conner_pt_index = -1;
else
{
conner_pt_index = getNearPointIndex(pt);
//添加新的控制点
if(conner_pt_index==-1)
{
if(mark_count<=(WW_MAX_MARK_COUNT-1))
{
Control_pts[mark_count].x = (float)pt.x;
Control_pts[mark_count].y = (float)pt.y;
Control_pts[mark_count].z = 0;
mark_count++;
}
}
}
}
else  if ( event == CV_EVENT_MOUSEMOVE ) //修改控制点坐标
{
if(conner_pt_index >-1)
{
Control_pts[conner_pt_index].x = (float)x;
Control_pts[conner_pt_index].y = (float)y;
}
}

};

int main(int argc, char* argv[])
{

CvSize image_sz = cvSize( 1000,1000);
image = cvCreateImage(image_sz , 8, 3 );
cvNamedWindow("Win",0);
cvSetMouseCallback( "Win", on_mouse, 0 );
cvResizeWindow("Win",500,500);

cout<<"============== Bezier curve DEMO =============="<<endl;
cout<<" "<<endl;
cout<<"1.use mouse to click control point (red) to select a control point"<<endl;
cout<<"2.use mouse to modify control point"<<endl;
cout<<"4.use 'W','S' to add precision or reduce precision."<<endl;
cout<<"5.press 'Z' to show control points."<<endl;
cout<<"===press ESC to exit==="<<endl;

//初始化四个控制点
Control_pts[0].x = 200;
Control_pts[0].y = 200;
Control_pts[0].z = 0;

Control_pts[1].x = 300;
Control_pts[1].y = 500;
Control_pts[1].z = 0;

Control_pts[2].x = 400;
Control_pts[2].y = 560;
Control_pts[2].z = 0;

Control_pts[3].x = 500;
Control_pts[3].y = 100;
Control_pts[3].z = 0;

int divs = 50; //控制精细度

for(;;)
{

CvPoint pt_now,pt_pre;
cvZero(image);

//绘制控制点
if(is_showControlLines)
{
for(int i =0;i<mark_count;i++)
{
CvPoint ptc;
ptc.x = (int) Control_pts[i].x;
ptc.y = (int) Control_pts[i].y;
cvCircle( image, ptc, 4, CV_RGB(255,0,0), 1,CV_AA, 0);
}
}

//绘制Bezier曲线
CvPoint3D32f *pControls = Control_pts;
for(int j=0;j<mark_count-3;j+=3)
{
for (int i=0;i<=divs;i++)
{
float u = (float)i/divs;
CvPoint3D32f newPt = Bernstein(u,pControls);

pt_now.x = (int)newPt.x;
pt_now.y = (int)newPt.y;

if(i>0) cvLine(image,pt_now,pt_pre,CV_RGB(230,255,0),2,CV_AA, 0 );
pt_pre = pt_now;
}

//画控制线
if(is_showControlLines)DrawControlLine(pControls);
pControls+=3;
}

cvShowImage("Win",image);
int keyCode = cvWaitKey(20);
if (keyCode==27) break;
if(keyCode=='w'||keyCode=='W') divs+=2;
if(keyCode=='s'||keyCode=='S') divs-=2;
if(keyCode=='z'||keyCode=='Z') is_showControlLines = is_showControlLines^1;

//cout<<"precision : "<<divs<<endl;
}
return 0;
}


• 本文已收录于以下专栏：

## 有理贝塞尔曲线（Rational Bezier Curves）

• xuehuafeiwu123
• 2017年01月18日 13:48
• 889

## Qt绘制贝塞尔曲线例程

main.cpp #include #include "mywidget.h" int main(int argc, char *argv[]) { QApplication a(argc...
• zgrjkflmkyc
• 2015年05月23日 15:31
• 4114

## 【matlab】绘制贝塞尔曲线 Bézier

clear format long x=(0:.1:20)' %横坐标的范围和步长 %besselj函数求第一类贝塞尔曲线 y_0=besselj(0,x) %0阶 y_1=besselj(1...
• u010141025
• 2015年01月20日 10:06
• 2451

## 插值技术之Bezier插值(1) -- Bezier Curve

• i_dovelemon
• 2015年07月11日 22:15
• 3124

## qt下bezier曲线的绘制（C++）

bezier曲线在编程中的难点在于求取曲线的系数，如果系数确定了那么就可以用微小的直线段画出曲线。bezier曲线的系数也就是bernstein系数，此系数的性质可以自行百度，我们在这里是利用bern...
• u013935238
• 2015年11月24日 14:46
• 1126

## 利用GDI+、贝塞尔曲线绘制一个带曲线的矩形

• liyjupc
• 2014年03月27日 22:03
• 1243

## Qt绘制贝塞尔曲线

• super_rat
• 2013年09月25日 09:13
• 4375

## 利用MATLAB绘制Bezier曲线

• lafengxiaoyu
• 2017年02月20日 20:43
• 3135

## Android 绘制N阶Bezier曲线

• venshine
• 2016年06月25日 16:04
• 5880

## java 画的4个点的Bezier曲线

//其中第2和第3个实心点为控制点，可以鼠标拖动，但是不能太快，不然曲线点的坐标x,y计算跟不上。import java.awt.Color; import java.awt.Dimension; i...
• ytlcainiao
• 2015年04月25日 09:35
• 2154

举报原因： 您举报文章：绘制贝塞尔Bezier曲线 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)