Printing a polar worksheet

ddanbe 2 Tallied Votes 253 Views Share

To refresh my mind I did some exercises about complex numbers. I was constantly drawing axes and arrows.
So I decided to print out some worksheets with a program to make my life a bit easier, and because it is always fun to design a little program to do that for me. Like to share this. Enjoy.
This how it can look on the screen.
Polarsheet.png

The listing just shows the main two classes.
In the possiblity that anyone would be interested in the whole project, I might send a zip file.
But it should be obvious how to come up with your own.

mattster commented: Very Nice! +6
using System;
using System.Collections.Generic;
using System.Drawing;

namespace ComplexNumberWorksheet
{
    class Plot
    {    
    /// <summary>
    /// class to plot x and y 2D carthesian coordinates on a Form or Panel or printer!
    /// 
    /// Because on the form coordinates start at the upper left corner with 0,0
    /// with the y coordinate going down, a little transformation is done here
    /// so that x,y coordinates act as normal carthesian coordinates, with 0,0
    /// in the center of the Form or Panel.
    /// There is Some support for polar coordinates also.
    /// DM 18 dec 2014
    /// </summary>
    
        struct PlotPort
        {
            public int minX;
            public int maxX;
            public int minY;
            public int maxY;
        };

        private PlotPort _PlotW;    //"window" of carthesian coordinates
        private Size _ClientArea;   //keeps the pixels info
        private float _Xspan;
        private float _Yspan;
        private Graphics _G;

        public Plot() { }

        public Plot(Size Plotarea, Graphics G)
        {
            _ClientArea = Plotarea;
            _G = G;
        }

        public Size ClientArea { set { _ClientArea = value; } }

        public Pen PlotPen { get; set; }

        public int AxisUnits { get; set; }

        /// <summary>
        /// Set the bounderies of the form(screen) to real(world) coordinates.
        /// </summary>
        /// <param name="minx">lowest x value</param>
        /// <param name="maxx">highest x value</param>
        /// <param name="miny">lowest y value</param>
        /// <param name="maxy">highest y value</param>
        public void SetPlotPort(int minx, int maxx, int miny, int maxy)
        {
            _PlotW.minX = minx;
            _PlotW.maxX = maxx;
            _PlotW.minY = miny;
            _PlotW.maxY = maxy;
            _Xspan = _PlotW.maxX - _PlotW.minX;
            _Yspan = _PlotW.maxY - _PlotW.minY;
        }

        public void PlotPixel(PointF P, Color C)
        {
            //workhorse of this class
            Bitmap bm = new Bitmap(1, 1);
            bm.SetPixel(0, 0, C);
            P = ToScreen(P);
            _G.DrawImageUnscaled(bm, (int)P.X, (int)P.Y);
        }

        public void PlotLine(PointF from, PointF to)
        {
            _G.DrawLine(PlotPen, ToScreen(from), ToScreen(to));
        }

        public void PlotCircle(PointF midPnt, float radius)
        {
            PointF pt = ToScreen(midPnt);
            _G.DrawEllipse(PlotPen, pt.X - radius * _ClientArea.Width / _Xspan,
                pt.Y - radius * _ClientArea.Height / _Yspan,
                2 * radius * _ClientArea.Width / _Xspan, 2 * radius * _ClientArea.Height / _Yspan);
        }

        public void PlotXGrid()
        {
            for (int i = 1; i < _PlotW.maxY - _PlotW.minY; i ++)
            {
                PlotLine(new PointF(_PlotW.minX, _PlotW.maxY - i), new PointF(_PlotW.maxX, _PlotW.maxY - i)); 
            }
        }

        public void PlotYGrid()
        {
            for (int i = 1; i < _PlotW.maxX - _PlotW.minX; i++)
            {
                PlotLine(new PointF(_PlotW.maxX - i, _PlotW.minY), new PointF(_PlotW.maxX - i, _PlotW.maxY));
            }
        }

        public void PlotGrid()
        {
            PlotXGrid();
            PlotYGrid();
        }

        public void PlotXAxis()
        {
            PlotPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            PlotPen.Width = 4;
            PointF X0 = new PointF(_PlotW.minX, _PlotW.minY + _Yspan / 2f);
            PointF X1 = new PointF(_PlotW.maxX, _PlotW.minY + _Yspan / 2f);
            _G.DrawLine(PlotPen, ToScreen(X0), ToScreen(X1));
            PlotPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
        }

        public void PlotYAxis()
        {
            PlotPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
            PlotPen.Width = 2;
            PointF Y0 = new PointF(_PlotW.minX + _Xspan / 2f, _PlotW.maxY);
            PointF Y1 = new PointF(_PlotW.minX + _Xspan / 2f, _PlotW.minY);
            _G.DrawLine(PlotPen, ToScreen(Y0), ToScreen(Y1));
            PlotPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
        }

        public void PlotAxes()
        {
            PlotXAxis();
            PlotYAxis();
        }

        public void PlotPolarLines(int angle, int lenght)
        {
            const double toRad = Math.PI / 180.0;

            float x = 0f;
            float y = 0f;

            for (int i = 0; i < 360; i+=angle)
            {
                x = (float)(lenght * Math.Cos(toRad * i));
                y = (float)(lenght * Math.Sin(toRad * i));
                PlotLine(new PointF(0f, 0f), new PointF(x, y));
            }
        }

        public PointF ToCarthesian(double Theta, double r)
        {          
            return new PointF((float)(r * Math.Cos(Theta)), (float)(r * Math.Sin(Theta)));          
        }

        /// <summary>
        /// Plot a list of carthesian points on the screen
        /// </summary>
        /// <param name="thePts"></param>
        /// <param name="G"></param>
        public void PlotPoints(List<PointF> thePts,Pen P)
        {
            PointF[] PtAr = thePts.ToArray();
            for (int k = 0; k < PtAr.Length; k++)
            {
                PtAr[k] = ToScreen(PtAr[k]);
            }
            _G.DrawLines(P, PtAr);
        }

        /// <summary>
        /// Transform a point in carthesian coordinates to a point on the screen
        /// </summary>
        /// <param name="ptC">The point in carthesian(world) coordinates</param>
        /// <returns>Transformed point to be plotted on the screen</returns>
        private PointF ToScreen(PointF ptC)
        {
            //PointF aP = new PointF();
            ptC.X = _ClientArea.Width / _Xspan * ptC.X + _ClientArea.Width / 2f;
            ptC.Y = -_ClientArea.Height / _Yspan * ptC.Y + _ClientArea.Height / 2f;
            return ptC;
        }
    }
}

//*******************FORM CLASS LISTING STARTS HERE****************

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

namespace ComplexNumberWorksheet
{
    public partial class Form1 : Form
    {
        private PrintDocument PrintDoc; 
        private int axDivisions = 1;
        private int polarAngle = 360;
        private bool showAxes = false;
        private bool showGrids = false;

        public Form1()
        {
            InitializeComponent();
            //Create a PrintDocument object
            PrintDoc = new PrintDocument();
            //Add PrintPage event handler
            PrintDoc.PrintPage += new PrintPageEventHandler(printAPage);
        }

        /// <summary>
        /// Routine to draw, be it on a Panel or PrintPreview or whatever
        /// </summary>
        /// <param name="S">Gives the rectangle size in pixels to draw in</param>
        /// <param name="g">Drawing needs a Graphics object</param>
        private void DrawStuff(Size S, Graphics g)
        {          
            Plot pos = new Plot(S, g);    
            pos.SetPlotPort(-axDivisions, axDivisions, -axDivisions, axDivisions);
            if (showAxes)
            {
                pos.PlotPen = new Pen(Color.Green, 2.5f);
                pos.PlotXAxis();
                pos.PlotYAxis();
            }
            if (showGrids)
            {
                pos.PlotPen = new Pen(Color.Blue);
                pos.PlotXGrid();
                pos.PlotYGrid();
            }

            pos.PlotPen = new Pen(Color.Red);
            pos.PlotPen.Width = 2;
            for (int radius = 1; radius <= axDivisions; radius++)
            {
                pos.PlotCircle(new Point(0, 0), radius);
            }
            pos.PlotPolarLines(polarAngle, axDivisions);
        }

        private void DrawPnl_Paint(object sender, PaintEventArgs e)
        {
            DrawStuff(this.DrawPnl.ClientSize, e.Graphics);
        }

        private void PreviewBtn_Click(object sender, EventArgs e)
        {         
            PrintPreviewDialog printPreviewDlg = new PrintPreviewDialog();
            ((Form)printPreviewDlg).WindowState = FormWindowState.Maximized;
            printPreviewDlg.Document = PrintDoc; //give the PrintDoc to the preview dialog
            printPreviewDlg.Show();            
        }

        private void PrintBtn_Click(object sender, EventArgs e)
        {           
            //Print the document, also fires the PrintPage eventhandler
            PrintDoc.Print();
        }

        private void printAPage(object sender, PrintPageEventArgs PE)
        {
            int sideLength = 0;
            if (PE.PageBounds.Width < PE.PageBounds.Height)
            {
                sideLength = PE.PageBounds.Width;
            }
            else
            {
                sideLength = PE.PageBounds.Height;
            }
            DrawStuff(new Size(sideLength, sideLength), PE.Graphics);
        }

        private void axDivisionsUpDwn_ValueChanged(object sender, EventArgs e)
        {
            this.axDivisions = (int)this.axDivisionsUpDwn.Value;
            this.Refresh();
        }

        private void polarAngleCmbBx_SelectedIndexChanged(object sender, EventArgs e)
        {
            string comboItem = this.polarAngleCmbBx.SelectedItem.ToString();
            comboItem = comboItem.Substring(0, comboItem.Length - 1);
            this.polarAngle = int.Parse(comboItem);
            this.Refresh();
        }

        private void plotAxesChkBx_CheckedChanged(object sender, EventArgs e)
        {
            showAxes = !showAxes;
            this.Refresh();
        }

        private void showGridsChBx_CheckedChanged(object sender, EventArgs e)
        {
            showGrids = !showGrids;
            this.Refresh();
        }             
    }
}