Does anyone have a decent algorithm for calculating axis minima and maxima?
When creating a chart for a given set of data items, I'd like to be able to give the algorithm:
The algorithm should return
The ticks should be at a regular interval should be of a "reasonable" size (e.g. 1, 3, 5, possibly even 2.5, but not any more sig figs).
The presence of the optional value will skew this, but without that value the largest item should appear between the top two tick marks, the lowest value between the bottom two.
This is a language-agnostic question, but if there's a C#/.NET library around, that would be smashing ;)
OK, here's what I came up with for one of our applications. Note that it doesn't deal with the "optional value" scenario you mention, since our optional value is always 0, but it shouldn't be hard for you to modify.
Data is continually added to the series so we just keep the range of y values up to date by inspecting each data point as its added; this is very inexpensive and easy to keep track of. Equal minimum and maximum values are special cased: a spacing of 0 indicates that no markers should be drawn.
This solution isn't dissimilar to Andrew's suggestion above, except that it deals, in a slightly kludgy way with some arbitrary fractions of the exponent multiplier.
Lastly, this sample is in C#. Hope it helps.
private float GetYMarkerSpacing()
{
YValueRange range = m_ScrollableCanvas.
TimelineCanvas.DataModel.CurrentYRange;
if ( range.RealMinimum == range.RealMaximum )
{
return 0;
}
float absolute = Math.Max(
Math.Abs( range.RealMinimum ),
Math.Abs( range.RealMaximum ) ),
spacing = 0;
for ( int power = 0; power < 39; ++power )
{
float temp = ( float ) Math.Pow( 10, power );
if ( temp <= absolute )
{
spacing = temp;
}
else if ( temp / 2 <= absolute )
{
spacing = temp / 2;
break;
}
else if ( temp / 2.5 <= absolute )
{
spacing = temp / 2.5F;
break;
}
else if ( temp / 4 <= absolute )
{
spacing = temp / 4;
break;
}
else if ( temp / 5 <= absolute )
{
spacing = temp / 5;
break;
}
else
{
break;
}
}
return spacing;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With