Fractals: Mandelbrot tout simplement (C)

Description

Bonjour,

Cette évolution (C) de "Fractals: Mandelbrot tout simplement" permet d'adapter librement la taille de l'image, alors qu'il est courant de ne mettre à disposition que quelques dimensions fixes.

L'adaptation se fait simplement en changeant la grandeur de la fenêtre principale (voir lien "Canvas sur fenêtre entière"):
<!DOCTYPE html>
<html><head>
  <title>Fractal: Mandelbrot-C</title>
  <meta name='author' content='William Voirol, Switzerland, Août 2016'>
  <script>
    var cnv,ctx,imd,txt,w,h,ima=0,nbC=32,R=[0],G=[0],B=[0],
    xInf=[-2.02,   -1.8,  -0.4,-0.195, -0.18],
    xSup=[1.336,-0.4017,0.2178,0.0567,-0.133],
    yInf=[-1.26,   -0.5,   0.7,   0.8, 1.017],
    ySup=[1.256, 0.5483,1.1632,0.9887, 1.052];

    function NbrCol(inp) {
      if (isNaN(inp.value)) {inp.value=nbC; return;}
      var n=Number(inp.value);
      if (n<4) n=4; else if (n>256) n=256;
      if (n!=nbC) {
        R[n-1]=R[nbC-1]; G[n-1]=G[nbC-1]; B[n-1]=B[nbC-1];
        nbC=n; CalCol();
      }
    }
    function SetCol(k,hex) { // k=0: int, k=1: bord, k=2: ext
     var m=nbC-1,c=parseInt(hex,16),r=(c>>16)&255,g=(c>>8)&255,b=c&255;
      if (k<=1) {R[k]=r; G[k]=g; B[k]=b;} else {R[m]=r; G[m]=g; B[m]=b;}
      CalCol();
    }
    function CalCol() {
      var n,m=nbC-1,dr=(R[m]-R[1])/nbC,dg=(G[m]-G[1])/nbC,db=(B[m]-B[1])/nbC;
      for (n=1; n<m; ++n) {R[n]=R[1]+n*dr; G[n]=G[1]+n*dg; B[n]=B[1]+n*db;}
      Draw();
    }
    function Size() {
      w=cnv.width=window.innerWidth; h=cnv.height=window.innerHeight-20;
      imd=ctx.createImageData(w,h);
    }
    function Draw() {
      var t=new Date().getTime();
      var d=imd.data,xI=xInf[ima],yI=yInf[ima];
      var f=Math.max((xSup[ima]-xI)/(w-1),(ySup[ima]-yI)/(h-1));
      var xS=xI+w*f-f,yS=yI+h*f-f;
      for (var j=0,k=0,y=yS; j<h; ++j,y-=f)
        for (var i=0,x=xI; i<w; ++i,x+=f,k+=4) {
          var n=nbC,u=x,v=y,uu=u*u,vv=v*v;
          while ((--n>0)&&(uu+vv<4)) {v=2*u*v+y; u=uu-vv+x; uu=u*u; vv=v*v;}
          d[k]=R[n]; d[k+1]=G[n]; d[k+2]=B[n]; d[k+3]=255;
        }
      ctx.putImageData(imd,0,0);
      t=new Date().getTime()-t;
      txt.innerHTML='['+xI.toPrecision(5)+','+yI.toPrecision(5)+' ; '+
        xS.toPrecision(5)+','+yS.toPrecision(5)+'], zoom='+
        (1/f).toPrecision(5)+', colors='+nbC+', w='+w+', h='+h+': '+t+'ms';
    }
    function Init() {
      cnv=document.getElementById('Cnv'); ctx=cnv.getContext('2d');
      txt=document.getElementById('Txt');
      Size();
      R[nbC-1]=G[nbC-1]=B[nbC-1]=0; SetCol(1,'FFFFFF');
    }
  </script>
</head><body style='font-size:14px' onload='Init()' onresize='Size(); Draw()'>
  <input type='text' style='position:fixed; left:0; top:0; text-align:right'
    size='1' value='32' onchange='NbrCol(this)'>
  <input type='color' style='position:fixed; left:46px; top:0' size='5'
    value='#000000' onchange='SetCol(0,this.value.substr(1),16)'>
  <input type='color' style='position:fixed; left:110px; top:0'size='5'
    value='#FFFFFF' onchange='SetCol(1,this.value.substr(1),16)'>
  <input type='color' style='position:fixed; left:174px; top:0'size='5'
    value='#000000' onchange='SetCol(2,this.value.substr(1),16)'>
  <div style='position:fixed; left:250px; top:0; background-color:yellow;
    cursor:default' onclick='ima=(ima+1)%xInf.length; Draw()'> ► </div>
  <div id='Txt' style='position:fixed; left:290px; top:0; color:blue'> </div>
  <canvas id='Cnv' width=840 height=630
    style='position:fixed; left:0; top:24px'>
  </canvas>
</body></html>
La mise en page 2D maintient le point (xInf,yInf) en bas à gauche et s'arange pour que (xSup,ySup) soit juste encore visible sur l'image.
La zone effectivement représentée s'indique entre crochets [] juste à droite de ►.

Attention: Le temps d'actualisation de l'image augmente avec le nombre de pixels et le nombre de couleurs !

La prochaine étape (D) permettra de choisir librement la zone à représenter.

Liens:
Canvas sur fenêtre entière.
Fractals: Mandelbrot tout simplement (A): Base.
Fractals: Mandelbrot tout simplement (B): Couleurs.

Bonne lecture ...

Codes Sources

Vous n'êtes pas encore membre ?

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

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

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

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