Mandelbrot

Using TExec to handle keyboard events and TComplex to draw the Mandelbrot set.

Pressing the keys 'z' and 'u' will zoom and unzoom the picture near the mouse location, 'r' will reset to the default view.

Try it (in compiled mode!) with: root mandelbrot.C+

Details

when a mouse event occurs the myexec() function is called (by using AddExec). Depending on the pressed key, the mygenerate() function is called, with the proper arguments. Note the last_x and last_y variables that are used in myexec() to store the last pointer coordinates (px is not a pointer position in kKeyPress events).

Author: Luigi Bardelli [email protected]
This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Sunday, July 05, 2020 at 07:32 AM.

In [1]:
%%cpp -d
#include <TStyle.h>
#include <TROOT.h>
#include <TH2.h>
#include <TComplex.h>
#include <TVirtualPad.h>
#include <TCanvas.h>

TH2F *last_histo=NULL;

A helper function is created:

In [2]:
%%cpp -d
void mygenerate(double factor, double cen_x, double cen_y)
{
  printf("Regenerating...\n");
  // resize histo:
  if(factor>0)
    {
      double dx=last_histo->GetXaxis()->GetXmax()-last_histo->GetXaxis()->GetXmin();
      double dy=last_histo->GetYaxis()->GetXmax()-last_histo->GetYaxis()->GetXmin();
      last_histo->SetBins(
                          last_histo->GetNbinsX(),
                          cen_x-factor*dx/2,
                          cen_x+factor*dx/2,
                          last_histo->GetNbinsY(),
                          cen_y-factor*dy/2,
                          cen_y+factor*dy/2
                          );
      last_histo->Reset();
    }
  else
    {
      if(last_histo!=NULL) delete last_histo;
      // allocate first view...
      last_histo= new TH2F("h2",
         "Mandelbrot [move mouse and  press z to zoom, u to unzoom, r to reset]",
                           200,-2,2,200,-2,2);
      last_histo->SetStats(0);
    }
  const int max_iter=50;
  for(int bx=1;bx<=last_histo->GetNbinsX();bx++)
    for(int by=1;by<=last_histo->GetNbinsY();by++)
      {
         double x=last_histo->GetXaxis()->GetBinCenter(bx);
         double y=last_histo->GetYaxis()->GetBinCenter(by);
         TComplex point( x,y);
         TComplex z=point;
         int iter=0;
         while (z.Rho()<2){
            z=z*z+point;
            last_histo->Fill(x,y);
            iter++;
            if(iter>max_iter) break;
         }
      }
  last_histo->SetContour(99);
  last_histo->Draw("colz");
  gPad->Modified();
  gPad->Update();
  printf("Done.\n");
}

A helper function is created:

In [3]:
%%cpp -d
void myexec()
{
  // get event information
  int event = gPad->GetEvent();
  int px = gPad->GetEventX();
  int py = gPad->GetEventY();

  // some magic to get the coordinates...
  double xd = gPad->AbsPixeltoX(px);
  double yd = gPad->AbsPixeltoY(py);
  float x = gPad->PadtoX(xd);
  float y = gPad->PadtoY(yd);

  static float last_x;
  static float last_y;

  if(event!=kKeyPress)
    {
      last_x=x;
      last_y=y;
      return;
    }

  const double Z=2.;
  switch(px){
  case 'z': // ZOOM
    mygenerate(1./Z, last_x, last_y);
    break;
  case 'u': // UNZOOM
    mygenerate(Z   , last_x, last_y);
    break;
  case 'r': // RESET
    mygenerate(-1   , last_x, last_y);
    break;
  };
}
In [4]:
// cosmetics...
  gStyle->SetPadGridX(kTRUE);
  gStyle->SetPadGridY(kTRUE);
  new TCanvas("canvas","View Mandelbrot set");
  // this generates and draws the first view...
  mygenerate(-1,0,0);

  // add exec
  gPad->AddExec("myexec","myexec()");
Regenerating...
Done.

Draw all canvases

In [5]:
%jsroot on
gROOT->GetListOfCanvases()->Draw()