Multi Color Graph

From: ROHLFS Reiner (Reiner.Rohlfs@obs.unige.ch)
Date: Tue Oct 28 1997 - 11:23:26 MET


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.



#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();
//     }
//  }
//}



#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);
	

};


#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();
}



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:26:22 MET