22 std::cerr <<
m_className <<
"::SetComponent: Null pointer.\n";
31 std::cerr <<
m_className <<
"::SetComponent: Null pointer.\n";
38 const double xmax,
const double ymax,
41 if (xmin == xmax || ymin == ymax || zmin == zmax) {
42 std::cerr <<
m_className <<
"::SetArea: Null area range not permitted.\n";
45 m_xMin = std::min(xmin, xmax);
46 m_yMin = std::min(ymin, ymax);
47 m_zMin = std::min(zmin, zmax);
48 m_xMax = std::max(xmin, xmax);
49 m_yMax = std::max(ymin, ymax);
50 m_zMax = std::max(zmin, zmax);
56 std::cerr <<
m_className <<
"::Plot2d: Error creating plot.\n";
62 std::cerr <<
m_className <<
"::Plot3d: Error creating plot.\n";
66bool ViewCell::Plot(
const bool use3d) {
67 if (!m_component && !m_nebem) {
68 std::cerr <<
m_className <<
"::Plot: Component is not defined.\n";
72 double pmin = 0., pmax = 0.;
75 std::cerr <<
m_className <<
"::Plot: Component is not ready.\n";
80 std::cerr <<
m_className <<
"::Plot: Component is not ready.\n";
86 double x0 = m_xMin, y0 = m_yMin, z0 = m_zMin;
87 double x1 = m_xMax, y1 = m_yMax, z1 = m_zMax;
92 <<
" Bounding box cannot be determined.\n"
93 <<
" Call SetArea first.\n";
99 <<
" Bounding box cannot be determined.\n"
100 <<
" Call SetArea first.\n";
106 const double dx = std::max(
fabs(x0),
fabs(x1));
107 const double dy = std::max(
fabs(y0),
fabs(y1));
108 const double dz = std::max(
fabs(z0),
fabs(z1));
112 if (!use3d)
m_canvas->SetTitle(m_label.c_str());
120 (gPad->GetListOfPrimitives()->GetSize() == 0 && gPad->GetX1() == 0 &&
121 gPad->GetX2() == 1 && gPad->GetY1() == 0 && gPad->GetY2() == 1)) {
124 const double bm =
m_canvas->GetBottomMargin();
125 const double lm =
m_canvas->GetLeftMargin();
126 const double rm =
m_canvas->GetRightMargin();
127 const double tm =
m_canvas->GetTopMargin();
129 TPad* pad =
new TPad(
"cell",
"", 0, 0, 1, 1);
130 pad->SetFillStyle(0);
131 pad->SetFrameFillStyle(0);
135 gPad->Range(x0 - (x1 - x0) * (lm / (1. - rm - lm)),
136 y0 - (y1 - y0) * (bm / (1. - tm - lm)),
137 x1 + (x1 - x0) * (rm / (1. - rm - lm)),
138 y1 + (y1 - y0) * (tm / (1. - tm - lm)));
141 if (m_nebem)
return PlotNeBem(use3d);
144 const std::string cellType = m_component->
GetCellType();
147 double sx = 0., sy = 0.;
151 const int nMinX = perX ? int(x0 / sx) - 1 : 0;
152 const int nMaxX = perX ? int(x1 / sx) + 1 : 0;
153 const int nMinY = perY ? int(y0 / sy) - 1 : 0;
154 const int nMaxY = perY ? int(y1 / sy) + 1 : 0;
158 const int nPhi = perPhi ? int(360. / sphi) : 0;
160 if (use3d) SetupGeo(dx, dy, dz);
161 const bool polar = m_component->
IsPolar();
165 std::vector<std::string> wireTypes;
167 for (
unsigned int i = 0; i < nWires; ++i) {
168 double xw = 0., yw = 0., dw = 0., vw = 0., lw = 0., qw = 0.;
172 m_component->
GetWire(i, xw, yw, dw, vw, lbl, lw, qw, nTrap);
174 if (wireTypes.empty()) {
175 wireTypes.push_back(lbl);
178 const unsigned int nWireTypes = wireTypes.size();
179 for (
unsigned int j = 0; j < nWireTypes; ++j) {
180 if (lbl == wireTypes[j]) {
186 type = wireTypes.size();
187 wireTypes.push_back(lbl);
192 for (
int j = 0; j <= nPhi; ++j) {
193 const double phi = yw * Garfield::DegreeToRad + j * sphi;
194 const double x = r *
cos(phi);
195 const double y = r *
sin(phi);
197 PlotWire(x, y, dw, type, std::min(0.5 * lw, dz));
199 PlotWire(x, y, dw, type);
204 for (
int nx = nMinX; nx <= nMaxX; ++nx) {
205 const double x = xw + nx * sx;
206 if (x + 0.5 * dw <= x0 || x - 0.5 * dw >= x1)
continue;
207 for (
int ny = nMinY; ny <= nMaxY; ++ny) {
208 const double y = yw + ny * sy;
209 if (y + 0.5 * dw <= y0 || y - 0.5 * dw >= y1)
continue;
211 PlotWire(x, y, dw, type, std::min(0.5 * lw, dz));
213 PlotWire(x, y, dw, type);
221 for (
unsigned int i = 0; i < nPlanesX; ++i) {
222 double xp = 0., vp = 0.;
225 for (
int nx = nMinX; nx <= nMaxX; ++nx) {
226 const double x = xp + nx * sx;
227 if (x < x0 || x > x1)
continue;
229 const double width = std::min(0.01 * dx, 0.01 * dy);
230 PlotPlane(width, dy, dz, x, 0);
232 PlotPlane(x, y0, x, y1);
239 for (
unsigned int i = 0; i < nPlanesY; ++i) {
240 double yp = 0., vp = 0.;
243 for (
int ny = nMinY; ny <= nMaxY; ++ny) {
244 const double y = yp + ny * sy;
245 if (y < y0 || y > y1)
continue;
247 const double width = std::min(0.01 * dx, 0.01 * dy);
248 PlotPlane(dx, width, dz, 0, y);
250 PlotPlane(x0, y, x1, y);
258 if (nPlanesR > 0 || nPlanesPhi > 0) {
261 std::array<double, 2>
phi = {0., 360.};
267 double w = 0.01 * std::min(dx, dy);
268 std::array<double, 2> r = {0., 0.};
270 m_component->
GetPlaneR(0, r[0], vp, lbl);
274 m_component->
GetPlaneR(1, r[1], vp, lbl);
275 w = 0.01 * (r[1] - r[0]);
277 for (
unsigned int i = 0; i < nPlanesR; ++i) {
279 const auto med = m_geo->GetMedium(
"Metal");
280 const auto tubs = m_geo->MakeTubs(
"Plane", med, r[i] - w, r[i] + w,
282 tubs->SetLineColor(kGreen - 5);
283 tubs->SetTransparency(75);
284 m_geo->GetTopVolume()->AddNode(tubs, 1);
287 circle.SetDrawOption(
"same");
288 circle.SetFillStyle(0);
290 circle.DrawEllipse(0, 0, r[i], r[i], phi[0], phi[1], 0);
294 std::swap(r[0], r[1]);
295 }
else if (nPlanesR == 0) {
296 r[1] = std::max(dx, dy);
298 for (
unsigned int i = 0; i < nPlanesPhi; ++i) {
299 const double cp =
cos(phi[i] * DegreeToRad);
300 const double sp =
sin(phi[i] * DegreeToRad);
302 const auto med = m_geo->GetMedium(
"Metal");
303 const double dr = 0.5 * (r[1] - r[0]);
304 TGeoVolume* plane = m_geo->MakeBox(
"Plane", med, dr, w, dz);
305 plane->SetLineColor(kGreen - 5);
306 plane->SetTransparency(75);
307 TGeoRotation* rot =
new TGeoRotation(
"", phi[i], 0, 0);
308 const double rm = 0.5 * (r[0] + r[1]);
309 TGeoCombiTrans* tr =
new TGeoCombiTrans(cp * rm, sp * rm, 0, rot);
310 m_geo->GetTopVolume()->AddNode(plane, 1, tr);
312 PlotPlane(r[0] * cp, r[0] * sp, r[1] * cp, r[1] * sp);
316 double rt = 0., vt = 0.;
319 if (m_component->
GetTube(rt, vt, nt, lbl)) {
321 PlotTube(0.98 * rt, 1.02 * rt, nt, dz);
323 PlotTube(0., 0., rt, nt);
328 m_geo->CloseGeometry();
329 m_geo->GetTopNode()->Draw(
"ogl");
337bool ViewCell::PlotNeBem(
const bool use3d) {
340 std::cerr <<
m_className <<
"::PlotNeBem: 3D plot not implemented yet.\n";
346 for (
unsigned int i = nRegions; i-- > 0;) {
347 std::vector<double> xv;
348 std::vector<double> yv;
349 Medium* medium =
nullptr;
350 unsigned int bctype = 1;
352 if (!m_nebem->
GetRegion(i, xv, yv, medium, bctype, v))
continue;
353 const unsigned int n = xv.size();
356 line.SetDrawOption(
"same");
358 line.SetLineStyle(2);
360 line.SetLineStyle(1);
362 for (
unsigned int j = 0; j < n; ++j) {
363 const unsigned int k = j < n - 1 ? j + 1 : 0;
364 line.DrawLine(xv[j], yv[j], xv[k], yv[k]);
370 for (
unsigned int i = 0; i < nWires; ++i) {
371 double x = 0.,
y = 0., d = 0., v = 0., q = 0.;
372 if (!m_nebem->
GetWire(i, x, y, d, v, q))
continue;
373 PlotWire(x, y, d, 0);
378 for (
unsigned int i = 0; i < nSegments; ++i) {
379 double x0 = 0., y0 = 0., x1 = 0., y1 = 0., v = 0.;
380 if (!m_nebem->
GetSegment(i, x0, y0, x1, y1, v))
continue;
381 PlotPlane(x0, y0, x1, y1);
388void ViewCell::SetupGeo(
const double dx,
const double dy,
const double dz) {
391 gGeoManager =
nullptr;
392 m_geo.reset(
new TGeoManager(
"ViewCellGeoManager", m_label.c_str()));
393 TGeoMaterial* matVacuum =
new TGeoMaterial(
"Vacuum", 0., 0., 0.);
394 TGeoMaterial* matMetal =
new TGeoMaterial(
"Metal", 63.546, 29., 8.92);
395 TGeoMedium* medVacuum =
new TGeoMedium(
"Vacuum", 0, matVacuum);
396 TGeoMedium* medMetal =
new TGeoMedium(
"Metal", 1, matMetal);
397 m_geo->AddMaterial(matVacuum);
398 m_geo->AddMaterial(medMetal->GetMaterial());
400 m_geo->MakeBox(
"World", medVacuum, 1.05 * dx, 1.05 * dy, 1.05 * dz);
401 m_geo->SetTopVolume(world);
403 TGeoVolume* top = m_geo->GetTopVolume();
404 TGeoBBox* box =
dynamic_cast<TGeoBBox*
>(top);
405 double halfLenghts[3] = {1.05 * dx, 1.05 * dy, 1.05 * dz};
406 if (box) box->SetDimensions(halfLenghts);
410void ViewCell::PlotWire(
const double x,
const double y,
const double d,
412 if (m_useWireMarker) {
415 markerStyle = kFullCircle;
416 }
else if (type == 1) {
417 markerStyle = kOpenCircle;
418 }
else if (type == 2) {
419 markerStyle = kFullSquare;
420 }
else if (type == 3) {
421 markerStyle = kOpenSquare;
423 markerStyle = 26 + type;
426 marker.SetMarkerStyle(markerStyle);
427 marker.SetDrawOption(
"Psame");
428 marker.DrawMarker(x, y);
433 circle.SetDrawOption(
"same");
434 circle.SetFillColor(kWhite);
435 circle.DrawEllipse(x, y, 0.5 * d, 0.5 * d, 0, 360, 0);
438void ViewCell::PlotWire(
const double x,
const double y,
const double d,
439 const int type,
const double lz) {
441 const auto medium = m_geo->GetMedium(
"Metal");
442 TGeoVolume* wire = m_geo->MakeTube(
"Wire", medium, 0., 0.5 * d, lz);
445 wire->SetLineColor(kGray + 2);
448 wire->SetLineColor(kRed + 2);
451 wire->SetLineColor(kPink + 3);
454 wire->SetLineColor(kCyan + 3);
457 wire->SetLineColor(kBlue + type);
460 m_geo->GetTopVolume()->AddNode(wire, 1,
new TGeoTranslation(x, y, 0.));
463void ViewCell::PlotTube(
const double x0,
const double y0,
const double r,
467 circle.SetDrawOption(
"same");
468 circle.SetFillStyle(0);
469 circle.DrawEllipse(x0, y0, r, r, 0, 360, 0);
473 double*
x =
new double[n + 1];
474 double*
y =
new double[n + 1];
475 for (
int i = 0; i <= n; ++i) {
476 const double phi = i * TwoPi / double(n);
477 x[i] = x0 + r *
cos(phi);
478 y[i] = y0 + r *
sin(phi);
481 pline.SetDrawOption(
"same");
482 pline.DrawPolyLine(n + 1, x, y);
487void ViewCell::PlotTube(
const double x0,
const double y0,
488 const double r1,
const double r2,
const int n,
491 TGeoVolume* tube =
nullptr;
494 tube = m_geo->MakeTube(
"Tube", m_geo->GetMedium(
"Metal"), r1, r2, lz);
496 tube = m_geo->MakePgon(
"Tube", m_geo->GetMedium(
"Metal"), 0., 360., n, 2);
497 TGeoPgon* pgon =
dynamic_cast<TGeoPgon*
>(tube->GetShape());
498 pgon->DefineSection(0, -lz, r1, r2);
499 pgon->DefineSection(1, +lz, r1, r2);
501 tube->SetLineColor(kGreen + 2);
502 tube->SetTransparency(75);
503 m_geo->GetTopVolume()->AddNode(tube, 1,
new TGeoTranslation(x0, y0, 0));
506void ViewCell::PlotPlane(
const double x0,
const double y0,
507 const double x1,
const double y1) {
510 line.SetDrawOption(
"same");
511 line.DrawLine(x0, y0, x1, y1);
514void ViewCell::PlotPlane(
const double dx,
const double dy,
const double dz,
515 const double x0,
const double y0) {
517 const auto medium = m_geo->GetMedium(
"Metal");
518 TGeoVolume* plane = m_geo->MakeBox(
"Plane", medium, dx, dy, dz);
519 plane->SetLineColor(kGreen - 5);
520 plane->SetTransparency(75);
521 m_geo->GetTopVolume()->AddNode(plane, 1,
new TGeoTranslation(x0, y0, 0));
bool GetVoltageRange(double &pmin, double &pmax) override
Calculate the voltage range [V].
bool GetPeriodicityY(double &s)
Get the periodic length in the y-direction.
bool IsPolar() const
Are polar coordinates being used?
unsigned int GetNumberOfWires() const
Get the number of wires.
std::string GetCellType()
bool GetWire(const unsigned int i, double &x, double &y, double &diameter, double &voltage, std::string &label, double &length, double &charge, int &ntrap) const
Retrieve the parameters of a wire.
bool GetPlaneR(const unsigned int i, double &r, double &voltage, std::string &label) const
Retrieve the parameters of a plane at constant radius.
unsigned int GetNumberOfPlanesY() const
Get the number of equipotential planes at constant y.
unsigned int GetNumberOfPlanesX() const
Get the number of equipotential planes at constant x.
bool GetPeriodicityX(double &s)
Get the periodic length in the x-direction.
bool GetTube(double &r, double &voltage, int &nEdges, std::string &label) const
Retrieve the tube parameters.
bool GetPlaneX(const unsigned int i, double &x, double &voltage, std::string &label) const
Retrieve the parameters of a plane at constant x.
bool GetPeriodicityPhi(double &s)
Get the periodicity [degree] in phi.
bool GetPlanePhi(const unsigned int i, double &phi, double &voltage, std::string &label) const
Retrieve the parameters of a plane at constant phi.
bool GetBoundingBox(double &x0, double &y0, double &z0, double &x1, double &y1, double &z1) override
Get the bounding box coordinates.
unsigned int GetNumberOfPlanesPhi() const
Get the number of equipotential planes at constant phi.
bool GetPlaneY(const unsigned int i, double &y, double &voltage, std::string &label) const
Retrieve the parameters of a plane at constant y.
unsigned int GetNumberOfPlanesR() const
Get the number of equipotential planes at constant radius.
Two-dimensional implementation of the nearly exact Boundary Element Method.
unsigned int GetNumberOfSegments() const
Return the number of conducting straight-line segments.
bool GetVoltageRange(double &vmin, double &vmax) override
Calculate the voltage range [V].
bool GetSegment(const unsigned int i, double &x0, double &y0, double &x1, double &x2, double &v) const
Return the coordinates and voltage of a given straight-line segment.
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the bounding box coordinates.
unsigned int GetNumberOfRegions() const
Return the number of regions.
bool GetRegion(const unsigned int i, std::vector< double > &xv, std::vector< double > &yv, Medium *&medium, unsigned int &bctype, double &v)
Return the properties of a given region.
bool GetWire(const unsigned int i, double &x, double &y, double &d, double &v, double &q) const
Return the coordinates, diameter, potential and charge of a given wire.
unsigned int GetNumberOfWires() const
Return the number of wires.
Base class for visualization classes.
void Plot3d()
Make a three-dimensional drawing of the cell geometry (using TGeo).
void SetArea()
Take the plot range from the bounding box of the component class.
void SetComponent(ComponentAnalyticField *comp)
Set the component for which to draw the cell geometry.
void Plot2d()
Make a two-dimensional drawing of the cell geometry.
DoubleAc cos(const DoubleAc &f)
DoubleAc fabs(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)