三次样条插值算法

1 总体说明

三次样条插值算法是一种计算量和效果都比较理想的插值算法。关于三次样条插值算法的原理这里不做过多的解释,下面的代码是我在网上收集了两种C++实现版本的基础上自己整合的一个版本。由于本人刚接触C++不久,水平有限。没有使用模板机制将代码做的更通用。关于算法实现有下面几点说明。

  1. 所有有关的类都被包含到SplineSpace命名空间中。
  2. SplineSpace中一个有三个类分别是异常类(SplineFailure),接口类(SplineInterface)和实现类(Spline)。有一个枚举类型说明边界条件(BoundaryCondition),取值为:GivenFirstOrder和GivenSecondOrder。分别对应I型边界条件和II型边界条件。
  3. 接口类定义了Spline在实现的过程中必须要有的三个方法:单点插值、多点插值和自动生成插值序列。
  4. 异常类是可能被实现类抛出的类,如果在实现类的运行过程中出现了已知数据过少构造失败、使用了外插值、设定输出点数过少等行为会抛出该类。因此应该将插值的过程用try...catch(SplineFailure sf)包裹起来。如:
double x0[2]={1,2};
double y0[2]={3,4}; try
{
SplineInterface* sp = new Spline(x0,y0,2);
//...
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}

上面代码就会抛出异常并显示“构造失败,已知点数过少”。

2 插值方法调用

2.1单点插值

调用方法如下:

#include <iostream>
#include "Spline.h" using namespace std;
using namespace SplineSpace; int main(void)
{
//单点插值测试 double x0[5]={1,2,4,5,6}; //已知的数据点
double y0[5]={1,3,4,2,5};
try
{
//Spline sp(x0,y0,5,GivenSecondOrder,0,0);
SplineInterface* sp = new Spline(x0,y0,5); //使用接口,且使用默认边界条件
double x=4.5;
double y;
sp->SinglePointInterp(x,y); //求x的插值结果y
cout<<"x="<<x<<"时的插值结果为:"<<y<<endl;
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
getchar(); //程序暂停
}

此时屏幕会输出"x=4.5时的插值结果为2.71107"。

  1. 可以直接构造Spline对象进行使用,也可以将它转化成对应的接口使用。
  2. 默认边界条件为II型边界条件(已知边界的二阶导数),默认左右边界二阶导数为都0,即自然边界条件。
  3. 已知的数据点数要至少为3(3个点对应一条曲线)。

2.2多点插值

调用方法如下(省略了和上面重复的代码部分):

//多点插值测试

double x0[5]={1,2,4,5,6};		//已知的数据点
double y0[5]={1,3,4,2,5}; double x[4] = {1.5,2.5,3.5,4.5}; //插值点
double y[4];
double leftBound=0,RightBound=0; //边界导数 try
{
Spline sp(x0,y0,5,GivenSecondOrder,leftBound,RightBound);
sp.MultiPointInterp(x,4,y); //求x的插值结果y
for(int i = 0;i < 4;i++)
{
cout<<"x="<<x[i]<<"时的插值结果为:"<<y[i]<<endl;
}
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
getchar(); //程序暂停

显示结果如下:

x=1.5时的插值结果为:2.01383
x=2.5时的插值结果为:3.8978
x=3.5时的插值结果为:4.62372
x=4.5时的插值结果为:2.71107

2.3自动生成插值序列

自动生成插值序列方法会根据指定的插值点数,在插值自变量区间等间距的生成插值点。这个方法在绘图的时候非常好用。指定的插值点数越多,绘制出来的图形质量越好。调用方法如下:

//自动插值测试

double x0[5]={1,2,4,5,6};		//已知的数据点
double y0[5]={1,3,4,2,5}; double x[10]; //插值点
double y[10]; try
{
SplineInterface* sp = new Spline(x0,y0,5); //使用接口,且使用默认边界条件
sp->AutoInterp(10,x,y); //求x的插值结果y for(int i = 0;i < 10;i++)
cout<<x[i]<<",";
cout<<endl;
for(int i = 0;i < 10;i++)
cout<<y[i]<<",";
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
getchar(); //程序暂停

显示结果如下:

1,1.55556,2.11111,2.66667,3.22222,3.77778,4.33333,4.88889,5.44444,6,
1,2.12528,3.21225,4.14572,4.639,4.38218,3.1524,2.02937,2.79183,5,

将上面结果复制粘贴到matlab中绘图,并且和matlab中的三次样条拟合结果作比较。matlab代码如下:

clear
clc x0=[1,2,4,5,6]; %已知的自变量
y0=[1,3,4,2,5]; %已知的因变量 pp=csape(x0,y0,'second',[0,0]); %二阶边界条件,且导数都为0
x = linspace(1,6,200);
y = ppval(pp,x); %C++算法得出了的结果
xCpp = [1,1.55556,2.11111,2.66667,3.22222,3.77778,4.33333,4.88889,5.44444,6];
yCpp = [1,2.12528,3.21225,4.14572,4.639,4.38218,3.1524,2.02937,2.79183,5]; h=figure;
plot(xCpp,yCpp,'*',x,y);
legend('c++插值结果','matlab插值结果')
title('插值结果')
h.Name = '插值结果';
h.NumberTitle = 'off';

结果如下:

可以看到C++中的算法得到的结果和matlab中得到的结果相同。

C++源程序代码:

有CSDN下载积分的童鞋可以使用右边的下载链接支持一下:三次样条插值C++代码

没有积分的童鞋也可以直接在本站下载源码:三次样条插值C++代码

三次样条插值算法C++实现的更多相关文章

  1. 三次样条插值matlab实现

    三次样条插值matlab实现 %三次样条差值-matlab通用程序 - zhangxiaolu2015的专栏 - CSDN博客 https://blog.csdn.net/zhangxiaolu201 ...

  2. Scipy和Numpy的插值对比

    技术背景 插值法在图像处理和信号处理.科学计算等领域中是非常常用的一项技术.不同的插值函数,可以根据给定的数据点构造出来一系列的分段函数.这一点有别于函数拟合,函数拟合一般是指用一个给定形式的连续函数 ...

  3. OpenGL 实现Interpolation插值算法

    这是一个静态插值算法的效果,图形学中插值算法应用十分广.如动画.photoshop, autocAD等软件画曲线,还有shader中的渐变上色也是一个硬件支持的插值算法. Interpolation是 ...

  4. [原创.数据可视化系列之十三]idw反距离权重插值算法的javascript代码实现

    图形渲染中,idw反距离权重插值算法是一个应用非常广泛的方法,但是js实现的比较少,目前实现一个: //idw算法 //输入[[x:0,y:0,v:0],[x:0,y:0,v:0],[x:0,y:0, ...

  5. 井眼轨迹的三次样条插值 (vs + QT + coin3d)

    井眼轨迹数据的测量值是离散的,根据某些测斜公式,我们可以计算出离散的三维的井眼轨迹坐标,但是真实的井眼轨迹是一条平滑的曲线,这就需要我们对测斜数据进行插值,使井眼轨迹变得平滑,我暂时决定使用三次样条进 ...

  6. resize函数有五种插值算法

    转自http://blog.csdn.net/fengbingchun/article/details/17335477 最新版OpenCV2.4.7中,cv::resize函数有五种插值算法:最近邻 ...

  7. Opencv 三次样条曲线(Cubic Spline)插值

    本系列文章由 @YhL_Leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/47707679 1.样条曲线简介 样条曲 ...

  8. java 三次样条插值 画光滑曲线 例子

    java 三次样条插值 画光滑曲线 例子 主要是做数值拟合,根据sin函数采点,取得数据后在java中插值并在swing中画出曲线,下面为截图  不光滑和光滑曲线前后对比:    代码: 执行类: p ...

  9. 分段三次Hermite插值及其与三次样条的比较

    分段三次 Hermite 插值多项式 (PCHIP) 语法 p = pchip(x,y,xq) pp = pchip(x,y)   说明 p = pchip(x,y,xq) 返回与 xq 中的查询点对 ...

随机推荐

  1. Nginx反向代理tomcat返回400 bad request

    Nginx反向代理tomcat返回400 bad request nginx 版本1.12, tomcat版本 9.06 最近用Nginx做反向代理tomcat,实现前后端分离,nginx 将请求代理 ...

  2. spring boot通过Interceptor和HandlerMethodReturnValueHandler实现统一处理为controller返回对象统计处理时间

    思路:实现思路都是基于Aop实现,方式上可以通过spring aop和spring mvc的aop机制都能实现. 通过Interceptor的可以实现为controller插入开始时间和执行结束时间, ...

  3. 收藏Dotnetbar的官方学习链接

    Archive for the DotNetBar for Windows Forms Category: http://www.devcomponents.com/kb2/?cat=3 视频教程: ...

  4. Entity Framework Code first 可能会导致循环或多个级联路径.

    用code first映射数据库报错 Introducing FOREIGN KEY constraint 'FK_dbo.Roles_dbo.SubSystems_SubSystemID' on t ...

  5. Python模块subprocess

    subprocess的常用用法 """ Description: Author:Nod Date: Record: #-------------------------- ...

  6. Git和代码规范

    最近发现和代码有点问题,总是在上线的紧急关头,和代码浪费了很多的时间,那么总结一下和代码的规范吧. 1.首先我们从master拉取代码进行开发. 2.开发完成之后,把代码上到test上面进行测试,上t ...

  7. JAVA 异常类型结构分析

    JAVA 异常类型结构分析 Throwable 是所有异常类型的基类,Throwable 下一层分为两个分支,Error 和 Exception. Error 和 Exception Error Er ...

  8. HTML/CSS基础知识(四)

    WEB标准和W3C的理解与认识 Web标准是一系列标准的集合. 网页主要由三部分组成:结构(Structure).表现(Presentation)和行为(Behavior). 对应的标准也分三方面:结 ...

  9. bitbucket 上公钥SSH key如何add key并进行项目运用

    前提:从sourcetree 添加项目时老是拉取不下来,查到原因是应为bitbucket需要SSH key公钥 目的:公钥相当于你在任何一台电脑只要有公钥授权就可以随时提交代码到服务器 原因: 1.很 ...

  10. 游戏中转盘概率的算法---python实现

    加入转盘的内容及概率如下 转盘倍数 0.5 0.6 0.7 0.8 1 1.2 1.5 1.8 2 机率 0.2 0.15 0.15 0.2 0.2 0.1 0.1 0.05 0.05 下面来实现转盘 ...