Partage
  • Partager sur Facebook
  • Partager sur Twitter

Atelier Cod'Art

24 octobre 2009 à 20:50:02

J'essaierai la visualisation de morceaux de musique quand j'aurai le temps, ça a l'air intéressant.
Pour l'instant, j'ai codé un programme qui, à partir d'une image entrée en niveaux de gris, rend un terrain.

Voici des exemples à partir de bruits de Perlin arrangés à ma sauce :
Image utilisateur
Image utilisateur

Il faudra que j'améliore le rendu de l'eau car là c'est pas top. Sinon je prévois d'ajouter des nuages. Désolé pour l'antialiasing, je savais pas trop comment faire.

Voici le code source : http://pastebin.org/47969
  • Partager sur Facebook
  • Partager sur Twitter
25 octobre 2009 à 2:44:30

Une éponge de menger infini en raytracing par distance field :-°

C'est presque du temps réel, ~10 FPS sur ma 8800GT en 320x240 :D !
Sinon le code est un shader a executer sur un quad opengl 2D !
Faisable facilement via un logiciel de shader style opengl shader designer ou qshaderedit.


Image utilisateur

Image utilisateur


(Code glsl, syntaxe proche du c++)
//Vertex Shader
uniform float time;
varying vec3 org,dir;
void main()
{
	gl_Position=gl_Vertex;
	org=vec3(0.5,0.5,0.0);
	dir=normalize(vec3(gl_Vertex.x*1.6,gl_Vertex.y,1.0));
		
}




// Fragment Shader
varying vec3 org,dir;



//-----------------------------------------------------------------------------
// Scene/Objects
//-----------------------------------------------------------------------------
float box(vec3 p, vec3 pos, vec3 size)
{
	return max(max(abs(p.x-pos.x)-size.x,abs(p.y-pos.y)-size.y),abs(p.z-pos.z)-size.z);
}


float scene(vec3 p)
{
	//Infinite sponge !
	p.x=mod(p.x,1.0);
	p.y=mod(p.y,1.0);
	p.z=mod(p.z,1.0);
	
	//Draw Just a cube 
	float d = box(p,vec3(0.5,0.5,0.5),vec3(0.5));
	
	// Soustract cubes
	float step,xstep,ystep,sstep;
	for(int ite=0; ite<3; ite++)
	{
		step = 1.0/pow(3.0,float(ite));
		for(int x=0; x<3*(ite+1); x++)
		for(int y=0; y<3*(ite+1); y++)
		{
			sstep = step/6.0;
			xstep = step*float(x)+step*0.5;
			ystep = step*float(y)+step*0.5;
			d = max(  -box( p, vec3(0.5,xstep,ystep), vec3(1.0,sstep,sstep) ), d  );
			d = max(  -box( p, vec3(xstep,0.5,ystep), vec3(sstep,1.0,sstep) ), d  );
			d = max(  -box( p, vec3(xstep,ystep,0.5), vec3(sstep,sstep,1.0) ), d  );
		}
	}
	
	return d;
}





//-----------------------------------------------------------------------------
// Tools
//-----------------------------------------------------------------------------
//Get Normal
vec3 getN(vec3 p)
{
	vec3 eps = vec3(0.001,0.0,0.0);
	return normalize(vec3(
		scene(p+eps.xyy)-scene(p-eps.xyy),
		scene(p+eps.yxy)-scene(p-eps.yxy),
		scene(p+eps.yyx)-scene(p-eps.yyx)
	));
}
//Get Ambiant Occlusion
float AO(vec3 p, vec3 n)
{
	float dlt = 0.4;
	float oc = 0.0, d = 1.0;
	for(int i = 0; i<6; i++)
	{
		oc += (float(i) * dlt - scene(p + n * float(i) * dlt)) / d;
		d *= 2.0;
	}
	return clamp(1.0-oc, 0.0, 1.0);
}
//Raymarching by distance field
vec3 Raymarche(vec3 org, vec3 dir, int step=64)
{
	float d=0.0;
	vec3 p=org;
	
	for(int i=0; i<step; i++)
	{
		d = scene(p);
		p += d*dir;
	}
	
	return p;
}


//-----------------------------------------------------------------------------
// Main Loops
//-----------------------------------------------------------------------------
void main()
{
	vec3 p = Raymarche(org,dir,32);
	vec4 color = AO(p,getN(p));
	
	
	
	gl_FragColor = color+pow(length(org-p),2.0)*vec4(1.0,0.5,0.3,1.0);
}
  • Partager sur Facebook
  • Partager sur Twitter
25 octobre 2009 à 8:17:48

Bonjour !

Pour ma part je vous invite à une petite excursion au pays des automates cellulaires.

Les captures d'écran ci-dessous représentent une génération des automates cellulaires MAZE (règles B3/S45678), DIAMOEBA (règles B35678/S5678) et REPLICATOR (B1357/S1357) initialisés avec respectivement 20 000, 100 000 et 100 cellules.

Automate cellulaire CORAL (B3/S45678)
MAZE (règles B3/S45678)

Automate cellulaire DIAMOEBA (B35678/S5678)
DIAMOEBA (règles B35678/S5678)

Automate cellulaire REPLICATOR (B1357/S1357)
REPLICATOR (B1357/S1357)

Je vous donne la seule partie un tant soit peu intéressante du code : un foncteur pour créer des automates cellulaires life-like avec une implémentation naïve (= à base de matrice d'entiers) raisonnablement performante jusqu'à 100 000 cases environ. Les cellules peuvent avoir 255 états distincts, ce qui permet de définir les couleurs selon leur âge.

module type PARAMETERS =
  sig
    val rows : int
    val columns : int
    val birth : int list
    val survival : int list
  end

module type S =
  sig
    val init : seed:int -> int array array
    val evolve : unit -> int array array
  end

module Make (Param : PARAMETERS) : S =
  struct
    let matrix = ref (Array.make_matrix Param.columns Param.rows 0)

    let count_neighbors ~x ~y =
      let res = ref (-1) in
      for i = x - 1 to x + 1 do
        for j = y - 1 to y + 1 do
          let i' = (i + Param.columns) mod Param.columns 
          and j' = (j + Param.rows) mod Param.rows in
          res := !res + Obj.magic (!matrix.(i').(j') > 0)
        done;
      done;
      !res

    let can_birth n = List.mem n Param.birth
    let can_survive n = List.mem n Param.survival

    let init ~seed =
      Random.self_init ();
      for i = 1 to seed do
        !matrix.(Random.int Param.columns).(Random.int Param.rows) <- 1
      done;
      !matrix

    let evolve () =
      let matrix' = Array.mapi (fun x col ->
        Array.mapi (fun y state ->
          let n = count_neighbors ~x ~y in
          if state > 0 then (if can_survive n then min 255 (state + 1) else 0)
          else Obj.magic (can_birth n) 
        ) col
      ) !matrix in
      matrix := matrix';
      matrix'
  end


Remarque : les deux appels à Obj.magic correspondent à une fonction de conversion bool_of_int et sont ici sans danger.

Cordialement,
Cacophrène
  • Partager sur Facebook
  • Partager sur Twitter
26 octobre 2009 à 0:35:13

Bonjour !

J'ai créé une sorte de spirale d'Ulam, mais en changeant les règles ... Sur ma spirale, il n'y a que des nombres premiers, et sont coloriés en noir ceux qui sont jumeaux, c'est-à-dire qu'ils sont séparés par une distance égale à deux. (Par exemple, 17 et 19 sont des nombres premiers jumeaux, parce qu'ils sont tout les deux premiers, et que 19-17 = 2. Dans ma spirale, ils sont tout les deux coloriés en noir). Pour les curieux, plus d'informations ici.



Le code :
<?php
	header ("Content-type: image/png");

	$nb_nb_premiers = 450000;
	$cote = ceil(sqrt($nb_nb_premiers)); // On définit la taille du côté.
	$image = imagecreate($cote, $cote);	
	$fond_blanc = imagecolorallocate($image, 255, 255, 255); // On applique une fond blanc.
	$noir = imagecolorallocate($image, 0, 0, 0);
	
	$milieu = ceil($cote/2);
	
	$fichier = fopen('liste_nb_premiers.txt', 'r'); // On charge un fichier où sont stockés les nombres premiers inférieurs à 10 millions, pour plus de simplicité.
	$premiers = array();
	$p = 0;
	while(!feof($fichier) AND $p < $nb_nb_premiers) { // On récupère les nombres premiers.
		$premiers[$p] = fgets($fichier);
		$p++;
	}
	$distance = 1;
	$x = $milieu;
	$y = $milieu;
	$directions = array( // On définit des directions dans l'ordre.
		'd' => 'h',
		'h' => 'g',
		'g' => 'b',
		'b' => 'd'
	);
	$direct = 'b';
	$change_direct = 0;
	for($a = 1; $a < $nb_nb_premiers; $a++) {
		if((sqrt($a) == floor(sqrt($a))) OR (sqrt((4*$a)+1) == floor(sqrt((4*$a)+1)))) { // Si le nombre est de la forme n^2 ou n(n+1).
			$change_direct++;
			$direct = $directions[$direct]; // On change la direction.
		}
		
		if($change_direct%2 == 0) // Quand on a changé de direction un nombre pair de fois ...
			$distance++; // ... on augmente de un la distance.
		
		// On effectue le changement de direction.
		if($direct == 'd') $x++;
		elseif($direct == 'h') $y--;
		elseif($direct == 'g') $x--;
		elseif($direct == 'b') $y++;
		
		if(($premiers[$a] - $premiers[$a-1]) == 2 OR ($premiers[$a+1] - $premiers[$a]) == 2) // Si ce nombre premier possède un jumeau ...
			ImageSetPixel($image, $x, $y, $noir); // ... on le colorie en noir.
	}
	
	imagepng($image); // On affiche l'image.
?>


J'espère ne pas m'être trompé, j'utilise très peu GD, et je ne code plus beaucoup ...

F.
  • Partager sur Facebook
  • Partager sur Twitter
10 novembre 2009 à 17:44:19

Bonjour,

J'ai approfondi un peu le sujet des IFS, et plus particulièrement la génération aléatoire des IFS.

Bien qu'assez mathématique, je pense que le sujet reste accessible aux zéros (dont moi même). Voici un lien :

http://mathenjeans.free.fr/amej/editio [...] /94pge083.htm
http://mathenjeans.free.fr/amej/editio [...] /94pge087.htm
http://mathenjeans.free.fr/amej/editio [...] /94pge093.htm

J'ai cree un petit outil (plutot sommaire) permettant de tracer simplement des IFS:
On dispose d'une fenetre quadrillee pour definir les triangles (3 clics droits: triangle de base (bleu); 3 clics gauches: triangle representant une fonction contractante (rouge)). Ensuite on clique sur entree et on visualise le resultat. La touche tab permet de reinitialiser les donnees et effacer l'ecran. echap pour quitter.

Exemple :

definition:


Image utilisateur

resultat :


Image utilisateur

Code :



Je poste tout le code au cas ou quelqu'un serait intéressé, mais la partie intéressante se trouve dans le main.


coordonnees.h


#ifndef _COORDONNEES_H
#define _COORDONNEES_H

typedef struct
{
    double x;
    double y;
} Coordonnees;

typedef struct
{
    Coordonnees vtx[3];
} Triangle;

#endif


listes.h


#ifndef _LISTES_H
#define _LISTES_H


typedef struct _list
{
    Triangle triangle;
    struct _list *next;
} LIST;

void cons (LIST** list, Triangle triangle);
void free_list (LIST* list);


#endif


main.c


#include <stdlib.h>
#include <SDL.h>
#include <math.h>
#include <time.h>


#include "coordonnees.h"
#include "listes.h"


#define SCREENSHOT      0
/* il faudrait effectuer un calcul sur le nombre d'iterations necessaires */
#define ITER            30


void setPixel(SDL_Surface* screen, int x, int y, Uint32 color);
void tracerTriangle (SDL_Surface* screen, Triangle triangle, Uint32 color);


#define BLANC           SDL_MapRGB(screen->format, 255, 255, 255)
#define NOIR            SDL_MapRGB(screen->format, 0, 0, 0)
#define ROUGE           SDL_MapRGB(screen->format, 255, 0, 0)
#define BLEU            SDL_MapRGB(screen->format, 0, 0, 255)
#define GRIS            SDL_MapRGB(screen->format, 170, 170, 170)

#define rand_0_1()      (rand()/(double)RAND_MAX)
#define rand_a_b(a,b)   ((b-a) * rand_0_1() + a)
#define rand_0_b(b)     (b * rand_0_1())


typedef struct
{
    double a;
    double b;
    double c;
    double d;
    double e;
    double f;
} MATRIX_2D;

Coordonnees Function (Coordonnees co, MATRIX_2D abcdef)
{
    Coordonnees ret = { co.x*abcdef.a+co.y*abcdef.b+abcdef.e, co.x*abcdef.c+co.y*abcdef.d+abcdef.f };
    return ret;
}

void drawing (SDL_Surface *screen, MATRIX_2D *abcdef, double *probability, unsigned nbFunctions)
{
    unsigned i, j, k;
    double random;
    Coordonnees co;

    for (i=0; i<screen->w*screen->h; i++)
    {
        /* tirage aleatoire d'un pixel de l'ecran */
        co.x = rand_0_1(), co.y = rand_0_1();
        //co.x = (double)i/screen->w, co.y = fmod(i,screen->w);
        //co.x = 0, co.y = 0; /* marche aussi */
        for (j=0; j<=ITER; j++)
        {
            random = rand_0_b (probability[nbFunctions-1]);
            /* choix de la fonction contractante */
            for (k=0; k<nbFunctions && probability[k] <= random; k++);
            co = Function (co, abcdef[k]);
        }
        setPixel(screen, co.x*screen->w, co.y*screen->h, NOIR);
    }
}

double calcul_abcdef (MATRIX_2D *abcdef, Triangle base, Triangle func)
{
    abcdef->a = (func.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-func.vtx[1].x*base.vtx[2].y+func.vtx[2].x*base.vtx[1].y+(func.vtx[1].x-func.vtx[2].x)*base.vtx[0].y)/(base.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-base.vtx[1].x*base.vtx[2].y+base.vtx[2].x*base.vtx[1].y+(base.vtx[1].x-base.vtx[2].x)*base.vtx[0].y);
    abcdef->b = (base.vtx[0].x*(func.vtx[2].x-func.vtx[1].x)-base.vtx[1].x*func.vtx[2].x+func.vtx[1].x*base.vtx[2].x+func.vtx[0].x*(base.vtx[1].x-base.vtx[2].x))/(base.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-base.vtx[1].x*base.vtx[2].y+base.vtx[2].x*base.vtx[1].y+(base.vtx[1].x-base.vtx[2].x)*base.vtx[0].y);
    abcdef->c = (base.vtx[1].y*func.vtx[2].y+base.vtx[0].y*(func.vtx[1].y-func.vtx[2].y)+func.vtx[0].y*(base.vtx[2].y-base.vtx[1].y)-func.vtx[1].y*base.vtx[2].y)/(base.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-base.vtx[1].x*base.vtx[2].y+base.vtx[2].x*base.vtx[1].y+(base.vtx[1].x-base.vtx[2].x)*base.vtx[0].y);
    abcdef->d = -(base.vtx[1].x*func.vtx[2].y+base.vtx[0].x*(func.vtx[1].y-func.vtx[2].y)-base.vtx[2].x*func.vtx[1].y+(base.vtx[2].x-base.vtx[1].x)*func.vtx[0].y)/(base.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-base.vtx[1].x*base.vtx[2].y+base.vtx[2].x*base.vtx[1].y+(base.vtx[1].x-base.vtx[2].x)*base.vtx[0].y);
    abcdef->e = -(base.vtx[0].x*(func.vtx[2].x*base.vtx[1].y-func.vtx[1].x*base.vtx[2].y)+func.vtx[0].x*(base.vtx[1].x*base.vtx[2].y-base.vtx[2].x*base.vtx[1].y)+(func.vtx[1].x*base.vtx[2].x-base.vtx[1].x*func.vtx[2].x)*base.vtx[0].y)/(base.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-base.vtx[1].x*base.vtx[2].y+base.vtx[2].x*base.vtx[1].y+(base.vtx[1].x-base.vtx[2].x)*base.vtx[0].y);
    abcdef->f = (base.vtx[0].x*(func.vtx[1].y*base.vtx[2].y-base.vtx[1].y*func.vtx[2].y)+base.vtx[0].y*(base.vtx[1].x*func.vtx[2].y-base.vtx[2].x*func.vtx[1].y)+func.vtx[0].y*(base.vtx[2].x*base.vtx[1].y-base.vtx[1].x*base.vtx[2].y))/(base.vtx[0].x*(base.vtx[2].y-base.vtx[1].y)-base.vtx[1].x*base.vtx[2].y+base.vtx[2].x*base.vtx[1].y+(base.vtx[1].x-base.vtx[2].x)*base.vtx[0].y);
    return fabs(abcdef->a*abcdef->d-abcdef->b*abcdef->c);
}

void prepare_and_draw (SDL_Surface *screen, LIST *listeTriangles, Triangle triangleBase, unsigned nbTriangles)
{
    unsigned i;
    double *probability = NULL;
    MATRIX_2D *abcdef = NULL;
#if SCREENSHOT
    char filename[MAX_PATH];
    char date[500];
    time_t t = time(NULL);
    strftime(date, sizeof date, "%d_%b_%Y_%Hh%Mm%Ss", localtime(&t));
    sprintf(filename, "screens/triangles_%s.bmp", date);
    SDL_SaveBMP(screen, filename);
#endif

    SDL_FillRect(screen, NULL, BLANC);
    if (nbTriangles > 0)
    {
        abcdef = calloc (nbTriangles, sizeof *abcdef);
        probability = calloc (nbTriangles, sizeof *probability);
        if (abcdef != NULL && probability != NULL)
        {
            /* calcul des fonctions affines et probabilites */
            for (i=0; i<nbTriangles; i++)
            {
                probability[i] = calcul_abcdef (&abcdef[i], triangleBase, listeTriangles->triangle) + (i ? probability[i-1] : 0);
                listeTriangles = listeTriangles->next;
            }
            /* dessin */
            drawing (screen, abcdef, probability, nbTriangles);
            free(abcdef);
            free(probability);
        }
    }
#if SCREENSHOT
    sprintf(filename, "screens/IFS_%s.bmp", date);
    SDL_SaveBMP(screen, filename);
#endif
    SDL_Flip(screen);
}

void quadrillage (SDL_Surface *screen, unsigned n, Uint32 color)
{
    unsigned x, y, range_x, range_y;
    range_x = screen->w/n, range_y = screen->h/n;
    for (x=0; x<screen->w; x+=range_x)
    {
        for (y=0; y<screen->h; y++)
        {
            setPixel(screen, x, y, color);
        }
    }
    for (y=0; y<screen->h; y+=range_y)
    {
        for (x=0; x<screen->w; x++)
        {
            setPixel(screen, x, y, color);
        }
    }
}

#define SCR_W   600
#define SCR_H   600
#define QUAD    10

int main ( int argc, char** argv )
{
    unsigned done, numTriangle = 0, nbVertice = 0;
    SDL_Event event;
    SDL_Surface *screen;
    Coordonnees co;
    LIST* listeTriangles = NULL;
    Triangle triangleBase, triangleBaseDessine, triangleDessine, triangle;

    //srand(time(NULL));
    /*  initialise SDL video */
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "Unable to init SDL: %s\n", SDL_GetError() );
        return 1;
    }

    screen = SDL_SetVideoMode(SCR_W, SCR_H, 32, SDL_HWSURFACE);
    quadrillage (screen, QUAD, GRIS);
    SDL_Flip(screen);

    done = 0, numTriangle;
    while (!done)
    {
        /* attente d'un evenement */
        SDL_WaitEvent(&event);
        /*  on traite l'evenement */
        switch (event.type)
        {
            /* fermeture de la fenetre */
        case SDL_QUIT:
            done = 1;
            break;

            /*  appui d'une touche */
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym)
            {
            case SDLK_ESCAPE: /*  Touche Echap */
                done = 1;
                break;

                /* calcule les fonctions et affiche l'IFS */
            case SDLK_RETURN:
                prepare_and_draw (screen, listeTriangles, triangleBase, numTriangle);
                numTriangle = 0, nbVertice = 0;
                break;

                /* reinitialise */
            case SDLK_TAB:
                free_list (listeTriangles), listeTriangles = NULL;
                numTriangle = 0, nbVertice = 0;
                SDL_FillRect(screen, NULL, NOIR);
                quadrillage (screen, QUAD, GRIS);
                SDL_Flip(screen);
                break;

            default:
                break;
            } /* fin switch (event.key.keysym.sym) */
            break;

            /* Clic de la souris */
        case SDL_MOUSEBUTTONUP:
            co.x = (double)event.button.x;
            co.y = (double)event.button.y;
            switch (event.button.button)
            {
                /* definition triangles contractants */
            case SDL_BUTTON_LEFT:
                triangle.vtx[nbVertice].x = co.x/screen->w;
                triangle.vtx[nbVertice].y = co.y/screen->h;
                triangleDessine.vtx[nbVertice] = co;
                nbVertice++;
                if (nbVertice == 3)
                {
                    tracerTriangle(screen, triangleDessine, ROUGE);
                    cons (&listeTriangles, triangle);
                    numTriangle++, nbVertice = 0;
                }
                break;

                /* definition triangle base */
            case SDL_BUTTON_RIGHT:
                triangleBaseDessine.vtx[nbVertice] = co;
                triangleBase.vtx[nbVertice].x = co.x/screen->w;
                triangleBase.vtx[nbVertice].y = co.y/screen->h;
                nbVertice++;
                if (nbVertice == 3)
                {
                    tracerTriangle(screen, triangleBaseDessine, BLEU);
                    nbVertice = 0;
                }
                break;

            default:
                break;
            }
            break;

        } /* fin switch (event.type) */
    } /* fin boucle evenementielle */
    free_list (listeTriangles);
    SDL_Quit();
    return 0;
}


listes.c


#include <stdlib.h>


#include "coordonnees.h"
#include "listes.h"



LIST* new_elem (Triangle triangle)
{
    LIST* ret = malloc (sizeof *ret);
    if (ret != NULL)
        ret->triangle = triangle, ret->next = NULL;
    return ret;
}

void free_list (LIST* list)
{
    LIST* next;
    while (list != NULL)
    {
        next = list->next;
        free(list), list = next;
    }
}

void cons (LIST** list, Triangle triangle)
{
    LIST* elem = new_elem (triangle);
    if (elem != NULL)
        elem->next = *list, *list = elem;
}


gdi.c


#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>


#include "coordonnees.h"


/* Dessine un pixel - mode 32 bits */
void setPixel(SDL_Surface* screen, unsigned x, unsigned y, Uint32 color)
{
    if (x < screen->w && y < screen->h)
    {
        Uint8 *p = (Uint8 *)screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
        *(Uint32 *)p = color;
    }
}

void tracerSegment (SDL_Surface* screen, Coordonnees a, Coordonnees b, Uint32 color)
{
    int x1 = a.x;
    int y1 = a.y;
    int x2 = b.x;
    int y2 = b.y;
    int dx, dy, e;
    if ( (dx = x2 - x1) != 0)
    {
        if (dx > 0)
        {
            if ( (dy = y2 - y1) != 0)
            {
                if (dy > 0) // vecteur oblique dans le 1er quadran

                {
                    if (dx >= dy) // vecteur diagonal ou oblique proche de l’horizontale, dans le 1e octant
                    {
                        dx = (e=dx) * 2;
                        dy = dy * 2;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( ++x1 == x2 )
                                break;
                            if ( (e = e - dy) < 0 )
                            {
                                y1++;
                                e = e + dx;
                            }
                        }
                    }
                    else // vecteur oblique proche de la verticale, dans le 2e octant
                    {
                        dy = (e=dy) * 2;
                        dx = dx * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( ++y1 == y2 )
                                break;
                            if ( (e = e - dx) < 0 )
                            {
                                x1++;
                                e = e + dy;
                            }
                        }
                    }
                }
                else // (dy < 0)// vecteur oblique dans le 4e cadran
                {
                    if (dx >= -dy) // vecteur diagonal ou oblique proche de l’horizontale, dans le 8e octant

                    {
                        dx = (e=dx) * 2;
                        dy = dy * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( ++x1 == x2 )
                                break;
                            if ( (e += dy) < 0 )
                            {
                                y1--;
                                e = e + dx;
                            }
                        }
                    }
                    else // (dx < -dy) vecteur oblique proche de la verticale, dans le 7e octant
                    {
                        dy = (e=dy) * 2 ;
                        dx = dx * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( --y1 == y2 )
                                break;
                            if ( (e += dx) > 0 )
                            {
                                x1++;
                                e = e + dy;
                            }
                        }
                    }
                }
            }
            else // (dy == 0 && dx > 0) - vecteur horizontal vers la droite
            {
                do
                {
                    setPixel(screen, x1, y1, color);
                }
                while ( ++x1 <= x2);
            }
        }
        else // dx < 0
        {
            if ( (dy = y2 - y1) != 0 )
            {
                if (dy > 0) // vecteur oblique dans le 2e quadran
                {
                    if (-dx >= dy) // vecteur diagonal ou oblique proche de l’horizontale, dans le 4e octant

                    {
                        dx = (e=dx) * 2;
                        dy = dy * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( --x1 == x2 )
                                break;
                            if ( (e = e + dy) > 0 )
                            {
                                y1++;
                                e = e + dx;
                            }
                        }
                    }
                    else // vecteur diagonal ou oblique proche de la verticale, dans le 4e octant
                    {
                        dy = (e=dy) * 2;
                        dx = dx * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( ++y1 == y2 )
                                break;
                            if ( (e = e + dx) < 0 )
                            {
                                x1--;
                                e = e + dy;
                            }
                        }
                    }
                }
                else // (dy < 0)
                {
                    if (-dx >= -dy)
                    {
                        dx = (e=dx) * 2;
                        dy = dy * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( --x1 == x2 )
                                break;
                            if ( (e = e - dy) > 0 )
                            {
                                y1--;
                                e = e + dx;
                            }
                        }
                    }
                    else
                    {
                        dy = (e=dy) * 2;
                        dx = dx * 2 ;
                        while (1)
                        {
                            setPixel(screen, x1, y1, color);
                            if ( --y1 == y2 )
                                break;
                            if ( (e = e - dx) > 0 )
                            {
                                x1--;
                                e = e + dy;
                            }
                        }
                    }
                }
            }
            else // (dy == 0 && dx < 0) - vecteur horizontal vers la gauche
            {
                do
                {
                    setPixel(screen, x1, y1, color);
                }
                while ( --x1 >= x2);
            }
        }
    }
    else if (y1 != y2)
    {
        if (y1 < y2) // vecteur vertical vers le bas
        {
            do
            {
                setPixel(screen, x1, y1, color);
            }
            while ( ++y1 <= y2);
        }
        else // vecteur vertical vers le haut
        {
            do
            {
                setPixel(screen, x1, y1, color);
            }
            while ( --y1 >= y2);
        }
    }
}

void tracerTriangle (SDL_Surface* screen, Triangle triangle, Uint32 color)
{
    tracerSegment (screen, triangle.vtx[0], triangle.vtx[1], color);
    tracerSegment (screen, triangle.vtx[1], triangle.vtx[2], color);
    tracerSegment (screen, triangle.vtx[2], triangle.vtx[0], color);
    SDL_Flip(screen);
}


EDIT: petite correction dans le code.

EDIT 2 : code mis en secret
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
11 novembre 2009 à 11:40:41

Je regarde ce topic à chaque fois qu'il y a de nouveaux codes (pas le temps de participer :/ ) et j'aurais deux choses à dire :
  • Bravo à tous ceux qui continuent à faire vivre Cod'Art !
  • Je vous en prie, mettez les images dans des balises <secret>. Attendre 5 min pour que la page arrête de bouger c'est super énervant :/ .
  • Partager sur Facebook
  • Partager sur Twitter
17 novembre 2009 à 6:10:30

Citation : bluestorm

J'ai l'impression que le sujet des fractacles a été un peu surexploité sur le topic.


OK c'est pas de moi, mais je pense que ça vaut le coup d'oeil :] :
http://www.geeks3d.com/20091116/explor [...] al/#more-6135
  • Partager sur Facebook
  • Partager sur Twitter
3 décembre 2009 à 22:22:50

Hello,

Bluestorm ne va pas etre content :p , mais je ramene une nouvelle fractale : )

Il s'agit du Tricorn, ou mandelbar set.

C'est a peu pres la meme chose que mandelbrot, avec une legere modification de la suite.

Image utilisateur

Le code est dispo ici : http://vlad.washere.free.fr/src/C/tricorn.rar
  • Partager sur Facebook
  • Partager sur Twitter
Découvrez un petit jeu Android bien sympa : http://www.siteduzero.com/forum/sujet/appli-jeu-android-cube-racer
Anonyme
4 décembre 2009 à 0:26:00

Voici mes petits tests :
Image utilisateur
<?php
$img = imagecreatetruecolor(512, 512);
imageantialias($img, false);

for($i=0;$i<512;$i+=4){
   $color = imagecolorallocatealpha($img, (256-$i)*2, $i*3, $i*5, 67);
   imageline($img, 0, $i, 512-$i, 0, $color); // HG
   imageline($img, 512-$i, 0, 512, 512-$i, $color); // HD
   imageline($img, 512, 512-$i, $i, 512, $color); // BD
   imageline($img, $i, 512, 0, $i, $color); // BG
}

header('Content-type: image/jpeg');
imagejpeg($img);

et
Image utilisateur
<?php
$img = imagecreatetruecolor(512, 512);
imageantialias($img, false);

for($i=0;$i<256;$i+=4){
   $color = imagecolorallocatealpha($img, (256-$i)*2, $i*3, $i*7, 67);
   imageline($img, 0, $i, 256-$i, 0, $color); // HG
   imageline($img, 512-$i, 0, 512, 256-$i, $color); // HD
   imageline($img, 512, 512-$i, 256+$i, 512, $color); // BD
   imageline($img, $i, 512, 0, 256+$i, $color); // BG
}

header('Content-type: image/jpeg');
imagejpeg($img);
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
5 décembre 2009 à 11:54:02

Le topic est-il mort?

J'ai fait un automate cellulaire. Au démarrage, tous les pixels ont un statuts aléatoire entre 0 et 3 (de rouge au jaune). Ensuite, à chaque cycle, une cellule augmente sont statuts (0->1, 1->2, 2->3, 3->0) si au moins 3 des 8 cellules adjacentes ont le statuts suivant.
Voici le cycle 100 :
Image utilisateur

Et voici le code utilisé pour la générer :
<?php
define('X', 512);
define('Y', 512);
define('ETAT', 4);

include('gif.class.php');

$array = array();
for($i=0;$i<X;$i++){
   $array[$i] = array();
   for($j=0;$j<Y;$j++)
      $array[$i][$j] = rand(0,ETAT-1);
}

$anim = array();
$duree = array();
$img = imagecreatetruecolor(X, Y);
$color = array();
for($i=0;$i<ETAT;$i++){
   $color[] = imagecolorallocate($img, 0xFF, (0xFF/ETAT)*$i, 0);
}

for($i=0;$i<1000;$i++){
   $array = avancer($array);
   $anim[] = dessiner($img, $array, $color);
   $duree[] = 10;
}

$gif = new GIFEncoder($anim, $duree, 0, 2, 0, 0, 0, 'bin');

header('Content-type: image/gif');
echo $gif->GetAnimation();

Et les fonctions :
<?php
function dessiner($img, $array, $color){
   foreach($array as $y=>$ligne)
      foreach($ligne as $x=>$cellule)
         imagesetpixel($img, $x, $y, $color[$cellule]);
   ob_start();
   imagegif($img);
   return ob_get_clean();
}
function avancer($array){
   $new = array();
   foreach($array as $y=>$ligne){
      $new[$y] = array();
      foreach($ligne as $x=>$cellule){
         $nbr = 0;
         if(isset($array[$y-1][$x-1]) AND $array[$y-1][$x-1] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y][$x-1]) AND $array[$y][$x-1] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y-1][$x]) AND $array[$y-1][$x] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y-1][$x+1]) AND $array[$y-1][$x+1] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y+1][$x-1]) AND $array[$y+1][$x-1] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y][$x+1]) AND $array[$y][$x+1] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y+1][$x]) AND $array[$y+1][$x] == ($cellule+1)%ETAT)
            $nbr++;
         if(isset($array[$y+1][$x+1]) AND $array[$y+1][$x+1] == ($cellule+1)%ETAT)
            $nbr++;

         if($nbr>=3)
            $new[$y][$x] = ($cellule+1)%ETAT;
         else
            $new[$y][$x] = $cellule;
      }
   }
   return $new;
}

Attention!! Temps d'exécution : 24 minutes, donc évitez de l'utilisez comme ça :-°

Autrement, si quelqu'un à une idée pour rendre l'exécution plus rapide, je suis preneur :)
  • Partager sur Facebook
  • Partager sur Twitter
7 décembre 2009 à 1:11:25

Citation : berdes1

Le topic est-il mort?


Non, le topic n'est pas mort, il est juste moins anime qu'au debut de l'atelier.


Citation : berdes1

Attention!! Temps d'exécution : 24 minutes, donc évitez de l'utilisez comme ça :-°

Autrement, si quelqu'un à une idée pour rendre l'exécution plus rapide, je suis preneur :)



Ne m'y connaissant pas trop en php, je peux rien te dire pour ameliorer ton script, mais le php etant un langage interprete, il est assez lent a l'execution.
Un langage compile, tel que C ou C++ serait sans doute plus rapide.
  • Partager sur Facebook
  • Partager sur Twitter
Découvrez un petit jeu Android bien sympa : http://www.siteduzero.com/forum/sujet/appli-jeu-android-cube-racer
Anonyme
7 décembre 2009 à 7:29:36

Oui, mais il n'empêche que même en C, ça se fera pas en 3 secondes. En fait, j'ai fait des fractales aussi et d'après les comparaisons que j'ai pu faire, le C avec GD et environ 20 fois plus rapide que le PHP. :-°
Par contre, j'ai toujours un problème de mémoire : 30% (de 2Go) utilisés pour une image de 13500*12000 (10.5 Mo en png) c'est un peu trop à mon goût, même si ça dure seulement un peu plus d'une minute.

Voici une perle découverte durant l'exploration de la fractale :
Image utilisateur

Je pense pas que le code d'une Mandelbort soit très intéressant, mais je le met toujours (pour la gestion des couleurs par exemple) :
#include <stdio.h>
#include <stdlib.h>
#include <gd.h>

int main() {
    const double x1 = -2.1;
    const double x2 = 0.6;
    double x = x1;
    const double y1 = -1.2;
    const double y2 = 1.2;
    double y = y1;
    double z1 = 0;
    double z2 = 0;
    int n = 0;
    const int zoom = 5000;
    const int iteration = 300;
    const double precision = (double)1/zoom;
    double tmp;
    gdImagePtr fractal = NULL;
    int colors[iteration];
    int noir;
    FILE *fichier = NULL;

    fractal = gdImageCreateTrueColor((x2-x1)*zoom, (y2-y1)*zoom);
    noir = gdImageColorAllocate(fractal, 0, 0, 0);
    for(n=1; n<iteration; n++){
        if(n<40)
            colors[n] = gdImageColorAllocate(fractal, 0, 0, n*255/40);
        else
            colors[n] = gdImageColorAllocate(fractal, (n-40)*255/(iteration-40), (n-40)*255/(iteration-40), 255);
    }


    for(x=x1; x<x2; x+=precision){
        for(y=y1; y<y2; y+=precision){
            z1 = 0;
            z2 = 0;
            n = 0;

            do{
                tmp = z1;
                z1 = z1*z1 - z2*z2 + x;
                z2 = 2*tmp*z2 + y;
                n++;
            } while((z1*z1+z2*z2)<4 && n<iteration);

            if(n != iteration)
                gdImageSetPixel(fractal, (x-x1)*zoom, (y-y1)*zoom, colors[n]);
        }
    }

    fichier = fopen("img.png", "w+");
    gdImagePng(fractal, fichier);
    fclose(fichier);


    return (EXIT_SUCCESS);
}
  • Partager sur Facebook
  • Partager sur Twitter
7 décembre 2009 à 13:32:46

Hello,

Je vais vous presenter mon dernier gadjet inutile :)

J'ai voulu m'interesser un peu a la representation des informations dans une images.
J'ai donc fait un truc tres simple. Je compte chaque apparition des caracteres contenus dans un fichier texte, et je les affiches ensuites dans une fenetre sous forme de cercles, avec une position et une couleur random, le rayon du cercle etant defini par le nombre d'apparition.

Image utilisateur


Code :
Ouai, j'avais envie de coder en python :)
#!/usr/local/bin/python2.5

import pygame
import random

def hello():
    print("Hello\nWelcome to alphabet_view. This prog analise a text file and make a graphic representation of the caracters presents in the file.\n")

def get_file_name():
    name = raw_input("Enter file name : ");
    return (name)

def read_file(file_name):
    f = open(file_name, "r")
    line = f.read()
    f.close()
    return line

def stat_lines(lines, var, val):
    c = 0
    while c < len(lines):
        c_list = 0
        present = 0
        while c_list < len(var):
            if var[c_list] == lines[c]:
                val[c_list] += 1
                present = 1
            c_list += 1
        if present == 0:
            var.append(lines[c])
            val.append(1)
        c += 1

def draw(window, var, val):
    c = 0
    text = pygame.font.SysFont("Arial", 12)
    for c in range(len(var)):
        x = random.randint(0, 800)
        y = random.randint(0, 600)
        pos = x, y
        color = random.randint(0x05, 0xffffff)
        text_area = text.render(var[c], True, (0xff, 0xff, 0xff))
        pygame.draw.circle(window, color, pos, val[c], 1)
        window.blit(text_area, pos)

def gui(var, val):
    pygame.init()
    pygame.font.init()
    run = 1
    size = width, height = 800, 600
    window = pygame.display.set_mode(size)
    pygame.display.set_caption("Alphabet viewer")
    draw(window, var, val)
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = 0
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    window.fill(0)
                    draw(window, var, val)
                elif event.key == pygame.K_r:
                    draw(window, var, val)

        pygame.display.flip()
    pygame.font.quit()
    pygame.display.quit()

hello()
file_name = get_file_name()
lines = read_file(file_name)
var = []
val   = []
dic = stat_lines(lines, var, val)
gui(var, val)
  • Partager sur Facebook
  • Partager sur Twitter
Découvrez un petit jeu Android bien sympa : http://www.siteduzero.com/forum/sujet/appli-jeu-android-cube-racer
7 décembre 2009 à 16:43:18

Commentaire sur ton code :

Coder dans un autre langage, c'est bien, mais il faut essayer d'être un peu idiomatique, respecter le style du langage, et ne pas faire comme si tu faisais du C.

Ton code python n'est pas très joli :
- les itérations du style for i in len(foo) sont à bannir, on utilise for elem in foo. Si tu veux itérer sur deux listes à la fois : for k, i in zip(var, val)
- Python a un GC, pas besoin d'allouer tes structures à l'avance : li = []; foo(li) est inutile et nuit à la clarté de ton code (on pense que li, puisqu'elle est passée en paramètre, contient une valeur intéressante). Alloue ta liste à l'intérieur de ta fonction et pas en dehors.

De plus, tu n'as pas tenu compte des considérations algorithmiques "de base" : ta méthode de décompte des occurences est très lente (recherche linéaire à chaque fois), pour ce genre de choses il faut utiliser une structure à accès arbitraire, comme un tableau, ou un dictionnaire en Python.

Voici le code un peu nettoyé (et encore, je ne fais pas de Python; un pythonneux trouvera certainement des choses à améliorer) :
import pygame
import random

def hello():
    print("Hello\nWelcome to alphabet_view. "
          "This prog analise a text file and "
          "make a graphic representation of "
          "the caracters presents in the file.\n")

def get_file_name():
    name = raw_input("Enter file name : ");
    return (name)

def read_file(file_name):
    f = open(file_name, "r")
    line = f.read()
    f.close()
    return line

def gather_stats(lines):
    stats = dict()
    for c in lines:
        stats[c] = stats.get(c, 0) + 1
    return stats

def draw(window, stats, size):
    text = pygame.font.SysFont("Arial", 12)
    for key, occurences in stats.iteritems():
        width, height = size
        x = random.randint(0, width)
        y = random.randint(0, height)
        pos = x, y
        color = random.randint(0x05, 0xffffff)
        text_area = text.render(key, True, (0xff, 0xff, 0xff))
        pygame.draw.circle(window, color, pos, occurences, 1)
        window.blit(text_area, pos)

def gui(stats):
    pygame.init()
    pygame.font.init()
    run = 1
    size = 800, 600
    window = pygame.display.set_mode(size)
    pygame.display.set_caption("Alphabet viewer")
    def display(): draw(window, stats, size)
    display()
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = 0
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    window.fill(0)
                    display()
                elif event.key == pygame.K_r:
                    display()
        pygame.display.flip()
    pygame.font.quit()
    pygame.display.quit()

def main():
    hello()
    file_name = get_file_name()
    lines = read_file(file_name)
    stats = gather_stats(lines)
    gui(stats)

main()


Une fois ces modifications effectuées, on peut (très) facilement modifier ton programme pour prendre en compte les mots du texte, plutôt que des lettres isolées :
for w in re.findall('\w+', lines):
        stats[w] = stats.get(w, 0) + 1


Exemple en prenant le code source lui-même :
Image utilisateur

Ce n'est pas très spectaculaire puisque sur un texte aussi court, la plupart des mots reviennent une seule fois, mais on obtient quand même des résultats plus intéressants (qui en disent plus sur la structure du texte : une fois la langue fixée, la répartition des fréquences des lettres ne change quasiment pas, alors que celle des mots dépend du champ lexical du texte). En particulier on observe que "pygame" revient le plus souvent (rond bleu clair en bas).

Il y a encore du travail à fournir pour obtenir quelque chose de vraiment amusant, mais c'est déjà un bon début (ce que Vladimir a fait). Dans quelles directions envisages-tu de faire évoluer ton truc ?
J'ai pensé à quelque chose, si ça t'intéresse : ça pourrait être intéressant de regrouper entre eux les mots "proches" (peu de lettres de différence). Soit seulement regrouper à l'affichage, soit carrément mettre leurs occurences en commun. Ça aurait des effets amusants, mais aussi des effets utiles comme la mise en commun des itérateurs mono-lettre ("i", "j", "k", peut être intéressant quand on analyse le code d'un programme) ou de mots ayant la même racine dans un texte.
La question de regrouper les choses proches dans un ensemble de données est intéressante et plutôt amusante, et il existe aussi des algorithmes bien connus (chercher "clustering").
  • Partager sur Facebook
  • Partager sur Twitter
8 décembre 2009 à 13:30:22

Merci d'avoir commente mon code.
J'essairais de tenir compte de tes conseils pour mes futures aventures en python ;)

Initialement, je n'avais pas prevu de faire evoluer ce code.
J'ai fait ce mini-projet pour decouvrir python (c'etait mon premier code en python).

J'essairais selon le temps et ma motivation de regrouper les mots proches en utilisant leur occurrences.
  • Partager sur Facebook
  • Partager sur Twitter
Découvrez un petit jeu Android bien sympa : http://www.siteduzero.com/forum/sujet/appli-jeu-android-cube-racer
11 décembre 2009 à 23:55:19

Hi again :)

J'ai un petit peu cherché du coté du buddhabrot, et voici ce qu'il en est ressorti :

Image utilisateur

En modifiant un peu la formule :
Image utilisateur

Puis :
Image utilisateur

Et :
Image utilisateur



Le code est dispo ici :
http://vlad.washere.free.fr/src/CPP/buddhabrot.rar
  • Partager sur Facebook
  • Partager sur Twitter
Découvrez un petit jeu Android bien sympa : http://www.siteduzero.com/forum/sujet/appli-jeu-android-cube-racer
12 décembre 2009 à 14:38:54

@Yannshu : superbe ;)
Personnellement voila mes deux premiers essais (pas très originaux, superformula le lien est en première page du topic) :

Image utilisateur


Image utilisateur


<?php
	header('Content-type: image/png');

	$image = imagecreate(256, 256);
	$x0 = 127;
	$y0 = 127;
	
	$w = imagecolorallocate($image, 255, 255, 255);
	$c = imagecolorallocate($image, 128, 128, 255);
	
	//les paramètres que l'ont peut/doit modifier pour obtenir des résultats différents
	$a = 1; $b = 1;
	$m = 7; $n1 = 5; $n2 = 7; $n3 = 42; 
	
	for($i = 0; $i < 360; $i += .01) {
		$phi = deg2rad($i);
		$r = pow(
				pow(
					abs(
						cos($m * $phi / 4) / $a
					),
					$n2
				) + pow(
					abs(
						sin($m * $phi / 4) / $b
					),
					$n3
				),
				-1 / $n1
				);
		
		$x = $r * cos($phi);
		$y = $r * sin($phi);		

		imagesetpixel($image, $x * 50 + $x0, $y * 50 + $y0, $c);
	}

	//imagepng($image, '.png');
	imagepng($image);
?>


A propos quelqu'un aurait-il une idée pour réduire l'aliasing ? :)
  • Partager sur Facebook
  • Partager sur Twitter
12 décembre 2009 à 14:59:04

Citation

A propos quelqu'un aurait-il une idée pour réduire l'aliasing ? :)



Tu as plusieurs méthodes classiques :
- utiliser une bibliothèque de dessin qui propose déjà de l'antialiasing
- (ou bien) ajouter un petit flou à ton image (par exemple chaque pixel devient la moyenne de sa composante, et d'un quart de la composante de chacun de ses quatres voisins)
- (ou bien) générer une image plus grande (par exemple 2*largeur 2*hauteur), puis la redimensionner intelligemment (par exemple en faisant une moyenne, cf. idée du flou)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
12 décembre 2009 à 15:15:47

Contre l'antialiassing, il y a une fonction toute faite : http://fr.php.net/manual/fr/function.imageantialias.php
  • Partager sur Facebook
  • Partager sur Twitter
12 décembre 2009 à 16:12:04

@bluestrom : merci, je pense que le plus simple est de créer une image deux fois plus grande.

@berdes1 : j'ai essayé mais je pense que ça ne marche que si tu traces une ligne, or dans le cas présent je trace point par point.

Toujours dans le classique j'en ai profiter pour faire la fameuse courbe du dragon : ici (D(15), le départ et l'arrivée sont notées en rouge).


<?php
	header('Content-type: image/png');

	$size = 1024;

	$image = imagecreate(1024, 1024);
	
	$w = imagecolorallocate($image, 255, 255, 255);
	$c = imagecolorallocate($image, 128, 128, 255);
	$r = imagecolorallocate($image, 255, 0, 0);
	
	function D($n) {
		if($n == 0) {
			return 'Fa';
		}
		
		else {
			$Dn_1 = D($n - 1);
			
			$res = str_replace('a', 'ARBFR', $Dn_1);
			$res = str_replace('b', 'LFaLb', $res);
			$res = strtolower($res);
			
			return $res;
		}
	}

	$start_x = 640; $start_y = 384;
	$x = $start_x; $y = $start_y;
	$x_way = 0; $y_way = 1;
	
	$D = D(15);
	
	for($i = 0, $l = strlen($D); $i < $l; $i++) {
		switch($D[$i]) {
			case 'f': //on avance de 3 pixels (histoire de bien voir le chemin et non pas d'avoir un paté)
				$tmp_x = $x; $tmp_y = $y;
				if($x_way != 0) {
					$x = $x_way == 1 ? $x + 3 : $x - 3;
				}
					
				else {
					$y = $y_way == 1 ? $y + 3 : $y - 3;
				}
				imageline($image, $x, $y, $tmp_x, $tmp_y, $c);
				break;
			
			case 'l':
				if($x_way != 0) {
					$y_way = $x_way == 1 ? 1 : -1;
					$x_way = 0;
				}
				
				else {
					$x_way = $y_way == 1 ? -1 : 1;
					$y_way = 0;
				}
				break;
			
			case 'r':
				if($x_way != 0) {
					$y_way = $x_way == 1 ? -1 : 1;
					$x_way = 0;
				}
				
				else {
					$x_way = $y_way == 1 ? 1 : -1;
					$y_way = 0;
				}
				break;
			
			default:
				break;
		};
	}
	
	imagefilledellipse($image, $start_x, $start_y / 2, 3, 3, $r);
	imagefilledellipse($image, $x, $y / 2, 3, 3, $r);

	imagecolortransparent($image, $w);
	//imagepng($image, 'dragon.png');
	imagepng($image);
?>



Edit :
Image utilisateur
Image utilisateur
Image utilisateur
Image utilisateur

Dans l'ordre Hilbert, un zoom sur Mandelbrot, les deux derniers sont des "trucs" qui sont sortis d'expérimentations avec le L-System (j'aime bien le dernier :))
  • Partager sur Facebook
  • Partager sur Twitter
13 décembre 2009 à 12:10:13

Salut,

J'ai fait le triangle de Sierpinski en Delphi grâce au code php de souCaline qui se trouve ici
Image utilisateur

EDIT : Je viens de voir qu'un topic était fait exprès pour les triangles de Sierpinski donc je met juste un lien... ICI
  • Partager sur Facebook
  • Partager sur Twitter
Réviser avec simplicité votre vocabulaire avec Revisuic. Inscrivez-vous sur Studyuik et gérez vos données scolaire !
13 décembre 2009 à 14:37:34

Un code complétement refactorisé pour les L-System :

<?php
	function LSystem($s) {
		if(!isset($s['w']) || !isset($s['h']) || !isset($s['axiom']) || !isset($s['replace']) || !isset($s['order']) || isset($s['order']) < 0) {
			return;
		}
		
		//récupère/définit tout les paramètres
		$x       = isset($s['x'])     ? $s['x']     : 0;
		$y       = isset($s['y'])     ? $s['y']     : 0;
		$step    = isset($s['step'])  ? $s['step']  : 1;
		$angle   = isset($s['angle']) ? $s['angle'] : 90;
		$axiom   = $s['axiom'];
		$order   = $s['order'];
		$replace = $s['replace'];
		$w       = $s['w'];
		$h       = $s['h'];

		$str = $axiom;
		
		$lengths = array();
		foreach($replace as $key => $value) {
			$lengths[$key] = strlen($value);
		}

		for($i = $order; $i > 0; $i--) { // /!\ génère la chaîne (si on veut remplacer des caractères qui ne sont pas des lettres il faut modifier la fonction /!\
			$str = strtolower($str);
			
			foreach($replace as $key => $value) {
				$str = str_replace(strtolower($key), strtoupper($value), $str);
			}
		}
		$str = strtolower($str);
		
		$image = imagecreatetruecolor($w, $h);
		imagecolortransparent($image, imagecolorallocate($image, 0, 0, 0));
		imageantialias($image, true);
		
		if(isset($s['color'])) {
			$color = imagecolorallocate($image, $s['color'][0], $s['color'][1], $s['color'][2]);
		}
		
		else {
			$color = imagecolorallocate($image, 255, 128, 128);
		}
		
		$prevx = $x; $prevy = $y; //valeur qui serviront lors de la rencontre de '[' et de ']'
		$angle = deg2rad($angle);
		$dir   = $angle;
		
		//echo $str . '<br />';
		
		for($i = 0, $l = strlen($str); $i < $l; $i++) {
			switch($str[$i]) {
				case 'f': //avance et trace le chemin
					$nextx = $x + $step * cos($dir);
					$nexty = $y + $step * sin($dir);
					imageline($image, $x, $y, $nextx, $nexty, $color);
					$x = $nextx;
					$y = $nexty;
					//echo '(' . $x . ', ' . $y . ')<br />';
					break;
				
				case 'g': //avance sans tracer le chemin
					$x = $x + $step * cos($dir);
					$y = $y + $step * sin($dir);
					break;
				
				case '+': //on augment l'angle
					$dir += $angle;
					break;
				
				case '-':
					$dir -= $angle;
					break;
				
				case '[': //sauve l'état courant
					$prevx = $x;
					$prevy = $y;
					break;
				
				case ']': //restaure cet état
					$x = $prevx;
					$y = $prevy;
					break;
				
				default:
					break;			
			};
		}

		return $image;
	}
?>


Du coup le code est générique et plutôt simple d'utilisation par exemple pour représenter le dernier exemple de cette page :
Image utilisateur

Le code et le suivant :
<?php
	$image = LSystem(array(
		'w'       => 256,
		'h'       => 256,
		'x'       => 192,
		'y'       => 64,
		'step'    => 3,
		'angle'   => 90,
		'axiom'   => 'f+f+f+f',
		'order'   => 2,
		'replace' => array(
			'f'   => 'F+g-FF+F+FF+Fg+FF-g+FF-F-FF-Fg-FFF',
			'g'   => 'gggggg'
		),
		'color'   => array(100, 150, 200)
	));
?>


D'ailleurs je ne suis pas très habitué au PHP, est-ce que c'est courant de passer des tableaux associatifs dans ce langage ? En JS par exemple ça l'est mais pour le PHP j'en ai aucune idée.
  • Partager sur Facebook
  • Partager sur Twitter
27 février 2010 à 16:06:54

Hi again (ca fesait longtemps ) ;)

Voici pour vous un attracteur de Lorenz fraichement codé.
Image utilisateur
Image utilisateur

Pour plus d'info sur ce que c'est :
http://fr.wikipedia.org/wiki/Th%C3%A9orie_du_chaos
http://fr.wikipedia.org/wiki/Attracteur
http://fr.wikipedia.org/wiki/Syst%C3%A [...] que_de_Lorenz
http://fr.wikipedia.org/wiki/Attracteur_de_Lorenz


Le code est dispo ici:
http://vlad.washere.free.fr/src/C/LorenzAttractor.zip
(Pas la peine de faire de me remarque sur celui-ci, je sais très bien ce que je pourrais faire pour l'améliorer, mais j'ai profondément la flemme de le faire.)
  • Partager sur Facebook
  • Partager sur Twitter
Découvrez un petit jeu Android bien sympa : http://www.siteduzero.com/forum/sujet/appli-jeu-android-cube-racer
27 février 2010 à 18:57:33

Citation : Yannshu


Voici pour vous un attracteur de Lorenz fraichement codé.



:waw: Magnifique...
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
1 mars 2010 à 19:08:37

Un essai de Buddahbrot pas très concluant.

(le résultat doit être à peu près aussi beau que la source ^^)

#include <cmath>
#include <ctime>
#include <iostream>
#include <vector>

#include "EasyBMP.h"

using namespace std;

int main(int argc, char *argv[]) {
	int width = 1024, height = 1024;
	BMP image;

	image.SetSize(width, height);
	image.SetBitDepth(24);

	double re_min = -2, re_max = 1,
	       im_min = -1.5, im_max = 1.5;
	double re_f = (re_max - re_min) / (width - 1),
	       im_f = (im_max - im_min) / (height - 1);

	int maxIter = 8192, max = 10000000;
	vector< vector< int > > arr(width, vector< int >(height, 0));
	srand(time(NULL));

	for(int y = 0; y < max; ++y) {
		double c_im = im_min + abs(im_max - im_min) * rand() / RAND_MAX;

		double c_re = re_min + abs(re_max - re_min) * rand() / RAND_MAX;
		double Z_re = c_re, Z_im = c_im;
		bool inside = true;
		int k = 0;

		for(; k < maxIter; ++k) {
			double Z_re2 = Z_re * Z_re, Z_im2 = Z_im * Z_im;
			Z_im = 2 * Z_re * Z_im + c_im;

			Z_re = Z_re2 - Z_im2 + c_re;

			double a = Z_re * width / (abs(re_min) + abs(re_max)) + width / 2, b = Z_im * height / (abs(im_min) + abs(im_max)) + height / 2;

			if(fmod(a, 1) < .5) {
				a = floor(a);
			}

			else {
				a = ceil(a);
			}

			if(fmod(b, 1) < .5) {
				b = floor(b);
			}

			else {
				b = ceil(b);
			}

			if(a >= 0 && a < width && b >= 0 && b < height) {
				arr[(int)a][(int)b] += 1;
			}


			Z_re = Z_re2 - Z_im2 + c_re;

			if(Z_re2 + Z_im2 > 2) break;
		}
	}

	int sup = 0;

	for(int i = 0; i < width; ++i) {
		for(int j = 0; j < height; ++j) {
			if(arr[i][j] > sup) {
				sup = arr[i][j];
			}
		}
	}

	for(int i = 0; i < width; ++i) {
		for(int j = 0; j < height; ++j) {
			double r = pow(1. * (sup - arr[i][j]) / sup, 1. / 3.3);
			image(i, j)->Red = 0. + 127. * r;
			image(i, j)->Green = 0. + 191. * r;
			image(i, j)->Blue = 0. + 255. * r;
		}
	}
	if(argc >= 2) {
		image.WriteToFile(argv[1]);
	}

	else {
		image.WriteToFile("test.bmp");
	}

	return 0;
}


Edit : un essai de dithering (déjà présenté dans ce topic) avec Lenna :

Image utilisateur Clic!

#include <iostream>
#include <vector>

#include "EasyBMP.h"

using namespace std;

int main(int argc, char *argv[]) {
	if(argc < 3) {
		cout << "Need 2 args : <sourcefile> <newfile>." << endl;
		return 0;
	}

	BMP image;
	image.ReadFromFile(argv[1]);
	int w = image.TellWidth(), h = image.TellHeight();
	vector< vector< double > > arr(w, vector<double>(h));

	for(int j = 0; j < h; ++j) {// Grayscale
		for(int i = 0; i < w; ++i) {
			arr[i][j] = .2125 * image(i, j)->Red + .7154 * image(i, j)->Green + .0721 * image(i, j)->Blue;
		}
	}

	for(int j = 0; j < h; ++j) {// Dithering
		for(int i = 1; i < w; ++i) {
			double op = arr[i][j], np = op < 127.5 ? 0 : 255, err = (op - np) / 16.;

			arr[i][j] = np;
			if(i + 1 < w)              arr[i + 1][j] += err * 7;
			if(i - 1 > 0 && j + 1 < h) arr[i - 1][j + 1] += err * 3;
			if(j + 1 < h)              arr[i][j + 1] += err * 5;
			if(i + 1 < w && j + 1 < h) arr[i + 1][j + 1] += err * 1;
		}
	}

	for(int j = 0; j < h; ++j) {
		for(int i = 1; i < w; ++i) {
			int p = static_cast<int>(arr[i][j]);
			image(i, j)->Red = p;
			image(i, j)->Green = p;
			image(i, j)->Blue = p;
		}
	}

	image.WriteToFile(argv[2]);
	
	return 0;
}
  • Partager sur Facebook
  • Partager sur Twitter
5 mars 2010 à 16:16:40

Bonjour :)
Apres avoir vu les derniers posts, j'ai eu envie de continue mon programme de flames fractales ^^
Les fractales son maintenant lues depuis un fichiers ou on peut definir le gamma, 3 coefficients pour x et y par fonction (x = coeff1*x + coeff2*y + coeff3 , y = coeff4*y + coeff5*x + coeff6 ) le RGB de chaque fonction, le poids des fonctions (sur mille) et une transformation pour chaque fonction (vous pouvez choisir entre 27 transormations, listees dans le code)
Voila un fichier d'example (triangle de Sierpinski):
4     -> GAMMA
0.5   -> COEFF1
0     -> COEFF2
0     -> COEFF3
0.5   -> COEFF4
0     -> COEFF5
0     -> COEFF6
255   -> Rouge
56    -> Vert
82    -> Bleu
333   -> Poids
linear -> Style (linear=aucun :p)
0.5   -> COEFF1
0     -> COEFF2
0.25  -> ...
0.5
0.0
0.433012702 ( = 0.5*sqrt(3)/2; )
56
255
23
333
linear
0.5
0.0
0.5
0.5
0
0
56
77
255
333
linear

Ici, on a trois fonctions avec des poids egal.
De plus, j'ai implemente un systeme d'animation (le programme choisit un coefficient au debut et il la change au cours de l'execution et les iterations sont augmentes au cours de l'execution)
Edit:
Avec la nouvelle version(lien de telechargement change), vous pouvez aussi fiare des arguments variables, c'est a dire faire linear:ex ou 0.3525:1 et le programme choisira un des arguments au hazard (vous pouvez en faire autant que vous voulez). Ce systeme marche avec touts les arguments sauf le gamma et le poids(vous n'aurez pas d'erreur pour ce dernier, mais le premier argument comptera toujours).
Le programme (executable windows compile statiquement, editez le fichier flame pour changer l'animation) 257KB, format RAR: Telechargement
Enfin, le code :) (comme toujours, C++ et SFML ^^ )

main.cpp
#include "flame.h"

int main(int argc, char *argv[])
{
    sf::Clock time;
    float lastTime = 0;
    sf::RenderWindow app(sf::VideoMode(800, 600, 32), "Flame fractal");

    Flame test("flame");

    bool animated = true;

    while(app.IsOpened())
    {
        sf::Event Event;
        while(app.GetEvent(Event))
        {
            if(Event.Type == sf::Event::Closed)
            {
                app.Close();
            }
            else if(Event.Type == sf::Event::KeyPressed)
            {
                switch(Event.Key.Code)
                {
                    case sf::Key::A:
                        animated = !animated;
                        time.Reset();
                    break;
                    case sf::Key::Escape:
                        app.Close();
                    break;
                    default:
                    break;
                }
            }
        }
        app.Clear();
        if(animated)
        {
            if(time.GetElapsedTime() - lastTime >= 0.08)
            {
                lastTime = time.GetElapsedTime();
                test.change();
            }
            test.render((int)(time.GetElapsedTime()*5000));
        }
        test.Draw(app);
        app.Display();
    }

    return 0;
}


flame.h
#ifndef FLAME_H
#define FLAME_H
#include <SFML/Graphics.hpp>
#include <vector>
#include <iostream>
#include <sstream>
#include <fstream>

class Flame
{
    public:
        Flame();
        Flame(const std::string& fileName);
        void openFile(const std::string& fileName);
        void render(int maxIt);
        void Draw(sf::RenderWindow& app);
        void change();
    protected:
        double gamma;
        int func;
        int coeff1;
        int coeff2;
        bool add;
        sf::Sprite sprite;
        sf::Image flame;
        std::vector< std::vector< std::vector<double> > > params;
};

#endif//FLAME_H


flame.cpp
<secret>
#include "flame.h"

Flame::Flame()
{
    params = std::vector< std::vector< std::vector<double> > >();
    flame.Create(800,600,sf::Color::Black);
}

Flame::Flame(const std::string& fileName)
{
    Flame();
    openFile(fileName);
}

void Flame::openFile(const std::string& fileName)
{
    std::ifstream file(fileName.c_str(), std::ios::in);
    if(file)
    {
        params.clear();

        std::string gammaStr;
        getline(file,gammaStr);
        std::istringstream stmg;
        stmg.str(gammaStr);
        stmg >> gamma;

        int lines = 0;
        int c = 0;
        std::string tmp;
        std::vector< std::vector<std::string> > lineTab;
        std::vector<std::string> lineV;
        while(getline(file,tmp))
        {
            lineV.push_back(tmp);
            c++;
            lines++;
            if(c==11)
            {
                lineTab.push_back(lineV);
                lineV.clear();
                c = 0;
            }
        }

        if(lines%11 == 0)
        {
            int num = lines/11;
            for(int i = 0; i < num; i++)
            {
                std::vector< std::vector<double> > tmpV;
                for(int u = 0; u < 10; u++)
                {
                    std::vector<double> numTmp;

                    std::string word;
                    std::stringstream stream(lineTab[i][u]);
                    while(getline(stream,word,':'))
                    {
                        double numT;
                        std::istringstream stm;
                        stm.str(word);
                        stm >> numT;
                        numTmp.push_back(numT);
                    }

                    tmpV.push_back(numTmp);
                }
                int u = 9;

                std::string word;
                std::stringstream stream(lineTab[i][u+1]);
                std::vector<double> numTmp;
                while(getline(stream,word,':'))
                {
                    double numT = 0;
                    if(word == "linear")
                    {
                        numT = 0;
                    }
                    else if(word == "cross")
                    {
                        numT = 1;
                    }
                    else if(word == "tangent")
                    {
                        numT = 2;
                    }
                    else if(word == "cylinder")
                    {
                        numT = 3;
                    }
                    else if(word == "bubble")
                    {
                        numT = 4;
                    }
                    else if(word == "rings")
                    {
                        numT = 5;
                    }
                    else if(word == "power")
                    {
                        numT = 6;
                    }
                    else if(word == "exponential")
                    {
                        numT = 7;
                    }
                    else if(word == "popcorn")
                    {
                        numT = 8;
                    }
                    else if(word == "eyefish")
                    {
                        numT = 9;
                    }
                    else if(word == "fisheye")
                    {
                        numT = 10;
                    }
                    else if(word == "bent")
                    {
                        numT = 11;
                    }
                    else if(word == "julia")
                    {
                        numT = 12;
                    }
                    else if(word == "ex")
                    {
                        numT = 13;
                    }
                    else if(word == "diamond")
                    {
                        numT = 14;
                    }
                    else if(word == "spiral")
                    {
                        numT = 15;
                    }
                    else if(word == "fan1")
                    {
                        numT = 16;
                    }
                    else if(word == "cosine")
                    {
                        numT = 17;
                    }
                    else if(word == "swirl")
                    {
                        numT = 18;
                    }
                    else if(word == "spherical")
                    {
                        numT = 19;
                    }
                    else if(word == "sinusoidal")
                    {
                        numT = 20;
                    }
                    else if(word == "heart")
                    {
                        numT = 21;
                    }
                    else if(word == "disc")
                    {
                        numT = 22;
                    }
                    else if(word == "hyperbolic")
                    {
                        numT = 23;
                    }
                    else if(word == "horseshoe2")
                    {
                        numT = 24;
                    }
                    else if(word == "hankerchief")
                    {
                        numT = 25;
                    }
                    else if(word == "polar")
                    {
                        numT = 26;
                    }
                    else if(word == "horseshoe1")
                    {
                        numT = 27;
                    }
                    numTmp.push_back(numT);
                }
                tmpV.push_back(numTmp);

                params.push_back(tmpV);
            }
        }
    }
    file.close();
    add = true;
    func = -1;
    coeff1 = -1;
    coeff2 = -1;
}

void Flame::change()
{
    if(func == -1 || coeff1 == -1 || coeff2 == -1)
    {
        if(params.size() > 0)
        {
            func = sf::Randomizer::Random(0,params.size()-1);
            coeff1 = sf::Randomizer::Random(0,5);
            coeff2 = sf::Randomizer::Random(0,params[func][coeff1].size()-1);

            if(sf::Randomizer::Random(0,1) == 0)
            {
                add = true;
            }
            else
            {
                add = false;
            }
        }
    }
    else
    {
        if(add)
        {
            params[func][coeff1][coeff2] += 0.02;
        }
        else
        {
            params[func][coeff1][coeff2] -= 0.02;
        }
    }
}

void Flame::render(int maxIt)
{
    flame.Create(800,600,sf::Color::Black);
    std::vector< std::vector<unsigned int> > frequency(flame.GetWidth(),std::vector<unsigned int>(flame.GetHeight(),0));
    unsigned int max_frequency = 0;

    float x = sf::Randomizer::Random(0,flame.GetWidth());
    float y = sf::Randomizer::Random(0,flame.GetHeight());
    int cRed = sf::Randomizer::Random(0,255);
    int cGreen = sf::Randomizer::Random(0,255);
    int cBlue = sf::Randomizer::Random(0,255);

    float c1 = (flame.GetWidth()/2);
    float c2 = (flame.GetHeight()/2);

    x = (x-c1)/c1;
    y = (y-c2)/c2;

    for(int i = 0; i <= maxIt; i++)
    {
        int CiRed = 0;
        int CiGreen = 0;
        int CiBlue = 0;

        double x2 = x, y2 = y;
        //params[n][9] = weight
        int n = 0;
        int f = sf::Randomizer::Random(1,1000);
        double sum = 1;
        for(unsigned int u = 0; u < params.size(); u++)
        {
            sum += params[u][9][0];
            if(f >= sum-params[u][9][0] && f < sum)
            {
                n = u;
            }
        }

        {
        int rand1 = sf::Randomizer::Random(0,params[n][0].size()-1);
        int rand2 = sf::Randomizer::Random(0,params[n][1].size()-1);
        int rand3 = sf::Randomizer::Random(0,params[n][2].size()-1);

        x = params[n][0][rand1]*x2+params[n][1][rand2]*y2+params[n][2][rand3];
        }

        {
        int rand1 = sf::Randomizer::Random(0,params[n][3].size()-1);
        int rand2 = sf::Randomizer::Random(0,params[n][4].size()-1);
        int rand3 = sf::Randomizer::Random(0,params[n][5].size()-1);

        y = params[n][3][rand1]*y2+params[n][4][rand2]*x2+params[n][5][rand3];
        }

        {
        int rand1 = sf::Randomizer::Random(0,params[n][6].size()-1);
        CiRed = (int)params[n][6][rand1];
        }

        {
        int rand1 = sf::Randomizer::Random(0,params[n][7].size()-1);
        CiGreen = (int)params[n][7][rand1];
        }

        {
        int rand1 = sf::Randomizer::Random(0,params[n][8].size()-1);
        CiBlue = (int)params[n][8][rand1];
        }

        cRed=(cRed+CiRed)/2;
        cGreen=(cGreen+CiGreen)/2;
        cBlue=(cBlue+CiBlue)/2;

        double cX = x;
        double cY = y;

        double theta = atan(cX/cY);
        double r = sqrt(cX*cX+cY*cY);

        int rand1 = sf::Randomizer::Random(0,params[n][10].size()-1);
        if(params[n][10][rand1] == 1)
        {
            //CROSS
            x = sqrt(1/pow((pow(cX,2)-pow(cY,2)),2))*cX;
            y = sqrt(1/pow((pow(cX,2)-pow(cY,2)),2))*cY;
        }
        else if(params[n][10][rand1] == 2)
        {
            //TANGENT
            x = sin(cX)/cos(cY);
            y = tan(cY);
        }
        else if(params[n][10][rand1] == 3)
        {
            //CYLINDER
            x = sin(cX);
            y = cY;
        }
        else if(params[n][10][rand1] == 4)
        {
            //BUBBLE
            x = 4/(pow(r,2)+4)*cX;
            y = 4/(pow(r,2)+4)*cY;
        }
        else if(params[n][10][rand1] == 5)
        {
            //RINGS
            double c = 1;
            x = (int(r+pow(c,2))%int(2*pow(c,2)) - pow(c,2) + r*(1-pow(c,2)))*cos(theta);
            y = (int(r+pow(c,2))%int(2*pow(c,2)) - pow(c,2) + r*(1-pow(c,2)))*sin(theta);
        }
        else if(params[n][10][rand1] == 6)
        {
            //POWER
            x = pow(r,sin(theta))*cos(theta);
            y = pow(r,sin(theta))*sin(theta);
        }
        else if(params[n][10][rand1] == 7)
        {
            //EXPONENTIAL
            x = exp(cX-1)*cos(M_PI*cY);
            y = exp(cX-1)*sin(M_PI*cY);
        }
        else if(params[n][10][rand1] == 8)
        {
            //POPCORN
            double c = 0.1, f = 0.34;
            x = cX + c*sin(tan(3*cY));
            y = cY + f*sin(tan(3*cX));
        }
        else if(params[n][10][rand1] == 9)
        {
            //EYEFISH
            x = (2/(r+1))*cX;
            y = (2/(r+1))*cY;
        }
        else if(params[n][10][rand1] == 10)
        {
            //FISHEYE
            x = (2/(r+1))*cY;
            y = (2/(r+1))*cX;
        }
        else if(params[n][10][rand1] == 11)
        {
            //BENT
            if(cX >= 0 && y >= 0)
            {
                x = cX, y = cY;
            }
            else if(cX < 0 && y >= 0)
            {
                x = 2*cX, y = cY;
            }
            else if(cX >= 0 && cY < 0)
            {
                x = cX, y = cY/2;
            }
            else if(cX < 0 && cY < 0)
            {
                x = 2*cX, y = cY/2;
            }
        }
        else if(params[n][10][rand1] == 12)
        {
            //JULIA
            double omg = 0;
            x = sqrt(r)*cos(theta/2+omg);
            y = sqrt(r)*sin(theta/2+omg);
        }
        else if(params[n][10][rand1] == 13)
        {
            //EX
            double p0 = sin(theta+r);
            double p1 = cos(theta-r);
            x = r*(pow(p0,3)+pow(p1,3));
            y = r*(pow(p0,3)-pow(p1,3));
        }
        else if(params[n][10][rand1] == 14)
        {
            //DIAMOND
            x = sin(theta)*cos(r);
            y = cos(theta)*sin(r);
        }
        else if(params[n][10][rand1] == 15)
        {
            //SPIRAL
            x = (cos(theta)+sin(r))/r;
            y = (sin(theta)-cos(r))/r;
        }
        else if(params[n][10][rand1] == 16)
        {
            //FAN1

            float f = 1;
            float c = 16;
            float t = M_PI*c;
            if((int(theta+f)%int(t)) > t/2)
            {
                x = r*(cos(theta-t/2));
                y = r*(sin(theta-t/2));
            }
            else
            {
                x = r*(cos(theta+t/2));
                y = r*(sin(theta+t/2));
            }
        }
        else if(params[n][10][rand1] == 17)
        {
            //COSINE
            x = cos(M_PI*cX)*cosh(cY);
            y = -sin(M_PI*cX)*sinh(cY);
        }
        else if(params[n][10][rand1] == 18)
        {
            //SWIRL
            x = cX*sin(r*r)-cY*cos(r*r);
            y = cX*cos(r*r)+cY*sin(r*r);
        }
        else if(params[n][10][rand1] == 19)
        {
            //SPHERICAL
            x = cX/r*r;
            y = cY/r*r;
        }
        else if(params[n][10][rand1] == 20)
        {
            //SINUSOIDAL
            x = sin(cX);
            y = sin(cY);
        }
        else if(params[n][10][rand1] == 21)
        {
            //HEART
            x = r*sin(theta*r);
            y = -r*cos(theta*r);
        }
        else if(params[n][10][rand1] == 22)
        {
            //DISC
            x = sin(M_PI*r)*theta/M_PI;
            y = cos(M_PI*r)*theta/M_PI;
        }
        else if(params[n][10][rand1] == 23)
        {
            //HYPERBOLIC
            x = sin(theta)/r;
            y = cos(theta)*r;
        }
        else if(params[n][10][rand1] == 24)
        {
            //HORSEHOE2
            x = r*cos(2*theta);
            y = r*sin(2*theta);
        }
        else if(params[n][10][rand1] == 25)
        {
            //HANKERCHIEF
            x = r*sin(theta+r);
            y = r*cos(theta-r);
        }
        else if(params[n][10][rand1] == 26)
        {
            //POLAR
            x = theta/M_PI;
            y = r-1;
        }
        else if(params[n][10][rand1] == 27)
        {
            //HORSEHOE1
            x = ((cX-cY)*(cX+cY))/r;
            y = (2*cY*cX)/r;
        }

        if(i>=20)
        {
            unsigned int nX = int((x*c1)+c1);
            unsigned int nY = int((y*c2)+c2);
            if(nX < flame.GetWidth() && nY < flame.GetHeight() && nX >= 0 && nY >= 0)
            {
                frequency[nX][nY]++;
                if(frequency[nX][nY] > max_frequency)
                {
                    max_frequency = frequency[nX][nY];
                }
                cRed *= pow(log(frequency[nX][nY])/log(max_frequency),1/gamma);
                cGreen *= pow(log(frequency[nX][nY])/log(max_frequency),1/gamma);
                cBlue *= pow(log(frequency[nX][nY])/log(max_frequency),1/gamma);
                flame.SetPixel(nX,nY,sf::Color(cRed,cGreen,cBlue));
            }
        }
    }
}

void Flame::Draw(sf::RenderWindow& app)
{
    sprite.SetImage(flame);
    app.Draw(sprite);
}

</secret>


PS: vous pouvez stopper et recommencer l'animation avec la touche 'a'
  • Partager sur Facebook
  • Partager sur Twitter
7 mars 2010 à 0:03:20

Bonjour à tous, toutes !

Voilà, pour ma part, un petit fractal amusant en python :

from turtle import *

def dessin(chaine,X,angle) :
    for i in range(len(chaine)) :
        if chaine[i]=='X' :
            forward(X)
        elif chaine[i] == '+' :
            right(angle)
        elif chaine[i] == '-' :
            left(angle)
        i+=i

def substitution(chaine):
    C2=''
    for i in range(len(chaine)) :
        if chaine[i]=='X' :
            C2=C2+'X--X+'
        else :
            C2=C2+chaine[i]
        i=i+1
    return C2
speed("fastest")
chaine='X'
for j in range(0,50) :
    dessin(chaine,2,120)
    chaine = substitution(chaine)
    print (chaine)

je vous laisse juger :-°
Bonne soirée :)

Pourkoisa
  • Partager sur Facebook
  • Partager sur Twitter
7 mars 2010 à 16:31:41

Citation : cerium50


Edit : un essai de dithering (déjà présenté dans ce topic) avec Lenna :



Intéressant !

Voici le même genre d'image en couleur (l'image de sortie est composée de huit couleurs, on effectue un traitement séparé sur chaque canal).

Image utilisateur

Code :
#include <SDL.h>
#include <stdlib.h>



#define SEUIL       127
#define filename    "lena_std.bmp"

/* Recupere la couleur d'un pixel - mode 32 bits */
Uint32 GetPixel(SDL_Surface *screen, int x, int y)
{
    Uint8 *p = (Uint8 *)screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
    return *(Uint32 *)p;
}

/* Dessine un pixel - mode 32 bits */
void setPixel(SDL_Surface *screen, int x, int y, Uint32 pixel)
{
    Uint8 *p = (Uint8 *)screen->pixels + y * screen->pitch + x * screen->format->BytesPerPixel;
    *(Uint32 *)p = pixel;
}

void tramage (SDL_Surface *screen)
{
    int x, y;
    unsigned i;
    double oldpixel, newpixel, quant_error, color;
    double *redArray = NULL, *greenArray = NULL, *blueArray = NULL;
    double* bmpChannels[3];
    Uint32 temp, pixel;
    Uint8 r, g, b;
    SDL_PixelFormat *fmt = screen->format;

    if (  (redArray = calloc(screen->h*screen->w, sizeof* redArray)) != NULL
            &&(greenArray = calloc(screen->h*screen->w, sizeof* greenArray)) != NULL
            &&(blueArray = calloc(screen->h*screen->w, sizeof* blueArray)) != NULL   )
    {
        SDL_LockSurface(screen);
        bmpChannels[0] = redArray;
        bmpChannels[1] = greenArray;
        bmpChannels[2] = blueArray;

        /* Stocke les canaux de l'image dans des tableaux dynamiques */
        for (y=0; y<screen->h; y++)
        {
            for (x=0; x<screen->w; x++)
            {
                pixel = GetPixel(screen, x, y);
                /* Get Red component */
                temp=pixel&fmt->Rmask; /* Isolate red component */
                temp=temp>>fmt->Rshift;/* Shift it down to 8-bit */
                temp=temp<<fmt->Rloss; /* Expand to a full 8-bit number */
                r=(Uint8)temp;
                /* Get Green component */
                temp=pixel&fmt->Gmask; /* Isolate green component */
                temp=temp>>fmt->Gshift;/* Shift it down to 8-bit */
                temp=temp<<fmt->Gloss; /* Expand to a full 8-bit number */
                g=(Uint8)temp;
                /* Get Blue component */
                temp=pixel&fmt->Bmask; /* Isolate blue component */
                temp=temp>>fmt->Bshift;/* Shift it down to 8-bit */
                temp=temp<<fmt->Bloss; /* Expand to a full 8-bit number */
                b=(Uint8)temp;

                *(redArray + x + y*screen->w) = r;
                *(greenArray + x + y*screen->w) = g;
                *(blueArray + x + y*screen->w) = b;
            }
        }
        /* dithering : Floyd-Steinberg algorithm */
        for (y=0; y<screen->h; y++)
        {
            for (x=0; x<screen->w; x++)
            {
                for (i=0; i<3; i++)
                {
                    oldpixel = *(bmpChannels[i] + x + y*screen->w);
                    newpixel = (oldpixel < SEUIL) ? 0 : 255;
                    quant_error = oldpixel - newpixel;
                    *(bmpChannels[i] + x + y*screen->w) = newpixel;
                    if (x<screen->w-1)
                        *(bmpChannels[i] + x+1 +  y*screen->w) += (7./16) * quant_error;
                    if (x>0 && y<screen->h-1)
                        *(bmpChannels[i] + x-1 + (y+1)*screen->w) += (3./16) * quant_error;
                    if (y<screen->h-1)
                        *(bmpChannels[i] + x + (y+1)*screen->w) += (5./16) * quant_error;
                    if (x<screen->w-1 && y<screen->h-1)
                        *(bmpChannels[i] + x+1 + (y+1)*screen->w) += (1./16) * quant_error;
                }
                /* applique sur l'ecran */
                color = SDL_MapRGB(fmt, *(bmpChannels[0] + x + y*screen->w), *(bmpChannels[1] + x + y*screen->w), *(bmpChannels[2] + x + y*screen->w));
                SetPixel(screen, x, y, color);
            }
        }

        SDL_UnlockSurface(screen);
        free(redArray),free(greenArray),free(blueArray);
    }
}

int main ( int argc, char** argv )
{
    unsigned done = 0;
    SDL_Surface *screen, *image;
    SDL_Event event;

    /*  initialise SDL video */
    if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "Unable to init SDL: %s\n", SDL_GetError() );
        return 1;
    }

    /*  make sure SDL cleans up before exit */
    atexit(SDL_Quit);

    /*  create a new window */
    image = SDL_LoadBMP(filename);
    screen = SDL_SetVideoMode(image->w, image->h, 32, SDL_HWSURFACE);
    SDL_BlitSurface(image, NULL, screen, NULL);
    SDL_Flip(screen);
    SDL_FreeSurface(image);

    /* affichage */

    SDL_Flip(screen);

    while (!done)
    {
        /* attente d'un evenement */
        SDL_WaitEvent(&event);
        /*  on traite l'evenement */
        switch (event.type)
        {
            /* fermeture de la fenetre */
        case SDL_QUIT:
            done = 1;
            break;

            /*  appui d'une touche */
        case SDL_KEYDOWN:
            switch (event.key.keysym.sym)
            {
            case SDLK_ESCAPE: /*  Touche Echap */
                done = 1;
                break;

            case SDLK_SPACE: /*  Touche Espace */
                tramage(screen);
                SDL_Flip(screen);
                SDL_SaveBMP(screen, "resultRGB.bmp");
                break;


            default:
                break;
            } /* fin switch (event.key.keysym.sym) */
            break;

        } /* fin switch (event.type) */
    } /* fin boucle evenementielle */

    return 0;
}


Il y a cependant un truc qui me turlupine : j'ai beau modifier la macro SEUIL, le résultat ne change pas...

Une idée ?

yoch
  • Partager sur Facebook
  • Partager sur Twitter
7 mars 2010 à 23:25:37

#Chryzode n°1
# Prk0s
from turtle import *
from math import *
shape('turtle')
up()
goto(0,-100)
down()
circle(100)
up()
goto(0,0)

def position (rayon) :
    reset()
    up()
    goto(0,-rayon)
    down()
    circle(rayon)
    up()
    goto(0,0)
    #A ce point,la tortue est au centre du cercle
#Il faut maintenant définir une règle pour tracer les points suivant une règle
def coordonee(nbpoint, position):
    up()
    goto(100*cos(position*pi/nbpoint), 100*sin(position*pi/nbpoint))
# Ceci permet d'aller n'importe ou sur le cercle
def chryz(rayon, nbpoint, ptdepart, div) :
    position(rayon)
    up()
    coordonee( nbpoint, ptdepart )
    down()
    i=ptdepart
    speed("fastest")
    while i<=(2*div)*nbpoint :
        up()
        goto(rayon*(cos((i*pi)/nbpoint)), (rayon*sin((i*pi)/nbpoint)))
        down()
        goto(rayon*cos(((i/div)*pi/nbpoint)), rayon* sin(((i/div)*pi/nbpoint)))
        
        i=i+1


Bonsoir !
Voilà un script que fais des CHRYZODES en python !
Pour l'instant, seuls certains types, ceux du type 1/n

chryz(rayon, nbpoint, ptdepart, div)


rayon = rayon du cerlce contenant le chryzode
nbpoint = nombre de points ( en gros, précision du dessin ). Je conseille 1/2 * rayon
ptdepart : mettez 0 pour commencer de la droite du cercle. Changez le pour orienter le chryzode...
div = la valeur de n pour avoir le chryzode représentant les divisions "1/n"

Il n'y a pas de couleur... mais le résultat est fidel à celui des sites sur le sujet :D

Enjoy ;)
  • Partager sur Facebook
  • Partager sur Twitter
8 mars 2010 à 2:57:21

Il y a quelques temps je m'étais mis dans la tête de trouver comment représenter simplement des constructions mathématiques en 3D. Et puis comme j'avais que ça sous la main, j'ai bricolé quelques trucs en javascript, plus ou moins inaboutis. Après m'être un peu inspiré de la simplicité d'un exemple fourni avec WinCaml (un script qui s'appelle "tores.ml" et qui génère des images de tore en 3D), j'ai fini par fabriquer un exemple en javascript plus ou moins dans l'air du temps : des tores imbriqués représentant une version plus ou moins personnelle du drapeau olympique. On peut faire tourner cet assemblage par les flèches du clavier ou à l'aide de la souris en maintenant le clic appuyé, et changer les paramètres de la représentation (enfin, faites attention, le javascript n'étant pas le langage le plus adapté pour ça, un nombre de calculs élevés occupera pas mal votre navigateur ; ne vous attendez pas non plus à un mouvement super fluide de manière générale).

Vous trouverez facilement le code javascript dans la source de la page en question : il s'agit du fichier perspective.js, dont voici, en un peu délesté des parties inutiles, le cœur :

var points = new Array();
var theta = 0;
var phi = 0;

function scalaire(p, q)
{
	return (p[0]*q[0] + p[1]*q[1] + p[2]*q[2]);
}

function plot(p, couleur)
{
	var point = document.createElement('div');
	point.className = "point";
	element.appendChild(point);

	points.push([point, p, couleur]);
}

function afficher(base)
{
	var orx = element_real_offsets[0] + element.clientLeft + element.clientWidth/2;
	var ory = element_real_offsets[1] + element.clientTop + element.clientHeight/2;
	var ux = 40;
	var uy = 40;
	var k = base[0];
	var u = base[1];
	var v = base[2];

	/* Les deux fonctions perspective et distance sont utilisées sans le dire et dans une tentative d'accélération de la rapidité pour effectuer les calculs dans la boucle qui suit :
distance, qui renvoie un nombre exprimant l'éloignement du point par rapport au point de vue, est utilisée pour calculer le paramètre c,
et perspective, qui renvoie la projection sur un plan plus ou moins affine d'un point dans l'espace, est utilisé pour calculer les style.top et style.left des points

	function perspective(p)
	{
		return [orx + scalaire(p, base[1])*ux, ory - scalaire(p, base[2])*uy];
	}
	function distance(p)
	{
		return (scalaire(p, base[0]));
	}
	*/

	var n = points.length;
	var i = 0;
	var c = 0, p = [0, 0, 0];
	while(i < n)
	{
		p = points[i][1];
		c = 100 + parseInt(50*(p[0]*k[0] + p[1]*k[1] + p[2]*k[2]));
		points[i][0].style.zIndex = c;
		c = 200 - (c > 0 ? (c < 200 ? c : 200) : 0);
		points[i][0].style.background = 'rgb('+(points[i][2][0] + c)+','+(points[i][2][1] + c)+','+(points[i][2][2] + c)+')';
		points[i][0].style.top = parseInt(ory - (p[0]*v[0] + p[1]*v[1] + p[2]*v[2])*uy);
		points[i][0].style.left = parseInt(orx + (p[0]*u[0] + p[1]*u[1] + p[2]*u[2])*ux);
		i++;
	}
}

function surface(f, i, s, nu, nv, couleur)
{
	var pasu = (s - i)/nu;
	var pasv = (s - i)/nv
	var u = i;
	var v = i;
	while(u <= s)
	{
		v = i;
		while(v <= s)
		{
			plot(f(u, v), couleur);
			v+= pasv;
		}
		u += pasu;
	}
}

function tore2(u, v)
{
	var r = 0.3;
	var R = 3.;
	var cf = Math.sqrt(R*R - r*r);
	var su = Math.sin(u), cu = Math.cos(u), sv = Math.sin(v), cv = Math.cos(v);

	return [r*cu, cf*cu*cv - (r + R*su)*sv, cf*cu*sv + (r + R*(su))*cv];
}

function decaler(f, v)
{
	return (function(x, y)
	{
		var p = f(x, y);
		return [p[0] + v[0], p[1] + v[1], p[2] + v[2]];
	});
}


function tournery(f, t)
{
	return(function(x, y)
	{
		var p = f(x, y);
		var ct = Math.cos(t), st = Math.sin(t);
		return [p[0]*ct - st*p[2], p[1], ct*p[2] + st*p[0]];
	});
}
function tournerz(f, t)
{
	return(function(x, y)
	{
		var p = f(x, y);
		var ct = Math.cos(t), st = Math.sin(t);
		return [p[0]*ct - st*p[1], ct*p[1] + st*p[0], p[2]];
	});
}

function base(theta, phi)
{
	var ct = Math.cos(theta), st = Math.sin(theta);
	var cp = Math.cos(phi), sp = Math.sin(phi);
	return [[ct*cp, ct*sp, st], [-sp, cp, 0], [-st*cp, -st*sp, ct]];
}

function calculer()
{
	document.getElementById('total_points').innerHTML = 'Patientez, les coordonnées sont en cours de calcul...';
	var nombre_points_par_cercle = parseInt(document.getElementById('nb_points').value);
	var nombre_cercles_par_tore = parseInt(document.getElementById('nb_cercles').value);
	var taille_points = parseInt(document.getElementById('taille_points').value);

	var n = points.length;
	var i = n - 1;
	while(i >= 0)
	{
		element.removeChild(points[i][0]);
		points[i][0] = null;
		points[i] = null;
		points.pop();
		i--;
	}

	surface(decaler(tournery(tore2, -Math.PI/6), [0.5, -4,   -1]), -Math.PI, Math.PI, nombre_points_par_cercle, nombre_cercles_par_tore, [0, 0, 255]);
	surface(decaler(tournery(tore2,  Math.PI/3), [  0, -1, -2.5]), -Math.PI, Math.PI, nombre_points_par_cercle, nombre_cercles_par_tore, [255, 255, 0]);
	surface(decaler(tournery(tore2, Math.PI/12), [  0,  0,   -2]), -Math.PI, Math.PI, nombre_points_par_cercle, nombre_cercles_par_tore, [0, 0, 0]);
	surface(decaler(tournerz(tore2,  Math.PI/3), [  0,1.3,  1.8]), -Math.PI, Math.PI, nombre_points_par_cercle, nombre_cercles_par_tore, [0, 255, 0])
	surface(decaler(tournery(tore2, -Math.PI/6), [-0.5, 3, -1.3]), -Math.PI, Math.PI, nombre_points_par_cercle, nombre_cercles_par_tore, [255, 0, 0]);

	var i = 0;
	var n = points.length;
	while(i < n)
	{
		points[i][0].style.width = taille_points;
		points[i][0].style.height = taille_points;
		i++;
	}

	afficher(base(theta, phi));

	document.getElementById('total_points').innerHTML = 'Nombre total de points : '+(nombre_points_par_cercle*nombre_cercles_par_tore*5) + '. Le mouvement commence à être fluide en dessous de 2000 points.';
}

calculer();




Le concept est de représenter des surfaces, décrites par des fonctions de deux variables, en calculant la projection sur un plan adéquat de points de cette surface pris à intervalles voulus réguliers. On a une meilleure - quoique moins maniable - illustration de ce concept ici, où les tores sont plus gros et le nombre de points plus élevés (on y reconnaît presque les cercles de villarceau que j'ai utilisés pour décrire les tores).

NB : je n'ai pas testé la validité de mon travail sous Internet Explorer, je nourris même le soupçon qu'il n'y fonctionne pas, ou au mieux bizarrement.
  • Partager sur Facebook
  • Partager sur Twitter