2012-09-10 26 views
6

Creé esta clase en actionscript, devuelve un punto dado del bezier. Y lo que estoy tratando de lograr es obtener el ángulo del punto actual. Busqué en Internet, pero no pude encontrar mucho. ¿Cómo puedo hacer esto?Ángulo de un punto dado en una curva de Bezier?

public static function quadraticBezierPoint(u:Number, anchor1:Point, anchor2:Point, control:Point):Point { 
    var uc:Number = 1 - u; 
    var posx:Number = Math.pow(uc, 2) * anchor1.x + 2 * uc * u * control.x + Math.pow(u, 2) * anchor2.x; 
    var posy:Number = Math.pow(uc, 2) * anchor1.y + 2 * uc * u * control.y + Math.pow(u, 2) * anchor2.y; 
    return new Point(posx, posy); 
} 
+2

Si usted está haciendo matemáticas para conseguir el punto en sí, por qué no puede usted tomar la derivada para encontrar la pendiente? luego toma el atan2 para encontrar el ángulo? No estoy muy familiarizado con las curvas de Beizer, por lo que no hago de esto una respuesta real –

Respuesta

9

Dado:

  • puntos de control p0, p1, p2
  • tiempo t

punto B es el punto de la curva de Bezier cuadrática descrito por P0, P1, y p2 en el momento t.
q0 es el punto en la curva de bezier lineal descrito por p0 y p1 en el tiempo t.
q1 es el punto en la curva de bezier lineal descrito por p1 y p2 en el tiempo t.
El segmento de línea entre q0 y q1 es tangente a la curva de Bezier cuadrática en el punto B.

Por lo tanto, el ángulo de la curva de Bezier en el instante t es igual a la pendiente del segmento de línea entre q0 y q1.

Wikipedia tiene un lovely gif demostrando esto. El punto negro es el punto B, y los puntos finales del segmento de línea verde son q0 y q1.

El principio es idéntico para las curvas bezier de mayores dimensiones. Para encontrar el ángulo de un punto en una curva de bezier de N grados, encuentre q0 y q1, que son los puntos en las curvas de bezier N-1-degree para los puntos de control [p0, p1, ..., p (N-1)] y [p1, p2, ..., pN]. El ángulo es igual a la pendiente del segmento de línea q0-q1.

En pseudocódigo:

def bezierCurve(controlPoints, t): 
    if len(controlPoints) == 1: 
     return controlPoints[0] 
    else: 
     allControlPointsButTheLastOne = controlPoints[:-1] 
     allControlPointsButTheFirstOne = controlPoints[1:] 
     q0 = bezierCurve(allControlPointsButTheLatOne, t) 
     q1 = bezierCurve(allControlPointsButTheFirstOne, t) 
     return (1-t) * q0 + t * q1 

def bezierAngle(controlPoints, t): 
    q0 = bezierCurve(controlPoints[:-1], t) 
    q1 = bezierCurve(controlPoints[1:], t) 
    return math.atan2(q1.y - q0.y, q1.x - q0.x) 
+0

Gracias por explicar lo que tendría que hacer, no pude usar tu código porque sería demasiado intenso para la CPU y no era lo suficientemente dinámico, por lo que ¡Publiqué mi solución en mi pregunta! – tversteeg

3

Después de la explicación de Kevin me hizo una solución dinámica, pero simple:

public static function quadraticBezierAngle(u:Number, anchor1:Point, anchor2:Point, control:Point):Number { 
    var uc:Number = 1 - u; 
    var dx:Number = (uc * control.x + u * anchor2.x) - (uc * anchor1.x + u * control.x); 
    var dy:Number = (uc * control.y + u * anchor2.y) - (uc * anchor1.y + u * control.y); 
    return Math.atan2(dy, dx); 
} 
Cuestiones relacionadas