Index: /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/ChartUtil.cs
===================================================================
--- /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/ChartUtil.cs	(revision 14151)
+++ /trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/ChartUtil.cs	(revision 14152)
@@ -27,18 +27,35 @@
   public static class ChartUtil {
     public static void CalculateAxisInterval(double min, double max, int ticks, out double axisMin, out double axisMax, out double axisInterval) {
-      var dmin = (max - min).Decimals();
-      axisMin = min.Floor(dmin);
-      var range = max - axisMin;
-      var slice = range / ticks;
-      var dslice = slice.Decimals();
-      var floor = slice.Floor(dslice);
-      var ceil = slice.Ceil(dslice);
-      var axisRange = floor * ticks;
-      axisInterval = floor;
-      if (axisRange < max - axisMin) {
-        axisRange = ceil * ticks;
-        axisInterval = ceil;
+      if (double.IsInfinity(min) || double.IsNaN(min) || double.IsInfinity(max) || double.IsNaN(max) || (min >= max))
+        throw new ArgumentOutOfRangeException("Invalid range provided.");
+
+      var range = max - min;
+      var minLog = Math.Log10(Math.Abs(min));
+      var maxLog = Math.Log10(Math.Abs(max));
+      var rangeLog = Math.Log10(range);
+
+      var dMin = (int)Math.Floor(minLog);
+      var dMax = (int)Math.Floor(maxLog);
+      var dRange = (int)Math.Floor(rangeLog);
+
+      int decimalRank;
+      if (dMin == dMax && dMax == dRange)
+        decimalRank = dMin - 1;
+      else
+        decimalRank = Math.Min(Math.Min(dMin, dMax), dRange);
+
+      var aMin = min.RoundDown(decimalRank);
+      var aMax = max.RoundUp(decimalRank);
+
+      // if one of the interval ends is a multiple of 5 or 10, change the other interval end to be a multiple as well
+      if (((aMin % 5).IsAlmost(0) || (aMin % 10).IsAlmost(0)) && !((aMax % 5).IsAlmost(0) || (aMax % 10).IsAlmost(0))) {
+        aMax = Math.Min(aMax + 5 - aMax % 5, aMax + 10 - aMax % 10);
+      } else if (((aMax % 5).IsAlmost(0) || (aMax % 10).IsAlmost(0)) && !((aMin % 5).IsAlmost(0) || (aMin % 10).IsAlmost(0))) {
+        aMin = Math.Max(aMin - aMin % 5, aMin - aMin % 10);
       }
-      axisMax = axisMin + axisRange;
+
+      axisMin = aMin;
+      axisMax = aMax;
+      axisInterval = (aMax - aMin) / ticks;
     }
 
@@ -66,4 +83,5 @@
     }
 
+    // find the number of decimals needed to represent the value
     private static int Decimals(this double x) {
       if (x.IsAlmost(0) || double.IsInfinity(x) || double.IsNaN(x))
@@ -79,4 +97,36 @@
     }
 
+    private static double RoundDown(this double value, int decimalRank) {
+      if (decimalRank > 0) {
+        var floor = (int)Math.Floor(value);
+        var pow = (int)Math.Pow(10, decimalRank);
+        // round down to nearest multiple of 5 or 10
+        var mod = Math.Min(floor % pow, floor % (pow / 2));
+        return floor - mod;
+      }
+      return value.Floor(Math.Abs(decimalRank));
+    }
+
+    private static double RoundUp(this double value, int decimalRank) {
+      if (decimalRank > 0) {
+        var ceil = (int)Math.Ceiling(value);
+        var pow = (int)Math.Pow(10, decimalRank);
+        // round up to nearest multiple of 5 or 10
+        var mod = ceil % (pow / 2) == 0 || ceil % pow == 0 ? 0 : Math.Min(pow / 2 - ceil % (pow / 2), pow - ceil % pow);
+        return ceil + mod;
+      }
+      return value.Ceil(Math.Abs(decimalRank));
+    }
+
+    private static double RoundNearest(this double value, int decimalRank) {
+      var nearestDown = value.RoundDown(decimalRank);
+      var nearestUp = value.RoundUp(decimalRank);
+
+      if (nearestUp - value > value - nearestDown)
+        return nearestDown;
+
+      return nearestUp;
+    }
+
     // rounds down to the nearest value according to the given number of decimal precision
     private static double Floor(this double value, int precision) {
@@ -85,12 +135,8 @@
     }
 
+    // rounds up to the nearest value according to the given number of decimal precision
     private static double Ceil(this double value, int precision) {
       var n = Math.Pow(10, precision);
       return Math.Round(Math.Ceiling(value * n) / n, precision);
-    }
-
-    private static double Round(this double value, int precision) {
-      var n = Math.Pow(10, precision);
-      return Math.Round(Math.Round(value * n) / n, precision);
     }
 
