예제 #1
0
        private void MenuShowChart_Clicked(object sender, RoutedEventArgs e)
        {
            try
            {
                Func <double, double> fx = this.Fx.CompileDynamicMethod();
                Func <double, double> gx = this.Gx.CompileDynamicMethod();
                if (this.chartData.YTo == null || this.chartData.YFrom == null) //chart data y-values were not initialized
                {
                    Parallel.Invoke(() =>
                    {
                        Extremum extremum    = DiagramWindow.FuncFindMinMax(new Func <double, double>[] { fx, gx }, this.chartData.XFrom, this.chartData.XTo);
                        this.chartData.YFrom = -Math.Abs(1.5 * Math.Max(Math.Abs(extremum.Min), Math.Abs(extremum.Max)));
                        this.chartData.YTo   = -chartData.YFrom;
                    });
                }

                DiagramWindow diagWnd = new DiagramWindow(chartData.XFrom, chartData.XTo, chartData.YFrom, chartData.YTo, chartData.Dx);

                diagWnd.DrawGraph(new Func <double, double>[] { fx, gx }, this.chartData.XFrom, this.chartData.XTo);


                diagWnd.Owner = this;
                diagWnd.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
                diagWnd.ShowDialog();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
예제 #2
0
        private void MenuChartConfig_Clicked(object sender, RoutedEventArgs e)
        {
            double xFrom             = this.chartData.XFrom;
            double xTo               = this.chartData.XTo;
            Func <double, double> fx = this.Fx.CompileDynamicMethod();
            Func <double, double> gx = this.Gx.CompileDynamicMethod();
            Extremum extremum        = DiagramWindow.FuncFindMinMax(new Func <double, double>[] { fx, gx }, xFrom, xTo);
            double   yFrom           = this.chartData.YFrom ?? -Math.Abs(1.5 * Math.Max(Math.Abs(extremum.Min), Math.Abs(extremum.Max)));
            double   yTo             = -yFrom;

            ChartConfigWindow configWnd = new ChartConfigWindow(xFrom, xTo, yFrom, yTo, this.chartData.Dx, this.BindYToFx, this.BindYToGx);

            configWnd.ChartConfigChanged += delegate(object o, ChartEventArgs eArgs)
            {
                this.chartData.XFrom = eArgs.From.X;
                this.chartData.XTo   = eArgs.To.X;
                this.chartData.YFrom = eArgs.From.Y;
                this.chartData.YTo   = eArgs.To.Y;
                this.chartData.Dx    = eArgs.Dx;
                this.BindYToFx       = eArgs.BindToFx;
                this.BindYToGx       = eArgs.BindToGx;

                if (this.BindYToFx && this.BindYToGx)
                {
                    extremum = DiagramWindow.FuncFindMinMax(new Func <double, double>[] { fx, gx }, xFrom, xTo);
                }
                else if (this.BindYToFx)
                {
                    extremum = DiagramWindow.FuncFindMinMax(new Func <double, double>[] { fx }, xFrom, xTo);
                }
                else if (this.BindYToGx)
                {
                    extremum = DiagramWindow.FuncFindMinMax(new Func <double, double>[] { gx }, xFrom, xTo);
                }

                this.chartData.YFrom = -Math.Abs(1.5 * Math.Max(Math.Abs(extremum.Min), Math.Abs(extremum.Max)));
                this.chartData.YTo   = -this.chartData.YFrom;
            };



            configWnd.Owner = this;
            configWnd.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterOwner;
            configWnd.Show();
        }
        private void DrawGraph(DrawArgs args, Action EndCallback = null)
        {
            double from = args.From, to = args.To;

            //while (!Dispatcher.Invoke<bool>(() => drawCanvas.IsLoaded))
            //{
            //}

            int width  = args.UIWidth;  //(int)drawCanvas.ActualWidth;
            int height = args.UIHeight; //(int)drawCanvas.ActualHeight;


            DrawingVisual drawingVisual = new DrawingVisual();


            using (DrawingContext c = drawingVisual.RenderOpen())
            {
                //Brushes
                SolidColorBrush textBrush = new SolidColorBrush(Colors.Black);
                Pen             axisPen   = new Pen(Brushes.Black, 1);
                //Pen graphPen = new Pen(Brushes.Red, 1);
                const int FontSize = 12;


                double xFrom, xTo;
                double yFrom, yTo;

                // Func<double, double> f = args.F;

                this.xFrom = xFrom = from;
                this.xTo   = xTo = to;
                Extremum extremum = FuncFindMinMax(args.F, xFrom, xTo);
                if (this.yFrom == null || this.yTo == null)
                {
                    this.yFrom = yFrom = -Math.Abs(1.5 * Math.Max(Math.Abs(extremum.Min), Math.Abs(extremum.Max))); //чтобы хотя бы часть графика попала в область отображения
                    this.yTo   = yTo = -yFrom;
                }
                else
                {
                    yFrom = this.yFrom.Value;
                    yTo   = this.yTo.Value;
                }

                //інтервал повинен бути симетричним (потрібно для рисування осей координат)
                if (-xFrom != xTo)
                {
                    double radius = Math.Max(Math.Abs(xFrom), Math.Abs(xTo));
                    xFrom = -radius;
                    xTo   = radius;
                }


                //Scales
                double xScale = width / (xTo - xFrom);
                double yScale = height / (yTo - yFrom);

                //Origin
                int x0 = width / 2,
                    y0 = height / 2;

                //draw horizontal axis
                c.DrawLine(axisPen, new Point(0, y0), new Point(width, y0));
                //draw verical axis
                c.DrawLine(axisPen, new Point(x0, 0), new Point(x0, height));

                //draw horizontal divisions
                int N = 10;                           //number of divisions

                double valueX    = (xTo - xFrom) / N, //ціна поділки
                       divHeight = 2;                 //висота поділки
                int stepX        = width / N;         //крок по вісі Х (від поділки до поділки)

                double divCounter = xFrom;


                for (int x = x0 % stepX; x < width; x += stepX, divCounter += valueX)
                {
                    c.DrawLine(axisPen, new Point(x, y0 - divHeight), new Point(x, y0 + divHeight));

                    FormattedText formattedText = new FormattedText(Math.Round(divCounter, 4) + "",
                                                                    new System.Globalization.CultureInfo("en-us"),
                                                                    FlowDirection.LeftToRight,
                                                                    new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal),
                                                                    FontSize,
                                                                    textBrush);
                    c.DrawText(formattedText, new Point(x - FontSize, y0 + divHeight)); //!!!!!!!!FontSize
                }

                //draw vertical divisions
                double valueY   = (yTo - yFrom) / N;
                double divWidth = divHeight; //division width (height for horizontal axis)
                int    stepY    = height / N;

                divCounter = yTo;
                for (int y = y0 % stepY; y < height; y += stepY, divCounter -= valueY)
                {
                    if (y == y0)
                    {
                        continue;
                    }
                    c.DrawLine(axisPen, new Point(x0 - divWidth, y), new Point(x0 + divWidth, y));

                    int divCounterLength = divCounter.ToString().Length; //кількість символів у числовому записі поділки

                    FormattedText formattedText = new FormattedText(Math.Round(divCounter, 4) + "",
                                                                    new System.Globalization.CultureInfo("en-us"),
                                                                    FlowDirection.LeftToRight,
                                                                    new Typeface(new FontFamily("Arial"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal),
                                                                    FontSize,
                                                                    textBrush);
                    c.DrawText(formattedText, new Point(x0 - ((Math.Truncate(yTo)).ToString().Length + 5) * 8 - 2 * divWidth, y - FontSize)); //!!!!!!!!FontSize //* FontSize - divWidth * 2
                }


                //draw desired graph
                int colorIndex = 0;
                foreach (Func <double, double> f in args.F)
                {
                    Pen graphPen = new Pen(new SolidColorBrush(this.lineColors[colorIndex]), 1); //set line color
                    colorIndex++;

                    xFrom = from;
                    xTo   = to;
                    //dx = valueX / 10000.0;//CalculateDX(f);//0.00001;
                    double xPrev = xFrom, yPrev = f(xFrom);
                    float  xCorrection = x0 % stepX;
                    float  yCorrection = y0 % stepY;

                    Dispatcher.Invoke(() =>
                    {
                        progressBar.Value   = xFrom;
                        progressBar.Minimum = xFrom;
                        progressBar.Maximum = xTo;
                    });
                    for (double x = xFrom + dx; x < xTo; x += dx)
                    {
                        double fx;
                        try
                        {
                            fx = f(x);
                        }
                        catch (DivideByZeroException)
                        { continue; }

                        if (fx > 2 * yTo || fx < 2 * yFrom)        //если график ушел на бесконечность
                        {
                            while (fx > 2 * yTo || fx < 2 * yFrom) //пропустить этот участок
                            {
                                manualResetEvent.WaitOne();
                                cancelToken.Token.ThrowIfCancellationRequested();

                                if (x > xTo)
                                {
                                    break;
                                }
                                x += dx;
                                try
                                {
                                    fx = f(x);
                                }
                                catch (DivideByZeroException)
                                {
                                    continue;
                                }
                            }
                            xPrev = x;
                            yPrev = fx;
                        }

                        //if (Math.Abs(fx - yPrev) < 0.02) //avoid drawing the same point multiple times = пропустить очень-очень близкие пары значений
                        //    continue;

                        if (ArePointsEqual(PointToScreen(
                                               new Point(xPrev, yPrev), extremum.Max, extremum.Min, width, height),
                                           PointToScreen(new Point(x, fx), extremum.Max, extremum.Min, width, height), 1))
                        {
                            continue;
                        }


                        manualResetEvent.WaitOne();
                        cancelToken.Token.ThrowIfCancellationRequested();


                        c.DrawLine(graphPen, new Point(xPrev * xScale + x0, -yPrev * yScale + y0), new Point(x * xScale + x0, -fx * yScale + y0));

                        Dispatcher.Invoke(() => progressBar.Value = x);

                        xPrev = x;
                        yPrev = fx;
                    }
                }
            }

            manualResetEvent.WaitOne();
            cancelToken.Token.ThrowIfCancellationRequested();

            if (EndCallback != null)
            {
                EndCallback();
            }


            args.visualTargetPS.RootVisual = drawingVisual; //updating visual tree
        }
예제 #4
0
        private void MenuReport_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Func <double, double> fx = this.Fx.CompileDynamicMethod();
                Func <double, double> gx = this.Gx.CompileDynamicMethod();
                if (this.chartData.YTo == null || this.chartData.YFrom == null) //chart data y-values were not initialized
                {
                    Parallel.Invoke(() =>
                    {
                        Extremum extremum    = DiagramWindow.FuncFindMinMax(new Func <double, double>[] { fx, gx }, this.chartData.XFrom, this.chartData.XTo);
                        this.chartData.YFrom = -Math.Abs(1.5 * Math.Max(Math.Abs(extremum.Min), Math.Abs(extremum.Max)));
                        this.chartData.YTo   = -chartData.YFrom;
                    });
                }

                DiagramWindow diagWnd = new DiagramWindow(chartData.XFrom, chartData.XTo, chartData.YFrom, chartData.YTo, chartData.Dx);
                diagWnd.Owner = this;

                RenderTargetBitmap rtb = diagWnd.DrawGraphToImage(new Func <double, double>[] { fx, gx }, width: 800, height: 800);
                diagWnd.Close();

                PngBitmapEncoder png = new PngBitmapEncoder();
                png.Frames.Add(BitmapFrame.Create(rtb));
                using (Stream stm = File.Create("diagram.png"))
                {
                    png.Save(stm);
                }

                //generate pdf--------------------------------------------------------
                PdfDocument doc = new PdfDocument();
                doc.Info.Title = "RootFinder Report";

                PdfPage page1 = doc.AddPage();

                // Get an XGraphics object for drawing
                XGraphics gfx = XGraphics.FromPdfPage(page1);

                // Create a font
                XFont font = new XFont("Times New Roman", 14, XFontStyle.Regular);

                //generate a report---------------------------------------------------------------------------------------------------------------
                StringBuilder report = new StringBuilder();
                string        task   = "Finding roots of equations using dynamic expression tree generation and function interpolation\r\n" +
                                       "\tUsed algorithms: Shunting-yard algorithm and Lagrange interpolation.\r\n\r\n";
                report.Append(task);
                report.AppendFormat("Search interval: {0}\r\n", lblSrcInterval.Content);
                report.AppendFormat("Eps.: {0}\r\n", lblEps.Content);
                report.AppendFormat("Interpolation error: {0}\r\n", lblInterpError.Content);
                report.AppendFormat("Number of roots: {0}\r\n", lblRoots.Content);
                report.AppendFormat("Power of Lagrange polynomial: {0}\r\n", lblLagPower.Content);
                report.AppendFormat("Roots are shown on the page #2\r\n", lblInterpError.Content);

                //generate a report---------------------------------------------------------------------------------------------------------------


                XTextFormatter tf = new XTextFormatter(gfx);

                XRect rect = new XRect(10, 10, page1.Width - 10, 150);
                gfx.DrawRectangle(XBrushes.SeaShell, rect);
                //tf.Alignment = ParagraphAlignment.Left;
                tf.DrawString(report.ToString(), font, XBrushes.Black, rect, XStringFormats.TopLeft);

                XImage img = XImage.FromFile("diagram.png");

                gfx.DrawImage(img, (page1.Width - img.PixelWidth / 1.5) / 2.0, 250, img.PixelWidth / 1.5, img.PixelHeight / 1.5);

                //page#2 - roots
                const int stringsPerPage = 50;
                int       k = 0;
                for (; k < this.roots.Count; k += stringsPerPage)
                {
                    StringBuilder rootsStr = new StringBuilder();
                    if (k == 0)
                    {
                        rootsStr.AppendLine("Roots found:\r\n");
                    }

                    for (int i = 0; i < stringsPerPage && i + k < this.roots.Count; i++)
                    {
                        rootsStr.AppendLine(string.Format("{0}", this.roots[i + k]));
                    }
                    PdfPage page2 = doc.AddPage();
                    gfx = XGraphics.FromPdfPage(page2);
                    gfx.DrawRectangle(XBrushes.White, rect);
                    tf   = new XTextFormatter(gfx);
                    rect = new XRect(10, 10, page2.Width - 10, page2.Height - 10);
                    tf.DrawString(rootsStr.ToString(), font, XBrushes.Black, rect, XStringFormats.TopLeft);
                }

                using (FileStream fStream = new FileStream("report.pdf", FileMode.Create))
                {
                    doc.Save(fStream);
                }
                Process.Start("report.pdf");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }