原迹手写之贝赛尔曲线(穿过已知点画平滑曲线(3次贝塞尔曲线)

为了把一串点连成光滑的曲线,先研究贝塞尔曲线,又搞B样条插值。。。。都没有成功(数学没那么强)。

后来在

[翻译] AGG 之贝塞尔插值 http://liyiwen.javaeye.com/blog/705489  。看到一种比较好的方法:

运用贝塞尔曲线的光滑性来穿过这些点。

大致思路就是 先算出相邻原始点的中点,在把相邻中点连成的线段平移到对应的原始点,以平移后的中点作为控制点,相邻原始点为起始点画贝塞尔曲线,这样就保证了连接处的光滑。而贝塞尔曲线本身是光滑的,所以就把这些原始点用光滑曲线连起来了。


我封装了一个函数,留着以后用。

(c++版,其它语言只要把数组和可变数组稍微变一下就能用)

 

[cpp]  view plain   copy
  1. void createCurve(CvPoint *originPoint,int originCount,vector<CvPoint> &curvePoint){  
  2.     //控制点收缩系数 ,经调试0.6较好,CvPoint是<a href="http://lib.csdn.net/base/opencv" class='replace_word' title="OpenCV知识库" target='_blank' style='color:#df3434; font-weight:bold;'>OpenCV</a>的,可自行定义结构体(x,y)  
  3.     float scale = 0.6;  
  4.     CvPoint midpoints[originCount];  
  5.     //生成中点       
  6.     for(int i = 0 ;i < originCount ; i++){      
  7.         int nexti = (i + 1) % originCount;  
  8.         midpoints[i].x = (originPoint[i].x + originPoint[nexti].x)/2.0;  
  9.         midpoints[i].y = (originPoint[i].y + originPoint[nexti].y)/2.0;  
  10.     }      
  11.       
  12.     //平移中点  
  13.     CvPoint extrapoints[2 * originCount];   
  14.     for(int i = 0 ;i < originCount ; i++){  
  15.          int nexti = (i + 1) % originCount;  
  16.          int backi = (i + originCount - 1) % originCount;  
  17.          CvPoint midinmid;  
  18.          midinmid.x = (midpoints[i].x + midpoints[backi].x)/2.0;  
  19.          midinmid.y = (midpoints[i].y + midpoints[backi].y)/2.0;  
  20.          int offsetx = originPoint[i].x - midinmid.x;  
  21.          int offsety = originPoint[i].y - midinmid.y;  
  22.          int extraindex = 2 * i;  
  23.          extrapoints[extraindex].x = midpoints[backi].x + offsetx;  
  24.          extrapoints[extraindex].y = midpoints[backi].y + offsety;  
  25.          //朝 originPoint[i]方向收缩   
  26.          int addx = (extrapoints[extraindex].x - originPoint[i].x) * scale;  
  27.          int addy = (extrapoints[extraindex].y - originPoint[i].y) * scale;  
  28.          extrapoints[extraindex].x = originPoint[i].x + addx;  
  29.          extrapoints[extraindex].y = originPoint[i].y + addy;  
  30.            
  31.          int extranexti = (extraindex + 1)%(2 * originCount);  
  32.          extrapoints[extranexti].x = midpoints[i].x + offsetx;  
  33.          extrapoints[extranexti].y = midpoints[i].y + offsety;  
  34.          //朝 originPoint[i]方向收缩   
  35.          addx = (extrapoints[extranexti].x - originPoint[i].x) * scale;  
  36.          addy = (extrapoints[extranexti].y - originPoint[i].y) * scale;  
  37.          extrapoints[extranexti].x = originPoint[i].x + addx;  
  38.          extrapoints[extranexti].y = originPoint[i].y + addy;  
  39.            
  40.     }      
  41.       
  42.     CvPoint controlPoint[4];  
  43.     
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值