Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
orbits.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_eve_7
3/// Bodies orbiting bodies orbiting bodies, built as an element hierarchy.
4///
5/// The shapes are the random spheres, tubes, tube segments and cut tubes of
6/// gl/glViewerLOD.C. Each body sits at a distance from the origin of a pivot,
7/// a plain REveElement that spins about its local z axis, so the body moves on
8/// a circle in the pivot's xy plane. Each body spins about its own z axis as
9/// well. The pivots of a body's children are the body's children, so the
10/// children orbit in the body's frame and follow both its orbit and its spin.
11///
12/// The spins are set with REveTrans::SetMotion() and extrapolated on the
13/// client. A timer advances each matrix to the current angle and sends the
14/// motion again every kRefreshSec, which also brings the motion to a client
15/// that connects later.
16///
17/// \macro_code
18///
19/// \author Matevz Tadel
20
21#include <ROOT/REveElement.hxx>
22#include <ROOT/REveGeoShape.hxx>
23#include <ROOT/REveManager.hxx>
24#include <ROOT/REveScene.hxx>
25#include <ROOT/REveTrans.hxx>
26#include <ROOT/REveUtil.hxx>
27#include <ROOT/REveVector.hxx>
28
29#include "TGeoSphere.h"
30#include "TGeoTube.h"
31#include "TMath.h"
32#include "TRandom.h"
33#include "TTimer.h"
34
35#include <iterator>
36#include <vector>
37
38using namespace ROOT::Experimental;
39
40namespace {
41
42const Double_t kRefreshSec = 2.;
43
44const Color_t kColors[] = {kRed, kGreen + 1, kBlue, kOrange, kMagenta, kCyan + 1,
45 kYellow + 1, kAzure + 1, kViolet, kTeal, kPink + 1, kSpring};
46
47/// An element that spins about its local z axis at fRate rad/s, starting from
48/// fBase at server time fT0Ms.
49struct Spinner {
50 REveElement *fEl;
52 Double_t fRate;
53 Double_t fT0Ms;
54};
55
56std::vector<Spinner> gSpinners;
57
58/// A random shape of the kinds glViewerLOD.C uses, about `size` across.
59TGeoShape *RandomShape(Double_t size)
60{
61 TRandom &r = *gRandom;
62 const Double_t rMin = r.Rndm() * 0.5 * size;
63 const Double_t rMax = rMin + (0.2 + r.Rndm() * 0.5) * size;
64 const Double_t dz = (0.2 + r.Rndm()) * size;
65 const Double_t phi1 = r.Rndm() * 90.;
66 const Double_t phi2 = phi1 + 90. + r.Rndm() * 180.;
67
68 switch (r.Integer(4)) {
69 case 0: return new TGeoSphere(0., rMax);
70 case 1: return new TGeoTube(rMin, rMax, dz);
71 case 2: return new TGeoTubeSeg(rMin, rMax, dz, phi1, phi2);
72 default:
73 return new TGeoCtub(rMin, rMax, dz, phi1, phi2, r.Rndm() * .5, r.Rndm() * .5, -1. + r.Rndm() * .5, r.Rndm() * .5,
74 r.Rndm() * .5, 1. - r.Rndm() * .5);
75 }
76}
77
78/// Give `t` a random orientation, keeping its position.
79void RandomOrientation(REveTrans &t)
80{
81 TRandom &r = *gRandom;
82 t.RotateLF(1, 2, r.Uniform(0, TMath::TwoPi()));
83 t.RotateLF(2, 3, r.Uniform(0, TMath::Pi()));
84 t.RotateLF(1, 2, r.Uniform(0, TMath::TwoPi()));
85}
86
87void AddSpinner(REveElement *el, Double_t rate)
88{
89 gSpinners.push_back({el, el->RefMainTrans(), rate, REveUtil::ServerTimeMs()});
90}
91
92/// Under `parent`, add `n` pivots, each with a body at `radius`, and recurse
93/// for `levels` - 1 more levels with smaller bodies and orbits.
94void AddLevel(REveElement *parent, Int_t levels, Int_t n, Double_t radius, Double_t size)
95{
96 TRandom &r = *gRandom;
97 for (Int_t i = 0; i < n; ++i) {
98 auto pivot = new REveElement(Form("%s pivot %d", parent->GetCName(), i));
99 RandomOrientation(pivot->RefMainTrans());
100 parent->AddElement(pivot);
101 AddSpinner(pivot, r.Uniform(0.2, 0.6) * (r.Rndm() < 0.5 ? -1 : 1));
102
103 auto body = new REveGeoShape(Form("%s body %d", parent->GetCName(), i));
104 body->SetShape(RandomShape(size));
105 body->SetMainColor(kColors[r.Integer(std::size(kColors))]);
106 body->RefMainTrans().SetPos(radius * r.Uniform(0.7, 1.3), 0, 0);
107 RandomOrientation(body->RefMainTrans());
108 pivot->AddElement(body);
109 AddSpinner(body, r.Uniform(0.5, 1.5) * (r.Rndm() < 0.5 ? -1 : 1));
110
111 if (levels > 1)
112 AddLevel(body, levels - 1, n, 0.35 * radius, 0.4 * size);
113 }
114}
115
116/// Advances every spinner to the current angle and sends the spin again.
117class OrbitRefresher : public TTimer {
118public:
119 OrbitRefresher() : TTimer(Long_t(1000 * kRefreshSec), kTRUE) {}
120
121 Bool_t Notify() override
122 {
124 const Double_t now = REveUtil::ServerTimeMs();
125 for (auto &s : gSpinners) {
126 REveTrans &t = s.fEl->RefMainTrans();
127 t = s.fBase;
128 t.RotateLF(1, 2, s.fRate * (now - s.fT0Ms) / 1000.);
129 t.SetMotion(REveVectorD(), REveVectorD(), REveVectorD(0, 0, 1), s.fRate, 2 * kRefreshSec);
130 s.fEl->StampTrans();
131 }
132 Reset();
133 return kTRUE;
134 }
135};
136
137} // namespace
138
139void orbits(Int_t levels = 3, Int_t n = 6, UInt_t seed = 4357)
140{
141 auto eveMng = REveManager::Create();
142 eveMng->AllowMultipleRemoteConnections(false, false);
143
144 gRandom->SetSeed(seed);
145 gSpinners.clear();
146
147 auto system = new REveElement("Orbits");
148 eveMng->GetEventScene()->AddElement(system);
149 AddLevel(system, levels, n, 1000, 150);
150
151 eveMng->Show();
152
153 auto timer = new OrbitRefresher;
154 timer->Notify();
155 timer->TurnOn();
156}
Converter * fBase
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
Definition RtypesCore.h:78
int Int_t
Signed integer 4 bytes (int)
Definition RtypesCore.h:60
short Color_t
Color number (short)
Definition RtypesCore.h:100
long Long_t
Signed long integer 4 bytes (long). Size depends on architecture.
Definition RtypesCore.h:69
unsigned int UInt_t
Unsigned integer 4 bytes (unsigned int)
Definition RtypesCore.h:61
double Double_t
Double 8 bytes.
Definition RtypesCore.h:74
constexpr Bool_t kTRUE
Definition RtypesCore.h:108
@ kTeal
Definition Rtypes.h:67
@ kPink
Definition Rtypes.h:67
@ kRed
Definition Rtypes.h:66
@ kOrange
Definition Rtypes.h:67
@ kGreen
Definition Rtypes.h:66
@ kMagenta
Definition Rtypes.h:66
@ kCyan
Definition Rtypes.h:66
@ kBlue
Definition Rtypes.h:66
@ kAzure
Definition Rtypes.h:67
@ kYellow
Definition Rtypes.h:66
@ kViolet
Definition Rtypes.h:67
@ kSpring
Definition Rtypes.h:67
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
R__EXTERN TRandom * gRandom
Definition TRandom.h:73
char * Form(const char *fmt,...)
Formats a string in a circular formatting buffer.
Definition TString.cxx:2571
Base class for REveUtil visualization elements, providing hierarchy management, rendering control and...
Wrapper for TGeoShape with absolute positioning and color attributes allowing display of extracted TG...
RAII guard for locking Eve manager (ctor) and processing changes (dtor).
REveTrans is a 4x4 transformation matrix for homogeneous coordinates stored internally in a column-ma...
The cut tubes constructor has the form:
Definition TGeoTube.h:174
Base abstract class for all shapes.
Definition TGeoShape.h:25
TGeoSphere are not just balls having internal and external radii, but sectors of a sphere having defi...
Definition TGeoSphere.h:17
A tube segment is a tube having a range in phi.
Definition TGeoTube.h:94
Cylindrical tube class.
Definition TGeoTube.h:17
This is the base class for the ROOT Random number generators.
Definition TRandom.h:28
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition TRandom.cxx:614
Handles synchronous and a-synchronous timer events.
Definition TTimer.h:51
void Reset()
Reset the timer.
Definition TTimer.cxx:162
Bool_t Notify() override
Notify when timer times out.
Definition TTimer.cxx:148
const Int_t n
Definition legend1.C:16
Namespace for ROOT features in testing.
Definition TROOT.h:100
constexpr Double_t Pi()
Definition TMath.h:40
constexpr Double_t TwoPi()
Definition TMath.h:47