Вам, вероятно, придется написать это самостоятельно. Я думаю, что вы могли бы сделать это, внедрив в код функцию квадратичной кривой Безье, которую можно найти здесь . Вы решаете, насколько хорошо вы хотите приращения, решая только для нескольких значений. Если вы хотите прямую линию, решите только для 0 и 1 и соедините эти точки с линиями. Если вам нужен пример с одним углом, найдите 0, 0,5 и 1 и соедините точки по порядку. Если вам нужен третий пример, решите для 0, 0,25, 0,5, 0,75 и 1. Вероятно, было бы лучше поместить его в цикл for, например так:
float stepValue = (float)0.25;
float lastCalculatedValue;
for (float t = 0; t <= 1; t += stepValue)
{
// Solve the quadratic bezier function to get the point at t.
// If this is not the first point, connect it to the previous point with a line.
// Store the new value in lastCalculatedValue.
}
Редактировать: На самом деле, похоже, что вы хотите, чтобы линия проходила через вашу контрольную точку. Если это так, вы не хотите использовать квадратичную кривую Безье. Вместо этого вы, вероятно, хотите кривую Лагранжа. Этот веб-сайт может помочь с уравнением: http://www.math.ucla.edu/~baker/java/hoefer/Lagrange.htm. Но в любом случае вы можете использовать один и тот же тип цикла для контроля степени плавности.
2nd Edit: похоже, работает. Просто измените элемент numberOfSteps на общее количество сегментов линии, которое вы хотите, и настройте массив точек соответствующим образом. Кстати, вы можете использовать более трех пунктов. Он просто распределит общее количество отрезков по ним. Но я инициализировал массив так, чтобы результат выглядел как ваш последний пример.
3-е редактирование: я немного обновил код, чтобы вы могли щелкнуть левой кнопкой мыши на форме, чтобы добавить точки, и правой кнопкой мыши, чтобы удалить последнюю точку. Кроме того, я добавил NumericUpDown внизу, чтобы вы могли изменять количество сегментов во время выполнения.
public class Form1 : Form
{
private int numberOfSegments = 4;
private double[,] multipliers;
private List<Point> points;
private NumericUpDown numberOfSegmentsUpDown;
public Form1()
{
this.numberOfSegmentsUpDown = new NumericUpDown();
this.numberOfSegmentsUpDown.Value = this.numberOfSegments;
this.numberOfSegmentsUpDown.ValueChanged += new System.EventHandler(this.numberOfSegmentsUpDown_ValueChanged);
this.numberOfSegmentsUpDown.Dock = DockStyle.Bottom;
this.Controls.Add(this.numberOfSegmentsUpDown);
this.points = new List<Point> {
new Point(100, 110),
new Point(50, 60),
new Point(100, 10)};
this.PrecomputeMultipliers();
}
public void PrecomputeMultipliers()
{
this.multipliers = new double[this.points.Count, this.numberOfSegments + 1];
double pointCountMinusOne = (double)(this.points.Count - 1);
for (int currentStep = 0; currentStep <= this.numberOfSegments; currentStep++)
{
double t = currentStep / (double)this.numberOfSegments;
for (int pointIndex1 = 0; pointIndex1 < this.points.Count; pointIndex1++)
{
double point1Weight = pointIndex1 / pointCountMinusOne;
double currentMultiplier = 1;
for (int pointIndex2 = 0; pointIndex2 < this.points.Count; pointIndex2++)
{
if (pointIndex2 == pointIndex1)
continue;
double point2Weight = pointIndex2 / pointCountMinusOne;
currentMultiplier *= (t - point2Weight) / (point1Weight - point2Weight);
}
this.multipliers[pointIndex1, currentStep] = currentMultiplier;
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Point? previousPoint = null;
for (int currentStep = 0; currentStep <= numberOfSegments; currentStep++)
{
double sumX = 0;
double sumY = 0;
for (int pointIndex = 0; pointIndex < points.Count; pointIndex++)
{
sumX += points[pointIndex].X * multipliers[pointIndex, currentStep];
sumY += points[pointIndex].Y * multipliers[pointIndex, currentStep];
}
Point newPoint = new Point((int)Math.Round(sumX), (int)Math.Round(sumY));
if (previousPoint.HasValue)
e.Graphics.DrawLine(Pens.Black, previousPoint.Value, newPoint);
previousPoint = newPoint;
}
for (int pointIndex = 0; pointIndex < this.points.Count; pointIndex++)
{
Point point = this.points[pointIndex];
e.Graphics.FillRectangle(Brushes.Black, new Rectangle(point.X - 1, point.Y - 1, 2, 2));
}
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (e.Button == MouseButtons.Left)
{
this.points.Add(e.Location);
}
else
{
this.points.RemoveAt(this.points.Count - 1);
}
this.PrecomputeMultipliers();
this.Invalidate();
}
private void numberOfSegmentsUpDown_ValueChanged(object sender, EventArgs e)
{
this.numberOfSegments = (int)this.numberOfSegmentsUpDown.Value;
this.PrecomputeMultipliers();
this.Invalidate();
}
}