Chart Drawing Solution

Environment: Windows 95/98, Visual C++ 5.0 SP3

These are two classes I'm using to draw easy (absolutely not complex) graphs. I wrote it because I need a light (and cheap) control that could solve some problems about data showing.

What This Control Can Do

  • draw on the same chart few (up to 64, but you can change if you prefer) graphs with different styles
  • each graph can has up to 32k data (I never try this !)
  • draw NULL datas (undrawing them) so that you can show graphs with different X timebase
  • copy to clipboard
  • copy to file

What This Control Can Not Do

  • show data in 3d styles
  • print graph directly to printer
  • do a lot of things that I don't remember at this time...

How to use it

  1. First you must include the two classes in you project: add the files HMXChart.* and HMXDataset.* in your project
  2. include the HMXChart.h header in the CFormView that will show chart; the form must contain a static text control (modify its ID, e.g. IDC_CHART)
  3. create an object (in your formview object) derived from CHMXChart
  4. in formview initialization routine subclass the static text control
  5. set data and make-up
<

To set the data must be used following function

m_chart.SetData ( n, xxx );
where n represents the dataset, and xxx is the value (double). Every time this function is called a new value is added to the dataset. If you want modify a specific value, use this function:
m_chart.SetData ( n, idx, xxx );
where n is the dataset, idx is the idx-th element (zero based index), and xxx is the new value.

To create a new dataset its enought that a single value is added.

Following questions convinced me to design a new feature for this chart: NULL data.

What about if I have an hole in my data?

This is an example:

I have 2 datasets (Y1 and Y2):

X Y1 Y2
0 21 -12
1 17
2 33 10
3 10
4 23 15
5 22 18
6 12 16
7 13
8 45 17
How can I show these data in the same chart? To answer these questions I wrote this class so that it's possible to handle NULL data. Of course NULL value cannot be in the double range, because there could be a value that could be equal to that NULL. So I decided to define this NULL value as the upper limit of double range (see limits.h for details):
HMX_DATASET_VALUE_INVALID = 1.7976931348623158e+308
What about if a value is 1.7976931348623158e+308?
You can set it to 1.7976931348623158e+308 - 1, having a little error :)

In the example you can set to HMX_DATASET_VALUE_INVALID all the values that have no digits.

Even if the HMX_DATASET_VALUE_INVALID is a right concept for all dataset styles, in vertical bar style the value HMX_DATASET_VALUE_INVALID looks like 0.0, because all bars (positive and negative) starts from the zero line, thus the value 0.0 is represented with a 0 height bar.

There are three data formats: line, vertical bar and area; and the function to use to set the right format is:

m_chart.SetDatasetStyle( n, xxx );
where n is the dataset to modify and xxx can be:
HMX_DATASET_STYLE_LINE,
HMX_DATASET_STYLE_VBAR,
HMX_DATASET_STYLE_AREA;
If the style is line, it is possible to define a marker with the function
m_chart.SetDatasetMarker( n, xxx );
There are 4 different markers:
HMX_DATASET_MARKER_TRI,
HMX_DATASET_MARKER_BOX,
HMX_DATASET_MARKER_SPH,
HMX_DATASET_MARKER_DIA,
that correspond to a triangle (with vertex up), a square box, a shere and a diamond (45 degree rotated box). The marker size depends on the pen size. Please note that with small size box, sphere and diamond have the same look, reducing the readability.

To set the pen size use following function:

m_chart.SetDatasetPenSize( n, size );
If you're showing a line style graph, the pen size corresponds to the number of pixel used to draw the line; if the style is vertical bar, then the pen size corresponds to the width of the bar; in this case that number must be between 1 and 10; 1 is the smallest bar, 10 is the larger (occupies all the bar space). See the example and try to modify this value (an example is better than 1k words).

It's possible (of course) to set the X and Y labels; Y labels depend on the datasets and on the Y Ticks, X labels are added manually. They're strings, so it's possible to show numbers, text, date and so on.

Another interesting function allows the chart to have a good readability: rounding. It's possible to round the upper and lower chart limits to the multiple of each number, usually 2, 5, 10, 20, 500, and so on. This is its use:

m_chart.SetRoundY( n );
where n is the rounding value. Try to modify the example to see what it does mean.

There are al lot of self-explaining functions that improve chart readability.

Downloads

Download demo project - 47 Kb


Comments

  • Very cool but it burns out resources very fast and the system crash. Help !!!

    Posted by Legacy on 09/11/2003 12:00am

    Originally posted by: MGA

    Also using the demo project I've noticed that the creation of the graph uses a lot of SYSTEM and GDI RESOURCES.
    
    Those resources can be easily monitored using the OS utilities to do that.
    The result is that, when resources are at 0, the application do not refresh the graph any more, video is white or black.
    Things return to the normality after closing the application.
    I've tried on some OS (2000, NT, XP, ME) and I got the same result.
    I've also noticed that the effect increases doing a simple test:
    - create a new graph,
    - overlap it with the window of another application, the window size has to be smaller,
    - more this second window over the graph as it was something you use to clean, this probably causes many void CHMXChart::OnPaint().
    In this way the crash occurs shortly.

    I've done my best to find the bug but with no result.

    Is anybody that can help me ? I like the control a lot but I can't use it in this way.

    MGA

    Reply
  • How to empty it ?

    Posted by Legacy on 03/20/2003 12:00am

    Originally posted by: So1o

    Could anyone tell me how to empty the chart ?

    Reply
  • Can i use this in a CView?

    Posted by Legacy on 01/30/2003 12:00am

    Originally posted by: Stefan

    I would like to use this chart in a CView, how can i do that?

    Reply
  • printing the graph

    Posted by Legacy on 12/26/2002 12:00am

    Originally posted by: junaid

    hi!
    thanx mr. colorcio for being so helpful.....ur suggestions really did the trick and i have got rid of the tideous problem.
    well i still havea problem in sending the graph to the printer, how can i take the print out of the graphs, which i have plotted. Mr. colorcio, i have mailed u but didnt got the reply, can u please extend the cooperationa bit further.
    thanking in advance
    junaid

    Reply
  • Graphs and printing

    Posted by Legacy on 12/18/2002 12:00am

    Originally posted by: junaid ali

    hi!
    the problmes we r facing are
    1. How can i take the printout of the graphs.
    2. secondly when i open the graph dialog for the first time,
    its ok.but when when i close the window and reopen
    it,the graph appears to to shrink, means on the same
    scale, the graph(desired curve )appears twice and is
    shrinked.now close the graph again and reopen it, it
    will shrink 3 times and so forth.how can i overcome this
    problem.
    Can anyone help me in this regard.
    well Mr. colurcio , i have mailed u as u asked me to do, but havnt got the reply, if u can cooperate a bit more, that will be really helpful in this cause.
    An early response is required.
    thanking in advance.

    Reply
  • Refreshing the graph

    Posted by Legacy on 12/17/2002 12:00am

    Originally posted by: Junaid

    hi!
    the problmes we r facing are
    1. How can i take the printout of the graphs.
    2. secondly when i open the graph dialog for the first time,
    its ok.but when when i close the window and reopen
    it,the graph appears to to shrink, means on the same
    scale, the graph(desired curve )appears twice and is
    shrinked.now close the graph again and reopen it, it
    will shrink 3 times and so forth.how can i overcome this
    problem.
    Can anyone help me in this regard.
    well Mr. colurcio , i have mailed u as u asked me to do, but havnt got the reply, if u can cooperate a bit more, that will be really helpful in this cause.
    thanking in advance.

    Reply
  • PRINTING

    Posted by Legacy on 12/10/2002 12:00am

    Originally posted by: Junaid

    sir! this project helped me alot....i ll b pleased if u can help me to get the print out of these plots...
    Any can help me in this regard will be highly appreciated.
    Thanx.
    Junaid Ali.

    Reply
  • Addition to "bubble" data elements

    Posted by Legacy on 10/23/2001 12:00am

    Originally posted by: Chris Adamson

    I really enjoyed how simple the set of classes you created were to use. Thank you!
    
    

    I've added some functionality for displaying only the latest data (up to a user defined maximum).

    For example, I needed a graph to show temperature entries for the past hour from the current time (once per minute). After an hour has past, I start discarding the oldest sample each minute.

    The additions:

    CHMXDataset:

    //method added to bubble the entries left
    //(for a plotting only the newest data in a graph)
    //does not deallocate any memory in the process; upper
    //bound is decremented by one
    //each member is bubbled one element left (ie down) and the
    //element at index 0 is discarded

    inline void BubbleDataElements(void)
    {
    m_data.RemoveAt(0);
    };

    CHMXChart:

    //--->
    inline void BubbleDataSet(const UINT &index)
    {
    m_dataset[index].BubbleDataElements();
    };
    inline void BubbleXLabels(void)
    {
    m_strarrScaleXLabel.RemoveAt(0);
    };
    //<---

    Here's an example usage (sorry if formatting is bad):

    void CILRTemperatureDoc::UpdateChartDataSets(CHMXChart &chart)
    {
    if (MAX_SAMPLES_PER_SERIES == m_nNumSamples) //need to bubble the elements
    {
    chart.BubbleXLabels();
    for (UINT i = 0; i < m_nTags; i++)
    chart.BubbleDataSet(i);
    }

    for (UINT j = 0; j < m_nTags; j++)
    VERIFY(chart.SetData(j, m_dDataArray[m_iWorkingIndex][j]));

    }

    I hope this helps anyone who could use such functionality.
    -Chris

    Reply
  • Nice to meet this control....!

    Posted by Legacy on 08/20/2001 12:00am

    Originally posted by: Jaewoo Joung

    I need graph control...
    then.. I seek and seek...

    Here is that I want..

    Reply
  • Very Nice piece of Code!!!!!!

    Posted by Legacy on 03/29/2001 12:00am

    Originally posted by: Pravin Lunagaria

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • 10 Rules that Make or Break Enterprise App Development Projects In today's app-driven world, application development is a top priority. Even so, 68% of enterprise application delivery projects fail. Designing and building applications that pay for themselves and adapt to future needs is incredibly difficult. Executing one successful project is lucky, but making it a repeatable process and strategic advantage? That's where the money is. With help from our most experienced project leads and software engineers, …

  • As more and more organizations migrate to the cloud, many are faced with hidden costs emerging from unexpected places. Two non-obvious and non-trivial factors can drive up costs. First are separate charges for everything from server memory to intrusion detection. Second are the high personnel costs for early-generation, manually operated clouds. These costs can rack up quickly, creating total cost of ownership (TCO) surprises. Keeping TCO low in the cloud is essentially a matter of management strategy. IT …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds