Ceci est une solution pour le TD Mandelbrot.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Fractale de Mandelbrot</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas width="1200" height="800">
En attente...
</canvas>
<script src="./script.js"></script>
</body>
</html>
const ITERATIONS = 500;
const ZOOMFACTOR = 2;
let canvas = document.querySelector('canvas');
let ctx = canvas.getContext('2d');
let w = canvas.width;
let h = canvas.height;
/* réglage de la vue :
x, y: coordonées du centre
dot: taille d'un pixel dans le repère
*/
var pan = {
x:-.5,
y:0,
dot: 0.01
}
const colormap = [
[0, 0, 0],
[20, 0, 20],
[50, 0, 50],
[80, 0, 80],
[30, 0, 80],
[20, 80, 80],
[0, 100, 80],
[0, 100, 30],
[60, 120, 10],
[94, 100, 0],
[100, 70, 0],
[100, 14, 0]
];
function draw(){
/*
trace selon les les coordonnées dans pan
*/
let img = ctx.getImageData(0, 0, w, h);
let data = img.data;
for (let i=0; i<data.length; i+=4){
let indice = ~~(i /4);
let col = indice % w;
let lig = ~~(indice / w);
let x = pan.x + (col - w/2)*pan.dot;
let y = pan.y - (lig - h/2)/pan.dot;
let score = getScore(x, y);
let color = getColor(score);
data[i] = color[0];
data[i+1] = color[1];
data[i+2] = color[2];
data[i+3] = 255;
}
ctx.putImageData(img, 0, 0);
}
function mod2(z){
/*
z: complexe, objet ayant les attributs re et im
renvoie le module de z au carré
*/
return z.re*z.re + z.im*z.im
}
function getScore(cx, cy){
/* teste l'appartenance ce cx, cy à l'ensemble.
renvoie un float entre 0 et 1, 0 pour appartenance complète à l'ensemble. */
let zx = 0;
let zy = 0;
for (let i=0; i<ITERATIONS; i++){
let nzx = zx*zx - zy*zy + cx
zy = 2*zx*zy + cy;
zx = nzx;
let m2 = zx*zx + zy*zy;
if (m2>=4) {
return 1 - Math.max(0, i - Math.log(m)/Math.log(4))/ITERATIONS;
}
}
return 0;
}
function getColor(score)
{
/* calcule la couleur selon le score et la colormap */
if (score== 1) {
return colormap[colormap.length - 1];
}
let x = (colormap.length-1)*value;
let i = Math.floor(x);
let di = x - i;
let r1, g1, b1, r2, g2, b2;
[r1, g1, b1] = colormap[i];
[r2, g2, b2] = colormap[i+1];
let r = Math.round(r1 + di*(r2 - r1));
let g = Math.round(g1 + di*(g2 - g1));
let b = Math.round(b1 + di*(b2 - b1));
return [r, g, b];
}
function getCursorPosition(canvas, event) {
/* lit les coordonnées du clic souris */
const rect = canvas.getBoundingClientRect()
const x = event.clientX - rect.left
const y = event.clientY - rect.top
return [x, y];
}
function click(e){
/* gère un click */
let lig, col;
[col,lig] = getCursorPosition(canvas, e);
let x = pan.x + (col-w/2)*pan.dot;
let y = pan.y - (lig - h/2)*pan.dot;
pan.dot /= ZOOMFACTOR;
pan.x = x - (col - w/2)*dot;
pan.y = y + (lig - h/2)*dot;
draw();
}
canvas.addEventListener('mousedown', click)
draw();