Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TEveProjectionManager.cxx
Go to the documentation of this file.
1 // @(#)root/eve:$Id$
2 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 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 "TEveProjectionManager.h"
13 #include "TEveManager.h"
14 #include "TEveProjectionBases.h"
15 #include "TEveCompound.h"
16 
17 #include "TBuffer3D.h"
18 #include "TBuffer3DTypes.h"
19 #include "TVirtualPad.h"
20 #include "TVirtualViewer3D.h"
21 
22 #include "TClass.h"
23 
24 #include <list>
25 
26 /** \class TEveProjectionManager
27 \ingroup TEve
28 Manager class for steering of projections and managing projected objects.
29 
30 Recursively projects TEveElement's and draws axis in the projected
31 scene. It enables to interactively set TEveProjection parameters
32 and updates projected scene accordingly.
33 */
34 
35 ClassImp(TEveProjectionManager);
36 
37 ////////////////////////////////////////////////////////////////////////////////
38 /// Constructor.
39 
40 TEveProjectionManager::TEveProjectionManager(TEveProjection::EPType_e type):
41  TEveElementList("TEveProjectionManager",""),
42  TAttBBox(),
43  fProjection (0),
44  fCurrentDepth(0),
45  fImportEmpty (kFALSE)
46 {
47  for (Int_t i = 0; i < TEveProjection::kPT_End; ++i)
48  fProjections[i] = 0;
49 
50  if (type != TEveProjection::kPT_Unknown)
51  SetProjection(type);
52 }
53 
54 ////////////////////////////////////////////////////////////////////////////////
55 /// Destructor.
56 /// Destroys also dependent elements.
57 
58 TEveProjectionManager::~TEveProjectionManager()
59 {
60  for (Int_t i = 0; i < TEveProjection::kPT_End; ++i)
61  {
62  delete fProjections[i];
63  }
64  while ( ! fDependentEls.empty())
65  {
66  fDependentEls.front()->Destroy();
67  }
68 }
69 
70 ////////////////////////////////////////////////////////////////////////////////
71 /// Add el as dependent element.
72 
73 void TEveProjectionManager::AddDependent(TEveElement* el)
74 {
75  fDependentEls.push_back(el);
76 }
77 
78 ////////////////////////////////////////////////////////////////////////////////
79 /// Remove el as dependent element.
80 
81 void TEveProjectionManager::RemoveDependent(TEveElement* el)
82 {
83  fDependentEls.remove(el);
84 }
85 
86 ////////////////////////////////////////////////////////////////////////////////
87 /// Updates name to have consistent information with projection.
88 
89 void TEveProjectionManager::UpdateName()
90 {
91  if (fProjection->Is2D())
92  SetName(Form ("%s (%3.1f)", fProjection->GetName(), fProjection->GetDistortion()*1000));
93  else
94  SetName(fProjection->GetName());
95 }
96 
97 ////////////////////////////////////////////////////////////////////////////////
98 /// Set projection type and distortion.
99 
100 void TEveProjectionManager::SetProjection(TEveProjection::EPType_e type)
101 {
102  static const TEveException eH("TEveProjectionManager::SetProjection ");
103 
104  if (fProjections[type] == 0)
105  {
106  switch (type)
107  {
108  case TEveProjection::kPT_RPhi:
109  {
110  fProjections[type] = new TEveRPhiProjection();
111  break;
112  }
113  case TEveProjection::kPT_RhoZ:
114  {
115  fProjections[type] = new TEveRhoZProjection();
116  break;
117  }
118  case TEveProjection::kPT_3D:
119  {
120  fProjections[type] = new TEve3DProjection();
121  break;
122  }
123  default:
124  throw eH + "projection type not valid.";
125  break;
126  }
127  }
128 
129  if (fProjection && fProjection->Is2D() != fProjections[type]->Is2D())
130  {
131  throw eH + "switching between 2D and 3D projections not implemented.";
132  }
133 
134  fProjection = fProjections[type];
135  fProjection->SetCenter(fCenter);
136  UpdateName();
137 }
138 
139 ////////////////////////////////////////////////////////////////////////////////
140 /// Set projection center and rebuild projected scene.
141 
142 void TEveProjectionManager::SetCenter(Float_t x, Float_t y, Float_t z)
143 {
144  fCenter.Set(x, y, z);
145  fProjection->SetCenter(fCenter);
146  ProjectChildren();
147 }
148 
149 ////////////////////////////////////////////////////////////////////////////////
150 /// React to element being pasted or dnd-ed.
151 /// Return true if redraw is needed (virtual method).
152 
153 Bool_t TEveProjectionManager::HandleElementPaste(TEveElement* el)
154 {
155  List_t::size_type n_children = fChildren.size();
156  ImportElements(el);
157  return n_children != fChildren.size();
158 }
159 
160 ////////////////////////////////////////////////////////////////////////////////
161 /// Returns true if element el should be imported.
162 ///
163 /// Behaviour depends on the value of the fImportEmpty member:
164 /// false - el or any of its children must be projectable (default);
165 /// true - always import.
166 
167 Bool_t TEveProjectionManager::ShouldImport(TEveElement* el)
168 {
169  if (fImportEmpty)
170  return kTRUE;
171 
172  if (el->IsA() != TEveElementList::Class() && el->IsA()->InheritsFrom(TEveProjectable::Class()))
173  return kTRUE;
174  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
175  if (ShouldImport(*i))
176  return kTRUE;
177  return kFALSE;
178 }
179 
180 ////////////////////////////////////////////////////////////////////////////////
181 /// Update dependent elements' bounding box and mark scenes
182 /// containing element root or its children as requiring a repaint.
183 
184 void TEveProjectionManager::UpdateDependentElsAndScenes(TEveElement* root)
185 {
186  for (List_i i=fDependentEls.begin(); i!=fDependentEls.end(); ++i)
187  {
188  TAttBBox* bbox = dynamic_cast<TAttBBox*>(*i);
189  if (bbox)
190  bbox->ComputeBBox();
191  }
192 
193  List_t scenes;
194  root->CollectSceneParentsFromChildren(scenes, 0);
195  gEve->ScenesChanged(scenes);
196 }
197 
198 ////////////////////////////////////////////////////////////////////////////////
199 /// If el is TEveProjectable add projected instance else add plain
200 /// TEveElementList to parent. Call the same function on el's
201 /// children.
202 ///
203 /// Returns the projected replica of el. Can be 0, if el and none of
204 /// its children are projectable.
205 
206 TEveElement* TEveProjectionManager::ImportElementsRecurse(TEveElement* el,
207  TEveElement* parent)
208 {
209  static const TEveException eh("TEveProjectionManager::ImportElementsRecurse ");
210 
211  TEveElement *new_el = 0;
212 
213  if (ShouldImport(el))
214  {
215  TEveProjected *new_pr = 0;
216  TEveProjectable *pble = dynamic_cast<TEveProjectable*>(el);
217  if (pble)
218  {
219  new_el = (TEveElement*) pble->ProjectedClass(fProjection)->New();
220  new_pr = dynamic_cast<TEveProjected*>(new_el);
221  new_pr->SetProjection(this, pble);
222  new_pr->SetDepth(fCurrentDepth);
223  }
224  else
225  {
226  new_el = new TEveElementList;
227  }
228  new_el->SetElementName (Form("%s [P]", el->GetElementName()));
229  new_el->SetElementTitle(Form("Projected replica.\n%s", el->GetElementTitle()));
230  new_el->SetRnrSelf (el->GetRnrSelf());
231  new_el->SetRnrChildren (el->GetRnrChildren());
232  new_el->SetPickable (el->IsPickable());
233  parent->AddElement(new_el);
234 
235  TEveCompound *cmpnd = dynamic_cast<TEveCompound*>(el);
236  TEveCompound *cmpnd_pr = dynamic_cast<TEveCompound*>(new_el);
237  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
238  {
239  TEveElement* child_pr = ImportElementsRecurse(*i, new_el);
240  if (cmpnd && (*i)->GetCompound() == cmpnd)
241  child_pr->SetCompound(cmpnd_pr);
242  }
243  }
244 
245  return new_el;
246 }
247 
248 ////////////////////////////////////////////////////////////////////////////////
249 /// Recursively import elements and apply projection to the newly
250 /// imported objects.
251 ///
252 /// If ext_list is not 0 the new element is also added to the list.
253 /// This simplifies construction of complex views where projected
254 /// elements are distributed into several scenes for optimization of
255 /// updates and rendering.
256 ///
257 /// Returns the projected replica of el. Can be 0, if el and none of
258 /// its children are projectable.
259 
260 TEveElement* TEveProjectionManager::ImportElements(TEveElement* el,
261  TEveElement* ext_list)
262 {
263  TEveElement* new_el = ImportElementsRecurse(el, this);
264  if (new_el)
265  {
266  AssertBBox();
267  ProjectChildrenRecurse(new_el);
268  AssertBBoxExtents(0.1);
269  StampTransBBox();
270 
271  UpdateDependentElsAndScenes(new_el);
272 
273  if (ext_list)
274  ext_list->AddElement(new_el);
275  }
276  return new_el;
277 }
278 
279 ////////////////////////////////////////////////////////////////////////////////
280 /// Recursively import elements and apply projection to the newly
281 /// imported objects.
282 ///
283 /// The proj_parent argument should be a projected replica of parent
284 /// of element 'el'. This allows to insert projected children of
285 /// a given element when they are added after the projection has
286 /// been already performed on the parent.
287 /// This is called from TEveElement::ProjectChild().
288 ///
289 /// Returns the projected replica of el. Can be 0, if el and none of
290 /// its children are projectable.
291 
292 TEveElement* TEveProjectionManager::SubImportElements(TEveElement* el,
293  TEveElement* proj_parent)
294 {
295  TEveElement* new_el = ImportElementsRecurse(el, proj_parent);
296  if (new_el)
297  {
298  AssertBBox();
299  ProjectChildrenRecurse(new_el);
300  AssertBBoxExtents(0.1);
301  StampTransBBox();
302 
303  UpdateDependentElsAndScenes(new_el);
304  }
305  return new_el;
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////////
309 /// Recursively import children elements of el and apply projection
310 /// to the newly imported objects.
311 ///
312 /// The proj_parent argument should be a projected replica of
313 /// element 'el'. This allows to insert projected children of
314 /// a given element when they are added after the projection has
315 /// been already performed on the parent.
316 /// This is called from TEveElement::ProjectChild().
317 ///
318 /// Returns the projected replica of el. Can be 0, if el and none of
319 /// its children are projectable.
320 
321 Int_t TEveProjectionManager::SubImportChildren(TEveElement* el, TEveElement* proj_parent)
322 {
323  List_t new_els;
324  for (List_i i = el->BeginChildren(); i != el->EndChildren(); ++i)
325  {
326  TEveElement* new_el = ImportElementsRecurse(*i, proj_parent);
327  if (new_el)
328  new_els.push_back(new_el);
329  }
330 
331  if ( ! new_els.empty())
332  {
333  AssertBBox();
334  for (List_i i = new_els.begin(); i != new_els.end(); ++i)
335  {
336  ProjectChildrenRecurse(*i);
337  }
338  AssertBBoxExtents(0.1);
339  StampTransBBox();
340 
341  UpdateDependentElsAndScenes(proj_parent);
342  }
343  return (Int_t) new_els.size();
344 }
345 
346 ////////////////////////////////////////////////////////////////////////////////
347 /// Project el (via TEveProjected::UpdateProjection()) and recurse
348 /// through el's children.
349 /// Bounding-box is updated along the recursion.
350 
351 void TEveProjectionManager::ProjectChildrenRecurse(TEveElement* el)
352 {
353  TEveProjected* pted = dynamic_cast<TEveProjected*>(el);
354  if (pted)
355  {
356  pted->UpdateProjection();
357  TAttBBox* bb = dynamic_cast<TAttBBox*>(pted);
358  if (bb)
359  {
360  Float_t* b = bb->AssertBBox();
361  BBoxCheckPoint(b[0], b[2], b[4]);
362  BBoxCheckPoint(b[1], b[3], b[5]);
363  }
364  el->ElementChanged(kFALSE);
365  }
366 
367  for (List_i i=el->BeginChildren(); i!=el->EndChildren(); ++i)
368  ProjectChildrenRecurse(*i);
369 }
370 
371 ////////////////////////////////////////////////////////////////////////////////
372 /// Project all children recursively, update bounding-box and notify
373 /// TEveManger about the scenes that have been changed.
374 
375 void TEveProjectionManager::ProjectChildren()
376 {
377  BBoxInit();
378  for (List_i i=BeginChildren(); i!=EndChildren(); ++i)
379  ProjectChildrenRecurse(*i);
380  AssertBBoxExtents(0.1);
381  StampTransBBox();
382 
383  UpdateDependentElsAndScenes(this);
384 }
385 
386 ////////////////////////////////////////////////////////////////////////////////
387 /// Virtual from TAttBBox; fill bounding-box information.
388 ///
389 /// The bounding-box information is kept coherent during addition of
390 /// projected elements and projection parameter updates. This is
391 /// called only in case the manager has not been populated at all.
392 
393 void TEveProjectionManager::ComputeBBox()
394 {
395  static const TEveException eH("TEveProjectionManager::ComputeBBox ");
396 
397  if (HasChildren() == kFALSE) {
398  BBoxZero();
399  return;
400  }
401 
402  BBoxInit();
403 }