// @(#)root/graf:$Name: $:$Id: TGaxis.cxx,v 1.6 2000/09/01 07:02:27 brun Exp $
// Author: Rene Brun, Olivier Couet 12/12/94
/*************************************************************************
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <fstream.h>
#include <time.h>
#include <math.h>
#include <float.h>
#include "TROOT.h"
#include "TGaxis.h"
#include "TVirtualPad.h"
#include "TVirtualX.h"
#include "TLine.h"
#include "TLatex.h"
#include "TStyle.h"
#include "TF1.h"
#include "TMath.h"
ClassImp(TGaxis)
//______________________________________________________________________________
//
// Service class for the graphical representation of axis.
// Instances of this class are generated by the histogram classes and TGraph.
//
// The picture below has been generated by the following macro.
//{
//
// gROOT.Reset();
//
// c1 = new TCanvas("c1","Examples of Gaxis",10,10,700,500);
//
// c1->Range(-10,-1,10,1);
//
// TGaxis *axis1 = new TGaxis(-4.5,-0.2,5.5,-0.2,-6,8,510,"");
// axis1->SetName("axis1");
// axis1->Draw();
//
// TGaxis *axis2 = new TGaxis(-4.5,0.2,5.5,0.2,0.001,10000,510,"G");
// axis2->SetName("axis2");
// axis2->Draw();
//
// TGaxis *axis3 = new TGaxis(-9,-0.8,-9,0.8,-8,8,50510,"");
// axis3->SetName("axis3");
// axis3->Draw();
//
// TGaxis *axis4 = new TGaxis(-7,-0.8,-7,0.8,1,10000,50510,"G");
// axis4->SetName("axis4");
// axis4->Draw();
//
// TGaxis *axis5 = new TGaxis(-4.5,-0.6,5.5,-0.6,1.2,1.32,80506,"-+");
// axis5->SetName("axis5");
// axis5->SetLabelSize(0.03);
// axis5->SetTextFont(72);
// axis5->SetLabelOffset(0.025);
//
// axis5->Draw();
//
// TGaxis *axis6 = new TGaxis(-4.5,0.6,5.5,0.6,100,900,50510,"-");
// axis6->SetName("axis6");
// axis6->Draw();
//
// TGaxis *axis7 = new TGaxis(8,-0.8,8,0.8,0,9000,50510,"+L");
// axis7->SetName("axis7");
// axis7->SetLabelOffset(0.01);
// axis7->Draw();
//
// //one can make axis going top->bottom. However because of a long standing
// //problem, the two x values should not be equal
// TGaxis *axis8 = new TGaxis(6.5,0.8,6.499,-0.8,0,90,50510,"-");
// axis8->SetName("axis8");
// axis8->Draw();
//}
//
/*
*/
//
//
//
// See the second TGaxis constructor for examples of TGaxis
// with a mapping function.
//______________________________________________________________________________
TGaxis::TGaxis(): TLine(), TAttText(11,0,1,62,0.040)
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis default constructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =========================
fGridLength = 0.;
fLabelOffset = 0.005;
fLabelSize = 0.040;
fLabelFont = 62;
fLabelColor = 1;
fTickSize = 0.030;
fTitleOffset = 1;
fTitleSize = fLabelSize;
fName = " ";
fTitle = " ";
fTimeFormat = "";
fFunctionName= "";
fFunction = 0;
}
//______________________________________________________________________________
TGaxis::TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
Double_t wmin, Double_t wmax, Int_t ndiv, Option_t *chopt,
Double_t gridlength)
: TLine(xmin,ymin,xmax,ymax), TAttText(11,0,1,62,0.040)
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis normal constructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =========================
// See explanation of parameters in PaintAxis
//
fWmin = wmin;
fWmax = wmax;
fNdiv = ndiv;
fGridLength = gridlength;
fLabelOffset = 0.005;
fLabelSize = 0.040;
fLabelFont = 62;
fLabelColor = 1;
fTickSize = 0.030;
fTitleOffset = 1;
fTitleSize = fLabelSize;
fChopt = chopt;
fName = " ";
fTitle = " ";
fTimeFormat = "";
fFunctionName= "";
fFunction = 0;
}
//______________________________________________________________________________
TGaxis::TGaxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
const char *funcname, Int_t ndiv, Option_t *chopt,
Double_t gridlength)
: TLine(xmin,ymin,xmax,ymax), TAttText(11,0,1,62,0.040)
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis constructor with a TF1 to map axis values-*-*-*
//*-* ===============================================
// See explanation of parameters in PaintAxis
// Instead of the wmin,wmax arguments of the normal constructor, the
// name of a TF1 function can be specified. This function will be used
// by TGaxis::PaintAxis to map the user coordinates to the axis values
// and ticks.
// Examples:
//void gaxis3a()
//{
// gStyle->SetOptStat(0);
//
// TH2F *h2 = new TH2F("h","Axes",2,0,10,2,-2,2);
// h2->Draw();
//
// TF1 *f1=new TF1("f1","-x",-10,10);
// TGaxis *A1 = new TGaxis(0,2,10,2,"f1",510,"-");
// A1->SetTitle("axis with decreasing values");
// A1->Draw();
//
// TF1 *f2=new TF1("f2","exp(x)",0,2);
// TGaxis *A2 = new TGaxis(1,1,9,1,"f2");
// A2->SetTitle("exponential axis");
// A2->SetLabelSize(0.03);
// A2->SetTitleSize(0.03);
// A2->SetTitleOffset(1.2);
// A2->Draw();
//
// TF1 *f3=new TF1("f3","log10(x)",0,800);
// TGaxis *A3 = new TGaxis(2,-2,2,0,"f3",505);
// A3->SetTitle("logarithmic axis");
// A3->SetLabelSize(0.03);
// A3->SetTitleSize(0.03);
// A3->SetTitleOffset(1.2);
// A3->Draw();
//}
//
/*
*/
//
fFunction = (TF1*)gROOT->GetFunction(funcname);
if (!fFunction) {
Error("TGaxis, calling constructor with an unknown function:%s",funcname);
fWmin = 0;
fWmax = 1;
} else {
fWmin = fFunction->GetXmin();
fWmax = fFunction->GetXmax();
}
fFunctionName= funcname;
fNdiv = ndiv;
fGridLength = gridlength;
fLabelOffset = 0.005;
fLabelSize = 0.040;
fLabelFont = 62;
fLabelColor = 1;
fTickSize = 0.030;
fTitleOffset = 1;
fTitleSize = fLabelSize;
fChopt = chopt;
fName = " ";
fTitle = " ";
fTimeFormat = "";
}
//______________________________________________________________________________
TGaxis::~TGaxis()
{
//*-*-*-*-*-*-*-*-*-*-*Gaxis default destructor-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =======================
}
//______________________________________________________________________________
void TGaxis::CenterTitle(Bool_t center)
{
// if center = kTRUE axis title will be centered
// default is right adjusted
if (center) SetBit(kCenterTitle);
else ResetBit(kCenterTitle);
}
//______________________________________________________________________________
void TGaxis::DrawAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
Double_t wmin, Double_t wmax, Int_t ndiv, Option_t *chopt,
Double_t gridlength)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this axis with new attributes*-*-*-*-*-*-*-*-*-*
//*-* ==================================
TGaxis *newaxis = new TGaxis(xmin,ymin,xmax,ymax,wmin,wmax,ndiv,chopt,gridlength);
newaxis->SetLineColor(fLineColor);
newaxis->SetLineWidth(fLineWidth);
newaxis->SetLineStyle(fLineStyle);
newaxis->SetTextAlign(fTextAlign);
newaxis->SetTextAngle(fTextAngle);
newaxis->SetTextColor(fTextColor);
newaxis->SetTextFont(fTextFont);
newaxis->SetTextSize(fTextSize);
newaxis->SetTitleSize(fTitleSize);
newaxis->SetTitleOffset(fTitleOffset);
newaxis->SetLabelFont(fLabelFont);
newaxis->SetLabelColor(fLabelColor);
newaxis->SetLabelSize(fLabelSize);
newaxis->SetLabelOffset(fLabelOffset);
newaxis->SetTickSize(fTickSize);
newaxis->SetBit(kCanDelete);
newaxis->AppendPad();
}
//______________________________________________________________________________
void TGaxis::Paint(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*Draw this axis with its current attributes*-*-*-*-*-*-*
//*-* ==========================================
Double_t wmin = fWmin;
Double_t wmax = fWmax;
Int_t ndiv = fNdiv;
PaintAxis(fX1,fY1,fX2,fY2,wmin,wmax,ndiv,fChopt.Data(),fGridLength);
}
//______________________________________________________________________________
void TGaxis::PaintAxis(Double_t xmin, Double_t ymin, Double_t xmax, Double_t ymax,
Double_t &wmin, Double_t &wmax, Int_t &ndiv, Option_t *chopt,
Double_t gridlength)
{
//*-*-*-*-*-*-*-*-*-*-*-*Control function to draw an axis*-*-*-*-*-*-*-*-*-*-*
//*-* ================================
//
//============> Original authors (O.Couet C.E.Vandoni N.Cremel-Somon)
// largely modified and converted to C++ class by Rene Brun
//
// _Input parameters:
//
// xmin : X origin coordinate in WC space.
// xmax : X end axis coordinate in WC space.
// ymin : Y origin coordinate in WC space.
// ymax : Y end axis coordinate in WC space.
// wmin : Lowest value for the tick mark
// labels written on the axis.
// wmax : Highest value for the tick mark labels
// written on the axis.
// ndiv : Number of divisions.
//
// ndiv=N1 + 100*N2 + 10000*N3
// N1=number of 1st divisions.
// N2=number of 2nd divisions.
// N3=number of 3rd divisions.
// e.g.:
// nndi=0 --> no tick marks.
// nndi=2 --> 2 divisions, one tick mark in the middle
// of the axis.
//
// chopt : Options (see below).
//
// chopt='G': loGarithmic scale, default is linear.
// chopt='B': Blank axis. Useful to superpose axis.
//
// Orientation of tick marks on axis.
// ----------------------------------
//
// Tick marks are normally drawn on the positive side of the axis,
// however, if X0=X1, then negative.
//
// chopt='+': tick marks are drawn on Positive side. (default)
// chopt='-': tick mark are drawn on the negative side.
// i.e: '+-' --> tick marks are drawn on both sides of the axis.
// chopt='U': Unlabeled axis, default is labeled.
//
// Size of tick marks
// ------------------
// By default, tick marks have a length equal to 3 per cent of the
// axis length.
// When the option "S" is specified, the length of the tick marks
// is equal to fTickSize*axis_length, where fTickSize may be set
// via TGaxis::SetTickSize.
//
// Position of labels on axis.
// ---------------------------
//
// Labels are normally drawn on side opposite to tick marks.
// However:
//
// chopt='=': on Equal side
//
// Orientation of labels on axis.
// ------------------------------
//
// Labels are normally drawn parallel to the axis.
// However if X0=X1, then Orthogonal
// if Y0=Y1, then Parallel
//
// Position of labels on tick marks.
// ---------------------------------
//
// Labels are centered on tick marks.
// However , if X0=X1, then they are right adjusted.
//
// chopt='R': labels are Right adjusted on tick mark.
// (default is centered)
// chopt='L': labels are Left adjusted on tick mark.
// chopt='C': labels are Centered on tick mark.
// chopt='M': In the Middle of the divisions.
//
// Format of labels.
// -----------------
//
// Blank characters are stripped, and then the
// label is correctly aligned. the dot, if last
// character of the string, is also stripped.
//
// In the following, we have some parameters, like
// tick marks length and characters height (in percentage
// of the length of the axis (WC))
// The default values are as follows:
//
// Primary tick marks: 3.0 %
// Secondary tick marks: 1.5 %
// Third order tick marks: .75 %
// Characters height for labels: 4%
//
// Labels offset: 1.0 %
//
// Optional grid.
// --------------
//
// chopt='W': cross-Wire
//
// Axis bining optimization.
// -------------------------
//
// By default the axis bining is optimized .
//
// chopt='N': No bining optimization
// chopt='I': Integer labelling
//
//
// Time representation.
// --------------------
//
// Axis labels may be considered as times, plotted in
// a defined time format. The format id set with SetTimeFormat().
//
// chopt='t': Plot times with a defined format instead of values
//
static const char *where = "PaintAxis";
Double_t alfa, beta, ratio1, ratio2, grid_side;
Double_t axis_lengthN = 0;
Double_t axis_length0 = 0;
Double_t axis_length1 = 0;
Double_t axis_length;
Double_t atick[3];
Double_t tick_side, label_side;
Double_t charheight;
Double_t phil, phi, sinphi, cosphi, asinphi, acosphi;
Double_t BinLow, BinLow2, BinLow3;
Double_t BinHigh, BinHigh2, BinHigh3;
Double_t BinWidth, BinWidth2, BinWidth3;
Double_t textsize;
Double_t xpl1, xpl2, ypl1, ypl2;
Double_t Xtick = 0;
Double_t Xtick0, Xtick1, DXtick;
Double_t Ytick, Ytick0, Ytick1;
Double_t Wlabel, DWlabel;
Double_t Xfactor, Yfactor;
Double_t Xlabel, Ylabel, DXlabel;
Double_t Xone, Xtwo;
Double_t rlab;
Double_t X0, X1, Y0, Y1, XX0, XX1, YY0, YY1;
XX0 = XX1 = YY0 = YY1 = 0;
Double_t Xxmin, Xxmax, Yymin, Yymax;
Xxmin = Xxmax = Yymin = Yymax = 0;
Double_t XLside, XMside;
Double_t WW, AF, RNE;
Double_t XX, YY;
Double_t XexpT = 0;
Double_t YexpT = 0;
Double_t XMNLOG, X00, X11, H2, H2SAV, AXMUL, Y, SMALD;
Float_t chupxvsav, chupyvsav;
Double_t rtxw, rtyw;
Int_t Nlabels, Nticks, Nticks0, Nticks1;
Int_t i, j, k, l, decade, ltick;
Int_t Mside, Lside;
Int_t NEXE = 0;
Int_t LNLEN = 0;
Int_t IEXE, IF1, IF2, NA, NF, IH1, IH2, NBININ, NCH, KMOD;
Int_t OptionLog,OptionBlank,OptionVert,OptionPlus,OptionMinus,OptionUnlab,OptionPara;
Int_t OptionDown,OptionRight,OptionLeft,OptionCent,OptionEqual,OptionDot;
Int_t OptionY,OptionText,OptionGrid,OptionSize,OptionNoopt,OptionInt,OptionM,OptionUp,OptionX;
Int_t OptionTime;
Int_t first,last,labelnumber;
Int_t Xalign, Yalign;
Int_t N, NN1, NN2, NN3, N1A, N2A, N3A, NB2, NB3;
Int_t nbins, N1Aold, NN1old;
N1Aold = NN1old = 0;
Int_t ndyn;
Int_t NHILAB = 0;
Int_t IDN;
Bool_t FLEXE = 0;
Bool_t FLEXPO,FLEXNE, LogInteger;
char *LABEL;
char *CHTEMP;
char *CODED;
static char CHLABEL[32];
static char kCHTEMP[36];
static char CHCODED[8];
TLine *linegrid;
TString timeformat;
time_t timelabel;
Double_t timed, wTimeIni;
struct tm* utctis;
const Int_t precision = 5;
Double_t epsilon = 0.00001;
const Double_t kPI=3.141592;
//*-*-______________________________________
Double_t rwmi = wmin;
Double_t rwma = wmax;
CHTEMP = &kCHTEMP[0];
LABEL = &CHLABEL[0];
linegrid = 0;
fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());
//*-*- the following parameters correspond to the pad range in NDC
//*-*- and the WC coordinates in the pad
Double_t padh = gPad->GetWh()*gPad->GetAbsHNDC();
Double_t padw = gPad->GetWw()*gPad->GetAbsWNDC();
Double_t RWxmin = gPad->GetX1();
Double_t RWxmax = gPad->GetX2();
Double_t RWymin = gPad->GetY1();
Double_t RWymax = gPad->GetY2();
if(strchr(chopt,'G')) OptionLog = 1; else OptionLog = 0;
if(strchr(chopt,'B')) OptionBlank= 1; else OptionBlank= 0;
if(strchr(chopt,'V')) OptionVert = 1; else OptionVert = 0;
if(strchr(chopt,'+')) OptionPlus = 1; else OptionPlus = 0;
if(strchr(chopt,'-')) OptionMinus= 1; else OptionMinus= 0;
if(strchr(chopt,'U')) OptionUnlab= 1; else OptionUnlab= 0;
if(strchr(chopt,'P')) OptionPara = 1; else OptionPara = 0;
if(strchr(chopt,'O')) OptionDown = 1; else OptionDown = 0;
if(strchr(chopt,'R')) OptionRight= 1; else OptionRight= 0;
if(strchr(chopt,'L')) OptionLeft = 1; else OptionLeft = 0;
if(strchr(chopt,'C')) OptionCent = 1; else OptionCent = 0;
if(strchr(chopt,'=')) OptionEqual= 1; else OptionEqual= 0;
if(strchr(chopt,'.')) OptionDot = 1; else OptionDot = 0;
if(strchr(chopt,'Y')) OptionY = 1; else OptionY = 0;
if(strchr(chopt,'T')) OptionText = 1; else OptionText = 0;
if(strchr(chopt,'W')) OptionGrid = 1; else OptionGrid = 0;
if(strchr(chopt,'S')) OptionSize = 1; else OptionSize = 0;
if(strchr(chopt,'N')) OptionNoopt= 1; else OptionNoopt= 0;
if(strchr(chopt,'I')) OptionInt = 1; else OptionInt = 0;
if(strchr(chopt,'M')) OptionM = 1; else OptionM = 0;
if(strchr(chopt,'0')) OptionUp = 1; else OptionUp = 0;
if(strchr(chopt,'X')) OptionX = 1; else OptionX = 0;
if(strchr(chopt,'t')) OptionTime = 1; else OptionTime = 0;
//*-*- Set the grid length
if (OptionGrid) {
if (gridlength == 0) gridlength = 0.8;
linegrid = new TLine();
linegrid->SetLineColor(GetLineColor());
linegrid->SetLineStyle(3);
linegrid->SetLineWidth(1);
}
//*-*- Determine time format
timeformat = fTimeFormat;
// correct for time offset not being integer
if (OptionTime) {
wmin += gStyle->GetTimeOffset() - (int)(gStyle->GetTimeOffset());
wmax += gStyle->GetTimeOffset() - (int)(gStyle->GetTimeOffset());
}
//*-*- Determine number of divisions 1, 2 and 3
N = ndiv;
N3A = N/10000;
N = N-N3A*10000;
N2A = N/100;
N1A = N-N2A*100;
NN3 = TMath::Max(N3A,1);
NN2 = TMath::Max(N2A,1)*NN3;
NN1 = TMath::Max(N1A,1)*NN2+1;
Nticks= NN1;
//*-*- Axis bining optimization is ignored if:
//*-*- - the first and the last label are equal
//*-*- - the number of divisions is 0
//*-*- - less than 1 primary division is requested
//*-*- - logarithmic scale is requested
if (wmin == wmax || ndiv == 0 || N1A <= 1 || OptionLog) {
OptionNoopt = 1;
OptionInt = 0;
}
//*-*- Axis bining optimization
if ( (wmax-wmin) < 1 && OptionInt) {
Error(where, "option I not available");
OptionInt = 0;
}
if (!OptionNoopt || OptionInt ) {
//*-*- Primary divisions optimization
//*-*- When integer labelling is required, Optimize is invoked first
//*-*- and only if the result is not an integer labelling, AdjustBinSize is invoked.
Optimize(wmin,wmax,N1A,BinLow,BinHigh,nbins,BinWidth);
if (OptionInt) {
if (BinLow != Double_t(int(BinLow)) || BinWidth != Double_t(int(BinWidth))) {
AdjustBinSize(wmin,wmax,N1A,BinLow,BinHigh,nbins,BinWidth);
}
}
if ((wmin-BinLow) > epsilon) { BinLow += BinWidth; nbins--; }
if ((BinHigh-wmax) > epsilon) { BinHigh -= BinWidth; nbins--; }
if (TMath::Abs(xmax-xmin) <= epsilon) {
rtyw = (ymax-ymin)/(wmax-wmin);
Xxmin = xmin;
Xxmax = xmax;
Yymin = rtyw*(BinLow-wmin) + ymin;
Yymax = rtyw*(BinHigh-wmin) + ymin;
}
else {
rtxw = (xmax-xmin)/(wmax-wmin);
Xxmin = rtxw*(BinLow-wmin) + xmin;
Xxmax = rtxw*(BinHigh-wmin) + xmin;
if (ymax == ymin) {
Yymin = ymin;
Yymax = ymax;
}
else {
alfa = (ymax-ymin)/(xmax-xmin);
beta = (ymin*xmax-ymax*xmin)/(xmax-xmin);
Yymin = alfa*Xxmin + beta;
Yymax = alfa*Xxmax + beta;
}
}
if (!fFunction) {
wmin = BinLow;
wmax = BinHigh;
}
//*-*- Secondary divisions optimization
NB2 = N2A;
if (!OptionNoopt && N2A > 1 && BinWidth > 0) {
Optimize(wmin,wmin+BinWidth,N2A,BinLow2,BinHigh2,NB2,BinWidth2);
}
//*-*- Tertiary divisions optimization
NB3 = N3A;
if (!OptionNoopt && N3A > 1 && BinWidth2 > 0) {
Optimize(BinLow2,BinLow2+BinWidth2,N3A,BinLow3,BinHigh3,NB3,BinWidth3);
}
N1Aold = N1A;
NN1old = NN1;
N1A = nbins;
NN3 = TMath::Max(NB3,1);
NN2 = TMath::Max(NB2,1)*NN3;
NN1 = TMath::Max(N1A,1)*NN2+1;
Nticks = NN1;
}
//*-*- Coordinates are normalized
ratio1 = 1/(RWxmax-RWxmin);
ratio2 = 1/(RWymax-RWymin);
X0 = ratio1*(xmin-RWxmin);
X1 = ratio1*(xmax-RWxmin);
Y0 = ratio2*(ymin-RWymin);
Y1 = ratio2*(ymax-RWymin);
if (!OptionNoopt || OptionInt ) {
XX0 = ratio1*(Xxmin-RWxmin);
XX1 = ratio1*(Xxmax-RWxmin);
YY0 = ratio2*(Yymin-RWymin);
YY1 = ratio2*(Yymax-RWymin);
}
if ((X0 == X1) && (Y0 == Y1)) {
Error(where, "length of axis is 0");
return;
}
//*-*- Return wmin, wmax and the number of primary divisions
if (OptionX) {
ndiv = N1A;
return;
}
TLine *lineaxis = new TLine();
TLatex *textaxis = new TLatex();
lineaxis->SetLineColor(GetLineColor());
lineaxis->SetLineStyle(1);
lineaxis->SetLineWidth(gStyle->GetLineWidth());
textaxis->SetTextColor(GetTextColor());
textaxis->SetTextFont(GetTextFont());
if (!gPad->IsBatch()) {
gVirtualX->GetCharacterUp(chupxvsav, chupyvsav);
gVirtualX->SetClipOFF(gPad->GetCanvasID());
}
//*-*- Compute length of axis
axis_length = TMath::Sqrt((X1-X0)*(X1-X0)+(Y1-Y0)*(Y1-Y0));
if (axis_length == 0) {
Error(where, "length of axis is 0");
goto L210;
}
if (!OptionNoopt || OptionInt) {
axis_lengthN = TMath::Sqrt((XX1-XX0)*(XX1-XX0)+(YY1-YY0)*(YY1-YY0));
axis_length0 = TMath::Sqrt((XX0-X0)*(XX0-X0)+(YY0-Y0)*(YY0-Y0));
axis_length1 = TMath::Sqrt((X1-XX1)*(X1-XX1)+(Y1-YY1)*(Y1-YY1));
if (axis_lengthN < epsilon) {
OptionNoopt = 1;
OptionInt = 0;
wmin = rwmi;
wmax = rwma;
N1A = N1Aold;
NN1 = NN1old;
Nticks = NN1;
}
}
if (X0 == X1) {
phi = 0.5*kPI;
phil = phi;
} else {
phi = TMath::ATan2((Y1-Y0),(X1-X0));
Int_t px0 = gPad->UtoPixel(X0);
Int_t py0 = gPad->VtoPixel(Y0);
Int_t px1 = gPad->UtoPixel(X1);
Int_t py1 = gPad->VtoPixel(Y1);
if (X0 < X1) phil = TMath::ATan2(Double_t(py0-py1), Double_t(px1-px0));
else phil = TMath::ATan2(Double_t(py1-py0), Double_t(px0-px1));
}
cosphi = TMath::Cos(phi);
sinphi = TMath::Sin(phi);
acosphi = TMath::Abs(cosphi);
asinphi = TMath::Abs(sinphi);
if (acosphi <= epsilon) { acosphi = 0; cosphi = 0; }
if (asinphi <= epsilon) { asinphi = 0; sinphi = 0; }
//*-*- Mside positive, tick marks on positive side
//*-*- Mside negative, tick marks on negative side
//*-*- Mside zero, tick marks on both sides
//*-*- Default is positive except for vertical axis
Mside=1;
if (X0 == X1 && Y1 > Y0) Mside = -1;
if (OptionPlus) Mside = 1;
if (OptionMinus) Mside = -1;
if (OptionPlus && OptionMinus) Mside = 0;
Lside = -Mside;
if (OptionEqual) Lside = Mside;
if (OptionPlus && OptionMinus) {
Lside = -1;
if (OptionEqual) Lside=1;
}
XLside = Lside;
XMside = Mside;
//*-*- Tick marks size
if(XMside >= 0) tick_side = 1;
else tick_side = -1;
if (OptionSize) atick[0] = tick_side*axis_length*fTickSize;
else atick[0] = tick_side*axis_length*0.03;
atick[1] = 0.5*atick[0];
atick[2] = 0.5*atick[1];
//*-*- Set the side of the grid
if ((X0 == X1) && (Y1 > Y0)) grid_side =-1;
else grid_side = 1;
//*-*- Compute Values if Function is given
if(fFunction) {
rwmi = fFunction->Eval(wmin);
rwma = fFunction->Eval(wmax);
if(rwmi > rwma) {
Double_t t = rwma;
rwma = rwmi;
rwmi = t;
}
}
//*-*- Draw the axis if needed...
if (!OptionBlank) {
xpl1 = X0;
xpl2 = X1;
ypl1 = Y0;
ypl2 = Y1;
lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
}
//*-*- No bining
if (ndiv == 0)goto L210;
if (wmin == wmax) {
Error(where, "wmin (%f) == wmax (%f)", wmin, wmax);
goto L210;
}
//*-*- Draw axis title if it exists
if (strlen(GetTitle())) {
charheight = GetTitleSize();
textaxis->SetTextSize (charheight);
Double_t toffset = GetTitleOffset();
if (toffset < 0.1) toffset = 1;
if (X1 == X0) Ylabel = XLside*1.6*charheight*toffset;
else Ylabel = XLside*1.3*charheight*toffset;
if (Y1 == Y0) Ylabel = XLside*1.6*charheight*toffset;
Double_t axispos;
if (TestBit(kCenterTitle)) axispos = 0.5*axis_length;
else axispos = axis_length;
if (TestBit(kRotateTitle)) {
if (X1 >= X0) {
if (TestBit(kCenterTitle)) textaxis->SetTextAlign(22);
else textaxis->SetTextAlign(12);
Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
} else {
if (TestBit(kCenterTitle)) textaxis->SetTextAlign(22);
else textaxis->SetTextAlign(32);
Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
}
textaxis->PaintLatex(gPad->GetX1() + xpl1*(gPad->GetX2() - gPad->GetX1()),
gPad->GetY1() + ypl1*(gPad->GetY2() - gPad->GetY1()),
phil=(kPI+phil)*180/kPI,
charheight,
GetTitle());
} else {
if (X1 >= X0) {
if (TestBit(kCenterTitle)) textaxis->SetTextAlign(22);
else textaxis->SetTextAlign(32);
Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
} else {
if (TestBit(kCenterTitle)) textaxis->SetTextAlign(22);
else textaxis->SetTextAlign(12);
Rotate(axispos,Ylabel,cosphi,sinphi,X0,Y0,xpl1,ypl1);
}
textaxis->PaintLatex(gPad->GetX1() + xpl1*(gPad->GetX2() - gPad->GetX1()),
gPad->GetY1() + ypl1*(gPad->GetY2() - gPad->GetY1()),
phil*180/kPI,
charheight,
GetTitle());
}
}
//*-*- Labels preparation:
//*-*- Get character height
//*-*- Compute the labels orientation in case of overlaps
//*-*- (with alphanumeric labels for horizontal axis).
charheight = GetLabelSize();
textaxis->SetTextFont(GetLabelFont());
textaxis->SetTextColor(GetLabelColor());
textaxis->SetTextSize (charheight);
textaxis->SetTextAngle(GetTextAngle());
if (!OptionUp && !OptionDown && !OptionY) {
if (OptionText && ymin == ymax) {
NHILAB = 0;
Double_t binwdh = 0.9*(axis_length/Double_t(N1A));
textsize = 0;
for (i=0; i<NHILAB; i++) {
// CALL IGTEXT(0,0,HILabs(I),charheight,textsize,'S');
if (textsize > binwdh) {
OptionUp = 1;
OptionRight= 1;
OptionCent = 0;
OptionLeft = 0;
break;
}
}
}
}
//*-*- Now determine orientation of labels on axis
if (!gPad->IsBatch()) {
if (cosphi > 0) gVirtualX->SetCharacterUp(-sinphi,cosphi);
else gVirtualX->SetCharacterUp(sinphi,-cosphi);
if (X0 == X1) gVirtualX->SetCharacterUp(0,1);
if (OptionVert) gVirtualX->SetCharacterUp(0,1);
if (OptionPara) gVirtualX->SetCharacterUp(-sinphi,cosphi);
if (OptionDown) gVirtualX->SetCharacterUp(cosphi,sinphi);
}
//*-*- Now determine text alignment
Xalign = 2;
Yalign = 1;
if (X0 == X1) Xalign = 3;
if (Y0 != Y1) Yalign = 2;
if (OptionCent) Xalign = 2;
if (OptionRight) Xalign = 3;
if (OptionLeft) Xalign = 1;
if (TMath::Abs(cosphi) > 0.9) {
Xalign = 2;
} else {
if (cosphi*sinphi > 0) Xalign = 1;
if (cosphi*sinphi < 0) Xalign = 3;
}
textaxis->SetTextAlign(10*Xalign+Yalign);
//*-*- Position of labels in Y
if(XLside >= 0) label_side = 1;
else label_side = -1;
Ylabel = label_side*fLabelOffset;
//*-*- Draw the linear tick marks if needed...
if (!OptionLog) {
if (ndiv) {
if (fFunction) {
if (OptionNoopt && !OptionInt) {
DXtick=(BinHigh-BinLow)/Double_t(Nticks-1);
} else {
DXtick=(BinHigh-BinLow)/Double_t(Nticks-1);
}
} else {
if (OptionNoopt && !OptionInt) DXtick=axis_length/Double_t(Nticks-1);
else DXtick=axis_lengthN/Double_t(Nticks-1);
}
for (k=0;k<Nticks; k++) {
ltick = 2;
if (k%NN3 == 0) ltick = 1;
if (k%NN2 == 0) ltick = 0;
if (fFunction) {
Xtick = (fFunction->Eval(BinLow+Double_t(k)*DXtick)-rwmi)* axis_length / TMath::Abs(rwma-rwmi);
} else {
Xtick = Double_t(k)*DXtick;
}
Ytick = 0;
if (!Mside) Ytick -= atick[ltick];
if ( OptionNoopt && !OptionInt) {
Rotate(Xtick,Ytick,cosphi,sinphi,X0,Y0,xpl2,ypl2);
Rotate(Xtick,atick[ltick],cosphi,sinphi,X0,Y0,xpl1,ypl1);
}
else {
Rotate(Xtick,Ytick,cosphi,sinphi,XX0,YY0,xpl2,ypl2);
Rotate(Xtick,atick[ltick],cosphi,sinphi,XX0,YY0,xpl1,ypl1);
}
if (OptionVert) {
if ((X0 != X1) && (Y0 != Y1)) {
if (Mside) {
xpl1 = xpl2;
if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
else ypl1 = ypl2 - atick[ltick];
}
else {
xpl1 = 0.5*(xpl1 + xpl2);
xpl2 = xpl1;
ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
}
}
}
lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
if (OptionGrid) {
if (ltick == 0) {
if (OptionNoopt && !OptionInt) {
Rotate(Xtick,0,cosphi,sinphi,X0,Y0 ,xpl2,ypl2);
Rotate(Xtick,grid_side*gridlength ,cosphi,sinphi,X0,Y0 ,xpl1,ypl1);
}
else {
Rotate(Xtick,0,cosphi ,sinphi,XX0,YY0 ,xpl2,ypl2);
Rotate(Xtick,grid_side*gridlength ,cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
}
linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
}
}
}
Xtick0 = 0;
Xtick1 = Xtick;
if ((!OptionNoopt || OptionInt) && axis_length0) {
if (fFunction) Nticks0 = Int_t((BinLow-wmin)/DXtick);
else Nticks0 = Int_t(axis_length0/DXtick);
if (Nticks0 > 1000) Nticks0 = 1000;
for (k=0; k<=Nticks0; k++) {
ltick = 2;
if (k%NN3 == 0) ltick = 1;
if (k%NN2 == 0) ltick = 0;
Ytick0 = 0;
if (!Mside) Ytick0 -= atick[ltick];
if (fFunction) {
Xtick0 = (fFunction->Eval(BinLow - Double_t(k)*DXtick)-rwmi)
* axis_length / TMath::Abs(rwma-rwmi);
}
Rotate(Xtick0,Ytick0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
Rotate(Xtick0,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
if (OptionVert) {
if ((X0 != X1) && (Y0 != Y1)) {
if (Mside) {
xpl1 = xpl2;
if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
else ypl1 = ypl2 - atick[ltick];
}
else {
xpl1 = 0.5*(xpl1 + xpl2);
xpl2 = xpl1;
ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
}
}
}
lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
if (OptionGrid) {
if (ltick == 0) {
Rotate(Xtick0,0,cosphi,sinphi,XX0,YY0,xpl2,ypl2);
Rotate(Xtick0,grid_side*gridlength ,cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
}
}
Xtick0 -= DXtick;
}
}
if ((!OptionNoopt || OptionInt) && axis_length1) {
if (fFunction) Nticks1 = int((wmax-BinHigh)/DXtick);
else Nticks1 = int(axis_length1/DXtick);
if (Nticks1 > 1000) Nticks1 = 1000;
for (k=0; k<=Nticks1; k++) {
ltick = 2;
if (k%NN3 == 0) ltick = 1;
if (k%NN2 == 0) ltick = 0;
Ytick1 = 0;
if (!Mside) Ytick1 -= atick[ltick];
if (fFunction) {
Xtick1 = (fFunction->Eval(BinHigh + Double_t(k)*DXtick)-rwmi)
* axis_length / TMath::Abs(rwma-rwmi);
}
Rotate(Xtick1,Ytick1,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
Rotate(Xtick1,atick[ltick],cosphi,sinphi,XX0,YY0 ,xpl1,ypl1);
if (OptionVert) {
if ((X0 != X1) && (Y0 != Y1)) {
if (Mside) {
xpl1 = xpl2;
if (cosphi > 0) ypl1 = ypl2 + atick[ltick];
else ypl1 = ypl2 - atick[ltick];
}
else {
xpl1 = 0.5*(xpl1 + xpl2);
xpl2 = xpl1;
ypl1 = 0.5*(ypl1 + ypl2) + atick[ltick];
ypl2 = 0.5*(ypl1 + ypl2) - atick[ltick];
}
}
}
lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
if (OptionGrid) {
if (ltick == 0) {
Rotate(Xtick1,0,cosphi,sinphi,XX0,YY0 ,xpl2,ypl2);
Rotate(Xtick1,grid_side*gridlength,cosphi,sinphi,XX0,YY0,xpl1,ypl1);
linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
}
}
Xtick1 += DXtick;
}
}
}
}
//*-*- Draw the numeric labels if needed...
if (!OptionUnlab) {
if (!OptionLog) {
if (N1A) {
//*-*- Spacing of labels
if ((wmin == wmax) || (ndiv == 0)) {
Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
goto L210;
}
Wlabel = wmin;
DWlabel = (wmax-wmin)/Double_t(N1A);
if (OptionNoopt && !OptionInt) DXlabel = axis_length/Double_t(N1A);
else DXlabel = axis_lengthN/Double_t(N1A);
if (!OptionText && !OptionTime) {
//*-*- Here we have to decide what format to generate
//*-*- (for numeric labels only)
//*-*- Test the magnitude, decide format
FLEXE = kFALSE;
NEXE = 0;
FLEXPO = kFALSE;
FLEXNE = kFALSE;
WW = TMath::Max(TMath::Abs(wmin),TMath::Abs(wmax));
//*-*- First case : (wmax-wmin)/N1A less than 0.001
//*-*- (0.001 precision of 5 (precision) characters). Then we use x 10 n
//*-*- format. If AF >=0 x10 n cannot be used
if ((TMath::Abs(wmax-wmin)/Double_t(N1A)) < 0.00099) {
AF = TMath::Log10(WW) + epsilon;
if (AF < 0) {
FLEXE = kTRUE;
NEXE = int(AF);
IEXE = TMath::Abs(NEXE);
Wlabel = Wlabel*TMath::Power(10,IEXE);
DWlabel = DWlabel*TMath::Power(10,IEXE);
IF1 = precision;
IF2 = precision-2;
goto L110;
}
}
if (WW >= 1) AF = TMath::Log10(WW);
else AF = TMath::Log10(WW*0.0001);
AF += epsilon;
NF = Int_t(AF)+1;
if (NF > precision) FLEXPO = kTRUE;
if (NF < -precision) FLEXNE = kTRUE;
//*-*- Use x 10 n format.
if (FLEXPO) {
FLEXE = kTRUE;
while ( WW > TMath::Power(10,precision-1)) {
NEXE++;
WW /= 10;
Wlabel /= 10;
DWlabel /= 10;
}
}
if (FLEXNE) {
FLEXE = kTRUE;
RNE = 1/TMath::Power(10,precision-2);
while (WW < RNE) {
NEXE--;
WW *= 10;
Wlabel *= 10;
DWlabel *= 10;
}
}
NA = 0;
for (i=precision-1; i>0; i--) {
if (TMath::Abs(WW) < TMath::Power(10,i)) NA = precision-i;
}
ndyn = N1A;
while (ndyn) {
Double_t wdyn = TMath::Abs((wmax-wmin)/ndyn);
if (wdyn <= 0.999 && NA < precision-2) {
NA++;
ndyn /= 10;
}
else break;
}
IF2 = NA;
IF1 = TMath::Max(NF+NA,precision)+1;
L110:
if (TMath::Min(wmin,wmax) < 0)IF1 = IF1+1;
IF1 = TMath::Min(IF1,32);
//*-*- In some cases, IF1 and IF2 are too small....
while (DWlabel < TMath::Power(10,-IF2)) {
IF1++;
IF2++;
}
CODED = &CHCODED[0];
if (IF1 > 15) IF1=15;
if (IF2 > 15) IF2=15;
if (IF2) sprintf(CODED,"%%%d.%df",IF1,IF2);
else sprintf(CODED,"%%%d.%df",IF1+1,1);
}
//*-*- Here we draw labels
if (OptionM) Nlabels = N1A-1;
else Nlabels = N1A;
wTimeIni = Wlabel;
for ( k=0; k<=Nlabels; k++) {
if (fFunction) {
Xlabel = (fFunction->Eval(Wlabel)-rwmi)
* axis_length / TMath::Abs(rwma-rwmi);
} else {
Xlabel = DXlabel*k;
}
if (OptionM) Xlabel += 0.5*DXlabel;
if (!OptionText && !OptionTime) {
sprintf(LABEL,&CHCODED[0],Wlabel);
Wlabel += DWlabel;
LabelsLimits(LABEL,first,last); //Eliminate blanks
if (LABEL[first] == '.') { //check if '.' is preceeded by a digit
strcpy(CHTEMP, "0");
strcat(CHTEMP, &LABEL[first]);
strcpy(LABEL, CHTEMP);
first = 1; last = strlen(LABEL);
}
if (LABEL[first] == '-' && LABEL[first+1] == '.') {
strcpy(CHTEMP, "-0");
strcat(CHTEMP, &LABEL[first+1]);
strcpy(LABEL, CHTEMP);
first = 1; last = strlen(LABEL);
}
//*-*- Here we eliminate the non significiant 0 after '.'
while (LABEL[last] == '0') {
LABEL[last] = 0; last--;
}
//*-*- Here we eliminate the dot, unless dot is forced.
if (LABEL[last] == '.') {
if (!OptionDot) { LABEL[last] = 0; last--;}
}
}
//*-*- Generate the time labels
if (OptionTime) {
timed = Wlabel + (int)(gStyle->GetTimeOffset());
timelabel = (time_t)((Long_t)(timed));
utctis = gmtime(&timelabel);
strftime(LABEL,36,timeformat.Data(),utctis);
first = 0; last=strlen(LABEL)-1;
//*-*- Appends fractionnal part if seconds displayed
if (DWlabel<0.9) {
double tmpdb;
int tmplast, tmpfirst;
strcpy(CHTEMP,&LABEL[first]);
sprintf(LABEL,"%7.5f",modf(timed,&tmpdb));
tmplast = strlen(LABEL)-1;
//*-*- Here we eliminate the non significiant 0 after '.'
while (LABEL[tmplast] == '0') {
LABEL[tmplast] = 0; tmplast--;
}
//*-*- replace the "0." at the begining by "s"
if (CHTEMP[strlen(CHTEMP)-1] == 's' || CHTEMP[strlen(CHTEMP)-1] == 'S') {
tmpfirst = 2;
} else {
tmpfirst = 1;
LABEL[tmpfirst] = 's';
}
strcat(CHTEMP, &LABEL[tmpfirst]);
strcpy(LABEL, CHTEMP);
first = 0; last = strlen(LABEL)-1;
}
Wlabel = wTimeIni + (k+1)*DWlabel;
}
//*-*- Here we generate labels (numeric or alphanumeric).
if (OptionNoopt && !OptionInt)
Rotate (Xlabel,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
else Rotate (Xlabel,Ylabel,cosphi,sinphi,XX0,YY0,XX,YY);
if (Y0 == Y1 && !OptionDown && !OptionUp) {
if (Lside < 0) YY -= charheight;
}
if (OptionVert) {
if (X0 != X1 && Y0 != Y1) {
if (OptionNoopt && !OptionInt)
Rotate (Xlabel,0,cosphi,sinphi,X0,Y0,XX,YY);
else Rotate (Xlabel,0,cosphi,sinphi,XX0,YY0,XX,YY);
if (cosphi > 0 ) YY += Ylabel;
if (cosphi < 0 ) YY -= Ylabel;
}
}
if (!OptionY || (X0 == X1)) {
if (!OptionText) {
if (first > last) strcpy(CHTEMP, " ");
else strcpy(CHTEMP, &LABEL[first]);
textaxis->PaintTextNDC(XX,YY,CHTEMP);
}
else {
// if (k+1 > NHILAB) strcpy(CHTEMP, " ");
// else strcpy(CHTEMP, HILabs(k));
textaxis->PaintTextNDC(XX,YY,CHTEMP);
}
}
else {
//*-*- Text alignment is down
if (!OptionText) LNLEN = last-first+1;
else {
if (k+1 > NHILAB) LNLEN = 0;
// else LNLEN = strlen(HILabs(k));
}
for ( l=1; l<=LNLEN; l++) {
if (!OptionText) *CHTEMP = LABEL[first+l-2];
else {
if (LNLEN == 0) strcpy(CHTEMP, " ");
// else strcpy(CHTEMP, HILabs(k)(l:l));
else strcpy(CHTEMP, "1");
}
textaxis->PaintTextNDC(XX,YY,CHTEMP);
YY -= charheight*1.3;
}
}
}
//*-*- Here we use the format x 10 ** n
if (FLEXE && !OptionText && NEXE) {
sprintf(LABEL,"x10^{%d}", NEXE);
if (X0 != X1) { Xfactor = X1-X0+0.1*charheight; Yfactor = 0; }
else { Xfactor = Y1-Y0+0.1*charheight; Yfactor = 0; }
Rotate (Xfactor,Yfactor,cosphi,sinphi,X0,Y0,XX,YY);
textaxis->SetTextAlign(11);
textaxis->PaintLatex(gPad->GetX1() + XX*(gPad->GetX2() - gPad->GetX1()),
gPad->GetY1() + YY*(gPad->GetY2() - gPad->GetY1()),
0,
charheight,
LABEL);
}
}
}
}
//*-*- Log axis
if (OptionLog && ndiv) {
if ((wmin == wmax) || (ndiv == 0)) {
Error(where, "wmin (%f) == wmax (%f), or ndiv == 0", wmin, wmax);
goto L210;
}
if (wmin <= 0) {
Error(where, "negative logarithmic axis");
goto L210;
}
if (wmax <= 0) {
Error(where, "negative logarithmic axis");
goto L210;
}
XMNLOG = TMath::Log10(wmin);
if (XMNLOG > 0) XMNLOG += 1.E-6;
else XMNLOG -= 1.E-6;
X00 = 0;
X11 = axis_length;
H2 = TMath::Log10(wmax);
H2SAV = H2;
if (H2 > 0) H2 += 1.E-6;
else H2 -= 1.E-6;
IH1 = int(XMNLOG);
IH2 = 1+int(H2);
NBININ = IH2-IH1+1;
AXMUL = (X11-X00)/(H2SAV-XMNLOG);
//*-*- If:
//*-*- a) The number of decades is less than two.
//*-*- b) and 1 =< wmin and wmax =<10000
//*-*- c) and there is no labels overlap.
//*-*- then some intermediate label is drawn (LogInteger=kTRUE).
LogInteger = kFALSE;
if (TMath::Log10(wmax/wmin) < 2 && wmin >= 1 && wmax <= 10000) LogInteger = kTRUE;
SMALD = (TMath::Log10(1./0.9)/TMath::Log10(wmax/wmin))*axis_length;
if (xmin == xmax && SMALD <= charheight) LogInteger = kFALSE;
if (ymin == ymax) {
textsize = 0;
// CALL IGTEXT(0.,0.,"0.01",charheight,textsize,'S');
if (0.5*textsize > SMALD) LogInteger = kFALSE;
}
//*-*- Plot decade and intermediate tick marks
decade = IH1-2;
labelnumber = IH1;
if ( XMNLOG > 0 && (XMNLOG-Double_t(IH1) > 0) ) labelnumber++;
for (j=1; j<=NBININ; j++) {
//*-*- Plot decade
decade++;
if (X0 == X1 && j == 1) Ylabel += charheight*0.33;
if (Y0 == Y1 && j == 1) Ylabel -= charheight*0.65;
Xone = X00+AXMUL*(Double_t(decade)-XMNLOG);
if (X00 > Xone) goto L160;
if (Xone > X11) break;
Xtwo = Xone;
Y = 0;
if (!Mside) Y -= atick[0];
Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2);
Rotate(Xtwo,atick[0],cosphi,sinphi,X0,Y0,xpl1,ypl1);
if (OptionVert) {
if ((X0 != X1) && (Y0 != Y1)) {
if (Mside) {
xpl1=xpl2;
if (cosphi > 0) ypl1 = ypl2 + atick[0];
else ypl1 = ypl2 - atick[0];
}
else {
xpl1 = 0.5*(xpl1 + xpl2);
xpl2 = xpl1;
ypl1 = 0.5*(ypl1 + ypl2) + atick[0];
ypl2 = 0.5*(ypl1 + ypl2) - atick[0];
}
}
}
lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
if (OptionGrid) {
Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2,ypl2);
Rotate(Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0,xpl1,ypl1);
linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
}
if (!OptionUnlab) {
//*-*- Here we generate labels (numeric only).
if (LogInteger) {
rlab = TMath::Power(10,labelnumber);
sprintf(LABEL, "%d", Int_t(rlab));
LabelsLimits(LABEL,first,last);
if (LABEL[last] == '.') {LABEL[last] = 0; last--;}
}
else {
sprintf(LABEL, "%d", labelnumber);
LabelsLimits(LABEL,first,last);
}
Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
if ((X0 == X1) && !OptionPara) {
if (Lside < 0) {
if (Mside < 0) {
if (labelnumber == 0) NCH=1;
else NCH=2;
XX += NCH*charheight;
} else {
if (labelnumber >= 0) XX += 0.25*charheight;
else XX += 0.50*charheight;
}
}
}
if ((Y0 == Y1) && !OptionDown && !OptionUp) {
if (Lside < 0) YY -= charheight;
}
if (N1A == 0)goto L210;
KMOD = NBININ/N1A;
if (KMOD == 0) KMOD=1000000;
if ((NBININ <= N1A) || (j == 1) || (j == NBININ) || ((NBININ > N1A)
&& (j%KMOD == 0))) {
if ((labelnumber != 0) && (labelnumber != 1)) {
if (LogInteger) {
textaxis->PaintTextNDC(XX,YY,&LABEL[first]);
}
else {
XX = XX-(last-first)*(charheight*0.25);
textaxis->PaintTextNDC(XX,YY,"10");
Double_t s10 = textaxis->GetTextSize();
textaxis->SetTextSize (0.6*s10);
Double_t pixels;
if (padw < padh) pixels = s10*padw;
else pixels = s10*padh;
Int_t alig = textaxis->GetTextAlign();
Int_t aligh = alig/10;
Int_t aligv = alig%10;
if (aligh == 1) XexpT = XX + 0.70*pixels/padw;
if (aligh == 2) XexpT = XX + 0.60*pixels/padw;
if (aligh == 3) XexpT = XX + 0.01*pixels/padw;
if (aligv == 1) YexpT = YY + 0.60*pixels/padh;
if (aligv == 2) YexpT = YY + 0.30*pixels/padh;
if (aligv == 3) YexpT = YY + 0.01*pixels/padh;
textaxis->SetTextAlign(11);
textaxis->PaintTextNDC(XexpT,YexpT,&LABEL[first]);
textaxis->SetTextSize (charheight);
textaxis->SetTextAlign(alig);
}
}
if (labelnumber == 0) textaxis->PaintTextNDC(XX,YY,"1");
if (labelnumber == 1) textaxis->PaintTextNDC(XX,YY,"10");
}
labelnumber++;
}
L160:
for (k=2;k<10;k++) {
//*-*- Plot intermediate tick marks
Xone = X00+AXMUL*(TMath::Log10(Double_t(k))+Double_t(decade)-XMNLOG);
if (X00 > Xone) continue;
if (Xone > X11) goto L200;
Y = 0;
if (!Mside) Y -= atick[1];
Xtwo = Xone;
Rotate(Xone,Y,cosphi,sinphi,X0,Y0,xpl2,ypl2);
Rotate(Xtwo,atick[1],cosphi,sinphi,X0,Y0,xpl1,ypl1);
if (OptionVert) {
if ((X0 != X1) && (Y0 != Y1)) {
if (Mside) {
xpl1 = xpl2;
if (cosphi > 0) ypl1 = ypl2 + atick[1];
else ypl1 = ypl2 - atick[1];
}
else {
xpl1 = 0.5*(xpl1+xpl2);
xpl2 = xpl1;
ypl1 = 0.5*(ypl1+ypl2) + atick[1];
ypl2 = 0.5*(ypl1+ypl2) - atick[1];
}
}
}
IDN = N1A*2;
if ((NBININ <= IDN) || ((NBININ > IDN) && (k == 5))) {
lineaxis->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
//*-*- Draw the intermediate LOG labels if requested
if (LogInteger && !OptionUnlab) {
rlab = Double_t(k)*TMath::Power(10,labelnumber-1);
sprintf(CHTEMP, "%d", Int_t(rlab));
LNLEN = strlen(CHTEMP);
if (CHTEMP[LNLEN-1] == '.') LNLEN--;
Rotate (Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
if ((X0 == X1) && !OptionPara) {
if (Lside < 0) {
if (labelnumber == 0) NCH=1;
else NCH=2;
XX += NCH*charheight;
}
}
if ((Y0 == Y1) && !OptionDown && !OptionUp) {
if (Lside < 0) YY -= charheight;
}
if (OptionVert) {
if ((X0 != X1) && (Y0 != Y1)) {
Rotate(Xone,Ylabel,cosphi,sinphi,X0,Y0,XX,YY);
if (cosphi > 0) YY += Ylabel;
else YY -= Ylabel;
}
}
if (CHTEMP[0] == '0') printf("len=%d, chtemp=%sn",strlen(CHTEMP),CHTEMP);
if (CHTEMP[0] != '0') textaxis->PaintTextNDC(XX,YY,CHTEMP);
}
//*-*- Draw the intermediate LOG grid if only three decades are requested
if (OptionGrid && NBININ <= 5) {
Rotate(Xone,0,cosphi,sinphi,X0,Y0,xpl2, ypl2);
Rotate(Xone,grid_side*gridlength,cosphi,sinphi,X0,Y0, xpl1,ypl1);
linegrid->PaintLineNDC(xpl1, ypl1, xpl2, ypl2);
}
} //endif ((NBININ <= IDN) ||
} //endfor (k=2;k<10;k++)
} //endfor (j=1; j<=NBININ; j++)
L200:
Int_t kuku=0; if (kuku) { }
} //endif (OptionLog && ndiv)
L210:
delete lineaxis;
delete linegrid;
delete textaxis;
}
//______________________________________________________________________________
void TGaxis::Optimize(Double_t A1, Double_t A2, Int_t nold
,Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BinWidth)
{
//*-*-*-*-*-*-*-*-*-*-*-*Reasonable Axis labels optimisation*-*-*-*-*-*-*-*-*
//*-* ===================================
//*-* Get reasonable values for tick marks & ensure they are
//*-* not plotted beyond allowed limits
//*-*
//*-* _Input parameters:
//*-*
//*-* A1,A2 : Old WMIN,WMAX .
//*-* BinLow,BinHigh : New WMIN,WMAX .
//*-* nold : Old NDIV .
//*-* nbins : New NDIV .
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Int_t lwid, kwid;
Int_t ntemp = 0;
Int_t jlog = 0;
Double_t siground = 0;
Double_t alb, awidth, sigfig;
Double_t timemulti = 1;
Int_t roundmode =0;
Int_t OptionTime;
if(strchr(fChopt.Data(),'t')) OptionTime = 1; else OptionTime = 0;
Double_t AL = TMath::Min(A1,A2);
Double_t AH = TMath::Max(A1,A2);
if (AL == AH) AH = AL+1;
//*-*- IF nold == -1 , program uses binwidth input from calling routine
if (nold == -1 && BinWidth > 0 ) goto L90;
ntemp = TMath::Max(nold,2);
if (ntemp < 1) ntemp = 1;
L20:
awidth = (AH-AL)/Double_t(ntemp);
if (awidth >= FLT_MAX) goto LOK; //in float.h
if (awidth <= 0) goto LOK;
//*-*- If time representation, bin width should be rounded to seconds
// minutes, hours or days
if (OptionTime && awidth>=60) { // if width in seconds, treat it as normal
// width in minutes
awidth /= 60; timemulti *=60;
roundmode = 1; // round minutes (60)
// width in hours ?
if (awidth>=60) {
awidth /= 60; timemulti *= 60;
roundmode = 2; // round hours (24)
// width in days ?
if (awidth>=24) {
awidth /= 24; timemulti *= 24;
roundmode = 3; // round days (30)
// width in months ?
if (awidth>=30.43685) { // Mean month length in 1900.
awidth /= 30.43685; timemulti *= 30.43685;
roundmode = 2; // round months (12)
// width in years ?
if (awidth>=12) {
awidth /= 12; timemulti *= 12;
roundmode = 0; // round years (10)
}
}
}
}
}
//*-*- Get nominal bin width in exponential form
jlog = Int_t(TMath::Log10(awidth));
if (jlog <-200 || jlog > 200) {
BinLow = 0;
BinHigh = 1;
BinWidth = 0.01;
nbins = 100;
return;
}
if (awidth <= 1 && (!OptionTime || timemulti==1) ) jlog--;
sigfig = awidth*TMath::Power(10,-jlog);
//*-*- Round mantissa
switch (roundmode) {
//*-*- Round mantissa up to 1, 1.5, 2, 3, or 6 in case of minutes
case 1: // case 60
if (sigfig <= 1) siground = 1;
else if (sigfig <= 1.5 && jlog==1) siground = 1.5;
else if (sigfig <= 2) siground = 2;
else if (sigfig <= 3 && jlog ==1) siground = 3;
else if (jlog==0) {siground = 1; jlog++;}
else siground = 6;
break;
case 2: // case 12 and 24
//*-*- Round mantissa up to 1, 1.2, 2, 2.4, 3 or 6 in case of hours or months
if (sigfig <= 1 && jlog==0) siground = 1;
else if (sigfig <= 1.2 && jlog==1) siground = 1.2;
else if (sigfig <= 2 && jlog==0) siground = 2;
else if (sigfig <= 2.4 && jlog==1) siground = 2.4;
else if (sigfig <= 3) siground = 3;
else if (sigfig <= 6) siground = 6;
else if (jlog==0) siground = 12;
else siground = 2.4;
break;
//*-*- Round mantissa up to 1, 1.4, 2, or 7 in case of days (weeks)
case 3: // case 30
if (sigfig <= 1 && jlog==0) siground = 1;
else if (sigfig <= 1.4 && jlog==1) siground = 1.4;
else if (sigfig <= 3 && jlog ==1) siground = 3;
else siground = 7;
break;
default :
//*-*- Round mantissa up to 1, 2, 2.5, 5, or 10 in case of decimal number
if (sigfig <= 1) siground = 1;
else if (sigfig <= 2) siground = 2;
// else if (sigfig <= 2.5) siground = 2.5;
else if (sigfig <= 5 && (!OptionTime || jlog<1)) siground = 5;
else if (sigfig <= 6 && OptionTime && jlog==1) siground = 6;
else {siground = 1; jlog++; }
break;
}
BinWidth = siground*TMath::Power(10,jlog);
if (OptionTime) BinWidth *= timemulti;
//*-*- Get new bounds from new width BinWidth
L90:
alb = AL/BinWidth;
lwid = Int_t(alb);
if (alb < 0) lwid--;
BinLow = BinWidth*Double_t(lwid);
alb = AH/BinWidth + 1.00001;
kwid = Int_t(alb);
if (alb < 0) kwid--;
BinHigh = BinWidth*Double_t(kwid);
nbins = kwid - lwid;
if (nold == -1) goto LOK;
if (nold <= 5) { //*-*- Request for one bin is difficult case
if (nold > 1 || nbins == 1)goto LOK;
BinWidth = BinWidth*2;
nbins = 1;
goto LOK;
}
if (2*nbins == nold) { ntemp++; goto L20; }
LOK:
Double_t oldBinLow = BinLow;
Double_t oldBinHigh = BinHigh;
Int_t oldnbins = nbins;
Double_t atest = BinWidth*0.0001;
if (TMath::Abs(BinLow-A1) >= atest) { BinLow += BinWidth; nbins--; }
if (TMath::Abs(BinHigh-A2) >= atest) { BinHigh -= BinWidth; nbins--; }
if (OptionTime && nbins==0) {
nbins = 2*oldnbins;
BinHigh = oldBinHigh;
BinLow = oldBinLow;
BinWidth = (oldBinHigh - oldBinLow)/nbins;
Double_t atest = BinWidth*0.0001;
if (TMath::Abs(BinLow-A1) >= atest) { BinLow += BinWidth; nbins--; }
if (TMath::Abs(BinHigh-A2) >= atest) { BinHigh -= BinWidth; nbins--; }
}
}
//______________________________________________________________________________
void TGaxis::AdjustBinSize(Double_t A1, Double_t A2, Int_t nold
,Double_t &BinLow, Double_t &BinHigh, Int_t &nbins, Double_t &BinWidth)
{
//*-*-*-*-*-*-*-*-*-*-*-*Axis labels optimisation*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ========================
//
// This routine adjusts the bining of the axis
// in order to have integer values for the labels
//
// _Input parameters:
//
// A1,A2 : Old WMIN,WMAX .
// BinLow,BinHigh : New WMIN,WMAX .
// nold : Old NDIV (primary divisions)
// nbins : New NDIV .
//
BinWidth = TMath::Abs(A2-A1)/Double_t(nold);
if (BinWidth <= 1) { BinWidth = 1; BinLow = int(A1); }
else {
Int_t width = int(BinWidth/5) + 1;
BinWidth = 5*width;
BinLow = int(A1/BinWidth)*BinWidth;
//*-*- We determine BinLow to have one tick mark at 0
//*-*- if there are negative labels.
if (A1 < 0) {
for (Int_t ic=0; ic<1000; ic++) {
Double_t rbl = BinLow/BinWidth;
Int_t ibl = int(BinLow/BinWidth);
if ( (rbl-ibl) == 0 || ic > width) { BinLow -= 5; break;}
}
}
}
BinHigh = int(A2);
nbins = 0;
Double_t XB = BinLow;
while (XB <= BinHigh) {
XB += BinWidth;
nbins++;
}
BinHigh = XB - BinWidth;
}
//______________________________________________________________________________
void TGaxis::LabelsLimits(char *label, Int_t &first, Int_t &last)
{
//*-*-*-*-*-*-*-*-*Find first and last character of a label*-*-*-*-*-*-*-*-*-*
//*-* ========================================
last = strlen(label)-1;
for (Int_t i=0; i<=last; i++) {
if (strchr("1234567890-+.", label[i]) ) { first = i; return; }
}
Error("LabelsLimits", "attempt to draw a blank label");
}
//______________________________________________________________________________
void TGaxis::Rotate(Double_t X, Double_t Y, Double_t CFI, Double_t SFI
,Double_t XT, Double_t YT, Double_t &U, Double_t &V)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*-*Rotate axis coordinates*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =======================
U = CFI*X-SFI*Y+XT;
V = SFI*X+CFI*Y+YT;
}
//______________________________________________________________________________
void TGaxis::SavePrimitive(ofstream &out, Option_t *)
{
// Save primitive as a C++ statement(s) on output stream out
char quote = '"';
if (gROOT->ClassSaved(TGaxis::Class())) {
out<<" ";
} else {
out<<" TGaxis *";
}
out<<"gaxis = new TGaxis("<<fX1<<","<<fY1<<","<<fX2<<","<<fY2
<<","<<fWmin<<","<<fWmax<<","<<fNdiv<<","<<quote<<fChopt.Data()<<quote<<");"<<endl;
out<<" gaxis->SetLabelOffset("<<GetLabelOffset()<<");"<<endl;
out<<" gaxis->SetLabelSize("<<GetLabelSize()<<");"<<endl;
out<<" gaxis->SetTickSize("<<GetTickSize()<<");"<<endl;
out<<" gaxis->SetGridLength("<<GetGridLength()<<");"<<endl;
out<<" gaxis->SetTitleOffset("<<GetTitleOffset()<<");"<<endl;
if (strlen(GetName())) {
out<<" gaxis->SetName("<<quote<<GetName()<<quote<<");"<<endl;
}
if (strlen(GetTitle())) {
out<<" gaxis->SetTitle("<<quote<<GetTitle()<<quote<<");"<<endl;
}
out<<" gaxis->Draw();"<<endl;
}
//______________________________________________________________________________
void TGaxis::SetFunction(const char *funcname)
{
// specify a function to map the axis values
// =========================================
fFunctionName = funcname;
if (strlen(funcname) == 0) {
fFunction = 0;
return;
}
fFunction = (TF1*)gROOT->GetFunction(funcname);
if (!fFunction) {
Error("SetFunction, Unknown function:%s",funcname);
} else {
fWmin = fFunction->GetXmin();
fWmax = fFunction->GetXmax();
}
}
//______________________________________________________________________________
void TGaxis::SetName(char *name)
{
//*-*-*-*-*-*-*-*-*-*-*Change the name of the axis*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ============================
fName = name;
}
//______________________________________________________________________________
void TGaxis::SetOption(Option_t *option)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*To set axis options*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ===================
fChopt = option;
}
//______________________________________________________________________________
void TGaxis::SetTitle(const char *title)
{
//*-*-*-*-*-*-*-*-*-*-*Change the title of the axis*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ============================
fTitle = title;
}
//______________________________________________________________________________
void TGaxis::SetTimeFormat(const char *tformat)
{
//*-*-*-*-*-*-*-*-*-*-*Change the format used for time plotting *-*-*-*-*-*-*-*
//*-* ========================================
// The format string for date and time use the same options as the one used
// in the standard strftime C function, i.e. :
// for date :
// %a abbreviated weekday name
// %b abbreviated month name
// %d day of the month (01-31)
// %m month (01-12)
// %y year without century
//
// for time :
// %H hour (24-hour clock)
// %I hour (12-hour clock)
// %p local equivalent of AM or PM
// %M minute (00-59)
// %S seconds (00-61)
// %% %
fTimeFormat = tformat;
}
//______________________________________________________________________________
void TGaxis::Streamer(TBuffer &R__b)
{
// Stream an object of class TGaxis.
UInt_t R__s, R__c;
if (R__b.IsReading()) {
Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
TLine::Streamer(R__b);
TAttText::Streamer(R__b);
R__b >> fNdiv;
R__b >> fWmin;
R__b >> fWmax;
R__b >> fGridLength;
R__b >> fTickSize;
R__b >> fLabelOffset;
R__b >> fLabelSize;
R__b >> fTitleOffset;
R__b >> fTitleSize;
R__b >> fLabelFont;
if (R__v > 2) {
R__b >> fLabelColor;
}
fChopt.Streamer(R__b);
fName.Streamer(R__b);
fTitle.Streamer(R__b);
fTimeFormat.Streamer(R__b);
if (R__v > 1) {
fFunctionName.Streamer(R__b);
fFunction = (TF1*)gROOT->GetFunction(fFunctionName.Data());
}
R__b.CheckByteCount(R__s, R__c, TGaxis::IsA());
} else {
R__c = R__b.WriteVersion(TGaxis::IsA(), kTRUE);
TLine::Streamer(R__b);
TAttText::Streamer(R__b);
R__b << fNdiv;
R__b << fWmin;
R__b << fWmax;
R__b << fGridLength;
R__b << fTickSize;
R__b << fLabelOffset;
R__b << fLabelSize;
R__b << fTitleOffset;
R__b << fTitleSize;
R__b << fLabelFont;
R__b << fLabelColor;
fChopt.Streamer(R__b);
fName.Streamer(R__b);
fTitle.Streamer(R__b);
fTimeFormat.Streamer(R__b);
fFunctionName.Streamer(R__b);
R__b.SetByteCount(R__c, kTRUE);
}
}
ROOT page - Class index - Top of the page
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.