Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
webdemo.C
Go to the documentation of this file.
1 /// \file
2 /// \ingroup tutorial_geom
3 /// Web-based GUI to draw the geometry shapes.
4 /// Using functionality of web geometry viewer
5 /// Based on original geodemo.C macro
6 ///
7 /// \macro_code
8 ///
9 /// \author Andrei Gheata
10 /// \author Sergey Linev
11 
12 #include <vector>
13 #include <string>
14 
15 #include "TMath.h"
16 #include "TRandom.h"
17 #include "TROOT.h"
18 #include "TGeoManager.h"
19 #include "TGeoNode.h"
20 #include "TGeoBBox.h"
21 #include "TGeoPara.h"
22 #include "TGeoTube.h"
23 #include "TGeoCone.h"
24 #include "TGeoEltu.h"
25 #include "TGeoSphere.h"
26 #include "TGeoTorus.h"
27 #include "TGeoTrd1.h"
28 #include "TGeoTrd2.h"
29 #include "TGeoParaboloid.h"
30 #include "TGeoHype.h"
31 #include "TGeoPcon.h"
32 #include "TGeoPgon.h"
33 #include "TGeoArb8.h"
34 #include "TGeoXtru.h"
35 #include "TGeoCompositeShape.h"
36 #include "TGeoPhysicalNode.h"
37 
38 #include <ROOT/RWebWindow.hxx>
39 #include <ROOT/REveGeomViewer.hxx>
40 
41 Bool_t comments = kTRUE;
42 Bool_t grotate = kFALSE;
43 Bool_t axis = kTRUE;
44 
45 std::string getOptions()
46 {
47  std::string opt;
48  if (grotate) opt.append("rotate;");
49  if (axis) opt.append("axis;");
50  return opt;
51 }
52 
53 // create here to keep it in memory
54 auto geomViewer = std::make_shared<ROOT::Experimental::REveGeomViewer>();
55 
56 auto helpWindow = ROOT::Experimental::RWebWindow::Create();
57 
58 auto mainWindow = ROOT::Experimental::RWebWindow::Create();
59 
60 void display()
61 {
62  geomViewer->SetShowHierarchy(false);
63  geomViewer->SetGeometry(gGeoManager);
64  geomViewer->Show({600, 600, 160, 0});
65 }
66 
67 //______________________________________________________________________________
68 void autorotate()
69 {
70  grotate = !grotate;
71  geomViewer->SetDrawOptions(getOptions());
72 }
73 
74 //______________________________________________________________________________
75 void axes()
76 {
77  axis = !axis;
78  geomViewer->SetDrawOptions(getOptions());
79 }
80 
81 //______________________________________________________________________________
82 void gcomments()
83 {
84  comments = !comments;
85  if (!comments)
86  helpWindow->CloseConnections();
87 }
88 
89 //______________________________________________________________________________
90 void SavePicture(const char *name, TObject *objcanvas, TObject *objvol, Int_t iaxis, Double_t step)
91 {
92  // TDOD: provide in geom viewer
93 }
94 
95 //______________________________________________________________________________
96 Int_t randomColor()
97 {
98  Double_t color = 7.*gRandom->Rndm();
99  return (1+Int_t(color));
100 }
101 
102 //______________________________________________________________________________
103 std::string AddDbl(const char *datamember, Double_t value, const char *comment)
104 {
105  return TString::Format("%10s = %5.2f => %s", datamember, value, comment).Data();
106 }
107 
108 //______________________________________________________________________________
109 std::string AddInt(const char *datamember, Int_t value, const char *comment)
110 {
111  return TString::Format("%10s = %5d => %s", datamember, value, comment).Data();
112 }
113 
114 //______________________________________________________________________________
115 void help(const std::vector<std::string> &info = {}, TGeoVolume *fvol = nullptr, Int_t iaxis = 0, const std::vector<std::string> &info2 = {})
116 {
117  if (!info.empty() && !comments)
118  return;
119 
120  std::vector<std::string> lines({
121  " >>>>>>> web geometry viewer <<<<<< ",
122  " Demo for building TGeo basic shapes and simple geometry. Shape parameters are",
123  " displayed in the right pad",
124  "- Click left mouse button to execute one demo",
125  "- While pointing the mouse to the pad containing the geometry, do:",
126  "- .... click-and-move to rotate",
127  "- .... use mouse wheel for zooming",
128  "- .... double click for reset position",
129  "- Execute box(1,8) to divide a box in 8 equal slices along X",
130  "- Most shapes can be divided on X,Y,Z,Rxy or Phi :",
131  "- .... root[0] <shape>(IAXIS, NDIV, START, STEP);",
132  " .... IAXIS = 1,2,3 meaning (X,Y,Z) or (Rxy, Phi, Z)",
133  " .... NDIV = number of slices",
134  " .... START = start slicing position",
135  " .... STEP = division step",
136  "- Click Comments ON/OFF to toggle comments",
137  "- Click Ideal/Align geometry to see how alignment works"
138  });
139 
140  helpWindow->SetDefaultPage("file:webhelp.html");
141 
142  unsigned connid = helpWindow->GetDisplayConnection();
143 
144  if (!info.empty()) {
145  lines = info;
146  TGeoPatternFinder *finder = (fvol && (iaxis > 0) && (iaxis < 4)) ? fvol->GetFinder() : nullptr;
147  if (finder) {
148  TGeoVolume *volume = finder->GetVolume();
149  TGeoShape *sh = volume->GetShape();
150  lines.emplace_back(Form("Division of %s on axis %d (%s)", volume->GetName(), iaxis, sh->GetAxisName(iaxis)));
151  lines.emplace_back(AddInt("fNdiv",finder->GetNdiv(),"number of divisions"));
152  lines.emplace_back(AddDbl("fStart",finder->GetStart(),"start divisioning position"));
153  lines.emplace_back(AddDbl("fStep",finder->GetStep(),"division step"));
154  }
155  if (!info2.empty())
156  lines.insert(lines.end(), info2.begin(), info2.end());
157  }
158  int height = 200;
159  if (lines.size() > 10) height = 50 + lines.size()*20;
160 
161  if (!connid) connid = helpWindow->Show({600, height, 160, 650});
162 
163  std::string msg = "";
164  bool first = true;
165  for (auto &line : lines) {
166  if (line.empty()) continue;
167  std::string style = "", p = "<p style='";
168  if (first) { style = "font-size:150%;color:red"; first = false; }
169  else if (line.find("----")==0) { style = "color:red"; }
170  else if (line.find("Execute")==0) { style = "color:blue"; }
171  else if (line.find("Division")==0) { style = "font-size:120%;color:green"; }
172  if (style.empty()) p = "<p>"; else { p.append(style); p.append("'>"); }
173  p.append(line);
174  p.append("</p>");
175  msg.append(p);
176  }
177 
178  if (msg.empty())
179  helpWindow->Send(connid, "Initial text");
180  else
181  helpWindow->Send(connid, msg);
182 }
183 
184 //______________________________________________________________________________
185 void box(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
186 {
187  if (iaxis<0 || iaxis>3) {
188  printf("Wrong division axis. Range is 1-3.\n");
189  return;
190  }
191 
192  if (gGeoManager) delete gGeoManager;
193  new TGeoManager("box", "poza1");
194  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
195  TGeoMedium *med = new TGeoMedium("MED",1,mat);
196  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
197  gGeoManager->SetTopVolume(top);
198  TGeoVolume *vol = gGeoManager->MakeBox("BOX",med, 20,30,40);
199  vol->SetLineColor(randomColor());
200  vol->SetLineWidth(2);
201  top->AddNode(vol,1);
202  if (iaxis) {
203  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
204  if (!slice) return;
205  slice->SetLineColor(randomColor());
206  }
207  gGeoManager->CloseGeometry();
208 
209  display();
210 
211  TGeoBBox *bbox = (TGeoBBox*)(vol->GetShape());
212 
213  help({"TGeoBBox - box class",
214  AddDbl("fDX",bbox->GetDX(),"half length in X"),
215  AddDbl("fDY",bbox->GetDY(),"half length in Y"),
216  AddDbl("fDZ",bbox->GetDZ(),"half length in Z"),
217  AddDbl("fOrigin[0]",(bbox->GetOrigin())[0],"box origin on X"),
218  AddDbl("fOrigin[1]",(bbox->GetOrigin())[1],"box origin on Y"),
219  AddDbl("fOrigin[2]",(bbox->GetOrigin())[2],"box origin on Z")},
220  vol, iaxis,
221  {"Execute: box(iaxis, ndiv, start, step) to divide this.",
222  "----- IAXIS can be 1, 2 or 3 (X, Y, Z)",
223  "----- NDIV must be a positive integer",
224  "----- START must be a valid axis offset within shape range on divided axis",
225  "----- STEP is the division step. START+NDIV*STEP must be in range also",
226  "----- If START and STEP are omitted, all range of the axis will be divided"});
227 }
228 
229 //______________________________________________________________________________
230 void para(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
231 {
232  if (iaxis<0 || iaxis>3) {
233  printf("Wrong division axis. Range is 1-3.\n");
234  return;
235  }
236  if (gGeoManager) delete gGeoManager;
237  new TGeoManager("para", "poza1");
238  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
239  TGeoMedium *med = new TGeoMedium("MED",1,mat);
240  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
241  gGeoManager->SetTopVolume(top);
242  TGeoVolume *vol = gGeoManager->MakePara("PARA",med, 20,30,40,30,15,30);
243  vol->SetLineColor(randomColor());
244  vol->SetLineWidth(2);
245  top->AddNode(vol,1);
246  if (iaxis) {
247  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
248  if (!slice) return;
249  slice->SetLineColor(randomColor());
250  }
251  gGeoManager->CloseGeometry();
252  gGeoManager->SetNsegments(80);
253 
254  display();
255 
256  TGeoPara *para = (TGeoPara*)(vol->GetShape());
257 
258  help({"TGeoPara - parallelepiped class",
259  AddDbl("fX", para->GetX(), "half length in X"),
260  AddDbl("fY", para->GetY(), "half length in Y"),
261  AddDbl("fZ", para->GetZ(), "half length in Z"),
262  AddDbl("fAlpha", para->GetAlpha(), "angle about Y of the Z bases"),
263  AddDbl("fTheta", para->GetTheta(), "inclination of para axis about Z"),
264  AddDbl("fPhi", para->GetPhi(), "phi angle of para axis")},
265  vol, iaxis,
266  {"Execute: para(iaxis, ndiv, start, step) to divide this.",
267  "----- IAXIS can be 1, 2 or 3 (X, Y, Z)", "----- NDIV must be a positive integer",
268  "----- START must be a valid axis offset within shape range on divided axis",
269  "----- STEP is the division step. START+NDIV*STEP must be in range also",
270  "----- If START and STEP are omitted, all range of the axis will be divided"});
271  // SavePicture("para",c,vol,iaxis,step);
272 }
273 
274 //______________________________________________________________________________
275 void tube(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
276 {
277  if (iaxis<0 || iaxis>3) {
278  printf("Wrong division axis. Range is 1-3.\n");
279  return;
280  }
281 
282  if (gGeoManager) delete gGeoManager;
283  new TGeoManager("tube", "poza2");
284  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
285  TGeoMedium *med = new TGeoMedium("MED",1,mat);
286  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
287  gGeoManager->SetTopVolume(top);
288  TGeoVolume *vol = gGeoManager->MakeTube("TUBE",med, 20,30,40);
289  vol->SetLineColor(randomColor());
290  vol->SetLineWidth(2);
291  top->AddNode(vol,1);
292  if (iaxis) {
293  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
294  if (!slice) return;
295  slice->SetLineColor(randomColor());
296  }
297  gGeoManager->CloseGeometry();
298  gGeoManager->SetNsegments(80);
299 
300  display();
301 
302  TGeoTube *tube = (TGeoTube*)(vol->GetShape());
303  help({"TGeoTube - tube class",
304  AddDbl("fRmin",tube->GetRmin(),"minimum radius"),
305  AddDbl("fRmax",tube->GetRmax(),"maximum radius"),
306  AddDbl("fDZ", tube->GetDZ(), "half length in Z")},
307  vol, iaxis,
308  {"Execute: tube(iaxis, ndiv, start, step) to divide this.",
309  "----- IAXIS can be 1, 2 or 3 (Rxy, Phi, Z)",
310  "----- NDIV must be a positive integer",
311  "----- START must be a valid axis offset within shape range on divided axis",
312  "----- STEP is the division step. START+NDIV*STEP must be in range also",
313  "----- If START and STEP are omitted, all range of the axis will be divided"});
314 
315 // SavePicture("tube",c,vol,iaxis,step);
316 }
317 
318 //______________________________________________________________________________
319 void tubeseg(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
320 {
321  if (iaxis<0 || iaxis>3) {
322  printf("Wrong division axis. Range is 1-3.\n");
323  return;
324  }
325 
326  if (gGeoManager) delete gGeoManager;
327  new TGeoManager("tubeseg", "poza3");
328  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
329  TGeoMedium *med = new TGeoMedium("MED",1,mat);
330  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
331  gGeoManager->SetTopVolume(top);
332  TGeoVolume *vol = gGeoManager->MakeTubs("TUBESEG",med, 20,30,40,-30,270);
333  vol->SetLineColor(randomColor());
334  if (iaxis) {
335  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
336  if (!slice) return;
337  slice->SetLineColor(randomColor());
338  }
339  vol->SetLineWidth(2);
340  top->AddNode(vol,1);
341  gGeoManager->CloseGeometry();
342 // gGeoManager->SetNsegments(40);
343  gGeoManager->SetNsegments(80);
344 
345  display();
346 
347  TGeoTubeSeg *tubeseg = (TGeoTubeSeg*)(vol->GetShape());
348 
349  help({ "TGeoTubeSeg - tube segment class",
350  AddDbl("fRmin",tubeseg->GetRmin(),"minimum radius"),
351  AddDbl("fRmax",tubeseg->GetRmax(),"maximum radius"),
352  AddDbl("fDZ", tubeseg->GetDZ(), "half length in Z"),
353  AddDbl("fPhi1",tubeseg->GetPhi1(),"first phi limit"),
354  AddDbl("fPhi2",tubeseg->GetPhi2(),"second phi limit")},
355  vol, iaxis,
356  {"Execute: tubeseg(iaxis, ndiv, start, step) to divide this.",
357  "----- IAXIS can be 1, 2 or 3 (Rxy, Phi, Z)",
358  "----- NDIV must be a positive integer",
359  "----- START must be a valid axis offset within shape range on divided axis",
360  "----- STEP is the division step. START+NDIV*STEP must be in range also",
361  "----- If START and STEP are omitted, all range of the axis will be divided"});
362 // SavePicture("tubeseg",c,vol,iaxis,step);
363 }
364 
365 //______________________________________________________________________________
366 void ctub(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
367 {
368  if (iaxis<0 || iaxis>2) {
369  printf("Wrong division axis. Range is 1-2.\n");
370  return;
371  }
372 
373  if (gGeoManager) delete gGeoManager;
374  new TGeoManager("ctub", "poza3");
375  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
376  TGeoMedium *med = new TGeoMedium("MED",1,mat);
377  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
378  gGeoManager->SetTopVolume(top);
379  Double_t theta = 160.*TMath::Pi()/180.;
380  Double_t phi = 30.*TMath::Pi()/180.;
381  Double_t nlow[3];
382  nlow[0] = TMath::Sin(theta)*TMath::Cos(phi);
383  nlow[1] = TMath::Sin(theta)*TMath::Sin(phi);
384  nlow[2] = TMath::Cos(theta);
385  theta = 20.*TMath::Pi()/180.;
386  phi = 60.*TMath::Pi()/180.;
387  Double_t nhi[3];
388  nhi[0] = TMath::Sin(theta)*TMath::Cos(phi);
389  nhi[1] = TMath::Sin(theta)*TMath::Sin(phi);
390  nhi[2] = TMath::Cos(theta);
391  TGeoVolume *vol = gGeoManager->MakeCtub("CTUB",med, 20,30,40,-30,250, nlow[0], nlow[1], nlow[2], nhi[0],nhi[1],nhi[2]);
392  vol->SetLineColor(randomColor());
393  if (iaxis) {
394  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
395  if (!slice) return;
396  slice->SetLineColor(randomColor());
397  }
398  vol->SetLineWidth(2);
399  top->AddNode(vol,1);
400  gGeoManager->CloseGeometry();
401 // gGeoManager->SetNsegments(40);
402  gGeoManager->SetNsegments(80);
403 
404  display();
405 
406  TGeoTubeSeg *tubeseg = (TGeoTubeSeg*)(vol->GetShape());
407 
408  help({ "TGeoTubeSeg - tube segment class",
409  AddDbl("fRmin",tubeseg->GetRmin(),"minimum radius"),
410  AddDbl("fRmax",tubeseg->GetRmax(),"maximum radius"),
411  AddDbl("fDZ", tubeseg->GetDZ(), "half length in Z"),
412  AddDbl("fPhi1",tubeseg->GetPhi1(),"first phi limit"),
413  AddDbl("fPhi2",tubeseg->GetPhi2(),"second phi limit")},
414  vol, iaxis);
415 // SavePicture("tubeseg",c,vol,iaxis,step);
416 }
417 
418 //______________________________________________________________________________
419 void cone(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
420 {
421  if (iaxis<0 || iaxis>3) {
422  printf("Wrong division axis. Range is 1-3.\n");
423  return;
424  } else if (iaxis==1) {
425  printf("cannot divide cone on Rxy\n");
426  return;
427  }
428 
429  if (gGeoManager) delete gGeoManager;
430  new TGeoManager("cone", "poza4");
431  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
432  TGeoMedium *med = new TGeoMedium("MED",1,mat);
433  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
434  gGeoManager->SetTopVolume(top);
435  TGeoVolume *vol = gGeoManager->MakeCone("CONE",med, 40,10,20,35,45);
436  vol->SetLineColor(randomColor());
437  vol->SetLineWidth(2);
438  if (iaxis) {
439  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
440  if (!slice) return;
441  slice->SetLineColor(randomColor());
442  }
443  top->AddNode(vol,1);
444  gGeoManager->CloseGeometry();
445  gGeoManager->SetNsegments(80);
446 
447  display();
448 
449  TGeoCone *cone = (TGeoCone*)(vol->GetShape());
450 
451  help({ "TGeoCone - cone class",
452  AddDbl("fDZ", cone->GetDZ(), "half length in Z"),
453  AddDbl("fRmin1",cone->GetRmin1(),"inner radius at -dz"),
454  AddDbl("fRmax1",cone->GetRmax1(),"outer radius at -dz"),
455  AddDbl("fRmin2",cone->GetRmin2(),"inner radius at +dz"),
456  AddDbl("fRmax2",cone->GetRmax2(),"outer radius at +dz")},
457  vol, iaxis,
458  {"Execute: cone(iaxis, ndiv, start, step) to divide this.",
459  "----- IAXIS can be 2 or 3 (Phi, Z)",
460  "----- NDIV must be a positive integer",
461  "----- START must be a valid axis offset within shape range on divided axis",
462  "----- STEP is the division step. START+NDIV*STEP must be in range also",
463  "----- If START and STEP are omitted, all range of the axis will be divided"});
464 // SavePicture("cone",c,vol,iaxis,step);
465 }
466 
467 //______________________________________________________________________________
468 void coneseg(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
469 {
470  if (iaxis<0 || iaxis>3) {
471  printf("Wrong division axis. Range is 1-3.\n");
472  return;
473  }
474 
475  if (gGeoManager) delete gGeoManager;
476  new TGeoManager("coneseg", "poza5");
477  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
478  TGeoMedium *med = new TGeoMedium("MED",1,mat);
479  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
480  gGeoManager->SetTopVolume(top);
481  TGeoVolume *vol = gGeoManager->MakeCons("CONESEG",med, 40,30,40,10,20,-30,250);
482  vol->SetLineColor(randomColor());
483 // vol->SetLineWidth(2);
484  top->AddNode(vol,1);
485  if (iaxis) {
486  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
487  if (!slice) return;
488  slice->SetLineColor(randomColor());
489  }
490  gGeoManager->CloseGeometry();
491  gGeoManager->SetNsegments(80);
492 
493  display();
494 
495  TGeoConeSeg *coneseg = (TGeoConeSeg*)(vol->GetShape());
496 
497  help({ "TGeoConeSeg - coneseg class",
498  AddDbl("fDZ", coneseg->GetDZ(), "half length in Z"),
499  AddDbl("fRmin1",coneseg->GetRmin1(),"inner radius at -dz"),
500  AddDbl("fRmax1",coneseg->GetRmax1(),"outer radius at -dz"),
501  AddDbl("fRmin2",coneseg->GetRmin1(),"inner radius at +dz"),
502  AddDbl("fRmax2",coneseg->GetRmax1(),"outer radius at +dz"),
503  AddDbl("fPhi1",coneseg->GetPhi1(),"first phi limit"),
504  AddDbl("fPhi2",coneseg->GetPhi2(),"second phi limit")},
505  vol, iaxis,
506  {"Execute: coneseg(iaxis, ndiv, start, step) to divide this.",
507  "----- IAXIS can be 2 or 3 (Phi, Z)",
508  "----- NDIV must be a positive integer",
509  "----- START must be a valid axis offset within shape range on divided axis",
510  "----- STEP is the division step. START+NDIV*STEP must be in range also",
511  "----- If START and STEP are omitted, all range of the axis will be divided"});
512 // SavePicture("coneseg",c,vol,iaxis,step);
513 }
514 
515 //______________________________________________________________________________
516 void eltu(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
517 {
518  if (gGeoManager) delete gGeoManager;
519  new TGeoManager("eltu", "poza6");
520  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
521  TGeoMedium *med = new TGeoMedium("MED",1,mat);
522  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
523  gGeoManager->SetTopVolume(top);
524  TGeoVolume *vol = gGeoManager->MakeEltu("ELTU",med, 30,10,40);
525  vol->SetLineColor(randomColor());
526 // vol->SetLineWidth(2);
527  top->AddNode(vol,1);
528  if (iaxis) {
529  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
530  if (!slice) return;
531  slice->SetLineColor(randomColor());
532  }
533  gGeoManager->CloseGeometry();
534  gGeoManager->SetNsegments(80);
535 
536  display();
537 
538  TGeoEltu *eltu = (TGeoEltu*)(vol->GetShape());
539 
540  help({ "TGeoEltu - eltu class",
541  AddDbl("fA",eltu->GetA(), "semi-axis along x"),
542  AddDbl("fB",eltu->GetB(), "semi-axis along y"),
543  AddDbl("fDZ", eltu->GetDZ(), "half length in Z")},
544  vol, iaxis,
545  {"Execute: eltu(iaxis, ndiv, start, step) to divide this.",
546  "----- IAXIS can be 2 or 3 (Phi, Z)",
547  "----- NDIV must be a positive integer",
548  "----- START must be a valid axis offset within shape range on divided axis",
549  "----- STEP is the division step. START+NDIV*STEP must be in range also",
550  "----- If START and STEP are omitted, all range of the axis will be divided"});
551 // SavePicture("eltu",c,vol,iaxis,step);
552 }
553 
554 //______________________________________________________________________________
555 void sphere(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
556 {
557  if (iaxis!=0) {
558  printf("Cannot divide spheres\n");
559  return;
560  }
561 
562  if (gGeoManager) delete gGeoManager;
563  new TGeoManager("sphere", "poza7");
564  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
565  TGeoMedium *med = new TGeoMedium("MED",1,mat);
566  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
567  gGeoManager->SetTopVolume(top);
568  TGeoVolume *vol = gGeoManager->MakeSphere("SPHERE",med, 30,40,60,120,30,240);
569  vol->SetLineColor(randomColor());
570  vol->SetLineWidth(2);
571  top->AddNode(vol,1);
572  if (iaxis) {
573  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
574  if (!slice) return;
575  slice->SetLineColor(randomColor());
576  }
577  gGeoManager->CloseGeometry();
578  gGeoManager->SetNsegments(80);
579 
580  display();
581 
582  TGeoSphere *sphere = (TGeoSphere*)(vol->GetShape());
583 
584  help({ "TGeoSphere- sphere class",
585  AddDbl("fRmin",sphere->GetRmin(),"inner radius"),
586  AddDbl("fRmax",sphere->GetRmax(),"outer radius"),
587  AddDbl("fTheta1",sphere->GetTheta1(),"lower theta limit"),
588  AddDbl("fTheta2",sphere->GetTheta2(),"higher theta limit"),
589  AddDbl("fPhi1",sphere->GetPhi1(),"lower phi limit"),
590  AddDbl("fPhi2",sphere->GetPhi2(),"higher phi limit")},
591  vol, iaxis);
592 // SavePicture("sphere",c,vol,iaxis,step);
593 }
594 
595 //______________________________________________________________________________
596 void torus(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
597 {
598  if (iaxis!=0) {
599  printf("Cannot divide a torus\n");
600  return;
601  }
602 
603  if (gGeoManager) delete gGeoManager;
604  new TGeoManager("torus", "poza2");
605  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
606  TGeoMedium *med = new TGeoMedium("MED",1,mat);
607  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
608  gGeoManager->SetTopVolume(top);
609  TGeoVolume *vol = gGeoManager->MakeTorus("TORUS",med, 40,20,25,0,270);
610  vol->SetLineColor(randomColor());
611  top->AddNode(vol,1);
612  if (iaxis) {
613  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
614  if (!slice) return;
615  slice->SetLineColor(2);
616  }
617  gGeoManager->CloseGeometry();
618  gGeoManager->SetNsegments(80);
619 
620  display();
621 
622  TGeoTorus *tor = (TGeoTorus*)(vol->GetShape());
623 
624  help({ "TGeoTorus - torus class",
625  AddDbl("fR",tor->GetR(),"radius of the ring"),
626  AddDbl("fRmin",tor->GetRmin(),"minimum radius"),
627  AddDbl("fRmax",tor->GetRmax(),"maximum radius"),
628  AddDbl("fPhi1", tor->GetPhi1(), "starting phi angle"),
629  AddDbl("fDphi", tor->GetDphi(), "phi range")},
630  vol, iaxis);
631 }
632 
633 //______________________________________________________________________________
634 void trd1(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
635 {
636  if (iaxis<0 || iaxis>3) {
637  printf("Wrong division axis. Range is 1-3.\n");
638  return;
639  } else if (iaxis==1) {
640  printf("Cannot divide trd1 on X axis\n");
641  return;
642  }
643 
644 
645  if (gGeoManager) delete gGeoManager;
646  new TGeoManager("trd1", "poza8");
647  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
648  TGeoMedium *med = new TGeoMedium("MED",1,mat);
649  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
650  gGeoManager->SetTopVolume(top);
651  TGeoVolume *vol = gGeoManager->MakeTrd1("Trd1",med, 10,20,30,40);
652  vol->SetLineColor(randomColor());
653  vol->SetLineWidth(2);
654  top->AddNode(vol,1);
655  if (iaxis) {
656  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
657  if (!slice) return;
658  slice->SetLineColor(randomColor());
659  }
660  gGeoManager->CloseGeometry();
661  gGeoManager->SetNsegments(80);
662 
663  display();
664 
665  TGeoTrd1 *trd1 = (TGeoTrd1*)(vol->GetShape());
666 
667  help({ "TGeoTrd1 - Trd1 class",
668  AddDbl("fDx1",trd1->GetDx1(),"half length in X at lower Z surface(-dz)"),
669  AddDbl("fDx2",trd1->GetDx2(),"half length in X at higher Z surface(+dz)"),
670  AddDbl("fDy",trd1->GetDy(),"half length in Y"),
671  AddDbl("fDz",trd1->GetDz(),"half length in Z")},
672  vol, iaxis,
673  {"Execute: trd1(iaxis, ndiv, start, step) to divide this.",
674  "----- IAXIS can be 2 or 3 (Y, Z)",
675  "----- NDIV must be a positive integer",
676  "----- START must be a valid axis offset within shape range on divided axis",
677  "----- STEP is the division step. START+NDIV*STEP must be in range also",
678  "----- If START and STEP are omitted, all range of the axis will be divided"});
679 // SavePicture("trd1",c,vol,iaxis,step);
680  }
681 
682 //______________________________________________________________________________
683 void parab()
684 {
685  if (gGeoManager) delete gGeoManager;
686  new TGeoManager("parab", "paraboloid");
687  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
688  TGeoMedium *med = new TGeoMedium("MED",1,mat);
689  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
690  gGeoManager->SetTopVolume(top);
691  TGeoVolume *vol = gGeoManager->MakeParaboloid("PARAB",med,0, 40, 50);
692  TGeoParaboloid *par = (TGeoParaboloid*)vol->GetShape();
693  vol->SetLineColor(randomColor());
694  vol->SetLineWidth(2);
695  top->AddNode(vol,1);
696  gGeoManager->CloseGeometry();
697  gGeoManager->SetNsegments(80);
698 
699  display();
700 
701  help({ "TGeoParaboloid - Paraboloid class",
702  AddDbl("fRlo",par->GetRlo(),"radius at Z=-dz"),
703  AddDbl("fRhi",par->GetRhi(),"radius at Z=+dz"),
704  AddDbl("fDz",par->GetDz(),"half-length on Z axis"),
705  "----- A paraboloid is described by the equation:",
706  "----- z = a*r*r + b; where: r = x*x + y*y",
707  "----- Create with: TGeoParaboloid *parab = new TGeoParaboloid(rlo, rhi, dz);",
708  "----- dz: half-length in Z (range from -dz to +dz",
709  "----- rlo: radius at z=-dz given by: -dz = a*rlo*rlo + b",
710  "----- rhi: radius at z=+dz given by: dz = a*rhi*rhi + b",
711  "----- rlo != rhi; both >= 0"});
712 }
713 
714 //______________________________________________________________________________
715 void hype()
716 {
717  if (gGeoManager) delete gGeoManager;
718  new TGeoManager("hype", "hyperboloid");
719  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
720  TGeoMedium *med = new TGeoMedium("MED",1,mat);
721  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
722  gGeoManager->SetTopVolume(top);
723  TGeoVolume *vol = gGeoManager->MakeHype("HYPE",med,10, 45 ,20,45,40);
724  TGeoHype *hype = (TGeoHype*)vol->GetShape();
725  vol->SetLineColor(randomColor());
726  vol->SetLineWidth(2);
727  top->AddNode(vol,1);
728  gGeoManager->CloseGeometry();
729  gGeoManager->SetNsegments(80);
730 
731  display();
732 
733  help({ "TGeoHype - Hyperboloid class",
734  AddDbl("fRmin",hype->GetRmin(),"minimum inner radius"),
735  AddDbl("fStIn",hype->GetStIn(),"inner surface stereo angle [deg]"),
736  AddDbl("fRmax",hype->GetRmax(),"minimum outer radius"),
737  AddDbl("fStOut",hype->GetStOut(),"outer surface stereo angle [deg]"),
738  AddDbl("fDz",hype->GetDz(),"half-length on Z axis"),
739  "----- A hyperboloid is described by the equation:",
740  "----- r^2 - (tan(stereo)*z)^2 = rmin^2; where: r = x*x + y*y",
741  "----- Create with: TGeoHype *hype = new TGeoHype(rin, stin, rout, stout, dz);",
742  "----- rin < rout; rout > 0",
743  "----- rin = 0; stin > 0 => inner surface conical",
744  "----- stin/stout = 0 => corresponding surface cylindrical"});
745 }
746 
747 //______________________________________________________________________________
748 void pcon(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
749 {
750  if (iaxis<0 || iaxis>3) {
751  printf("Wrong division axis. Range is 1-3.\n");
752  return;
753  } else if (iaxis==1) {
754  printf("Cannot divide pcon on Rxy\n");
755  return;
756  }
757 
758  if (gGeoManager) delete gGeoManager;
759  new TGeoManager("pcon", "poza10");
760  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
761  TGeoMedium *med = new TGeoMedium("MED",1,mat);
762  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
763  gGeoManager->SetTopVolume(top);
764  TGeoVolume *vol = gGeoManager->MakePcon("PCON",med, -30.0,300,4);
765  TGeoPcon *pcon = (TGeoPcon*)(vol->GetShape());
766  pcon->DefineSection(0,0,15,20);
767  pcon->DefineSection(1,20,15,20);
768  pcon->DefineSection(2,20,15,25);
769  pcon->DefineSection(3,50,15,20);
770  vol->SetLineColor(randomColor());
771  vol->SetLineWidth(2);
772  top->AddNode(vol,1);
773  if (iaxis) {
774  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
775  if (!slice) return;
776  slice->SetLineColor(randomColor());
777  }
778  gGeoManager->CloseGeometry();
779  gGeoManager->SetNsegments(80);
780 
781  display();
782 
783  std::vector<std::string> lines = { "TGeoPcon - pcon class",
784  AddDbl("fPhi1",pcon->GetPhi1(),"lower phi limit"),
785  AddDbl("fDphi",pcon->GetDphi(),"phi range"),
786  AddDbl("fNz",pcon->GetNz(),"number of z planes")};
787 
788  for (Int_t j=0; j<pcon->GetNz(); j++)
789  lines.emplace_back(Form("fZ[%i]=%5.2f fRmin[%i]=%5.2f fRmax[%i]=%5.2f",
790  j,pcon->GetZ()[j],j,pcon->GetRmin()[j],j,pcon->GetRmax()[j]));
791 
792  help(lines, vol, iaxis,
793  {"Execute: pcon(iaxis, ndiv, start, step) to divide this.",
794  "----- IAXIS can be 2 or 3 (Phi, Z)",
795  "----- NDIV must be a positive integer",
796  "----- START must be a valid axis offset within shape range on divided axis",
797  "----- STEP is the division step. START+NDIV*STEP must be in range also",
798  "----- If START and STEP are omitted, all range of the axis will be divided"});
799 // SavePicture("pcon",c,vol,iaxis,step);
800 }
801 
802 //______________________________________________________________________________
803 void pgon(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
804 {
805  if (iaxis<0 || iaxis>3) {
806  printf("Wrong division axis. Range is 1-3.\n");
807  return;
808  } else if (iaxis==1) {
809  printf("Cannot divide pgon on Rxy\n");
810  return;
811  }
812 
813  if (gGeoManager) delete gGeoManager;
814  new TGeoManager("pgon", "poza11");
815  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
816  TGeoMedium *med = new TGeoMedium("MED",1,mat);
817  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,150,150,100);
818  gGeoManager->SetTopVolume(top);
819  TGeoVolume *vol = gGeoManager->MakePgon("PGON",med, -45.0,270.0,4,4);
820  TGeoPgon *pgon = (TGeoPgon*)(vol->GetShape());
821  pgon->DefineSection(0,-70,45,50);
822  pgon->DefineSection(1,0,35,40);
823  pgon->DefineSection(2,0,30,35);
824  pgon->DefineSection(3,70,90,100);
825  vol->SetLineColor(randomColor());
826  vol->SetLineWidth(2);
827  top->AddNode(vol,1);
828  if (iaxis) {
829  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
830  if (!slice) return;
831  slice->SetLineColor(randomColor());
832  }
833  gGeoManager->CloseGeometry();
834  gGeoManager->SetNsegments(80);
835 
836  display();
837 
838  std::vector<std::string> lines({ "TGeoPgon - pgon class",
839  AddDbl("fPhi1",pgon->GetPhi1(),"lower phi limit"),
840  AddDbl("fDphi",pgon->GetDphi(),"phi range"),
841  AddDbl("fNedges",pgon->GetNedges(),"number of edges"),
842  AddDbl("fNz",pgon->GetNz(),"number of z planes")});
843 
844  for (Int_t j=0; j<pgon->GetNz(); j++)
845  lines.emplace_back(Form("fZ[%i]=%5.2f fRmin[%i]=%5.2f fRmax[%i]=%5.2f",
846  j,pgon->GetZ()[j],j,pgon->GetRmin()[j],j,pgon->GetRmax()[j]));
847 
848  help(lines, vol, iaxis,
849  {"Execute: pgon(iaxis, ndiv, start, step) to divide this.",
850  "----- IAXIS can be 2 or 3 (Phi, Z)",
851  "----- NDIV must be a positive integer",
852  "----- START must be a valid axis offset within shape range on divided axis",
853  "----- STEP is the division step. START+NDIV*STEP must be in range also",
854  "----- If START and STEP are omitted, all range of the axis will be divided"});
855 
856  // SavePicture("pgon",c,vol,iaxis,step);
857 }
858 
859 //______________________________________________________________________________
860 void arb8(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
861 {
862  if (iaxis!=0) {
863  printf("Cannot divide arb8\n");
864  return;
865  }
866 
867  if (gGeoManager) delete gGeoManager;
868  new TGeoManager("arb8", "poza12");
869  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
870  TGeoMedium *med = new TGeoMedium("MED",1,mat);
871  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
872  gGeoManager->SetTopVolume(top);
873  TGeoArb8 *arb = new TGeoArb8(20);
874  arb->SetVertex(0,-30,-25);
875  arb->SetVertex(1,-25,25);
876  arb->SetVertex(2,5,25);
877  arb->SetVertex(3,25,-25);
878  arb->SetVertex(4,-28,-23);
879  arb->SetVertex(5,-23,27);
880  arb->SetVertex(6,-23,27);
881  arb->SetVertex(7,13,-27);
882  TGeoVolume *vol = new TGeoVolume("ARB8",arb,med);
883  vol->SetLineColor(randomColor());
884  vol->SetLineWidth(2);
885  top->AddNode(vol,1);
886  if (iaxis) {
887  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
888  if (!slice) return;
889  slice->SetLineColor(randomColor());
890  }
891  gGeoManager->CloseGeometry();
892  gGeoManager->SetNsegments(80);
893 
894  display();
895 
896  std::vector<std::string> lines({"TGeoArb8 - arb8 class",
897  AddDbl("fDz",arb->GetDz(),"Z half length"),
898  "Vertices on lower Z plane:"});
899 
900  Double_t *vert = arb->GetVertices();
901  for (Int_t i=0; i<8; i++) {
902  if (i==4) lines.emplace_back("Vertices on higher Z plane:");
903  lines.emplace_back(Form(" fXY[%d] = (%5.2f, %5.2f)", i, vert[2*i], vert[2*i+1]));
904  }
905 
906  help(lines, vol, iaxis);
907 // SavePicture("arb8",c,vol,iaxis,step);
908 }
909 
910 //______________________________________________________________________________
911 void trd2(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
912 {
913  if (iaxis && iaxis!=3) {
914  printf("Wrong division axis. trd2 can divide only in Z (3)\n");
915  return;
916  }
917 
918  if (gGeoManager) delete gGeoManager;
919  new TGeoManager("trd2", "poza9");
920  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
921  TGeoMedium *med = new TGeoMedium("MED",1,mat);
922  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
923  gGeoManager->SetTopVolume(top);
924  TGeoVolume *vol = gGeoManager->MakeTrd2("Trd2",med, 10,20,30,10,40);
925  vol->SetLineColor(randomColor());
926  vol->SetLineWidth(2);
927  top->AddNode(vol,1);
928  if (iaxis) {
929  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
930  if (!slice) return;
931  slice->SetLineColor(randomColor());
932  }
933  gGeoManager->CloseGeometry();
934  gGeoManager->SetNsegments(80);
935 
936  display();
937 
938  TGeoTrd2 *trd2 = (TGeoTrd2*)(vol->GetShape());
939 
940  help({ "TGeoTrd2 - Trd2 class",
941  AddDbl("fDx1",trd2->GetDx1(),"half length in X at lower Z surface(-dz)"),
942  AddDbl("fDx2",trd2->GetDx2(),"half length in X at higher Z surface(+dz)"),
943  AddDbl("fDy1",trd2->GetDy1(),"half length in Y at lower Z surface(-dz)"),
944  AddDbl("fDy2",trd2->GetDy2(),"half length in Y at higher Z surface(-dz)"),
945  AddDbl("fDz",trd2->GetDz(),"half length in Z")},
946  vol, iaxis,
947  {"Execute: trd2(iaxis, ndiv, start, step) to divide this.",
948  "----- IAXIS can be only 3 (Z)",
949  "----- NDIV must be a positive integer",
950  "----- START must be a valid axis offset within shape range on divided axis",
951  "----- STEP is the division step. START+NDIV*STEP must be in range also",
952  "----- If START and STEP are omitted, all range of the axis will be divided"});
953 // SavePicture("trd2",c,vol,iaxis,step);
954 }
955 
956 //______________________________________________________________________________
957 void trap(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
958 {
959  if (iaxis && iaxis!=3) {
960  printf("Wrong division axis. Can divide only in Z (3)\n");
961  return;
962  }
963 
964  if (gGeoManager) delete gGeoManager;
965  new TGeoManager("trap", "poza10");
966  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
967  TGeoMedium *med = new TGeoMedium("MED",1,mat);
968  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
969  gGeoManager->SetTopVolume(top);
970  TGeoVolume *vol = gGeoManager->MakeTrap("Trap",med, 30,15,30,20,10,15,0,20,10,15,0);
971  vol->SetLineColor(randomColor());
972  vol->SetLineWidth(2);
973  top->AddNode(vol,1);
974  if (iaxis) {
975  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
976  if (!slice) return;
977  slice->SetLineColor(randomColor());
978  }
979  gGeoManager->CloseGeometry();
980  gGeoManager->SetNsegments(80);
981 
982  display();
983 
984  TGeoTrap *trap = (TGeoTrap*)(vol->GetShape());
985 
986  help({ "TGeoTrap - Trapezoid class",
987  AddDbl("fDz",trap->GetDz(),"half length in Z"),
988  AddDbl("fTheta",trap->GetTheta(),"theta angle of trapezoid axis"),
989  AddDbl("fPhi",trap->GetPhi(),"phi angle of trapezoid axis"),
990  AddDbl("fH1",trap->GetH1(),"half length in y at -fDz"),
991  AddDbl("fAlpha1",trap->GetAlpha1(),"angle between centers of x edges and y axis at -fDz"),
992  AddDbl("fBl1",trap->GetBl1(),"half length in x at -dZ and y=-fH1"),
993  AddDbl("fTl1",trap->GetTl1(),"half length in x at -dZ and y=+fH1"),
994  AddDbl("fH2",trap->GetH2(),"half length in y at +fDz"),
995  AddDbl("fBl2",trap->GetBl2(),"half length in x at +dZ and y=-fH1"),
996  AddDbl("fTl2",trap->GetTl2(),"half length in x at +dZ and y=+fH1"),
997  AddDbl("fAlpha2",trap->GetAlpha2(),"angle between centers of x edges and y axis at +fDz")},
998  vol, iaxis,
999  {"Execute: trap(iaxis, ndiv, start, step) to divide this.",
1000  "----- IAXIS can be only 3 (Z)",
1001  "----- NDIV must be a positive integer",
1002  "----- START must be a valid axis offset within shape range on divided axis",
1003  "----- STEP is the division step. START+NDIV*STEP must be in range also",
1004  "----- If START and STEP are omitted, all range of the axis will be divided"});
1005 // SavePicture("trap",c,vol,iaxis,step);
1006 }
1007 
1008 //______________________________________________________________________________
1009 void gtra(Int_t iaxis=0, Int_t ndiv=8, Double_t start=0, Double_t step=0)
1010 {
1011  if (iaxis && iaxis!=3) {
1012  printf("Wrong division axis. Can divide only in Z (3)\n");
1013  return;
1014  }
1015 
1016  if (gGeoManager) delete gGeoManager;
1017  new TGeoManager("gtra", "poza11");
1018  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
1019  TGeoMedium *med = new TGeoMedium("MED",1,mat);
1020  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
1021  gGeoManager->SetTopVolume(top);
1022  TGeoVolume *vol = gGeoManager->MakeGtra("Gtra",med, 30,15,30,30,20,10,15,0,20,10,15,0);
1023  vol->SetLineColor(randomColor());
1024  vol->SetLineWidth(2);
1025  top->AddNode(vol,1);
1026  if (iaxis) {
1027  TGeoVolume *slice = vol->Divide("SLICE",iaxis,ndiv,start,step);
1028  if (!slice) return;
1029  slice->SetLineColor(randomColor());
1030  }
1031  gGeoManager->CloseGeometry();
1032  gGeoManager->SetNsegments(80);
1033 
1034  display();
1035 
1036  TGeoGtra *trap = (TGeoGtra*)(vol->GetShape());
1037 
1038  help({ "TGeoGtra - Twisted trapezoid class",
1039  AddDbl("fDz",trap->GetDz(),"half length in Z"),
1040  AddDbl("fTheta",trap->GetTheta(),"theta angle of trapezoid axis"),
1041  AddDbl("fPhi",trap->GetPhi(),"phi angle of trapezoid axis"),
1042  AddDbl("fTwist",trap->GetTwistAngle(), "twist angle"),
1043  AddDbl("fH1",trap->GetH1(),"half length in y at -fDz"),
1044  AddDbl("fAlpha1",trap->GetAlpha1(),"angle between centers of x edges and y axis at -fDz"),
1045  AddDbl("fBl1",trap->GetBl1(),"half length in x at -dZ and y=-fH1"),
1046  AddDbl("fTl1",trap->GetTl1(),"half length in x at -dZ and y=+fH1"),
1047  AddDbl("fH2",trap->GetH2(),"half length in y at +fDz"),
1048  AddDbl("fBl2",trap->GetBl2(),"half length in x at +dZ and y=-fH1"),
1049  AddDbl("fTl2",trap->GetTl2(),"half length in x at +dZ and y=+fH1"),
1050  AddDbl("fAlpha2",trap->GetAlpha2(),"angle between centers of x edges and y axis at +fDz")},
1051  vol, iaxis,
1052  {"Execute: gtra(iaxis, ndiv, start, step) to divide this.",
1053  "----- IAXIS can be only 3 (Z)",
1054  "----- NDIV must be a positive integer",
1055  "----- START must be a valid axis offset within shape range on divided axis",
1056  "----- STEP is the division step. START+NDIV*STEP must be in range also",
1057  "----- If START and STEP are omitted, all range of the axis will be divided"});
1058 // SavePicture("gtra",c,vol,iaxis,step);
1059 }
1060 
1061 //______________________________________________________________________________
1062 void xtru()
1063 {
1064  if (gGeoManager) delete gGeoManager;
1065  new TGeoManager("xtru", "poza12");
1066  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
1067  TGeoMedium *med = new TGeoMedium("MED",1,mat);
1068  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
1069  gGeoManager->SetTopVolume(top);
1070  TGeoVolume *vol = gGeoManager->MakeXtru("XTRU",med,4);
1071  TGeoXtru *xtru = (TGeoXtru*)vol->GetShape();
1072  Double_t x[8] = {-30,-30,30,30,15,15,-15,-15};
1073  Double_t y[8] = {-30,30,30,-30,-30,15,15,-30};
1074  xtru->DefinePolygon(8,x,y);
1075  xtru->DefineSection(0,-40, -20., 10., 1.5);
1076  xtru->DefineSection(1, 10, 0., 0., 0.5);
1077  xtru->DefineSection(2, 10, 0., 0., 0.7);
1078  xtru->DefineSection(3, 40, 10., 20., 0.9);
1079  vol->SetLineColor(randomColor());
1080  vol->SetLineWidth(2);
1081  top->AddNode(vol,1);
1082  gGeoManager->CloseGeometry();
1083  gGeoManager->SetNsegments(80);
1084 
1085  display();
1086 
1087  help({ "TGeoXtru - Polygonal extrusion class",
1088  AddDbl("fNvert",xtru->GetNvert(),"number of polygone vertices"),
1089  AddDbl("fNz",xtru->GetNz(),"number of Z sections"),
1090  "----- Any Z section is an arbitrary polygone",
1091  "----- The shape can have an arbitrary number of Z sections, as for pcon/pgon",
1092  "----- Create with: TGeoXtru *xtru = new TGeoXtru(nz);",
1093  "----- Define the blueprint polygon :",
1094  "----- Double_t x[8] = {-30,-30,30,30,15,15,-15,-15};",
1095  "----- Double_t y[8] = {-30,30,30,-30,-30,15,15,-30};",
1096  "----- xtru->DefinePolygon(8,x,y);",
1097  "----- Define translations/scales of the blueprint for Z sections :",
1098  "----- xtru->DefineSection(i, Zsection, x0, y0, scale);",
1099  "----- Sections have to be defined in increasing Z order",
1100  "----- 2 sections can be defined at same Z (not for first/last sections)"});
1101 }
1102 
1103 //______________________________________________________________________________
1104 void composite()
1105 {
1106 
1107  if (gGeoManager) delete gGeoManager;
1108  new TGeoManager("xtru", "poza12");
1109  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
1110  TGeoMedium *med = new TGeoMedium("MED",1,mat);
1111  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,100);
1112  gGeoManager->SetTopVolume(top);
1113 
1114  // define shape components with names
1115  TGeoPgon *pgon = new TGeoPgon("pg",0.,360.,6,2);
1116  pgon->DefineSection(0,0,0,20);
1117  pgon->DefineSection(1, 30,0,20);
1118 
1119  new TGeoSphere("sph", 40., 45.);
1120  // define named geometrical transformations with names
1121  TGeoTranslation *tr = new TGeoTranslation(0., 0., 45.);
1122  tr->SetName("tr");
1123  // register all used transformations
1124  tr->RegisterYourself();
1125  // create the composite shape based on a Boolean expression
1126  TGeoCompositeShape *cs = new TGeoCompositeShape("mir", "sph:tr*pg");
1127 
1128  TGeoVolume *vol = new TGeoVolume("COMP",cs);
1129  vol->SetLineColor(randomColor());
1130  top->AddNode(vol,1);
1131  gGeoManager->CloseGeometry();
1132  gGeoManager->SetNsegments(100);
1133 
1134  display();
1135 
1136  help({ "TGeoCompositeShape - composite shape class",
1137  "----- Define the shape components and don't forget to name them",
1138  "----- Define geometrical transformations that apply to shape components",
1139  "----- Name all transformations and register them",
1140  "----- Define the composite shape based on a Boolean expression",
1141  " TGeoCompositeShape(\"someName\", \"expression\")",
1142  "----- Expression is made of <shapeName:transfName> components related by Boolean operators",
1143  "----- Boolean operators can be: (+) union, (-) subtraction and (*) intersection",
1144  "----- Use parenthesis in the expression to force precedence"});
1145 }
1146 
1147 //______________________________________________________________________________
1148 void ideal()
1149 {
1150 // This is an ideal geometry. In real life, some geometry pieces are moved/rotated
1151 // with respect to their ideal positions. This is called alignment. Alignment
1152 // operations can be handled by TGeo starting from a CLOSED geometry (applied a posteriori)
1153 // Alignment is handled by PHYSICAL NODES, representing an unique object in geometry.
1154 //
1155 // Creating physical nodes:
1156 // 1. TGeoPhysicalNode *node = gGeoManager->MakePhysicalNode(const char *path)
1157 // - creates a physical node represented by path
1158 // - path can be : TOP_1/A_2/B_3
1159 // - B_3 is the 'final node' e.g. the logical node represented by this physical node
1160 // 2. TGeoPhysicalNode *node = gGeoManager->MakePhysicalNode()
1161 // - creates a physical node representing the current modeller state
1162 
1163 // Setting visualisation options for TGeoPhysicalNode *node:
1164 // 1. node->SetVisibility(Bool_t flag); // set node visible(*) or invisible
1165 // 2. node->SetIsVolAtt(Bool_t flag); // set line attributes to match the ones of the volumes in the branch
1166 // - default - TRUE
1167 // - when called with FALSE - the attributes defined for the physical node will be taken
1168 // node->SetLineColor(color);
1169 // node->SetLineWidth(width);
1170 // node->SetLineStyle(style);
1171 // 3. node->SetVisibleFull(Bool_t flag); // not only last node in the branch is visible (default)
1172 //
1173 // Activating/deactivating physical nodes drawing - not needed in case of alignment
1174 
1175 // Aligning physical nodes
1176 //==========================
1177 // node->Align(TGeoMatrix *newmat, TGeoShape *newshape, Bool_t check=kFALSE);
1178 // newmat = new matrix to replace final node LOCAL matrix
1179 // newshape = new shape to replace final node shape
1180 // check = optional check if the new aligned node is overlapping
1181 // gGeoManager->SetDrawExtraPaths(Bool_t flag)
1182 
1183  if (gGeoManager) delete gGeoManager;
1184  new TGeoManager("alignment", "Ideal geometry");
1185  TGeoMaterial *mat = new TGeoMaterial("Al", 26.98,13,2.7);
1186  TGeoMedium *med = new TGeoMedium("MED",1,mat);
1187  TGeoVolume *top = gGeoManager->MakeBox("TOP",med,100,100,10);
1188  gGeoManager->SetTopVolume(top);
1189  TGeoVolume *slicex = top->Divide("SX",1,10,-100,10);
1190  TGeoVolume *slicey = slicex->Divide("SY",2,10,-100,10);
1191  TGeoVolume *vol = gGeoManager->MakePgon("CELL",med,0.,360.,6,2);
1192  TGeoPgon *pgon = (TGeoPgon*)(vol->GetShape());
1193  pgon->DefineSection(0,-5,0.,2.);
1194  pgon->DefineSection(1,5,0.,2.);
1195  vol->SetLineColor(randomColor());
1196  slicey->AddNode(vol,1);
1197  gGeoManager->CloseGeometry();
1198  gGeoManager->SetNsegments(80);
1199 
1200  display();
1201 
1202  help({ "Ideal / Aligned geometry",
1203  "-- Create physical nodes for the objects you want to align",
1204  "-- You must start from a valid CLOSED geometry",
1205  " TGeoPhysicalNode *node = gGeoManager->MakePhysicalNode(const char *path)",
1206  " + creates a physical node represented by path, e.g. TOP_1/A_2/B_3",
1207  " node->Align(TGeoMatrix *newmat, TGeoShape *newshape, Bool_t check=kFALSE)",
1208  " + newmat = new matrix to replace final node LOCAL matrix",
1209  " + newshape = new shape to replace final node shape",
1210  " + check = optional check if the new aligned node is overlapping"});
1211 }
1212 
1213 //______________________________________________________________________________
1214 void align()
1215 {
1216  if (!gGeoManager) return;
1217  if (strcmp(gGeoManager->GetName(),"alignment")) {
1218  printf("Click: <Ideal geometry> first\n");
1219  return;
1220  }
1221  char name[30];
1222  TObjArray *list = gGeoManager->GetListOfPhysicalNodes();
1223  TGeoPhysicalNode *node;
1224  TGeoTranslation *tr;
1225  for (Int_t i=1; i<=10; i++) {
1226  for (Int_t j=1; j<=10; j++) {
1227  node = 0;
1228  sprintf(name, "TOP_1/SX_%d/SY_%d/CELL_1",i,j);
1229  if (list) node = (TGeoPhysicalNode*)list->At(10*(i-1)+j-1);
1230  if (!node) node = gGeoManager->MakePhysicalNode(name);
1231  if (node->IsAligned()) {
1232  tr = (TGeoTranslation*)node->GetNode()->GetMatrix();
1233  tr->SetTranslation(2.*gRandom->Rndm(), 2.*gRandom->Rndm(),0.);
1234  } else {
1235  tr = new TGeoTranslation(2.*gRandom->Rndm(), 2.*gRandom->Rndm(),0.);
1236  }
1237  node->Align(tr);
1238  }
1239  }
1240 
1241  display();
1242 }
1243 
1244 //______________________________________________________________________________
1245 void quit()
1246 {
1247  mainWindow->TerminateROOT();
1248 }
1249 
1250 //______________________________________________________________________________
1251 void webdemo ()
1252 {
1253  // configure default html page
1254  // either HTML code can be specified or just name of file after 'file:' prefix
1255  mainWindow->SetDefaultPage("file:webdemo.html");
1256 
1257  // this is call-back, invoked when message received from client
1258  mainWindow->SetDataCallBack([](unsigned connid, const std::string &arg) {
1259  gROOT->ProcessLine(arg.c_str());
1260  });
1261 
1262  mainWindow->Show({150,750, 0,0});
1263 
1264  geomViewer->SetDrawOptions(getOptions());
1265 }