2013-03-24 29 views
12

Sono riuscito a implementare curve di Bezier quadratiche e cubiche. Sono piuttosto semplici perché abbiamo una formula. Ora voglio rappresentare una curva Bezier n-esimo ordine utilizzando la generalizzazione:n-esimo ordine Bezier Curves?

enter image description here

Dove

enter image description here

e

enter image description here

sto usando un libreria bitmap per rendere l'output, quindi ecco il mio codice:

// binomialCoef(n, k) = (factorial(n)/(factorial(k) * factorial(n- k))) 
unsigned int binomialCoef(unsigned int n, const unsigned int k) 
{ 
    unsigned int r = 1; 

    if(k > n) 
     return 0; 

    for(unsigned int d = 1; d <= k; d++) 
    { 
     r *= n--; 
     r /= d; 
    } 

    return r; 
} 

void nBezierCurve(Bitmap* obj, const Point* p, const unsigned int nbPoint, float steps, const unsigned char red, const unsigned char green, const unsigned char blue) 
{ 
    int bx1 = p[0].x; 
    int by1 = p[0].y; 
    int bx2; 
    int by2; 

    steps = 1/steps; 

    for(float i = 0; i < 1; i += steps) 
    { 
     bx2 = by2 = 0; 
     for(int j = 0; (unsigned int)j < nbPoint; j++) 
     { 
      bx2 += (int)(binomialCoef(nbPoint, j) * pow(1 - i, (float)nbPoint - j) * pow(i, j) * p[j].x); 
      by2 += (int)(binomialCoef(nbPoint, j) * pow(1 - i, (float)nbPoint - j) * pow(i, j) * p[j].y); 
     } 

     bresenhamLine(obj, bx1, by1, bx2, by2, red, green, blue); 

     bx1 = bx2; 
     by1 = by2; 
    } 

    // curve must end on the last anchor point 
    bresenhamLine(obj, bx1, by1, p[nbPoint - 1].x, p[nbPoint - 1].y, red, green, blue); 
} 

Ecco l'insieme dei punti di rendering:

Point ncurv[] = { 
        20, 200, 
        70, 300, 
        200, 400, 
        250, 200 
       }; 

ed ecco l'output:

enter image description here

La curva rossa è un Bezier cubica. Quello blu dovrebbe essere il 4 ° ordine di Bezier, che è lo stesso di Bezier cubico, ma in questo caso non sono gli stessi ?!

EDIT: Ho dimenticato di notare che il punto in basso a sinistra è (0, 0)

+1

Sembra che si sta perdendo la precisione a causa dei piccoli valori decimali. –

risposta

4

La somma nella formula ...

enter image description here

... va da 0 a n, vale a dire per un ordine n-esimo Bezier è necessario n + 1 punti.

Hai 4 punti, quindi stai disegnando un bezier di terzo ordine.

L'errore nel codice è qui:

for(int j = 0; (unsigned int)j < nbPoint; j++) 

dovrebbe essere:

for(int j = 0; (unsigned int)j <= nbPoint; j++) 

altrimenti sei solo l'iterazione da 0 a n-1.

3rd-order bezier

EDIT:

Fuori di interesse, la forma si stavano diventando è la stessa come se il punto mancante (5 °) era a (0,0), in quanto questo è l'unico punto che avrebbe contribuiscono niente al tuo somma ...

4th-order bezier with 5th point at origin

+0

ma quando 'j' raggiunge' nbPoint', 'p [j]' è oltre i limiti della matrice dei punti? – Jonas

+0

Sì - è necessario aggiungere un 5 ° punto per creare un bezier del 4 ° ordine. Quindi p deve essere di dimensione nbPoint + 1. –

+0

Sì, capisco ora. Grazie. – Jonas

2

Si sta cercando di costruire una curva di Bézier di 4 ° ordine su solo quattro punti. Non c'è da stupirsi che non funzioni.

+3

Come è questa una risposta? –

+1

Questo non fornisce una risposta alla domanda.Per criticare o richiedere chiarimenti da un autore, lasciare un commento sotto il loro post. - [Dalla revisione] (https://stackoverflow.com/review/low-quality-posts/16357822) –

+0

@DonaldDuck: risponde alla domanda in modo sintetico e corretto. La risposta di Richard Inglis è migliore, con tutte quelle belle immagini e tutto il resto, ma se leggi la prima frase di quella risposta vedrai che è essenzialmente la stessa della mia. – TonyK