Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2434_crossvalidation/HeuristicLab.Visualization.ChartControlsExtensions/3.3/ChartUtil.cs @ 16310

Last change on this file since 16310 was 14029, checked in by gkronber, 8 years ago

#2434: merged trunk changes r12934:14026 from trunk to branch

File size: 3.5 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23
24using System;
25
26namespace HeuristicLab.Visualization.ChartControlsExtensions {
27  public static class ChartUtil {
28    public static void CalculateAxisInterval(double min, double max, int ticks, out double axisMin, out double axisMax, out double axisInterval) {
29      var dmin = (max - min).Decimals();
30      axisMin = min.Floor(dmin);
31      var range = max - axisMin;
32      var slice = range / ticks;
33      var dslice = slice.Decimals();
34      var floor = slice.Floor(dslice);
35      var ceil = slice.Ceil(dslice);
36      var axisRange = floor * ticks;
37      axisInterval = floor;
38      if (axisRange < max - axisMin) {
39        axisRange = ceil * ticks;
40        axisInterval = ceil;
41      }
42      axisMax = axisMin + axisRange;
43    }
44
45    // this method tries to find an axis interval with as few fractional digits as possible (because it looks nicer)
46    // we only try between 3 and 5 ticks (inclusive) because it wouldn't make sense to exceed this interval
47    public static void CalculateOptimalAxisInterval(double min, double max, out double axisMin, out double axisMax, out double axisInterval) {
48      CalculateAxisInterval(min, max, 5, out axisMin, out axisMax, out axisInterval);
49      int bestLsp = int.MaxValue;
50      for (int ticks = 3; ticks <= 5; ++ticks) {
51        double aMin, aMax, aInterval;
52        CalculateAxisInterval(min, max, ticks, out aMin, out aMax, out aInterval);
53        var x = aInterval;
54        int lsp = 0; // position of the least significant fractional digit
55        while (x - Math.Floor(x) > 0) {
56          ++lsp;
57          x *= 10;
58        }
59        if (lsp <= bestLsp) {
60          axisMin = aMin;
61          axisMax = aMax;
62          axisInterval = aInterval;
63          bestLsp = lsp;
64        }
65      }
66    }
67
68    private static int Decimals(this double x) {
69      if (x.IsAlmost(0) || double.IsInfinity(x) || double.IsNaN(x))
70        return 0;
71
72      var v = Math.Abs(x);
73      int d = 1;
74      while (v < 1) {
75        v *= 10;
76        d++;
77      }
78      return d;
79    }
80
81    // rounds down to the nearest value according to the given number of decimal precision
82    private static double Floor(this double value, int precision) {
83      var n = Math.Pow(10, precision);
84      return Math.Round(Math.Floor(value * n) / n, precision);
85    }
86
87    private static double Ceil(this double value, int precision) {
88      var n = Math.Pow(10, precision);
89      return Math.Round(Math.Ceiling(value * n) / n, precision);
90    }
91
92    private static double Round(this double value, int precision) {
93      var n = Math.Pow(10, precision);
94      return Math.Round(Math.Round(value * n) / n, precision);
95    }
96
97    private static bool IsAlmost(this double value, double other, double eps = 1e-12) {
98      return Math.Abs(value - other) < eps;
99    }
100  }
101}
Note: See TracBrowser for help on using the repository browser.