Draw Bezier curves.

Draw Bezier curves.

See version :

Pas de dépendances

Download :

#include <math.h>
#include <sdl/sdl.h>

#define XRES 800
#define YRES 600
#define MINX -2.0
#define MINY -3.0
#define MAXX 5.0
#define MAXY 4.0

#define NBCONTROL 4

#ifdef WIN32
#pragma comment(lib,"sdl.lib")
#pragma comment(lib,"sdlmain.lib")
#endif

typedef struct 
{
    double x,y;
} ControlPoint;


ControlPoint Clist[NBCONTROL];

void UpdateEvents(Sint32* mousex,Sint32* mousey,char boutons[8],char key[SDLK_LAST])
{
    SDL_Event event;
    while(SDL_PollEvent(&event))
    {
        switch (event.type)
        {
        case SDL_KEYDOWN:
            key[event.key.keysym.sym]=1;
            break;
        case SDL_KEYUP:
            key[event.key.keysym.sym]=0;
            break;
        case SDL_MOUSEMOTION:
            *mousex=event.motion.x;
            *mousey=event.motion.y;
            break;
        case SDL_MOUSEBUTTONDOWN:
            boutons[event.button.button]=1;
            break;
        case SDL_MOUSEBUTTONUP:
            boutons[event.button.button]=0;
            break;
        }
    }
}

void SDL_PutPixel32(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    Uint8 *p = (Uint8*)surface->pixels + y * surface->pitch + x * 4;
    *(Uint32*)p = pixel;
}

Uint32 SDL_GetPixel32(SDL_Surface *surface, int x, int y)
{
    Uint8 *p = (Uint8*)surface->pixels + y * surface->pitch + x * 4;
    return *(Uint32*)p;
}

void Line(SDL_Surface* surf,int x1,int y1, int x2,int y2,Uint32 couleur)  // Bresenham
{
    int x,y;
    int Dx,Dy;
    int xincr,yincr;
    int erreur;
    int i;

    Dx = abs(x2-x1);
    Dy = abs(y2-y1);
    if(x1<x2)
        xincr = 1;
    else
        xincr = -1;
    if(y1<y2)
        yincr = 1;
    else
        yincr = -1;

    x = x1;
    y = y1;
    if(Dx>Dy)
    {
        erreur = Dx/2;
        for(i=0;i<Dx;i++)
        {
            x += xincr;
            erreur += Dy;
            if(erreur>Dx)
            {
                erreur -= Dx;
                y += yincr;
            }
            SDL_PutPixel32(surf,x, y,couleur);
        }
    }
    else
    {
        erreur = Dy/2;
        for(i=0;i<Dy;i++)
        {
            y += yincr;
            erreur += Dx;
            if(erreur>Dy)
            {
                erreur -= Dy;
                x += xincr;
            }
            SDL_PutPixel32(surf,x, y,couleur);
        }
    }
    SDL_PutPixel32(surf,x1,y1,couleur);
    SDL_PutPixel32(surf,x2,y2,couleur);
}

int Re_to_EcrX(double r)
{
    return (int)(XRES*(r-MINX)/(MAXX-MINX));
}

int Re_to_EcrY(double r)
{
    int y = (int)(YRES*(r-MINY)/(MAXY-MINY));
    y = YRES - y - 1;
    return y;
}

double Ecr_to_ReX(int i)
{
    return MINX + i*(MAXX-MINX)/XRES;
}

double Ecr_to_ReY(int i)
{
    return MAXY - i*(MAXY-MINY)/YRES;
}

void ShowAxis(SDL_Surface* screen)
{
    int centreX = Re_to_EcrX(0.0);
    int centreY = Re_to_EcrY(0.0);
    Line(screen,centreX,0,centreX,YRES-1,0xFFFFFF);  // axe vertical
    Line(screen,0,centreY,XRES-1,centreY,0xFFFFFF);  // axe horizontal
}

void ShowControlPoints(SDL_Surface* screen)
{
    int i;
    for(i=0;i<NBCONTROL;i++)
    {
        int x = Re_to_EcrX(Clist[i].x);
        int y = Re_to_EcrY(Clist[i].y);
        Line(screen,x-5,y-5,x+5,y+5,0xFF0000);
        Line(screen,x+5,y-5,x-5,y+5,0xFF0000);
    }
}

void InitCpoints()  // je place les points de controle arbitrairement autour d'un cercle fictif
{
    int i;
    for(i=0;i<NBCONTROL;i++)
    {
        double t = 0.15 + (i*3.0/NBCONTROL);
        Clist[i].x = cos(t);
        Clist[i].y = sin(t);
    }
}

void Casteljau(double t,ControlPoint* tab,int nbpoints,double* rx,double* ry)
{
    ControlPoint subtab[NBCONTROL];
    int i;
    if (nbpoints == 1)
    {
        *rx = tab[0].x;
        *ry = tab[0].y;
        return;
    }
    for(i=0;i<nbpoints-1;i++)
    {
        subtab[i].x = t*tab[i].x + (1-t)*tab[i+1].x;
        subtab[i].y = t*tab[i].y + (1-t)*tab[i+1].y;
    }
    Casteljau(t,subtab,nbpoints-1,rx,ry);
}

void ShowBezier(SDL_Surface* screen,double tstep,unsigned long couleur)
{
    double t = 0.0;
    int lastx = 0;
    int lasty = 0;
    int x,y;
    double rx = 0.0;
    double ry = 0.0;
    int i = 0;
    while(t<=1.0)
    {
        Casteljau(t,Clist,NBCONTROL,&rx,&ry);
        x = Re_to_EcrX(rx);
        y = Re_to_EcrY(ry);
        if (i!=0)
            Line(screen,x,y,lastx,lasty,couleur);
        lastx = x;
        lasty = y;
        t+=tstep;
        i++;
    }
}

void CheckMouseDeplace(Sint32 mousex,Sint32 mousey,char boutons[8])
{
    int i;
    if (boutons[SDL_BUTTON_LEFT]==0)
        return;
    for(i=0;i<NBCONTROL;i++)
    {
        int x = Re_to_EcrX(Clist[i].x);
        int y = Re_to_EcrY(Clist[i].y);
        if (abs(mousex-x)<=10 && abs(mousey-y)<=10)
        {
            Clist[i].x = Ecr_to_ReX(mousex);
            Clist[i].y = Ecr_to_ReY(mousey);
            return;
        }
    }
}

int main(int argc,char** argv)
{
    Sint32 mousex = 0;
    Sint32 mousey = 0;
    char boutons[8] = {0};
    char key[SDLK_LAST] = {0};
    SDL_Surface* screen;
    SDL_Init(SDL_INIT_VIDEO);
    screen=SDL_SetVideoMode(XRES,YRES,32,SDL_SWSURFACE|SDL_DOUBLEBUF);  
    SDL_ShowCursor(1);
    InitCpoints();
    while(!key[SDLK_ESCAPE])
    {
        SDL_FillRect(screen,NULL,0);
        UpdateEvents(&mousex,&mousey,boutons,key);
        if (SDL_MUSTLOCK(screen))
            SDL_LockSurface(screen);

        CheckMouseDeplace(mousex,mousey,boutons);
        
        ShowAxis(screen);
        ShowControlPoints(screen);
        ShowBezier(screen,0.002,0x00FF00);
        
        if (SDL_MUSTLOCK(screen))
            SDL_UnlockSurface(screen);        
        SDL_Flip(screen);
    }
    return 0;
}




Explanations

	No explanations yet.