()https://www.cnblogs.com/WhyEngine/p/4020294.html?tdsourcetag=s_pctim_aiomsg
- 插值:已知点列,并且完全经过点列
通过函数,在有限个点处的取值情况,估算出函数在其他点处的近似值。
插值可以用于填充图像变换时,像素之间的空隙。
-
拟合:已知点列,从整体上靠近他们
-
逼近:已知曲线,或者点列,通过逼近使得构造函数无线靠近他们。
科学和工程问题,可以通过诸如采样、实验等方法获得若干离散的数据,根据这些数据,我们往往希望得到一个连续的函数(曲线)或者更加密集的离散方程与已知数据吻合。
- Catmull–Rom_spline
https://en.wikipedia.org/wiki/Centripetal_Catmull–Rom_spline
使用了递归算法,是一种内插值曲线(interpolating spline,一条可以通过它control points的曲线)。
定义:
点P 代表一个点
1.
曲线片段C由 point P0,P1,P2,P3和knot sequence t0,t1,t2,t3定义。
曲线可以这样产生:
曲线C定义
A、B定义
t定义
t0 = 0
t1 = (p0到p1的长度)^a + t0;当a为0,则t1为t0长度;当a为1,则t1为两点距离+t0长度
因此t是 点距离^a次方 的叠加值
a==0:uniform Catmull-Rom spline(统一的)
a==1:chordal Catmull-Rom spline(和弦的)
a==0.5:centripetal Catmull-Rom spline(向心的)
把t=t1插入样条方程A1A2A3B1B2,可以获得曲线C=P1。同样地,t=t2则C=P2。
t就是曲线的变量,而且能够保证t=t1时通过点P1
向心卡特穆尔-罗姆样条与原来的卡特穆尔-罗姆公式和其他类型的卡特穆尔-罗姆公式相比,有几个理想的数学特性。首先,它不会在曲线段内形成循环或自交。第二,在曲线段内永远不会出现尖点。第三,更紧密地跟随控制点。
在计算机视觉中,向心Catmull-Rom样条被用来制定一个主动的分割模型。这种方法称为主动样条模型。[4]模型是在主动形状模型的基础上设计的,但采用向心卡特穆尔- rom样条曲线连接连续的两个点(主动形状模型采用简单的直线),这样描述一个形状所需的总点数较少。向心Catmull-Rom样条的使用使得形状模型的训练变得更加简单,并且可以更好地编辑分割后的轮廓。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Catmul : MonoBehaviour {
// Use the transforms of GameObjects in 3d space as your points or define array with desired points
public Transform[] points;
// Store points on the Catmull curve so we can visualize them
List<Vector2> newPoints = new List<Vector2>();
// How many points you want on the curve
uint numberOfPoints = 10;
// Parametric constant: 0.0 for the uniform spline, 0.5 for the centripetal spline, 1.0 for the chordal spline
public float alpha = 0.5f;
/////////////////////////////
void Update()
{
CatmulRom();
}
void CatmulRom()
{
newPoints.Clear();
Vector2 p0 = points[0].position; // Vector3 has an implicit conversion to Vector2
Vector2 p1 = points[1].position;
Vector2 p2 = points[2].position;
Vector2 p3 = points[3].position;
float t0 = 0.0f;
float t1 = GetT(t0, p0, p1);
float t2 = GetT(t1, p1, p2);
float t3 = GetT(t2, p2, p3);
for (float t=t1; t<t2; t+=((t2-t1)/(float)numberOfPoints))
{
Vector2 A1 = (t1-t)/(t1-t0)*p0 + (t-t0)/(t1-t0)*p1;
Vector2 A2 = (t2-t)/(t2-t1)*p1 + (t-t1)/(t2-t1)*p2;
Vector2 A3 = (t3-t)/(t3-t2)*p2 + (t-t2)/(t3-t2)*p3;
Vector2 B1 = (t2-t)/(t2-t0)*A1 + (t-t0)/(t2-t0)*A2;
Vector2 B2 = (t3-t)/(t3-t1)*A2 + (t-t1)/(t3-t1)*A3;
Vector2 C = (t2-t)/(t2-t1)*B1 + (t-t1)/(t2-t1)*B2;
newPoints.Add(C);
}
}
float GetT(float t, Vector2 p0, Vector2 p1)
{
float a = Mathf.Pow((p1.x-p0.x), 2.0f) + Mathf.Pow((p1.y-p0.y), 2.0f);
float b = Mathf.Pow(a, alpha * 0.5f);
return (b + t);
}
// Visualize the points
void OnDrawGizmos()
{
Gizmos.color = Color.red;
foreach (Vector2 temp in newPoints)
{
Vector3 pos = new Vector3(temp.x, temp.y, 0);
Gizmos.DrawSphere(pos, 0.3f);
}
}
}
网友评论