Tracer des fonctions cartésiennes.

Tracer des fonctions mathématiques cartésiennes.

Voir version :

Pas de dépendances

Télécharger :

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

#define XRES 800
#define YRES 600
#define MINX -5.0
#define MINY -6.0
#define MAXX 10.0
#define MAXY 10.0

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

void waitkey()            // attend qu'on appuie sur ESC
{
    SDL_Event event;
    while(1)            // boucle
    {
        while(SDL_PollEvent(&event))        // aquisition d'evenement
        {
            if (event.type == SDL_KEYDOWN)  // on appuie sur une touche ?
            {
                if (event.key.keysym.sym == SDLK_ESCAPE) return;  // c'est "ESC" ?
            }
        }
        SDL_Delay(1);
    }
}

void SDL_PutPixel32(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    Uint8 *p;
    if (x<0 || y<0 || x>surface->w-1 || y>surface->h-1)
        return;
    p = (Uint8*)surface->pixels + y * surface->pitch + x * 4;
    *(Uint32*)p = pixel;
}

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 ShowFoncion(SDL_Surface* screen,Uint32 couleur,double (*fonc)(double))
{
    int i;
    int lastx = 0;
    int lasty = 0;
    int x,y;
    double resfonc;
    for(i=0;i<XRES;i++)
    {
        x = i;
        resfonc = fonc(Ecr_to_ReX(i));
        y = Re_to_EcrY(resfonc);
        if (i!=0)
            Line(screen,x,y,lastx,lasty,couleur);
        lastx = x;
        lasty = y;
    }
}



double mon_polynome(double x)
{
    // changez ici la fonction que vous voulez afficher. (pas forcément un polynome)
    return 0.3*x*x*x + 0.2*x*x + 0.1*x -1;
}




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
    while(0);


}

int main(int argc,char** argv)
{
    SDL_Surface* screen;
    SDL_Init(SDL_INIT_VIDEO);
    screen=SDL_SetVideoMode(XRES,YRES,32,SDL_SWSURFACE|SDL_DOUBLEBUF);  
    if (SDL_MUSTLOCK(screen))
        SDL_LockSurface(screen);

    ShowAxis(screen);


    ShowFoncion(screen,0xFF0000,cos);
    ShowFoncion(screen,0xFFFF00,sin);
    ShowFoncion(screen,0x00FF00,mon_polynome);
    
    
    if (SDL_MUSTLOCK(screen))
        SDL_UnlockSurface(screen);        
    SDL_Flip(screen);
    waitkey();
    return 0;
}





Commentaires


  Un petit programme sympa qui permet d'afficher des fonctions mathématiques.
  Note : ce programme est pour les matheux : je n'explique pas les concept de mise a l'échelle qui apparaissent ici.
  En effet, nous avons 2 domaines :

  le domaine de la fonction Xmin..Xmax -> réel, et le domaine de l'écran 0..X-1 

  Les 4 fonctions Re_to_EcrX, Re_to_EcrY, Ecr_to_ReX, Ecr_to_ReY permettent de passer d'un domaine a un autre.
  Il y a une mise a l'échelle, et je considere également l'inversion verticale :
  Le concept d'invertion verticale vient du fait que le mode graphique 2D fait évoluer les Y vers le bas, alors
  que mathématiquement, il est d'usage de faire évoluer les Y vers le haut -> d'ou l'inversion verticale.
  
	
  Lancez le programme et constatez les courbes :
  on en a 3
  - une courbe cosinus en rouge
  - une courbe sinus en jaune
  - une courbe polynome du 3e degré en vert

  Regardons le main :
  Une fonction ShowAxis : qui dessinera les axes
  et 3 appels de ShowFonction, qui dessinent chacun des 3 courbes (que vous pouvez désactiver)

  Commençons :
  je définis un tableau de 4 double en #define : ce sera ma "fenetre" d'affichage, le domaine en X et en Y d'affichage.
  XMIN, XMAX, YMIN, et YMAX. Les fonctions de mise a l'échelle s'appuieront sur ces données ainsi que XRES et YRES.

  Premiere étape : afficher les axes :
  Ce qu'il faut, c'est que je sache ou tracer ces axes : ils dépendent de mon domaine X et Y !
  C'est une mise a l'échelle :

  Je veux retrouver le point (0,0) que j'appellerai centreX et centreY, afin d'afficher les axes.
  Je me sers des fonctions de changement de base pour ça.
  
  Note : j'ai protégé la fonction Putpixel (plus haut) : en disant que si un essaie d'écrire un pixel hors de la fenetre : il n'est pas écrit
  --> On évite ainsi les crashs.

  Une fois les axes affichés, on peut afficher des fonctions.
  Notez que je passe des fonctions en parametre !!!

  En C, on peut passer des fonctions en parametre.
  je vous renvoie a mon chapitre dessus, dans le chapitre G (pointeurs de fonction)

  Je peux passer des fonctions de la forme :

  double fonc(double)

  C'est le cas de la fonction sin et cos (voir math.h et mon tuto chapitre A)
  Et c'est le cas de ma fonction mon_polynome.

  La fonction ShowFonction va parcourir chaque pixels horizontal de 0 a X-1, et calculer le Y associé.
  Elle reliera ensuite par un segment (fonction Line) la coordonnée du point calculé a celui précédent.


Laissez un commentaire / post a comment