Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
REvePointSet.cxx
Go to the documentation of this file.
1 // @(#)root/eve7:$Id$
2 // Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2019, 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 <ROOT/REvePointSet.hxx>
13 
14 #include <ROOT/REveManager.hxx>
16 #include <ROOT/REveTrans.hxx>
17 #include <ROOT/REveRenderData.hxx>
18 
19 #include "TColor.h"
20 #include "TArrayI.h"
21 #include "TClass.h"
22 
23 
24 #include "json.hpp"
25 
26 
27 using namespace ROOT::Experimental;
28 namespace REX = ROOT::Experimental;
29 
30 /** \class REvePointSet
31 \ingroup REve
32 REvePointSet is a render-element holding a collection of 3D points with
33 optional per-point TRef and an arbitrary number of integer ids (to
34 be used for signal, volume-id, track-id, etc).
35 
36 3D point representation is implemented in base-class TPolyMarker3D.
37 Per-point TRef is implemented in base-class TPointSet3D.
38 
39 By using the REvePointSelector the points and integer ids can be
40 filled directly from a TTree holding the source data.
41 Setting of per-point TRef's is not supported.
42 
43 REvePointSet is a REveProjectable: it can be projected by using the
44 REveProjectionManager class.
45 */
46 
47 ////////////////////////////////////////////////////////////////////////////////
48 /// Constructor.
49 
50 REvePointSet::REvePointSet(const std::string& name, const std::string& title, Int_t n_points) :
51  REveElement(name, title),
52  TAttMarker(),
53  TAttBBox()
54 {
55  fMarkerStyle = 20;
56 
57  SetMainColorPtr(&fMarkerColor);
58 
59  Reset(n_points);
60 
61  // Override from REveElement.
62  fPickable = kTRUE;
63 }
64 
65 ////////////////////////////////////////////////////////////////////////////////
66 /// Copy constructor.
67 
68 REvePointSet::REvePointSet(const REvePointSet& e) :
69  REveElement(e),
70  REveProjectable(e),
71  TAttMarker(e),
72  TAttBBox(e)
73 {
74 }
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 /// Destructor.
78 
79 REvePointSet::~REvePointSet()
80 {
81 }
82 
83 ////////////////////////////////////////////////////////////////////////////////
84 /// Clone points and all point-related information from point-set 'e'.
85 
86 void REvePointSet::ClonePoints(const REvePointSet& e)
87 {
88  fPoints = e.fPoints;
89  fCapacity = e.fCapacity;
90  fSize = e.fSize;
91 }
92 
93 ////////////////////////////////////////////////////////////////////////////////
94 /// Drop all data and set-up the data structures to recive new data.
95 /// n_points specifies the initial size of the array.
96 
97 void REvePointSet::Reset(Int_t n_points)
98 {
99  fPoints.resize(n_points);
100  fCapacity = n_points;
101  fSize = 0;
102 
103  ResetBBox();
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// Resizes internal array to allow additional n_points to be stored.
108 /// Returns the old size which is also the location where one can
109 /// start storing new data.
110 /// The caller is *obliged* to fill the new point slots.
111 
112 Int_t REvePointSet::GrowFor(Int_t n_points)
113 {
114  assert(n_points >= 0);
115 
116  Int_t old_size = fCapacity;
117  Int_t new_size = old_size + n_points;
118 
119  fPoints.resize(new_size);
120  fCapacity = new_size;
121 
122  return old_size;
123 }
124 
125 int REvePointSet::SetNextPoint(float x, float y, float z)
126 {
127  return SetPoint(fSize, x, y, z);
128 }
129 
130 int REvePointSet::SetPoint(int n, float x, float y, float z)
131 {
132  if (n >= fCapacity)
133  {
134  fCapacity = std::max(n + 1, 2*fCapacity);
135  fPoints.resize(fCapacity);
136  }
137  fPoints[n].Set(x, y, z);
138  if (n >= fSize)
139  {
140  fSize = n + 1;
141  }
142  return fSize;
143 }
144 
145 ////////////////////////////////////////////////////////////////////////////////
146 /// Set marker style, propagate to projecteds.
147 
148 void REvePointSet::SetMarkerStyle(Style_t mstyle)
149 {
150  for (auto &pi: fProjectedList)
151  {
152  REvePointSet* pt = dynamic_cast<REvePointSet *>(pi);
153  if (pt)
154  {
155  pt->SetMarkerStyle(mstyle);
156  pt->StampObjProps();
157  }
158  }
159  TAttMarker::SetMarkerStyle(mstyle);
160 }
161 
162 ////////////////////////////////////////////////////////////////////////////////
163 /// Set marker size, propagate to projecteds.
164 
165 void REvePointSet::SetMarkerSize(Size_t msize)
166 {
167  for (auto &pi: fProjectedList)
168  {
169  REvePointSet* pt = dynamic_cast<REvePointSet *>(pi);
170  if (pt)
171  {
172  pt->SetMarkerSize(msize);
173  pt->StampObjProps();
174  }
175  }
176  TAttMarker::SetMarkerSize(msize);
177  StampObjProps();
178 }
179 
180 ////////////////////////////////////////////////////////////////////////////////
181 /// Copy visualization parameters from element el.
182 
183 void REvePointSet::CopyVizParams(const REveElement* el)
184 {
185  const REvePointSet* m = dynamic_cast<const REvePointSet*>(el);
186  if (m)
187  {
188  TAttMarker::operator=(*m);
189  }
190 
191  REveElement::CopyVizParams(el);
192 }
193 
194 ////////////////////////////////////////////////////////////////////////////////
195 /// Write visualization parameters.
196 
197 void REvePointSet::WriteVizParams(std::ostream& out, const TString& var)
198 {
199  REveElement::WriteVizParams(out, var);
200 
201  TAttMarker::SaveMarkerAttributes(out, var);
202 }
203 
204 ////////////////////////////////////////////////////////////////////////////////
205 /// Virtual from REveProjectable, returns REvePointSetProjected class.
206 
207 TClass* REvePointSet::ProjectedClass(const REveProjection*) const
208 {
209  return TClass::GetClass<REvePointSetProjected>();
210 }
211 
212 
213 Int_t REvePointSet::WriteCoreJson(nlohmann::json& j, Int_t rnr_offset)
214 {
215  Int_t ret = REveElement::WriteCoreJson(j, rnr_offset);
216 
217  j["fMarkerSize"] = GetMarkerSize();
218  j["fMarkerColor"] = GetMarkerColor();
219 
220  return ret;
221 }
222 
223 ////////////////////////////////////////////////////////////////////////////////
224 /// Crates 3D point array for rendering.
225 
226 void REvePointSet::BuildRenderData()
227 {
228  if (fSize > 0)
229  {
230  fRenderData = std::make_unique<REveRenderData>("makeHit", 3*fSize);
231  fRenderData->PushV(&fPoints[0].fX, 3*fSize);
232  }
233 }
234 
235 ////////////////////////////////////////////////////////////////////////////////
236 /// Compute bounding box.
237 
238 void REvePointSet::ComputeBBox()
239 {
240  if (fSize > 0) {
241  BBoxInit();
242  for (auto &p : fPoints)
243  {
244  BBoxCheckPoint(p.fX, p.fY, p.fZ);
245  }
246  } else {
247  BBoxZero();
248  }
249 }
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 /// Virtual method of base class TPointSet3D. The function call is
253 /// invoked with secondary selection in TPointSet3DGL.
254 
255 void REvePointSet::PointSelected(Int_t /* id */)
256 {
257  // Emit("PointSelected(Int_t)", id);
258 }
259 
260 
261 //==============================================================================
262 // REvePointSetArray
263 //==============================================================================
264 
265 /** \class REvePointSetArray
266 \ingroup REve
267 An array of point-sets with each point-set playing a role of a bin
268 in a histogram. When a new point is added to a REvePointSetArray,
269 an additional separating quantity needs to be specified: it
270 determines into which REvePointSet (bin) the point will actually be
271 stored. Underflow and overflow bins are automatically created but
272 they are not drawn by default.
273 
274 By using the REvePointSelector the points and the separating
275 quantities can be filled directly from a TTree holding the source
276 data.
277 Setting of per-point TRef's is not supported.
278 
279 After the filling, the range of separating variable can be
280 controlled with a slider to choose a sub-set of PointSets that are
281 actually shown.
282 */
283 
284 ////////////////////////////////////////////////////////////////////////////////
285 /// Constructor.
286 
287 REvePointSetArray::REvePointSetArray(const std::string& name,
288  const std::string& title) :
289  REveElement(name, title),
290 
291  fBins(nullptr), fDefPointSetCapacity(128), fNBins(0), fLastBin(-1),
292  fMin(0), fCurMin(0), fMax(0), fCurMax(0),
293  fBinWidth(0),
294  fQuantName()
295 {
296  SetMainColorPtr(&fMarkerColor);
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////
300 /// Destructor: deletes the fBins array. Actual removal of
301 /// elements done by REveElement.
302 
303 REvePointSetArray::~REvePointSetArray()
304 {
305  // printf("REvePointSetArray::~REvePointSetArray()\n");
306  delete [] fBins; fBins = nullptr;
307 }
308 
309 ////////////////////////////////////////////////////////////////////////////////
310 /// Virtual from REveElement, provide bin management.
311 
312 void REvePointSetArray::RemoveElementLocal(REveElement* el)
313 {
314  for (Int_t i=0; i<fNBins; ++i) {
315  if (fBins[i] == el) {
316  fBins[i] = nullptr;
317  break;
318  }
319  }
320 }
321 
322 ////////////////////////////////////////////////////////////////////////////////
323 /// Virtual from REveElement, provide bin management.
324 
325 void REvePointSetArray::RemoveElementsLocal()
326 {
327  delete [] fBins; fBins = nullptr; fLastBin = -1;
328 }
329 
330 ////////////////////////////////////////////////////////////////////////////////
331 /// Set marker color, propagate to children.
332 
333 void REvePointSetArray::SetMarkerColor(Color_t tcolor)
334 {
335  for (auto & el : fChildren)
336  {
337  TAttMarker* m = dynamic_cast<TAttMarker*>(el);
338  if (m && m->GetMarkerColor() == fMarkerColor)
339  m->SetMarkerColor(tcolor);
340  }
341  TAttMarker::SetMarkerColor(tcolor);
342 }
343 
344 ////////////////////////////////////////////////////////////////////////////////
345 /// Set marker style, propagate to children.
346 
347 void REvePointSetArray::SetMarkerStyle(Style_t mstyle)
348 {
349  for (auto & el : fChildren)
350  {
351  TAttMarker* m = dynamic_cast<TAttMarker*>(el);
352  if (m && m->GetMarkerStyle() == fMarkerStyle)
353  m->SetMarkerStyle(mstyle);
354  }
355  TAttMarker::SetMarkerStyle(mstyle);
356 }
357 
358 ////////////////////////////////////////////////////////////////////////////////
359 /// Set marker size, propagate to children.
360 
361 void REvePointSetArray::SetMarkerSize(Size_t msize)
362 {
363  for (auto & el : fChildren)
364  {
365  TAttMarker* m = dynamic_cast<TAttMarker*>(el);
366  if (m && m->GetMarkerSize() == fMarkerSize)
367  m->SetMarkerSize(msize);
368  }
369  TAttMarker::SetMarkerSize(msize);
370 }
371 
372 ////////////////////////////////////////////////////////////////////////////////
373 /// Get the total number of filled points.
374 /// 'under' and 'over' flags specify if under/overflow channels
375 /// should be added to the sum.
376 
377 Int_t REvePointSetArray::Size(Bool_t under, Bool_t over) const
378 {
379  Int_t size = 0;
380  const Int_t min = under ? 0 : 1;
381  const Int_t max = over ? fNBins : fNBins - 1;
382  for (Int_t i = min; i < max; ++i)
383  {
384  if (fBins[i])
385  size += fBins[i]->GetSize();
386  }
387  return size;
388 }
389 
390 ////////////////////////////////////////////////////////////////////////////////
391 /// Initialize internal point-sets with given binning parameters.
392 /// The actual number of bins is nbins+2, bin 0 corresponding to
393 /// underflow and bin nbin+1 to owerflow pointset.
394 
395 void REvePointSetArray::InitBins(const std::string& quant_name,
396  Int_t nbins, Double_t min, Double_t max)
397 {
398  static const REveException eh("REvePointSetArray::InitBins ");
399 
400  if (nbins < 1) throw eh + "nbins < 1.";
401  if (min > max) throw eh + "min > max.";
402 
403  RemoveElements();
404 
405  fQuantName = quant_name;
406  fNBins = nbins + 2; // under/overflow
407  fLastBin = -1;
408  fMin = fCurMin = min;
409  fMax = fCurMax = max;
410  fBinWidth = (fMax - fMin)/(fNBins - 2);
411 
412  fBins = new REvePointSet* [fNBins];
413 
414  for (Int_t i = 0; i < fNBins; ++i)
415  {
416  fBins[i] = new REvePointSet
417  (Form("Slice %d [%4.3lf, %4.3lf]", i, fMin + (i-1)*fBinWidth, fMin + i*fBinWidth),
418  "",
419  fDefPointSetCapacity);
420  fBins[i]->SetMarkerColor(fMarkerColor);
421  fBins[i]->SetMarkerStyle(fMarkerStyle);
422  fBins[i]->SetMarkerSize(fMarkerSize);
423  AddElement(fBins[i]);
424  }
425 
426  fBins[0]->SetName("Underflow");
427  fBins[0]->SetRnrSelf(kFALSE);
428 
429  fBins[fNBins-1]->SetName("Overflow");
430  fBins[fNBins-1]->SetRnrSelf(kFALSE);
431 }
432 
433 ////////////////////////////////////////////////////////////////////////////////
434 /// Add a new point. Appropriate point-set will be chosen based on
435 /// the value of the separating quantity 'quant'.
436 /// If the selected bin does not have an associated REvePointSet
437 /// the point is discarded and false is returned.
438 
439 Bool_t REvePointSetArray::Fill(Double_t x, Double_t y, Double_t z, Double_t quant)
440 {
441  fLastBin = TMath::FloorNint((quant - fMin)/fBinWidth) + 1;
442 
443  if (fLastBin < 0)
444  {
445  fLastBin = 0;
446  }
447  else if (fLastBin > fNBins - 1)
448  {
449  fLastBin = fNBins - 1;
450  }
451 
452  if (fBins[fLastBin] != 0)
453  {
454  fBins[fLastBin]->SetNextPoint(x, y, z);
455  return kTRUE;
456  }
457  else
458  {
459  return kFALSE;
460  }
461 }
462 
463 ////////////////////////////////////////////////////////////////////////////////
464 /// Call this after all the points have been filled.
465 /// At this point we can calculate bounding-boxes of individual
466 /// point-sets.
467 
468 void REvePointSetArray::CloseBins()
469 {
470  for (Int_t i=0; i<fNBins; ++i)
471  {
472  if (fBins[i])
473  {
474  fBins[i]->SetTitle(Form("N=%d", fBins[i]->GetSize()));
475  fBins[i]->ComputeBBox();
476  }
477  }
478  fLastBin = -1;
479 }
480 
481 ////////////////////////////////////////////////////////////////////////////////
482 /// Set active range of the separating quantity.
483 /// Appropriate point-sets are tagged for rendering.
484 /// Over/underflow point-sets are left as they were.
485 
486 void REvePointSetArray::SetRange(Double_t min, Double_t max)
487 {
488  using namespace TMath;
489 
490  fCurMin = min; fCurMax = max;
491  Int_t low_b = Max(0, FloorNint((min-fMin)/fBinWidth)) + 1;
492  Int_t high_b = Min(fNBins-2, CeilNint ((max-fMin)/fBinWidth));
493 
494  for (Int_t i = 1; i < fNBins - 1; ++i)
495  {
496  if (fBins[i])
497  fBins[i]->SetRnrSelf(i>=low_b && i<=high_b);
498  }
499 }
500 
501 /** \class REvePointSetProjected
502 \ingroup REve
503 Projected copy of a REvePointSet.
504 */
505 
506 ////////////////////////////////////////////////////////////////////////////////
507 /// Default contructor.
508 
509 REvePointSetProjected::REvePointSetProjected() :
510  REvePointSet (),
511  REveProjected ()
512 {
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////////
516 /// Set projection manager and projection model.
517 /// Virtual from REveProjected.
518 
519 void REvePointSetProjected::SetProjection(REveProjectionManager* proj,
520  REveProjectable* model)
521 {
522  REveProjected::SetProjection(proj, model);
523  CopyVizParams(dynamic_cast<REveElement*>(model));
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////////
527 /// Set depth (z-coordinate) of the projected points.
528 
529 void REvePointSetProjected::SetDepthLocal(Float_t d)
530 {
531  SetDepthCommon(d, this, fBBox);
532 
533  // XXXX rewrite
534 
535  Int_t n = fSize;
536  Float_t *p = & fPoints[0].fZ;
537  for (Int_t i = 0; i < n; ++i, p+=3)
538  *p = fDepth;
539 }
540 
541 ////////////////////////////////////////////////////////////////////////////////
542 /// Re-apply the projection.
543 /// Virtual from REveProjected.
544 
545 void REvePointSetProjected::UpdateProjection()
546 {
547  REveProjection &proj = * fManager->GetProjection();
548  REvePointSet &ps = * dynamic_cast<REvePointSet*>(fProjectable);
549  REveTrans *tr = ps.PtrMainTrans(kFALSE);
550 
551  // XXXX rewrite
552 
553  Int_t n = ps.GetSize();
554  Reset(n);
555  fSize = n;
556  const Float_t *o = & ps.RefPoint(0).fX;
557  Float_t *p = & fPoints[0].fX;
558  for (Int_t i = 0; i < n; ++i, o+=3, p+=3)
559  {
560  proj.ProjectPointfv(tr, o, p, fDepth);
561  }
562 }
563 
564 ////////////////////////////////////////////////////////////////////////////////
565 /// Virtual method of base class TPointSet3D.
566 /// Forward to projectable.
567 
568 void REvePointSetProjected::PointSelected(Int_t id)
569 {
570  REvePointSet *ps = dynamic_cast<REvePointSet*>(fProjectable);
571  ps->PointSelected(id);
572 }