2012-11-08 12 views
7

Wymagam implementacji interpolacji i ekstrapolacji w Ms-Chart w aplikacji Windows.Implementacja interpolacji w MS Chart

Do interpolacji Używam biblioteki "MathNet". ale nadal nie jestem świadomy tego, aby to wdrożyć.

Próbuję wdrożyć interpolację jak poniżej.

using MathNet.Numerics.Interpolation.Algorithms; 

NevillePolynomialInterpolation objIterpolate = new NevillePolynomialInterpolation(Xpoints, Ypoints); 

    double NewYValue; 
    NewYValue = Math.Abs(objIterpolate.Interpolate(newValue); 

jestem przekazując XPoints w NevillePolynomialInterpolation() jako pierwszy parametr, który jest XValues ​​tablica moim wykresie. i Ypoints jako tablicę YValues ​​mojego wykresu.

Przekazuję newValue jako XValue do uzyskania wartości interpolowanej.

Czy ktoś może zasugerować, czy jest to właściwa droga, czy sugeruje poprawny sposób wdrożenia interpolacji.

+0

O ile widzę, robisz to dobrze, chociaż nie jestem pewien, dlaczego musisz wziąć wartość bezwzględną interpolowanego wyniku? Czy mógłbyś rozwinąć * dlaczego * interesujesz się tym podejściem? –

+0

Nie jestem pewien, co zrobiłem, jest dobre lub złe. Zapamiętałem twoją sugestię. dzięki ... –

+0

Może możesz wstawić zrzut ekranu pokazujący przykład surowych i interpolowanych punktów danych? –

Odpowiedz

0

Udało mi się stworzyć krótki przykład, więc daj mi znać, jeśli mój kod wkleiłem poniżej działa dla Ciebie.

Nie jestem do tej pory przyzwyczajony do biblioteki MathDotNet, jednak Dokumentacja XML jest wystarczająco ładna, więc krzywa uczenia się nie jest tak stroma, jak kolejna biblioteka .NET wśród wielu innych.

W przeciwnym razie możesz przejść do strony internetowej biblioteki, aby zapoznać się z ich dokumentacją, poza kilkoma przykładami, których nie jestem pewien, aby pokryć interpolację, prawdopodobnie znajdziesz to samo, co masz, czytając XML dokumentacja. Możesz także sprawdzić github i zobaczyć implementację interpolacji, którą chcesz obsłużyć.

Oczywiście można również starać się realizować od podstaw, jeśli trzymać się algorytmu opisanego tu: http://en.wikipedia.org/wiki/Neville%27s_algorithm

Zresztą mam chcesz wykorzystać bibliotekę MathDotNet wykonać Neville interpolacji wielomianowej i wyświetlić surowy i interpolowana dane na tym samym obszarze wykresu.

O dodatkowe informacje na niektóre można znaleźć tutaj (jeszcze nie oczekują, że dużo):

Wykres

O wykresu MS, to wszystko o jak do czynienia z żadnymi innymi WinForm Kontroli, wystarczy sprawdzić w dokumentacji, jeśli coś jest trudne punkt, co jest trudne dla Ciebie i staram aby ci to wyjaśnić.

Póki co, aby być całkowicie szczerym, mam problem z tym, czego nie rozumiesz, czy to wykres MS, MathDotNet, oba? Który z nich jest dla ciebie problemem?

W każdym razie nie ma nic naprawdę nadzwyczajnego, po prostu przekazując swoje punkty X i Y do biblioteki MathDotNet (tak długo, jak implementacje bazowe Xs i Ys wdrażają IEnumerable<T> jak tablice T[] jest w porządku).

Następnie biblioteka wykonuje dla Ciebie wszystkie obliczenia matematyczne i musisz po prostu zastosować podane metody interpolacji (musisz zrozumieć, że interpolacja oznacza tutaj rodzaj mechanizmu interpolacji, rodzaj).

Sądziłem, że w fragmencie kodu: XPoints i YPoints są zarówno IEnumerable<T> kolekcje (ponieważ wymieniono są tablice) gdzie T jest rodzajem Double, Single lub bez względu na rodzaj .NET Liczba Primitive że pasuje dobrze.

// Copyright: Nothing At All License 
using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.Drawing; 
using System.Linq; 
using System.Runtime.InteropServices; 
using System.Threading.Tasks; 
using System.Windows.Forms; 
using System.Windows.Forms.DataVisualization.Charting; 
using MathNet.Numerics.Random; 

namespace HelpSO 
{ 
    public static class Program 
    { 
     [STAThread] 
     public static void Main(params String[] arguments) 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 

      var mainForm = new MainForm(); 

      Application.Run(mainForm); 
     } 
    } 

    /// <summary> 
    /// Main Form. 
    /// </summary> 
    public class MainForm : Form 
    { 
     /// <summary> 
     /// Initializes the chart and cosmetics, make-up, glamour, etc.. 
     /// </summary> 
     /// <returns>The chart.</returns> 
     private static Chart InitializeChart() 
     { 
      var chart = new Chart() 
      { 
       Dock = DockStyle.Fill,  
      }; 

      const String defaultChartAreaName = @"Default"; 
      const String defaultLegendName = @"Default"; 
      const String defaultTitleName = @"Default"; 

      var chartArea = chart.ChartAreas.Add(defaultChartAreaName); 

      var labelFont = new Font(@"Tahoma", 8f); 

      var axisX = chartArea.AxisX; 
      var axisY = chartArea.AxisY; 

      axisX.Title = @"X"; 
      axisY.Title = @"Y"; 

      axisX.LabelStyle.Format = axisX.LabelStyle.Format = "F4"; 

      axisX.TitleFont = axisY.TitleFont = labelFont; 
      axisX.LabelStyle.Font = axisY.LabelStyle.Font = labelFont; 

      axisX.TitleAlignment = axisY.TitleAlignment = StringAlignment.Far; 
      axisX.MajorGrid.Enabled = axisY.MajorGrid.Enabled = true; 
      axisX.MinorGrid.Enabled = axisY.MinorGrid.Enabled = true; 
      axisX.MinorGrid.LineDashStyle = axisY.MinorGrid.LineDashStyle = ChartDashStyle.Dash; 
      axisX.MinorGrid.LineColor = axisY.MinorGrid.LineColor = Color.Gainsboro; 

      var legend = chart.Legends.Add(defaultLegendName); 
      legend.TitleSeparator = LegendSeparatorStyle.ThickGradientLine; 
      legend.BorderColor = Color.Black; 
      legend.Title = "Legend"; 

      var title = chart.Titles.Add(defaultTitleName); 
      title.Text = @"My Awesome interpolated data"; 
      title.Font = new Font(title.Font.FontFamily, 12f); 

      MainForm.InitializeChartSeries(chart); 

      return chart; 
     } 

     /// <summary> 
     /// Initializes the chart series and related data (raw and interpolated). 
     /// </summary> 
     /// <param name="chart">Chart.</param> 
     private static void InitializeChartSeries(Chart chart) 
     { 
      const String rawDataSeriesName = @"Raw Data"; 
      const String interpolatedDataSeriesName = @"Interpolated Data"; 

      var rawDataSeries = chart.Series.Add(rawDataSeriesName); 
      var interpolatedDataSeriesSeries = chart.Series.Add(interpolatedDataSeriesName); 

      rawDataSeries.ChartType = SeriesChartType.FastLine; 
      interpolatedDataSeriesSeries.ChartType = SeriesChartType.Spline; 

      rawDataSeries.BorderWidth = interpolatedDataSeriesSeries.BorderWidth = 2; 

      var rawDataPoints = DataFactory.GenerateDummySine(10, 1, 0.25); 
      var interpolatedDataPoints = DataFactory.Interpolate(rawDataPoints, 10); 

      rawDataSeries.Points.DataBind(rawDataPoints, @"X", @"Y", String.Empty); 
      interpolatedDataSeriesSeries.Points.DataBind(interpolatedDataPoints, @"X", @"Y", String.Empty); 
     } 

     /// <summary> 
     /// Initializes a new instance of the <see cref="HelpSO.MainForm"/> class. 
     /// </summary> 
     public MainForm() 
     { 
      this.StartPosition = FormStartPosition.CenterScreen; 

      var chart = MainForm.InitializeChart(); 

      this.Controls.Add(chart); 
     } 
    } 

    /// <summary> 
    /// Data Factory. 
    /// </summary> 
    public static class DataFactory 
    { 
     /// <summary> 
     /// Generates a dummy sine. 
     /// </summary> 
     /// <returns>The dummy sine.</returns> 
     /// <param name="count">Count.</param> 
     /// <param name="amplitude">Amplitude.</param> 
     /// <param name="noiseAmplitude">Noise amplitude.</param> 
     public static IList<Point2D<Double, Double>> GenerateDummySine(UInt16 count, Double amplitude, Double noiseAmplitude) 
     { 
      if (count < 2) 
      { 
       throw new ArgumentOutOfRangeException(@"count"); 
      } 
      else 
      { 
       var dummySinePoints = new List<Point2D<Double, Double>>(); 

       var random = new Random(); 

       var xStep = 1.0/count; 

       for (var x = 0.0; x < 1.0; x += xStep) 
       { 
        var y = amplitude * Math.Sin(2f * Math.PI * x) + random.NextDouble() * noiseAmplitude; 

        var dummySinePoint = new Point2D<Double, Double>(x, y); 

        dummySinePoints.Add(dummySinePoint); 
       } 

       return dummySinePoints; 
      } 
     } 

     /// <summary> 
     /// Interpolate the specified source. 
     /// </summary> 
     /// <param name="source">Source.</param> 
     /// <param name="countRatio">Count ratio.</param> 
     public static IList<Point2D<Double, Double>> Interpolate(IList<Point2D<Double, Double>> source, UInt16 countRatio) 
     { 
      if (countRatio == 0) 
      { 
       throw new ArgumentOutOfRangeException(@"countRatio"); 
      } 
      else if (source.Count < 2) 
      { 
       throw new ArgumentOutOfRangeException(@"source"); 
      } 
      else 
      { 

       var rawDataPointsX = source.Select(item => item.X); 
       var rawDataPointsY = source.Select(item => item.Y); 

       // Could be done within one loop only... so far I'm pretty busy will update that example later 
       var xMin = rawDataPointsX.Min(); 
       var xMax = rawDataPointsX.Max(); 

       // Different Kinds of interpolation here... it's all up to you o pick up the one that's gonna match your own situation 
       // var interpolation = MathNet.Numerics.Interpolation.NevillePolynomialInterpolation.Interpolate(rawDataPointsX, rawDataPointsY); 
       var interpolation = MathNet.Numerics.Interpolation.CubicSpline.InterpolateNatural(rawDataPointsX, rawDataPointsY); 

       var listCopy = source.ToList(); 

       var xStep = (xMax - xMin)/(source.Count * countRatio); 

       for (var x = xMin; x <= xMax; x += xStep) 
       { 
        var y = interpolation.Interpolate(x); 

        var point2D = new Point2D<Double, Double>(x, y); 

        listCopy.Add(point2D); 
       } 

       return listCopy; 
      } 
     } 
    } 

    // C# lacks, for ***now***, generic constraints for primitive "numbers" 
    public struct Point2D<TX, TY> 
     where TX : struct, IComparable, IFormattable, IConvertible, IComparable<TX>, IEquatable<TX> 
     where TY : struct, IComparable, IFormattable, IConvertible, IComparable<TY>, IEquatable<TY> 
    { 
     public static Point2D<TX, TY> Empty = new Point2D<TX, TY>(); 

     public Point2D(TX x, TY y) 
     { 
      this._x = x; 
      this._y = y; 
     } 

     // C# 6 I miss you here: sad 
     private readonly TY _y; 
     public TY Y 
     { 
      get 
      { 
       return this._y; 
      } 
     } 

     // and there too :-(
     private readonly TX _x; 
     public TX X 
     { 
      get 
      { 
       return this._x; 
      } 
     } 
    } 
} 

Zapraszam do zadawania więcej pytań na ten temat.