您的位置:首页 > 其它

样条之贝塞尔(Bezier)

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

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

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



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

关于插值与样条的介绍请看:/article/4891792.html

.h文件

/****************************************************************

File name   :  YcBezierSpline.h
Author      :  叶峰
Version     :  2.0
Create Date :  2014/08/18
Description :  Bezier样条

*****************************************************************/

#ifndef __YcBezierSpline_H__
#define __YcBezierSpline_H__

// INCLUDES -----------------------------------------------------------------------------

#include "YicSpline.h"

// --------------------------------------------------------------------------------------

#define YD_MAX_BEZIER_CONTROL_VALUE 33

// --------------------------------------------------------------------------------------

class YcBezierSpline : public YicSpline
{
public:
YcBezierSpline();

~YcBezierSpline();

// 设置输出样条值的数目
void    SetSplineValuesCount(Yuint count);

// 获得输出样条值的数目
Yuint   GetSplineValuesCount() const;

// 计算样条数值
bool    BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount,
void* splineValuesPtr, Yuint splineStride) const;

protected:
void    ClearPowT();

void    BuildPowT();

Yreal    GetValueT(Yint t, Yint p) const
{
return m_pow_t[YD_MAX_BEZIER_CONTROL_VALUE*t + p];
}

protected:
Yuint   m_valuesCount;
Yreal*  m_pow_t;

protected:
static void    BuildYanghuiTriangle();
static Yint m_yanghuiRowIndex[YD_MAX_BEZIER_CONTROL_VALUE];
static Yint m_yanghuiTriangle[(YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2];
};

// --------------------------------------------------------------------------------------

#endif


CPP文件

/****************************************************************

File name   :  YcBezierSpline.cpp
Author      :  叶峰
Version     :  2.0
Create Date :  2014/08/18
Description :

*****************************************************************/

// INCLUDES -----------------------------------------------------------------------------

#include "..\..\YCommon_h\YSpline\YcBezierSpline.h"
#include <assert.h>

// --------------------------------------------------------------------------------------

Yint    YcBezierSpline::m_yanghuiRowIndex[YD_MAX_BEZIER_CONTROL_VALUE] = {0};
Yint    YcBezierSpline::m_yanghuiTriangle[(YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2] = {0};

void    YcBezierSpline::BuildYanghuiTriangle()
{
// 第0行
m_yanghuiRowIndex[0] = 0;
m_yanghuiTriangle[0] = 1;

Yint index = 1;
Yint t0,t1;
Yint* lastRow;
for (Yint i = 1; i < YD_MAX_BEZIER_CONTROL_VALUE; i++)
{
m_yanghuiRowIndex[i] = index;
m_yanghuiTriangle[index] = 1;
index++;

for (Yint j = 1; j <= i; j++)
{
lastRow = m_yanghuiTriangle + m_yanghuiRowIndex[i-1];
t0 = lastRow[j - 1];
t1 = (j < i) ? lastRow[j] : 0;

m_yanghuiTriangle[index] = t0 + t1;
index++;
}
}

assert(index == (YD_MAX_BEZIER_CONTROL_VALUE+1)*YD_MAX_BEZIER_CONTROL_VALUE/2);
}

// --------------------------------------------------------------------------------------

YcBezierSpline::YcBezierSpline()
{
if (m_yanghuiTriangle[0] == 0)
{
BuildYanghuiTriangle();
}

m_valuesCount = 0;
m_pow_t = NULL;

SetSplineValuesCount(100);
}

YcBezierSpline::~YcBezierSpline()
{
ClearPowT();
}

// 设置输出样条值的数目
void   YcBezierSpline::SetSplineValuesCount(Yuint count)
{
if (count < 2)
{
count = 2;
}

if (count == m_valuesCount)
{
return;
}
m_valuesCount = count;
BuildPowT();
}

// 获得输出样条值的数目
Yuint   YcBezierSpline::GetSplineValuesCount() const
{
return m_valuesCount;
}

void    YcBezierSpline::ClearPowT()
{
if (m_pow_t)
{
free(m_pow_t);
m_pow_t = NULL;
}
}

void    YcBezierSpline::BuildPowT()
{
ClearPowT();

m_pow_t = (Yreal*)malloc(m_valuesCount*YD_MAX_BEZIER_CONTROL_VALUE*sizeof(Yreal));
Yreal t;
for (Yuint i = 0; i < m_valuesCount; i++)
{
t = i/(m_valuesCount - 1.0f);

m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE] = 1.0f;
for (Yint j = 1; j < YD_MAX_BEZIER_CONTROL_VALUE; j++)
{
m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE + j] = m_pow_t[i*YD_MAX_BEZIER_CONTROL_VALUE + j - 1]*t;
}
}
}

// 计算样条数值
bool    YcBezierSpline::BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount,
void* splineValuesPtr, Yuint splineStride) const
{
if (ctrlCount < 2 || ctrlCount > YD_MAX_BEZIER_CONTROL_VALUE)
{
return false;
}

Yreal* destValue;
Yreal* srcValue;
Yreal v;
const Yint* yanghuiRow = m_yanghuiTriangle + m_yanghuiRowIndex[ctrlCount - 1];

for (Yuint i = 0; i < m_valuesCount; i++)
{
v = 0.0f;
for (Yuint j = 0; j < ctrlCount; j++)
{
srcValue = (Yreal*)((char*)ctrlValuesPtr + ctrlStride*j);
v += yanghuiRow[j] * (*srcValue) * GetValueT(i, j) * GetValueT(m_valuesCount - 1 - i, ctrlCount - 1 - j);
}

destValue = (Yreal*)((char*)splineValuesPtr + splineStride*i);
*destValue = v;
}

return true;
}

// --------------------------------------------------------------------------------------


图像:





相关软件的下载地址为:http://files.cnblogs.com/WhyEngine/TestSpline.zip
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐