Я занимаюсь школьным проектом. Моя задача - написать небольшое приложение Winform, представляющее кривую Безье, но с некоторыми ограничениями.
Я сделал почти все, только еще один шаг впереди меня.
Вся программа запускается с пустым холстом, затем пользователь может щелкнуть по нему, и круг будет нарисован. После каждого 4-го щелчка кривая Безье появляется для этого многоугольника. Теперь приходит моя проблема.
Я застрял в том, что мне нужно каким-то образом контролировать, где будет 5-й щелчок. Это должно быть на линии, которая идет от 2-х пунктов: 3-го и 4-го.
Кто-нибудь может мне помочь с этим? Я действительно понятия не имею, с чего начать.
Пока это мой код.
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 grafika_beadando_kettesert
{
public partial class MainForm : Form
{
Graphics g;
int counter = 0;
Pen PenBlack = Pens.Black; //ezzel a tollal rajzolom a vonalat
Pen PenCurve = new Pen(Color.Blue, 3f); //ezzel a tollal rajzolom a görbét
Brush PenPoint; //Ezzel töltöm ki a pontot
int size = 4; // a lerakott pont mérete
int found = -1;
List<PointF> Points = new List<PointF>(); //ebbe a listába tárolom a pontokat
PointF p0, p1;
public MainForm()
{
InitializeComponent();
PenPoint = new SolidBrush(canvas.BackColor);
this.DoubleBuffered = true;
}
private void canvas_Paint(object sender, PaintEventArgs e)
{
g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
for (int i = 0; i < Points.Count - 1; i++) // mindig meg kell rajzolni az eddig meghúzott vonalakat a polygonból újra
g.DrawLine(PenBlack, Points[i], Points[i + 1]);
if (counter == 4)
{
DrawBeziergorbe();
counter = 0;
}
for (int i = 0; i < Points.Count; i++) // ezzel rajzolom meg az eddig felrakott pontokat újra
{
g.FillEllipse(PenPoint, Points[i].X - size, Points[i].Y - size, 2 * size, 2 * size);
g.DrawEllipse(PenBlack, Points[i].X - size, Points[i].Y - size, 2 * size, 2 * size);
}
}
private void canvas_MouseUp(object sender, MouseEventArgs e)
{
found = -1;
}
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
if (found != -1)
{
Points[found] = e.Location;
canvas.Invalidate();
}
}
private void canvas_MouseDown(object sender, MouseEventArgs e)
{
for (int i = 0; i < Points.Count; i++)
{
if (Math.Abs(Points[i].X - e.X) <= size && Math.Abs(Points[i].Y - e.Y) <= size)
{
found = i;
break;
}
}
if (found == -1)
{
Points.Add(e.Location); //ha nincs túl közel a lerakott pont egy jelenlegihez, akkor hozzáadja a
//"Points" listához, hogy innen kiolvasva újra belehessen rajzolni
found = Points.Count - 1;
counter++;
canvas.Invalidate();
}
}
private void DrawBeziergorbe() //Mivel n-ed fokú bezier görbe kell, ezért használom a binomiálisos megoldást
{
int n = Points.Count - 1;
double t = 0;
double h = 1.0 / 500.0;
double b = 0.0;
p0 = new PointF(0, 0);
for (int i = 0; i <= n; i++)
{
b = B(n, i, t);
p0.X += (float)(b * Points[i].X);
p0.Y += (float)(b * Points[i].Y);
}
while (t < 1)
{
t += h;
p1 = new PointF(0, 0);
for (int i = 0; i <= n; i++)
{
b = B(n, i, t);
p1.X += (float)(b * Points[i].X);
p1.Y += (float)(b * Points[i].Y);
}
g.DrawLine(PenCurve, p0, p1);
p0 = p1;
}
}
private double B(int n, int i, double t)
{
return Binom(n, i) * (Math.Pow(1 - t, n - i) * Math.Pow(t, i));
}
private uint Binom(int n, int k)
{
if (n == 0) return 0;
else if (k == 0 || k == n) return 1;
else return Binom(n - 1, k - 1) + Binom(n - 1, k);
}
}
}