1  #region License Information


2  /* HeuristicLab


3  * Copyright (C) 20022011 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 


22  using System;


23  using System.Collections.Generic;


24  using System.Drawing;


25  using System.Linq;


26  using System.Windows.Forms;


27  using System.Windows.Forms.DataVisualization.Charting;


28 


29  namespace HeuristicLab.Visualization.ChartControlsExtensions {


30  public partial class HistogramControl : UserControl {


31  private static readonly string SeriesName = "Histogram";


32 


33  private List<double> points;


34 


35  public HistogramControl() {


36  InitializeComponent();


37  points = new List<double>();


38  InitializeChart();


39  }


40 


41  public void AddPoint(double point) {


42  points.Add(point);


43  UpdateHistogram();


44  }


45 


46  public void AddPoints(IEnumerable<double> points) {


47  this.points.AddRange(points);


48  UpdateHistogram();


49  }


50 


51  public void ClearPoints() {


52  points.Clear();


53  UpdateHistogram();


54  }


55 


56  private void InitializeChart() {


57  chart.Series.Clear();


58  Series s = chart.Series.Add(SeriesName);


59  s.ChartType = SeriesChartType.Column;


60  s.BorderColor = Color.Black;


61  s.BorderWidth = 1;


62  s.BorderDashStyle = ChartDashStyle.Solid;


63  }


64 


65  private void UpdateHistogram() {


66 


67  Series histogramSeries = chart.Series[SeriesName];


68  histogramSeries.Points.Clear();


69 


70  if (!points.Any()) return;


71  int bins = (int)binsNumericUpDown.Value;


72 


73  double minValue = points.Min();


74  double maxValue = points.Max();


75  double intervalWidth = (maxValue  minValue) / bins;


76  if (intervalWidth <= 0) return;


77 


78  if (!exactCheckBox.Checked) {


79  intervalWidth = HumanRoundRange(intervalWidth);


80  minValue = Math.Floor(minValue / intervalWidth) * intervalWidth;


81  maxValue = Math.Ceiling(maxValue / intervalWidth) * intervalWidth;


82  }


83 


84  double current = minValue;


85  int count = 0;


86  foreach (double v in points.OrderBy(x => x)) {


87  if (v < current + intervalWidth) {


88  count++;


89  } else {


90  histogramSeries.Points.AddXY(current + intervalWidth / 2.0, count);


91  count = 1;


92  while (v >= current + intervalWidth) current += intervalWidth;


93  }


94  }


95  histogramSeries.Points.AddXY(current + intervalWidth / 2.0, count);


96 


97  histogramSeries["PointWidth"] = "1";


98 


99  ChartArea chartArea = chart.ChartAreas[histogramSeries.ChartArea];


100  chartArea.AxisY.Title = "Frequency";


101  chartArea.AxisX.Minimum = minValue;


102  chartArea.AxisX.Maximum = maxValue;


103 


104  double axisInterval = intervalWidth;


105  while ((maxValue  minValue) / axisInterval > 10.0) {


106  axisInterval *= 2.0;


107  }


108  chartArea.AxisX.Interval = axisInterval;


109  }


110 


111  private double HumanRoundRange(double range) {


112  double base10 = Math.Pow(10.0, Math.Floor(Math.Log10(range)));


113  double rounding = range / base10;


114  if (rounding <= 1.5) rounding = 1;


115  else if (rounding <= 2) rounding = 2;


116  else if (rounding <= 2.5) rounding = 2.5;


117  else if (rounding <= 5) rounding = 5;


118  else rounding = 10;


119  return rounding * base10;


120  }


121 


122  private void binsNumericUpDown_ValueChanged(object sender, EventArgs e) {


123  UpdateHistogram();


124  }


125 


126  private void exactCheckBox_CheckedChanged(object sender, EventArgs e) {


127  UpdateHistogram();


128  }


129  }


130  }

