Logo ROOT  
Reference Guide
REveBoxSet.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 "ROOT/REveBoxSet.hxx"
13#include "ROOT/REveShape.hxx"
16
17#include "TRandom.h"
18#include <cassert>
19
20#include <nlohmann/json.hpp>
21
22using namespace::ROOT::Experimental;
23
24/** \class REveBoxSet
25\ingroup REve
26Collection of 3D primitives (fixed-size boxes, boxes of different
27sizes, or arbitrary sexto-epipeds, cones). Each primitive can be assigned
28a signal value and a TRef.
29
30A collection of 3D-markers. The way how they are defined depends
31on the fBoxType data-member.
32 - kBT_FreeBox arbitrary box: specify 8*(x,y,z) box corners
33 - kBT_AABox axis-aligned box: specify (x,y,z) and (w, h, d)
34 - kBT_AABoxFixedDim axis-aligned box w/ fixed dimensions: specify (x,y,z)
35 also set fDefWidth, fDefHeight and fDefDepth
36 - kBT_Cone cone defined with position, axis-vector and radius
37 - EllipticCone cone with elliptic base (specify another radius and angle in deg)
38
39Each primitive can be assigned:
40
41 1. Color or signal value. Thresholds and signal-to-color mapping
42 can then be set dynamically via the REveRGBAPalette class.
43 2. External TObject* (stored as TRef).
44
45See also base-class REveDigitSet for more information.
46Tutorial: tutorials/eve/boxset_test.C
47*/
48
49////////////////////////////////////////////////////////////////////////////////
50
51REveBoxSet::REveBoxSet(const char* n, const char* t) :
52 REveDigitSet (n, t),
53
54 fBoxType (kBT_Undef),
55 fDefWidth (1),
56 fDefHeight (1),
57 fDefDepth (1),
58
59 fBoxSkip (0),
60
61 fDrawConeCap (kFALSE)
62{
63 // Constructor.
64
65 // Override from REveDigitSet.
66 fDisableLighting = kFALSE;
67}
68
69////////////////////////////////////////////////////////////////////////////////
70/// Return size of data-structure describing a box of type bt.
71
72Int_t REveBoxSet::SizeofAtom(REveBoxSet::EBoxType_e bt)
73{
74 static const REveException eH("REveBoxSet::SizeofAtom ");
75
76 switch (bt) {
77 case kBT_Undef: return 0;
78 case kBT_FreeBox: return sizeof(BFreeBox_t);
79 case kBT_AABox: return sizeof(BAABox_t);
80 case kBT_AABoxFixedDim: return sizeof(BAABoxFixedDim_t);
81 case kBT_Cone: return sizeof(BCone_t);
82 case kBT_EllipticCone: return sizeof(BEllipticCone_t);
83 case kBT_Hex: return sizeof(BHex_t);
84 default: throw(eH + "unexpected atom type.");
85 }
86 return 0;
87}
88
89////////////////////////////////////////////////////////////////////////////////
90/// Reset the data containers to zero size.
91/// The arguments describe the basic parameters of data storage.
92
93void REveBoxSet::Reset(REveBoxSet::EBoxType_e boxType, Bool_t valIsCol, Int_t chunkSize)
94{
95 fBoxType = boxType;
96 fValueIsColor = valIsCol;
97 fDefaultValue = valIsCol ? 0 : kMinInt;
98 ReleaseIds();
99 fPlex.Reset(SizeofAtom(fBoxType), chunkSize);
100}
101
102////////////////////////////////////////////////////////////////////////////////
103/// Reset the data containers to zero size.
104/// Keep the old data-storage parameters.
105
106void REveBoxSet::Reset()
107{
108 ReleaseIds();
109 fPlex.Reset(SizeofAtom(fBoxType), TMath::Max(fPlex.N(), 64));
110}
111
112////////////////////////////////////////////////////////////////////////////////
113/// Create a new box from a set of 8 vertices.
114/// To be used for box-type kBT_FreeBox.
115
116void REveBoxSet::AddBox(const Float_t* verts)
117{
118 static const REveException eH("REveBoxSet::AddBox ");
119
120 if (fBoxType != kBT_FreeBox)
121 throw(eH + "expect free box-type.");
122
123 BFreeBox_t* b = (BFreeBox_t*) NewDigit();
124 memcpy(b->fVertices, verts, sizeof(b->fVertices));
125 REveShape::CheckAndFixBoxOrientationFv(b->fVertices);
126}
127
128////////////////////////////////////////////////////////////////////////////////
129/// Create a new axis-aligned box from at a given position and with
130/// specified dimensions.
131/// To be used for box-type kBT_AABox.
132
133void REveBoxSet::AddBox(Float_t a, Float_t b, Float_t c, Float_t w, Float_t h, Float_t d)
134{
135 static const REveException eH("REveBoxSet::AddBox ");
136
137 if (fBoxType != kBT_AABox)
138 throw(eH + "expect axis-aligned box-type.");
139
140 BAABox_t* box = (BAABox_t*) NewDigit();
141 box->fA = a; box->fB = b; box->fC = c;
142 box->fW = w; box->fH = h; box->fD = d;
143}
144
145////////////////////////////////////////////////////////////////////////////////
146/// Create a new axis-aligned box from at a given position.
147/// To be used for box-type kBT_AABoxFixedDim.
148
149void REveBoxSet::AddBox(Float_t a, Float_t b, Float_t c)
150{
151 static const REveException eH("REveBoxSet::AddBox ");
152
153 if (fBoxType != kBT_AABoxFixedDim)
154 throw(eH + "expect axis-aligned fixed-dimension box-type.");
155
156 BAABoxFixedDim_t* box = (BAABoxFixedDim_t*) NewDigit();
157 box->fA = a; box->fB = b; box->fC = c;
158}
159
160////////////////////////////////////////////////////////////////////////////////
161/// Create a cone with apex at pos, axis dir and radius r.
162/// To be used for box-type kBT_Cone.
163
164void REveBoxSet::AddCone(const REveVector& pos, const REveVector& dir, Float_t r)
165{
166 static const REveException eH("REveBoxSet::AddCone ");
167
168 if (fBoxType != kBT_Cone)
169 throw(eH + "expect cone box-type.");
170
171 BCone_t* cone = (BCone_t*) NewDigit();
172 cone->fPos = pos;
173 cone->fDir = dir;
174 cone->fR = r;
175}
176
177////////////////////////////////////////////////////////////////////////////////
178/// Create a cone with apex at pos, axis dir and radius r.
179/// To be used for box-type kBT_EllipticCone.
180
181void REveBoxSet::AddEllipticCone(const REveVector& pos, const REveVector& dir,
182 Float_t r, Float_t r2, Float_t angle)
183{
184 static const REveException eH("REveBoxSet::AddEllipticCone ");
185
186 if (fBoxType != kBT_EllipticCone)
187 throw(eH + "expect elliptic-cone box-type.");
188
189 BEllipticCone_t* cone = (BEllipticCone_t*) NewDigit();
190 cone->fPos = pos;
191 cone->fDir = dir;
192 cone->fR = r;
193 cone->fR2 = r2;
194 cone->fAngle = angle;
195}
196
197////////////////////////////////////////////////////////////////////////////////
198/// Create a hexagonal prism with center of one hexagon at pos, radius of
199/// hexagon vertices r, rotation angle angle (in degrees), and length along z
200/// of depth. To be used for box-type kBT_Hex.
201
202void REveBoxSet::AddHex(const REveVector& pos, Float_t r, Float_t angle, Float_t depth)
203{
204 static const REveException eH("REveBoxSet::AddEllipticCone ");
205
206 if (fBoxType != kBT_Hex)
207 throw(eH + "expect hex box-type.");
208
209 BHex_t* hex = (BHex_t*) NewDigit();
210 hex->fPos = pos;
211 hex->fR = r;
212 hex->fAngle = angle;
213 hex->fDepth = depth;
214}
215
216////////////////////////////////////////////////////////////////////////////////
217/// Fill bounding-box information of the base-class TAttBBox (virtual method).
218/// If member 'REveFrameBox* fFrame' is set, frame's corners are used as bbox.
219
220void REveBoxSet::ComputeBBox()
221{
222 static const REveException eH("REveBoxSet::ComputeBBox ");
223
224 if (fFrame != 0)
225 {
226 BBoxInit();
227 Int_t n = fFrame->GetFrameSize() / 3;
228 Float_t *bbps = fFrame->GetFramePoints();
229 for (int i=0; i<n; ++i, bbps+=3)
230 BBoxCheckPoint(bbps);
231 return;
232 }
233
234 if(fPlex.Size() == 0)
235 {
236 BBoxZero();
237 return;
238 }
239
240 BBoxInit();
241
243 switch (fBoxType)
244 {
245
246 case kBT_FreeBox:
247 {
248 while (bi.next()) {
249 BFreeBox_t& b = * (BFreeBox_t*) bi();
250 for (Int_t i = 0; i < 8; ++i)
251 BBoxCheckPoint(b.fVertices[i]);
252 }
253 break;
254 }
255
256 case kBT_AABox:
257 {
258 while (bi.next()) {
259 BAABox_t& b = * (BAABox_t*) bi();
260 BBoxCheckPoint(b.fA, b.fB, b.fC);
261 BBoxCheckPoint(b.fA + b.fW, b.fB + b.fH , b.fC + b.fD);
262 }
263 break;
264 }
265
266 case kBT_AABoxFixedDim:
267 {
268 while (bi.next()) {
270 BBoxCheckPoint(b.fA, b.fB, b.fC);
271 BBoxCheckPoint(b.fA + fDefWidth, b.fB + fDefHeight , b.fC + fDefDepth);
272 }
273 break;
274 }
275
276 case kBT_Cone:
277 {
278 Float_t mag2=0, mag2Max=0, rMax=0;
279 while (bi.next()) {
280 BCone_t& b = * (BCone_t*) bi();
281 BBoxCheckPoint(b.fPos.fX, b.fPos.fY, b.fPos.fZ);
282 mag2 = b.fDir.Mag2();
283 if (mag2>mag2Max) mag2Max=mag2;
284 if (b.fR>rMax) rMax=b.fR;
285 }
286 Float_t off = TMath::Sqrt(mag2Max + rMax*rMax);
287 fBBox[0] -= off;fBBox[2] -= off;fBBox[4] -= off;
288 fBBox[1] += off;fBBox[3] += off;fBBox[5] += off;
289 break;
290 }
291
292 case kBT_EllipticCone:
293 {
294 Float_t mag2=0, mag2Max=0, rMax=0;
295 while (bi.next()) {
296 BEllipticCone_t& b = * (BEllipticCone_t*) bi();
297 BBoxCheckPoint(b.fPos.fX, b.fPos.fY, b.fPos.fZ);
298 mag2 = b.fDir.Mag2();
299 if (mag2>mag2Max) mag2Max=mag2;
300 if (b.fR > rMax) rMax = b.fR;
301 if (b.fR2 > rMax) rMax = b.fR2;
302 }
303 Float_t off = TMath::Sqrt(mag2Max + rMax*rMax);
304 fBBox[0] -= off;fBBox[2] -= off;fBBox[4] -= off;
305 fBBox[1] += off;fBBox[3] += off;fBBox[5] += off;
306 break;
307 }
308
309 case kBT_Hex:
310 {
311 while (bi.next()) {
312 BHex_t& h = * (BHex_t*) bi();
313 BBoxCheckPoint(h.fPos.fX - h.fR, h.fPos.fY - h.fR, h.fPos.fZ);
314 BBoxCheckPoint(h.fPos.fX + h.fR, h.fPos.fY - h.fR, h.fPos.fZ);
315 BBoxCheckPoint(h.fPos.fX + h.fR, h.fPos.fY + h.fR, h.fPos.fZ);
316 BBoxCheckPoint(h.fPos.fX - h.fR, h.fPos.fY + h.fR, h.fPos.fZ);
317 BBoxCheckPoint(h.fPos.fX - h.fR, h.fPos.fY - h.fR, h.fPos.fZ + h.fDepth);
318 BBoxCheckPoint(h.fPos.fX + h.fR, h.fPos.fY - h.fR, h.fPos.fZ + h.fDepth);
319 BBoxCheckPoint(h.fPos.fX + h.fR, h.fPos.fY + h.fR, h.fPos.fZ + h.fDepth);
320 BBoxCheckPoint(h.fPos.fX - h.fR, h.fPos.fY + h.fR, h.fPos.fZ + h.fDepth);
321 }
322 break;
323 }
324
325 default:
326 {
327 throw(eH + "unsupported box-type.");
328 }
329
330 } // end switch box-type
331}
332
333////////////////////////////////////////////////////////////////////////////////
334/// Fill core part of JSON representation.
335
336Int_t REveBoxSet::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset)
337{
338 Int_t ret = REveDigitSet::WriteCoreJson(j, rnr_offset);
339 j["boxType"] = int(fBoxType);
340
341 return ret;
342}
343
344////////////////////////////////////////////////////////////////////////////////
345/// Crates 3D point array for rendering.
346
347void REveBoxSet::BuildRenderData()
348{
349 fRenderData = std::make_unique<REveRenderData>("makeBoxSet", fPlex.Size()*24, 0, fPlex.Size());
350
351 switch (fBoxType)
352 {
353 case REveBoxSet::kBT_FreeBox:
354 {
356 while (bi.next())
357 {
359 // vertices
360 for (int c =0; c < 8; c++) {
361 for (int j =0; j < 3; j++)
362 fRenderData->PushV(b.fVertices[c][j]);
363 }
364 }
365 break;
366 }
367 case REveBoxSet::kBT_AABox:
368 {
370 while (bi.next())
371 {
373 // position
374 fRenderData->PushV(b.fA, b.fB, b.fC);
375 // dimensions
376 fRenderData->PushV(b.fW, b.fH, b.fD);
377 }
378 break;
379 }
380 default:
381 assert(false && "REveBoxSet::BuildRenderData only kBT_FreeBox type supported");
382 }
383
384 //
385 // setup colors
386 //
387 if (fSingleColor == false)
388 {
390 while (bi.next())
391 {
393 if (fValueIsColor)
394 {
395 fRenderData->PushI(int(b.fValue));
396 }
397 else if (fSingleColor == false)
398 {
399 UChar_t c[4] = {0, 0, 0, 0};
400 Bool_t visible = fPalette->ColorFromValue(b.fValue, fDefaultValue, c);
401
402 int value =
403 c[0] +
404 c[1] * 256 +
405 c[2] * 256*256;
406
407 // printf("box val [%d] values (%d, %d, %d) -> int <%d>\n", b.fValue, c[0], c[1], c[2], value);
408
409 // presume transparency 100% when non-visible
410 if (!visible)
411 value += 256*256*256*c[3];
412
413
414 fRenderData->PushI(value);
415 }
416 }
417 }
418
419 if (!fDigitIds.empty())
420 {
421 for (int i = 0; i < fPlex.N(); ++i)
422 {
423 fRenderData->PushI(GetId(i));
424 }
425 }
426}
427
428////////////////////////////////////////////////////////////////////////////////
429/// Fill the structure with a random set of boxes.
430
431void REveBoxSet::Test(Int_t nboxes)
432{
433 Reset(kBT_AABox, kTRUE, nboxes);
434 TRandom rnd(0);
435 const Float_t origin = 10, size = 2;
436 Int_t color;
437 for(Int_t i=0; i<nboxes; ++i)
438 {
439 AddBox(origin * rnd.Uniform(-1, 1),
440 origin * rnd.Uniform(-1, 1),
441 origin * rnd.Uniform(-1, 1),
442 size * rnd.Uniform(0.1, 1),
443 size * rnd.Uniform(0.1, 1),
444 size * rnd.Uniform(0.1, 1));
445
446 REveUtil::ColorFromIdx(rnd.Integer(256), (UChar_t*)&color);
447 DigitValue(color);
448 }
449}
ROOT::R::TRInterface & r
Definition: Object.C:4
#define d(i)
Definition: RSha256.hxx:102
#define b(i)
Definition: RSha256.hxx:100
#define c(i)
Definition: RSha256.hxx:101
#define h(i)
Definition: RSha256.hxx:106
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
const Int_t kMinInt
Definition: RtypesCore.h:113
int Int_t
Definition: RtypesCore.h:45
unsigned char UChar_t
Definition: RtypesCore.h:38
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
float Float_t
Definition: RtypesCore.h:57
const Bool_t kTRUE
Definition: RtypesCore.h:100
Base-class for storage of digit collections; provides transformation matrix (REveTrans),...
REveException Exception-type thrown by Eve classes.
Definition: REveTypes.hxx:41
This is the base class for the ROOT Random number generators.
Definition: TRandom.h:27
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
Definition: TRandom.cxx:672
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition: TRandom.cxx:360
void box(Int_t pat, Double_t x1, Double_t y1, Double_t x2, Double_t y2)
Definition: fillpatterns.C:1
const Int_t n
Definition: legend1.C:16
Short_t Max(Short_t a, Short_t b)
Definition: TMathBase.h:212
Double_t Sqrt(Double_t x)
Definition: TMath.h:691
auto * a
Definition: textangle.C:12