基于BSpline的插值运算
正在做的一个C#项目要用到插值运算,插值运算算法主要是用了BSpline和多项式。
找了一下没有写得特别好的BSpline的C#库,Delphi倒是有一个别人写的不错的例子。
简单改写了一下。
using System;
using System.Collections.Generic;
using System.Text;
namespace BSplineDemo
{
class Vertex
{
Single _X;
public Single X
{
get { return _X; }
set { _X = value; }
}
Single _Y;
public Single Y
{
get { return _Y; }
set { _Y = value; }
}
}
class BSpline
{
const double MaxError = 1e-6;
List<Vertex> _VertexList=new List<Vertex>();
//Boolean _Interpolated = false;
Vertex _firstVertex = new Vertex();
Vertex _lastVertex = new Vertex();
public int PointsCount
{
get
{
return _VertexList.Count;
}
}
public Vertex GetVertex(int Index)
{
if (Index == 0)
return _firstVertex;
else if (Index == PointsCount + 1)
return _lastVertex;
else
return _VertexList[Index - 1];
}
public Vertex Value(Single Parameter)
{
//if (!_Interpolated)
// Interpolate();
Vertex v = new Vertex();
int b, c;
double dist;
double mix;
b = Convert.ToInt32(Math.Truncate((PointsCount - 1) * Parameter));
for (c = b - 2; c <= b + 3; c++)
{
dist = Math.Abs((PointsCount - 1) * Parameter - (c - 1));
if (dist < 2)
{
if (dist < 1)
mix = 4.0 / 6.0 - dist * dist + 0.5 * dist * dist * dist;
else
mix = (2.0 - dist) * (2.0 - dist) * (2.0 - dist) / 6.0;
v.X = Convert.ToSingle(v.X + GetVertex(c).X * mix);
v.Y = Convert.ToSingle(v.Y + GetVertex(c).Y * mix);
}
}
return v;
}
public void AddVertex(Vertex AVertex)
{
_VertexList.Add(AVertex);
PhantomPoints();
//_Interpolated = false;
}
//B-Splines use phantompoints to interpolate begin and end points
private void PhantomPoints()
{
if (PointsCount > 1)
{
_firstVertex.X = 2 * _VertexList[0].X - _VertexList[1].X;
_firstVertex.Y = 2 * _VertexList[0].Y - _VertexList[1].Y;
_lastVertex.X = 2 * _VertexList[PointsCount - 1].X - _VertexList[PointsCount - 2].X;
_lastVertex.Y = 2 * _VertexList[PointsCount - 1].Y - _VertexList[PointsCount - 2].Y;
}
}
public void ClearVertexs()
{
_VertexList.Clear();
}
}
}
调用示例程序
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace BSplineDemo
{
public partial class Form1 : Form
{
private BSpline line = new BSpline();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//
Random rand=new Random();
line.ClearVertexs();
for (int i = 0; i < 3; i++)
{
Vertex v = new Vertex();
v.X = rand.Next(0, this.ClientSize.Width);
v.Y = rand.Next(0, this.ClientSize.Height);
line.AddVertex(v);
}
PaintLine();
}
private void PaintLine()
{
int j;
Graphics g = this.CreateGraphics();
g.Clear(Color.White);
Pen p=new Pen(Color.Black);
try
{
float X1 = 0, Y1 = 0;
for (j = 0; j <= 10; j++)
{
Single x = Convert.ToSingle(j / 10.0);
Vertex V = line.Value(x);
if (j == 0)
{
X1 = V.X;
Y1 = V.Y;
}
else
{
g.DrawLine(p, X1, Y1, V.X, V.Y);
X1 = V.X;
Y1 = V.Y;
}
}
for (j = 1; j <= line.PointsCount; j++)
{
Vertex V = line.GetVertex(j);
g.DrawEllipse(p, V.X - 2, V.Y - 2, 4, 4);
}
}
finally
{
p.Dispose();
g.Dispose();
}
}
}
}
Attachment | Size |
---|---|
BSplineDemo.rar | 38.23 KB |