e42.uk Circle Device

 

Quick Reference

Chart Drawing

Chart Drawing

Drawing charts is a fairly common requirement in engineering, science and maths. This is an implementation of a small charting library using pixman and freetype for use in a desktop Windows application.

Essential Components of a Chart

A chart generally consists of axes and some form of data within their range. A chart, rendered onto a set of pixels, also has dimensions. To begin these data items must be stored:

chart_context {
    point top_left;
    point bottom_right;
    axis axes[];
};

It is likely that more than one set of data is to be displayed on the same chart, in this case point data and a derived curve must be displayed together. To cater for display of that data multiple axes are required... details on how these are handled will have to come later.

axis {
    int type;
    double min, max;
    double step;
    tic tics[];
};

tic {
    double value;
    string label;
};

Axes may contain time or natural number or real number data, to account for this possibility different data structures can be defined...

axis_for_time {
    int type;
    uint64_t min, max;
    uint64_t step;
    tic tics[];
};

tic_for_time {
    uint64_t value;
    string label;
};

Finally a structure for data is required, this structure in the form as dictated by the types defined in the axes:

chart_data_for_time_vs_double {
    chart * chart_ptr;
    axis_for_time * x_axis;
    axis_for_time * y_axis;
    data_for_time_and_double * data;
};

data_for_time_and_double {
    uint64_t x;
    double y;
};

Once these are in place the next concern is one of style and how to present your axis/tics.

Calculating Tics

Generally a plot will have axes with appropriately scaled tics take for example the below chart, generated with GNUPlot, which has two axes appropriately scaled to the data displayed.

Appropriate Tics

The tics here will be calculated with the following algorithm:

step = pow(10, floor(log10(span / m)));
err = m / span * step;
if (err <= 0.15) step *= 10; else
if (err <= 0.35) step *= 5; else 
if (err <= 0.75) step *= 2;

Quick Links: Techie Stuff | General | Personal | Quick Reference