点击鼠标右键,在鼠标位置将创建新的点。
按住鼠标左键拖动控制点。
空格键屏幕将清空。
一起来玩一玩吧!
运行效果
源代码
////////////////////////
//程序名称:贝塞尔曲线
//
#include
#include
#include
#include
usingstd::vector;
#defineWIDTH800//宽
#defineHEIGHT600//高
structPoint{doublex,y;};
//初始化控制点
vector
Pointoperator+(constPoint&a,constPoint&b)
{
returnPoint({a.x+b.x,a.y+b.y});
}
Pointoperator*(doublef,constPoint&p)
returnPoint({f*p.x,f*p.y});
//计算二项式系数:C(n,k)=n!/(k!(n-k)!)
//这里我们不用公式,使用Pascal'sTriangle
//[1],n=0
//[1,1],n=1
//[1,2,1],n=2
//[1,3,3,1],n=3
//[1,4,6,4,1],n=4
intC(intn,intk)
vector
for(inti=2;i<=n;i++)
for(intj=i-1;j>0;j--)
array[j]+=array[j-1];
returnarray[k];
//绘制贝塞尔曲线,绘制t[0-end_t]范围
voiddrawBezier(constvector
if(points.size()<=1)return;
intn=points.size()-1;//阶次为点数-1
setfillcolor(RED);
for(doublet=0.0;t<=end_t;t+=0.001)
Pointp{0};
for(intk=0;k<=n;k++)
p=p+C(n,k)*pow(t,k)*pow(1-t,(double)n-k)*points[k];
//位置四舍五入
p.x+=0.5;
p.y+=0.5;
solidcircle((int)p.x,(int)p.y,3);
//递归获取每一层的控制点
voidbezierLevelPoints(vector
vector
vector
intn=pre.size();
if(n<=1)return;
for(inti=0;i Pointpoint=(1-t)*pre[i]+t*pre[i+1]; next.push_back(point); levels.push_back(next); bezierLevelPoints(levels,t); //处理输入事件 voidprocessInput() ExMessagemsg; while(peekmessage(&msg,EM_MOUSE|EM_KEY)) //按住左键拖动控制点 if(WM_MOUSEMOVE==msg.message&&msg.lbutton) for(auto&p:controlPoints) intdx=(int)p.x-msg.x; intdy=(int)p.y-msg.y; if(dx*dx+dy*dy<50) p.x=msg.x; p.y=msg.y; //点击右键,创建控制点 elseif(WM_RBUTTONDOWN==msg.message&&msg.rbutton) controlPoints.push_back({(double)msg.x,(double)msg.y}); //按空格键清空 elseif(WM_KEYDOWN==msg.message&&msg.vkcode==VK_SPACE) controlPoints.clear(); //画点、画线 voiddrawControlLines(vector intk=levels.size(); COLORREFcolor[8]={YELLOW,BROWN,CYAN,LIGHTRED,WHITE,GREEN,MAGENTA,RED}; for(inti=0;i vector intn=cur.size(); setlinecolor(color[i&0XF]); setfillcolor(color[i&0XF]); for(auto&point:cur) solidcircle((int)(point.x+0.5),(int)(point.y+0.5),3); if(k<=2)continue; for(intj=0;j line((int)(cur[j].x+0.5),(int)(cur[j].y+0.5),\ (int)(cur[j+1].x+0.5),(int)(cur[j+1].y+0.5)); intmain() TCHARbuf[32]; doublet=0.f; doubletime=-1.57079632679489661923;//pi/2; doublelastTime=0.f; doublecurrentTime=0.f; uint64_tstart,now,frequency; initgraph(WIDTH,HEIGHT); BeginBatchDraw(); QueryPerformanceCounter((LARGE_INTEGER*)&start); QueryPerformanceFrequency((LARGE_INTEGER*)&frequency); while(1) cleardevice(); QueryPerformanceCounter((LARGE_INTEGER*)&now); currentTime=(double)(now-start)/frequency; deltaTime=currentTime-lastTime; lastTime=currentTime; //保证不同帧率下绘制速度一致 time+=1.5*deltaTime; t=0.5*(1+sin(time)); //根据鼠标拖动更新控制点 processInput(); //得到每一层的控制点 vector //绘制控制点、控制线 drawControlLines(levels); //绘制0-t范围内的贝塞尔曲线 drawBezier(controlPoints,t); //提示信息 outtextxy(0,0,L"RightMouseButtontoCreatePoints."); outtextxy(0,16,L"LeftMouseButtontoDragPoints."); outtextxy(0,32,L"PressSPACEtoClear."); swprintf_s(buf,_T("t:%.3f"),t); outtextxy(0,48,buf); swprintf_s(buf,_T("time:%.0fms"),1000*deltaTime); outtextxy(0,64,buf); swprintf_s(buf,_T("fps:%d"),(int)(1.f/deltaTime)); outtextxy(0,80,buf); FlushBatchDraw(); return0; 非常好玩的程序,大家可以自己动动手写出来,代码不多适合练手~