Draw rose curves in C#

[rose curves]

A rose curve is a curve generated by the polar coordinate equation r = cos(n / d * θ). Here n and d should be relatively prime, so the fraction n / d cannot be simplified.


When you click the Draw button, the following event handler executes.

private void btnDraw_Click(object sender, EventArgs e)
{
    float A = float.Parse(txtA.Text);
    int n = int.Parse(txtN.Text);
    int d = int.Parse(txtD.Text);

    // Make the Bitmap and associated Graphics object.
    Bitmap bm = new Bitmap(300, 300);
    using (Graphics gr = Graphics.FromImage(bm))
    {
        gr.Clear(Color.White);
        gr.SmoothingMode = SmoothingMode.AntiAlias;

        // Set up a transformation to map the region
        // x/y = A +/- 0.1 onto the Bitmap.
        RectangleF rect = new RectangleF(
            -A - 0.1f, -A - 0.1f, 2 * A + 0.2f, 2 * A + 0.2f);
        PointF[] pts =
        {
            new PointF(0, bm.Height),
            new PointF(bm.Width, bm.Height),
            new PointF(0, 0),
        };
        gr.Transform = new Matrix(rect, pts);

        // Draw the curve.
        DrawCurve(gr, A, n, d);

        // Draw the axes.
        DrawAxes(gr, rect.Right);

        // Display the result and size the form to fit.
        picCurve.Image = bm;
        picCurve.SizeMode = PictureBoxSizeMode.AutoSize;
        this.ClientSize = new Size(
            picCurve.Right + picCurve.Top,
            picCurve.Bottom + picCurve.Top);
    }
}

This code gets the parameters A, n, and d. The values n and d are used in the rose curve equation. The value A is simply a scale factor.

Next, the event handler creates a transformation to map the curve’s area plus a margin onto the program’s PictureBox control. It then calls the DrawCurve method to draw the curve and the DrawAxes method to draw the X and Y axes. The DrawAxes method is straightforward so I won’t show it here. Download the example to see how it works.

The following code shows the DrawCurve method.

// Draw the curve.
// n and d should be relatively prime.
private void DrawCurve(Graphics gr, float A, int n, int d)
{
    const int num_points = 1000;

    // Period is Pi * d if n and d are both odd. 2 * Pi * d otherwise.
    double period = Math.PI * d;
    if ((n % 2 == 0) || (d % 2 == 0)) period *= 2;

    double dtheta = period / num_points;
    List<PointF> points = new List<PointF>();
    double k = (double)n / d;
    for (int i = 0; i < num_points; i++)
    {
        double theta = i * dtheta;
        double r = A * Math.Cos(k * theta);
        float x = (float)(r * Math.Cos(theta));
        float y = (float)(r * Math.Sin(theta));

        points.Add(new PointF(x, y));
    }

    gr.FillPolygon(Brushes.LightBlue, points.ToArray());

    // Draw the curve.
    using (Pen pen = new Pen(Color.Red, 0))
    {
        gr.DrawLines(pen, points.ToArray());
    }
}

The method starts by calculating the curve’s period. If n and d are both odd, then the period is πd. If either n or d is even, the curve’s period is 2πd.

The method makes a list of points and then enters a loop. Inside the loop, the code increments the variable theta and uses it to calculate the next point on the curve.

After the loop ends, the program fills the curve with light blue and then outlines it in red.

Download the example program to see additional details.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in algorithms, drawing, graphics, mathematics and tagged , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.