Plot a Valantine's heart on your screen

ddanbe 3 Tallied Votes 354 Views Share

There are many pictures of hearts out there.
I just wanted to draw a picture of a heart on my own from a math formula I found on the net.
Seems there are many formulas to find.
This is how it looks:
Heart.PNG
Enjoy!

Santanu.Das commented: Excellent +8
// Set up a WindowsForm application in Visual Studio, I named mine HeartPlot
// Make the size of the window about 500x500 pixels
// Make a fancy label on the form and fill in the following code for the Form1.cs file
// Code for a PolarPoint.cs and a Plot.cs file follow

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace HeartPlot
{
    public partial class Form1 : Form
    {
        private List<PointF> Coords;

        public Form1()
        {
            InitializeComponent();
            Coords = new List<PointF>();
        }

        private void PlotHeart(Graphics G)
        {
            Plot MyPlot = new Plot(this.Size);
            MyPlot.SetPlotPort(-5, 5, -5, 7);
            float a, b, r;
            Coords.Clear();
            for (double Th = 0.0; Th < 2.0 * Math.PI; Th += Math.PI / 180.0)
            {
                a = (float)Math.Sqrt(Math.Abs(Math.Cos(Th)));
                b = (float)Math.Sin(Th);
                r = b * a / (b + 1.4f) - 2f * b + 2f;
                PolarPointF P = new PolarPointF(r, (float)Th);
                Coords.Add(P.ToCarthesian());
            }
            float PencilWidth = 2.0f;
            Pen Pencil = new Pen(Color.Red, PencilWidth);
            MyPlot.PlotPoints(Coords, Pencil, G);
           // MyPlot.PlotAxes(G);
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            PlotHeart(e.Graphics);
        }
    }
}

//////////////////////////////////
// Code for the file PolarPoint.cs
//////////////////////////////////

using System;
using System.Drawing;


namespace HeartPlot
{
    /// <summary>
    /// A polar point defined by the radius (r) and the angle (Theta)
    /// </summary>
    public struct PolarPointF
    {
        public PolarPointF(float r, float Theta) : this()
        {
            this.r = r;
            this.Theta = Theta;
        }

        public float r { get; set; }

        public float Theta { get; set; }

        /// <summary>
        /// Converts a polar point to a carthesian coordinates, with Theta expressed in radians
        /// </summary>
        /// <returns>A PointF structure</returns>
        public PointF ToCarthesian()
        {
            return new PointF((float)(this.r * Math.Cos(this.Theta)), (float)(this.r * Math.Sin(this.Theta)));
        }

        /// <summary>
        /// Converts a PointF, representing carthesian coordinates to a PolarPointF
        /// </summary>
        /// <param name="P"></param>
        /// <returns></returns>
        public static PolarPointF FromCarthesian(PointF P)
        {
            float r = (float)Math.Sqrt(P.X * P.X + P.Y * P.Y);
            float Theta = (float)Math.Atan2(P.X, P.Y); // arctan with a "twist", see the Math class
            return new PolarPointF(r, Theta);
        }
    } 
}

//////////////////////////////////
// Code for the file PolarPoint.cs
//////////////////////////////////

using System;
using System.Collections.Generic;
using System.Drawing;

namespace HeartPlot
{
    /// <summary>
    /// 
    /// class to plot x and y values on a Form or Panel
    /// 
    /// 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
    /// 
    /// Update 3.0 DM 13-2-2018
    /// 
    /// </summary>
    public class Plot
    {
        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;

        public Plot() { }

        public Plot(Size Plotarea)
        {
            _ClientArea = Plotarea;
            SetPlotPort(-10, 10, -10, 10); //default
        }

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

        /// <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)
        {
            //set the bounderies of the form(screen) to real coordinates.
            _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, Graphics G)
        {
            //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); string s = Convert.ToString("astr");
        }

        public void PlotAxes(Graphics G)
        {
            Pen AxisPen = new Pen(Color.Red)
            {
                DashStyle = System.Drawing.Drawing2D.DashStyle.Dash
            };
            // X-Axis
            PointF X0 = new PointF(_PlotW.minX, _PlotW.minY + _Yspan / 2f);
            PointF X1 = new PointF(_PlotW.maxX, _PlotW.minY + _Yspan / 2f);
            //Y-Axis
            PointF Y0 = new PointF(_PlotW.minX + _Xspan / 2f, _PlotW.maxY);
            PointF Y1 = new PointF(_PlotW.minX + _Xspan / 2f, _PlotW.minY);

            G.DrawLine(AxisPen, ToScreen(X0), ToScreen(X1));
            G.DrawLine(AxisPen, ToScreen(Y0), ToScreen(Y1));

        }

        /// <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, Graphics G)
        {
            //for (int k = 1; k < thePts.Count; k++)
            //{
            //    G.DrawLine(P, ToScreen(thePts[k - 1]), ToScreen(thePts[k]));
            //}
            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 incarthesian 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()
            {
                X = _ClientArea.Width / _Xspan * ptC.X + _ClientArea.Width / 2f,
                Y = -_ClientArea.Height / _Yspan * ptC.Y + _ClientArea.Height / 2f
            };
            return aP;
        }
    }
}