Click here to Skip to main content
15,883,901 members
Articles / Programming Languages / C#

Universal Framework for Science and Engineering - Part 6: Determination of Orbits of Artificial Satellites

Rate me:
Please Sign up or sign in to vote.
4.88/5 (28 votes)
8 Jul 2011CPOL19 min read 82.4K   6.6K   82  
An article on framework applications to determine the orbits of artificial satellites
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Reflection;


using Chart.Drawing.Interfaces;
using Chart.Drawing.Painters;

namespace Chart.Drawing
{
    /// <summary>
    /// Performer of chart
    /// </summary>
    public class ChartPerformer
    {

        #region Fields
        /// <summary>
        /// Shift delta
        /// </summary>
        const int DELTA = 5;

        /// <summary>
        /// Control to draw
        /// </summary>
        protected IControl virtualControl = 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>();

        /// <summary>
        /// Painters of series
        /// </summary>
        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>
        /// 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>
        /// The blocked sign
        /// </summary>
        protected bool isBlocked = false;

        /// <summary>
        /// The "is indicated" sign
        /// </summary>
        protected bool isIndicated = false;

 
        /// <summary>
        /// Width
        /// </summary>
        protected int width;

        /// <summary>
        /// Height
        /// </summary>
        protected int height;

        /// <summary>
        /// Calcuales size of area
        /// </summary>
        protected CalculateAreaSize calculateAreaSize;

 
        /// <summary>
        /// Children performers
        /// </summary>
        protected List<ChartPerformer> children = new List<ChartPerformer>();

        /// <summary>
        /// Parent performer
        /// </summary>
        protected ChartPerformer parent;

        #endregion

        #region Ctor

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="control">Control to draw</param>
        /// <param name="insets">Insets</param>
        public ChartPerformer(IControl control, int[,] insets)
            : this()
        {
            this.virtualControl = control;
            this.insets = insets;
            linePen = new Pen(Color.Black);
            sR = new Rectangle();
            dR = new Rectangle();
            SetInsets();
        }


        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="size">Size</param>
        /// <param name="insets">insets</param>
        /// <param name="backColor">Bacground color</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();
            SetInsets();
        }


        /// <summary>
        /// Constuctor
        /// </summary>
        protected ChartPerformer()
        {
            calculateAreaSize = delegate()
            {
                width = virtualControl.Width;
                height = virtualControl.Height;
            };
        }

        #endregion

        #region Public Members

        /// <summary>
        /// Adds a performer
        /// </summary>
        /// <param name="performer">Performer to add</param>
        public void Add(ChartPerformer performer)
        {
            if (performer == this)
            {
                throw new Exception();
            }
            if (performer.parent != null)
            {
                throw new Exception();
            }
            children.Add(performer);
            performer.parent = this;
            foreach (ISeries s in painters.Keys)
            {
                performer.AddSeries(s, painters[s]);
            }
        }

        /// <summary>
        /// Removes a performer
        /// </summary>
        /// <param name="performer">Performer to remove</param>
        public void Remove(ChartPerformer performer)
        {
            children.Remove(performer);
        }

        /// <summary>
        /// Removes itself
        /// </summary>
        public void Remove()
        {
            if (parent != null)
            {
                parent.Remove(this);
                painters.Clear();
            }
        }

        /// <summary>
        /// The "is blocked" sign
        /// </summary>
        public bool IsBlocked
        {
            get
            {
                return isBlocked;
            }
            set
            {
                isBlocked = value;
                foreach (ChartPerformer p in children)
                {
                    p.IsBlocked = value;
                }
            }
        }

        /// <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
        {
            get
            {
                return coordPainter;
            }
            set
            {
                coordPainter = value;
            }
        }

        /// <summary>
        /// Calculator of area size
        /// </summary>
        public CalculateAreaSize CalculateAreaSize
        {
            get
            {
                return calculateAreaSize;
            }
            set
            {
                calculateAreaSize = value;
            }
        }


        /// <summary>
        /// Adds series
        /// </summary>
        /// <param name="s">Series to add</param>
        /// <param name="color">Color</param>
        public void AddSeries(ISeries s, Color color)
        {
            ISeriesPainter p = new SimpleSeriesPainter(color);
            AddSeries(s, p);
        }


        public void AddSeries(ISeries s, ISeriesPainter painter)
        {
            if (parent != null)
            {
                parent.AddSeries(s, painter);
                return;
            }
            series.Add(s);
            painter.Performer = this;
            painters[s] = painter;
            foreach (ChartPerformer ch in children)
            {
                ISeriesPainter p = painter.Clone() as ISeriesPainter;
                ch.AddSeries(s, p);
            }
        }

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


        /// <summary>
        /// Removes series those have attribute
        /// </summary>
        /// <param name="attributeType"></param>
        public void Remove(Type attributeType)
        {
            List<ISeries> l = new List<ISeries>();
            foreach (ISeries s in series)
            {
                Type type = s.GetType();
                object[] da = type.GetCustomAttributes(attributeType, true);
                if (da != null)
                {
                    if (da.Length > 0)
                    {
                        l.Add(s);
                    }
                }
            }
            l.ForEach(delegate(ISeries s)
            {
                series.Remove(s);
            }
        );
        }

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

        }

        /// <summary>
        /// Size calculation
        /// </summary>
        public void CalculateSize()
        {
            if (Count == 0)
            {
                dSize[0, 0] = -1;
                dSize[0, 1] = -1;
                dSize[1, 0] = 1;
                dSize[1, 1] = 1;
                return;
            }
            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;
                    }
                }
            }
            if (dSize[0, 1] != dSize[1, 1])
            {
                double delta = 0.02 * (dSize[1, 1] - dSize[0, 1]);
                dSize[0, 1] -= delta;
                dSize[1, 1] += delta;
            }
            IsNaN(true);
        }



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

        /// <summary>
        /// Resizes itself
        /// </summary>
        public void Resize()
        {
            if (isBlocked)
            {
                return;
            }
            if (virtualControl != null)
            {
                calculateAreaSize();
                size[0] = width - insets[0, 0] - insets[1, 0];
                size[1] = height - insets[0, 1] - insets[1, 1];
                if (size[0] <= 0 | size[1] <= 0)
                {
                    return;
                }
                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(Bkgnd), 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 (isBlocked)
            {
                return;
            }
            if (image == null)
            {
                return;
            }
            Brush brush = new SolidBrush(Bkgnd);
            Graphics gi = Graphics.FromImage(image);
            gi.FillRectangle(brush, 0, 0, image.Width, image.Height);
            if (IsNaN(false))
            {
                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(Color.Black);
                    p.Performer = this;
                    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 virtual void Paint(Graphics g)
        {
            if (isBlocked)
            {
                return;
            }
            if (image == null)
            {
                return;
            }
            g.DrawImage(iTemp, insets[0, 0], insets[0, 1]);
            if (IsNaN(false))
            {
                return;
            }
        }




        /// <summary>
        /// Performs all refresh operations
        /// </summary>
        public virtual void RefreshAll()
        {
            if (isBlocked)
            {
                return;
            }
            Resize();
 //           CalculateSize();
            Paint();
            if (coordPainter != null)
            {
                if (virtualControl != null)
                {
                    coordPainter.ClearInsets(virtualControl, insets);
                }
            }
       }



        /// <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>
        /// Physical - screen transformation
        /// </summary>
        /// <param name="x">Physisical coordinates</param>
        /// <param name="point">Screen coordinates</param>
        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>
        /// Screen - physical coordinates
        /// </summary>
        /// <param name="ix">Screen x - coordinate</param>
        /// <param name="iy">Screen y - coordinate</param>
        /// <param name="x">Physical x - coordinate</param>
        /// <param name="y">Physical y - coordinate</param>
        public void Transform(int ix, int iy, out double x, out double y)
        {
            x = 0;
            y = 0;
            int sx = size[0];
            int sy = size[1];
            double dx = dSize[0, 0] - dSize[1, 0];
            double dy = dSize[0, 1] - dSize[1, 1];
            double scx = 0;
            double scy = 0;
            try
            {
                scx = -dx / (double)sx;
                scy = dy / (double)sy;
            }
            catch (Exception)
            {
                return;
            }
            double ddx = scx * (double)(ix - insets[0, 0]);
            double ddy = scy * (double)(iy - insets[0, 1]);
            if (InvertX)
            {
                x = dSize[1, 0] - ddx;
            }
            else
            {
                x = ddx + dSize[0, 0];
            }
            if (InvertY)
            {
                y = ddy - dSize[1, 1];
            }
            else
            {
                y = dSize[1, 1] + ddy;
            }
        }

        #endregion

        #region Protected & Private Members

        /// <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>
        /// 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>
        /// Background color
        /// </summary>
        protected Color Bkgnd
        {
            get
            {
                if (virtualControl != null)
                {
                    return virtualControl.BackColor;
                }
                return backColor;
            }
        }

        private bool IsNaN(bool exception)
        {
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    if (Double.IsNaN(dSize[i, j]))
                    {
                        series.Clear();
                        CalculateSize();
                        if (exception)
                        {
                            throw new Exception("NAN");
                        }
                        return true;
                    }
                }
            }
            return false;
        }

        void SetInsets()
        {
            Bitmap bmp = new Bitmap(2, 2);
            Graphics g = Graphics.FromImage(bmp);
            insets[1, 1] = (int)((g.DpiY / 96f) * (float)insets[1, 1]);
        }


        #endregion

    }


    #region Delegates

    /// <summary>
    /// Calculates Area size
    /// </summary>
    public delegate void CalculateAreaSize();


    #endregion
}

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
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