none
C# creating fractals using recursion RRS feed

  • Question

  • Tried searching online, but could only find bits and bobs of outdated info on this. Essentially I'm trying to write a program that draws a square (and circle) fractals using recursion. For the square part I'm trying to draw a square within a field, then using recursion it would reduce its size by 50% (so half) and rotate it 90 degrees, and repeat depending on the recursion depth that's entered by the user.

    For the circle, I've managed to get something together, but Im struggling on getting it to draw only when a value is entered and a button is pressed - right now it just draws as soon as the form starts.

    Admittedly I haven't made that much progress but was hoping someone could point me in the right direction as I'm struggling with understanding how to go about this.

    Specifically with how I would create a recursive function that would reduce the size of the square and then rotate it by 90 degrees and draw it and the circle part.

    namespace MD2
    {
        public partial class Form1 : Form
        {
            int rekursijaDzilums;
            bool circleBool, squareBool;
            int xc = 10;
            int yc = 10;
    
            const int initialRadius = 100;
            const int centerX = 242;
            const int centerY = 267;
            const double factor = 0.45;//factor for reducing circle size
            int recursionDepth;
    
    
            public Form1()
            {
                InitializeComponent();
            }
    
    
            protected override void OnPaint(PaintEventArgs e)
            {
                base.OnPaint(e);
                
                DrawRecursionStage(centerX, centerY, initialRadius, e.Graphics);
                         
            }
                         
            private void DrawRecursionStage(int x, int y, int radius, Graphics g)
            {
                recursionDepth = Convert.ToInt32(textBox1.Text);
    
                if (IsRecursionDepthReached(radius))
                {
                    return;
                }
    
                DrawCircle(x, y, radius, g);
    
                int newRadius = (int)(radius * factor);
    
                DrawRecursionStage(x - radius, y, newRadius, g);
                DrawRecursionStage(x, y - radius, newRadius, g);
                DrawRecursionStage(x + radius, y, newRadius, g);
                DrawRecursionStage(x, y + radius, newRadius, g);
        }
    
    
            public void DrawCircle(int x, int y, int radius, Graphics g)
            {
                
                g.DrawEllipse(Pens.Black, x - radius, y - radius, 2 * radius, 2 * radius);
            }
    
    
            private bool IsRecursionDepthReached(int radius)
            {
                return radius < Math.Pow(factor, recursionDepth) * initialRadius;
            }
    
    
            private void drawButton_Click(object sender, EventArgs e)
            {
                rekursijaDzilums = int.Parse(textBox1.Text); //This is
                
                if (squareBool == true)
                {
                    textBox3.Text = "Square being drawn";
                    DrawRectangle();
                }
    
                
    
                if (circleBool == true)
                {
                    textBox3.Text = "Circle being drawn";
                   //Nothing here yet
                }
            }
    
            
            public void DrawRectangle()
            {
                /*
            Graphics dc = pictureBox1.CreateGraphics();
            Pen myPen = new Pen(Color.Black, 3);
            Point[] points =
        {
                    new Point(0, 0),
                    new Point(0, 400),
                    new Point(0, 400),
                    new Point(400,400),
                    new Point(400, 0),
                    new Point(0,0),
                    };
                dc.DrawLines(myPen, points);
                */
    
                Graphics dc = pictureBox1.CreateGraphics();
                Pen myPen = new Pen(Color.Black, 3);
                int width = 380;
                int height = 380;
                dc.DrawRectangle(myPen, xc, yc, width, height);
    
                for (int i = rekursijaDzilums; i >= rekursijaDzilums; i--)
                {
                    width = width / 2;
                    height = height / 2;
                    dc.DrawRectangle(myPen, xc, yc, width, height);
                }
    
            }
    
    
            
            
    
    
            private void circle_Click(object sender, EventArgs e)
            {
                squareBool = false;
                circleBool = true;
                textBox4.Text = "";
                textBox4.Text = "Circle was pressed"; //using for testing at this stage
            }
    
    
    
            private void square_Click(object sender, EventArgs e)
            {
                circleBool = false;
                squareBool = true;
                textBox4.Text = "";
                textBox4.Text = "Square was pressed"; //using for testing at this stage
            }
    
    
        }
    }
    

    Apologies for it being too long, but I wasnt sure if only parts of it would make sense.

    The end results should look like this when a 'recursionDepth' and button 'Draw' is clicked, it would draw this:

    Any pointers, criticisms or suggestions greatly appreciated.

    Thank you

    Saturday, November 23, 2019 7:47 PM

All replies

  • Hi Sox,

    A quick pointer to how to get it to wait for a button click instead of drawing when the form starts. It starts drawing right away because you've put the code in the OnPaint() method (which runs when the Form first starts). It also runs if the Form is moved, so it may not be the best place for this code. I can look at it a bit more to see where it *should* go, but for now, add this:

    You'd need a bool to indicate when not to run the DrawRecursionStage() method in the OnPaint:

    bool AtStart = true;
    
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
    
        if (!AtStartup)
            DrawRecursionStage(centerX, centerY, initialRadius, e.Graphics);
    }



    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Saturday, November 23, 2019 10:02 PM
    Moderator
  • Oops, forgot one more important thing: in the drawButton_Click, set AtStartup = false

    ~~Bonnie DeWitt [C# MVP]

    http://geek-goddess-bonnie.blogspot.com

    Saturday, November 23, 2019 10:03 PM
    Moderator
  • Ohh right, that makes sense.

    Thank you! Managed to fix it now

    Sunday, November 24, 2019 9:54 AM
  • Graphics is not my specialty but I think that what the graphics experts would do is to do the calculations in a background thread with a bitmap as output then just show the bitmap in the paint. Then when something happens such as the program is minimized and restored or if another application becomes active and its window is on top of yours and then your application is reactivated then the calculations are not re-done. If your calculations become more complex then you will need to use a background thread so you should learn how to do that now.


    Sam Hobbs
    SimpleSamples.Info

    Sunday, November 24, 2019 6:44 PM
  • And I think there is a bitmap control that makes things a bit easier.


    Sam Hobbs
    SimpleSamples.Info

    Sunday, November 24, 2019 7:30 PM