Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
01/23/17 16:11:02 (7 years ago)
Author:
abeham
Message:

#2457: updated branch to trunk

Location:
branches/PerformanceComparison/HeuristicLab.Analysis.Views
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/PerformanceComparison/HeuristicLab.Analysis.Views

  • branches/PerformanceComparison/HeuristicLab.Analysis.Views/3.3/ScatterPlotView.cs

    r13722 r14600  
    11#region License Information
    22/* HeuristicLab
    3  * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
    44 *
    55 * This file is part of HeuristicLab.
     
    2020#endregion
    2121
    22 using HeuristicLab.Collections;
    23 using HeuristicLab.Common;
     22using System;
     23using System.Windows.Forms;
    2424using HeuristicLab.Core.Views;
    2525using HeuristicLab.MainForm;
    26 using System;
    27 using System.Collections.Generic;
    28 using System.Drawing;
    29 using System.Linq;
    30 using System.Windows.Forms;
    31 using System.Windows.Forms.DataVisualization.Charting;
    3226
    3327namespace HeuristicLab.Analysis.Views {
     
    3529  [Content(typeof(ScatterPlot), true)]
    3630  public partial class ScatterPlotView : NamedItemView, IConfigureableView {
    37     protected List<Series> invisibleSeries;
    38     protected Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow> pointsRowsTable;
    39     private double xMin, xMax, yMin, yMax;
    4031
    4132    public new ScatterPlot Content {
     
    4637    public ScatterPlotView() {
    4738      InitializeComponent();
    48       pointsRowsTable = new Dictionary<IObservableList<Point2D<double>>, ScatterPlotDataRow>();
    49       invisibleSeries = new List<Series>();
    50       chart.CustomizeAllChartAreas();
    51       chart.ChartAreas[0].CursorX.Interval = 1;
    5239    }
    53 
    54     #region Event Handler Registration
    55     protected override void DeregisterContentEvents() {
    56       foreach (ScatterPlotDataRow row in Content.Rows)
    57         DeregisterScatterPlotDataRowEvents(row);
    58       Content.VisualPropertiesChanged -= new EventHandler(Content_VisualPropertiesChanged);
    59       Content.Rows.ItemsAdded -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
    60       Content.Rows.ItemsRemoved -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);
    61       Content.Rows.ItemsReplaced -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
    62       Content.Rows.CollectionReset -= new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
    63       base.DeregisterContentEvents();
    64     }
    65     protected override void RegisterContentEvents() {
    66       base.RegisterContentEvents();
    67       Content.VisualPropertiesChanged += new EventHandler(Content_VisualPropertiesChanged);
    68       Content.Rows.ItemsAdded += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded);
    69       Content.Rows.ItemsRemoved += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved);
    70       Content.Rows.ItemsReplaced += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced);
    71       Content.Rows.CollectionReset += new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset);
    72     }
    73 
    74     protected virtual void RegisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {
    75       row.NameChanged += new EventHandler(Row_NameChanged);
    76       row.VisualPropertiesChanged += new EventHandler(Row_VisualPropertiesChanged);
    77       pointsRowsTable.Add(row.Points, row);
    78       row.Points.ItemsAdded += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
    79       row.Points.ItemsRemoved += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
    80       row.Points.ItemsReplaced += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
    81       row.Points.CollectionReset += new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
    82     }
    83     protected virtual void DeregisterScatterPlotDataRowEvents(ScatterPlotDataRow row) {
    84       row.Points.ItemsAdded -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded);
    85       row.Points.ItemsRemoved -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved);
    86       row.Points.ItemsReplaced -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced);
    87       row.Points.CollectionReset -= new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset);
    88       pointsRowsTable.Remove(row.Points);
    89       row.VisualPropertiesChanged -= new EventHandler(Row_VisualPropertiesChanged);
    90       row.NameChanged -= new EventHandler(Row_NameChanged);
    91     }
    92     #endregion
    9340
    9441    protected override void OnContentChanged() {
    9542      base.OnContentChanged();
    96       invisibleSeries.Clear();
    97       chart.Titles[0].Text = string.Empty;
    98       chart.ChartAreas[0].AxisX.Title = string.Empty;
    99       chart.ChartAreas[0].AxisY.Title = string.Empty;
    100       chart.Series.Clear();
    101       if (Content != null) {
    102         chart.Titles[0].Text = Content.Name;
    103         AddScatterPlotDataRows(Content.Rows);
    104         ConfigureChartArea(chart.ChartAreas[0]);
    105         RecalculateMinMaxPointValues();
    106         RecalculateAxesScale(chart.ChartAreas[0]);
    107       }
     43      chart.Content = Content;
    10844    }
    10945
     
    11450
    11551    public void ShowConfiguration() {
    116       if (Content != null) {
    117         using (ScatterPlotVisualPropertiesDialog dialog = new ScatterPlotVisualPropertiesDialog(Content)) {
    118           dialog.ShowDialog(this);
    119         }
    120       } else MessageBox.Show("Nothing to configure.");
     52      chart.ShowConfiguration();
    12153    }
    12254
    123     protected virtual void AddScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {
    124       foreach (var row in rows) {
    125         RegisterScatterPlotDataRowEvents(row);
    126         Series series = new Series(row.Name);
    127         if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
    128         else series.LegendText = row.Name;
    129         ConfigureSeries(series, row);
    130         FillSeriesWithRowValues(series, row);
    131         chart.Series.Add(series);
    132       }
    133       ConfigureChartArea(chart.ChartAreas[0]);
    134       RecalculateMinMaxPointValues();
    135       RecalculateAxesScale(chart.ChartAreas[0]);
    136       UpdateYCursorInterval();
    137     }
    138 
    139     protected virtual void RemoveScatterPlotDataRows(IEnumerable<ScatterPlotDataRow> rows) {
    140       foreach (var row in rows) {
    141         DeregisterScatterPlotDataRowEvents(row);
    142         Series series = chart.Series[row.Name];
    143         if (chart.Series.IsUniqueName(series.Name + ".lr"))
    144           chart.Series.Remove(chart.Series[series.Name + ".lr"]);
    145         chart.Series.Remove(series);
    146         if (invisibleSeries.Contains(series))
    147           invisibleSeries.Remove(series);
    148       }
    149       RecalculateMinMaxPointValues();
    150       RecalculateAxesScale(chart.ChartAreas[0]);
    151     }
    152 
    153     private void ConfigureSeries(Series series, ScatterPlotDataRow row) {
    154       series.BorderWidth = 1;
    155       series.BorderDashStyle = ChartDashStyle.Solid;
    156       series.BorderColor = Color.Empty;
    157 
    158       if (row.VisualProperties.Color != Color.Empty)
    159         series.Color = row.VisualProperties.Color;
    160       else series.Color = Color.Empty;
    161       series.IsVisibleInLegend = row.VisualProperties.IsVisibleInLegend;
    162       series.ChartType = SeriesChartType.FastPoint;
    163       series.MarkerSize = row.VisualProperties.PointSize;
    164       series.MarkerStyle = ConvertPointStyle(row.VisualProperties.PointStyle);
    165       series.XAxisType = AxisType.Primary;
    166       series.YAxisType = AxisType.Primary;
    167 
    168       if (row.VisualProperties.DisplayName.Trim() != String.Empty) series.LegendText = row.VisualProperties.DisplayName;
    169       else series.LegendText = row.Name;
    170 
    171       string xAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.XAxisTitle)
    172                       ? "X"
    173                       : Content.VisualProperties.XAxisTitle;
    174       string yAxisTitle = string.IsNullOrEmpty(Content.VisualProperties.YAxisTitle)
    175                             ? "Y"
    176                             : Content.VisualProperties.YAxisTitle;
    177       series.ToolTip =
    178         series.LegendText + Environment.NewLine +
    179         xAxisTitle + " = " + "#VALX," + Environment.NewLine +
    180         yAxisTitle + " = " + "#VAL";
    181     }
    182 
    183     private void ConfigureChartArea(ChartArea area) {
    184       if (Content.VisualProperties.TitleFont != null) chart.Titles[0].Font = Content.VisualProperties.TitleFont;
    185       if (!Content.VisualProperties.TitleColor.IsEmpty) chart.Titles[0].ForeColor = Content.VisualProperties.TitleColor;
    186       chart.Titles[0].Text = Content.VisualProperties.Title;
    187 
    188       if (Content.VisualProperties.AxisTitleFont != null) area.AxisX.TitleFont = Content.VisualProperties.AxisTitleFont;
    189       if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisX.TitleForeColor = Content.VisualProperties.AxisTitleColor;
    190       area.AxisX.Title = Content.VisualProperties.XAxisTitle;
    191       area.AxisX.MajorGrid.Enabled = Content.VisualProperties.XAxisGrid;
    192 
    193       if (Content.VisualProperties.AxisTitleFont != null) area.AxisY.TitleFont = Content.VisualProperties.AxisTitleFont;
    194       if (!Content.VisualProperties.AxisTitleColor.IsEmpty) area.AxisY.TitleForeColor = Content.VisualProperties.AxisTitleColor;
    195       area.AxisY.Title = Content.VisualProperties.YAxisTitle;
    196       area.AxisY.MajorGrid.Enabled = Content.VisualProperties.YAxisGrid;
    197     }
    198 
    199     private void RecalculateAxesScale(ChartArea area) {
    200       area.AxisX.Minimum = CalculateMinBound(xMin);
    201       area.AxisX.Maximum = CalculateMaxBound(xMax);
    202       if (area.AxisX.Minimum == area.AxisX.Maximum) {
    203         area.AxisX.Minimum = xMin - 0.5;
    204         area.AxisX.Maximum = xMax + 0.5;
    205       }
    206       area.AxisY.Minimum = CalculateMinBound(yMin);
    207       area.AxisY.Maximum = CalculateMaxBound(yMax);
    208       if (area.AxisY.Minimum == area.AxisY.Maximum) {
    209         area.AxisY.Minimum = yMin - 0.5;
    210         area.AxisY.Maximum = yMax + 0.5;
    211       }
    212       if (xMax - xMin > 0) area.CursorX.Interval = Math.Pow(10, Math.Floor(Math.Log10(area.AxisX.Maximum - area.AxisX.Minimum) - 3));
    213       else area.CursorX.Interval = 1;
    214       area.AxisX.IsMarginVisible = false;
    215 
    216       if (!Content.VisualProperties.XAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.XAxisMinimumFixedValue)) area.AxisX.Minimum = Content.VisualProperties.XAxisMinimumFixedValue;
    217       if (!Content.VisualProperties.XAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.XAxisMaximumFixedValue)) area.AxisX.Maximum = Content.VisualProperties.XAxisMaximumFixedValue;
    218       if (!Content.VisualProperties.YAxisMinimumAuto && !double.IsNaN(Content.VisualProperties.YAxisMinimumFixedValue)) area.AxisY.Minimum = Content.VisualProperties.YAxisMinimumFixedValue;
    219       if (!Content.VisualProperties.YAxisMaximumAuto && !double.IsNaN(Content.VisualProperties.YAxisMaximumFixedValue)) area.AxisY.Maximum = Content.VisualProperties.YAxisMaximumFixedValue;
    220     }
    221 
    222     private static double CalculateMinBound(double min) {
    223       if (min == 0) return 0;
    224       var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(min))));
    225       return scale * (Math.Floor(min / scale));
    226     }
    227 
    228     private static double CalculateMaxBound(double max) {
    229       if (max == 0) return 0;
    230       var scale = Math.Pow(10, Math.Floor(Math.Log10(Math.Abs(max))));
    231       return scale * (Math.Ceiling(max / scale));
    232     }
    233 
    234     protected virtual void UpdateYCursorInterval() {
    235       double interestingValuesRange = (
    236         from series in chart.Series
    237         where series.Enabled
    238         let values = (from point in series.Points
    239                       where !point.IsEmpty
    240                       select point.YValues[0]).DefaultIfEmpty(1.0)
    241         let range = values.Max() - values.Min()
    242         where range > 0.0
    243         select range
    244         ).DefaultIfEmpty(1.0).Min();
    245 
    246       double digits = (int)Math.Log10(interestingValuesRange) - 3;
    247       double yZoomInterval = Math.Pow(10, digits);
    248       this.chart.ChartAreas[0].CursorY.Interval = yZoomInterval;
    249     }
    250 
    251     #region Event Handlers
    25255    #region Content Event Handlers
    25356    protected override void Content_NameChanged(object sender, EventArgs e) {
     
    25558        Invoke(new EventHandler(Content_NameChanged), sender, e);
    25659      else {
    257         chart.Titles[0].Text = Content.Name;
     60        Content.VisualProperties.Title = Content.Name;
    25861        base.Content_NameChanged(sender, e);
    25962      }
    260     }
    261     private void Content_VisualPropertiesChanged(object sender, EventArgs e) {
    262       if (InvokeRequired)
    263         Invoke(new EventHandler(Content_VisualPropertiesChanged), sender, e);
    264       else {
    265         ConfigureChartArea(chart.ChartAreas[0]);
    266         RecalculateAxesScale(chart.ChartAreas[0]); // axes min/max could have changed
    267       }
    268     }
    269     #endregion
    270     #region Rows Event Handlers
    271     private void Rows_ItemsAdded(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
    272       if (InvokeRequired)
    273         Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsAdded), sender, e);
    274       else {
    275         AddScatterPlotDataRows(e.Items);
    276       }
    277     }
    278     private void Rows_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
    279       if (InvokeRequired)
    280         Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsRemoved), sender, e);
    281       else {
    282         RemoveScatterPlotDataRows(e.Items);
    283       }
    284     }
    285     private void Rows_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
    286       if (InvokeRequired)
    287         Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_ItemsReplaced), sender, e);
    288       else {
    289         RemoveScatterPlotDataRows(e.OldItems);
    290         AddScatterPlotDataRows(e.Items);
    291       }
    292     }
    293     private void Rows_CollectionReset(object sender, CollectionItemsChangedEventArgs<ScatterPlotDataRow> e) {
    294       if (InvokeRequired)
    295         Invoke(new CollectionItemsChangedEventHandler<ScatterPlotDataRow>(Rows_CollectionReset), sender, e);
    296       else {
    297         RemoveScatterPlotDataRows(e.OldItems);
    298         AddScatterPlotDataRows(e.Items);
    299       }
    300     }
    301     #endregion
    302     #region Row Event Handlers
    303     private void Row_VisualPropertiesChanged(object sender, EventArgs e) {
    304       if (InvokeRequired)
    305         Invoke(new EventHandler(Row_VisualPropertiesChanged), sender, e);
    306       else {
    307         ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
    308         Series series = chart.Series[row.Name];
    309         series.Points.Clear();
    310         ConfigureSeries(series, row);
    311         FillSeriesWithRowValues(series, row);
    312         RecalculateMinMaxPointValues();
    313         RecalculateAxesScale(chart.ChartAreas[0]);
    314       }
    315     }
    316     private void Row_NameChanged(object sender, EventArgs e) {
    317       if (InvokeRequired)
    318         Invoke(new EventHandler(Row_NameChanged), sender, e);
    319       else {
    320         ScatterPlotDataRow row = (ScatterPlotDataRow)sender;
    321         chart.Series[row.Name].Name = row.Name;
    322       }
    323     }
    324     #endregion
    325     #region Points Event Handlers
    326     private void Points_ItemsAdded(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
    327       if (InvokeRequired)
    328         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsAdded), sender, e);
    329       else {
    330         ScatterPlotDataRow row = null;
    331         pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
    332         if (row != null) {
    333           Series rowSeries = chart.Series[row.Name];
    334           if (!invisibleSeries.Contains(rowSeries)) {
    335             rowSeries.Points.Clear();
    336             FillSeriesWithRowValues(rowSeries, row);
    337             RecalculateMinMaxPointValues();
    338             RecalculateAxesScale(chart.ChartAreas[0]);
    339             UpdateYCursorInterval();
    340           }
    341         }
    342       }
    343     }
    344     private void Points_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
    345       if (InvokeRequired)
    346         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsRemoved), sender, e);
    347       else {
    348         ScatterPlotDataRow row = null;
    349         pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
    350         if (row != null) {
    351           Series rowSeries = chart.Series[row.Name];
    352           if (!invisibleSeries.Contains(rowSeries)) {
    353             rowSeries.Points.Clear();
    354             FillSeriesWithRowValues(rowSeries, row);
    355             RecalculateMinMaxPointValues();
    356             RecalculateAxesScale(chart.ChartAreas[0]);
    357             UpdateYCursorInterval();
    358           }
    359         }
    360       }
    361     }
    362     private void Points_ItemsReplaced(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
    363       if (InvokeRequired)
    364         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_ItemsReplaced), sender, e);
    365       else {
    366         ScatterPlotDataRow row = null;
    367         pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
    368         if (row != null) {
    369           Series rowSeries = chart.Series[row.Name];
    370           if (!invisibleSeries.Contains(rowSeries)) {
    371             rowSeries.Points.Clear();
    372             FillSeriesWithRowValues(rowSeries, row);
    373             RecalculateMinMaxPointValues();
    374             RecalculateAxesScale(chart.ChartAreas[0]);
    375             UpdateYCursorInterval();
    376           }
    377         }
    378       }
    379     }
    380     private void Points_CollectionReset(object sender, CollectionItemsChangedEventArgs<IndexedItem<Point2D<double>>> e) {
    381       if (InvokeRequired)
    382         Invoke(new CollectionItemsChangedEventHandler<IndexedItem<Point2D<double>>>(Points_CollectionReset), sender, e);
    383       else {
    384         ScatterPlotDataRow row = null;
    385         pointsRowsTable.TryGetValue((IObservableList<Point2D<double>>)sender, out row);
    386         if (row != null) {
    387           Series rowSeries = chart.Series[row.Name];
    388           if (!invisibleSeries.Contains(rowSeries)) {
    389             rowSeries.Points.Clear();
    390             FillSeriesWithRowValues(rowSeries, row);
    391             RecalculateMinMaxPointValues();
    392             RecalculateAxesScale(chart.ChartAreas[0]);
    393             UpdateYCursorInterval();
    394           }
    395         }
    396       }
    397     }
    398     #endregion
    399     #endregion
    400 
    401     #region Chart Event Handlers
    402     private void chart_MouseDown(object sender, MouseEventArgs e) {
    403       HitTestResult result = chart.HitTest(e.X, e.Y);
    404       if (result.ChartElementType == ChartElementType.LegendItem) {
    405         ToggleSeriesVisible(result.Series);
    406       }
    407     }
    408     private void chart_MouseMove(object sender, MouseEventArgs e) {
    409       HitTestResult result = chart.HitTest(e.X, e.Y);
    410       if (result.ChartElementType == ChartElementType.LegendItem)
    411         this.Cursor = Cursors.Hand;
    412       else
    413         this.Cursor = Cursors.Default;
    414     }
    415     private void chart_CustomizeLegend(object sender, CustomizeLegendEventArgs e) {
    416       foreach (LegendItem legendItem in e.LegendItems) {
    417         var series = chart.Series[legendItem.SeriesName];
    418         if (series != null) {
    419           bool seriesIsInvisible = invisibleSeries.Contains(series);
    420           foreach (LegendCell cell in legendItem.Cells) {
    421             cell.ForeColor = seriesIsInvisible ? Color.Gray : Color.Black;
    422           }
    423         }
    424       }
    425     }
    426     #endregion
    427 
    428     private void ToggleSeriesVisible(Series series) {
    429       if (!invisibleSeries.Contains(series)) {
    430         series.Points.Clear();
    431         invisibleSeries.Add(series);
    432         RecalculateMinMaxPointValues();
    433       } else {
    434         invisibleSeries.Remove(series);
    435         if (Content != null) {
    436 
    437           var row = (from r in Content.Rows
    438                      where r.Name == series.Name
    439                      select r).Single();
    440           FillSeriesWithRowValues(series, row);
    441           RecalculateMinMaxPointValues();
    442           this.chart.Legends[series.Legend].ForeColor = Color.Black;
    443           RecalculateAxesScale(chart.ChartAreas[0]);
    444           UpdateYCursorInterval();
    445         }
    446       }
    447     }
    448 
    449     private void RecalculateMinMaxPointValues() {
    450       yMin = xMin = double.MaxValue;
    451       yMax = xMax = double.MinValue;
    452       foreach (var s in chart.Series.Where(x => x.Enabled)) {
    453         foreach (var p in s.Points) {
    454           double x = p.XValue, y = p.YValues[0];
    455           if (xMin > x) xMin = x;
    456           if (xMax < x) xMax = x;
    457           if (yMin > y) yMin = y;
    458           if (yMax < y) yMax = y;
    459         }
    460       }
    461     }
    462 
    463     private void FillSeriesWithRowValues(Series series, ScatterPlotDataRow row) {
    464       if (row.VisualProperties.ShowRegressionLine) {
    465         var xs = row.Points.Select(p => p.X).ToArray();
    466         var xsMin = xs.Min();
    467         var xsMax = xs.Max();
    468         var ys = row.Points.Select(p => p.Y).ToArray();
    469         var corr = alglib.pearsoncorr2(xs, ys);
    470         var slope = corr * ys.StandardDeviation() / xs.StandardDeviation();
    471         if (!double.IsNaN(slope) && !double.IsInfinity(slope)) {
    472           var off = ys.Average() - slope * xs.Average();
    473 
    474           Series lrSeries;
    475           if (chart.Series.IsUniqueName(series.Name + ".lr")) {
    476             lrSeries = new Series(series.Name + ".lr") {IsVisibleInLegend = false, ChartType = SeriesChartType.FastLine};
    477             chart.Series.Add(lrSeries);
    478           } else lrSeries = chart.Series[series.Name + ".lr"];
    479           lrSeries.Points.Clear();
    480           lrSeries.Points.AddXY(xsMin, slope * xsMin + off);
    481           lrSeries.Points.AddXY(xsMax, slope * xsMax + off);
    482         }
    483       } else if (!chart.Series.IsUniqueName(series.Name + ".lr"))
    484         chart.Series.Remove(chart.Series[series.Name + ".lr"]);
    485 
    486       for (int i = 0; i < row.Points.Count; i++) {
    487         var value = row.Points[i];
    488         DataPoint point = new DataPoint();
    489         if (IsInvalidValue(value.X) || IsInvalidValue(value.Y))
    490           point.IsEmpty = true;
    491         else {
    492           point.XValue = value.X;
    493           point.YValues = new double[] { value.Y };
    494         }
    495         series.Points.Add(point);
    496       }
    497     }
    498 
    499     #region Helpers
    500     private MarkerStyle ConvertPointStyle(ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle pointStyle) {
    501       switch (pointStyle) {
    502         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Circle:
    503           return MarkerStyle.Circle;
    504         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Cross:
    505           return MarkerStyle.Cross;
    506         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Diamond:
    507           return MarkerStyle.Diamond;
    508         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Square:
    509           return MarkerStyle.Square;
    510         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star4:
    511           return MarkerStyle.Star4;
    512         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star5:
    513           return MarkerStyle.Star5;
    514         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star6:
    515           return MarkerStyle.Star6;
    516         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Star10:
    517           return MarkerStyle.Star10;
    518         case ScatterPlotDataRowVisualProperties.ScatterPlotDataRowPointStyle.Triangle:
    519           return MarkerStyle.Triangle;
    520         default:
    521           return MarkerStyle.None;
    522       }
    523     }
    524 
    525     protected static bool IsInvalidValue(double x) {
    526       return double.IsNaN(x) || x < (double)decimal.MinValue || x > (double)decimal.MaxValue;
    52763    }
    52864    #endregion
Note: See TracChangeset for help on using the changeset viewer.