using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace periodBS {
public partial class Form1 : Form {
public int n, k;
public List<float> knot = new List<float>();
public float tmin = 0.0f,
tmax = 0.0f;
public float[,] ctrlPoint = new float[,] {{50, 100, 150, 200, 250, 300, 350},
{120, 20, 120, 20, 120, 20, 120}};
public Pen black = new Pen(Color.Black),
yellow = new Pen(Color.Red);
Graphics view;
public Form1() {
InitializeComponent();
}
// получение периодического узлового вектора
public List<float> GetKnot(int n, int k) {
int nKnots = n + k + 1;
List<float> retValue = new List<float>(new float[nKnots]);
for (int i = 0; i < nKnots; ++i)
retValue[i] = i;
return retValue;
}
// нерекурсивный расчет базисных функций
public float GetNormalizedFunction2(int i, int k, float t) {
float[,] N = new float[k, i + k];
for (int height = 1; height <= k; ++height) {
for (int width = i; width <= i + (k - height); ++width) {
float downValue = 0.0f,
downRightValue = 0.0f;
if (height == 1) {
if ((t >= knot[width]) && (t < knot[width + 1]))
downValue = 1.0f;
else
downValue = 0.0f;
N[height - 1, width] = downValue;
continue;
}
else {
downValue = N[height - 2, width];
downRightValue = N[height - 2, width + 1];
}
float fNum = (t - knot[width]) * downValue,
fDenum = knot[width + height - 1] - knot[width],
sNum = (knot[width + height] - t) * downRightValue,
sDenum = knot[width + height] - knot[width + 1],
retValue = 0.0f;
if (!fDenum.Equals(0.0f))
retValue += fNum / fDenum;
if (!sDenum.Equals(0.0f))
retValue += sNum / sDenum;
N[height - 1, width] = retValue;
}
}
return N[k - 1, i];
}
private void btn_draw_Click(object sender, EventArgs e) {
n = int.Parse(tb_n.Text);
k = int.Parse(tb_k.Text);
knot = GetKnot(n, k);
tmin = k - 1;
tmax = n;
drawBS();
drawBasis();
}
// отрисовка базисных функций
public void drawBasis() {
view = pb_basis.CreateGraphics();
for (int i = 0; i < ctrlPoint.GetLength(1); ++i) {
for (float t = tmin; t <= tmax; t += 0.005f) {
float basis = GetNormalizedFunction2(i, k, t);
view.DrawEllipse(black, t * 100.0f - 400.0f, 200.0f - basis * 200.0f, 1, 1);
}
}
}
// отрисовка b-сплайна
public void drawBS() {
view = pb_bs.CreateGraphics();
// отрисовка контрольных точек
for (int i = 0; i < ctrlPoint.GetLength(1); ++i)
view.DrawEllipse(yellow, ctrlPoint[0, i], ctrlPoint[1, i], 4, 4);
// отрисовка кривой
float x = 0.0f,
y = 0.0f,
curBasis = 0.0f;
for (float t = tmin; t <= tmax; t += 0.005f) {
x = 0.0f;
y = 0.0f;
for (int i = 0; i < ctrlPoint.GetLength(1); ++i) {
curBasis = GetNormalizedFunction2(i, k, t);
x += ctrlPoint[0, i] * curBasis;
y += ctrlPoint[1, i] * curBasis;
}
view.DrawEllipse(black, x, y, 1, 1);
}
}
}
}