Si tu réutilises le code d'un autre projet, il serait bon de le mentionner dans ton code (un commentaire pour le dire avec un lien vers le projet). Du reste, il me semble que QuickMan est sous GPL, et que tu devrais donc respecter toi aussi cette licence si tu distribues ton logiciel.
Etant donner qu'il y a beaucoup de mandelbrot en utilisant le complexe a + ib, je viens vous en présenter un utilisant l'algèbres des quaternions, qui sont des complexe de type a + ib+ jc+ kd
Cet algèbre n'est pas plus compliqué que les complexe normaux.
il est possible de faire beaucoup plus court en enlevant les threads
Bah, tes threads font quasiment la même chose, tu pourrais utiliser le préprocesseur pour générer tes fonctions et économiser... beaucoup de lignes.
Tu ferais bien d'utiliser les tableaux pour ta fonction drawMandelbrot.
Pour ta fonction main aussi.
Ton code fait tourner mon proc à 100%, rajoutes une petite gestion des ressources et ce sera pas mal.
En regardant cette vidéo, j'ai eu envie de réaliser le dessin du triangle de Pascal, et de le colorier. C'est tout simple, tout bête.
Résultats pour n=2,3,4
C'était plus joli sur papier, pour le coup y'a un gros mélange indistinct (et laid) entre du vert et du rouge, c'est pas beau. L'effet est bien plus joli avec de plus gros « points » et moins de détails quoi. Ça pourrait être sympa que t'essayes de faire un truc dans le style de la vidée.
À la base je voulais tester cairo en combinaison avec la SDL. Histoire d'avoir quelque chose à faire, j'ai implémenté la fougère de Barnsley. C'était relativement facile avec les formules trouvées sur wikipédia, par contre, cairo n'était pas franchement utile dans ce contexte. Du coup, j'ai fait une version allégée rien qu'avec la SDL que voici :
#include <time.h>
#include <SDL.h>
const int WIN_WIDTH = 600;
const int WIN_HEIGHT = 600;
int NB_ITER = 1024;
int NB_ITER2 = 512;
static void paint(void);
int main(int argc, char *argv[]) {
SDL_Init(SDL_INIT_VIDEO);
srand(time(NULL));
if (argc >= 3) {
NB_ITER = atoi(argv[1]);
NB_ITER2 = atoi(argv[2]);
}
paint();
while (1) {
SDL_Event evt;
SDL_WaitEvent(&evt);
switch (evt.type) {
case SDL_QUIT:
SDL_Quit();
return 0;
default:
break;
}
}
}
static void drawPixel(SDL_Surface *screen, SDL_Surface *pixel,
double x, double y)
{
double x0 = WIN_WIDTH / 2.0;
double y0 = WIN_HEIGHT; /* NB: y = 0 at the top of the window */
/* To stretch pixels all over the window */
double w = WIN_WIDTH / 5.5;
double h = WIN_HEIGHT / 10.5;
SDL_Rect rect = { .x = w * x + x0, .y = y0 - h * y };
SDL_BlitSurface(pixel, NULL, screen, &rect);
}
static int mt_rand(int min, int max) {
return ((double)rand() / ((double)RAND_MAX + 1)) * (max - min + 1) + min;
}
static void paint() {
SDL_Surface *screen = SDL_SetVideoMode(WIN_WIDTH, WIN_HEIGHT, 32,
SDL_HWSURFACE | SDL_DOUBLEBUF);
/* Set background */
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF));
SDL_Surface *pixel = SDL_CreateRGBSurface(SDL_HWSURFACE,
1, 1, 32, 0, 0, 0, 0);
SDL_FillRect(pixel, NULL, SDL_MapRGB(screen->format, 0, 0x7F, 0));
for (int k = 0; k < NB_ITER; k++) {
/* The algorithm itself */
double x = 0;
double y = 0;
for (int i = 0; i < NB_ITER2; i++) {
drawPixel(screen, pixel, x, y);
double x1, y1;
int r = mt_rand(0, 99);
if (r > 14) { /* prob of 85% */
/* f2 */
x1 = .85 * x + .04 * y;
y1 = -.04 * x + .85 * y + 1.6;
}
else if (r > 7) { /* prob of 7% */
/* f3 */
x1 = .2 * x - .26 * y;
y1 = .23 * x + .22 * y + 1.6;
}
else if (r > 0) { /* prob of 7% */
/* f4 */
x1 = -.15 * x + .28 * y;
y1 = .26 * x + .24 * y + .44;
}
else { /* prob of 1% */
/* f1 */
x1 = 0;
y1 = .16 * y;
}
x = x1;
y = y1;
}
SDL_Flip(screen);
}
SDL_FreeSurface(pixel);
}
Code compilable à l'aide de la commande : gcc `sdl-config --cflags` `sdl-config --libs` -std=c99 fern.c. Le nombre d'itérations peut être fourni en paramètres.
Voici le résultat avec le nombre d'itérations par défaut (1024 * 512) :
Salut,
J'ai écrit ces deux derniers jours une petite librairie pour dessiner avec une tortue, à la manière de LOGO, en Ocaml à l'aide de Graphics.
Voici le code (turtle.ml):
open Graphics
(* Maths *)
let to_rad x = x /. 180. *. atan infinity *. 2.
let round r =
let rr = int_of_float r in
(if r < float_of_int (rr + 1) -. 0.5 then
rr
else
(succ rr)) / 1000
(* Type cool et opérations *)
type turtle = Turtle of (float * float * float * bool)
let make x y a s = Turtle (x, y, a, s)
let (>>) m f = f m
let map f = function
| Turtle (x, y, a, s) -> Turtle (f x y a s)
let rec simple angle =
if angle > 180. then
simple (angle -. 360.)
else if angle <= -180. then
simple (angle +. 360.)
else
angle
(* Manipulation de la tortue *)
let left_float angle =
map (fun x y a s -> (x, y, simple (a +. simple angle), s))
let left angle = left_float (float_of_int angle)
let right_float angle = left_float (-. angle)
let right angle = left (- angle)
let goto_float x y (Turtle (_, _, a, s)) =
Turtle (x *. 1000., y *. 1000., a, s)
let goto x y = goto_float (float_of_int x) (float_of_int y)
let forward_float dist = function
| Turtle (x, y, a, s) ->
let nx = x +. (dist *. 1000.) *. cos (to_rad a)
and ny = y +. (dist *. 1000.) *. sin (to_rad a) in
begin
if s then
begin
moveto (round x) (round y) ;
lineto (round nx) (round ny) ;
end ;
Turtle (nx, ny, a, s)
end
let forward dist = forward_float (float_of_int dist)
let backward_float dist = forward_float (-. dist)
let backward dist = forward (- dist)
let up (Turtle (x, y, a, s)) = Turtle (x, y, a, true)
let down (Turtle (x, y, a, s)) = Turtle (x, y, a, false)
let init x y =
let _ = open_graph (" " ^ string_of_int x ^ "x" ^ string_of_int y) in
make 0. 0. 0. true
L'idée de base était de dessiner des arbres cool ; puisque la position est (discrètement grâce à l'opérateur (>>)) passée en argument à chaque fonction, il est simple de faire partir deux branches du même point.
Voici ce que j'ai pu obtenir (compilez avec ocamlc -o arbre graphics.cma turtle.ml arbre.ml):
arbre.ml:
open Turtle
let rec arbre taille r pos =
if r = 0 then pos else
let d = pos >> forward taille in
let _ = d >> left 45 >> arbre (taille - taille / 3) (pred r) in
d >> right 25 >> arbre (taille - taille / 5) (pred r) ;;
init 1000 600 >> goto 100 150 >> left 45 >> arbre 100 15 ;;
try let _ = read_int () in () with
| Graphics.Graphic_failure _ -> ()
open Turtle
let rec triangle taille r pos =
if r < 1 then pos else
let (a, b) = sous_triangle taille r pos in
let _ = sous_triangle taille r a in
let _ = sous_triangle taille r b in
pos
and sous_triangle taille r pos =
let coin_gauche = pos >> right 30 >> forward_float taille >> left 30 in
let coin_droite = pos >> left 30 >> forward_float taille >> right 30 in
let debut = coin_gauche >> left 90 >> forward_float taille >> left 150 in
let _ = debut >> triangle (taille /. 2.) (pred r) in
(coin_gauche, coin_droite) ;;
init 500 500 >> goto 250 450 >> right 90 >> triangle 200. 10 ;;
try let _ = read_int () in () with
| Graphics.Graphic_failure _ -> ()
Ce dernier rendu montre les limites de la chose : les flottants (qu'on manipule forcément puisqu'on utilse la trigonométrie pour trouver les coordonnées cartésiennes à partir des coordonnées polaires) sont imprécis. Mon (mauvais) algo pour le triangle repasse certains côtés ; si on disposait d'une précision parfaite, ça ne se verrait pas ; ici, certains segments ont l'air plus gros que d'autres et c'est moche.
Voilà, un petit bonus, les triangles rigolos que j'ai obtenus à cause de bugs idiots : le premier et le second.
Il faudrait factoriser ça, et ensuite essayer avec des valeurs différentes de 2.
Krnkktz > l'idée et le code sont sympa. Je pense que tu pourrais améliorer le rendu en passant de Graphics (qui est bien pour expérimenter mais moins bien pour les rends impecs) à un autre mode de rendu, comme Cairo ou PostScript.
Bonjour a tous,
je viens poster ici un projet un peu particulier, en effet c'est un clip vidéo généré par des algorithmes mathématiques.
Vous pouvez voir la vidéo ici !
Techniquement, ces images sont générées par du raytracing sur des surfaces procedurales décrites mathématiquement par leur équation de "distance par rapport au point".
Cette technique s'appelle le sphere tracing ou encore le raytracing par distance field.
Il y a quelques docs clés sur le net a propos de cet algo : Rendering world in two polygon ainsi que RayMarching and DistanceFields : a story of SphereTracing.
Chaque pixel est plus ou moins grisé en fonction du nombre d'étapes que prend l'algorithme d'Euclide (que tout le monde a vu au collège il me semble) pour calculer le PGCD des coordonnées. Ce qui est cool, c'est qu'on s'apperçoit que les coordonnées des nouveaux maximums forment la suite de fibonacci. On voit aussi l'axe de symétrie de l'image (c'est normal, pgcd(a, b) c'est la même chose que le pgcd(b, a)), et jcrois que y'a encore plein de trucs à voir dedans mais j'ai dormi pendant le reste de la conférence que j'ai vue qui en parlait alors je vous invite à vous renseigner :'
#include <stdio.h>
#include <stdlib.h>
#include <SDL/SDL.h>
#define HAUTEUR 600
#define LARGEUR 1024
#define HAUTEUR_CARRE 1
#define LARGEUR_CARRE 1
#define MAX_ETAPES 13
void draw_point(int, int);
int euclide(int, int, int);
void pause(void);
SDL_Surface *screen;
int max = 0;
void
draw_point(int a, int b)
{
SDL_Rect pos;
int e = euclide(a, b, 1), r;
if (e > max) {
max = e;
printf("Nouveau maximum au point (%d, %d) : %d\n", a, b, e);
}
r = 256 - 256 * e / MAX_ETAPES;
pos.x = LARGEUR_CARRE * a;
pos.y = HAUTEUR_CARRE * b;
pos.h = LARGEUR_CARRE;
pos.w = HAUTEUR_CARRE;
SDL_FillRect(screen, &pos,
SDL_MapRGB(screen->format,
r,
r,
r));
}
int euclide(int a, int b, int n)
{
int r = a % b;
if (r == 0)
return n;
else
return euclide(b, r, ++n);
}
void pause(void)
{
SDL_Event event;
while (1) {
SDL_WaitEvent(&event);
if (event.type == SDL_QUIT)
break;
}
}
int main(void)
{
int i, j;
if (SDL_Init(SDL_INIT_VIDEO) == -1) {
fprintf(stderr, "Erreur d'initialisation de la SDL : %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
screen = SDL_SetVideoMode(LARGEUR, HAUTEUR, 32, SDL_RESIZABLE);
for (i = 1; i <= LARGEUR / LARGEUR_CARRE; ++i) {
for (j = 1; j <= HAUTEUR / HAUTEUR_CARRE; ++j) {
draw_point(i, j);
}
SDL_Flip(screen);
}
pause();
SDL_Quit();
return EXIT_SUCCESS;
}
La bonne nouvelle, c'est qu'on peut zoomer en changeant les defines
Pas vraiment très original, mais je me suis amusé à dessiner l’ensemble de Mandelbrot, en GLSL (avec du Ruby, mais le vrai travail est effectué du côté du shader). Ici, les points qui font partie de la fractale sont dessinés normalement, et la couleur des autres est inversées, avec un dégradé pour faire plus joli. J’ai commencé simplement par dessiner un rectangle noir.
require 'ray'
ImageWidth = 640
ImageHeight = 480
image = Ray::Image.new [ImageWidth, ImageHeight]
Ray::ImageTarget.new image do |target|
target.shader.compile(:frag => StringIO.new(<<eof))
#version 130
const int max_it = 50;
const float width = #{ImageWidth.to_f};
const float height = #{ImageHeight.to_f};
in vec4 var_Color;
out vec4 out_FragColor;
vec2 mandelbrot_pos() {
return vec2((gl_FragCoord.x / width) * 2.7 - 2.1,
(gl_FragCoord.y / height) * 2.4 - 1.2);
}
vec2 complex_square(vec2 complex) {
return vec2(complex.x * complex.x - complex.y * complex.y,
2.0 * complex.x * complex.y);
}
vec4 inverse(vec4 color, int i) {
return vec4((vec3(1.0, 1.0, 1.0) - color.rgb) / float(i + 1), color.a);
}
void main() {
vec2 c = mandelbrot_pos();
vec2 z = vec2(0.0, 0.0);
int i = 0;
for (i = 0; i < max_it; i++) {
z = complex_square(z) + c;
if (dot(z, z) > 4.0) break;
}
out_FragColor = i == max_it ? var_Color : inverse(var_Color, i);
}
eof
target.draw Ray::Polygon.rectangle([0, 0, ImageWidth, ImageHeight], Ray::Color.black)
target.update
end
Ray.game "Mandelbrot", :size => image.size do
register { add_hook :quit, method(:exit!) }
scene :mandelbrot do
@sprite = sprite(image)
render do |win|
win.draw @sprite
end
end
scenes << :mandelbrot
end
Han ! J'avais jamais vu ce topic... Je m'étais intéressé à une époque à ce genre de problèmes, et avait fait quelques réalisations, mais j'ai abandonné par manque de temps et de motivation.
C'est l'occasion idéale pour s'y remettre. En tout cas, félicitation pour l'ensemble des travaux, qui sont très beaux pour la plupart.
Oh je n'avais jamais vu ce topic !! Merveilleux les screenshots des fractales et autres rendus mathématiques
Je voulais reprendre un post, ou il y a un labyrinthe 3D.
Citation : Yannshu
Et pour finir, un petit labyrinthe en 3 dimensions.
Petite explication pour le labyrinthe, les boudins en forme de cube representent le chemin entre le cube vert et le cube rouge.
Le cube vert et le cube rouge sont diagonalement positionnes. Il n'y a qu'un seul chemin entre ces deux cubes.
Mon vieux projet Klostro Laby est exactement la même chose, mais vu de l'intérieur
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html