2012-11-08 3 views
7

Windows 응용 프로그램의 Ms- 차트에서 보간 및 외삽을 구현해야합니다.MS 차트의 보간 구현

보간의 경우 "MathNet"라이브러리를 사용하고 있습니다. 그러나 나는 아직도 이것을 구현하는 것을 모르고있다.

아래와 같이 보간을 구현하려고합니다.

using MathNet.Numerics.Interpolation.Algorithms; 

NevillePolynomialInterpolation objIterpolate = new NevillePolynomialInterpolation(Xpoints, Ypoints); 

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

나는 XValues ​​내 차트의 배열하는 첫 번째 매개 변수로 NevillePolynomialInterpolation()에 XPoints를 전달하고있다. 및 Ypoints는 YValues ​​배열로 구성됩니다.

보간 값을 가져 오는 XValue로 newValue을 전달합니다.

누구나 제안 할 수 있습니까? 올바른 방법인지, 보간을 구현하는 올바른 방법을 제안 할 수 있습니까?

+0

보간 결과의 절대 값을 취해야하는 이유가 확실하지 않더라도 필자는이를 올바르게 수행하고 있음을 알 수 있습니다. 당신이 왜 *이 접근법에 관심이 있는지에 대해 자세히 설명해 주시겠습니까? –

+0

내가 한 것이 옳고 그른 것인지 잘 모르겠습니다. 나는 너의 제안을 적어 둔다. 덕분에 ... –

+0

어쩌면 당신은 원시 및 보간 데이터 포인트의 예를 보여주는 화면 덤프를 삽입 할 수 있습니까? –

답변

0

간단한 예제를 만들었으므로 아래에 붙여 넣은 코드에 적용됩니다.

MathDotNet 라이브러리에는 익숙하지 않지만, XML 문서가 너무 익숙해 져서 학습 곡선이 너무나도 다른 .NET 라이브러리보다 가파른 것은 아닙니다.

그렇다면 도서관 웹 사이트에서 여전히 문서를 살펴볼 수 있습니다. 예를 들어 보간법을 다루지 않는 몇 가지 예가 있지만 XML을 읽은 것과 같은 것을 찾을 수 있습니다 선적 서류 비치. github을 확인하고 처리 할 보간법의 구현을 볼 수도 있습니다. 물론

당신은 또한 당신이 바로 여기에 설명 된 알고리즘에 충실 경우 처음부터 구현하기 위해 시도 할 수 있습니다 : 당신은 네빌 다항식 보간을 수행하고 원료 및 보간을 표시 MathDotNet 라이브러리를 활용하려는 생각 http://en.wikipedia.org/wiki/Neville%27s_algorithm 어쨌든

동일한 차트 영역에있는 데이터

추가 정보에 대한 몇 가지를 여기에서 찾을 수 있습니다 (아직도 많은 것을 기대하지 않는다) :

는 MS 차트에 대해, 그것은 당신과 내가하려고합니다 하드 무엇인지 뭔가 까다로운 점 밖에 있으면 그냥 문서를 확인, 모든 다른 윈폼 컨트롤을 다루는 같은 관하여 당신을 위해 그것을 명확하게.

지금까지 완전히 이해할 수없는 것에 대해 나는 고심하고 있습니다. MS Chart, MathDotNet입니까? 어느 것이 당신에게 문제입니까?

어쨌든 Xs 및 Ys의 기본 구현이 T[] 배열과 마찬가지로 IEnumerable<T>을 구현하는 한 MathDotNet 라이브러리에 X 및 Y 포인트를 전달하는 것만 큼 멋진 것은 아닙니다.

그러면 라이브러리에서 모든 수학 연산을 수행하고 주어진 보간법의 Interpolate(...) 메쏘드를 사용해야 만합니다. 여기서 보간은 일종의 보간 엔진을 의미합니다.

나는 당신의 코드에서 그 가정 : XPointsYPoints 모두 IEnumerable<T> 모음 TDouble, Single의 유형 또는 무엇이든 잘 맞는 원시 .NET 번호의 종류이다 (당신은 그들이 배열 인 했나요 때문에).

// 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; 
      } 
     } 
    } 
} 

더 많은 질문이 있으시면 언제든지 문의하십시오.