# Draw a parametric heart-shaped curve in C#

It’s almost Valentine’s Day so once again it’s time to think about how to draw a heart-shaped curve. The post Plot a heart-shaped function in C# shows one method for plotting a fairly complex function.

This example plots the following simpler parametric equations:

As the parameter t varies from 0 to 2π, the equations generate X and Y coordinates that trace out the heart-shaped curve.

The following code shows how the program calculates the X and Y coordinates for a particular t value.

```// The curve's parametric equations.
private float X(float t)
{
double sin_t = Math.Sin(t);
return (float)(16 * sin_t * sin_t * sin_t);
}
private float Y(float t)
{
return (float)(
13 * Math.Cos(t) -
5 * Math.Cos(2 * t) -
2 * Math.Cos(3 * t) -
Math.Cos(4 * t));
}```

These methods simply evaluate the parametric equations and return their results.

The following code shows how the program draws the curve.

```// Draw the curve on a bitmap.
private Bitmap DrawHeart(int width, int height)
{
Bitmap bm = new Bitmap(width, height);
using (Graphics gr = Graphics.FromImage(bm))
{
gr.SmoothingMode = SmoothingMode.AntiAlias;

// Generate the points.
const int num_points = 100;
List points = new List();
float dt = (float)(2 * Math.PI / num_points);
for (float t = 0; t <= 2 * Math.PI; t += dt)

// Get the coordinate bounds.
float wxmin = points[0].X;
float wxmax = wxmin;
float wymin = points[0].Y;
float wymax = wymin;
foreach (PointF point in points)
{
if (wxmin > point.X) wxmin = point.X;
if (wxmax < point.X) wxmax = point.X;
if (wymin > point.Y) wymin = point.Y;
if (wymax < point.Y) wymax = point.Y;
}

// Make the world coordinate rectangle.
RectangleF world_rect = new RectangleF(
wxmin, wymin, wxmax - wxmin, wymax - wymin);

// Make the device coordinate rectangle with a margin.
const int margin = 5;
Rectangle device_rect = new Rectangle(
margin, margin,
picGraph.ClientSize.Width - 2 * margin,
picGraph.ClientSize.Height - 2 * margin);

// Map world to device coordinates without distortion.
// Flip vertically so Y increases downward.
SetTransformationWithoutDisortion(gr,
world_rect, device_rect, false, true);

// Draw the curve.
gr.FillPolygon(Brushes.Pink, points.ToArray());
using (Pen pen = new Pen(Color.Red, 0))
{
gr.DrawPolygon(pen, points.ToArray());
}
}
return bm;
}```

After some preparation the code loops through 100 values for t to generate points on the curve. That part is short and reasonably straightforward. The bulk of this method figures out how to center the resulting curve.

To do that the code first loops through the curve's points to find the minimum and maximum X and Y coordinates. It uses those values to make a rectangle that encloses the points in world coordinates.

Next the method creates a rectangle giving the area in the PictureBox where the heart-shaped curve should be placed. The code subtracts a bit to leave a margin around the edges of the PictureBox.

The program then calls the SetTransformationWithoutDisortion method described in the post Map drawing coordinates without distortion in C# to prepare the Graphics object to map the world coordinates to the device coordinates.

Finally the method draws the polygon. The Graphics object's transformations automatically make the result fit the PictureBox nicely.