This program uses the following equations to draw the butterfly curve:

The following `Paint` event handler draws the curve.

private const int period = 24; // Draw the butterfly. private void Form1_Paint(object sender, PaintEventArgs e) { e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; e.Graphics.Clear(this.BackColor); // Scale and translate. RectangleF world_rect = new RectangleF(-4.0f, -4.4f, 8.0f, 7.3f); float cx = (world_rect.Left + world_rect.Right) / 2; float cy = (world_rect.Top + world_rect.Bottom) / 2; // Center the world coordinates at origin. e.Graphics.TranslateTransform(-cx, -cy); // Scale to fill the form. float scale = Math.Min( this.ClientSize.Width / world_rect.Width, this.ClientSize.Height / world_rect.Height); e.Graphics.ScaleTransform(scale, scale, MatrixOrder.Append); // Move the result to center on the form. e.Graphics.TranslateTransform( this.ClientSize.Width / 2, this.ClientSize.Height / 2, MatrixOrder.Append); // Generate the points. PointF pt0, pt1; double t = 0; double expr = Math.Exp(Math.Cos(t)) - 2 * Math.Cos(4 * t) - Math.Pow(Math.Sin(t / 12), 5); pt1 = new PointF( (float)(Math.Sin(t) * expr), (float)(-Math.Cos(t) * expr)); using (Pen the_pen = new Pen(Color.Blue, 0)) { const long num_lines = 5000; for (long i = 0; i < num_lines; i++) { t = i * period * Math.PI / num_lines; expr = Math.Exp(Math.Cos(t)) - 2 * Math.Cos(4 * t) - Math.Pow(Math.Sin(t / 12), 5); pt0 = pt1; pt1 = new PointF( (float)(Math.Sin(t) * expr), (float)(-Math.Cos(t) * expr)); the_pen.Color = GetColor(t); e.Graphics.DrawLine(the_pen, pt0, pt1); } } }

The code uses translation and scale transformations to make the curve fit the form nicely. It then loops the variable `t` from 0 to 24π to generate the points along the curve. For the each line segment between a pair of adjacent points, the code calls the following `GetColor` method to pick a color for that segment and then draws it.

// Return an appropriate color for this segment. private Color GetColor(double t) { return Colors[(int)(t / Math.PI)]; }

The `GetColor` method divides the parameter `t` by π and uses the result as an index into the `Colors` array, which is initialized in the form’s `Load` event handler.

private Color[] Colors; // Initialize the colors. private void Form1_Load(object sender, EventArgs e) { // Redraw when resized. this.ResizeRedraw = true; Colors = new Color[] { Color.Pink, Color.Red, ... Color.Violet }; }

Pretty but your math based examples always fry my mind 🙁

Sorry about that 😉

Even if you don’t follow the equations (I don’t really understand them too well, either), there are some things to learn from this example. For example, how to plot a parametric function X(t) and Y(t).

The next two examples will also highlight techniques used by this example.

Fantastic, I wish I have a maths background like you, it is extra ordinary

There’s a tiny tiny (not so tiny) mistake in the original formulas:

x = Cos(t) * Exp(Cos(t)) – 2 * Cos(4 * t) – Sin(t / 12) ^ 5

y = Sin(t) * Exp(Cos(t)) – 2 * Cos(4 * t) – Sin(t / 12) ^ 5

They really are:

x = Cos(t) * (Exp(Cos(t)) – 2 * Cos(4 * t) – Sin(t / 12) ^ 5)

y = Sin(t) * (Exp(Cos(t)) – 2 * Cos(4 * t) – Sin(t / 12) ^ 5)

Then I got my butterfly 😀

Sorry about that. You’re right. I didn’t transcribe from the source code correctly.

Pingback: Use double buffering to prevent flicker when drawingC# Helper