source: trunk/sources/HeuristicLab.Visualization.ChartControlsExtensions/3.3/HistogramControl.cs @ 11171

Last change on this file since 11171 was 11171, checked in by ascheibe, 6 years ago

#2115 merged r11170 (copyright update) into trunk

File size: 5.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2014 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Drawing;
25using System.Linq;
26using System.Windows.Forms;
27using System.Windows.Forms.DataVisualization.Charting;
28
29namespace HeuristicLab.Visualization.ChartControlsExtensions {
30  public partial class HistogramControl : UserControl {
31    private static readonly string SeriesName = "Histogram";
32
33    private List<double> points;
34    public int NumberOfBins {
35      get { return (int)binsNumericUpDown.Value; }
36      set { binsNumericUpDown.Value = value; }
37    }
38
39    public int MinimumNumberOfBins {
40      get { return (int)binsNumericUpDown.Minimum; }
41      set { binsNumericUpDown.Minimum = value; }
42    }
43
44    public int MaximumNumberOfBins {
45      get { return (int)binsNumericUpDown.Maximum; }
46      set { binsNumericUpDown.Maximum = value; }
47    }
48
49    public int IncrementNumberOfBins {
50      get { return (int)binsNumericUpDown.Increment; }
51      set { binsNumericUpDown.Increment = value; }
52    }
53
54    public bool CalculateExactBins {
55      get { return exactCheckBox.Checked; }
56      set { exactCheckBox.Checked = value; }
57    }
58
59    public bool ShowExactCheckbox {
60      get { return exactCheckBox.Visible; }
61      set { exactCheckBox.Visible = value; }
62    }
63
64    public HistogramControl() {
65      InitializeComponent();
66      points = new List<double>();
67      InitializeChart();
68    }
69
70    public void AddPoint(double point) {
71      points.Add(point);
72      UpdateHistogram();
73    }
74
75    public void AddPoints(IEnumerable<double> points) {
76      this.points.AddRange(points);
77      UpdateHistogram();
78    }
79
80    public void ClearPoints() {
81      points.Clear();
82      UpdateHistogram();
83    }
84
85    private void InitializeChart() {
86      chart.Series.Clear();
87      Series s = chart.Series.Add(SeriesName);
88      s.ChartType = SeriesChartType.Column;
89      s.BorderColor = Color.Black;
90      s.BorderWidth = 1;
91      s.BorderDashStyle = ChartDashStyle.Solid;
92    }
93
94    private void UpdateHistogram() {
95      if (InvokeRequired) {
96        Invoke((Action)UpdateHistogram, null);
97        return;
98      }
99      Series histogramSeries = chart.Series[SeriesName];
100      histogramSeries.Points.Clear();
101
102      if (!points.Any()) return;
103      int bins = (int)binsNumericUpDown.Value;
104
105      double minValue = points.Min();
106      double maxValue = points.Max();
107      double intervalWidth = (maxValue - minValue) / bins;
108      if (intervalWidth <= 0) return;
109
110      if (!exactCheckBox.Checked) {
111        intervalWidth = HumanRoundRange(intervalWidth);
112        minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;
113        maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;
114      }
115
116      double current = minValue, intervalCenter = intervalWidth / 2.0;
117      int count = 0;
118      foreach (double v in points.OrderBy(x => x)) {
119        while (v > current + intervalWidth) {
120          histogramSeries.Points.AddXY(current + intervalCenter, count);
121          current += intervalWidth;
122          count = 0;
123        }
124        count++;
125      }
126      histogramSeries.Points.AddXY(current + intervalCenter, count);
127
128      histogramSeries["PointWidth"] = "1";
129
130      ChartArea chartArea = chart.ChartAreas[histogramSeries.ChartArea];
131      chartArea.AxisY.Title = "Frequency";
132      chartArea.AxisX.Minimum = minValue;
133      chartArea.AxisX.Maximum = maxValue;
134
135      double axisInterval = intervalWidth;
136      while ((maxValue - minValue) / axisInterval > 10.0) {
137        axisInterval *= 2.0;
138      }
139      chartArea.AxisX.Interval = axisInterval;
140    }
141
142    private double HumanRoundRange(double range) {
143      double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));
144      double rounding = range / base10;
145      if (rounding <= 1.5) rounding = 1;
146      else if (rounding <= 2.25) rounding = 2;
147      else if (rounding <= 3.75) rounding = 2.5;
148      else if (rounding <= 7.5) rounding = 5;
149      else rounding = 10;
150      return rounding * base10;
151    }
152
153    private void binsNumericUpDown_ValueChanged(object sender, EventArgs e) {
154      UpdateHistogram();
155    }
156
157    private void exactCheckBox_CheckedChanged(object sender, EventArgs e) {
158      UpdateHistogram();
159    }
160  }
161}
Note: See TracBrowser for help on using the repository browser.