三次样条插值算法实现曲线拟合
三次样条插值
#部分内容及布局参考了CSDN博主 宁悦 的内容。
原文链接:https://blog.csdn.net/deramer1/article/details/79034201
背景
当前正在做的项目有一个需求是可以通过手动调节曲线来改变规划好的航迹。初步想法是将曲线用有限的几个点来固定,然后通过样条插值算法来实现曲线的拟合。
目前项目正处于前期,后续实施之后会在来更新。
样条插值法定义
一种以 可变样条 来作出一条经过一系列点的光滑曲线的数学方法。插值样条是由一些多项式组成的,每一个多项式都是由相邻的两个数据点决定的,这样,任意的两个相邻的多项式以及它们的导数在连接点处都是连续的。
实景举例
假设我们已知四个离散点的数据,如下表所示。
x | y |
---|---|
-2 | 2 |
-1 | 0 |
1 | 2 |
3 | 1 |
在我目前的浅薄理解中,根据已知的这四个点来实现这个区间(-2,3)内曲线的拟合,大概就是我想要做的事情,把问题简化一下,如何得到当x=2时的y值呢?
直线插值(自己起的名字,实际上就是一次函数)
可以利用我们初中学过的知识,将这四个点连线,根据(1,2)和(3,1)这两个点确定该连线的方程,然后求出x=2是的y值,但是很明显这种做法会使得求得的曲线不够光滑,而且会导致函数的一阶导数不连续。
二次样条
既然一次函数的直线不能够满足我们的需求,我们使用简单的曲线,二次函数来实现。如果我们用二次函数:aX^2+bx+c来描述曲线,最后的结果可能会好一点,一共有4个点,可以分成3个区间。每一个区间都需要一个二次函数来描述,一共需要9个未知数。然后根据以下条件找出方程组,
- 曲线方程在节点处的值必须相等,即函数在x1,x2两个点处的值必须符合两个方程,这里一共是4个方程。
- 第一个端点和最后一个端点必须过第一个和最后一个方程:这里一共是2个方程。
- 节点处的一阶导数的值必须相等。这里为两个方程。
- 在这里假设第一个方程的二阶导数为0:这里为一个方程。
将上述9个方程联立求解,最后就可以实现预测x=2处节点的值。
三次样条
三次样条的原理:
三次样条的原理和二次样条的原理相同,我们用函数aX^3 + bX2+cX+d这个函数来进行操作,这里一共是4个点,分为3个区间,每个区间一个三次样条函数的话,一共是12个方程,只要我们找出这12个方程,这个问题就算解决了。
1>内部节点处的函数值应该相等,这里一共是4个方程。
2>函数的第一个端点和最后一个端点,应该分别在第一个方程和最后一个方程中。这里是2个方程。
3>两个函数在节点处的一阶导数应该相等。这里是两个方程。
4>两个函数在节点处的二阶导数应该相等,这里是两个方程。
5>端点处的二阶导数为零,这里是两个方程。
三次样条的C++实现(追赶法)
#include <iostream>
#include <malloc.h>
#include <stdlib.h>
#include <math.h>
using namespace std;double *zuigan(double *a,double *b,double *c,double *f,int n) //追赶法求线性方程组
{double *x=NULL;double *p=NULL;double *q=NULL;x=(double*)malloc(sizeof(double)*n);p=(double*)malloc(sizeof(double)*(n-1));q=(double*)malloc(sizeof(double)*n);double t=0;p[0]=f[0]/b[0];q[0]=c[0]/b[0];for (int i=1;i<n;i++){t=b[i]-a[i-1]*q[i-1];p[i]=(f[i]-a[i-1]*p[i-1])/t;q[i]=c[i]/t;}for (int i=0;i<n;i++){x[i]=p[i];}for (int i=n-2;i>=0;i--){x[i]=p[i]-q[i]*x[i+1];}return x;
}int main()
{double x[]={-3,-2,1,3};double y[]={2,0,3,1};double S1=-1,S2=1; //上下边界导数值double resX=1.5;double resY=0.0;double *h=NULL;double *u=NULL;double *v=NULL; double *b=NULL;double *d=NULL;int n=0;double *m=NULL;n=sizeof(x)/sizeof(double);h=(double*)malloc(sizeof(double)*(n-1));for (int i=0;i<n-1;i++){h[i]=x[i+1]-x[i];}u=(double*)malloc(sizeof(double)*(n-2));v=(double*)malloc(sizeof(double)*(n-2));for (int i=0;i<n-2;i++){u[i]=h[i]/(h[i]+h[i+1]);v[i]=1-u[i];}u[n-2]=1;d=(double*)malloc(sizeof(double)*n);for (int i=1;i<n-1;i++){d[i]=(6/(h[i-1]+h[i]))*((y[i+1]-y[i])/h[i]-(y[i]-y[i-1])/h[i-1]);}d[0]=6/h[0]*((y[1]-y[0])/h[0]-S1);d[n-1]=6/h[n-2]*(S2-(y[n-1]-y[n-2])/h[n-2]);b=(double*)malloc(sizeof(double)*n);for (int i=0;i<n;i++){b[i]=2;}double tmp=0;for (int i=n-2;i>0;i--){v[i]=v[i-1];}v[0]=1;m=(double*)malloc(sizeof(double)*n);m=zuigan(u,b,v,d,n);int j=0;for (double k=x[0];k<=x[n-1];k+=0.1) //求拟合值,步进为0.1{resX=k;for (int i=0;i<n;i++){if (resX>=x[i]&&resX<=x[i+1]){j=i;break;}} double r1=x[j+1]-resX;double r2=resX-x[j];resY=(pow(r1,3.0)/(6.0*h[j]))*m[j]+(pow(r2,3.0)/(6.0*h[j]))*m[j+1]+(y[j]-m[j]*h[j]*h[j]/6.0)*(r1/h[j])+(y[j+1]-m[j+1]*h[j]*h[j]/6.0)*(r2/h[j]);cout<<resY<<endl;}system("pause");return 0;
}
三次样条插值算法实现曲线拟合相关推荐
- 三次样条插值算法C++实现
三次样条插值算法 1 总体说明 三次样条插值算法是一种计算量和效果都比较理想的插值算法.关于三次样条插值算法的原理这里不做过多的解释,下面的代码是我在网上收集了两种C++实现版本的基础上自己整合的一个 ...
- 埃尔米特三次样条插值算法-JAVA版本实现
埃尔米特三次样条插值算法-JAVA版本实现 package math;/*** 三次样条插值** y1=a+bx1+cx1^2* y2=a+bx2+cx2^2* y3=a+bx3+cx3^2** (y ...
- hermite、三次样条插值算法 调用matlab函数、代码实现
一.Hermite插值 Hermite插值要求有些节点或全部节点的函数值和导数值重合,使得在节点出具有一定的光滑度 满足插值条件的三次Hermite插值多项H3(x)存在且唯一,其基函数计算公式如下: ...
- 一文讲解图像插值算法原理!附Python实现
Datawhale学习 作者:姚童,Datawhale优秀学习者 寄语:本文梳理了最近邻插值法.双线性插值法和三次样条插值法的原理,并以图像缩放为例,对原理进行了C++及Python实现. 在图像处理 ...
- 轨迹生成--三次样条插值
三次样条函数插值(Cubic spline function interpolation) 对于样条概念解释得很好 三次样条插值算法C++实现 开源项目推荐:我个人中意的Python/C++数学库 ...
- matlab样条插值如何用,三次样条插值matlab实现
%三次样条差值-matlab通用程序 - zhangxiaolu2015的专栏 - CSDN博客 https://blog.csdn.net/zha %[图文]三次样条插值算法详解_百度文库 http ...
- 【20220207】【信号处理】三次样条插值原理详解
方程组的求解本文不做介绍. 一.三次样条插值 1. 定义 三次样条插值(Cublic Spline Interpolation),简称 Spline 插值,是通过一系列样本点的光滑曲线,数学上通过求解 ...
- 三次样条插值matlab实现
三次样条插值matlab实现 %三次样条差值-matlab通用程序 - zhangxiaolu2015的专栏 - CSDN博客 https://blog.csdn.net/zhangxiaolu201 ...
- 转载:一文讲解图像插值算法原理
最近在研究插值算法,看到这篇CSDN博主Datawhale学习介绍的博文,觉得介绍得挺不错,转载过来.原文地址:https://blog.csdn.net/Datawhale/article/deta ...
- 三次样条曲线插值的基本原理及其C#实现
声明:本人空间的所有文章,若无特别声明,皆为本人原创,可自由转载,但要注明原作者和原始出处,不可作为商业用途. 下面的内容是直接从Word文档复制粘贴出来的,有很多内容丢失,完整的PDF版本可到百度网 ...
最新文章
- 第九十三期:带你聊聊 Java 并发编程之线程基础
- AI知识点(1)--激活函数
- python支持函数式编程么_Python 函数式编程
- [20150518]关于块转储问题2.txt
- 云桌面终端_云桌面是否真的有被夸大,看完你就知道了
- 4款Bootstrap在线富文本编辑器
- 支付宝内部功能调用APP的said说明(转载)
- opengl绘制太阳、地球、月亮,贴上纹理,设置光照,符合自转和公转规律
- python版本升级 mac_mac如何升级python版本
- the计算机科学全球大学排名,2020THE计算机科学专业排名发布,内地60所大学入榜,清华全球15...
- 搜狗Sogou拼音输入法,搜狗高速浏览器(IE浏览器内核)
- 人生历程中的几个观念瓶颈
- 超详细Seaborn绘图 ——(一)barplot
- 求职材料准备-入门导读
- SQL数据分析淘宝用户分析实操
- 服务器2012系统修复,windows2012R2: sfc /scannow,错误:资源保护无法启动修复服务 - Microsoft Community...
- 转:对冲基金交易策略框架
- GORM报错sql: Scan called without calling Next
- 拥抱开源,我们是认真的-网易易数2020年Apache Spark贡献总结
- 计算机网络功能及计算机网络分类