Click here to Skip to main content
15,892,072 members
Articles / Programming Languages / C#

LL Mathematical Parser

Rate me:
Please Sign up or sign in to vote.
4.88/5 (39 votes)
20 Jan 2010CPOL11 min read 70.7K   1.3K   82  
A mathematical parser based on Formal Language Theory constructs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MathParserDataStructures;
using System.Diagnostics;
namespace MathParser.v._3
{
    public partial class Parser : Form
    {
        Bitmap bitmap = null;
        public Parser()
        {
            InitializeComponent();
        }

        private void Parser_Load(object sender, EventArgs e)
        {
            _imagePanel.Location = new Point(this.ClientRectangle.Width / 2, 5);
            btnDraw.Location = new Point(_imagePanel.Width - (btnDraw.Width + 18), btnDraw.Location.Y);
            _btnClear.Location = new Point(_imagePanel.Width - (btnDraw.Width + 18), btnDraw.Location.Y + btnDraw.Size.Height + 5);
            _btnSave.Location = new Point(_imagePanel.Width - (btnDraw.Width + 18), btnDraw.Location.Y + btnDraw.Size.Height + _btnClear.Height + 10); 
            _imagePanel.Width = this.ClientRectangle.Width / 2 - 5;
            _imagePanel.Height = this.ClientRectangle.Height - 10;
            _tbFunction.Width = _imagePanel.Width - 8;
        }

        private void Parser_Paint(object sender, PaintEventArgs e)
        {
            this.DrawCoordinates();
        }

        private void DrawCoordinates()
        {
            int width = this._imagePanel.Width;
            int height = this._imagePanel.Height;
            int tenthHeigth = height / 10;
            int tenthWidth = width / 10;
            int penWidth = 3;
            Color penColor = Color.Red;
            if (height == 0 || width == 0)
                return;
            bitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bitmap); 
            
            g.Clear(this.BackColor);
            Pen pen = new Pen(penColor, penWidth);

            pen.EndCap = System.Drawing.Drawing2D.LineCap.ArrowAnchor;

            Point startPointVertical = new Point(tenthWidth, height - tenthHeigth);
            Point endPointVertical = new Point(tenthWidth, tenthHeigth);

            Point startPointHorizontal = startPointVertical;
            Point endPointHorizontal = new Point(width - tenthWidth, height - tenthHeigth);

            g.DrawLine(pen, startPointVertical, endPointVertical);
            g.DrawLine(pen, startPointHorizontal, endPointHorizontal);

            Font f = new Font(this._tbFunction.Font, FontStyle.Italic);
            Brush b = Brushes.Red;
            float offsetX = ((float)(endPointHorizontal.X - startPointHorizontal.X)) / 8;
            float offsetY = ((float)(startPointVertical.Y - endPointVertical.Y)) / 8;
            for (int i = 0; i <= 8; i++)
            {
                PointF p1 = new PointF((i * offsetX)+tenthWidth-5, startPointHorizontal.Y + 10);
                PointF p2 = new PointF(startPointVertical.X-20, i*offsetY+tenthHeigth-5);
                g.DrawString(i.ToString(), f, b, p1);
                g.DrawString((8-i).ToString(), f, b, p2);
            }

            this.CreateGraphics().DrawImage(bitmap, 0, 0);
            if (!String.IsNullOrEmpty(this._tbFunction.Text))
                btnDraw_Click(null, null);

        }

        private void Parser_Resize(object sender, EventArgs e)
        {
            _imagePanel.Location = new Point(this.ClientRectangle.Width/2, 5);
           _imagePanel.Width = this.ClientRectangle.Width / 2 - 5;
            _imagePanel.Height = this.ClientRectangle.Height - 10;
            btnDraw.Location = new Point(_imagePanel.Width - (btnDraw.Width + 5), btnDraw.Location.Y);
            _btnClear.Location = new Point(_imagePanel.Width - (btnDraw.Width + 5), btnDraw.Location.Y + btnDraw.Size.Height+5);
            _btnSave.Location = new Point(_imagePanel.Width - (btnDraw.Width + 5), btnDraw.Location.Y + btnDraw.Size.Height + _btnClear.Height + 10); 
            _tbFunction.Width = _imagePanel.Width - 8;
        }

        private void btnDraw_Click(object sender, EventArgs e)
        {
            int numberOfPoints = 500;
            string mathFunction = this._tbFunction.Text;
            if (String.IsNullOrEmpty(mathFunction))
                return;
            MathObj mathObj = new MathObj();
            PointF[] lineFunc = new PointF[numberOfPoints];
            int width = this._imagePanel.Width;
            int height = this._imagePanel.Height;
            int tenthHeigth = height / 10;
            int tenthWidth = width / 10;
            float offset = ((float)width * 10 / 10) / numberOfPoints;
            int startX= 0, endX = 10;
            double offsetX  = (double)(endX-startX)/numberOfPoints;
            double xVal = 0;

            char [] variablesArray = new char[1] { 'x' };
            double [] valuesArray = new double[1];

            for (int i = 0; i < numberOfPoints; i++)
            {
                lineFunc[i].X = tenthWidth + (float)(offset * (i + 1));
                
                try
                {/*
                  * ----------------------------------------
                  * Actual Mathematical calculation is here
                  * ----------------------------------------
                  */
                    valuesArray[0] = xVal;
                    lineFunc[i].Y = (height - tenthHeigth) - tenthHeigth * (float)mathObj.Evaluate(mathFunction, variablesArray, valuesArray);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                    return;
                }
                if (lineFunc[i].X > width || lineFunc[i].Y > height)
                {
                    lineFunc[i].X = lineFunc[i - 1].X;
                    lineFunc[i].Y = lineFunc[i - 1].Y;
                }

           // Debug.WriteLine("X: " + lineFunc[i].X.ToString() + " Y:" + lineFunc[i].Y.ToString());
                xVal += offsetX;
            }
           // Debug.WriteLine("tenthHeigth=" + tenthHeigth.ToString());
           // Debug.WriteLine("height=" + height.ToString());
            try
            {
                Graphics g = Graphics.FromImage(bitmap);
                g.DrawLines(new Pen(Color.Blue), lineFunc);
                this.CreateGraphics().DrawImage(bitmap, 0, 0);
            }
            catch (System.OverflowException ex)
            {
                MessageBox.Show("Could not draw the graph: " + ex.Message,"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
           
        }

        private void _btnClear_Click(object sender, EventArgs e)
        {
            this._tbFunction.Text = "";
            this.DrawCoordinates();
        }

        private void _btnSave_Click(object sender, EventArgs e)
        {
            SaveFileDialog s = new SaveFileDialog();
            s.FileName = "sample.jpg";
            s.Filter = "*.jpg|*.jpg";
            if (s.ShowDialog() == DialogResult.OK)
            {
                string path = s.FileName;
                bitmap.Save(path);
            }
        }

   
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Moldova (Republic of) Moldova (Republic of)
Interested in computer science, math, research, and everything that relates to innovation. Fan of agnostic programming, don't mind developing under any platform/framework if it explores interesting topics. In search of a better programming paradigm.

Comments and Discussions