Probablemente necesite codificar esto usted mismo. Creo que podría hacerlo implementando una función de curva de bezier cuadrática en el código, que se puede encontrar here. Usted decide qué tan bien desea los incrementos resolviendo solo unos pocos valores. Si quieres una línea recta, solo resuelve para 0 y 1 y conecta esos puntos con líneas. Si desea el ejemplo de un ángulo, resuelva para 0, 0.5 y 1 y conecte los puntos en orden. Si desea que su tercer ejemplo, resolver durante 0, 0,25, 0,5, 0,75 y 1. Probablemente sería mejor ponerlo en un bucle como este:
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.
}
Editar: En realidad, parece que quiere que la línea pase a través de su punto de control. Si ese es el caso, no desea usar una curva de bezier cuadrática. En cambio, es probable que desee una curva de Lagrange. Este sitio web podría ayudar con la ecuación: http://www.math.ucla.edu/~baker/java/hoefer/Lagrange.htm. Pero en cualquier caso, puede usar el mismo tipo de bucle para controlar el grado de suavidad.
2nd Edit: Parece que funciona. Simplemente cambie el miembro numberOfSteps para que sea el número total de segmentos de línea que desea y configure la matriz de puntos de manera apropiada. Por cierto, puedes usar más de tres puntos. Simplemente distribuirá el número total de segmentos de línea a través de ellos. Pero inicialicé la matriz para que el resultado se vea como tu último ejemplo.
3ra edición: Actualicé el código un poco para que pueda hacer clic izquierdo en el formulario para agregar puntos y haga clic con el botón derecho para eliminar el último punto. Además, agregué un NumericUpDown en la parte inferior para que pueda cambiar la cantidad de segmentos en tiempo de ejecución.
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();
}
}
que no podía hacer el tema de justicia, sino que obtendrá una buena información si miras hacia arriba las curvas de Bezier y cómo para formarlos. Podría repetir como sugiera, pero existen mejores métodos para calcular curvas. –
Quiero ser capaz de controlar el número de segmentos en la curva. –
La curva tiene un número infinito de 'segmentos'. La cantidad de puntos que elijas evaluar y luego renderizar líneas depende de ti. –