插值与样条

先讲些题外话,前几天国庆回老家,在家中翻出了十年前大学时的一些教材课本,翻了几本看了看竟然如此的陌生。想当年考试前那么地刻苦学习,拼了命地上自——到如今变成了一场空,真令人唏嘘。其中有一本教材是《数值分析》,这门课也是挺难的,至少现在让我看是完全看不懂了。而《数值分析》一开始就是讲插值的,可以说插值是这门课的基础。

在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点。插值是离散函数逼近的重要方法,利用它可通过函数在有限个点处的取值状况,估算出函数在其他点处的近似值。插值可以用于填充图像变换时像素之间的空隙。插值,拟合,逼近是数值分析的三大基础工具,通俗意义上它们的区别在于:插值是已知点列并且完全经过点列;拟合是已知点列,从整体上靠近它们,逼近是已知曲线,或者点列,通过逼近使得构造的函数无限靠近它们。科学和工程问题可以通过诸如采样、实验等方法获得若干离散的数据,根据这些数据,我们往往希望得到一个连续的函数(也就是曲线)或者更加密集的离散方程与已知数据相吻合。

插值问题的提法是:假定区间[a,b]上的实值函数f(x)在该区间上 n+1个互不相同点x0,x1……xn 处的值是f (x0),……f(xn),要求估算f(x)在[a,b]中某点x*的值。基本思路是,找到一个函数P(x),在x0,x1……xn 的节点上与f(x)函数值相同(有时,甚至一阶导数值也相同),用P(x*)的值作为函数f(x*)的近似。简单地讲就是已知数据上的若干值,为其补上未知的值。

样条方程是一类分段光滑、并且在各段交接处也有一定光滑性的函数。样条一词来源于工程绘图人员为了将一些指定点连接成一条光顺曲线所使用的工具,即富有弹性的细木条或薄钢条。由这样的样条形成的曲线在连接点处具有连续的坡度与曲率。分段低次多项式、在分段处具有一定光滑性的函数插值就是模拟以上原理发展起来的,它克服了高次多项式插值可能出现的振荡现象,具有较好的数值稳定性和收敛性,由这种插值过程产生的函数就是多项式样条函数。

在计算机被使用之前,数字演算用手工完成。虽然分段定义的象signum函数或阶梯函数这样的函数也被用到,一般人更喜欢多项式因为它们比较容易算。随着计算机的发展,样条变得越来越重要。它们一开始是作为多项式在插值中的替代品,后来又作为在计算机图形学中构造光滑和可变形状的工具。样条函数的研究始于20世纪中叶,到了60年代它与计算机辅助设计相结合,在外形设计方面得到成功的应用。样条理论已成为函数逼近的有力工具。它的应用范围也在不断扩大,不仅在数据处理、数值微分、数值积分、微分方程和积分方程数值解等数学领域有广泛的应用,而且与最优控制、变分问题、统计学、计算几何与泛函分析等学科均有密切的联系。

讲了这么多,其实我这篇博客的目的是秀一下我所实现的样条曲线,请看下面的软件截图:

这是一个实现十余种样条曲线的程序DEMO。下载地址为:http://files.cnblogs.com/WhyEngine/TestSpline.zip

软件使用方式如下:

  1. 鼠标滚轮用于控制整个场景的缩放。
  2. 鼠标右键用于拖动场景。
  3. 按下CTRL并点击鼠标左键时,会添加一个采样点。
  4. 鼠标左键可以选中某一采样点。选中采样点后直接拖动鼠标可以修改其坐标位。如果选中采样点后按下CTRL再拖动鼠标可以插入一个新采样点。
  5. 选中采样点后按键盘DELETE可以删除采样点。
  6. CTRL + DELETE可以删除全部采样点。
  7. 通过界面左边的列表框,用于可以选择样条曲线的计算方式。

代码使用C++,开发环境为VS2008。所有的样条插值都是一个基类的子类:

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

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

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

#ifndef __YicSpline_H__
#define __YicSpline_H__

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

#include "..\WhyDefines.h"
#include "..\WhyAssert.h"

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

class YicSpline
{
public:
    // 计算样条数值
    virtual bool    BuildSpline(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount,
        void* splineValuesPtr, Yuint splineStride) const = NULL;

    // 计算切线数值
    virtual bool    BuildTangent(const void* ctrlValuesPtr, Yuint ctrlStride, Yuint ctrlCount,
        void* tangentValuesPtr, Yuint tangentStride) const
    {
        return false;
    }
};

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

inline float YfGetFloatValue(const void* valuesPtr, int stride, int index)
{
    return *(float*)((char*)valuesPtr + stride*index);
}

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

#endif

在下面的博客中,我会一一介绍这些样条的插值算法:

(1)样条之贝塞尔(Bezier)

(2)样条之B

(3)样条之CatmullRom

(4)样条之埃尔米特(Hermite)

(5)样条之拉格朗日Lagrange(一元全区间)插值函数

(6)样条之抛物线(一元三点)插值函数

(7)样条之连分式插值函数

(8)样条之埃尔米特(Hermite)插值函数

(9)样条之埃特金(Aitken)逐步插值函数

(10)样条之EHMT插值函数

(11)样条之Akima光滑插值函数

(12)样条之最小二乘算法求多项式

(13)样条之切比雪夫算法求多项式

最后转上一首诗,原址为:http://blog.sciencenet.cn/blog-39437-530669.html

插值

有一种神奇叫简单美丽

有一种精彩叫数据处理

这是个十分古老的故事

故事主角不只厄米特伊

有一种拟合叫最小二乘

有一种插值叫拉格朗日

纠纠结结都是你情我愿

合合分分从来不伤和气

有一种苗条它叫做样条

有一种振荡它无止无息

钻之弥坚不必瞻前顾后

仰之弥高须从卑处做起

也许有些曲折有些失意

也许偶尔出轨偶尔迷离

这一切的一切都不重要

重要的是那过程和经历

时间: 2024-08-01 06:33:14

插值与样条的相关文章

样条之CatmullRom

所谓样条曲线是指给定一组控制点而得到一条曲线,曲线的大致形状由这些点予以控制,一般可分为插值样条和逼近样条两种,插值样条通常用于数字化绘图或动画的设计,逼近样条一般用来构造物体的表面.CatmullRom样条与上一节所讲的B样条很相似,不同在于CatmullRom样条的曲线会经过其每一个控制点. The centripetal Catmull–Rom is a subclass of cubic Hermite spline that extends the Catmull–Rom implem

样条之埃尔米特(Hermite)

埃尔米特(Charles Hermite,1822—1901) 法国数学家.巴黎综合工科学校毕业.曾任法兰西学院.巴黎高等师范学校.巴黎大学教授.法兰西科学院院士.在函数论.高等代数.微分方程等方面都有重要发现.1858年利用椭圆函数首先得出五次方程的解.1873年证明了自然对数的底e的超越性.在现代数学各分支中以他姓氏命名的概念(表示某种对称性)很多,如“埃尔米特二次型”.“埃尔米特算子”等. 这种算法是由上一节讲的CatmullRom演变而成. 关于插值与样条的介绍请看:http://www

样条之抛物线(一元三点)插值函数

它是根据给定结点上的数值,用抛物插值计算指定插值点处的函数.一元三点插值算法是一种精度更高的插值算法,使用这种方法插值出来的曲线不像线性插值算法那样在分段点的地方出现折点,显得更为平滑.但它是使用二次函数来进行曲线的拟合,曲线中还是会有不平滑的情况. 关于插值与样条的介绍请看:http://www.cnblogs.com/WhyEngine/p/4020294.html 核心代码: /////////////////////////////////////////////////////////

B样条

在数学的子学科数值分析里,B-样条是样条曲线一种特殊的表示形式.它是B-样条基曲线的线性组合.B-样条是贝兹(贝塞尔)曲线的一种一般化,可以进一步推广为非均匀有理B样条(NURBS),使得我们能给更多一般的几何体建造精确的模型. 常数B样条 常数B样条是最简单的样条.只定义在一个节点距离上,而且不是节点的函数.它只是不同节点段(knot span)的标志函数(indicator function). 线性B样条 线性B样条定义在两个相邻的节点段上,在节点连续但不可微. 三次B样条 一个片断上的B

样条之贝塞尔(Bezier)

我曾经发过两篇关于贝塞尔的文章:数学图形(1.47)贝塞尔(Bézier)曲线,数学图形之贝塞尔(Bézier)曲面.那是使用我自己定义的脚本语言生成贝塞尔图形.由于我自己定义的脚本语法功能有限,所以最多只能支持5次贝塞尔函数,而这里将实现N次. N阶贝塞尔曲线可如下推断: 给定点P0.P1.….Pn,其贝塞尔曲线即 看其公式需要先为之生成一套杨辉三角形数组. 关于插值与样条的介绍请看:http://www.cnblogs.com/WhyEngine/p/4020294.html .h文件 1

ArcGIS数据生产与精细化制图之中国年降水量分布图的制作

原文:ArcGIS数据生产与精细化制图之中国年降水量分布图的制作 楼主按:在今年的Esri中国用户大会上,我听了几场关于ArcGIS用于制图方面的讲座,也在体验区与Esri中国的技术老师有一些交流.一直觉得ArcGIS在空间数据管理和分析方面很强大,而在制图方面却表现得不怎么样.我看到在国内很多人制图用的是CorelDraw.AI(可能不仅仅是国内,国外的专业制图也是),诚然这些软件作为专门的图形软件,在很多方面有不可比拟的优势,但是对于地理信息制图来说,图形不能和地理信息相关联却是这些软件最大

插值与拟合

1.插值 -->求过已知有限个数据点的近似函数 1)拉格朗日多项式插值 -->n个插值点不同时确定了一个唯一的n次多项式 构造n次拉格朗日插值多项式(不使用解方程n个约束来求解待定系数) 2)牛顿插值 使用差商概念来构造牛顿插值公式(计算量小,余项与拉格朗日余项相等),当节点之差为常数时,使用差分来代替差商构造牛顿向前插值公式 3)分段线性插值 -->高次插值存在震荡缺陷,采用低次分段函数(线性函数) y=interp1(x0,y0,x,'method') -->method可取n

样条参数与曲线长度间的互相求解

背景 在开发路径插件时,需要解决以下问题:获得路径上某一点到路径起点的曲线长度:给定曲线长度,返回路径上点的位置.路径是由三次样条(Spline)组成的,三次样条就是最高次数为 3 的一元多项式.设样条为 P(t) = f(t), 只要知道 t 就可以得到具体位置的坐标.一阶导等信息.设样条曲线长度为 s,那么要求的就是 t-s 和 s-t 的关系.不幸的是,曲线长度的计算没有解析解,只有数值方法.数值方法不适用于游戏中的时时运算,对性能影响太大.但是,如果事先对 s-t 或 t-s 曲线采样,

Matlab随笔之插值与拟合(上)

1.拉格朗日插值 新建如下函数: function y=lagrange(x0,y0,x) %拉格朗日插值函数 %n 个节点数据以数组 x0, y0 输入(注意 Matlat 的数组下标从1开始), %m 个插值点以数组 x 输入,输出数组 y 为 m 个插值 n=length(x0);m=length(x); for i=1:m z=x(i); s=0.0; for k=1:n p=1.0; for j=1:n if j~=k p=p*(z-x0(j))/(x0(k)-x0(j)); end