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 "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 if (fOwnIds)
99 ReleaseIds();
100 fPlex.Reset(SizeofAtom(fBoxType), chunkSize);
101}
102
103////////////////////////////////////////////////////////////////////////////////
104/// Reset the data containers to zero size.
105/// Keep the old data-storage parameters.
106
107void REveBoxSet::Reset()
108{
109 if (fOwnIds)
110 ReleaseIds();
111 fPlex.Reset(SizeofAtom(fBoxType), TMath::Max(fPlex.N(), 64));
112}
113
114////////////////////////////////////////////////////////////////////////////////
115/// Create a new box from a set of 8 vertices.
116/// To be used for box-type kBT_FreeBox.
117
118void REveBoxSet::AddBox(const Float_t* verts)
119{
120 static const REveException eH("REveBoxSet::AddBox ");
121
122 if (fBoxType != kBT_FreeBox)
123 throw(eH + "expect free box-type.");
124
125 BFreeBox_t* b = (BFreeBox_t*) NewDigit();
126 memcpy(b->fVertices, verts, sizeof(b->fVertices));
127 REveShape::CheckAndFixBoxOrientationFv(b->fVertices);
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// Create a new axis-aligned box from at a given position and with
132/// specified dimensions.
133/// To be used for box-type kBT_AABox.
134
135void REveBoxSet::AddBox(Float_t a, Float_t b, Float_t c, Float_t w, Float_t h, Float_t d)
136{
137 static const REveException eH("REveBoxSet::AddBox ");
138
139 if (fBoxType != kBT_AABox)
140 throw(eH + "expect axis-aligned box-type.");
141
142 BAABox_t* box = (BAABox_t*) NewDigit();
143 box->fA = a; box->fB = b; box->fC = c;
144 box->fW = w; box->fH = h; box->fD = d;
145}
146
147////////////////////////////////////////////////////////////////////////////////
148/// Create a new axis-aligned box from at a given position.
149/// To be used for box-type kBT_AABoxFixedDim.
150
151void REveBoxSet::AddBox(Float_t a, Float_t b, Float_t c)
152{
153 static const REveException eH("REveBoxSet::AddBox ");
154
155 if (fBoxType != kBT_AABoxFixedDim)
156 throw(eH + "expect axis-aligned fixed-dimension box-type.");
157
158 BAABoxFixedDim_t* box = (BAABoxFixedDim_t*) NewDigit();
159 box->fA = a; box->fB = b; box->fC = c;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163/// Create a cone with apex at pos, axis dir and radius r.
164/// To be used for box-type kBT_Cone.
165
166void REveBoxSet::AddCone(const REveVector& pos, const REveVector& dir, Float_t r)
167{
168 static const REveException eH("REveBoxSet::AddCone ");
169
170 if (fBoxType != kBT_Cone)
171 throw(eH + "expect cone box-type.");
172
173 BCone_t* cone = (BCone_t*) NewDigit();
174 cone->fPos = pos;
175 cone->fDir = dir;
176 cone->fR = r;
177}
178
179////////////////////////////////////////////////////////////////////////////////
180/// Create a cone with apex at pos, axis dir and radius r.
181/// To be used for box-type kBT_EllipticCone.
182
183void REveBoxSet::AddEllipticCone(const REveVector& pos, const REveVector& dir,
184 Float_t r, Float_t r2, Float_t angle)
185{
186 static const REveException eH("REveBoxSet::AddEllipticCone ");
187
188 if (fBoxType != kBT_EllipticCone)
189 throw(eH + "expect elliptic-cone box-type.");
190
191 BEllipticCone_t* cone = (BEllipticCone_t*) NewDigit();
192 cone->fPos = pos;
193 cone->fDir = dir;
194 cone->fR = r;
195 cone->fR2 = r2;
196 cone->fAngle = angle;
197}
198
199////////////////////////////////////////////////////////////////////////////////
200/// Create a hexagonal prism with center of one hexagon at pos, radius of
201/// hexagon vertices r, rotation angle angle (in degrees), and length along z
202/// of depth. To be used for box-type kBT_Hex.
203
204void REveBoxSet::AddHex(const REveVector& pos, Float_t r, Float_t angle, Float_t depth)
205{
206 static const REveException eH("REveBoxSet::AddEllipticCone ");
207
208 if (fBoxType != kBT_Hex)
209 throw(eH + "expect hex box-type.");
210
211 BHex_t* hex = (BHex_t*) NewDigit();
212 hex->fPos = pos;
213 hex->fR = r;
214 hex->fAngle = angle;
215 hex->fDepth = depth;
216}
217
218////////////////////////////////////////////////////////////////////////////////
219/// Fill bounding-box information of the base-class TAttBBox (virtual method).
220/// If member 'REveFrameBox* fFrame' is set, frame's corners are used as bbox.
221
222void REveBoxSet::ComputeBBox()
223{
224 static const REveException eH("REveBoxSet::ComputeBBox ");
225
226 if (fFrame != 0)
227 {
228 BBoxInit();
229 Int_t n = fFrame->GetFrameSize() / 3;
230 Float_t *bbps = fFrame->GetFramePoints();
231 for (int i=0; i<n; ++i, bbps+=3)
232 BBoxCheckPoint(bbps);
233 return;
234 }
235
236 if(fPlex.Size() == 0)
237 {
238 BBoxZero();
239 return;
240 }
241
242 BBoxInit();
243
245 switch (fBoxType)
246 {
247
248 case kBT_FreeBox:
249 {
250 while (bi.next()) {
251 BFreeBox_t& b = * (BFreeBox_t*) bi();
252 for (Int_t i = 0; i < 8; ++i)
253 BBoxCheckPoint(b.fVertices[i]);
254 }
255 break;
256 }
257
258 case kBT_AABox:
259 {
260 while (bi.next()) {
261 BAABox_t& b = * (BAABox_t*) bi();
262 BBoxCheckPoint(b.fA, b.fB, b.fC);
263 BBoxCheckPoint(b.fA + b.fW, b.fB + b.fH , b.fC + b.fD);
264 }
265 break;
266 }
267
268 case kBT_AABoxFixedDim:
269 {
270 while (bi.next()) {
272 BBoxCheckPoint(b.fA, b.fB, b.fC);
273 BBoxCheckPoint(b.fA + fDefWidth, b.fB + fDefHeight , b.fC + fDefDepth);
274 }
275 break;
276 }
277
278 case kBT_Cone:
279 {
280 Float_t mag2=0, mag2Max=0, rMax=0;
281 while (bi.next()) {
282 BCone_t& b = * (BCone_t*) bi();
283 BBoxCheckPoint(b.fPos.fX, b.fPos.fY, b.fPos.fZ);
284 mag2 = b.fDir.Mag2();
285 if (mag2>mag2Max) mag2Max=mag2;
286 if (b.fR>rMax) rMax=b.fR;
287 }
288 Float_t off = TMath::Sqrt(mag2Max + rMax*rMax);
289 fBBox[0] -= off;fBBox[2] -= off;fBBox[4] -= off;
290 fBBox[1] += off;fBBox[3] += off;fBBox[5] += off;
291 break;
292 }
293
294 case kBT_EllipticCone:
295 {
296 Float_t mag2=0, mag2Max=0, rMax=0;
297 while (bi.next()) {
298 BEllipticCone_t& b = * (BEllipticCone_t*) bi();
299 BBoxCheckPoint(b.fPos.fX, b.fPos.fY, b.fPos.fZ);
300 mag2 = b.fDir.Mag2();
301 if (mag2>mag2Max) mag2Max=mag2;
302 if (b.fR > rMax) rMax = b.fR;
303 if (b.fR2 > rMax) rMax = b.fR2;
304 }
305 Float_t off = TMath::Sqrt(mag2Max + rMax*rMax);
306 fBBox[0] -= off;fBBox[2] -= off;fBBox[4] -= off;
307 fBBox[1] += off;fBBox[3] += off;fBBox[5] += off;
308 break;
309 }
310
311 case kBT_Hex:
312 {
313 while (bi.next()) {
314 BHex_t& h = * (BHex_t*) bi();
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);
318 BBoxCheckPoint(h.fPos.fX - h.fR, h.fPos.fY + h.fR, h.fPos.fZ);
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 BBoxCheckPoint(h.fPos.fX + h.fR, h.fPos.fY + h.fR, h.fPos.fZ + h.fDepth);
322 BBoxCheckPoint(h.fPos.fX - h.fR, h.fPos.fY + h.fR, h.fPos.fZ + h.fDepth);
323 }
324 break;
325 }
326
327 default:
328 {
329 throw(eH + "unsupported box-type.");
330 }
331
332 } // end switch box-type
333}
334
335////////////////////////////////////////////////////////////////////////////////
336/// Fill core part of JSON representation.
337
338Int_t REveBoxSet::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset)
339{
340 Int_t ret = REveDigitSet::WriteCoreJson(j, rnr_offset);
341 j["boxType"] = int(fBoxType);
342
343 printf(" WriteCoreJsonMAIN color %d \n", GetMainColor());
344
345 return ret;
346}
347
348////////////////////////////////////////////////////////////////////////////////
349/// Crates 3D point array for rendering.
350
351void REveBoxSet::BuildRenderData()
352{
353 fRenderData = std::make_unique<REveRenderData>("makeBoxSet", fPlex.Size()*24, 0, fPlex.Size());
354
355 switch (fBoxType)
356 {
357 case REveBoxSet::kBT_FreeBox:
358 {
360 while (bi.next())
361 {
363 // vertices
364 for (int c =0; c < 8; c++) {
365 for (int j =0; j < 3; j++)
366 fRenderData->PushV(b.fVertices[c][j]);
367 }
368 }
369 break;
370 }
371 case REveBoxSet::kBT_AABox:
372 {
374 while (bi.next())
375 {
377 // position
378 fRenderData->PushV(b.fA, b.fB, b.fC);
379 // dimensions
380 fRenderData->PushV(b.fW, b.fH, b.fD);
381 }
382 break;
383 }
384 default:
385 assert(false && "REveBoxSet::BuildRenderData only kBT_FreeBox type supported");
386 }
387
388 //
389 // setup colors
390 //
391 if (fSingleColor == false)
392 {
393
395 while (bi.next())
396 {
398 if (fValueIsColor)
399 {
400 fRenderData->PushI(int(b.fValue));
401 }
402 else if (fSingleColor == false)
403 {
404 UChar_t c[4] = {0, 0, 0, 0};
405 Bool_t visible = fPalette->ColorFromValue(b.fValue, fDefaultValue, c);
406
407 int value =
408 c[0] +
409 c[1] * 256 +
410 c[2] * 256*256;
411
412 // printf("box val [%d] values (%d, %d, %d) -> int <%d>\n", b.fValue, c[0], c[1], c[2], value);
413
414 // presume transparency 100% when non-visible
415 if (!visible)
416 value += 256*256*256*c[3];
417
418
419 fRenderData->PushI(value);
420 }
421 }
422 }
423}
424
425////////////////////////////////////////////////////////////////////////////////
426/// Fill the structure with a random set of boxes.
427
428void REveBoxSet::Test(Int_t nboxes)
429{
430 Reset(kBT_AABox, kTRUE, nboxes);
431 TRandom rnd(0);
432 const Float_t origin = 10, size = 2;
433 Int_t color;
434 for(Int_t i=0; i<nboxes; ++i)
435 {
436 AddBox(origin * rnd.Uniform(-1, 1),
437 origin * rnd.Uniform(-1, 1),
438 origin * rnd.Uniform(-1, 1),
439 size * rnd.Uniform(0.1, 1),
440 size * rnd.Uniform(0.1, 1),
441 size * rnd.Uniform(0.1, 1));
442
443 REveUtil::ColorFromIdx(rnd.Integer(256), (UChar_t*)&color);
444 DigitValue(color);
445 }
446}
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
const Int_t kMinInt
Definition: RtypesCore.h:102
unsigned char UChar_t
Definition: RtypesCore.h:36
const Bool_t kFALSE
Definition: RtypesCore.h:90
float Float_t
Definition: RtypesCore.h:55
const Bool_t kTRUE
Definition: RtypesCore.h:89
REveException Exception-type thrown by Eve classes.
Definition: REveTypes.hxx:40
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:635
virtual UInt_t Integer(UInt_t imax)
Returns a random integer uniformly distributed on the interval [ 0, imax-1 ].
Definition: TRandom.cxx:349
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:681
basic_json<> json
default JSON class
Definition: REveElement.hxx:88
auto * a
Definition: textangle.C:12