Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveGeoShape.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Author: Matevz Tadel 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #include "TEveGeoShape.h"
13 #include "TEveTrans.h"
14 #include "TEveManager.h"
16 #include "TEveProjections.h"
17 #include "TEveProjectionManager.h"
18 
19 #include "TEveGeoShapeExtract.h"
20 #include "TEveGeoPolyShape.h"
21 
22 #include "TROOT.h"
23 #include "TBuffer3D.h"
24 #include "TBuffer3DTypes.h"
25 #include "TVirtualViewer3D.h"
26 #include "TColor.h"
27 #include "TFile.h"
28 
29 #include "TGeoShape.h"
30 #include "TGeoVolume.h"
31 #include "TGeoNode.h"
32 #include "TGeoShapeAssembly.h"
33 #include "TGeoCompositeShape.h"
34 #include "TGeoBoolNode.h"
35 #include "TGeoManager.h"
36 #include "TGeoMatrix.h"
37 #include "TVirtualGeoPainter.h"
38 
39 namespace
40 {
41  TGeoManager* init_geo_mangeur()
42  {
43  // Create a phony geo manager that can be used for storing free
44  // shapes. Otherwise shapes register themselves to current
45  // geo-manager (or even create one).
46 
47  TGeoManager *old = gGeoManager;
48  TGeoIdentity *old_id = gGeoIdentity;
49  gGeoManager = 0;
50  TGeoManager* mgr = new TGeoManager();
51  mgr->SetNameTitle("TEveGeoShape::fgGeoMangeur",
52  "Static geo manager used for wrapped TGeoShapes.");
53  gGeoIdentity = new TGeoIdentity("Identity");
54  gGeoManager = old;
55  gGeoIdentity = old_id;
56  return mgr;
57  }
58 
59  TGeoHMatrix localGeoHMatrixIdentity;
60 }
61 
62 /** \class TEveGeoShape
63 \ingroup TEve
64 Wrapper for TGeoShape with absolute positioning and color
65 attributes allowing display of extracted TGeoShape's (without an
66 active TGeoManager) and simplified geometries (needed for non-linear
67 projections).
68 
69 TGeoCompositeShapes and TGeoAssemblies are supported.
70 
71 If fNSegments data-member is < 2 (0 by default), the default number of
72 segments is used for tesselation and special GL objects are
73 instantiated for selected shapes (spheres, tubes). If fNSegments is > 2,
74 it gets forwarded to geo-manager and this tesselation detail is
75 used when creating the buffer passed to GL.
76 */
77 
78 ClassImp(TEveGeoShape);
79 
80 TGeoManager* TEveGeoShape::fgGeoMangeur = init_geo_mangeur();
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Return static geo-manager that is used internally to make shapes
84 /// lead a happy life.
85 /// Set gGeoManager to this object when creating TGeoShapes to be
86 /// passed into TEveGeoShapes.
87 
88 TGeoManager* TEveGeoShape::GetGeoMangeur()
89 {
90  return fgGeoMangeur;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Return static identity matrix in homogeneous representation.
95 /// This is needed because TGeoCompositeShape::PaintComposite()
96 /// assumes TGeoShape::fgTransform is a TGeoHMatrix and we need to pass in
97 /// an identity matrix when painting a composite shape.
98 
99 TGeoHMatrix* TEveGeoShape::GetGeoHMatrixIdentity()
100 {
101  return &localGeoHMatrixIdentity;
102 }
103 
104 ////////////////////////////////////////////////////////////////////////////////
105 /// Constructor.
106 
107 TEveGeoShape::TEveGeoShape(const char* name, const char* title) :
108  TEveShape (name, title),
109  fNSegments (0),
110  fShape (0),
111  fCompositeShape (0)
112 {
113  InitMainTrans();
114 }
115 
116 ////////////////////////////////////////////////////////////////////////////////
117 /// Destructor.
118 
119 TEveGeoShape::~TEveGeoShape()
120 {
121  SetShape(0);
122 }
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 /// Create derived TEveGeoShape form a TGeoCompositeShape.
126 
127 TGeoShape* TEveGeoShape::MakePolyShape()
128 {
129  return TEveGeoPolyShape::Construct(fCompositeShape, fNSegments);
130 }
131 
132 ////////////////////////////////////////////////////////////////////////////////
133 /// Set number of segments.
134 
135 void TEveGeoShape::SetNSegments(Int_t s)
136 {
137  if (s != fNSegments && fCompositeShape != 0)
138  {
139  delete fShape;
140  fShape = MakePolyShape();
141  }
142  fNSegments = s;
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// Set TGeoShape shown by this object.
147 ///
148 /// The shape is owned by TEveGeoShape but TGeoShape::fUniqueID is
149 /// used for reference counting so you can pass the same shape to
150 /// several TEveGeoShapes.
151 ///
152 /// If it if is taken from an existing TGeoManager, manually
153 /// increase the fUniqueID before passing it to TEveGeoShape.
154 
155 void TEveGeoShape::SetShape(TGeoShape* s)
156 {
157  TEveGeoManagerHolder gmgr(fgGeoMangeur);
158 
159  if (fCompositeShape)
160  {
161  delete fShape;
162  fShape = fCompositeShape;
163  }
164  if (fShape)
165  {
166  fShape->SetUniqueID(fShape->GetUniqueID() - 1);
167  if (fShape->GetUniqueID() == 0)
168  {
169  delete fShape;
170  }
171  }
172  fShape = s;
173  if (fShape)
174  {
175  fShape->SetUniqueID(fShape->GetUniqueID() + 1);
176  fCompositeShape = dynamic_cast<TGeoCompositeShape*>(fShape);
177  if (fCompositeShape)
178  {
179  fShape = MakePolyShape();
180  }
181  }
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 /// Compute bounding-box.
186 
187 void TEveGeoShape::ComputeBBox()
188 {
189  TGeoBBox *bb = dynamic_cast<TGeoBBox*>(fShape);
190  if (bb)
191  {
192  BBoxInit();
193  const Double_t *o = bb->GetOrigin();
194  BBoxCheckPoint(o[0] - bb->GetDX(), o[0] - bb->GetDY(), o[0] - bb->GetDZ());
195  BBoxCheckPoint(o[0] + bb->GetDX(), o[0] + bb->GetDY(), o[0] + bb->GetDZ());
196  }
197  else
198  {
199  BBoxZero();
200  }
201 }
202 
203 ////////////////////////////////////////////////////////////////////////////////
204 /// Paint object.
205 
206 void TEveGeoShape::Paint(Option_t* /*option*/)
207 {
208  static const TEveException eh("TEveGeoShape::Paint ");
209 
210  if (fShape == 0)
211  return;
212 
213  TEveGeoManagerHolder gmgr(fgGeoMangeur, fNSegments);
214 
215  if (fCompositeShape)
216  {
217  Double_t halfLengths[3] = { fCompositeShape->GetDX(), fCompositeShape->GetDY(), fCompositeShape->GetDZ() };
218 
219  TBuffer3D buff(TBuffer3DTypes::kComposite);
220  buff.fID = this;
221  buff.fColor = GetMainColor();
222  buff.fTransparency = GetMainTransparency();
223  RefMainTrans().SetBuffer3D(buff);
224  buff.fLocalFrame = kTRUE; // Always enforce local frame (no geo manager).
225  buff.SetAABoundingBox(fCompositeShape->GetOrigin(), halfLengths);
226  buff.SetSectionsValid(TBuffer3D::kCore|TBuffer3D::kBoundingBox);
227 
228  Bool_t paintComponents = kTRUE;
229 
230  // Start a composite shape, identified by this buffer
231  if (TBuffer3D::GetCSLevel() == 0)
232  paintComponents = gPad->GetViewer3D()->OpenComposite(buff);
233 
234  TBuffer3D::IncCSLevel();
235 
236  // Paint the boolean node - will add more buffers to viewer
237  TGeoMatrix *gst = TGeoShape::GetTransform();
238  TGeoShape::SetTransform(TEveGeoShape::GetGeoHMatrixIdentity());
239  if (paintComponents) fCompositeShape->GetBoolNode()->Paint("");
240  TGeoShape::SetTransform(gst);
241  // Close the composite shape
242  if (TBuffer3D::DecCSLevel() == 0)
243  gPad->GetViewer3D()->CloseComposite();
244  }
245  else
246  {
247  TBuffer3D& buff = (TBuffer3D&) fShape->GetBuffer3D
248  (TBuffer3D::kCore, kFALSE);
249 
250  buff.fID = this;
251  buff.fColor = GetMainColor();
252  buff.fTransparency = GetMainTransparency();
253  RefMainTrans().SetBuffer3D(buff);
254  buff.fLocalFrame = kTRUE; // Always enforce local frame (no geo manager).
255 
256  Int_t sections = TBuffer3D::kBoundingBox | TBuffer3D::kShapeSpecific;
257  if (fNSegments > 2)
258  sections |= TBuffer3D::kRawSizes | TBuffer3D::kRaw;
259  fShape->GetBuffer3D(sections, kTRUE);
260 
261  Int_t reqSec = gPad->GetViewer3D()->AddObject(buff);
262 
263  if (reqSec != TBuffer3D::kNone) {
264  // This shouldn't happen, but I suspect it does sometimes.
265  if (reqSec & TBuffer3D::kCore)
266  Warning(eh, "Core section required again for shape='%s'. This shouldn't happen.", GetName());
267  fShape->GetBuffer3D(reqSec, kTRUE);
268  reqSec = gPad->GetViewer3D()->AddObject(buff);
269  }
270 
271  if (reqSec != TBuffer3D::kNone)
272  Warning(eh, "Extra section required: reqSec=%d, shape=%s.", reqSec, GetName());
273  }
274 }
275 
276 ////////////////////////////////////////////////////////////////////////////////
277 /// Save the shape tree as TEveGeoShapeExtract.
278 /// File is always recreated.
279 /// This function is obsolete, use SaveExtractInstead().
280 
281 void TEveGeoShape::Save(const char* file, const char* name)
282 {
283  Warning("Save()", "This function is deprecated, use SaveExtract() instead.");
284  SaveExtract(file, name);
285 }
286 
287 ////////////////////////////////////////////////////////////////////////////////
288 /// Save the shape tree as TEveGeoShapeExtract.
289 /// File is always recreated.
290 
291 void TEveGeoShape::SaveExtract(const char* file, const char* name)
292 {
293  TEveGeoShapeExtract* gse = DumpShapeTree(this, 0);
294 
295  TFile f(file, "RECREATE");
296  gse->Write(name);
297  f.Close();
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Write the shape tree as TEveGeoShapeExtract to current directory.
302 
303 void TEveGeoShape::WriteExtract(const char* name)
304 {
305  TEveGeoShapeExtract* gse = DumpShapeTree(this, 0);
306  gse->Write(name);
307 }
308 
309 ////////////////////////////////////////////////////////////////////////////////
310 /// Export this shape and its descendants into a geoshape-extract.
311 
312 TEveGeoShapeExtract* TEveGeoShape::DumpShapeTree(TEveGeoShape* gsre,
313  TEveGeoShapeExtract* parent)
314 {
315  TEveGeoShapeExtract* she = new TEveGeoShapeExtract(gsre->GetName(), gsre->GetTitle());
316  she->SetTrans(gsre->RefMainTrans().Array());
317  {
318  Int_t ci = gsre->GetFillColor();
319  TColor *c = gROOT->GetColor(ci);
320  Float_t rgba[4] = { 1, 0, 0, Float_t(1 - gsre->GetMainTransparency()/100.) };
321  if (c)
322  {
323  rgba[0] = c->GetRed();
324  rgba[1] = c->GetGreen();
325  rgba[2] = c->GetBlue();
326  }
327  she->SetRGBA(rgba);
328  }
329  {
330  Int_t ci = gsre->GetLineColor();
331  TColor *c = gROOT->GetColor(ci);
332  Float_t rgba[4] = { 1, 0, 0, 1 };
333  if (c)
334  {
335  rgba[0] = c->GetRed();
336  rgba[1] = c->GetGreen();
337  rgba[2] = c->GetBlue();
338  }
339  she->SetRGBALine(rgba);
340  }
341  she->SetRnrSelf(gsre->GetRnrSelf());
342  she->SetRnrElements(gsre->GetRnrChildren());
343  she->SetRnrFrame(gsre->GetDrawFrame());
344  she->SetMiniFrame(gsre->GetMiniFrame());
345  she->SetShape(gsre->GetShape());
346  if (gsre->HasChildren())
347  {
348  TList* ele = new TList();
349  she->SetElements(ele);
350  she->GetElements()->SetOwner(true);
351  TEveElement::List_i i = gsre->BeginChildren();
352  while (i != gsre->EndChildren()) {
353  TEveGeoShape* l = dynamic_cast<TEveGeoShape*>(*i);
354  DumpShapeTree(l, she);
355  i++;
356  }
357  }
358  if (parent)
359  parent->GetElements()->Add(she);
360 
361  return she;
362 }
363 
364 ////////////////////////////////////////////////////////////////////////////////
365 /// Import a shape extract 'gse' under element 'parent'.
366 
367 TEveGeoShape* TEveGeoShape::ImportShapeExtract(TEveGeoShapeExtract* gse,
368  TEveElement* parent)
369 {
370  TEveGeoManagerHolder gmgr(fgGeoMangeur);
371  TEveManager::TRedrawDisabler redrawOff(gEve);
372  TEveGeoShape* gsre = SubImportShapeExtract(gse, parent);
373  gsre->ElementChanged();
374  return gsre;
375 }
376 
377 ////////////////////////////////////////////////////////////////////////////////
378 /// Recursive version for importing a shape extract tree.
379 
380 TEveGeoShape* TEveGeoShape::SubImportShapeExtract(TEveGeoShapeExtract* gse,
381  TEveElement* parent)
382 {
383  TEveGeoShape* gsre = new TEveGeoShape(gse->GetName(), gse->GetTitle());
384  gsre->RefMainTrans().SetFromArray(gse->GetTrans());
385  const Float_t* rgba = gse->GetRGBA();
386  gsre->SetMainColorRGB(rgba[0], rgba[1], rgba[2]);
387  gsre->SetMainAlpha(rgba[3]);
388  rgba = gse->GetRGBALine();
389  gsre->SetLineColor(TColor::GetColor(rgba[0], rgba[1], rgba[2]));
390  gsre->SetRnrSelf(gse->GetRnrSelf());
391  gsre->SetRnrChildren(gse->GetRnrElements());
392  gsre->SetDrawFrame(gse->GetRnrFrame());
393  gsre->SetMiniFrame(gse->GetMiniFrame());
394  gsre->SetShape(gse->GetShape());
395 
396  if (parent)
397  parent->AddElement(gsre);
398 
399  if (gse->HasElements())
400  {
401  TIter next(gse->GetElements());
402  TEveGeoShapeExtract* chld;
403  while ((chld = (TEveGeoShapeExtract*) next()) != 0)
404  SubImportShapeExtract(chld, gsre);
405  }
406 
407  return gsre;
408 }
409 
410 ////////////////////////////////////////////////////////////////////////////////
411 /// Return class for projected objects:
412 /// - 2D projections: TEvePolygonSetProjected,
413 /// - 3D projections: TEveGeoShapeProjected.
414 /// Virtual from TEveProjectable.
415 
416 TClass* TEveGeoShape::ProjectedClass(const TEveProjection* p) const
417 {
418  if (p->Is2D())
419  return TEvePolygonSetProjected::Class();
420  else
421  return TEveGeoShapeProjected::Class();
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////////
425 /// Create a TBuffer3D suitable for presentation of the shape.
426 /// Transformation matrix is also applied.
427 
428 TBuffer3D* TEveGeoShape::MakeBuffer3D()
429 {
430  if (fShape == 0) return 0;
431 
432  if (dynamic_cast<TGeoShapeAssembly*>(fShape)) {
433  // TGeoShapeAssembly makes a bad TBuffer3D.
434  return 0;
435  }
436 
437  TEveGeoManagerHolder gmgr(fgGeoMangeur, fNSegments);
438 
439  TBuffer3D* buff = fShape->MakeBuffer3D();
440  TEveTrans& mx = RefMainTrans();
441  if (mx.GetUseTrans())
442  {
443  Int_t n = buff->NbPnts();
444  Double_t* pnts = buff->fPnts;
445  for(Int_t k = 0; k < n; ++k)
446  {
447  mx.MultiplyIP(&pnts[3*k]);
448  }
449  }
450  return buff;
451 }
452 
453 
454 /** \class TEveGeoShapeProjected
455 \ingroup TEve
456 A 3D projected TEveGeoShape.
457 */
458 
459 ClassImp(TEveGeoShapeProjected);
460 
461 ////////////////////////////////////////////////////////////////////////////////
462 /// Constructor.
463 
464 TEveGeoShapeProjected::TEveGeoShapeProjected() :
465  TEveShape("TEveGeoShapeProjected"),
466  fBuff(0)
467 {
468 }
469 
470 ////////////////////////////////////////////////////////////////////////////////
471 /// Destructor.
472 
473 TEveGeoShapeProjected::~TEveGeoShapeProjected()
474 {
475  delete fBuff;
476 }
477 
478 ////////////////////////////////////////////////////////////////////////////////
479 /// This should never be called as this class is only used for 3D
480 /// projections.
481 /// The implementation is required as this metod is abstract.
482 /// Just emits a warning if called.
483 
484 void TEveGeoShapeProjected::SetDepthLocal(Float_t /*d*/)
485 {
486  Warning("SetDepthLocal", "This function only exists to fulfill an abstract interface.");
487 }
488 
489 ////////////////////////////////////////////////////////////////////////////////
490 /// This is virtual method from base-class TEveProjected.
491 
492 void TEveGeoShapeProjected::SetProjection(TEveProjectionManager* mng,
493  TEveProjectable* model)
494 {
495  TEveProjected::SetProjection(mng, model);
496 
497  TEveGeoShape* gre = dynamic_cast<TEveGeoShape*>(fProjectable);
498  CopyVizParams(gre);
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 /// This is virtual method from base-class TEveProjected.
503 
504 void TEveGeoShapeProjected::UpdateProjection()
505 {
506  TEveGeoShape *gre = dynamic_cast<TEveGeoShape*>(fProjectable);
507  TEveProjection *prj = fManager->GetProjection();
508 
509  delete fBuff;
510  fBuff = gre->MakeBuffer3D();
511 
512  if (fBuff)
513  {
514  fBuff->SetSectionsValid(TBuffer3D::kCore | TBuffer3D::kRawSizes | TBuffer3D::kRaw);
515 
516  Double_t *p = fBuff->fPnts;
517  for (UInt_t i = 0; i < fBuff->NbPnts(); ++i, p+=3)
518  {
519  prj->ProjectPointdv(p, 0);
520  }
521  }
522 
523  ResetBBox();
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Override of virtual method from TAttBBox.
528 
529 void TEveGeoShapeProjected::ComputeBBox()
530 {
531  if (fBuff && fBuff->NbPnts() > 0)
532  {
533  BBoxInit();
534 
535  Double_t *p = fBuff->fPnts;
536  for (UInt_t i = 0; i < fBuff->NbPnts(); ++i, p+=3)
537  {
538  BBoxCheckPoint(p[0], p[1], p[2]);
539  }
540  }
541  else
542  {
543  BBoxZero();
544  }
545 }