Puntos espaciados uniformemente a lo largo de una curva bezier

He mirado alnetworkingedor por un time y no puedo encontrar una solución a este problema. Digamos que tengo una curva de bezier cúbica (definida por 4 puntos) y quiero get un set de puntos que estén espaciados uniformemente a lo largo de la curva. Piense en colocar un text a lo largo de una curva para un ejemplo.

Ahora el problema es que si ingreso t (valor de interpolación de 0-1) con un incremento constante, los puntos no están espaciados uniformemente. La distancia a lo largo de la curva es menor cuando la curva hace un giro y más larga cuando la curva es recta.

Entonces, ¿cómo coloco los puntos de manera uniforme a lo largo de una curva bezier?

Es más una pregunta matemática. Entonces una curva bezier tiene la siguiente fórmula , tanto en el componente x como en y .

 B_x(t) = (1-t)^3 * P0_x + (1-t)^2 * t * P1_x + (1-t) * t^2 * P2_x + t^3 * P3_x B_y(t) = (1-t)^3 * P0_y + (1-t)^2 * t * P1_y + (1-t) * t^2 * P2_x + t^3 * P3_y 

La longitud recorrida por t largo de una curva gamma está dada por:

 length_gamma(t) = integration( sqrt( derivative( gamma_x(s) ) ^2 + derivative( gamma_y(s) ) ^2 ) ) 

No existe una solución de escritura humana para la integral, por lo que debe aproximarse.

Reemplace el gamma(t) por la expresión B(t) para get la longitud length_B recorrida por t largo del segmento bezier. Digamos que viaja de 0 a L

Ahora select n valores entre 0 y L que correspondan a los puntos espaciados uniformemente. Por ejemplo, las longitudes de la forma k*L/n para k de 0 a n .

Ahora necesita length_B la longitud de la length_B , para que pueda calcular la t de la longitud l . Es un montón de matemáticas y soy flojo como el infierno, intenta hacerlo tú mismo. Si no puedes, puedes ir al stackexchange de matemáticas . Para una respuesta más completa, puedes ir allí de todos modos.

Una vez que tienes esa function inversa length_B (o una aproximación razonable), tu process es bastante simple.

  • Cree longitudes l[k] de distancia de path dada lejos del origen (P0_x,P1_x) .
  • Calcule su t[k] usando length_B_inverse .
  • Posicionando los puntos usando (B_x(t[k]),B_y(t[k])) .

Para ampliar lo que dijo Marco, una técnica común para hacer esto es caminar por la curva en incrementos mucho más pequeños que los pasos de longitud fija que desea tomar y almacenar el punto de salida resultante (¿y quizás la distancia?) En una tabla.

Luego, recorre la tabla y descarta todas las inputs, excepto los puntos que están más cerca de los múltiplos integers de las distancias que deseas recorrer.

Luego te queda una tabla que puedes indexar directamente en el time de ejecución muy rápidamente. Si quiere ir al punto que es 5 veces el tamaño de su distancia, mire en su tabla en el índice [5].

Tenga en count que puede hacer los dos pasos en uno y no almacenar los elementos adicionales en la tabla para empezar, pero es más fácil de visualizar y comprender en dos pasos.

Una vez vi una técnica para calcular esto sobre la marcha sin precalcular una tabla (¡tampoco usé iteración / búsqueda de raíz!), Pero desafortunadamente no recuerdo los detalles):

Si lo recuerdo o lo encuentro, ¡publicaré la información!

Bueno, ha pasado un time …

¡Pero finalmente pude resolver este problema!

Todo lo que necesitas es en esta publicación: mover naves entre dos planetas a lo largo de un bezier, faltando algunas ecuaciones para acelerar

Aquí hay un algorithm que da resultados bastante buenos:

  Point Index(float pos) const { int count = p.NumPoints(); Vector val(0.0,0.0,0.0); for(int i=0;i<count;i++) { val += bin(pos,i,count-1)*Vector(p.Points(i)); } return Point(val); } float bin(float pos, int i, int n) const { return float(ni(n,i)) * pow(double(pos), double(i))*pow(double(1.0-pos), double(ni)); } int ni(int n, int i) const { if (i==0) { return 1; } if (n==i) { return 1; } return ni(n-1,i-1)+ni(n-1,i); } 
Intereting Posts