Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 45 additions & 29 deletions graf2d/gpad/src/TPad.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1228,6 +1228,7 @@ Int_t TPad::DistancetoPrimitive(Int_t px, Int_t py)
/// - xmargin is the space along x between pads in percent of canvas.
/// - ymargin is the space along y between pads in percent of canvas.
/// - color is the color of the new pads. If 0, color is the canvas color.
/// - The outer margins of the pads are taken from the current canvas margins.
///
/// Pads are automatically named `canvasname_n` where `n` is the division number
/// starting from top left pad.
Expand All @@ -1236,6 +1237,18 @@ Int_t TPad::DistancetoPrimitive(Int_t px, Int_t py)
///
/// \image html gpad_pad3.png
///
/// Example if:
/// /// ~~~ {.cpp}
/// c->SetLeftMargin(0.30);
/// c->SetBottomMargin(0.10);
/// c->SetRightMargin(0.05);
/// c->SetTopMargin(0.10);
/// c->Divide(nx, ny, 0.03, 0.05, 46);
/// ~~~
/// \image html canvas_divide_custom.png
///
/// More examples are in `tutorials/visualisation/graphics/canvas_divide_example.C`
///
/// Once a pad is divided into sub-pads, one can set the current pad
/// to a subpad with a given division number as illustrated above
/// with TPad::cd(subpad_number).
Expand Down Expand Up @@ -1269,40 +1282,43 @@ void TPad::Divide(Int_t nx, Int_t ny, Float_t xmargin, Float_t ymargin, Int_t co
TContext ctxt(kTRUE);

cd();
if (nx <= 0) nx = 1;
if (ny <= 0) ny = 1;
Int_t ix, iy;
Double_t x1, y1, x2, y2, dx, dy;
TPad *pad;
if (nx == 0)
nx = 1;
if (ny == 0)
ny = 1;

Double_t xl = GetLeftMargin();
Double_t xr = GetRightMargin();
Double_t yb = GetBottomMargin();
Double_t yt = GetTopMargin();

TString name, title;
Int_t n = 0;
if (color == 0) color = GetFillColor();
if (xmargin >= 0 && ymargin >= 0) {
//general case
dy = 1/Double_t(ny);
dx = 1/Double_t(nx);
for (iy=0;iy<ny;iy++) {
y2 = 1 - iy*dy - ymargin;
y1 = y2 - dy + 2*ymargin;
if (y1 < 0) y1 = 0;
if (y1 > y2) continue;
for (ix=0;ix<nx;ix++) {
x1 = ix*dx + xmargin;
x2 = x1 +dx -2*xmargin;
if (x1 > x2) continue;
auto dx = (1 - xl - xr - xmargin * (nx - 1)) / nx; // width of a subpad
auto dy = (1 - yt - yb - ymargin * (ny - 1)) / ny; // height of a subpad

Int_t n = 0;
for (auto iy = 0; iy < ny; iy++) {
auto y2 = 1 - yt - iy * (dy + ymargin);
auto y1 = y2 - dy;
if (y1 < yb)
y1 = yb;
for (auto ix = 0; ix < nx; ix++) {
auto x1 = xl + ix * (dx + xmargin);
auto x2 = x1 + dx;
if (x2 > (1 - xr))
xr = 1 - xr;
n++;
name.Form("%s_%d", GetName(), n);
pad = new TPad(name.Data(), name.Data(), x1, y1, x2, y2, color);
auto pad = new TPad(name.Data(), name.Data(), x1, y1, x2, y2, color);
pad->SetNumber(n);
pad->Draw();
}
}
} else {
// special case when xmargin < 0 or ymargin < 0
Double_t xl = GetLeftMargin();
Double_t xr = GetRightMargin();
Double_t yb = GetBottomMargin();
Double_t yt = GetTopMargin();
xl /= (1-xl+xr)*nx;
xr /= (1-xl+xr)*nx;
yb /= (1-yb+yt)*ny;
Expand All @@ -1311,23 +1327,23 @@ void TPad::Divide(Int_t nx, Int_t ny, Float_t xmargin, Float_t ymargin, Int_t co
SetRightMargin(xr);
SetBottomMargin(yb);
SetTopMargin(yt);
dx = (1-xl-xr)/nx;
dy = (1-yb-yt)/ny;
auto dx = (1 - xl - xr) / nx;
auto dy = (1 - yb - yt) / ny;
Int_t number = 0;
for (Int_t i=0;i<nx;i++) {
x1 = i*dx+xl;
x2 = x1 + dx;
auto x1 = i * dx + xl;
auto x2 = x1 + dx;
if (i == 0) x1 = 0;
if (i == nx-1) x2 = 1-xr;
for (Int_t j=0;j<ny;j++) {
number = j*nx + i +1;
y2 = 1 -j*dy -yt;
y1 = y2 - dy;
auto y2 = 1 - j * dy - yt;
auto y1 = y2 - dy;
if (j == 0) y2 = 1-yt;
if (j == ny-1) y1 = 0;
name.Form("%s_%d", GetName(), number);
title.Form("%s_%d", GetTitle(), number);
pad = new TPad(name.Data(), title.Data(), x1, y1, x2, y2, color);
auto pad = new TPad(name.Data(), title.Data(), x1, y1, x2, y2, color);
pad->SetNumber(number);
pad->SetBorderMode(0);
if (i == 0) pad->SetLeftMargin(xl*nx);
Expand Down
131 changes: 131 additions & 0 deletions tutorials/visualisation/graphics/canvas_divide_example.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// variants: 0 - custom values
// 1 - default values
// 2+ - old default values
void canvas_divide_example(int use_variant = 0)
{
auto wx = 600; // width and heigh
auto wy = 400;

auto nx = 3; // top-level pad division
auto ny = 2;

auto ml = 0.30; // top-level pad margins
auto mb = 0.10;
auto mr = 0.05;
auto mt = 0.10;

auto c = new TCanvas("canvas_divide", "canvas_divide", wx, wy);
c->SetFillColor(19);

if (use_variant == 0) {
c->SetLeftMargin(ml);
c->SetBottomMargin(mb);
c->SetRightMargin(mr);
c->SetTopMargin(mt);

c->Divide(nx, ny, 0.03, 0.05, 46);
} else if (use_variant == 1) {
c->Divide(nx, ny, 0.01, 0.01, 46);
} else {
c->SetLeftMargin(0.01);
c->SetBottomMargin(0.01);
c->SetRightMargin(0.01);
c->SetTopMargin(0.01);

c->Divide(nx, ny, 0.02, 0.02, 46);
}

ml = c->GetLeftMargin();
mb = c->GetBottomMargin();
mr = c->GetRightMargin();
mt = c->GetTopMargin();

auto h = new TH1F("", "", 100, -3.3, 3.3);
h->GetXaxis()->SetLabelFont(43);
h->GetXaxis()->SetLabelSize(12);
h->GetYaxis()->SetLabelFont(43);
h->GetYaxis()->SetLabelSize(12);
h->GetYaxis()->SetNdivisions(505);
h->SetMaximum(30 * nx * ny);
h->SetFillColor(41);

Int_t number = 0;
for (Int_t i = 0; i < nx * ny; i++) {
number++;
c->cd(number);
h->FillRandom("gaus", 1000);
h->DrawCopy();
}

c->cd();

TArrow arr;

arr.DrawArrow(0, 0.5, ml, 0.5, 0.01, "<|>");
arr.DrawArrow(0.5, 0, 0.5, mb, 0.01, "<|>");
arr.DrawArrow(1 - mr, 0.5, 1, 0.5, 0.01, "<|>");
arr.DrawArrow(0.5, 1 - mt, 0.5, 1, 0.01, "<|>");

TLatex tex_x;
tex_x.SetNDC(1);
tex_x.SetTextSize(0.03);
tex_x.SetTextAlign(12);
tex_x.SetTextAngle(90);

TLatex tex_y;
tex_y.SetNDC(1);
tex_y.SetTextSize(0.03);
tex_y.SetTextAlign(12);

tex_x.DrawLatex(ml / 2, 0.5, TString::Format(" ml = %.2f", ml));
tex_x.DrawLatex(1 - mr / 2, 0.5, TString::Format(" mr = %.2f", mr));

tex_y.DrawLatex(0.5, mb / 2, TString::Format(" mb = %.2f", mb));
tex_y.DrawLatex(0.5, 1 - mt / 2, TString::Format(" mt = %.2f", mt));

for (int i = 0; i < nx; ++i) {
for (int j = 0; j < ny; ++j) {

float x1, x2, xc, y1, y2, yc;

auto spad = c->GetPad(1 + j * nx + i); // current pad
x1 = spad->GetXlowNDC() + spad->GetWNDC();
xc = spad->GetXlowNDC() + spad->GetWNDC() / 2;
if (i < (nx - 1)) {
auto spad_nx = c->GetPad(1 + j * nx + (i + 1)); // next pad in x
x2 = spad_nx->GetXlowNDC();
}
auto xm = x2 - x1;

if (j < (ny - 1)) {
auto spad_ny = c->GetPad(1 + (j + 1) * nx + i); // next pad in y
y1 = spad_ny->GetYlowNDC() + spad->GetHNDC();
}
y2 = spad->GetYlowNDC();
yc = spad->GetYlowNDC() + spad->GetHNDC() / 2;
auto ym = y2 - y1;

if (i < (nx - 1)) {
arr.DrawArrow(x1, yc, x2, yc, 0.01, "<|>");
tex_x.DrawLatex((x1 + x2) / 2, yc, TString::Format(" xm = %.2f", xm));
}
if (j < (ny - 1)) {
arr.DrawArrow(xc, y1, xc, y2, 0.01, "<|>");
tex_y.DrawLatex(xc, (y1 + y2) / 2, TString::Format(" ym = %.2f", ym));
}
}
}

TText text;
text.SetTextSize(0.03);
text.SetTextFont(102);
text.SetNDC(1);

if (use_variant == 0) {
text.DrawText(0.01, 0.90, "c->SetLeftMargin(ml);");
text.DrawText(0.01, 0.85, "c->SetBottomMargin(mb);");
text.DrawText(0.01, 0.80, "c->SetRightMargin(mr);");
text.DrawText(0.01, 0.75, "c->SetTopMargin(mt);");
text.DrawText(0.01, 0.70, "c->Divide(nx, ny, xm, ym);");
}
}