Creating Line Charts - Page 5
       by kirupa  |  23 September 2006

I started covering the interesting code from this project in the previous page. In this page I will explain how the chart data is normalized and plotted!

Normalizing the Chart
One of my design goals was to make the chart be capable of plotting a wide range of values. Like I mentioned earlier, you are constrained by your chart's height and width, so you will need to ensure that the highest and lowest values of your chart display in a reasonably accurate scale.

The following is the code that normalizes the chart's height and width:

// Taking care of some bookwork (declaring/initializing variables)
int maxDataPoints = points.Length;
int chartHeight = bmp.Height - bottomOffset;
int chartWidth = bmp.Width - rightOffset;
 
// Adjustable Values
double adjustedMax = maxValue * .10 + maxValue;
double adjustedMin = minValue - .50 * minValue;
double adjustVerticalRatio = (chartHeight-topOffset) / adjustedMax;
double adjustHorizontalRatio = ((chartWidth - leftOffset) / (maxDataPoints - 1));

One good way of looking at this is via an example. Let's say your maximum data point is 1000, and your chart's height is 100 pixels. That means, for every pixel, you have to cover 10 points of data so that you can display your 1000-value data point. That also means that a value of 500, will be 50 pixels high. Similarly, a data point that is 100, will only be 10 pixels tall.

What you are trying to do is come up with a good ratio between your chart's height and the number of data values each pixel will cover. The ratio is, as shown above, determined only by your maximum data point, and the ratio is what the adjustVerticalRatio variable stores.

Likewise for the horizontal case, the adjustHorizontalRatio variable stores the distance each data point must be separated by in order to fill up the horizontal space. Ideally, that would be the chart's width divided by the number of data points.

Notice in a lot of the above cases, I take into account any vertical or horizontal offsets that you may have introduced.

Plotting the Lines
To plot the lines, you first determine the starting and ending X and Y positions. Because in order to draw any lines, you need a starting point as well as an ending point. In our case, since all the lines are interconnected, your ending point for one line is the starting point for the next line.

The code for determining the two x and y positions can be found below:

int xPos = Convert.ToInt32(i * adjustHorizontalRatio) + leftOffset;
int xPos2 = Convert.ToInt32((i + 1) * adjustHorizontalRatio) + leftOffset;
 
int yPos = Convert.ToInt32(chartHeight - adjustVerticalRatio * points[i]);
int yPos2 = Convert.ToInt32(chartHeight - adjustVerticalRatio * points[i + 1]);

Some key things to note are how the earlier adjustHorizontalRatio and adjustVerticalRatio values are being used. Notice also that I am converting all of the earlier data into integers, for as you will see in the next line, the x and y positions are specified as a Point object that only accepts integer values:

gfx.DrawLine(chartPen, new Point(xPos, yPos), new Point(xPos2, yPos2));

You will see the Point class again when I explain how to draw border lines in the next page.

Onwards to the next page!

1 | 2 | 3 | 4 | 5 | 6




SUPPORTERS:

kirupa.com's fast and reliable hosting provided by Media Temple.