`
westice
  • 浏览: 115537 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

穿过已知点画平滑曲线(3次贝塞尔曲线)

阅读更多

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

后来在

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

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

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


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

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

 

void createCurve(CvPoint *originPoint,int originCount,vector<CvPoint> &curvePoint){
    //控制点收缩系数 ,经调试0.6较好,CvPoint是opencv的,可自行定义结构体(x,y)
    float scale = 0.6;
    CvPoint midpoints[originCount];
    //生成中点     
    for(int i = 0 ;i < originCount ; i++){    
        int nexti = (i + 1) % originCount;
        midpoints[i].x = (originPoint[i].x + originPoint[nexti].x)/2.0;
        midpoints[i].y = (originPoint[i].y + originPoint[nexti].y)/2.0;
    }    
    
    //平移中点
    CvPoint extrapoints[2 * originCount]; 
    for(int i = 0 ;i < originCount ; i++){
         int nexti = (i + 1) % originCount;
         int backi = (i + originCount - 1) % originCount;
         CvPoint midinmid;
         midinmid.x = (midpoints[i].x + midpoints[backi].x)/2.0;
         midinmid.y = (midpoints[i].y + midpoints[backi].y)/2.0;
         int offsetx = originPoint[i].x - midinmid.x;
         int offsety = originPoint[i].y - midinmid.y;
         int extraindex = 2 * i;
         extrapoints[extraindex].x = midpoints[backi].x + offsetx;
         extrapoints[extraindex].y = midpoints[backi].y + offsety;
         //朝 originPoint[i]方向收缩 
         int addx = (extrapoints[extraindex].x - originPoint[i].x) * scale;
         int addy = (extrapoints[extraindex].y - originPoint[i].y) * scale;
         extrapoints[extraindex].x = originPoint[i].x + addx;
         extrapoints[extraindex].y = originPoint[i].y + addy;
         
         int extranexti = (extraindex + 1)%(2 * originCount);
         extrapoints[extranexti].x = midpoints[i].x + offsetx;
         extrapoints[extranexti].y = midpoints[i].y + offsety;
         //朝 originPoint[i]方向收缩 
         addx = (extrapoints[extranexti].x - originPoint[i].x) * scale;
         addy = (extrapoints[extranexti].y - originPoint[i].y) * scale;
         extrapoints[extranexti].x = originPoint[i].x + addx;
         extrapoints[extranexti].y = originPoint[i].y + addy;
         
    }    
    
    CvPoint controlPoint[4];
    //生成4控制点,产生贝塞尔曲线
    for(int i = 0 ;i < originCount ; i++){
           controlPoint[0] = originPoint[i];
           int extraindex = 2 * i;
           controlPoint[1] = extrapoints[extraindex + 1];
           int extranexti = (extraindex + 2) % (2 * originCount);
           controlPoint[2] = extrapoints[extranexti];
           int nexti = (i + 1) % originCount;
           controlPoint[3] = originPoint[nexti];    
           float u = 1;
           while(u >= 0){
               int px = bezier3funcX(u,controlPoint);
               int py = bezier3funcY(u,controlPoint);
               //u的步长决定曲线的疏密
               u -= 0.005;
               CvPoint tempP = cvPoint(px,py);
               //存入曲线点 
               curvePoint.push_back(tempP);
           }    
    }
}

//三次贝塞尔曲线
float bezier3funcX(float uu,CvPoint *controlP){
   float part0 = controlP[0].x * uu * uu * uu;
   float part1 = 3 * controlP[1].x * uu * uu * (1 - uu);
   float part2 = 3 * controlP[2].x * uu * (1 - uu) * (1 - uu);
   float part3 = controlP[3].x * (1 - uu) * (1 - uu) * (1 - uu);   
   return part0 + part1 + part2 + part3; 
}    

float bezier3funcY(float uu,CvPoint *controlP){
   float part0 = controlP[0].y * uu * uu * uu;
   float part1 = 3 * controlP[1].y * uu * uu * (1 - uu);
   float part2 = 3 * controlP[2].y * uu * (1 - uu) * (1 - uu);
   float part3 = controlP[3].y * (1 - uu) * (1 - uu) * (1 - uu);   
   return part0 + part1 + part2 + part3; 
} 
 

 

我用opencv画的效果图:


 

 

 

  • 大小: 30.2 KB
  • 大小: 20 KB
分享到:
评论
3 楼 my251394667 2015-10-25  
请问用你这个函数如何绘制图啊
2 楼 fg5823820 2011-07-27  
C++ 能这样创建数组么
1 楼 skyfen 2010-09-08  
很棒!佩服 !

相关推荐

    bezier曲线平滑C语言代码-贝塞尔曲线C语言实现-bezier曲线平滑-曲线拟合-贝塞尔曲线

    这是一份C语言版本的bezier曲线(贝塞尔曲线)绘制代码,实现了二次和三次bezier曲线的绘制,可用于一系列给定的离散点的曲线平滑。此代码封装成函数,可以直接调用。脚本里边有参数和代码的注释,可供使用者学习和...

    EXCELVBA贝塞尔曲线及插值_贝塞尔平滑_EXCELVBA贝塞尔曲线及插值_excelvba插值_

    在Excel VBA编程中,贝塞尔曲线是一种常用于数据可视化和图形设计的技术,它通过一组控制点来定义平滑曲线。这种曲线在工程、艺术、游戏开发等领域都有广泛应用。本主题将深入探讨如何在Excel VBA中实现贝塞尔曲线...

    VC++三次样条插值&贝塞尔曲线&GDI+平滑曲线程序

    《VC++实现三次样条插值与贝塞尔曲线及GDI+平滑曲线解析》 在计算机图形学领域,绘制平滑曲线是一项重要的任务,它能够有效地表达数据趋势,为可视化提供良好的支持。本程序是基于VC++环境,利用MFC(Microsoft ...

    c# 二次贝塞尔曲线算法

    3. **计算每个点的位置**:对于每一步,使用上面提到的二次贝塞尔曲线的数学公式计算出该步对应点的位置。 4. **绘制曲线**:最后,连接这些计算得到的点,形成最终的二次贝塞尔曲线。 #### 四、代码分析 基于上述...

    2次贝塞尔曲线算法

    二次贝塞尔曲线是计算机图形学中常用的一种平滑曲线生成方法,它由三个点定义:起始点P0、结束点P2以及一个控制点P1。通过这三个点,我们可以计算出一系列点,这些点连接起来形成的曲线即为二次贝塞尔曲线。该曲线...

    bezier曲线绘制Python代码-bezier曲线算法-贝塞尔曲线平滑-曲线拟合代码-曲线平滑算法-三次贝塞尔曲线

    这是一份python 版本的bezier曲线(贝塞尔曲线)绘制代码,实现了二次和三次bezier曲线的绘制,可用于一系列给定的离散点的曲线平滑。此代码封装成函数,可以直接调用。脚本里边有参数和代码的注释,可供使用者学习...

    贝塞尔曲线函数 曲线平滑算法

    贝塞尔曲线(Bézier curve)是计算机图形学中常用的一种参数曲线,它以其发明者...通过学习和理解这些源代码,开发者可以更好地掌握贝塞尔曲线的计算方法,并将其应用到自己的项目中,实现自定义的平滑曲线效果。

    本附件完美地复制了 Excel 画平滑曲线的算法,贝塞尔曲线

    本附件是一个Excel文档 ...里面的公开的VBA代码可以计算贝塞尔曲线的任意插值,即EXCEL画平滑曲线散点图的方法 附件并详细描述了这一算法,用户可以自行在其他语言实现。 本附件原创作者为 EXCELHOME.NET 的 海底眼

    基于三次贝塞尔曲线的类汽车曲率连续路径平滑

    考虑曲率连续性和最大曲率约束,一种新颖的路径平滑算法是根据三次贝塞尔曲线提出的。 在算法中,贝塞尔转弯和贝塞尔路径分别为发达。 Bezier 转弯首先设计用于连接两个任意配置。 然后可以通过以下方式获得贝塞尔...

    VC++三次样条插值和贝塞尔曲线实例程序.zip_VC++ 三次样条_vc 贝塞尔曲线_三次样条曲线_曲线插值_贝塞尔曲线

    总结来说,三次样条插值和贝塞尔曲线是计算机图形学中基础但重要的概念,它们分别提供了数据点的平滑连接和灵活的曲线设计。在VC++环境中,通过编写和调试相关的程序,我们可以更好地理解和掌握这些理论,并将其应用...

    基于贝塞尔曲线的路径规划(Python实现)

    基于贝塞尔曲线的路径规划是一种常用的算法,它可以用来生成平滑的路径,适用于各种应用场景,如机器人导航、动画设计、游戏开发等。 核心原理是通过贝塞尔曲线的插值计算,将给定的起点和终点之间的路径进行平滑化...

    java 二次贝塞尔曲线算法

    java 二次贝塞尔曲线算法,根据起点、终点和控制点输出点集合

    贝赛尔曲线 基于mfc实现的,通过添加点画出贝塞尔曲线

    贝塞尔曲线是一种在计算机图形学中广泛使用的数学工具,它能帮助我们生成平滑、连续的曲线路径。基于MFC(Microsoft Foundation Classes)实现的贝塞尔曲线,是将这一数学概念应用于实际编程的一个实例,主要服务于...

    Android过若干点绘制平滑曲线.zip

    总之,通过理解贝塞尔曲线的原理和Android中的`Path`、`Paint`和`Canvas`类,开发者可以轻松地实现过若干点绘制平滑曲线的功能,为应用增添丰富的视觉效果。实践中,关键在于合理选择控制点以获得期望的曲线形状,并...

    besaier.rar_QT 平滑_c++ curve_qt besaier_曲线平滑_贝塞尔

    在实际应用中,开发人员通常会使用QT的QPainter类配合QPen、QBrush等对象,通过设置贝塞尔曲线的控制点来绘制平滑曲线。例如,使用`QPainterPath::addBezierTo()`函数添加一个贝塞尔曲线段到路径中。此外,还可以...

    c#/WPF二次贝塞尔曲线

    其中,二次贝塞尔曲线是WPF图形绘制中的一个重要元素,它允许开发者创建平滑、曲线的图形路径。这篇关于“C#/WPF二次贝塞尔曲线”的主题将深入探讨二次贝塞尔曲线的概念、参数方程以及如何在C# WPF应用中实现它的...

    圆弧与贝塞尔曲线互相转换

    三次贝塞尔曲线是贝塞尔曲线中的一种,其特点是具有四个控制点,包括起点、终点以及两个控制点。三次贝塞尔曲线能够提供足够的灵活性来近似较为复杂的曲线形状。 总结来说,圆弧与贝塞尔曲线的互相转换是一个复杂但...

    用Opengl实现三次贝塞尔曲线

    此外,对于学习者来说,了解贝塞尔曲线的性质,如线性不等价性(改变控制点的位置不会改变曲线的形状)、平滑性(曲线在控制点处的切线可通过相邻控制点确定)和可分解性(任何三次贝塞尔曲线都可以拆分成两个二次...

    贝塞尔曲线计算器

    贝塞尔曲线是一种在计算机图形学中广泛使用的数学工具,它能生成平滑、连续的曲线,常用于2D和3D图形设计、动画制作以及游戏开发。这个名为“贝塞尔曲线计算器”的程序提供了直观的方式来计算和可视化这些曲线。 ...

    visualization7_三次贝塞尔曲线的绘制_

    三次贝塞尔曲线是一种在计算机图形学中广泛应用的数学模型,常用于曲线的平滑插值和形状设计。本文将深入探讨三次贝塞尔曲线的基本概念、数学公式、OpenGL实现及其在可视化中的应用。 三次贝塞尔曲线是由四个控制点...

Global site tag (gtag.js) - Google Analytics