ROOT logo

From $ROOTSYS/tutorials/graphics/mandelbrot.C

#include <TStyle.h>
#include <TROOT.h>
#include <TH2.h>
#include <TComplex.h>
#include <TVirtualPad.h>
#include <TCanvas.h>

//==================================================================
//
// Using TExec to handle keyboard events and TComplex to draw the Mandelbrot set.
// Author : Luigi Bardelli [ bardelli@fi.infn.it ]
//
// 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).
//==================================================================

TH2F *last_histo=NULL;

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->Draw("colz");
  gPad->Modified();
  gPad->Update();
  printf("Done.\n");
}

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;
  };
}

void mandelbrot()
{
  // cosmetics...
  gROOT->SetStyle("Plain");
  gStyle->SetPalette(1,0);
  gStyle->SetPadGridX(kTRUE);
  gStyle->SetPadGridY(kTRUE);
  new TCanvas("canvas","View Mandelbrot set");
  gPad->SetCrosshair();
  // this generates and draws the first view...
  mygenerate(-1,0,0);

  // add exec
  gPad->AddExec("myexec","myexec()");
}
 mandelbrot.C:1
 mandelbrot.C:2
 mandelbrot.C:3
 mandelbrot.C:4
 mandelbrot.C:5
 mandelbrot.C:6
 mandelbrot.C:7
 mandelbrot.C:8
 mandelbrot.C:9
 mandelbrot.C:10
 mandelbrot.C:11
 mandelbrot.C:12
 mandelbrot.C:13
 mandelbrot.C:14
 mandelbrot.C:15
 mandelbrot.C:16
 mandelbrot.C:17
 mandelbrot.C:18
 mandelbrot.C:19
 mandelbrot.C:20
 mandelbrot.C:21
 mandelbrot.C:22
 mandelbrot.C:23
 mandelbrot.C:24
 mandelbrot.C:25
 mandelbrot.C:26
 mandelbrot.C:27
 mandelbrot.C:28
 mandelbrot.C:29
 mandelbrot.C:30
 mandelbrot.C:31
 mandelbrot.C:32
 mandelbrot.C:33
 mandelbrot.C:34
 mandelbrot.C:35
 mandelbrot.C:36
 mandelbrot.C:37
 mandelbrot.C:38
 mandelbrot.C:39
 mandelbrot.C:40
 mandelbrot.C:41
 mandelbrot.C:42
 mandelbrot.C:43
 mandelbrot.C:44
 mandelbrot.C:45
 mandelbrot.C:46
 mandelbrot.C:47
 mandelbrot.C:48
 mandelbrot.C:49
 mandelbrot.C:50
 mandelbrot.C:51
 mandelbrot.C:52
 mandelbrot.C:53
 mandelbrot.C:54
 mandelbrot.C:55
 mandelbrot.C:56
 mandelbrot.C:57
 mandelbrot.C:58
 mandelbrot.C:59
 mandelbrot.C:60
 mandelbrot.C:61
 mandelbrot.C:62
 mandelbrot.C:63
 mandelbrot.C:64
 mandelbrot.C:65
 mandelbrot.C:66
 mandelbrot.C:67
 mandelbrot.C:68
 mandelbrot.C:69
 mandelbrot.C:70
 mandelbrot.C:71
 mandelbrot.C:72
 mandelbrot.C:73
 mandelbrot.C:74
 mandelbrot.C:75
 mandelbrot.C:76
 mandelbrot.C:77
 mandelbrot.C:78
 mandelbrot.C:79
 mandelbrot.C:80
 mandelbrot.C:81
 mandelbrot.C:82
 mandelbrot.C:83
 mandelbrot.C:84
 mandelbrot.C:85
 mandelbrot.C:86
 mandelbrot.C:87
 mandelbrot.C:88
 mandelbrot.C:89
 mandelbrot.C:90
 mandelbrot.C:91
 mandelbrot.C:92
 mandelbrot.C:93
 mandelbrot.C:94
 mandelbrot.C:95
 mandelbrot.C:96
 mandelbrot.C:97
 mandelbrot.C:98
 mandelbrot.C:99
 mandelbrot.C:100
 mandelbrot.C:101
 mandelbrot.C:102
 mandelbrot.C:103
 mandelbrot.C:104
 mandelbrot.C:105
 mandelbrot.C:106
 mandelbrot.C:107
 mandelbrot.C:108
 mandelbrot.C:109
 mandelbrot.C:110
 mandelbrot.C:111
 mandelbrot.C:112
 mandelbrot.C:113
 mandelbrot.C:114
 mandelbrot.C:115
 mandelbrot.C:116
 mandelbrot.C:117
 mandelbrot.C:118
 mandelbrot.C:119
 mandelbrot.C:120
 mandelbrot.C:121
 mandelbrot.C:122
 mandelbrot.C:123
 mandelbrot.C:124
 mandelbrot.C:125
 mandelbrot.C:126
 mandelbrot.C:127
 mandelbrot.C:128
 mandelbrot.C:129
 mandelbrot.C:130