math - que - Dibuja una curva de Bézier cuadrática a través de tres puntos dados
parabola que pasa por tres puntos pdf (3)
Tengo tres puntos en 2D y quiero dibujar una curva de Bézier cuadrática que pasa a través de ellos. ¿Cómo calculo el punto de control medio ( x1
e y1
como en quadTo)? Conozco el álgebra lineal de la universidad, pero necesito ayuda simple para esto.
¿Cómo puedo calcular el punto de control medio para que la curva también lo atraviese?
Deje que P0, P1, P2 sean los puntos de control y Pc el punto fijo por el que desea que pase la curva.
Entonces la curva de Bezier se define por
P(t) = P0*t^2 + P1*2*t*(1-t) + P2*(1-t)^2
... donde t va de cero a 1.
Hay un número infinito de respuestas a su pregunta, ya que podría pasar a través de su punto para cualquier valor de t ... Así que solo elija una, como t = 0.5, y resuelva para P1:
Pc = P0*.25 + P1*2*.25 + P2*.25
P1 = (Pc - P0*.25 - P2*.25)/.5
= 2*Pc - P0/2 - P2/2
Allí los valores de "P" son pares (x, y), por lo que solo aplique la ecuación una vez para x y una vez para y:
x1 = 2*xc - x0/2 - x2/2
y1 = 2*yc - y0/2 - y2/2
... donde (xc, yc) es el punto por el que quiere que pase, (x0, y0) es el punto inicial, y (x2, y2) es el punto final. Esto le dará un Bezier que pasa a través de (xc, yc) en t = 0.5.
He utilizado la respuesta de Nemos en mi aplicación JavaFX, pero mi objetivo era dibujar la curva, de modo que el punto de inflexión visual de la curva siempre coincida con el seleccionado (CP).
CP = ControlPoint
SP = StartPoint
EP = EndPoint
BP (t) = variable Punto en BeziérCurve donde t está entre 0 y 1
Para lograr esto hice una variable t (no arreglar 0.5). Si el punto elegido CP ya no está en el medio entre SP y EP, debe variar t up o down un poco. Como primer paso, debe saber si CP está más cerca de SP o EP: Deje que distanceSP sea la distancia entre CP y SP y distanceEP, la distancia entre CP y EP, entonces yo defino la relación como:
ratio = (distanceSP - distanceEP) / (distanceSP + distanceEP);
Ahora vamos a usar esto para variar t arriba y abajo:
ratio = 0.5 - (1/3) * ratio;
Nota: esta es todavía una aproximación y se elige 1/3 por intento y error.
Aquí está mi función Java: (Point2D es una clase de JavaFX)
private Point2D adjustControlPoint(Point2D start, Point2D end, Point2D visualControlPoint) {
// CP = ControlPoint, SP = StartPoint, EP = EndPoint, BP(t) = variable Point on BeziérCurve where t is between 0 and 1
// BP(t) = SP*t^2 + CP*2*t*(1-t) + EP*(1-t)^2
// CP = (BP(t) - SP*t^2 - EP*(1-t)^2) / ( 2*t*(1-t) )
// but we are missing t the goal is to approximate t
double distanceStart = visualControlPoint.distance(start);
double distanceEnd = visualControlPoint.distance(end);
double ratio = (distanceStart - distanceEnd) / (distanceStart + distanceEnd);
// now approximate ratio to be t
ratio = 0.5 - (1.0 / 3) * ratio;
double ratioInv = 1 - ratio;
Point2D term2 = start.multiply( ratio * ratio );
Point2D term3 = end.multiply( ratioInv * ratioInv );
double term4 = 2 * ratio * ratioInv;
return visualControlPoint.subtract(term2).subtract(term3).multiply( 1 / term4);
}
Espero que esto ayude.
Si no desea el punto medio exacto, más bien desea cualquier valor para t (0 a 1), la ecuación es:
controlX = pointToPassThroughX/t - startX*t - endX*t;
controlY = pointToPassThroughY/t - startY*t - endY*t;
Por supuesto, esto también funcionará para el punto medio, solo t para que sea 0.5. ¡Sencillo! :-)