by kirupa |
23 September 2006I 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!
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.
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!
|