Dessiner a la main une structure fractale [djgpp] [vga 13h]

Soyez le premier à donner votre avis sur cette source.

Vue 10 934 fois - Téléchargée 251 fois

Description

Ce petit programme vous permet de dessiner une structure fractale à la main. En fait c'est assez différent des autres générateurs de fractales habituels : ici pas de plan complexe, pas de jolies fractales de Mandelbrot, on peut très bien comprendre comment ça marche avec quelques connaissances de base en géométrie et trigonométrie (comme moi quoi). Pour donner un exemple vous dessinez d'abord un 'générateur' et puis vous dessinez la 'forme' que vous voulez faire prendre à votre fractale. Le programme va s'occuper de répéter votre 'générateur' sur chaque segment de votre 'forme', et le faire plusieurs fois afin d'obtenir une structure fractale. Par exemple, avec une ligne composé de 4 segments qui forme un triangle comme 'générateur', et un triangle équilatéral comme 'forme', vous aurez un flocon de Koch.

Ici le programme fait seulement trois générations, mais vous pouvez facilement changez ça dans la fonction BOUTON_Valider

Le vrai intérêt du code est je pense plutôt le système de 'event' développé pour pouvoir facilement manipuler des boutons, des 'surfaces',... que l'algorithme de génération de la fractale

connaissances requises pour ce programme : quelques bases en géométrie/trigonométrie, listes chainées, pointeurs sur fonctions, mode graphique VGA 13h

Source / Exemple :


#include        "fractal.h"

int             addy;   // permet d'afficher le 200eme pixel

//------//------//------//------//------//------//------//------//------//

int     main(int argc,char** argv)
{
        EVENT*  e;
        int     i;

        //------// DESSIN DE L'INTERFACE //-----------------------------//

                // initialise le mode graphique
        GFX_Init();

                // dessine l'interface rouge a droite
        for (i=0 ; i<200 ; i++)
                memset(SCREEN+201+320*i,LIGHTRED,119);

                // affiche le titre (avec une petite ombre)
        GFX_Print(SCREEN,220, 9,RED  ,-1,"GENERATEUR");
        GFX_Print(SCREEN,220,17,RED  ,-1,"DE FRACTAL");
        GFX_Print(SCREEN,219, 8,BLACK,-1,"GENERATEUR");
        GFX_Print(SCREEN,219,16,BLACK,-1,"DE FRACTAL");

                // affiche la 'boite de texte'
        for (i=MENU_TEXT-1 ; i<MENU_TEXT+(18-MENU_BOUTONS)*8+1 ; i++)
                memset(SCREEN+MENU_X+320*i-1,WHITE,99);

        //------// EVENEMENTS //----------------------------------------//

                // initialise le gestionnaire d'evenements
        EVENT_Init(0,319,0,199,0x3FF,0xFF);

                // cree les boutons
        BOUTON_Func[0]=&BOUTON_Nouveau;
        BOUTON_Func[1]=&BOUTON_Valider;
        BOUTON_Func[2]=&BOUTON_Annuler;
        BOUTON_Func[3]=&BOUTON_Quitter;
        strcpy(BOUTON_String[0],"  Nouveau  ");
        strcpy(BOUTON_String[1],"  Valider  ");
        strcpy(BOUTON_String[2],"  Annuler  ");
        strcpy(BOUTON_String[3],"  Quitter  ");
        for (i=0 ; i<MENU_BOUTONS ; i++)
        {
                e=EVENT_Create();               // nouvel evenement
                e->Id=i;                        // id = numero du bouton
                e->AreaIn=1;                    // interieur 'plein'
                e->x1=MENU_X-1;                 // defini les coordonnees
                e->x2=e->x1+99;                 // du bouton, d'apres le
                e->y1=i*12+MENU_Y;              // numero du bouton et les
                e->y2=e->y1+9;                  // coordonnees du menu
                e->fin=&BOUTON_RemplirIn;       // fonction 'IN'
                e->fout=&BOUTON_RemplirOut;     // fonction 'OUT'
                BOUTON_RemplirOut(e);           // dessine le bouton
                BOUTON_Event[i]=e;              // le rajoute au tableau
        }

                // cree la surface de dessin
        e=EVENT_Create();
        e->AreaIn=1;
        e->x1=0;
        e->x2=200;
        e->y1=0;
        e->y2=200;
        e->fin=&FRACTAL_Dessin;
        e->fout=&FRACTAL_DessinOut;
        addy=0;

        //------// AUTRES INITIALISATIONS + PROGRAMME //----------------//

                // initialise le fractal et le generateur
        FRACTAL_Init();

        while (1)
        {
                        // gestionnaire des evenements
                EVENT_Manager(&__fractal_intermediaire);

                        // affichage (avec curseur magenta clair)
                GFX_Display(LIGHTMAGENTA);
        }

        // cette partie est absolument inutile
        // vu qu'on a une boucle infinie juste
        // avant, elle est la juste pour faire
        // 'plus propre'...

                // efface les fractals
        EVENT_Delete(NULL);

                // fini !
        return 0;
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_Affiche()
{
        FRACT*  f;
        int     i;

                // avant toute chose, on efface la surface de dessin
        for (i=0 ; i<200 ; i++) memset(SCREEN+320*i,BLACK,201);

        if (etape==MODE_GENER)
                FRACTAL_Tracer(gener_debut,LIGHTGREEN);
        else if (etape==MODE_FRACT)
        {
                FRACTAL_Tracer(gener_debut,DARKGRAY);
                FRACTAL_Tracer(fract_debut,LIGHTGREEN);
        }
        else
        {
                        // convertit les positions
                f=final;
                while (f)
                {
                        f->x=100.0+f->x*100.0;
                        f->y=100.0-f->y*100.0;
                        f=f->n;
                }

                        // dessine le fractal
                FRACTAL_Tracer(final,LIGHTRED);

                        // reconvertit les positions
                f=final;
                while (f)
                {
                        f->x=f->x/100.0-1.0;
                        f->y=1.0-f->y/100.0;
                        f=f->n;
                }
        }
}

//------//------//------//------//------//------//------//------//------//

FRACT*  FRACTAL_Copier(FRACT* f1)
{
        FRACT*  f2;
        FRACT*  f2_debut;

        f2=malloc(sizeof(FRACT));
        f2_debut=f2;
        f2->p=NULL;
        while (f1->n)
        {
                f2->x=f1->x;
                f2->y=f1->y;
                f2->a=f1->a;
                f2->l=f1->l;
                f2->n=malloc(sizeof(FRACT));
                f2->n->p=f2;
                f2=f2->n;
                f1=f1->n;
        }
        f2->x=f1->x;
        f2->y=f1->y;
        f2->a=f1->a;
        f2->l=f1->l;
        f2->n=NULL;

        return f2_debut;
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_Dessin(EVENT* e)
{
        FRACT*  f;
        FRACT*  f2;

                // fixe le pointeur selon ce qui doit etre dessine
        if (etape==MODE_GENER) f=gener;
        else if (etape==MODE_FRACT) f=fract;
        else return;

                // affiche la position
        GFX_Print(SCREEN,MENU_X,MENU_TEXT   ,BLACK,WHITE,
        "X : %.2f ",(double)(EVENT_x)/100.0-1.0);
        GFX_Print(SCREEN,MENU_X,MENU_TEXT+8 ,BLACK,WHITE,
        "Y : %.2f ",1.0-(double)(EVENT_y)/100.0);

                // empeche l'utilisateur de dessiner trop de segments
        if (((nsegs_fract==MAX_SEGS)&&(etape==MODE_FRACT))
        ||  ((nsegs_gener==MAX_SEGS)&&(etape==MODE_GENER)))
        {
                FRACTAL_Affiche();
                return;
        }

                // si l'utilisateur doit dessiner le tout premier point
        if (!f)
        {
                        // si l'utilisateur a clique
                if ((EVENT_button&1)&&(!(EVENT_button2&1)))
                {
                                // creation du premier vertex
                        f=malloc(sizeof(FRACT));
                        f->p=NULL;
                        f->n=NULL;
                        f->x=EVENT_x;
                        f->y=EVENT_y;
                        nsegs_fract++;
                        fract_debut=f;
                }
        }

                // si l'utilisateur rajoute un segment
        else if ((f->x!=EVENT_x)||(f->y!=EVENT_y))
        {
                        // affiche l'angle et la longueur
                f->a=ANGLE(f->x,f->y,EVENT_x,EVENT_y);
                f->l=LONGUEUR(f->x,f->y,EVENT_x,EVENT_y)/200.0;
                GFX_Print(SCREEN,MENU_X,MENU_TEXT+16,BLACK,WHITE,
                "A : %.2f ",f->a);
                GFX_Print(SCREEN,MENU_X,MENU_TEXT+24,BLACK,WHITE,
                "L : %.2f ",f->l);

                        // redessine le fractal
                FRACTAL_Affiche();

                        // dessine la premiere ligne
                LIGNE
                (
                        SCREEN,
                        f->x,
                        f->y,
                        EVENT_x,
                        EVENT_y,
                        LIGHTBLUE
                );

                        // dessine la deuxieme ligne, si mode generateur
                if (etape==MODE_GENER) LIGNE
                (
                        SCREEN,
                        EVENT_x,
                        EVENT_y,
                        f->n->x,
                        f->n->y,
                        LIGHTBLUE
                );

                        // si clic gauche
                if ((EVENT_button&1)&&(!(EVENT_button2&1)))
                {
                                // nouveau point
                        f2=f->n;
                        f->n=malloc(sizeof(FRACT));
                        f->n->p=f;
                        f=f->n;
                        f->n=f2;
                        if (f2) f2->p=f;

                                // on enregistre les coordonnees
                        f->x=EVENT_x;
                        f->y=EVENT_y;

                                // on augmente le compteur correspondant
                        if (etape==MODE_GENER) nsegs_gener++;
                        else if (etape==MODE_FRACT) nsegs_fract++;
                }
        }

                // on actualise le pointeur correspondant
        if (etape==MODE_GENER) gener=f;
        else if (etape==MODE_FRACT) fract=f;
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_DessinOut(EVENT* e)
{
                // dessine le fractal
        FRACTAL_Affiche();

        if (etape!=MODE_FINAL)
        {
                        // efface les coordonnes de la souris
                GFX_Print(SCREEN,MENU_X,MENU_TEXT   ,BLACK,WHITE,
                "X :        ");
                GFX_Print(SCREEN,MENU_X,MENU_TEXT+8 ,BLACK,WHITE,
                "Y :        ");
                GFX_Print(SCREEN,MENU_X,MENU_TEXT+16,BLACK,WHITE,
                "A :        ");
                GFX_Print(SCREEN,MENU_X,MENU_TEXT+24,BLACK,WHITE,
                "L :        ");
        }
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_Effacer(FRACT* pf)
{
        while (pf->n)
        {
                pf=pf->n;
                free(pf->p);
        }
        free(pf);
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_Generation(FRACT* pf)
{
        FRACT*  f;
        double  a;
        double  l;

                // genere le fractal
        while (pf->n)
        {
                a=pf->a;
                l=pf->l;

                gener=gener_debut;
                while (gener->n->n)
                {
                                // on cree un nouveau point
                        f=pf->n;
                        pf->n=malloc(sizeof(FRACT));
                        pf->n->p=pf;
                        pf->n->n=f;
                        f->p=pf->n;

                                // on calcule l'angle et la longueur
                        pf->a=a+gener->a;
                        pf->l=l*gener->l;

                                // on calcule ses coordonnees
                        pf->n->x=pf->x+pf->l*cos(pf->a*PI/180.0);
                        pf->n->y=pf->y+pf->l*sin(pf->a*PI/180.0);

                        gener=gener->n;
                        pf=pf->n;
                }
                pf->a=a+gener->a;
                pf->l=l*gener->l;
                pf=pf->n;
        }
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_Init()
{
                // initialise la variable qui specifie l'action en cours
        etape=MODE_GENER;

                // initialise le fractal
        fract=NULL;
        fract_debut=NULL;
        nsegs_fract=-1;
        final=NULL;

                // initialise le generateur
        gener=malloc(sizeof(FRACT));
        gener->x=0;
        gener->y=100;
        gener->n=malloc(sizeof(FRACT));
        gener->p=NULL;
        gener_debut=gener;
        gener=gener->n;
        gener->n=NULL;
        gener->p=gener_debut;
        gener->x=200;
        gener->y=100;
        gener=gener_debut;
        nsegs_gener=1;
}

//------//------//------//------//------//------//------//------//------//

void    FRACTAL_Tracer(FRACT* f,char c)
{
                // on dessine le fractal
        if (f) while (f->n)
        {
                LIGNE   // on trace un segment
                (
                        SCREEN,
                        f->x,
                        f->y,
                        f->n->x,
                        f->n->y,
                        c
                );
                f=f->n; // segment suivant
                if (EVENT_button&2) { getch(); GFX_Display(LIGHTMAGENTA); }
        }
}

//------//------//------//------//------//------//------//------//------//

void            __fractal_intermediaire()
{
        if (EVENT_key==72<<8) addy=0;
        if (EVENT_key==80<<8) addy=1;
        EVENT_y+=addy;
}

Conclusion :


en fait je dois vous avertir que j'ai abandonné l'écriture du programme alors qu'il était presque fini, en fait ça m'intéressait plus trop. il n'est donc pas possible d'enregistrer la fractale
cependant je trouve le code assez intéressant pour figurer sur cppfrance

j'avais aussi déjà fait un programme similaire, mais très mal foutu et qui faisait planter nombre de PC. ici c'est simplement du mode graphique 320x200x256, ça devrait aller mieux. le code est également un peu plus clair

pour compiler le prog, faites :
gcc fractal.c bouton.c gfx.c event.c -s -Wall -o fractal.exe

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

dletozeun
Messages postés
546
Date d'inscription
vendredi 13 février 2004
Statut
Membre
Dernière intervention
9 janvier 2008
-
tu pourrias pas mettre un exe dans ton zip?

Parce que apres etre allé sur:
http://www.delorie.com/djgpp/doc/incs/

pour chercher les nombreux header files qui me manquaient j'ai encore plein d'erreur de syntaxe et autre....

et je n'est jamais essayé de compiler de la facon dont tu l'a preconisé...
luhtor
Messages postés
2023
Date d'inscription
mardi 24 septembre 2002
Statut
Membre
Dernière intervention
28 juillet 2008
4 -
Ca a l'air rigolo ton programme :), mais un exe serait pas mal oue.
cs_gorgonzola
Messages postés
37
Date d'inscription
samedi 16 mars 2002
Statut
Membre
Dernière intervention
21 février 2015
-
bah cppfrance me dit que je ne peux pas mettre de .exe dans les zip...
mais bon voici quand même un exécutable : http://gcheese.free.fr/fractal.exe
on ne peut pas enregistrer l'image c'est normal hein

mais normalement il n'y a aucun probleme pour compiler avec ma ligne de commande... mais attention il faut télécharger le zip pour ça ! ici j'ai seulement mis le fichier fractal.c dans la partie "code" pour donner un aperçu, mais les autres fichiers sont dans le zip !
dletozeun
Messages postés
546
Date d'inscription
vendredi 13 février 2004
Statut
Membre
Dernière intervention
9 janvier 2008
-
ben oui zip j'ai telechargé le zip mais deja tu n'as pas mis tous les headers file que tu utilises...

Merci pour l'exe
quelques remarques:

c'est normal que mon processeur est tout le tps a fond quand je lance le prog?
et quand j'ai le malheur de cliquer du bouton droit le programme se bloque et j'oi plus qu'a ouvrir le gestionnaire de taches pour le fermer manuellement
dommage que la resolution est si basse, des que l'on veut faire un truc compliqué on n'y voit plus rien

A part ca je trouve le prog assez amusant ! on obtien en s'y prenant bien de jolies choses.
douggyfresh
Messages postés
21
Date d'inscription
lundi 24 mai 2004
Statut
Membre
Dernière intervention
25 mai 2005
-
j'ai essaye ton ptit prog. La gestion de la souris en mode console est parfaite. Mais, je ne sais comment tracer a la main une fractale. De plus, il arrive que je ne sache comment sortir du programme. Il fallait indiquer une touche de sortie. J'ai essaye escape. Mais le programme tourne toujours.
Et compliments quand meme. Continue toujours de la sorte.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.