Multi Color Graph

ROHLFS Reiner (Reiner.Rohlfs@obs.unige.ch)
Tue, 28 Oct 1997 11:23:26 +0100 (MET)


--Boundary_(ID_fqz+wleIRXFmj2ZzEr67GQ)
Content-type: TEXT/PLAIN; CHARSET=US-ASCII

Hi Rooters,

I want to draw a graph, but the color of the line should change if the Y-value
is above or below a limit.

I created a
class LimitGraph : public TGraph
{
public:
virtual void PaintGraph(Int_t npoints, Float_t *x, Float *y, Option_t *chopt);
};

In case of chopt == "L" this LimitGraph::PaintGraph() functions draws the line
itself. For the other options TGraph::PaintGraph() is called.

Inside this LimitGraph::PaintGraph() function the full line is split into parts
where the color should not change (the line does not pass a Y-limit) For each
part I call

SetLineColor(col);
gPad->PaintPolyLine(nrPt, xwork, ywork);

where col is the color the line should have,
nrPt is the number of points of the part of line and
xwork, ywork are arrays of the points of the line.

But the color of the line does not change!
How can I set the color for each part of the line?

If you are interested in I attach the full source code.

Reiner.

--Boundary_(ID_fqz+wleIRXFmj2ZzEr67GQ)
Content-type: TEXT/plain; CHARSET=US-ASCII
Content-description: LimitGraph.cpp

#include <string.h>
#include <math.h>

#include "TStyle.h"
#include "TVirtualPad.h"

#include "LineGraph.h"

///////////////////////////////////////////////////////////////////////////////
LimitGraph::LimitGraph(Int_t n, Float_t *x, Float_t *y)
: TGraph(n, x, y)
{
m_limLow = -MAXFLOAT;
m_limHeigh = MAXFLOAT;
m_colLow = m_colHeigh = gStyle->GetLineColor();

}
///////////////////////////////////////////////////////////////////////////////
LimitGraph::LimitGraph() : TGraph()
{
m_limLow = -MAXFLOAT;
m_limHeigh = MAXFLOAT;
m_colLow = m_colHeigh = gStyle->GetLineColor();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Int_t LimitGraph::GetRange(Float_t val)
{
if (val < m_limLow)
return -1;
if (val > m_limHeigh)
return 1;
return 0;
}
///////////////////////////////////////////////////////////////////////////////
void LimitGraph::PaintGraph(Int_t npoints, Float_t *x, Float_t *y, Option_t *chopt)
{
//*-*-*-*-*-*-*-*-*-*-*-*Control function to draw a graph*-*-*-*-*-*-*-*-*-*-*
//*-* ================================
// _Input parameters:
//
// npoints : Number of points in X or in Y.
// X(N) or X(2) : X coordinates or (XMIN,XMAX) (WC space).
// Y(N) or Y(2) : Y coordinates or (YMIN,YMAX) (WC space).
// chopt : Option.
//

Int_t OptionLine;
Int_t drawPt, pt;
char * found;
Int_t range, oldRange; // low : -1, between : 0, heigh : 1
Float_t * xwork, *ywork;
Float_t limit;
Color_t stdColor, col;
char opt[30];

//*-* ______________________________________

if (npoints <= 0) {
Error("PaintGraph", "illegal number of points (%d)", npoints);
return;
}

// search for L or l and remove all these characters from opt
strcpy(opt, chopt);
OptionLine = 0;
while (found = strchr(opt, 'L'))
{
OptionLine = 1;
strcpy(found, found+1);
}
while (found = strchr(opt, 'l'))
{
OptionLine = 1;
strcpy(found, found+1);
}

TGraph::PaintGraph(npoints, x, y, opt);

if (!OptionLine)
return;

stdColor = GetLineColor();

xwork = new Float_t[npoints];
ywork = new Float_t[npoints];

xwork[0] = x[0];
ywork[0] = y[0];
oldRange = GetRange(y[0]);

drawPt = 1;
for (pt = 1; pt < npoints; pt++) {
range = GetRange(y[pt]);

xwork[drawPt] = x[pt];
ywork[drawPt] = y[pt];

if (range != oldRange)
{
// get the first limit that was passed
// this also works if both limits are passed between two points.
if ((oldRange == -1) ||
(oldRange == 0 && range == -1) )
limit = m_limLow;
else
limit = m_limHeigh;

// this point has to be used again
pt--;

// it is not necessary to check that ywork[drawPt] != ywork[drawPt-1]
// because if they are identical than range == oldRange and this
// code is not executed
xwork[drawPt] = xwork[drawPt-1] +
(xwork[drawPt] - xwork[drawPt-1]) *
(limit - ywork[drawPt-1]) /
(ywork[drawPt] - ywork[drawPt-1]);
ywork[drawPt] = limit;
}

if (range != oldRange || pt == (npoints - 1))
{
// set color of line
if ((oldRange && range && pt != npoints -1) || oldRange == 0)
col = stdColor;
else if (oldRange == -1)
col = m_colLow;
else
col = m_colHeigh;
SetLineColor(col);

// draw a peace of line
gPad->PaintPolyLine(drawPt+1,xwork,ywork);

if ( pt == (npoints - 1))
// stop here if this was the last point
continue;

xwork[0] = xwork[drawPt];
ywork[0] = ywork[drawPt];
drawPt = 1;

// there was a jump over both limits if none of the ranges are 0
// set oldRange to 0 in this case
if (oldRange && range)
oldRange = 0;
else
oldRange = range;
}
else
drawPt++;

}
delete [] xwork;
delete [] ywork;
SetLineColor(stdColor);
}

//void TGraph::ComputeLogs(Int_t npoints, Int_t opt)
//{

//*-*-*-*-*-*-*-*-*-*-*-*Convert WC from Log scales*-*-*-*-*-*-*-*-*-*-*-*
//*-* ==========================
//
// Take the LOG10 of xwork and ywork according to the value of Options
// and put it in xworkl and yworkl.
//
// npoints : Number of points in xwork and in ywork.
//

// for (Int_t i=0;i<npoints;i++) {
// xworkl[i] = xwork[i];
// yworkl[i] = ywork[i];
// if (opt) continue;
// if (gPad->GetLogx()) {
// if (xworkl[i] > 0) xworkl[i] = TMath::Log10(xworkl[i]);
// else xworkl[i] = gPad->GetX1();
// }
// if (gPad->GetLogy()) {
// if (yworkl[i] > 0) yworkl[i] = TMath::Log10(yworkl[i]);
// else yworkl[i] = gPad->GetY1();
// }
// }
//}

--Boundary_(ID_fqz+wleIRXFmj2ZzEr67GQ)
Content-type: TEXT/plain; CHARSET=US-ASCII
Content-description: LineGraph.h

#include "TGraph.h"

class LimitGraph : public TGraph
{
Float_t m_limLow; // lower limit for color change
Float_t m_limHeigh; // higher limit for color change
Color_t m_colLow; // color of lines below lover limit
Color_t m_colHeigh; // color of lines above higher limit

public:
LimitGraph();
LimitGraph(Int_t n, Float_t *x, Float_t *y);

virtual void PaintGraph(Int_t npoints, Float_t *x, Float_t *y,
Option_t *chopt);

inline void SetHeighLimit(Float_t lim) {m_limHeigh = lim;};
inline void SetLowLimit (Float_t lim) {m_limLow = lim;};
inline void SetHeighColor(Color_t col) {m_colHeigh = col;};
inline void SetLowColor (Color_t col) {m_colLow = col;};

private:
Int_t GetRange(Float_t val);

};

--Boundary_(ID_fqz+wleIRXFmj2ZzEr67GQ)
Content-type: TEXT/plain; CHARSET=US-ASCII
Content-description: gt.cpp

#include <string.h>

#include "TROOT.h"
#include "TApplication.h"
#include "TCanvas.h"
#include "TPad.h"

#include "LineGraph.h"

////////////////////////////////////////////
void ShowGraph()
{
// Create a new canvas.
TCanvas * c1 = new TCanvas("c1","canvas",50,10,600,300);

// crate a pad
TPad * pad = new TPad("p1", "pad", 0.05, 0.05, 0.95, 0.95);
pad->SetFillColor(17);
pad->SetBorderSize(0);
pad->Draw();
pad->cd();

// create a graph
Float_t x[] = {8., 10., 13., 14., 16.};
Float_t y[] = {1., 3., 6., 4., 4.};
LimitGraph * graph = new LimitGraph(5, x, y);
graph->SetLineColor(3);
graph->SetHeighLimit(5.5);
graph->SetLowLimit(2.0);
graph->SetHeighColor(2);
graph->SetLowColor(4);
graph->Draw("APL");
c1->Update();

}

////////////////////////////////////////////

TApplication * myApp;

extern void InitGui();
VoidFuncPtr_t initFuncs[] = {InitGui, 0};
TROOT root ("Reiner", "Reiners Application", initFuncs);

main(int argc, char ** argv)
{
myApp = new TApplication("Reiners plot test", &argc, argv, NULL, 0);

ShowGraph();

myApp->Run();
}

--Boundary_(ID_fqz+wleIRXFmj2ZzEr67GQ)--