Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
mandelbrot.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_graphics
3 /// \notebook -js
4 /// Using TExec to handle keyboard events and TComplex to draw the Mandelbrot set.
5 ///
6 /// Pressing the keys 'z' and 'u' will zoom and unzoom the picture
7 /// near the mouse location, 'r' will reset to the default view.
8 ///
9 /// Try it (in compiled mode!) with: `root mandelbrot.C+`
10 ///
11 /// \macro_image (js)
12 ///
13 /// ### Details
14 ///
15 /// when a mouse event occurs the myexec() function is called (by
16 /// using AddExec). Depending on the pressed key, the mygenerate()
17 /// function is called, with the proper arguments. Note the
18 /// last_x and last_y variables that are used in myexec() to store
19 /// the last pointer coordinates (px is not a pointer position in
20 /// kKeyPress events).
21 ///
22 /// \macro_code
23 ///
24 /// \author Luigi Bardelli <bardelli@fi.infn.it>
25 
26 #include <TStyle.h>
27 #include <TROOT.h>
28 #include <TH2.h>
29 #include <TComplex.h>
30 #include <TVirtualPad.h>
31 #include <TCanvas.h>
32 
33 TH2F *last_histo=NULL;
34 
35 void mygenerate(double factor, double cen_x, double cen_y)
36 {
37  printf("Regenerating...\n");
38  // resize histo:
39  if(factor>0)
40  {
41  double dx=last_histo->GetXaxis()->GetXmax()-last_histo->GetXaxis()->GetXmin();
42  double dy=last_histo->GetYaxis()->GetXmax()-last_histo->GetYaxis()->GetXmin();
43  last_histo->SetBins(
44  last_histo->GetNbinsX(),
45  cen_x-factor*dx/2,
46  cen_x+factor*dx/2,
47  last_histo->GetNbinsY(),
48  cen_y-factor*dy/2,
49  cen_y+factor*dy/2
50  );
51  last_histo->Reset();
52  }
53  else
54  {
55  if(last_histo!=NULL) delete last_histo;
56  // allocate first view...
57  last_histo= new TH2F("h2",
58  "Mandelbrot [move mouse and press z to zoom, u to unzoom, r to reset]",
59  200,-2,2,200,-2,2);
60  last_histo->SetStats(0);
61  }
62  const int max_iter=50;
63  for(int bx=1;bx<=last_histo->GetNbinsX();bx++)
64  for(int by=1;by<=last_histo->GetNbinsY();by++)
65  {
66  double x=last_histo->GetXaxis()->GetBinCenter(bx);
67  double y=last_histo->GetYaxis()->GetBinCenter(by);
68  TComplex point( x,y);
69  TComplex z=point;
70  int iter=0;
71  while (z.Rho()<2){
72  z=z*z+point;
73  last_histo->Fill(x,y);
74  iter++;
75  if(iter>max_iter) break;
76  }
77  }
78  last_histo->SetContour(99);
79  last_histo->Draw("colz");
80  gPad->Modified();
81  gPad->Update();
82  printf("Done.\n");
83 }
84 
85 void myexec()
86 {
87  // get event information
88  int event = gPad->GetEvent();
89  int px = gPad->GetEventX();
90  int py = gPad->GetEventY();
91 
92  // some magic to get the coordinates...
93  double xd = gPad->AbsPixeltoX(px);
94  double yd = gPad->AbsPixeltoY(py);
95  float x = gPad->PadtoX(xd);
96  float y = gPad->PadtoY(yd);
97 
98  static float last_x;
99  static float last_y;
100 
101  if(event!=kKeyPress)
102  {
103  last_x=x;
104  last_y=y;
105  return;
106  }
107 
108  const double Z=2.;
109  switch(px){
110  case 'z': // ZOOM
111  mygenerate(1./Z, last_x, last_y);
112  break;
113  case 'u': // UNZOOM
114  mygenerate(Z , last_x, last_y);
115  break;
116  case 'r': // RESET
117  mygenerate(-1 , last_x, last_y);
118  break;
119  };
120 }
121 
122 void mandelbrot()
123 {
124  // cosmetics...
125  gStyle->SetPadGridX(kTRUE);
126  gStyle->SetPadGridY(kTRUE);
127  new TCanvas("canvas","View Mandelbrot set");
128  // this generates and draws the first view...
129  mygenerate(-1,0,0);
130 
131  // add exec
132  gPad->AddExec("myexec","myexec()");
133 }