17bool Invert(std::array<std::array<double, 3>, 3>& a) {
20 const double c11 = a[1][1] * a[2][2] - a[1][2] * a[2][1];
21 const double c12 = a[1][2] * a[2][0] - a[1][0] * a[2][2];
22 const double c13 = a[1][0] * a[2][1] - a[1][1] * a[2][0];
23 const double c21 = a[2][1] * a[0][2] - a[2][2] * a[0][1];
24 const double c22 = a[2][2] * a[0][0] - a[2][0] * a[0][2];
25 const double c23 = a[2][0] * a[0][1] - a[2][1] * a[0][0];
26 const double c31 = a[0][1] * a[1][2] - a[0][2] * a[1][1];
27 const double c32 = a[0][2] * a[1][0] - a[0][0] * a[1][2];
28 const double c33 = a[0][0] * a[1][1] - a[0][1] * a[1][0];
29 const double t1 =
fabs(a[0][0]);
30 const double t2 =
fabs(a[1][0]);
31 const double t3 =
fabs(a[2][0]);
34 if (t2 < t1 && t3 < t1) {
36 det = c22 * c33 - c23 * c32;
37 }
else if (t1 < t2 && t3 < t2) {
39 det = c13 * c32 - c12 * c33;
42 det = c23 * c12 - c22 * c13;
44 if (det == 0.)
return false;
45 const double s = pivot / det;
58std::string Fmt(
const double x) {
60 snprintf(buf, 100,
"%g", x);
61 return std::string(buf);
77 if (!m_canvas) m_canvas.reset(
new TCanvas(name.c_str(),
""));
78 m_pad = m_canvas.get();
84 if (!pad)
return false;
85 if (pad->GetListOfPrimitives()->GetSize() == 0 &&
86 pad->GetX1() == 0 && pad->GetX2() == 1 &&
87 pad->GetY1() == 0 && pad->GetY2() == 1) {
94 const double x1,
const double y1) {
96 const double bm = pad->GetBottomMargin();
97 const double lm = pad->GetLeftMargin();
98 const double rm = pad->GetRightMargin();
99 const double tm = pad->GetTopMargin();
100 const double dx = x1 - x0;
101 const double dy = y1 - y0;
102 pad->Range(x0 - dx * (lm / (1. - rm - lm)),
103 y0 - dy * (bm / (1. - tm - lm)),
104 x1 + dx * (rm / (1. - rm - lm)),
105 y1 + dy * (tm / (1. - tm - lm)));
110 const double xmax,
const double ymax) {
112 if (xmin == xmax || ymin == ymax) {
113 std::cerr <<
m_className <<
"::SetArea: Null area is not permitted.\n"
114 <<
" " << xmin <<
" < x < " << xmax <<
"\n"
115 <<
" " << ymin <<
" < y < " << ymax <<
"\n";
126 const double xmax,
const double ymax,
129 if (xmin == xmax || ymin == ymax || zmin == zmax) {
130 std::cerr <<
m_className <<
"::SetArea: Null area range not permitted.\n";
143 const double x0,
const double y0,
const double z0) {
145 const double fnorm = sqrt(fx * fx + fy * fy + fz * fz);
146 if (fnorm > 0 && fx * fx + fz * fz > 0) {
147 const double fxz = sqrt(fx * fx + fz * fz);
151 m_proj[1][0] = -fx * fy / (fxz * fnorm);
152 m_proj[1][1] = (fx * fx + fz * fz) / (fxz * fnorm);
153 m_proj[1][2] = -fy * fz / (fxz * fnorm);
157 }
else if (fnorm > 0 && fy * fy + fz * fz > 0) {
158 const double fyz = sqrt(fy * fy + fz * fz);
159 m_proj[0][0] = (fy * fy + fz * fz) / (fyz * fnorm);
160 m_proj[0][1] = -fx * fz / (fyz * fnorm);
161 m_proj[0][2] = -fy * fz / (fyz * fnorm);
170 <<
" Normal vector has zero norm. No new projection set.\n";
177 m_plane[3] = fx * x0 + fy * y0 + fz * z0;
183 const double x0,
const double y0,
const double z0,
184 const double hx,
const double hy,
const double hz) {
186 const double fnorm = sqrt(fx * fx + fy * fy + fz * fz);
189 <<
" Normal vector has zero norm. No new projection set.\n";
193 const double wx = fx / fnorm;
194 const double wy = fy / fnorm;
195 const double wz = fz / fnorm;
200 m_plane[3] = wx * x0 + wy * y0 + wz * z0;
202 double d = hx * wx + hy * wy + hz * wz;
203 double ux = hx - d * wx;
204 double uy = hy - d * wy;
205 double uz = hz - d * wz;
206 double unorm = std::sqrt(ux * ux + uy * uy + uz * uz);
207 if (unorm < 1.e-10) {
209 if (fy * fy + fz * fz > 0) {
220 d = ux * wx + uy * wy + uz * wz;
224 unorm = std::sqrt(ux * ux + uy * uy + uz * uz);
234 m_prmat[0][1] = wy * uz - wz * uy;
235 m_prmat[1][1] = wz * ux - wx * uz;
236 m_prmat[2][1] = wx * uy - wy * ux;
241 for (
unsigned int i = 0; i < 3; ++i) {
250 <<
" Inversion failed; reset to default.\n";
254 std::cout <<
m_className <<
"::SetPlane:\n PRMAT:\n";
255 for (
size_t i = 0; i < 3; ++i) {
256 std::printf(
" %10.5f %10.5f %10.5f\n",
259 std::cout <<
" PROJ:\n";
260 for (
size_t i = 0; i < 3; ++i) {
261 std::printf(
" %10.5f %10.5f %10.5f\n",
264 std::cout <<
" PLANE:\n";
265 std::printf(
" %10.5f %10.5f %10.5f %10.5f\n",
272 double auxu[3], auxv[3];
273 const double ctheta = cos(theta);
274 const double stheta = sin(theta);
275 for (
int i = 0; i < 3; ++i) {
276 auxu[i] = ctheta *
m_proj[0][i] - stheta *
m_proj[1][i];
277 auxv[i] = stheta *
m_proj[0][i] + ctheta *
m_proj[1][i];
279 for (
int i = 0; i < 3; ++i) {
288 m_proj = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 0}}};
290 m_prmat = {{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
294 m_proj = {{{1, 0, 0}, {0, 0, 1}, {0, 0, 0}}};
300 m_proj = {{{0, 1, 0}, {0, 0, 1}, {0, 0, 0}}};
306 m_proj = {{{0, 0, 1}, {1, 0, 0}, {0, 0, 0}}};
312 m_proj = {{{0, 0, 1}, {0, 1, 0}, {0, 0, 0}}};
319 std::string fname = s +
"_0";
320 while (gROOT->GetListOfFunctions()->FindObject(fname.c_str())) {
322 fname = s +
"_" + std::to_string(idx);
329 std::string hname = s +
"_0";
330 while (gDirectory->GetList()->FindObject(hname.c_str())) {
332 hname = s +
"_" + std::to_string(idx);
339 std::string hname = s +
"_0";
340 while (gROOT->GetListOfCanvases()->FindObject(hname.c_str())) {
342 hname = s +
"_" + std::to_string(idx);
359 std::cerr <<
m_className <<
"::UpdateProjectionMatrix:\n"
360 <<
" Zero norm vector; reset to default.\n";
368 std::cerr <<
m_className <<
"::UpdateProjectionMatrix:\n"
369 <<
" Inversion failed; reset to default.\n";
375 const std::array<float, 3>& x1,
376 std::array<float, 3>& xc)
const {
379 const bool in0 =
InBox(x0);
380 const bool in1 =
InBox(x1);
381 if (in0 == in1)
return;
383 const std::array<float, 3> dx = {x1[0] - x0[0], x1[1] - x0[1],
387 for (
size_t i = 0; i < 3; ++i) {
388 if (dx[i] == 0. || (xc[i] >= bmin[i] && xc[i] <= bmax[i]))
continue;
389 const double b = xc[i] < bmin[i] ? bmin[i] : bmax[i];
390 const double s = (b - xc[i]) / dx[i];
392 for (
size_t j = 0; j < 3; ++j) {
393 if (j != i) xc[j] += dx[j] * s;
399 const short col,
const short lw) {
401 const size_t nP = xl.size();
405 gr.SetLineColor(col);
408 std::vector<float> xgr;
409 std::vector<float> ygr;
411 bool in0 =
InBox(x0);
413 float xp = 0., yp = 0.;
414 ToPlane(x0[0], x0[1], x0[2], xp, yp);
418 for (
unsigned int j = 1; j < nP; ++j) {
420 bool in1 =
InBox(x1);
422 float xp = 0., yp = 0.;
423 std::array<float, 3> xc;
425 ToPlane(xc[0], xc[1], xc[2], xp, yp);
430 float xp = 0., yp = 0.;
431 ToPlane(x1[0], x1[1], x1[2], xp, yp);
434 }
else if (!xgr.empty()) {
435 gr.DrawGraph(xgr.size(), xgr.data(), ygr.data(),
"Lsame");
443 gr.DrawGraph(xgr.size(), xgr.data(), ygr.data(),
"Lsame");
449 std::string xLabel =
"";
450 constexpr double tol = 1.e-4;
452 if (fabs(
m_proj[0][0] - 1) < tol) {
454 }
else if (fabs(
m_proj[0][0] + 1) < tol) {
455 xLabel =
"#minus#it{x}";
456 }
else if (fabs(
m_proj[0][0]) > tol) {
457 xLabel = Fmt(
m_proj[0][0]) +
" #it{x}";
461 if (!xLabel.empty()) {
462 if (
m_proj[0][1] < -tol) {
463 xLabel +=
" #minus ";
464 }
else if (
m_proj[0][1] > tol) {
467 if (fabs(
m_proj[0][1] - 1) < tol || fabs(
m_proj[0][1] + 1) < tol) {
469 }
else if (fabs(
m_proj[0][1]) > tol) {
470 xLabel += Fmt(fabs(
m_proj[0][1])) +
" #it{y}";
473 if (fabs(
m_proj[0][1] - 1) < tol) {
475 }
else if (fabs(
m_proj[0][1] + 1) < tol) {
476 xLabel =
"#minus#it{y}";
477 }
else if (fabs(
m_proj[0][1]) > tol) {
478 xLabel = Fmt(
m_proj[0][1]) +
" #it{y}";
483 if (!xLabel.empty()) {
484 if (
m_proj[0][2] < -tol) {
485 xLabel +=
" #minus ";
486 }
else if (
m_proj[0][2] > tol) {
489 if (fabs(
m_proj[0][2] - 1) < tol || fabs(
m_proj[0][2] + 1) < tol) {
491 }
else if (fabs(
m_proj[0][2]) > tol) {
492 xLabel += Fmt(fabs(
m_proj[0][2])) +
" #it{z}";
495 if (fabs(
m_proj[0][2] - 1) < tol) {
497 }
else if (fabs(
m_proj[0][2] + 1) < tol) {
498 xLabel =
"#minus#it{z}";
499 }
else if (fabs(
m_proj[0][2]) > tol) {
500 xLabel = Fmt(
m_proj[0][2]) +
" #it{z}";
512 std::string yLabel =
"";
513 constexpr double tol = 1.e-4;
515 if (fabs(
m_proj[1][0] - 1) < tol) {
517 }
else if (fabs(
m_proj[1][0] + 1) < tol) {
518 yLabel =
"#minus#it{x}";
519 }
else if (fabs(
m_proj[1][0]) > tol) {
520 yLabel = Fmt(
m_proj[1][0]) +
" #it{x}";
524 if (!yLabel.empty()) {
525 if (
m_proj[1][1] < -tol) {
526 yLabel +=
" #minus ";
527 }
else if (
m_proj[1][1] > tol) {
530 if (fabs(
m_proj[1][1] - 1) < tol || fabs(
m_proj[1][1] + 1) < tol) {
532 }
else if (fabs(
m_proj[1][1]) > tol) {
533 yLabel += Fmt(fabs(
m_proj[1][1])) +
" #it{y}";
536 if (fabs(
m_proj[1][1] - 1) < tol) {
538 }
else if (fabs(
m_proj[1][1] + 1) < tol) {
539 yLabel =
"#minus#it{y}";
540 }
else if (fabs(
m_proj[1][1]) > tol) {
541 yLabel = Fmt(
m_proj[1][1]) +
" #it{y}";
546 if (!yLabel.empty()) {
547 if (
m_proj[1][2] < -tol) {
548 yLabel +=
" #minus ";
549 }
else if (
m_proj[1][2] > tol) {
552 if (fabs(
m_proj[1][2] - 1) < tol || fabs(
m_proj[1][2] + 1) < tol) {
554 }
else if (fabs(
m_proj[1][2]) > tol) {
555 yLabel += Fmt(fabs(
m_proj[1][2])) +
" #it{z}";
558 if (fabs(
m_proj[1][2] - 1) < tol) {
560 }
else if (fabs(
m_proj[1][2] + 1) < tol) {
561 yLabel =
"#minus#it{z}";
562 }
else if (fabs(
m_proj[1][2]) > tol) {
563 yLabel = Fmt(
m_proj[1][2]) +
" #it{z}";
574 std::string description;
576 constexpr double tol = 1.e-4;
578 if (fabs(
m_plane[0] - 1) < tol) {
580 }
else if (fabs(
m_plane[0] + 1) < tol) {
582 }
else if (fabs(
m_plane[0]) > tol) {
583 description = Fmt(
m_plane[0]) +
" x";
587 if (!description.empty()) {
589 description +=
" - ";
591 description +=
" + ";
595 }
else if (fabs(
m_plane[1]) > tol) {
596 description += Fmt(fabs(
m_plane[1])) +
" y";
599 if (fabs(
m_plane[1] - 1) < tol) {
601 }
else if (fabs(
m_plane[1] + 1) < tol) {
603 }
else if (fabs(
m_plane[1]) > tol) {
604 description = Fmt(
m_plane[1]) +
" y";
609 if (!description.empty()) {
611 description +=
" - ";
613 description +=
" + ";
617 }
else if (fabs(
m_plane[2]) > tol) {
618 description += Fmt(fabs(
m_plane[2])) +
" z";
621 if (fabs(
m_plane[2] - 1) < tol) {
623 }
else if (fabs(
m_plane[2] + 1) < tol) {
625 }
else if (fabs(
m_plane[2]) > tol) {
626 description = Fmt(
m_plane[2]) +
" z";
631 description +=
" = " + Fmt(
m_plane[3]);
636 double& xmin,
double& ymin,
637 double& xmax,
double& ymax)
const {
639 if (!sensor)
return false;
641 std::array<double, 3> bbmin;
642 std::array<double, 3> bbmax;
643 if (!sensor->
GetArea(bbmin[0], bbmin[1], bbmin[2],
644 bbmax[0], bbmax[1], bbmax[2])) {
646 <<
" Sensor area is not defined.\n"
647 <<
" Please set the plot limits explicitly (SetArea).\n";
650 return PlotLimits(bbmin, bbmax, xmin, ymin, xmax, ymax);
654 double& xmin,
double& ymin,
655 double& xmax,
double& ymax)
const {
657 if (!cmp)
return false;
659 std::array<double, 3> bbmin;
660 std::array<double, 3> bbmax;
662 bbmax[0], bbmax[1], bbmax[2])) {
664 <<
" Bounding box of the component is not defined.\n"
665 <<
" Please set the plot limits explicitly (SetArea).\n";
668 if (std::isinf(bbmin[0]) || std::isinf(bbmax[0]) ||
669 std::isinf(bbmin[1]) || std::isinf(bbmax[1]) ||
670 std::isinf(bbmin[2]) || std::isinf(bbmax[2])) {
671 std::array<double, 3> cellmin = {0., 0., 0.};
672 std::array<double, 3> cellmax = {0., 0., 0.};
674 cellmax[0], cellmax[1], cellmax[2])) {
676 <<
" Cell boundaries are not defined.\n"
677 <<
" Please set the plot limits explicitly (SetArea).\n";
680 for (
size_t i = 0; i < 3; ++i) {
681 if (std::isinf(bbmin[i]) || std::isinf(bbmax[i])) {
682 bbmin[i] = cellmin[i];
683 bbmax[i] = cellmax[i];
687 return PlotLimits(bbmin, bbmax, xmin, ymin, xmax, ymax);
691 double& xmax,
double& ymax)
const {
695 return PlotLimits(bbmin, bbmax, xmin, ymin, xmax, ymax);
699 std::array<double, 3>& bbmax,
700 double& xmin,
double& ymin,
701 double& xmax,
double& ymax)
const {
702 constexpr double tol = 1.e-4;
703 double umin[2] = {-std::numeric_limits<double>::max(),
704 -std::numeric_limits<double>::max()};
705 double umax[2] = {std::numeric_limits<double>::max(),
706 std::numeric_limits<double>::max()};
707 for (
unsigned int i = 0; i < 3; ++i) {
710 for (
unsigned int j = 0; j < 2; ++j) {
711 if (fabs(
m_proj[j][i]) < tol)
continue;
712 const double t1 = bbmin[i] /
m_proj[j][i];
713 const double t2 = bbmax[i] /
m_proj[j][i];
714 const double tmin = std::min(t1, t2);
715 const double tmax = std::max(t1, t2);
716 if (tmin > umin[j] && tmin < umax[j]) umin[j] = tmin;
717 if (tmax < umax[j] && tmax > umin[j]) umax[j] = tmax;
Abstract base class for components.
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the bounding box coordinates.
virtual bool GetElementaryCell(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the coordinates of the elementary cell.
bool GetArea(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Return the current user area.
std::array< double, 4 > m_plane
static void SetRange(TVirtualPad *pad, const double x0, const double y0, const double x1, const double y1)
std::array< std::array< double, 3 >, 3 > m_prmat
void Clip(const std::array< float, 3 > &x0, const std::array< float, 3 > &x1, std::array< float, 3 > &xc) const
bool InBox(const std::array< T, 3 > &x) const
void DrawLine(const std::vector< std::array< float, 3 > > &xl, const short col, const short lw)
static std::string FindUnusedHistogramName(const std::string &s)
Find an unused histogram name.
void SetPlaneZX()
Set the viewing plane to z-x.
void SetPlaneYZ()
Set the viewing plane to y-z.
static std::string FindUnusedCanvasName(const std::string &s)
Find an unused canvas name.
std::array< std::array< double, 3 >, 3 > m_proj
TPad * GetCanvas()
Retrieve the canvas.
static bool RangeSet(TVirtualPad *)
void SetPlaneXZ()
Set the viewing plane to x-z.
bool PlotLimits(Sensor *sensor, double &xmin, double &ymin, double &xmax, double &ymax) const
void SetPlaneXY()
Set the viewing plane to x-y.
void ToPlane(const T x, const T y, const T z, T &xp, T &yp) const
std::string PlaneDescription()
void SetPlaneZY()
Set the viewing plane to z-y.
bool PlotLimitsFromUserBox(double &xmin, double &ymin, double &xmax, double &ymax) const
static std::string FindUnusedFunctionName(const std::string &s)
Find an unused function name.
void Rotate(const double angle)
Rotate the viewing plane (angle in radian).
ViewBase()=delete
Default constructor.
void UpdateProjectionMatrix()
virtual void SetPlane(const double fx, const double fy, const double fz, const double x0, const double y0, const double z0)
PlottingEngine plottingEngine
DoubleAc fabs(const DoubleAc &f)