Mandelbrot mit JSXGraph

Aus Wiki1

(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
Zeile 9: Zeile 9:
   // Slider für Iterationstiefe
   // Slider für Iterationstiefe
-
   const slider = board.create('slider', [[-2.3, 1.3], [1, 1.3], [10, 10, 200]], {
+
   const slider = board.create('slider', [[-2.3, 1.3], [1, 1.3], [10, 50, 300]], {
     name:'Tiefe',
     name:'Tiefe',
     snapWidth:1
     snapWidth:1
   });
   });
-
   // Mandelbrot-Berechnung für einen Punkt
+
   // Canvas ins DOM hängen
 +
  const div = document.getElementById('jxgbox');
 +
  const canvas = document.createElement('canvas');
 +
  canvas.width = 800;
 +
  canvas.height = 600;
 +
  canvas.style.position = 'absolute';
 +
  canvas.style.left = "0px";
 +
  canvas.style.top = "0px";
 +
  div.appendChild(canvas);
 +
  const ctx = canvas.getContext('2d');
 +
 
   function mandelbrotIter(cx, cy, maxIter) {
   function mandelbrotIter(cx, cy, maxIter) {
-
     let x = 0, y = 0;
+
     let x = 0, y = 0, iter = 0;
-
    let iter = 0;
+
     while (x*x + y*y <= 4 && iter < maxIter) {
     while (x*x + y*y <= 4 && iter < maxIter) {
-
       let xtemp = x*x - y*y + cx;
+
       const xtemp = x*x - y*y + cx;
       y = 2*x*y + cy;
       y = 2*x*y + cy;
       x = xtemp;
       x = xtemp;
Zeile 27: Zeile 36:
   }
   }
-
   // Raster erstellen
+
   function drawMandelbrot(maxIter) {
-
  const N = 100; // Auflösung (mehr = langsamer, feiner)
+
    const bb = board.getBoundingBox(); // [x_min, y_max, x_max, y_min]
-
  const stepX = (board.getBoundingBox()[2] - board.getBoundingBox()[0]) / N;
+
    const img = ctx.createImageData(canvas.width, canvas.height);
-
  const stepY = (board.getBoundingBox()[1] - board.getBoundingBox()[3]) / N;
+
-
  let rects = [];
+
    for (let px = 0; px < canvas.width; px++) {
 +
      for (let py = 0; py < canvas.height; py++) {
 +
        // Koordinaten im Mandelbrot-Bereich
 +
        const cx = bb[0] + (px / canvas.width) * (bb[2] - bb[0]);
 +
        const cy = bb[3] + (py / canvas.height) * (bb[1] - bb[3]);
-
  for (let i = 0; i < N; i++) {
+
        const iter = mandelbrotIter(cx, cy, maxIter);
-
    for (let j = 0; j < N; j++) {
+
        const idx = 4 * (py * canvas.width + px);
-
      const x = board.getBoundingBox()[0] + i*stepX;
+
-
      const y = board.getBoundingBox()[3] + j*stepY;
+
-
      // kleine Rechtecke
+
        if (iter >= maxIter) {
-
      let r = board.create('polygon', [
+
          img.data[idx] = 0;    // R
-
        [x, y],
+
          img.data[idx+1] = 0;  // G
-
        [x+stepX, y],
+
          img.data[idx+2] = 0;  // B
-
        [x+stepX, y+stepY],
+
          img.data[idx+3] = 255; // A
-
        [x, y+stepY]
+
         } else {
-
      ], {
+
          const c = Math.floor(255 * iter / maxIter);
-
         borders: {visible:false},
+
          img.data[idx]  = c;      // R
-
        fillColor: 'black',
+
          img.data[idx+1] = 100;    // G
-
        fillOpacity: 1,
+
          img.data[idx+2] = 255 - c; // B
-
        withLines:false,
+
          img.data[idx+3] = 255;    // A
-
        hasInnerPoints:true,
+
         }
-
         fixed:true
+
       }
-
      });
+
-
       rects.push({poly:r, cx:x, cy:y});
+
     }
     }
 +
    ctx.putImageData(img, 0, 0);
   }
   }
-
   // Update-Funktion
+
   // Erneuern, wenn Slider bewegt wird
-
   board.on('update', function() {
+
   slider.on('drag', () => {
-
     const maxIter = Math.round(slider.Value());
+
     drawMandelbrot(Math.round(slider.Value()));
-
    rects.forEach(obj => {
+
-
      let it = mandelbrotIter(obj.cx, obj.cy, maxIter);
+
-
      if (it >= maxIter) {
+
-
        obj.poly.setAttribute({fillColor: 'black'});
+
-
      } else {
+
-
        // Farbverlauf
+
-
        const c = Math.floor(255*it/maxIter);
+
-
        obj.poly.setAttribute({fillColor: 'rgb(${c},${100},${255-c})'});
+
-
      }
+
-
    });
+
   });
   });
 +
 +
  // Initial zeichnen
 +
  drawMandelbrot(Math.round(slider.Value()));
</jsxgraph>
</jsxgraph>

Version vom 10:30, 15. Sep. 2025

Persönliche Werkzeuge