• 样条之贝塞尔(Bezier)


          我曾经发过两篇关于贝塞尔的文章:数学图形(1.47)贝塞尔(Bézier)曲线数学图形之贝塞尔(Bézier)曲面。那是使用我自己定义的脚本语言生成贝塞尔图形。由于我自己定义的脚本语法功能有限,所以最多只能支持5次贝塞尔函数,而这里将实现N次。

          N阶贝塞尔曲线可如下推断:

          给定点P0P1、…、Pn,其贝塞尔曲线即

          mathbf{B}(t)=sum_{i=0}^n {nchoose i}mathbf{P}_i(1-t)^{n-i}t^i ={nchoose 0}mathbf{P}_0(1-t)^nt^{0}+{nchoose 1}mathbf{P}_1(1-t)^{n-1}t^{1}+cdots+{nchoose n-1}mathbf{P}_{n-1}(1-t)^{1}t^{n-1}+{nchoose n}mathbf{P}_n(1-t)^{0}t^n mbox{ , } t in [0,1]

    看其公式需要先为之生成一套杨辉三角形数组。

    关于插值与样条的介绍请看:http://www.cnblogs.com/WhyEngine/p/4020294.html

    .h文件

     1 /****************************************************************
     2 
     3   File name   :  YcBezierSpline.h
     4   Author      :  叶峰
     5   Version     :  2.0
     6   Create Date :  2014/08/18  
     7   Description :  Bezier样条
     8 
     9 *****************************************************************/
    10 
    11 #ifndef __YcBezierSpline_H__
    12 #define __YcBezierSpline_H__
    13 
    14 // INCLUDES -----------------------------------------------------------------------------
    15 
    16 #include "YicSpline.h"
    17 
    18 // --------------------------------------------------------------------------------------
    19 
    20 #define YD_MAX_BEZIER_CONTROL_VALUE 33
    21 
    22 // --------------------------------------------------------------------------------------
    23 
    24 class YcBezierSpline : public YicSpline
    25 {
    26 public:
    27     YcBezierSpline();
    28 
    29     ~YcBezierSpline();
    30 
    31     // 设置输出样条值的数目
    32     void    SetSplineValuesCount(Yuint count);
    33 
    34     // 获得输出样条值的数目
    35     Yuint   GetSplineValuesCount() const;
    36 
    37     // 计算样条数值
    38     bool    BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount, 
    39         void* splineValuesPtr, Yuint splineStride) const;
    40 
    41 protected:
    42     void    ClearPowT();
    43 
    44     void    BuildPowT();
    45 
    46     Yreal    GetValueT(Yint t, Yint p) const
    47     {
    48         return m_pow_t[YD_MAX_BEZIER_CONTROL_VALUE*t + p];
    49     }
    50 
    51 protected:
    52     Yuint   m_valuesCount;
    53     Yreal*  m_pow_t;
    54 
    55 protected:
    56     static void    BuildYanghuiTriangle();
    57     static Yint m_yanghuiRowIndex[YD_MAX_BEZIER_CONTROL_VALUE];
    58     static Yint m_yanghuiTriangle[(YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2];
    59 };
    60 
    61 // --------------------------------------------------------------------------------------
    62 
    63 #endif

    CPP文件

      1 /****************************************************************
      2 
      3   File name   :  YcBezierSpline.cpp
      4   Author      :  叶峰
      5   Version     :  2.0
      6   Create Date :  2014/08/18  
      7   Description :  
      8 
      9 *****************************************************************/
     10 
     11 // INCLUDES -----------------------------------------------------------------------------
     12 
     13 #include "....YCommon_hYSplineYcBezierSpline.h"
     14 #include <assert.h>
     15 
     16 // --------------------------------------------------------------------------------------
     17 
     18 Yint    YcBezierSpline::m_yanghuiRowIndex[YD_MAX_BEZIER_CONTROL_VALUE] = {0};
     19 Yint    YcBezierSpline::m_yanghuiTriangle[(YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2] = {0};
     20 
     21 void    YcBezierSpline::BuildYanghuiTriangle()
     22 {
     23     // 第0行
     24     m_yanghuiRowIndex[0] = 0;
     25     m_yanghuiTriangle[0] = 1;
     26 
     27     Yint index = 1;
     28     Yint t0,t1;
     29     Yint* lastRow;
     30     for (Yint i = 1; i < YD_MAX_BEZIER_CONTROL_VALUE; i++)
     31     {
     32         m_yanghuiRowIndex[i] = index;
     33         m_yanghuiTriangle[index] = 1;
     34         index++;
     35 
     36         for (Yint j = 1; j <= i; j++)
     37         {
     38             lastRow = m_yanghuiTriangle + m_yanghuiRowIndex[i-1];
     39             t0 = lastRow[j - 1];
     40             t1 = (j < i) ? lastRow[j] : 0;
     41 
     42             m_yanghuiTriangle[index] = t0 + t1;
     43             index++;
     44         }
     45     }
     46 
     47     assert(index == (YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2);
     48 }
     49 
     50 // --------------------------------------------------------------------------------------
     51 
     52 YcBezierSpline::YcBezierSpline()
     53 {
     54     if (m_yanghuiTriangle[0] == 0)
     55     {
     56         BuildYanghuiTriangle();
     57     }
     58 
     59     m_valuesCount = 0;
     60     m_pow_t = NULL;
     61 
     62     SetSplineValuesCount(100);
     63 }
     64 
     65 YcBezierSpline::~YcBezierSpline()
     66 {
     67     ClearPowT();
     68 }
     69 
     70 // 设置输出样条值的数目
     71 void   YcBezierSpline::SetSplineValuesCount(Yuint count)
     72 {
     73     if (count < 2)
     74     {
     75         count = 2;
     76     }
     77 
     78     if (count == m_valuesCount)
     79     {
     80         return;
     81     }
     82     m_valuesCount = count;
     83     BuildPowT();
     84 }
     85 
     86 // 获得输出样条值的数目
     87 Yuint   YcBezierSpline::GetSplineValuesCount() const
     88 {
     89     return m_valuesCount;
     90 }
     91 
     92 void    YcBezierSpline::ClearPowT()
     93 {
     94     if (m_pow_t)
     95     {
     96         free(m_pow_t);
     97         m_pow_t = NULL;
     98     }
     99 }
    100 
    101 void    YcBezierSpline::BuildPowT()
    102 {
    103     ClearPowT();
    104 
    105     m_pow_t = (Yreal*)malloc(m_valuesCount*YD_MAX_BEZIER_CONTROL_VALUE*sizeof(Yreal));
    106     Yreal t;
    107     for (Yuint i = 0; i < m_valuesCount; i++)
    108     {
    109         t = i/(m_valuesCount - 1.0f);
    110 
    111         m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE] = 1.0f;
    112         for (Yint j = 1; j < YD_MAX_BEZIER_CONTROL_VALUE; j++)
    113         {
    114             m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE + j] = m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE + j - 1]*t;
    115         }
    116     }
    117 }
    118 
    119 // 计算样条数值
    120 bool    YcBezierSpline::BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount, 
    121     void* splineValuesPtr, Yuint splineStride) const
    122 {
    123     if (ctrlCount < 2 || ctrlCount > YD_MAX_BEZIER_CONTROL_VALUE)
    124     {
    125         return false;
    126     }
    127 
    128     Yreal* destValue;
    129     Yreal* srcValue;
    130     Yreal v;
    131     const Yint* yanghuiRow = m_yanghuiTriangle + m_yanghuiRowIndex[ctrlCount - 1];
    132 
    133     for (Yuint i = 0; i < m_valuesCount; i++)
    134     {
    135         v = 0.0f;
    136         for (Yuint j = 0; j < ctrlCount; j++)
    137         {
    138             srcValue = (Yreal*)((char*)ctrlValuesPtr + ctrlStride*j);
    139             v += yanghuiRow[j] * (*srcValue) * GetValueT(i, j) * GetValueT(m_valuesCount - 1 - i, ctrlCount - 1 - j);
    140         }
    141 
    142         destValue = (Yreal*)((char*)splineValuesPtr + splineStride*i);
    143         *destValue = v;
    144     }
    145 
    146     return true;
    147 }
    148 
    149 // --------------------------------------------------------------------------------------

     图像:

    相关软件的下载地址为:http://files.cnblogs.com/WhyEngine/TestSpline.zip

  • 相关阅读:
    委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)
    C#异步:实现一个最简单的异步
    关于Thread.IsBackground属性的理解(转载)
    C# 中的多线程(转载)
    个人对AutoResetEvent和ManualResetEvent的理解(转载)
    C#线程系列讲座(4):同步与死锁
    Nginx location 配置踩坑过程分享
    微信扫码登录网页实现原理
    负载均衡SLB
    Tomcat学习
  • 原文地址:https://www.cnblogs.com/WhyEngine/p/4020365.html
Copyright © 2020-2023  润新知