/// <summary> /// Initializes a new instance of the CustomSeriesSample class. /// </summary> public CustomSeriesSample() { InitializeComponent(); // Use a custom function for a series FunctionSeries series = CustomFunctionChart.Series[1] as FunctionSeries; series.Function = x => 110 + 3 * Math.Sin(x); }
/// <summary> /// LineBrushProperty property changed handler. /// </summary> /// <param name="d">FunctionSeries that changed its LineBrush.</param> /// <param name="e">Event arguments.</param> private static void OnLineBrushPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { FunctionSeries source = d as FunctionSeries; Brush value = e.NewValue as Brush; source.LegendItem.DataContext = new ContentControl { Background = value }; }
private void OnRegressionTypeChanged(object sender, SelectionChangedEventArgs e) { // Get the options and the series ComboBox combo = sender as ComboBox; if (combo == null || ParticulateAnalysis == null) { return; } ScatterSeries dataSeries = ParticulateAnalysis.Series[0] as ScatterSeries; FunctionSeries regressionSeries = ParticulateAnalysis.Series[1] as FunctionSeries; if (dataSeries == null || regressionSeries == null) { return; } // Get the active DataPoints (this assumes the default template for // ScatterSeries) Canvas plotArea = VisualTreeHelper.GetChild(dataSeries, 0) as Canvas; if (plotArea == null) { return; } List <DataPoint> activePoints = plotArea .Children .OfType <DataPoint>() .ToList(); // The dimensions were added linearly to the ComboBox int dimension = combo.SelectedIndex + 1; // Initialize a simple least squares analysis int i = 0; int j = 0; int k = 0; double[] y = new double[activePoints.Count]; double[,] x = new double[activePoints.Count, dimension + 1]; for (i = 0; i < activePoints.Count; i++) { DataPoint point = activePoints[i]; double independentValue = Convert.ToDouble(point.IndependentValue, CultureInfo.InvariantCulture); for (j = 0; j <= dimension; j++) { x[i, j] = Math.Pow(independentValue, j); } y[i] = Convert.ToDouble(point.DependentValue, CultureInfo.InvariantCulture); } // Create the equations double[][] matrix = new double[dimension + 1][]; for (i = 0; i <= dimension; i++) { // Create the row matrix[i] = new double[dimension + 2]; // indeterminate coefficients for (j = 0; j <= dimension; j++) { matrix[i][j] = 0.0; for (k = 0; k < activePoints.Count; k++) { matrix[i][j] += x[k, i] * x[k, j]; } } // determinate values for (k = 0; k < activePoints.Count; k++) { matrix[i][dimension + 1] += x[k, i] * y[k]; } } // Convert to row-echelon form i = 0; j = 0; while (i <= dimension && j <= dimension) { // Get the pivot in column j starting at row i int pivotRow = i; for (k = i; k <= dimension; k++) { if (Math.Abs(matrix[k][j]) > Math.Abs(matrix[pivotRow][j])) { pivotRow = k; } } double pivot = matrix[pivotRow][j]; // If we have a pivot element if (pivot != 0) { // Swap the current row with the pivot row double[] temp = matrix[i]; matrix[i] = matrix[pivotRow]; matrix[pivotRow] = temp; pivotRow = i; // Normalize the pivot row to the pivot double c = matrix[i][j]; for (k = 0; k <= dimension + 1; k++) { matrix[i][k] /= c; } // Clear out the pivot position from the remaining rows for (k = i + 1; k <= dimension; k++) { c = matrix[k][j]; for (int m = i; m <= dimension + 1; m++) { matrix[k][m] -= c * matrix[i][m]; } } i++; } j++; } // Solve using substitution for (i = dimension - 1; i >= 0; i--) { for (j = dimension; j > i; j--) { matrix[i][dimension + 1] -= matrix[i][j] * matrix[j][dimension + 1]; matrix[i][j] = 0; } } // Capture the coefficients double a0 = matrix[0][dimension + 1]; double a1 = matrix[1][dimension + 1]; double a2 = (dimension >= 2) ? matrix[2][dimension + 1] : double.NaN; double a3 = (dimension >= 3) ? matrix[3][dimension + 1] : double.NaN; double a4 = (dimension == 4) ? matrix[4][dimension + 1] : double.NaN; // Create the function Func <double, double> function = null; switch (dimension) { case 1: function = z => a1 * z + a0; break; case 2: function = z => a2 * z * z + a1 * z + a0; break; case 3: function = z => a3 * z * z * z + a2 * z * z + a1 * z + a0; break; case 4: function = z => a4 * z * z * z * z + a3 * z * z * z + a2 * z * z + a1 * z + a0; break; } // Create the title StackPanel title = new StackPanel { Orientation = Orientation.Horizontal }; title.Children.Add( new TextBlock { Text = "f(x) = ", Margin = new Thickness(0, 4, 0, 0) }); title.Children.Add( new TextBlock { Text = a0.ToString("N3", CultureInfo.InvariantCulture), Margin = new Thickness(0, 4, 0, 0) }); AddTitleTerm(title, a1, 1); if (dimension >= 2) { AddTitleTerm(title, a2, 2); } if (dimension >= 3) { AddTitleTerm(title, a3, 3); } if (dimension == 4) { AddTitleTerm(title, a4, 4); } // Set the function and the title regressionSeries.Function = function; regressionSeries.Title = title; }
/// <summary> /// FunctionProperty property changed handler. /// </summary> /// <param name="d">FunctionSeries that changed its Function.</param> /// <param name="e">Event arguments.</param> private static void OnFunctionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { FunctionSeries source = d as FunctionSeries; source.Refresh(); }