Click here to Skip to main content
15,896,036 members
Articles / Programming Languages / C#

Universal Framework for Science and Engineering - Part 2: Regression

Rate me:
Please Sign up or sign in to vote.
4.77/5 (19 votes)
11 Jul 20067 min read 51.2K   5K   76  
An article on universal scalable engineering framework applications.
using System;
using System.Collections.Generic;
using System.Text;

using System.Windows.Forms;
using System.Drawing;

using Chart;

namespace Chart
{
    /// <summary>
    /// Performer of chart
    /// </summary>
    public class ChartPerformer
    {
        /// <summary>
        /// Shift delta
        /// </summary>
        const int DELTA = 5;

        /// <summary>
        /// Control to draw
        /// </summary>
        protected Control control = null;




        /// <summary>
        /// internal insets 
        /// </summary>
        protected int[,] internalInsets = new int[,] { { 0, 0 }, { 0, 0 } };

        /// <summary>
        /// Array of series
        /// </summary>
        protected List<ISeries> series = new List<ISeries>();


        protected Dictionary<ISeries, ISeriesPainter> painters = new Dictionary<ISeries, ISeriesPainter>();

        /// <summary>
        /// Size of canvas
        /// </summary>
        protected int[] size = new int[2];

        /// <summary>
        /// Physical size
        /// </summary>
        protected double[,] dSize = new double[2, 2];

        /// <summary>
        /// Insets
        /// </summary>
        protected int[,] insets;

        /// <summary>
        /// Temporary buffer
        /// </summary>
        protected Image iTemp;

        /// <summary>
        /// Buffer
        /// </summary>
        protected Image image;

        /// <summary>
        /// Auxiliary variable
        /// </summary>
        protected int xp;

        /// <summary>
        /// Auxiliary variable
        /// </summary>
        protected int yp;

        /// <summary>
        /// Auxiliary variable
        /// </summary>
        protected int xc;

        /// <summary>
        /// Auxiliary variable
        /// </summary>
        protected int yc;

        /// <summary>
        /// Rectangle for drawing
        /// </summary>
        protected Rectangle r = new Rectangle();

        /// <summary>
        /// Painter of coordinates
        /// </summary>
        protected ICoordPainter coordPainter = null;

        /// <summary>
        /// The "is mouse moved" sign
        /// </summary>
        protected bool isMoved;

        /// <summary>
        /// Pen for coordinates drawing
        /// </summary>
        protected Pen linePen;

        /// <summary>
        /// Source rectangle
        /// </summary>
        protected Rectangle sR;

        /// <summary>
        /// Descination rectangle
        /// </summary>
        protected Rectangle dR;

        /// <summary>
        /// The invert x - axis sign
        /// </summary>
        protected bool invertX = false;


        /// <summary>
        /// The invert y - axis sign
        /// </summary>
        protected bool invertY = false;

        /// <summary>
        /// Background color
        /// </summary>
        protected Color backColor;

        /// <summary>
        /// Step along x axis
        /// </summary>
        protected int stepX = 0;

        /// <summary>
        /// Step alogn y axis
        /// </summary>
        protected int stepY = 0;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="control">Control to draw</param>
        /// <param name="insets">Insets</param>
        public ChartPerformer(Control control, int[,] insets)
        {
            this.control = control;
            this.insets = insets;
            control.MouseDown += new MouseEventHandler(onMouseDown);
            control.MouseUp += new MouseEventHandler(onMouseUp);
            control.MouseMove += new MouseEventHandler(onMouseMove);
            control.MouseLeave += new EventHandler(onMouseLeave);
            linePen = new Pen(Color.Black);
            sR = new Rectangle();
            dR = new Rectangle();
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="size">Size</param>
        /// <param name="insets">insets</param>
        public ChartPerformer(int[] size, int[,] insets, Color backColor)
        {
            this.size = size;
            this.insets = insets;
            this.backColor = backColor;
            linePen = new Pen(Color.Black);
            sR = new Rectangle();
            dR = new Rectangle();
            image = new Bitmap(size[0], size[1]);
            iTemp = new Bitmap(size[0], size[1]);
            Image im = image;
            Graphics g = Graphics.FromImage(im);
            Color back = bkgnd;
            g.FillRectangle(new SolidBrush(back), 0, 0, im.Width, im.Height);
            g.Dispose();
            im = iTemp;
            g = Graphics.FromImage(im);
            g.FillRectangle(new SolidBrush(back), 0, 0, im.Width, im.Height);
            g.Dispose();
        }

        /// <summary>
        /// Constuctor
        /// </summary>
        protected ChartPerformer()
        {
        }


        /// <summary>
        /// Adds histogram
        /// </summary>
        /// <param name="histogram">Histogram</param>
        /// <param name="color">Color</param>
 /*       public void AddHistogram(double[,] histogram, Color color)
        {
            histograms.Add(new object[] { histogram, color });
        }*/

        /// <summary>
        /// Access to size
        /// </summary>
        public double this[int i, int j]
        {
            get
            {
                return dSize[i, j];
            }
            set
            {
                dSize[i, j] = value;
            }
        }


        /// <summary>
        /// Step along x axis
        /// </summary>
        public int StepX
        {
            get
            {
                return stepX;
            }
            set
            {
                stepX = value;
            }
        }

        /// <summary>
        /// Step alogn y axis
        /// </summary>
        public int StepY
        {
            get
            {
                return stepY;
            }
            set
            {
                stepY = value;
            }
        }


        /// <summary>
        /// Internal insets
        /// </summary>
        public int[,] InternalInsets
        {
            get
            {
                return internalInsets;
            }
        }

        /// <summary>
        /// The invert x - axis sign
        /// </summary>
        public bool InvertX
        {
            get
            {
                return invertX;
            }
            set
            {
                invertX = value;
            }
        }

        /// <summary>
        /// The invert y - axis sign
        /// </summary>
        public bool InvertY
        {
            get
            {
                return invertY;
            }
            set
            {
                invertY = value;
            }
        }

        /// <summary>
        /// Painter of coordinates
        /// </summary>
        public ICoordPainter Coordinator
        {
            set
            {
                coordPainter = value;
            }
        }

        /// <summary>
        /// Adds series
        /// </summary>
        /// <param name="s">Series to add</param>
        public void AddSeries(ISeries s, Color color)
        {
            series.Add(s);
            painters[s] = new SimpleSeriesPainter(this, color);
        }


        public void AddSeries(ISeries s, ISeriesPainter painter)
        {
            series.Add(s);
            painters[s] = painter;
        }

        /// <summary>
        /// Access to series
        /// </summary>
        public ISeries this[int n]
        {
            get
            {
                return series[n];
            }
        }

        /// <summary>
        /// Count of series
        /// </summary>
        public int Count
        {
            get
            {
                return series.Count;
            }
        }

        /// <summary>
        /// The last series
        /// </summary>
        public ISeries Last
        {
            get
            {
                if (series.Count == 0)
                {
                    return null;
                }
                return this[Count - 1];
            }
        }

        /// <summary>
        /// Removes all series
        /// </summary>
        public void RemoveAll()
        {
            series.Clear();
            //histograms.Clear();
        }

        /// <summary>
        /// Removes a series
        /// </summary>
        /// <param name="s">The series to remove</param>
        public void Remove(ISeries s)
        {
            series.Remove(s);
            if (painters.ContainsKey(s))
            {
                painters.Remove(s);
            }
        }

        /// <summary>
        /// Size calculation
        /// </summary>
        public void CalculateSize()
        {
            for (int i = 0; i < Count; i++)
            {
                ISeries s = this[i];
                double[,] size = s.Size;
                if (i == 0)
                {
                    for (int j = 0; j < 2; j++)
                    {
                        for (int k = 0; k < 2; k++)
                        {
                            dSize[j, k] = size[j, k];
                        }
                    }
                    continue;
                }
                for (int j = 0; j < 2; j++)
                {
                    if (size[0, j] < dSize[0, j])
                    {
                        dSize[0, j] = size[0, j];
                    }
                    if (size[1, j] > dSize[1, j])
                    {
                        dSize[1, j] = size[1, j];
                    }
                }
            }
            //resizeHistograms();
            for (int i = 0; i < 2; i++)
            {
                double[] p = new double[3];
                double a = size[i] + internalInsets[i, 0] + internalInsets[i, 1];
                p[0] = (double)internalInsets[0, i] / a;
                p[1] = (double)size[i] / a;
                p[2] = (double)internalInsets[1, i] / a;
                double min = dSize[0, i];
                double max = dSize[1, i];
                dSize[0, i] = min - p[0] * (max - min);
                dSize[1, i] = max + p[2] * (max - min);
            }
            for (int i = 0; i < 2; i++)
            {
                if (dSize[0, i] == dSize[1, i])
                {
                    if (dSize[1, i] > 0)
                    {
                        dSize[0, i] = 0;
                        dSize[1, i] *= 1.1;
                    }
                    else if (dSize[1, i] < 0)
                    {
                        dSize[1, i] = 0;
                        dSize[0, i] *= 1.1;
                    }
                    else
                    {
                        dSize[0, i] = -1;
                        dSize[1, i] = 1;
                    }
                }
            }
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    if (Double.IsNaN(dSize[i, j]))
                    {
                        throw new Exception("NaN");
                    }
                }
            }
        }

        public void Transform(double[] x, int[] point)
        {
            if (InvertX)
            {
                point[0] = (int)((double)(size[0])
                    * ((x[0] - dSize[1, 0]) / (dSize[0, 0] - dSize[1, 0])));
            }
            else
            {
                point[0] = (int)((double)((size[0])
                    * (x[0] - dSize[0, 0]) / (dSize[1, 0] - dSize[0, 0])));
            }
            if (InvertY)
            {
                point[1] = size[1]
                    - (int)((double)((size[1])
                    * ((x[1] - dSize[1, 1]) / (dSize[0, 1] - dSize[1, 1]))));
            }
            else
            {
                point[1] = size[1] - (int)((double)((size[1])
                    * ((x[1] - dSize[0, 1]) / (dSize[1, 1] - dSize[0, 1]))));
            }
        }


        /// <summary>
        /// Size of canvas
        /// </summary>
        public int[] CanvasSize
        {
            get
            {
                return size;
            }
        }

        /// <summary>
        /// Resizes itself
        /// </summary>
        public void Resize()
        {
            if (control != null)
            {
                size[0] = control.Width - insets[0, 0] - insets[1, 0];
                size[1] = control.Height - insets[0, 1] - insets[1, 1];
                image = new Bitmap(size[0], size[1]);
                iTemp = new Bitmap(size[0], size[1]);
            }
            else
            {
                image = new Bitmap(size[0], size[1]);
                iTemp = new Bitmap(size[0], size[1]);
                Image im = image;
                Graphics g = Graphics.FromImage(im);
                Color back = bkgnd;
                g.FillRectangle(new SolidBrush(back), 0, 0, im.Width, im.Height);
                g.Dispose();
                im = iTemp;
                g = Graphics.FromImage(im);
                g.FillRectangle(new SolidBrush(back), 0, 0, im.Width, im.Height);
                g.Dispose();
            }
            CalculateSize();
        }

        /// <summary>
        /// Bitmap
        /// </summary>
        public Image Image
        {
            get
            {
                Bitmap bitmap = new Bitmap(size[0] + insets[0, 0] + insets[1, 0],
                    size[1] + insets[0, 1] + insets[1, 1]);
                Paint();
                Graphics g = Graphics.FromImage(bitmap);
                g.FillRectangle(new SolidBrush(backColor), 0, 0, bitmap.Width, bitmap.Height);
                g.DrawImage(image, insets[0, 0], insets[0, 1]);
                if (coordPainter != null)
                {
                    coordPainter.DrawCoord(g, insets, dSize, size);
                }
                g.Dispose();
                return bitmap;
            }
        }

        /// <summary>
        /// Paints itself
        /// </summary>
        public void Paint()
        {
            if (image == null)
            {
                return;
            }
            Brush brush = new SolidBrush(bkgnd);
            Graphics gi = Graphics.FromImage(image);
            gi.FillRectangle(brush, 0, 0, image.Width, image.Height);
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    if (Double.IsNaN(dSize[i, j]))
                    {
                        return;
                    }
                }
            }
            if (coordPainter != null)
            {
                coordPainter.DrawCoord(gi, dSize, size);
            }
            for (int i = 0; i < Count; i++)
            {
                ISeries s = this[i];
                ISeriesPainter p = null;
                if (painters.ContainsKey(s))
                {
                    p = painters[s];
                }
                else
                {
                    p = new SimpleSeriesPainter(this, Color.Black);
                    painters[s] = p;
                }
                if (p != null)
                {
                    p.Draw(s, gi);
                }
            }
            //drawHistograms(gi);
            gi.Dispose();
            gi = Graphics.FromImage(iTemp);
            gi.DrawImage(image, 0, 0);
            gi.Dispose();
        }




        /// <summary>
        /// Paints itself
        /// </summary>
        /// <param name="g">Graphics to paint</param>
        public void Paint(Graphics g)
        {
            if (image == null)
            {
                return;
            }
            g.DrawImage(iTemp, insets[0, 0], insets[0, 1]);
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    if (Double.IsNaN(dSize[i, j]))
                    {
                        return;
                    }
                }
            }
            if (coordPainter != null)
            {
                if (control != null)
                {
                    coordPainter.ClearInsets(control, insets);
                    Graphics gc = Graphics.FromHwnd(control.Handle);
                    coordPainter.DrawCoord(gc, insets, dSize, size);
                    gc.Dispose();
                }
            }
        }



        /// <summary>
        /// Performs all refresh operations
        /// </summary>
        public virtual void RefreshAll()
        {
            Resize();
            CalculateSize();
            Paint();
            if (coordPainter != null)
            {
                if (control != null)
                {
                    coordPainter.ClearInsets(control, insets);
                }
            }
            if (control != null)
            {
                Graphics g = Graphics.FromHwnd(control.Handle);
                Paint(g);
            }
        }

        /// <summary>
        /// Refreshs itself
        /// </summary>
        public void Refresh()
        {
            //Resize();
            //CalculateSize();
            Paint();
            if (coordPainter != null)
            {
                if (control != null)
                {
                    coordPainter.ClearInsets(control, insets);
                }
            }
            if (control != null)
            {
                control.Refresh();
            }
        }

        /// <summary>
        /// The temporary buffer
        /// </summary>
        public Image Buffer
        {
            get
            {
                return iTemp;
            }
        }

        /// <summary>
        /// Physical - screen transformation
        /// </summary>
        /// <param name="x">Physical x - coordinate</param>
        /// <param name="y">Physical y - coordinate</param>
        /// <param name="p">Screen coordinates</param>
        public void Transform(double x, double y, int[] p)
        {
            if (invertX)
            {
                p[0] = (int)((double)size[0] * ((x - dSize[1, 0]) / (dSize[0, 0] - dSize[1, 0])));
            }
            else
            {
                p[0] = (int)((double)size[0] * ((x - dSize[0, 0]) / (dSize[1, 0] - dSize[0, 0])));
            }
            if (invertY)
            {
                p[1] = size[1] - (int)((double)size[1] * ((y - dSize[1, 1]) /
                    (dSize[0, 1] - dSize[1, 1])));
            }
            else
            {
                p[1] = size[1] - (int)((double)size[1] * ((y - dSize[0, 1]) /
                    (dSize[1, 1] - dSize[0, 1])));
            }
        }

        /// <summary>
        /// On mouse down event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        protected void onMouseDown(object sender, MouseEventArgs e)
        {
            xp = e.X - insets[0, 0];
            yp = e.Y - insets[0, 1];
            isMoved = true;
        }

        /// <summary>
        /// Draws histogram
        /// </summary>
        /// <param name="o">Histogram object</param>
        /// <param name="g">Graphics</param>
        protected void drawHistogram(object[] o, Graphics g)
        {
            double[,] hist = (double[,])o[0];
            Color color = (Color)o[1];
            double step = hist[1, 0] - hist[0, 0];
            double[] x = new double[2];
            int[] il = new int[2];
            int[] ir = new int[2];
            Pen pen = new Pen(Color.Black);
            Brush brush = new SolidBrush(color);
            for (int i = 0; i < hist.GetLength(0); i++)
            {
                x[0] = hist[i, 0];
                x[1] = hist[i, 1];
                Transform(x, il);
                x[0] += step;
                x[1] = 0;
                Transform(x, ir);
                int w = ir[0] - il[0];
                int h = ir[1] - il[1];
                g.FillRectangle(brush, il[0], il[1], w, h);
                g.DrawRectangle(pen, il[0], il[1], w, h);
            }
        }


        /// <summary>
        /// Draws all histograms
        /// </summary>
        /// <param name="g">Graphics to draw</param>
  /*      protected void drawHistograms(Graphics g)
        {
            foreach (object[] o in histograms)
            {
                drawHistogram(o, g);
            }
        }*/


        /// <summary>
        /// On mouse up event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        protected void onMouseUp(object sender, MouseEventArgs e)
        {
            if ((xp < xc) & (yp < yc))
            {
                double xb = dSize[0, 0];
                double xd = dSize[1, 0] - dSize[0, 0];
                dSize[0, 0] = xb + (double)xp * xd / (double)(size[0]);
                dSize[1, 0] = xb + (double)xc * xd / (double)(size[0]);
                double yb = dSize[1, 1];
                double yd = dSize[1, 1] - dSize[0, 1];
                dSize[0, 1] = yb - (double)yc * yd / (double)(size[1]);
                dSize[1, 1] = yb - (double)yp * yd / (double)(size[1]);
                Refresh();
            }
            else
            {
                RefreshAll();
            }
            Graphics g = Graphics.FromImage(iTemp);
            g.DrawImage(image, 0, 0);
            g.Dispose();
            isMoved = false;
        }

        /// <summary>
        /// On mouse leave event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        protected void onMouseLeave(object sender, EventArgs e)
        {
            if (isMoved)
            {
                RefreshAll();
                isMoved = false;
            }

        }

        /// <summary>
        /// On mouse move event handler
        /// </summary>
        /// <param name="sender">The sender</param>
        /// <param name="e">The event arguments</param>
        protected void onMouseMove(object sender, MouseEventArgs e)
        {
            if (!isMoved)
            {
                return;
            }
            xc = e.X - insets[0, 0];
            yc = e.Y - insets[0, 1];
            int xmin, ymin, xmax, ymax;
            if (xp > xc)
            {
                xmin = xc;
                xmax = xp;
            }
            else
            {
                xmin = xp;
                xmax = xc;
            }
            if (yp > yc)
            {
                ymin = yc;
                ymax = yp;
            }
            else
            {
                ymin = yp;
                ymax = yc;
            }
            Graphics g = Graphics.FromImage(iTemp);
            dR.X = xmin - DELTA;
            dR.Y = ymin - DELTA;
            dR.Width = 2 * DELTA + xmax - xmin;
            dR.Height = 2 * DELTA + ymax - ymin;
            sR.X = xmin - DELTA;
            sR.Y = ymin - DELTA;
            sR.Width = 2 * DELTA + xmax - xmin;
            sR.Height = 2 * DELTA + ymax - ymin;
            g.DrawImage(image, dR, sR, GraphicsUnit.Pixel);
            g.DrawRectangle(linePen, xmin, ymin, xmax - xmin, ymax - ymin);
            g.Dispose();
            g = Graphics.FromHwnd(control.Handle);
            dR.X = xmin - DELTA + insets[0, 0];
            dR.Y = ymin - DELTA + insets[0, 1];
            dR.Width = 2 * DELTA + xmax - xmin;
            dR.Height = 2 * DELTA + ymax - ymin;
            sR.X = xmin - DELTA;
            sR.Y = ymin - DELTA;
            sR.Width = 2 * DELTA + xmax - xmin;
            sR.Height = 2 * DELTA + ymax - ymin;
            g.DrawImage(iTemp, dR, sR, GraphicsUnit.Pixel);
            g.Dispose();
        }

        /// <summary>
        /// Resizes histogram
        /// </summary>
        /// <param name="o">Diagram object</param>
        protected void resizeHistogram(object[] o)
        {
            double[,] hist = o[0] as double[,];
            if (hist[0, 0] < dSize[0, 0])
            {
                dSize[0, 0] = hist[0, 0];
            }
            double a = hist[hist.GetLength(0) - 1, 0] + hist[1, 0] - hist[0, 0];
            if (a > dSize[1, 0])
            {
                dSize[1, 0] = a;
            }
            if (dSize[0, 1] > 0)
            {
                dSize[0, 1] = 0;
            }
            for (int i = 0; i < hist.GetLength(0); i++)
            {
                a = hist[i, 1];
                if (dSize[1, 1] < a)
                {
                    dSize[1, 1] = a;
                }
            }
        }

        /// <summary>
        /// Resizes all histograms
        /// </summary>
 /*       protected void resizeHistograms()
        {
            foreach (object[] o in histograms)
            {
                resizeHistogram(o);
            }
        }*/

        /// <summary>
        /// Background color
        /// </summary>
        protected Color bkgnd
        {
            get
            {
                if (control != null)
                {
                    return control.BackColor;
                }
                return backColor;
            }
        }
    }
}

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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
Russian Federation Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1

Comments and Discussions