Web-based GUI to draw the geometry shapes.
#include <vector>
#include <string>
std::string getOptions()
{
std::string opt;
if (grotate) opt.append("rotate;");
if (axis) opt.append("axis;");
return opt;
}
auto geomViewer = std::make_shared<ROOT::Experimental::REveGeomViewer>();
void display()
{
geomViewer->SetShowHierarchy(false);
geomViewer->Show({600, 600, 160, 0});
}
void autorotate()
{
grotate = !grotate;
geomViewer->SetDrawOptions(getOptions());
}
void axes()
{
axis = !axis;
geomViewer->SetDrawOptions(getOptions());
}
void gcomments()
{
comments = !comments;
if (!comments)
helpWindow->CloseConnections();
}
{
}
{
}
std::string AddDbl(
const char *datamember,
Double_t value,
const char *
comment)
{
}
std::string AddInt(
const char *datamember,
Int_t value,
const char *
comment)
{
}
void help(
const std::vector<std::string> &info = {},
TGeoVolume *fvol =
nullptr,
Int_t iaxis = 0,
const std::vector<std::string> &info2 = {})
{
if (!info.empty() && !comments)
return;
std::vector<std::string> lines({
" >>>>>>> web geometry viewer <<<<<< ",
" Demo for building TGeo basic shapes and simple geometry. Shape parameters are",
" displayed in the right pad",
"- Click left mouse button to execute one demo",
"- While pointing the mouse to the pad containing the geometry, do:",
"- .... click-and-move to rotate",
"- .... use mouse wheel for zooming",
"- .... double click for reset position",
"- Execute box(1,8) to divide a box in 8 equal slices along X",
"- Most shapes can be divided on X,Y,Z,Rxy or Phi :",
"- .... root[0] <shape>(IAXIS, NDIV, START, STEP);",
" .... IAXIS = 1,2,3 meaning (X,Y,Z) or (Rxy, Phi, Z)",
" .... NDIV = number of slices",
" .... START = start slicing position",
" .... STEP = division step",
"- Click Comments ON/OFF to toggle comments",
"- Click Ideal/Align geometry to see how alignment works"
});
helpWindow->SetDefaultPage("file:webhelp.html");
unsigned connid = helpWindow->GetDisplayConnection();
if (!info.empty()) {
lines = info;
if (finder) {
lines.emplace_back(AddInt(
"fNdiv",finder->
GetNdiv(),
"number of divisions"));
lines.emplace_back(AddDbl(
"fStart",finder->
GetStart(),
"start divisioning position"));
lines.emplace_back(AddDbl(
"fStep",finder->
GetStep(),
"division step"));
}
if (!info2.empty())
lines.insert(lines.end(), info2.begin(), info2.end());
}
int height = 200;
if (lines.size() > 10) height = 50 + lines.size()*20;
if (!connid) connid = helpWindow->Show({600, height, 160, 650});
std::string msg = "";
for (
auto &
line : lines) {
if (
line.empty())
continue;
std::string
style =
"", p =
"<p style='";
else if (
line.find(
"----")==0) {
style =
"color:red"; }
else if (
line.find(
"Execute")==0) {
style =
"color:blue"; }
else if (
line.find(
"Division")==0) {
style =
"font-size:120%;color:green"; }
if (
style.empty()) p =
"<p>";
else { p.append(
style); p.append(
"'>"); }
p.append("</p>");
msg.append(p);
}
if (msg.empty())
helpWindow->Send(connid, "Initial text");
else
helpWindow->Send(connid, msg);
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({"TGeoBBox - box class",
AddDbl(
"fDX",bbox->
GetDX(),
"half length in X"),
AddDbl(
"fDY",bbox->
GetDY(),
"half length in Y"),
AddDbl(
"fDZ",bbox->
GetDZ(),
"half length in Z"),
AddDbl(
"fOrigin[0]",(bbox->
GetOrigin())[0],
"box origin on X"),
AddDbl(
"fOrigin[1]",(bbox->
GetOrigin())[1],
"box origin on Y"),
AddDbl(
"fOrigin[2]",(bbox->
GetOrigin())[2],
"box origin on Z")},
vol, iaxis,
{"Execute: box(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 1, 2 or 3 (X, Y, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({"TGeoPara - parallelepiped class",
AddDbl(
"fX", para->
GetX(),
"half length in X"),
AddDbl(
"fY", para->
GetY(),
"half length in Y"),
AddDbl(
"fZ", para->
GetZ(),
"half length in Z"),
AddDbl(
"fAlpha", para->
GetAlpha(),
"angle about Y of the Z bases"),
AddDbl(
"fTheta", para->
GetTheta(),
"inclination of para axis about Z"),
AddDbl(
"fPhi", para->
GetPhi(),
"phi angle of para axis")},
vol, iaxis,
{"Execute: para(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 1, 2 or 3 (X, Y, Z)", "----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({"TGeoTube - tube class",
AddDbl(
"fRmin",tube->
GetRmin(),
"minimum radius"),
AddDbl(
"fRmax",tube->
GetRmax(),
"maximum radius"),
AddDbl(
"fDZ", tube->
GetDZ(),
"half length in Z")},
vol, iaxis,
{"Execute: tube(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 1, 2 or 3 (Rxy, Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoTubeSeg - tube segment class",
AddDbl(
"fRmin",tubeseg->
GetRmin(),
"minimum radius"),
AddDbl(
"fRmax",tubeseg->
GetRmax(),
"maximum radius"),
AddDbl(
"fDZ", tubeseg->
GetDZ(),
"half length in Z"),
AddDbl(
"fPhi1",tubeseg->
GetPhi1(),
"first phi limit"),
AddDbl(
"fPhi2",tubeseg->
GetPhi2(),
"second phi limit")},
vol, iaxis,
{"Execute: tubeseg(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 1, 2 or 3 (Rxy, Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis<0 || iaxis>2) {
printf("Wrong division axis. Range is 1-2.\n");
return;
}
TGeoVolume *vol =
gGeoManager->
MakeCtub(
"CTUB",med, 20,30,40,-30,250, nlow[0], nlow[1], nlow[2], nhi[0],nhi[1],nhi[2]);
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoTubeSeg - tube segment class",
AddDbl(
"fRmin",tubeseg->
GetRmin(),
"minimum radius"),
AddDbl(
"fRmax",tubeseg->
GetRmax(),
"maximum radius"),
AddDbl(
"fDZ", tubeseg->
GetDZ(),
"half length in Z"),
AddDbl(
"fPhi1",tubeseg->
GetPhi1(),
"first phi limit"),
AddDbl(
"fPhi2",tubeseg->
GetPhi2(),
"second phi limit")},
vol, iaxis);
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
} else if (iaxis==1) {
printf("cannot divide cone on Rxy\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoCone - cone class",
AddDbl(
"fDZ", cone->
GetDZ(),
"half length in Z"),
AddDbl(
"fRmin1",cone->
GetRmin1(),
"inner radius at -dz"),
AddDbl(
"fRmax1",cone->
GetRmax1(),
"outer radius at -dz"),
AddDbl(
"fRmin2",cone->
GetRmin2(),
"inner radius at +dz"),
AddDbl(
"fRmax2",cone->
GetRmax2(),
"outer radius at +dz")},
vol, iaxis,
{"Execute: cone(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 2 or 3 (Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoConeSeg - coneseg class",
AddDbl(
"fDZ", coneseg->
GetDZ(),
"half length in Z"),
AddDbl(
"fRmin1",coneseg->
GetRmin1(),
"inner radius at -dz"),
AddDbl(
"fRmax1",coneseg->
GetRmax1(),
"outer radius at -dz"),
AddDbl(
"fRmin2",coneseg->
GetRmin1(),
"inner radius at +dz"),
AddDbl(
"fRmax2",coneseg->
GetRmax1(),
"outer radius at +dz"),
AddDbl(
"fPhi1",coneseg->
GetPhi1(),
"first phi limit"),
AddDbl(
"fPhi2",coneseg->
GetPhi2(),
"second phi limit")},
vol, iaxis,
{"Execute: coneseg(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 2 or 3 (Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoEltu - eltu class",
AddDbl(
"fA",eltu->
GetA(),
"semi-axis along x"),
AddDbl(
"fB",eltu->
GetB(),
"semi-axis along y"),
AddDbl(
"fDZ", eltu->
GetDZ(),
"half length in Z")},
vol, iaxis,
{"Execute: eltu(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 2 or 3 (Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis!=0) {
printf("Cannot divide spheres\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoSphere- sphere class",
AddDbl(
"fRmin",sphere->
GetRmin(),
"inner radius"),
AddDbl(
"fRmax",sphere->
GetRmax(),
"outer radius"),
AddDbl(
"fTheta1",sphere->
GetTheta1(),
"lower theta limit"),
AddDbl(
"fTheta2",sphere->
GetTheta2(),
"higher theta limit"),
AddDbl(
"fPhi1",sphere->
GetPhi1(),
"lower phi limit"),
AddDbl(
"fPhi2",sphere->
GetPhi2(),
"higher phi limit")},
vol, iaxis);
}
{
if (iaxis!=0) {
printf("Cannot divide a torus\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoTorus - torus class",
AddDbl(
"fR",tor->
GetR(),
"radius of the ring"),
AddDbl(
"fRmin",tor->
GetRmin(),
"minimum radius"),
AddDbl(
"fRmax",tor->
GetRmax(),
"maximum radius"),
AddDbl(
"fPhi1", tor->
GetPhi1(),
"starting phi angle"),
AddDbl(
"fDphi", tor->
GetDphi(),
"phi range")},
vol, iaxis);
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
} else if (iaxis==1) {
printf("Cannot divide trd1 on X axis\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoTrd1 - Trd1 class",
AddDbl(
"fDx1",trd1->
GetDx1(),
"half length in X at lower Z surface(-dz)"),
AddDbl(
"fDx2",trd1->
GetDx2(),
"half length in X at higher Z surface(+dz)"),
AddDbl(
"fDy",trd1->
GetDy(),
"half length in Y"),
AddDbl(
"fDz",trd1->
GetDz(),
"half length in Z")},
vol, iaxis,
{"Execute: trd1(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 2 or 3 (Y, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
void parab()
{
display();
help({ "TGeoParaboloid - Paraboloid class",
AddDbl(
"fRlo",par->
GetRlo(),
"radius at Z=-dz"),
AddDbl(
"fRhi",par->
GetRhi(),
"radius at Z=+dz"),
AddDbl(
"fDz",par->
GetDz(),
"half-length on Z axis"),
"----- A paraboloid is described by the equation:",
"----- z = a*r*r + b; where: r = x*x + y*y",
"----- Create with: TGeoParaboloid *parab = new TGeoParaboloid(rlo, rhi, dz);",
"----- dz: half-length in Z (range from -dz to +dz",
"----- rlo: radius at z=-dz given by: -dz = a*rlo*rlo + b",
"----- rhi: radius at z=+dz given by: dz = a*rhi*rhi + b",
"----- rlo != rhi; both >= 0"});
}
void hype()
{
display();
help({ "TGeoHype - Hyperboloid class",
AddDbl(
"fRmin",hype->
GetRmin(),
"minimum inner radius"),
AddDbl(
"fStIn",hype->
GetStIn(),
"inner surface stereo angle [deg]"),
AddDbl(
"fRmax",hype->
GetRmax(),
"minimum outer radius"),
AddDbl(
"fStOut",hype->
GetStOut(),
"outer surface stereo angle [deg]"),
AddDbl(
"fDz",hype->
GetDz(),
"half-length on Z axis"),
"----- A hyperboloid is described by the equation:",
"----- r^2 - (tan(stereo)*z)^2 = rmin^2; where: r = x*x + y*y",
"----- Create with: TGeoHype *hype = new TGeoHype(rin, stin, rout, stout, dz);",
"----- rin < rout; rout > 0",
"----- rin = 0; stin > 0 => inner surface conical",
"----- stin/stout = 0 => corresponding surface cylindrical"});
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
} else if (iaxis==1) {
printf("Cannot divide pcon on Rxy\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
std::vector<std::string> lines = { "TGeoPcon - pcon class",
AddDbl(
"fPhi1",pcon->
GetPhi1(),
"lower phi limit"),
AddDbl(
"fDphi",pcon->
GetDphi(),
"phi range"),
AddDbl(
"fNz",pcon->
GetNz(),
"number of z planes")};
lines.emplace_back(
Form(
"fZ[%i]=%5.2f fRmin[%i]=%5.2f fRmax[%i]=%5.2f",
help(lines, vol, iaxis,
{"Execute: pcon(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 2 or 3 (Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis<0 || iaxis>3) {
printf("Wrong division axis. Range is 1-3.\n");
return;
} else if (iaxis==1) {
printf("Cannot divide pgon on Rxy\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
std::vector<std::string> lines({ "TGeoPgon - pgon class",
AddDbl(
"fPhi1",pgon->
GetPhi1(),
"lower phi limit"),
AddDbl(
"fDphi",pgon->
GetDphi(),
"phi range"),
AddDbl(
"fNedges",pgon->
GetNedges(),
"number of edges"),
AddDbl(
"fNz",pgon->
GetNz(),
"number of z planes")});
lines.emplace_back(
Form(
"fZ[%i]=%5.2f fRmin[%i]=%5.2f fRmax[%i]=%5.2f",
help(lines, vol, iaxis,
{"Execute: pgon(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be 2 or 3 (Phi, Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis!=0) {
printf("Cannot divide arb8\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
std::vector<std::string> lines({"TGeoArb8 - arb8 class",
AddDbl(
"fDz",arb->
GetDz(),
"Z half length"),
"Vertices on lower Z plane:"});
for (
Int_t i=0; i<8; i++) {
if (i==4) lines.emplace_back("Vertices on higher Z plane:");
lines.emplace_back(
Form(
" fXY[%d] = (%5.2f, %5.2f)", i, vert[2*i], vert[2*i+1]));
}
help(lines, vol, iaxis);
}
{
if (iaxis && iaxis!=3) {
printf("Wrong division axis. trd2 can divide only in Z (3)\n");
return;
}
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoTrd2 - Trd2 class",
AddDbl(
"fDx1",trd2->
GetDx1(),
"half length in X at lower Z surface(-dz)"),
AddDbl(
"fDx2",trd2->
GetDx2(),
"half length in X at higher Z surface(+dz)"),
AddDbl(
"fDy1",trd2->
GetDy1(),
"half length in Y at lower Z surface(-dz)"),
AddDbl(
"fDy2",trd2->
GetDy2(),
"half length in Y at higher Z surface(-dz)"),
AddDbl(
"fDz",trd2->
GetDz(),
"half length in Z")},
vol, iaxis,
{"Execute: trd2(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be only 3 (Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis && iaxis!=3) {
printf("Wrong division axis. Can divide only in Z (3)\n");
return;
}
TGeoVolume *vol =
gGeoManager->
MakeTrap(
"Trap",med, 30,15,30,20,10,15,0,20,10,15,0);
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoTrap - Trapezoid class",
AddDbl(
"fDz",trap->
GetDz(),
"half length in Z"),
AddDbl(
"fTheta",trap->
GetTheta(),
"theta angle of trapezoid axis"),
AddDbl(
"fPhi",trap->
GetPhi(),
"phi angle of trapezoid axis"),
AddDbl(
"fH1",trap->
GetH1(),
"half length in y at -fDz"),
AddDbl(
"fAlpha1",trap->
GetAlpha1(),
"angle between centers of x edges and y axis at -fDz"),
AddDbl(
"fBl1",trap->
GetBl1(),
"half length in x at -dZ and y=-fH1"),
AddDbl(
"fTl1",trap->
GetTl1(),
"half length in x at -dZ and y=+fH1"),
AddDbl(
"fH2",trap->
GetH2(),
"half length in y at +fDz"),
AddDbl(
"fBl2",trap->
GetBl2(),
"half length in x at +dZ and y=-fH1"),
AddDbl(
"fTl2",trap->
GetTl2(),
"half length in x at +dZ and y=+fH1"),
AddDbl(
"fAlpha2",trap->
GetAlpha2(),
"angle between centers of x edges and y axis at +fDz")},
vol, iaxis,
{"Execute: trap(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be only 3 (Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
{
if (iaxis && iaxis!=3) {
printf("Wrong division axis. Can divide only in Z (3)\n");
return;
}
TGeoVolume *vol =
gGeoManager->
MakeGtra(
"Gtra",med, 30,15,30,30,20,10,15,0,20,10,15,0);
if (iaxis) {
if (!slice) return;
}
display();
help({ "TGeoGtra - Twisted trapezoid class",
AddDbl(
"fDz",trap->
GetDz(),
"half length in Z"),
AddDbl(
"fTheta",trap->
GetTheta(),
"theta angle of trapezoid axis"),
AddDbl(
"fPhi",trap->
GetPhi(),
"phi angle of trapezoid axis"),
AddDbl(
"fH1",trap->
GetH1(),
"half length in y at -fDz"),
AddDbl(
"fAlpha1",trap->
GetAlpha1(),
"angle between centers of x edges and y axis at -fDz"),
AddDbl(
"fBl1",trap->
GetBl1(),
"half length in x at -dZ and y=-fH1"),
AddDbl(
"fTl1",trap->
GetTl1(),
"half length in x at -dZ and y=+fH1"),
AddDbl(
"fH2",trap->
GetH2(),
"half length in y at +fDz"),
AddDbl(
"fBl2",trap->
GetBl2(),
"half length in x at +dZ and y=-fH1"),
AddDbl(
"fTl2",trap->
GetTl2(),
"half length in x at +dZ and y=+fH1"),
AddDbl(
"fAlpha2",trap->
GetAlpha2(),
"angle between centers of x edges and y axis at +fDz")},
vol, iaxis,
{"Execute: gtra(iaxis, ndiv, start, step) to divide this.",
"----- IAXIS can be only 3 (Z)",
"----- NDIV must be a positive integer",
"----- START must be a valid axis offset within shape range on divided axis",
"----- STEP is the division step. START+NDIV*STEP must be in range also",
"----- If START and STEP are omitted, all range of the axis will be divided"});
}
void xtru()
{
Double_t x[8] = {-30,-30,30,30,15,15,-15,-15};
Double_t y[8] = {-30,30,30,-30,-30,15,15,-30};
display();
help({ "TGeoXtru - Polygonal extrusion class",
AddDbl(
"fNvert",xtru->
GetNvert(),
"number of polygone vertices"),
AddDbl(
"fNz",xtru->
GetNz(),
"number of Z sections"),
"----- Any Z section is an arbitrary polygone",
"----- The shape can have an arbitrary number of Z sections, as for pcon/pgon",
"----- Create with: TGeoXtru *xtru = new TGeoXtru(nz);",
"----- Define the blueprint polygon :",
"----- Double_t x[8] = {-30,-30,30,30,15,15,-15,-15};",
"----- Double_t y[8] = {-30,30,30,-30,-30,15,15,-30};",
"----- xtru->DefinePolygon(8,x,y);",
"----- Define translations/scales of the blueprint for Z sections :",
"----- xtru->DefineSection(i, Zsection, x0, y0, scale);",
"----- Sections have to be defined in increasing Z order",
"----- 2 sections can be defined at same Z (not for first/last sections)"});
}
void tessellated()
{
std::vector<Tessellated::Vertex_t> vert;
vert.reserve(120);
vert.emplace_back(0, 0.5 * (1 + sqrt5), -1); vert.emplace_back(0, 0.5 * (-1 + sqrt5), 0.5 * (-1 - sqrt5)); vert.emplace_back(-1, 0, 0.5 * (-1 - sqrt5)); vert.emplace_back(-1, 1, -1);
vert.emplace_back(1, 1, -1); vert.emplace_back(0, 0.5 * (1 + sqrt5), -1); vert.emplace_back(0, 0.5 * (-1 + sqrt5), 0.5 * (-1 - sqrt5)); vert.emplace_back(1, 0, 0.5 * (-1 - sqrt5));
vert.emplace_back(1, 1, -1); vert.emplace_back(0, 0.5 * (1 + sqrt5), -1); vert.emplace_back(0.5 * (-1 + sqrt5), 0.5 * (1 + sqrt5), 0); vert.emplace_back(0.5 * (1 + sqrt5), 1, 0);
vert.emplace_back(0.5 * (1 - sqrt5), 0.5 * (1 + sqrt5), 0); vert.emplace_back(0, 0.5 * (1 + sqrt5), -1); vert.emplace_back(0.5 * (-1 + sqrt5), 0.5 * (1 + sqrt5), 0); vert.emplace_back(0, 0.5 * (1 + sqrt5), 1);
vert.emplace_back(0.5 * (1 - sqrt5), 0.5 * (1 + sqrt5), 0); vert.emplace_back(0, 0.5 * (1 + sqrt5), -1); vert.emplace_back(-1, 1, -1); vert.emplace_back(0.5 * (-1 - sqrt5), 1, 0);
vert.emplace_back(1, 1, -1); vert.emplace_back(0.5 * (1 + sqrt5), 1, 0); vert.emplace_back(0.5 * (1 + sqrt5), 0, 0.5 * (1 - sqrt5)); vert.emplace_back(1, 0, 0.5 * (-1 - sqrt5));
vert.emplace_back(0.5 * (1 + sqrt5), 0, 0.5 * (1 - sqrt5)); vert.emplace_back(0.5 * (1 + sqrt5), -1, 0); vert.emplace_back(1, -1, -1); vert.emplace_back(1, 0, 0.5 * (-1 - sqrt5));
vert.emplace_back(1, -1, -1); vert.emplace_back(0, 0.5 * (-1 - sqrt5), -1); vert.emplace_back(0, 0.5 * (1 - sqrt5), 0.5 * (-1 - sqrt5)); vert.emplace_back(1, 0, 0.5 * (-1 - sqrt5));
vert.emplace_back(1, 0, 0.5 * (-1 - sqrt5)); vert.emplace_back(0, 0.5 * (-1 + sqrt5), 0.5 * (-1 - sqrt5)); vert.emplace_back(-1, 0, 0.5 * (-1 - sqrt5)); vert.emplace_back(0, 0.5 * (1 - sqrt5), 0.5 * (-1 - sqrt5));
vert.emplace_back(0.5 * (-1 + sqrt5), 0.5 * (1 + sqrt5), 0); vert.emplace_back(0.5 * (1 + sqrt5), 1, 0); vert.emplace_back(1, 1, 1); vert.emplace_back(0, 0.5 * (1 + sqrt5), 1);
vert.emplace_back(0.5 * (1 + sqrt5), 1, 0); vert.emplace_back(1, 1, 1); vert.emplace_back(1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(0.5 * (1 + sqrt5), 0, 0.5 * (-1 + sqrt5));
vert.emplace_back(0.5 * (1 + sqrt5), 0, 0.5 * (1 - sqrt5)); vert.emplace_back(0.5 * (1 + sqrt5), 1, 0); vert.emplace_back(0.5 * (1 + sqrt5), 0, 0.5 * (-1 + sqrt5)); vert.emplace_back(0.5 * (1 + sqrt5), -1, 0);
vert.emplace_back(0.5 * (1 - sqrt5), 0.5 * (1 + sqrt5), 0); vert.emplace_back(0, 0.5 * (1 + sqrt5), 1); vert.emplace_back(-1, 1, 1); vert.emplace_back(0.5 * (-1 - sqrt5), 1, 0);
vert.emplace_back(0, 0.5 * (1 + sqrt5), 1); vert.emplace_back(0, 0.5 * (-1 + sqrt5), 0.5 * (1 + sqrt5)); vert.emplace_back(-1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(-1, 1, 1);
vert.emplace_back(1, 1, 1); vert.emplace_back(0, 0.5 * (1 + sqrt5), 1); vert.emplace_back(0, 0.5 * (-1 + sqrt5), 0.5 * (1 + sqrt5)); vert.emplace_back(1, 0, 0.5 * (1 + sqrt5));
vert.emplace_back(0, 0.5 * (1 - sqrt5), 0.5 * (1 + sqrt5)); vert.emplace_back(-1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(0, 0.5 * (-1 + sqrt5), 0.5 * (1 + sqrt5)); vert.emplace_back(1, 0, 0.5 * (1 + sqrt5));
vert.emplace_back(0, 0.5 * (1 - sqrt5), 0.5 * (1 + sqrt5)); vert.emplace_back(1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(1, -1, 1); vert.emplace_back(0, 0.5 * (-1 - sqrt5), 1);
vert.emplace_back(0.5 * (1 + sqrt5), 0, 0.5 * (-1 + sqrt5)); vert.emplace_back(0.5 * (1 + sqrt5), -1, 0); vert.emplace_back(1, -1, 1); vert.emplace_back(1, 0, 0.5 * (1 + sqrt5));
vert.emplace_back(-1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(-1, 1, 1); vert.emplace_back(0.5 * (-1 - sqrt5), 1, 0); vert.emplace_back(0.5 * (-1 - sqrt5), 0, 0.5 * (-1 + sqrt5));
vert.emplace_back(-1, -1, 1); vert.emplace_back(-1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(0.5 * (-1 - sqrt5), 0, 0.5 * (-1 + sqrt5)); vert.emplace_back(0.5 * (-1 - sqrt5), -1, 0);
vert.emplace_back(0, 0.5 * (1 - sqrt5), 0.5 * (1 + sqrt5)); vert.emplace_back(-1, 0, 0.5 * (1 + sqrt5)); vert.emplace_back(-1, -1, 1); vert.emplace_back(0, 0.5 * (-1 - sqrt5), 1);
vert.emplace_back(0.5 * (-1 - sqrt5), -1, 0); vert.emplace_back(0.5 * (-1 - sqrt5), 0, 0.5 * (1 - sqrt5)); vert.emplace_back(0.5 * (-1 - sqrt5), 1, 0); vert.emplace_back(0.5 * (-1 - sqrt5), 0, 0.5 * (-1 + sqrt5));
vert.emplace_back(0.5 * (-1 - sqrt5), -1, 0); vert.emplace_back(0.5 * (-1 - sqrt5), 0, 0.5 * (1 - sqrt5)); vert.emplace_back(-1, 0, 0.5 * (-1 - sqrt5)); vert.emplace_back(-1, -1, -1);
vert.emplace_back(0, 0.5 * (-1 - sqrt5), -1); vert.emplace_back(0.5 * (1 - sqrt5), 0.5 * (-1 - sqrt5), 0); vert.emplace_back(0.5 * (-1 - sqrt5), -1, 0); vert.emplace_back(-1, -1, -1);
vert.emplace_back(0.5 * (1 - sqrt5), 0.5 * (-1 - sqrt5), 0); vert.emplace_back(0.5 * (-1 - sqrt5), -1, 0); vert.emplace_back(-1, -1, 1); vert.emplace_back(0, 0.5 * (-1 - sqrt5), 1);
vert.emplace_back(-1, 1, -1); vert.emplace_back(-1, 0, 0.5 * (-1 - sqrt5)); vert.emplace_back(0.5 * (-1 - sqrt5), 0, 0.5 * (1 - sqrt5)); vert.emplace_back(0.5 * (-1 - sqrt5), 1, 0);
vert.emplace_back(0, 0.5 * (-1 - sqrt5), -1); vert.emplace_back(0, 0.5 * (1 - sqrt5), 0.5 * (-1 - sqrt5)); vert.emplace_back(-1, 0, 0.5 * (-1 - sqrt5)); vert.emplace_back(-1, -1, -1);
vert.emplace_back(0, 0.5 * (-1 - sqrt5), -1); vert.emplace_back(0.5 * (1 - sqrt5), 0.5 * (-1 - sqrt5), 0); vert.emplace_back(0, 0.5 * (-1 - sqrt5), 1); vert.emplace_back(0.5 * (-1 + sqrt5), 0.5 * (-1 - sqrt5), 0);
vert.emplace_back(1, -1, -1); vert.emplace_back(0.5 * (1 + sqrt5), -1, 0); vert.emplace_back(0.5 * (-1 + sqrt5), 0.5 * (-1 - sqrt5), 0); vert.emplace_back(0, 0.5 * (-1 - sqrt5), -1);
vert.emplace_back(0.5 * (1 + sqrt5), -1, 0); vert.emplace_back(1, -1, 1); vert.emplace_back(0, 0.5 * (-1 - sqrt5), 1); vert.emplace_back(0.5 * (-1 + sqrt5), 0.5 * (-1 - sqrt5), 0);
tsl->
AddFacet(vert[0], vert[1], vert[2], vert[3]);
tsl->
AddFacet(vert[4], vert[7], vert[6], vert[5]);
tsl->
AddFacet(vert[8], vert[9], vert[10], vert[11]);
tsl->
AddFacet(vert[12], vert[15], vert[14], vert[13]);
tsl->
AddFacet(vert[16], vert[17], vert[18], vert[19]);
tsl->
AddFacet(vert[20], vert[21], vert[22], vert[23]);
tsl->
AddFacet(vert[24], vert[25], vert[26], vert[27]);
tsl->
AddFacet(vert[28], vert[29], vert[30], vert[31]);
tsl->
AddFacet(vert[32], vert[35], vert[34], vert[33]);
tsl->
AddFacet(vert[36], vert[39], vert[38], vert[37]);
tsl->
AddFacet(vert[40], vert[41], vert[42], vert[43]);
tsl->
AddFacet(vert[44], vert[45], vert[46], vert[47]);
tsl->
AddFacet(vert[48], vert[51], vert[50], vert[49]);
tsl->
AddFacet(vert[52], vert[55], vert[54], vert[53]);
tsl->
AddFacet(vert[56], vert[57], vert[58], vert[59]);
tsl->
AddFacet(vert[60], vert[63], vert[62], vert[61]);
tsl->
AddFacet(vert[64], vert[67], vert[66], vert[65]);
tsl->
AddFacet(vert[68], vert[71], vert[70], vert[69]);
tsl->
AddFacet(vert[72], vert[73], vert[74], vert[75]);
tsl->
AddFacet(vert[76], vert[77], vert[78], vert[79]);
tsl->
AddFacet(vert[80], vert[81], vert[82], vert[83]);
tsl->
AddFacet(vert[84], vert[87], vert[86], vert[85]);
tsl->
AddFacet(vert[88], vert[89], vert[90], vert[91]);
tsl->
AddFacet(vert[92], vert[93], vert[94], vert[95]);
tsl->
AddFacet(vert[96], vert[99], vert[98], vert[97]);
tsl->
AddFacet(vert[100], vert[101], vert[102], vert[103]);
tsl->
AddFacet(vert[104], vert[107], vert[106], vert[105]);
tsl->
AddFacet(vert[108], vert[111], vert[110], vert[109]);
tsl->
AddFacet(vert[112], vert[113], vert[114], vert[115]);
tsl->
AddFacet(vert[116], vert[117], vert[118], vert[119]);
display();
help( {"TGeoTessellated - Tessellated shape class",
AddInt(
"fNfacets",tsl->
GetNfacets(),
"number of facets"),
AddInt(
"fNvertices",tsl->
GetNvertices(),
"number of vertices"),
"----- A tessellated shape is defined by the number of facets",
"----- facets can be added using AddFacet",
"----- Create with: TGeoTessellated *tsl = new TGeoTessellated(nfacets);"});
}
void composite()
{
display();
help({ "TGeoCompositeShape - composite shape class",
"----- Define the shape components and don't forget to name them",
"----- Define geometrical transformations that apply to shape components",
"----- Name all transformations and register them",
"----- Define the composite shape based on a Boolean expression",
" TGeoCompositeShape(\"someName\", \"expression\")",
"----- Expression is made of <shapeName:transfName> components related by Boolean operators",
"----- Boolean operators can be: (+) union, (-) subtraction and (*) intersection",
"----- Use parenthesis in the expression to force precedence"});
}
void ideal()
{
display();
help({ "Ideal / Aligned geometry",
"-- Create physical nodes for the objects you want to align",
"-- You must start from a valid CLOSED geometry",
" TGeoPhysicalNode *node = gGeoManager->MakePhysicalNode(const char *path)",
" + creates a physical node represented by path, e.g. TOP_1/A_2/B_3",
" node->Align(TGeoMatrix *newmat, TGeoShape *newshape, Bool_t check=kFALSE)",
" + newmat = new matrix to replace final node LOCAL matrix",
" + newshape = new shape to replace final node shape",
" + check = optional check if the new aligned node is overlapping"});
}
void align()
{
printf("Click: <Ideal geometry> first\n");
return;
}
for (
Int_t i=1; i<=10; i++) {
for (
Int_t j=1; j<=10; j++) {
node = 0;
sprintf(
name,
"TOP_1/SX_%d/SY_%d/CELL_1",i,j);
} else {
}
}
}
display();
}
void quit()
{
mainWindow->TerminateROOT();
}
void webdemo ()
{
mainWindow->SetDefaultPage("file:webdemo.html");
mainWindow->SetDataCallBack([](unsigned connid, const std::string &arg) {
gROOT->ProcessLine(arg.c_str());
});
mainWindow->Show({150,750, 0,0});
geomViewer->SetDrawOptions(getOptions());
}